Loading...
gen/NetBSD/utmpx.c.patch Libc-391 Libc-763.11
--- Libc/Libc-391/gen/NetBSD/utmpx.c.patch
+++ Libc/Libc-763.11/gen/NetBSD/utmpx.c.patch
@@ -1,52 +1,572 @@
---- utmpx.c.orig	2004-07-13 13:02:37.000000000 -0700
-+++ utmpx.c	2004-08-05 15:25:10.000000000 -0700
-@@ -50,7 +50,6 @@
+--- 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 <assert.h>
 -#include <db.h>
- #include <errno.h>
+-#include <errno.h>
  #include <fcntl.h>
  #include <stdio.h>
-@@ -63,6 +62,13 @@
+ #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
-+#include <utmp.h>
-+#include <ttyent.h>
-+
-+static void _utmp_compat(const struct utmpx *);
++		_write_utmp_compat(ux);
 +#endif /* UTMP_COMPAT */
-+
- __warn_references(getlastlogx,
-     "warning: reference to compatibility getlastlogx(); include <utmpx.h> for correct reference")
- __warn_references(lastlogxname,
-@@ -72,7 +78,6 @@
- static int readonly = 0;
- static struct utmpx ut;
- static char utfile[MAXPATHLEN] = _PATH_UTMPX;
--static char llfile[MAXPATHLEN] = _PATH_LASTLOGX;
- 
- static struct utmpx *utmp_update(const struct utmpx *);
- 
-@@ -270,6 +275,9 @@
++	}
++	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;
  
- 	u = memcpy(&ut, &temp, sizeof(ut));
-+#ifdef UTMP_COMPAT
-+	_utmp_compat(u);
-+#endif /* UTMP_COMPAT */
+-	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)
-@@ -308,185 +316,50 @@
- 
+-		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;
  }
  
--/*
-- * The following are extensions and not part of the X/Open spec.
-- */
+ 
+-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)
 -{
@@ -66,25 +586,7 @@
 -		(void)memcpy(ut.ut_user, vers, sizeof(vers));
 -		if (write(fd, &ut, sizeof(ut)) == -1)
 -			goto failed;
-+#ifdef UTMP_COMPAT
-+static void
-+_utmp_compat(const struct utmpx *ux)
-+{
-+	struct utmp u;
-+	int fd, slot;
-+	struct ttyent *ttyp;
-+
-+	switch (ux->ut_type) {
-+	case INIT_PROCESS:
-+	case LOGIN_PROCESS:
-+	case USER_PROCESS:
-+		break;
-+	case DEAD_PROCESS:
-+		logout(ux->ut_line);
-+		return;
-+	default:
-+		return;
- 	}
+-	}
 -	if (write(fd, utx, sizeof(*utx)) == -1)
 -		goto failed;
 -	if (close(fd) == -1)
@@ -101,88 +603,104 @@
 -
 -int
 -utmpxname(const char *fname)
--{
--	size_t len;
--
++__private_extern__ int
++__utmpxname(struct _utmpx *U, const char *fname)
+ {
+ 	size_t len;
+ 
 -	_DIAGASSERT(fname != NULL);
--
--	len = strlen(fname);
--
++	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))
--		return 0;
--
--	/* must end in x! */
--	if (fname[len - 1] != 'x')
--		return 0;
--
++	if (len >= MAXPATHLEN)
+ 		return 0;
+ 
+ 	/* must end in x! */
+ 	if (fname[len - 1] != 'x')
+ 		return 0;
+ 
 -	(void)strlcpy(utfile, fname, sizeof(utfile));
 -	endutxent();
--	return 1;
--}
--
--
--void
--getutmp(const struct utmpx *ux, struct utmp *u)
--{
--
++	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));
--	(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;
--}
--
--void
--getutmpx(const struct utmp *u, struct utmpx *ux)
--{
--
++	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));
--	(void)memcpy(ux->ut_line, u->ut_line, sizeof(u->ut_line));
--	(void)memcpy(ux->ut_host, u->ut_host, sizeof(u->ut_host));
--	ux->ut_tv.tv_sec = u->ut_time;
--	ux->ut_tv.tv_usec = 0;
++	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_type = USER_PROCESS;
++	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;
 -}
 -
--int
--lastlogxname(const char *fname)
--{
--	size_t len;
--
--	_DIAGASSERT(fname != NULL);
--
--	len = strlen(fname);
--
--	if (len >= sizeof(llfile))
--		return 0;
--
--	/* must end in x! */
--	if (fname[len - 1] != 'x')
--		return 0;
--
--	(void)strlcpy(llfile, fname, sizeof(llfile));
--	return 1;
--}
--
 -struct lastlogx *
--getlastlogx(uid_t uid, struct lastlogx *ll)
--{
--
--	return __getlastlogx13(_PATH_LASTLOGX, uid, ll);
--}
--
--struct lastlogx *
--__getlastlogx13(const char *fname, uid_t uid, struct lastlogx *ll)
+-getlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
 -{
 -	DBT key, data;
 -	DB *db;
@@ -204,21 +722,8 @@
 -	if (data.size != sizeof(*ll)) {
 -		errno = EFTYPE;
 -		goto error;
-+	/* do equivalent of ttyslot(), but using ux->ut_slot */
-+	setttyent();
-+	slot = 1;
-+	for(;;) {
-+		if ((ttyp = getttyent()) == NULL) {
-+			endttyent();
-+			return;
-+		}
-+		if (!strcmp(ttyp->ty_name, ux->ut_line)) {
-+			endttyent();
-+			break;
-+		}
-+		slot++;
- 	}
- 
+-	}
+-
 -	if (ll == NULL)
 -		if ((ll = malloc(sizeof(*ll))) == NULL)
 -			goto done;
@@ -242,7 +747,7 @@
 -	_DIAGASSERT(fname != NULL);
 -	_DIAGASSERT(ll != NULL);
 -
--	db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0, DB_HASH, NULL);
+-	db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0644, DB_HASH, NULL);
 -
 -	if (db == NULL)
 -		return -1;
@@ -256,16 +761,5 @@
 -
 -	(db->close)(db);
 -	return error;
-+	/* now write utmp */
-+	(void)memset(&u, 0, sizeof(u));
-+	strncpy(u.ut_line, ux->ut_line, UT_LINESIZE);
-+	strncpy(u.ut_name, ux->ut_user, UT_NAMESIZE);
-+	strncpy(u.ut_host, ux->ut_host, UT_HOSTSIZE);
-+	u.ut_time = ux->ut_tv.tv_sec;
-+	if ((fd = open(_PATH_UTMP, O_WRONLY|O_CREAT, 0644)) >= 0) {
-+		(void)lseek(fd, (off_t)(slot * sizeof(struct utmp)), L_SET);
-+		(void)write(fd, &u, sizeof(struct utmp));
-+		(void)close(fd);
-+	}
  }
-+#endif /* UTMP_COMPAT */
++#endif /* UNIFDEF_LEGACY_UTMP_APIS */