Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Jan 2010 10:29:54 +0000 (UTC)
From:      Ed Schouten <ed@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r201637 - in user/ed/utmpx: include lib/libc/gen
Message-ID:  <201001061029.o06ATsvs096571@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ed
Date: Wed Jan  6 10:29:53 2010
New Revision: 201637
URL: http://svn.freebsd.org/changeset/base/201637

Log:
  Make utmpx actually work.

Modified:
  user/ed/utmpx/include/utmpx.h
  user/ed/utmpx/lib/libc/gen/Symbol.map
  user/ed/utmpx/lib/libc/gen/getutxent.c
  user/ed/utmpx/lib/libc/gen/pututxline.c
  user/ed/utmpx/lib/libc/gen/utxdb.h

Modified: user/ed/utmpx/include/utmpx.h
==============================================================================
--- user/ed/utmpx/include/utmpx.h	Wed Jan  6 10:21:16 2010	(r201636)
+++ user/ed/utmpx/include/utmpx.h	Wed Jan  6 10:29:53 2010	(r201637)
@@ -42,7 +42,11 @@ struct utmpx {
 	char		ut_user[32];
 	char		ut_id[8];
 	char		ut_line[32];
-	char		ut_host[256];
+#if __BSD_VISIBLE
+	char		ut_host[128];
+#else
+	char		__ut_host[128];
+#endif
 	pid_t		ut_pid;
 	short		ut_type;
 #define	EMPTY		0
@@ -59,6 +63,12 @@ struct utmpx {
 	struct timeval	ut_tv;
 };
 
+#if __BSD_VISIBLE
+#define	UTXDB_ACTIVE	0
+#define	UTXDB_LASTLOGIN	1
+#define	UTXDB_LOG	2
+#endif
+
 __BEGIN_DECLS
 void	endutxent(void);
 struct utmpx *getutxent(void);
@@ -66,6 +76,10 @@ struct utmpx *getutxid(const struct utmp
 struct utmpx *getutxline(const struct utmpx *);
 struct utmpx *pututxline(const struct utmpx *);
 void	setutxent(void);
+
+#if __BSD_VISIBLE
+int	setutxdb(int, const char *);
+#endif
 __END_DECLS
 
 #endif /* !_UTMPX_H_ */

Modified: user/ed/utmpx/lib/libc/gen/Symbol.map
==============================================================================
--- user/ed/utmpx/lib/libc/gen/Symbol.map	Wed Jan  6 10:21:16 2010	(r201636)
+++ user/ed/utmpx/lib/libc/gen/Symbol.map	Wed Jan  6 10:29:53 2010	(r201637)
@@ -373,6 +373,7 @@ FBSD_1.2 {
 	getutxid;
 	getutxline;
 	pututxline;
+	setutxdb;
 	setutxent;
 };
 

Modified: user/ed/utmpx/lib/libc/gen/getutxent.c
==============================================================================
--- user/ed/utmpx/lib/libc/gen/getutxent.c	Wed Jan  6 10:21:16 2010	(r201636)
+++ user/ed/utmpx/lib/libc/gen/getutxent.c	Wed Jan  6 10:29:53 2010	(r201637)
@@ -22,45 +22,219 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * $FreeBSD$
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
+#include <errno.h>
 #include <stdio.h>
+#include <string.h>
 #include <utmpx.h>
+#include "utxdb.h"
 #include "un-namespace.h"
 
+static FILE *uf = NULL;
+static int udb;
+static struct utmpx utx;
+
+int
+setutxdb(int db, const char *file)
+{
+
+	switch (db) {
+	case UTXDB_ACTIVE:
+		if (file == NULL)
+			file = _PATH_UTX_ACTIVE;
+		break;
+	case UTXDB_LASTLOGIN:
+		if (file == NULL)
+			file = _PATH_UTX_LASTLOGIN;
+		break;
+	case UTXDB_LOG:
+		if (file == NULL)
+			file = _PATH_UTX_LOG;
+		break;
+	default:
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (uf != NULL)
+		fclose(uf);
+	uf = fopen(file, "r");
+	if (uf == NULL)
+		return (-1);
+	udb = db;
+	return (0);
+}
+
+void
+setutxent(void)
+{
+
+	setutxdb(UTXDB_ACTIVE, NULL);
+}
+
 void
 endutxent(void)
 {
+
+	if (uf != NULL) {
+		fclose(uf);
+		uf = NULL;
+	}
+}
+
+static void
+futx_to_utx(const struct futx *fu, struct utmpx *ut)
+{
+
+	memset(ut, 0, sizeof *ut);
+
+	switch (fu->fu_type) {
+	case BOOT_TIME:
+	case OLD_TIME:
+	case NEW_TIME:
+	/* Extension: shutdown time. */
+	case SHUTDOWN_TIME:
+		break;
+	case USER_PROCESS:
+		FTOU_STRING(fu, ut, id);
+		FTOU_STRING(fu, ut, user);
+		FTOU_STRING(fu, ut, line);
+		/* Extension: host name. */
+		FTOU_STRING(fu, ut, host);
+		FTOU_PID(fu, ut);
+		break;
+	case INIT_PROCESS:
+		FTOU_STRING(fu, ut, id);
+		FTOU_PID(fu, ut);
+		break;
+	case LOGIN_PROCESS:
+		FTOU_STRING(fu, ut, id);
+		FTOU_STRING(fu, ut, user);
+		FTOU_PID(fu, ut);
+		break;
+	case DEAD_PROCESS:
+		FTOU_STRING(fu, ut, id);
+		FTOU_PID(fu, ut);
+		break;
+	default:
+		ut->ut_type = EMPTY;
+		return;
+	}
+
+	FTOU_TYPE(fu, ut);
+	FTOU_TV(fu, ut);
+}
+
+static struct futx *
+getfutxent(void)
+{
+	static struct futx fu;
+
+	if (uf == NULL)
+		setutxent();
+	if (uf == NULL)
+		return (NULL);
+
+	if (udb == UTXDB_LOG) {
+		uint16_t len;
+
+		if (fread(&len, sizeof len, 1, uf) != 1)
+			return (NULL);
+		len = be16toh(len);
+		if (len > sizeof fu) {
+			/* Forward compatibility. */
+			if (fread(&fu, sizeof fu, 1, uf) != 1)
+				return (NULL);
+			fseek(uf, len - sizeof fu, SEEK_CUR);
+		} else {
+			/* Partial record. */
+			memset(&fu, 0, sizeof fu);
+			if (fread(&fu, len, 1, uf) != 1)
+				return (NULL);
+		}
+		return (NULL);
+	} else {
+		if (fread(&fu, sizeof fu, 1, uf) != 1)
+			return (NULL);
+	}
+	return (&fu);
 }
 
 struct utmpx *
 getutxent(void)
 {
+	struct futx *fu;
 
-	return (NULL);
+	fu = getfutxent();
+	if (fu == NULL)
+		return (NULL);
+	futx_to_utx(fu, &utx);
+	return (&utx);
 }
 
 struct utmpx *
 getutxid(const struct utmpx *id)
 {
+	struct futx *fu;
 
-	return (NULL);
+	for (;;) {
+		fu = getfutxent();
+		if (fu == NULL)
+			return (NULL);
+
+		switch (fu->fu_type) {
+		case BOOT_TIME:
+		case OLD_TIME:
+		case NEW_TIME:
+		case SHUTDOWN_TIME:
+			if (fu->fu_type == id->ut_type)
+				goto found;
+		case USER_PROCESS:
+		case INIT_PROCESS:
+		case LOGIN_PROCESS:
+		case DEAD_PROCESS:
+			switch (id->ut_type) {
+			case USER_PROCESS:
+			case INIT_PROCESS:
+			case LOGIN_PROCESS:
+			case DEAD_PROCESS:
+				if (strncmp(fu->fu_id, id->ut_id,
+				    MIN(sizeof fu->fu_id, sizeof id->ut_id)) == 0)
+					goto found;
+			}
+		}
+	}
+
+found:
+	futx_to_utx(fu, &utx);
+	return (&utx);
 }
 
 struct utmpx *
 getutxline(const struct utmpx *line)
 {
+	struct futx *fu;
 
-	return (NULL);
-}
-
-void
-setutxent(void)
-{
+	for (;;) {
+		fu = getfutxent();
+		if (fu == NULL)
+			return (NULL);
+
+		switch (fu->fu_type) {
+		case USER_PROCESS:
+		case LOGIN_PROCESS:
+			if (strncmp(fu->fu_line, line->ut_line,
+			    MIN(sizeof fu->fu_line, sizeof line->ut_line)) == 0)
+				goto found;
+		}
+	}
+
+found:
+	futx_to_utx(fu, &utx);
+	return (&utx);
 }

Modified: user/ed/utmpx/lib/libc/gen/pututxline.c
==============================================================================
--- user/ed/utmpx/lib/libc/gen/pututxline.c	Wed Jan  6 10:21:16 2010	(r201636)
+++ user/ed/utmpx/lib/libc/gen/pututxline.c	Wed Jan  6 10:29:53 2010	(r201637)
@@ -22,14 +22,13 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * $FreeBSD$
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
+#include <sys/stat.h>
 #include <fcntl.h>
 #include <string.h>
 #include <unistd.h>
@@ -38,6 +37,25 @@ __FBSDID("$FreeBSD$");
 #include "un-namespace.h"
 
 static int
+futx_open(const char *file)
+{
+	int fd;
+	struct stat sb;
+
+	fd = _open(file, O_CREAT|O_RDWR, 0644);
+	if (fd < 0)
+		return (-1);
+
+	/* Safety check: never use broken files. */
+	if (_fstat(fd, &sb) != -1 && sb.st_size % sizeof(struct futx) != 0) {
+		_close(fd);
+		return (-1);
+	}
+
+	return (fd);
+}
+
+static int
 utx_to_futx(const struct utmpx *ut, struct futx *fu)
 {
 
@@ -58,7 +76,6 @@ utx_to_futx(const struct utmpx *ut, stru
 		UTOF_STRING(ut, fu, host);
 		UTOF_PID(ut, fu);
 		break;
-#if 0
 	case INIT_PROCESS:
 		UTOF_STRING(ut, fu, id);
 		UTOF_PID(ut, fu);
@@ -68,7 +85,6 @@ utx_to_futx(const struct utmpx *ut, stru
 		UTOF_STRING(ut, fu, user);
 		UTOF_PID(ut, fu);
 		break;
-#endif
 	case DEAD_PROCESS:
 		UTOF_STRING(ut, fu, id);
 		UTOF_PID(ut, fu);
@@ -93,7 +109,7 @@ utx_active_add(const struct futx *fu)
 	 * Register user login sessions.  Overwrite entries of sessions
 	 * that have already been terminated.
 	 */
-	fd = _open(_PATH_UTX_ACTIVE, O_CREAT|O_RDWR, 0644);
+	fd = futx_open(_PATH_UTX_ACTIVE);
 	if (fd < 0)
 		return;
 	if (lockf(fd, F_LOCK, 0) == -1) {
@@ -101,15 +117,19 @@ utx_active_add(const struct futx *fu)
 		return;
 	}
 	while (_read(fd, &fe, sizeof fe) == sizeof fe) {
-		/*
-		 * XXX: This check is invalid.  We should perform a
-		 * similar comparison as getutxid().
-		 */
-		if (fe.fu_type != USER_PROCESS) {
+		switch (fe.fu_type) {
+		case USER_PROCESS:
+		case INIT_PROCESS:
+		case LOGIN_PROCESS:
+			if (strncmp(fu->fu_id, fe.fu_id, sizeof fe.fu_id) != 0)
+				continue;
+			/* FALLTHROUGH */
+		default:
 			lseek(fd, -sizeof fe, SEEK_CUR);
-			break;
+			goto found;
 		}
 	}
+found:
 	_write(fd, fu, sizeof *fu);
 	lockf(fd, F_ULOCK, 0);
 	_close(fd);
@@ -118,8 +138,37 @@ utx_active_add(const struct futx *fu)
 static int
 utx_active_remove(const struct futx *fu)
 {
+	int fd;
+	struct futx fe;
 
-	return (0);
+	/*
+	 * Remove user login sessions, having the same ut_id.
+	 */
+	fd = futx_open(_PATH_UTX_ACTIVE);
+	if (fd < 0)
+		return (0);
+	if (lockf(fd, F_LOCK, 0) == -1) {
+		_close(fd);
+		return (0);
+	}
+	while (_read(fd, &fe, sizeof fe) == sizeof fe) {
+		switch (fe.fu_type) {
+		case USER_PROCESS:
+		case INIT_PROCESS:
+		case LOGIN_PROCESS:
+			if (strncmp(fu->fu_id, fe.fu_id, sizeof fe.fu_id) != 0)
+				continue;
+			lseek(fd, -sizeof fe, SEEK_CUR);
+			_write(fd, fu, sizeof *fu);
+			lockf(fd, F_ULOCK, 0);
+			_close(fd);
+			return (0);
+		}
+	}
+
+	lockf(fd, F_ULOCK, 0);
+	_close(fd);
+	return (1);
 }
 
 static void
@@ -133,7 +182,7 @@ utx_lastlogin_add(const struct futx *fu)
 	 * current user already has an entry.  If not, append a new
 	 * entry.
 	 */
-	fd = _open(_PATH_UTX_LASTLOGIN, O_CREAT|O_RDWR, 0644);
+	fd = futx_open(_PATH_UTX_LASTLOGIN);
 	if (fd < 0)
 		return;
 	if (lockf(fd, F_LOCK, 0) == -1) {
@@ -164,8 +213,8 @@ utx_log_add(const struct futx *fu)
 	/*
 	 * Append an entry to the log file.  We only need to append
 	 * records to this file, so to conserve space, trim any trailing
-	 * zero-bytes.  Prepend a length field, indicating the record of
-	 * the length, excluding the length field itself.
+	 * zero-bytes.  Prepend a length field, indicating the length of
+	 * the record, excluding the length field itself.
 	 */
 	for (l = sizeof *fu; l > 0 && ((char *)fu)[l - 1] == '\0'; l--);
 	r.len = htobe16(l);
@@ -186,7 +235,7 @@ pututxline(const struct utmpx *utmpx)
 	if (utx_to_futx(utmpx, &fu) != 0)
 		return (NULL);
 	
-	switch (utmpx->ut_type) {
+	switch (fu.fu_type) {
 	case BOOT_TIME:
 	case OLD_TIME:
 	case NEW_TIME:
@@ -196,9 +245,11 @@ pututxline(const struct utmpx *utmpx)
 		utx_active_add(&fu);
 		utx_lastlogin_add(&fu);
 		break;
-#if 0
+#if 0 /* XXX: Are these records of any use to us? */
 	case INIT_PROCESS:
 	case LOGIN_PROCESS:
+		utx_active_add(&fu);
+		break;
 #endif
 	case DEAD_PROCESS:
 		if (utx_active_remove(&fu) != 0)

Modified: user/ed/utmpx/lib/libc/gen/utxdb.h
==============================================================================
--- user/ed/utmpx/lib/libc/gen/utxdb.h	Wed Jan  6 10:21:16 2010	(r201636)
+++ user/ed/utmpx/lib/libc/gen/utxdb.h	Wed Jan  6 10:29:53 2010	(r201637)
@@ -53,9 +53,26 @@ struct futx {
 	uint32_t	fu_pid;
 	char		fu_user[32];
 	char		fu_line[32];
-	char		fu_host[256];
+	char		fu_host[128];
 } __packed;
 
+#define	FTOU_STRING(fu, ut, field) do { \
+	strncpy((ut)->ut_ ## field, (fu)->fu_ ## field,		\
+	    MIN(sizeof (ut)->ut_ ## field - 1, sizeof (fu)->fu_ ## field)); \
+} while (0)
+#define	FTOU_PID(fu, ut) do { \
+	(ut)->ut_pid = be32toh((fu)->fu_pid);				\
+} while (0)
+#define	FTOU_TYPE(fu, ut) do { \
+	(ut)->ut_type = (fu)->fu_type;					\
+} while (0)
+#define	FTOU_TV(fu, ut) do { \
+	uint64_t t;							\
+	t = be64toh((fu)->fu_tv);					\
+	(ut)->ut_tv.tv_sec = t / 1000000;				\
+	(ut)->ut_tv.tv_usec = t % 1000000;				\
+} while (0)
+
 #define	UTOF_STRING(ut, fu, field) do { \
 	strncpy((fu)->fu_ ## field, (ut)->ut_ ## field,		\
 	    MIN(sizeof (fu)->fu_ ## field, sizeof (ut)->ut_ ## field));	\



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001061029.o06ATsvs096571>