Loading...
--- /dev/null
+++ Libc/Libc-763.12/gen/NetBSD/utmpx.c.patch
@@ -0,0 +1,765 @@
+--- utmpx.c.orig 2010-06-24 19:43:32.000000000 -0700
++++ utmpx.c 2010-06-29 11:25:57.000000000 -0700
+@@ -42,111 +42,240 @@ __RCSID("$NetBSD: utmpx.c,v 1.25 2008/04
+ #include <sys/time.h>
+ #include <sys/wait.h>
+
+-#include <assert.h>
+-#include <db.h>
+-#include <errno.h>
+ #include <fcntl.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#ifdef UNIFDEF_LEGACY_UTMP_APIS
+ #include <utmp.h>
++#endif /* UNIFDEF_LEGACY_UTMP_APIS */
+ #include <utmpx.h>
++#include <utmpx-darwin.h>
++#include <errno.h>
+ #include <vis.h>
++#include <notify.h>
+
+-static FILE *fp;
+-static int readonly = 0;
+-static struct utmpx ut;
+-static char utfile[MAXPATHLEN] = _PATH_UTMPX;
++/* This is the default struct _utmpx shared by the POSIX APIs */
++__private_extern__
++struct _utmpx __utx__ = {
++ __UTX_MAGIC__, /* magic */
++ {}, /* ut */
++ PTHREAD_MUTEX_INITIALIZER, /* utmpx_mutex */
++ _PATH_UTMPX, /* utfile */
++ NULL, /* fp */
++ 1, /* utfile_system */
++ 0, /* readonly */
++};
++
++static struct utmpx *__getutxid(struct _utmpx *, const struct utmpx *);
+
+-static struct utmpx *utmp_update(const struct utmpx *);
++__private_extern__ const char _utmpx_vers[] = "utmpx-1.00";
+
+-static const char vers[] = "utmpx-1.00";
++__private_extern__ void
++__setutxent(struct _utmpx *U)
++{
++
++ (void)memset(&U->ut, 0, sizeof(U->ut));
++ if (U->fp == NULL)
++ return;
++#ifdef __LP64__
++ (void)fseeko(U->fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
++#else /* __LP64__ */
++ (void)fseeko(U->fp, (off_t)sizeof(U->ut), SEEK_SET);
++#endif /* __LP64__ */
++}
+
+ void
+-setutxent()
++_setutxent(struct _utmpx *U)
+ {
+
+- (void)memset(&ut, 0, sizeof(ut));
+- if (fp == NULL)
+- return;
+- (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
++ TEST_UTMPX_T("_setutxent", U);
++ UTMPX_LOCK(U);
++ __setutxent(U);
++ UTMPX_UNLOCK(U);
+ }
+
+
+ void
+-endutxent()
++setutxent()
+ {
++ _setutxent(&__utx__);
++}
++
+
+- (void)memset(&ut, 0, sizeof(ut));
+- if (fp != NULL) {
+- (void)fclose(fp);
+- fp = NULL;
+- readonly = 0;
++__private_extern__ void
++__endutxent(struct _utmpx *U)
++{
++ (void)memset(&U->ut, 0, sizeof(U->ut));
++ if (U->fp != NULL) {
++ int saveerrno = errno;
++ (void)fclose(U->fp);
++ errno = saveerrno;
++ U->fp = NULL;
++ U->readonly = 0;
+ }
+ }
+
+
+-struct utmpx *
+-getutxent()
++void
++_endutxent(struct _utmpx *U)
+ {
++ TEST_UTMPX_T("_endutxent", U);
++ UTMPX_LOCK(U);
++ __endutxent(U);
++ UTMPX_UNLOCK(U);
++}
+
+- if (fp == NULL) {
++
++void
++endutxent()
++{
++ _endutxent(&__utx__);
++}
++
++
++__private_extern__ struct utmpx *
++__getutxent(struct _utmpx *U)
++{
++ int saveerrno;
++#ifdef __LP64__
++ struct utmpx32 ut32;
++#endif /* __LP64__ */
++
++ if (U->fp == NULL) {
+ struct stat st;
+
+- if ((fp = fopen(utfile, "r+")) == NULL)
+- if ((fp = fopen(utfile, "w+")) == NULL) {
+- if ((fp = fopen(utfile, "r")) == NULL)
++ if ((U->fp = fopen(U->utfile, "r+")) == NULL)
++ if ((U->fp = fopen(U->utfile, "w+")) == NULL) {
++ if ((U->fp = fopen(U->utfile, "r")) == NULL)
+ goto fail;
+ else
+- readonly = 1;
++ U->readonly = 1;
+ }
+-
++
++ fcntl(fileno(U->fp), F_SETFD, 1); /* set close-on-exec flag */
+
+ /* get file size in order to check if new file */
+- if (fstat(fileno(fp), &st) == -1)
++ if (fstat(fileno(U->fp), &st) == -1)
+ goto failclose;
+
+ if (st.st_size == 0) {
+ /* new file, add signature record */
+- (void)memset(&ut, 0, sizeof(ut));
+- ut.ut_type = SIGNATURE;
+- (void)memcpy(ut.ut_user, vers, sizeof(vers));
+- if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
++#ifdef __LP64__
++ (void)memset(&ut32, 0, sizeof(ut32));
++ ut32.ut_type = SIGNATURE;
++ (void)memcpy(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
++ if (fwrite(&ut32, sizeof(ut32), 1, U->fp) != 1)
++#else /* __LP64__ */
++ (void)memset(&U->ut, 0, sizeof(U->ut));
++ U->ut.ut_type = SIGNATURE;
++ (void)memcpy(U->ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
++ if (fwrite(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
++#endif /* __LP64__ */
+ goto failclose;
+ } else {
+ /* old file, read signature record */
+- if (fread(&ut, sizeof(ut), 1, fp) != 1)
++#ifdef __LP64__
++ if (fread(&ut32, sizeof(ut32), 1, U->fp) != 1)
++#else /* __LP64__ */
++ if (fread(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
++#endif /* __LP64__ */
+ goto failclose;
+- if (memcmp(ut.ut_user, vers, sizeof(vers)) != 0 ||
+- ut.ut_type != SIGNATURE)
++#ifdef __LP64__
++ if (memcmp(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
++ ut32.ut_type != SIGNATURE)
++#else /* __LP64__ */
++ if (memcmp(U->ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
++ U->ut.ut_type != SIGNATURE)
++#endif /* __LP64__ */
++ {
++ errno = EINVAL;
+ goto failclose;
++ }
+ }
+ }
+
+- if (fread(&ut, sizeof(ut), 1, fp) != 1)
++#ifdef __LP64__
++ if (fread(&ut32, sizeof(ut32), 1, U->fp) != 1)
++#else /* __LP64__ */
++ if (fread(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
++#endif /* __LP64__ */
+ goto fail;
+
+- return &ut;
++#ifdef __LP64__
++ _utmpx32_64(&ut32, &U->ut);
++#endif /* __LP64__ */
++ return &U->ut;
+ failclose:
+- (void)fclose(fp);
++ saveerrno = errno;
++ (void)fclose(U->fp);
++ errno = saveerrno;
++ U->fp = NULL;
+ fail:
+- (void)memset(&ut, 0, sizeof(ut));
++ (void)memset(&U->ut, 0, sizeof(U->ut));
+ return NULL;
+ }
+
+
+ struct utmpx *
+-getutxid(const struct utmpx *utx)
++_getutxent(struct _utmpx *U)
+ {
++ struct utmpx *ret;
++
++ TEST_UTMPX_T("_getutxent", U);
++ UTMPX_LOCK(U);
++ ret = __getutxent(U);
++ UTMPX_UNLOCK(U);
++ return ret;
++}
++
++
++struct utmpx *
++getutxent()
++{
++ return _getutxent(&__utx__);
++}
+
+- _DIAGASSERT(utx != NULL);
++
++struct utmpx *
++_getutxid(struct _utmpx *U, const struct utmpx *utx)
++{
++ struct utmpx temp;
++ const struct utmpx *ux;
++ struct utmpx *ret;
+
+ if (utx->ut_type == EMPTY)
+ return NULL;
+
++ TEST_UTMPX_T("_getutxid", U);
++ UTMPX_LOCK(U);
++ /* make a copy as needed, and auto-fill if requested */
++ ux = _utmpx_working_copy(utx, &temp, 1);
++ if (!ux) {
++ UTMPX_UNLOCK(U);
++ return NULL;
++ }
++
++ ret = __getutxid(U, ux);
++ UTMPX_UNLOCK(U);
++ return ret;
++}
++
++
++struct utmpx *
++getutxid(const struct utmpx *utx)
++{
++ return _getutxid(&__utx__, utx);
++}
++
++
++static struct utmpx *
++__getutxid(struct _utmpx *U, const struct utmpx *utx)
++{
++
+ do {
+- if (ut.ut_type == EMPTY)
++ if (U->ut.ut_type == EMPTY)
+ continue;
+ switch (utx->ut_type) {
+ case EMPTY:
+@@ -155,21 +284,21 @@ getutxid(const struct utmpx *utx)
+ case BOOT_TIME:
+ case OLD_TIME:
+ case NEW_TIME:
+- if (ut.ut_type == utx->ut_type)
+- return &ut;
++ if (U->ut.ut_type == utx->ut_type)
++ return &U->ut;
+ break;
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ case USER_PROCESS:
+ case DEAD_PROCESS:
+- switch (ut.ut_type) {
++ switch (U->ut.ut_type) {
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ case USER_PROCESS:
+ case DEAD_PROCESS:
+- if (memcmp(ut.ut_id, utx->ut_id,
+- sizeof(ut.ut_id)) == 0)
+- return &ut;
++ if (memcmp(U->ut.ut_id, utx->ut_id,
++ sizeof(U->ut.ut_id)) == 0)
++ return &U->ut;
+ break;
+ default:
+ break;
+@@ -178,188 +307,253 @@ getutxid(const struct utmpx *utx)
+ default:
+ return NULL;
+ }
+- } while (getutxent() != NULL);
++ } while (__getutxent(U) != NULL);
+ return NULL;
+ }
+
+
+-struct utmpx *
+-getutxline(const struct utmpx *utx)
++static struct utmpx *
++__getutxline(struct _utmpx *U, const struct utmpx *utx)
+ {
+-
+- _DIAGASSERT(utx != NULL);
+-
+ do {
+- switch (ut.ut_type) {
++ switch (U->ut.ut_type) {
+ case EMPTY:
+ break;
+ case LOGIN_PROCESS:
+ case USER_PROCESS:
+- if (strncmp(ut.ut_line, utx->ut_line,
+- sizeof(ut.ut_line)) == 0)
+- return &ut;
++ if (strncmp(U->ut.ut_line, utx->ut_line,
++ sizeof(U->ut.ut_line)) == 0)
++ return &U->ut;
+ break;
+ default:
+ break;
+ }
+- } while (getutxent() != NULL);
++ } while (__getutxent(U) != NULL);
+ return NULL;
+ }
+
+
+ struct utmpx *
+-pututxline(const struct utmpx *utx)
++_getutxline(struct _utmpx *U, const struct utmpx *utx)
++{
++ struct utmpx *ret;
++
++ TEST_UTMPX_T("_getutxline", U);
++ UTMPX_LOCK(U);
++ ret = __getutxline(U, utx);
++ UTMPX_UNLOCK(U);
++ return ret;
++}
++
++
++struct utmpx *
++getutxline(const struct utmpx *utx)
+ {
+- struct utmpx temp, *u = NULL;
+- int gotlock = 0;
++ return _getutxline(&__utx__, utx);
++}
+
+- _DIAGASSERT(utx != NULL);
+
+- if (utx == NULL)
++struct utmpx *
++_pututxline(struct _utmpx *U, const struct utmpx *utx)
++{
++ struct utmpx *ux;
++
++ if (utx == NULL) {
++ errno = EINVAL;
+ return NULL;
++ }
+
+- if (strcmp(_PATH_UTMPX, utfile) == 0)
+- if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0))
+- return utmp_update(utx);
++ TEST_UTMPX_T("_pututxline", U);
++ UTMPX_LOCK(U);
++ if ((ux = __pututxline(&__utx__, utx)) != NULL && __utx__.utfile_system) {
++ _utmpx_asl(ux); /* the equivalent of wtmpx and lastlogx */
++#ifdef UTMP_COMPAT
++ _write_utmp_compat(ux);
++#endif /* UTMP_COMPAT */
++ }
++ UTMPX_UNLOCK(U);
++ return ux;
++}
+
+
+- (void)memcpy(&temp, utx, sizeof(temp));
++struct utmpx *
++pututxline(const struct utmpx *utx)
++{
++ return _pututxline(&__utx__, utx);
++}
++
++__private_extern__ struct utmpx *
++__pututxline(struct _utmpx *U, const struct utmpx *utx)
++{
++ struct utmpx temp, *u = NULL, *x;
++ const struct utmpx *ux;
++#ifdef __LP64__
++ struct utmpx32 ut32;
++#endif /* __LP64__ */
++ struct flock fl;
++#define gotlock (fl.l_start >= 0)
++
++ fl.l_start = -1; /* also means we haven't locked */
++ if (U->utfile_system)
++ if ((U->fp != NULL && U->readonly) || (U->fp == NULL && geteuid() != 0)) {
++ errno = EPERM;
++ return NULL;
++ }
+
+- if (fp == NULL) {
+- (void)getutxent();
+- if (fp == NULL || readonly)
++ if (U->fp == NULL) {
++ (void)__getutxent(U);
++ if (U->fp == NULL || U->readonly) {
++ errno = EPERM;
+ return NULL;
++ }
+ }
+
+- if (getutxid(&temp) == NULL) {
+- setutxent();
+- if (getutxid(&temp) == NULL) {
+- if (lockf(fileno(fp), F_LOCK, (off_t)0) == -1)
++ /* make a copy as needed, and auto-fill if requested */
++ ux = _utmpx_working_copy(utx, &temp, 0);
++ if (!ux)
++ return NULL;
++
++ if ((x = __getutxid(U, ux)) == NULL) {
++ __setutxent(U);
++ if ((x = __getutxid(U, ux)) == NULL) {
++ /*
++ * utx->ut_type has any original mask bits, while
++ * ux->ut_type has those mask bits removed. If we
++ * are trying to record a dead process, and
++ * UTMPX_DEAD_IF_CORRESPONDING_MASK is set, then since
++ * there is no matching entry, we return NULL.
++ */
++ if (ux->ut_type == DEAD_PROCESS &&
++ (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK)) {
++ errno = EINVAL;
+ return NULL;
+- gotlock++;
+- if (fseeko(fp, (off_t)0, SEEK_END) == -1)
++ }
++ /*
++ * Replace lockf() with fcntl() and a fixed start
++ * value. We should already be at EOF.
++ */
++ if ((fl.l_start = lseek(fileno(U->fp), 0, SEEK_CUR)) < 0)
++ return NULL;
++ fl.l_len = 0;
++ fl.l_whence = SEEK_SET;
++ fl.l_type = F_WRLCK;
++ if (fcntl(fileno(U->fp), F_SETLKW, &fl) == -1)
++ return NULL;
++ if (fseeko(U->fp, (off_t)0, SEEK_END) == -1)
+ goto fail;
+ }
+ }
+
+ if (!gotlock) {
++ /*
++ * utx->ut_type has any original mask bits, while
++ * ux->ut_type has those mask bits removed. If we
++ * are trying to record a dead process, if
++ * UTMPX_DEAD_IF_CORRESPONDING_MASK is set, but the found
++ * entry is not a (matching) USER_PROCESS, then return NULL.
++ */
++ if (ux->ut_type == DEAD_PROCESS &&
++ (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK) &&
++ x->ut_type != USER_PROCESS) {
++ errno = EINVAL;
++ return NULL;
++ }
+ /* we are not appending */
+- if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
++#ifdef __LP64__
++ if (fseeko(U->fp, -(off_t)sizeof(ut32), SEEK_CUR) == -1)
++#else /* __LP64__ */
++ if (fseeko(U->fp, -(off_t)sizeof(U->ut), SEEK_CUR) == -1)
++#endif /* __LP64__ */
+ return NULL;
+ }
+
+- if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
++#ifdef __LP64__
++ _utmpx64_32(ux, &ut32);
++ if (fwrite(&ut32, sizeof (ut32), 1, U->fp) != 1)
++#else /* __LP64__ */
++ if (fwrite(ux, sizeof (*ux), 1, U->fp) != 1)
++#endif /* __LP64__ */
+ goto fail;
+
+- if (fflush(fp) == -1)
++ if (fflush(U->fp) == -1)
+ goto fail;
+
+- u = memcpy(&ut, &temp, sizeof(ut));
++ u = memcpy(&U->ut, ux, sizeof(U->ut));
++ notify_post(UTMPX_CHANGE_NOTIFICATION);
+ fail:
+ if (gotlock) {
+- if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
++ int save = errno;
++ fl.l_type = F_UNLCK;
++ if (fcntl(fileno(U->fp), F_SETLK, &fl) == -1)
+ return NULL;
++ errno = save;
+ }
+ return u;
+ }
+
+
+-static struct utmpx *
+-utmp_update(const struct utmpx *utx)
+-{
+- char buf[sizeof(*utx) * 4 + 1];
+- pid_t pid;
+- int status;
+-
+- _DIAGASSERT(utx != NULL);
+-
+- (void)strvisx(buf, (const char *)(const void *)utx, sizeof(*utx),
+- VIS_WHITE);
+- switch (pid = fork()) {
+- case 0:
+- (void)execl(_PATH_UTMP_UPDATE,
+- strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
+- _exit(1);
+- /*NOTREACHED*/
+- case -1:
+- return NULL;
+- default:
+- if (waitpid(pid, &status, 0) == -1)
+- return NULL;
+- if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+- return memcpy(&ut, utx, sizeof(ut));
+- return NULL;
+- }
+-
+-}
+-
+ /*
+ * The following are extensions and not part of the X/Open spec.
+ */
+-int
+-updwtmpx(const char *file, const struct utmpx *utx)
+-{
+- int fd;
+- int saved_errno;
+-
+- _DIAGASSERT(file != NULL);
+- _DIAGASSERT(utx != NULL);
+-
+- fd = open(file, O_WRONLY|O_APPEND|O_SHLOCK);
+-
+- if (fd == -1) {
+- if ((fd = open(file, O_CREAT|O_WRONLY|O_EXLOCK, 0644)) == -1)
+- return -1;
+- (void)memset(&ut, 0, sizeof(ut));
+- ut.ut_type = SIGNATURE;
+- (void)memcpy(ut.ut_user, vers, sizeof(vers));
+- if (write(fd, &ut, sizeof(ut)) == -1)
+- goto failed;
+- }
+- if (write(fd, utx, sizeof(*utx)) == -1)
+- goto failed;
+- if (close(fd) == -1)
+- return -1;
+- return 0;
+-
+- failed:
+- saved_errno = errno;
+- (void) close(fd);
+- errno = saved_errno;
+- return -1;
+-}
+-
+-
+-int
+-utmpxname(const char *fname)
++__private_extern__ int
++__utmpxname(struct _utmpx *U, const char *fname)
+ {
+ size_t len;
+
+- _DIAGASSERT(fname != NULL);
++ if (fname == NULL) {
++ if(!U->utfile_system)
++ free(U->utfile);
++ U->utfile = _PATH_UTMPX;
++ U->utfile_system = 1;
++ __endutxent(U);
++ return 1;
++ }
+
+ len = strlen(fname);
+
+- if (len >= sizeof(utfile))
++ if (len >= MAXPATHLEN)
+ return 0;
+
+ /* must end in x! */
+ if (fname[len - 1] != 'x')
+ return 0;
+
+- (void)strlcpy(utfile, fname, sizeof(utfile));
+- endutxent();
++ if (U->utfile_system)
++ U->utfile = NULL;
++ U->utfile_system = 0;
++ if ((U->utfile = reallocf(U->utfile, len + 1)) == NULL)
++ return 0;
++
++ (void)strcpy(U->utfile, fname);
++ __endutxent(U);
+ return 1;
+ }
+
++int
++_utmpxname(struct _utmpx *U, const char *fname)
++{
++ int ret;
++
++ TEST_UTMPX_T("_utmpxname", U);
++ UTMPX_LOCK(U);
++ ret = __utmpxname(U, fname);
++ UTMPX_UNLOCK(U);
++ return ret;
++}
++
++int
++utmpxname(const char *fname)
++{
++ return _utmpxname(&__utx__, fname);
++}
+
++#ifdef UNIFDEF_LEGACY_UTMP_APIS
+ void
+ getutmp(const struct utmpx *ux, struct utmp *u)
+ {
+
+- _DIAGASSERT(ux != NULL);
+- _DIAGASSERT(u != NULL);
+-
+- (void)memcpy(u->ut_name, ux->ut_name, sizeof(u->ut_name));
++ bzero(u, sizeof(*u));
++ (void)memcpy(u->ut_name, ux->ut_user, sizeof(u->ut_name));
+ (void)memcpy(u->ut_line, ux->ut_line, sizeof(u->ut_line));
+ (void)memcpy(u->ut_host, ux->ut_host, sizeof(u->ut_host));
+ u->ut_time = ux->ut_tv.tv_sec;
+@@ -369,82 +563,16 @@ void
+ getutmpx(const struct utmp *u, struct utmpx *ux)
+ {
+
+- _DIAGASSERT(ux != NULL);
+- _DIAGASSERT(u != NULL);
+-
+- (void)memcpy(ux->ut_name, u->ut_name, sizeof(u->ut_name));
++ bzero(ux, sizeof(*ux));
++ (void)memcpy(ux->ut_user, u->ut_name, sizeof(u->ut_name));
++ ux->ut_user[sizeof(u->ut_name)] = 0;
+ (void)memcpy(ux->ut_line, u->ut_line, sizeof(u->ut_line));
++ ux->ut_line[sizeof(u->ut_line)] = 0;
+ (void)memcpy(ux->ut_host, u->ut_host, sizeof(u->ut_host));
++ ux->ut_host[sizeof(u->ut_host)] = 0;
+ ux->ut_tv.tv_sec = u->ut_time;
+ ux->ut_tv.tv_usec = 0;
+- (void)memset(&ux->ut_ss, 0, sizeof(ux->ut_ss));
+- ux->ut_pid = 0;
++ ux->ut_pid = getpid();
+ ux->ut_type = USER_PROCESS;
+- ux->ut_session = 0;
+- ux->ut_exit.e_termination = 0;
+- ux->ut_exit.e_exit = 0;
+-}
+-
+-struct lastlogx *
+-getlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
+-{
+- DBT key, data;
+- DB *db;
+-
+- _DIAGASSERT(fname != NULL);
+- _DIAGASSERT(ll != NULL);
+-
+- db = dbopen(fname, O_RDONLY|O_SHLOCK, 0, DB_HASH, NULL);
+-
+- if (db == NULL)
+- return NULL;
+-
+- key.data = &uid;
+- key.size = sizeof(uid);
+-
+- if ((db->get)(db, &key, &data, 0) != 0)
+- goto error;
+-
+- if (data.size != sizeof(*ll)) {
+- errno = EFTYPE;
+- goto error;
+- }
+-
+- if (ll == NULL)
+- if ((ll = malloc(sizeof(*ll))) == NULL)
+- goto done;
+-
+- (void)memcpy(ll, data.data, sizeof(*ll));
+- goto done;
+-error:
+- ll = NULL;
+-done:
+- (db->close)(db);
+- return ll;
+-}
+-
+-int
+-updlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
+-{
+- DBT key, data;
+- int error = 0;
+- DB *db;
+-
+- _DIAGASSERT(fname != NULL);
+- _DIAGASSERT(ll != NULL);
+-
+- db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0644, DB_HASH, NULL);
+-
+- if (db == NULL)
+- return -1;
+-
+- key.data = &uid;
+- key.size = sizeof(uid);
+- data.data = ll;
+- data.size = sizeof(*ll);
+- if ((db->put)(db, &key, &data, 0) != 0)
+- error = -1;
+-
+- (db->close)(db);
+- return error;
+ }
++#endif /* UNIFDEF_LEGACY_UTMP_APIS */