svn commit: r202188 - in head: include lib/libc/gen lib/libulog

Ed Schouten ed at FreeBSD.org
Wed Jan 13 17:29:56 UTC 2010


Author: ed
Date: Wed Jan 13 17:29:55 2010
New Revision: 202188
URL: http://svn.freebsd.org/changeset/base/202188

Log:
  Implement <utmpx.h>.
  
  The utmpx interface is the standardized interface of the user accounting
  database. The standard only defines a subset of the functions that were
  present in System V-like systems.
  
  I'd like to highlight some of the traits my implementation has:
  
  - The standard allows the on-disk format to be different than the
    in-memory representation (struct utmpx). Most operating systems don't
    do this, but we do. This allows us to keep our ABI more stable, while
    giving us the opportunity to modify the on-disk format. It also allows
    us to use a common file format across different architectures (i.e.
    byte ordering).
  
  - Our implementation of pututxline() also updates wtmp and lastlog (now
    called utx.log and utx.lastlogin). This means the databases are more
    likely to be in sync.
  
  - Care must be taken that our implementation discard any fields that are
    not applicable. For example, our DEAD_PROCESS records do not hold a
    TTY name. Just a time stamp, a record identifier and a process
    identifier. It also guarantees that strings (ut_host, ut_line and
    ut_user) are null terminated. ut_id is obviously not null terminated,
    because it's not a string.
  
  - The API and its behaviour should be conformant to POSIX, but there may
    be things that slightly deviate from the standard. This implementation
    uses separate file descriptors when writing to the log files. It also
    doesn't use getutxid() to search for a field to overwrite. It uses an
    allocation strategy similar to getutxid(), but prevents DEAD_PROCESS
    records from accumulating.
  
  Make sure libulog doesn't overwrite the manpages shipped with our C
  library. Also keep the symbol list in Symbol.map sorted.
  
  I'll bump __FreeBSD_version later this evening. I first want to convert
  everything to <utmpx.h> and get rid of <utmp.h>.

Added:
  head/include/utmpx.h   (contents, props changed)
  head/lib/libc/gen/getutxent.3   (contents, props changed)
  head/lib/libc/gen/getutxent.c   (contents, props changed)
  head/lib/libc/gen/pututxline.c   (contents, props changed)
  head/lib/libc/gen/utxdb.c   (contents, props changed)
  head/lib/libc/gen/utxdb.h   (contents, props changed)
Modified:
  head/include/Makefile
  head/lib/libc/gen/Makefile.inc
  head/lib/libc/gen/Symbol.map
  head/lib/libulog/Makefile

Modified: head/include/Makefile
==============================================================================
--- head/include/Makefile	Wed Jan 13 14:17:21 2010	(r202187)
+++ head/include/Makefile	Wed Jan 13 17:29:55 2010	(r202188)
@@ -23,8 +23,8 @@ INCS=	a.out.h ar.h assert.h bitstring.h 
 	stdbool.h stddef.h stdio.h stdlib.h string.h stringlist.h \
 	strings.h sysexits.h tar.h termios.h tgmath.h \
 	time.h timeconv.h timers.h ttyent.h \
-	ulimit.h unistd.h utime.h utmp.h uuid.h varargs.h vis.h wchar.h \
-	wctype.h wordexp.h
+	ulimit.h unistd.h utime.h utmp.h utmpx.h uuid.h varargs.h vis.h \
+	wchar.h wctype.h wordexp.h
 
 MHDRS=	float.h floatingpoint.h stdarg.h
 

Added: head/include/utmpx.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/include/utmpx.h	Wed Jan 13 17:29:55 2010	(r202188)
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2010 Ed Schouten <ed at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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$
+ */
+
+#ifndef _UTMPX_H_
+#define	_UTMPX_H_
+
+#include <sys/cdefs.h>
+#include <sys/_timeval.h>
+#include <sys/_types.h>
+
+#ifndef _PID_T_DECLARED
+typedef	__pid_t		pid_t;
+#define	_PID_T_DECLARED
+#endif
+
+struct utmpx {
+	short		ut_type;	/* Type of entry. */
+	struct timeval	ut_tv;		/* Time entry was made. */
+	char		ut_id[8];	/* Record identifier. */
+	pid_t		ut_pid;		/* Process ID. */
+	char		ut_user[32];	/* User login name. */
+	char		ut_line[16];	/* Device name. */
+#if __BSD_VISIBLE
+	char		ut_host[128];	/* Remote hostname. */
+#else
+	char		__ut_host[128];
+#endif
+	char		__ut_spare[64];
+};
+
+#define	EMPTY		0	/* No valid user accounting information. */
+#define	BOOT_TIME	1	/* Time of system boot. */
+#define	OLD_TIME	2	/* Time when system clock changed. */
+#define	NEW_TIME	3	/* Time after system clock changed. */
+#define	USER_PROCESS	4	/* A process. */
+#define	INIT_PROCESS	5	/* A process spawned by the init process. */
+#define	LOGIN_PROCESS	6	/* The session leader of a logged-in user. */
+#define	DEAD_PROCESS	7	/* A session leader who has exited. */
+#if __BSD_VISIBLE
+#define	SHUTDOWN_TIME	8	/* Time of system shutdown. */
+#endif
+
+#if __BSD_VISIBLE
+#define	UTXDB_ACTIVE	0	/* Active login sessions. */
+#define	UTXDB_LASTLOGIN	1	/* Last login sessions. */
+#define	UTXDB_LOG	2	/* Log indexed by time. */
+#endif
+
+__BEGIN_DECLS
+void	endutxent(void);
+struct utmpx *getutxent(void);
+struct utmpx *getutxid(const struct utmpx *);
+struct utmpx *getutxline(const struct utmpx *);
+struct utmpx *pututxline(const struct utmpx *);
+void	setutxent(void);
+
+#if __BSD_VISIBLE
+struct utmpx *getutxuser(const char *);
+int	setutxdb(int, const char *);
+#endif
+__END_DECLS
+
+#endif /* !_UTMPX_H_ */

Modified: head/lib/libc/gen/Makefile.inc
==============================================================================
--- head/lib/libc/gen/Makefile.inc	Wed Jan 13 14:17:21 2010	(r202187)
+++ head/lib/libc/gen/Makefile.inc	Wed Jan 13 17:29:55 2010	(r202188)
@@ -18,12 +18,12 @@ SRCS+=  __getosreldate.c __xuname.c \
 	gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \
 	getosreldate.c getpagesize.c getpagesizes.c \
 	getpeereid.c getprogname.c getpwent.c getttyent.c \
-	getusershell.c getvfsbyname.c glob.c \
+	getusershell.c getutxent.c getvfsbyname.c glob.c \
 	initgroups.c isatty.c isinf.c isnan.c jrand48.c lcong48.c \
 	lockf.c lrand48.c mrand48.c nftw.c nice.c \
 	nlist.c nrand48.c opendir.c \
 	pause.c pmadvise.c popen.c posix_spawn.c \
-	psignal.c pw_scan.c pwcache.c \
+	psignal.c pututxline.c pw_scan.c pwcache.c \
 	raise.c readdir.c readpassphrase.c rewinddir.c \
 	scandir.c seed48.c seekdir.c sem.c sem_new.c semctl.c \
 	setdomainname.c sethostname.c setjmperr.c setmode.c \
@@ -32,7 +32,7 @@ SRCS+=  __getosreldate.c __xuname.c \
 	sysconf.c sysctl.c sysctlbyname.c sysctlnametomib.c \
 	syslog.c telldir.c termios.c time.c times.c timezone.c tls.c \
 	ttyname.c ttyslot.c ualarm.c ulimit.c uname.c unvis.c \
-	usleep.c utime.c valloc.c vis.c wait.c wait3.c waitpid.c \
+	usleep.c utime.c utxdb.c valloc.c vis.c wait.c wait3.c waitpid.c \
 	wordexp.c
 
 SYM_MAPS+=${.CURDIR}/gen/Symbol.map
@@ -54,7 +54,7 @@ MAN+=	alarm.3 arc4random.3 \
 	getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \
 	getmntinfo.3 getnetgrent.3 getosreldate.3 getpagesize.3 \
 	getpagesizes.3 getpass.3 getpeereid.3 getprogname.3 getpwent.3 \
-	getttyent.3 getusershell.3 getvfsbyname.3 \
+	getttyent.3 getusershell.3 getutxent.3 getvfsbyname.3 \
 	glob.3 initgroups.3 isgreater.3 ldexp.3 lockf.3 makecontext.3 \
 	modf.3 \
 	nice.3 nlist.3 pause.3 popen.3 \
@@ -126,6 +126,10 @@ MLINKS+=getttyent.3 endttyent.3 getttyen
 	getttyent.3 isdialuptty.3 getttyent.3 isnettty.3 \
 	getttyent.3 setttyent.3
 MLINKS+=getusershell.3 endusershell.3 getusershell.3 setusershell.3
+MLINKS+=getutxent.3 endutxent.3 getutxent.3 getutxid.3 \
+	getutxent.3 getutxline.3 getutxent.3 getutxuser.3 \
+	getutxent.3 pututxline.3 getutxent.3 setutxdb.3 \
+	getutxent.3 setutxent.3
 MLINKS+=glob.3 globfree.3
 MLINKS+=isgreater.3 isgreaterequal.3 isgreater.3 isless.3 \
 	isgreater.3 islessequal.3 isgreater.3 islessgreater.3 \

Modified: head/lib/libc/gen/Symbol.map
==============================================================================
--- head/lib/libc/gen/Symbol.map	Wed Jan 13 14:17:21 2010	(r202187)
+++ head/lib/libc/gen/Symbol.map	Wed Jan 13 17:29:55 2010	(r202188)
@@ -359,17 +359,25 @@ FBSD_1.1 {
 
 FBSD_1.2 {
 	basename_r;
+	endutxent;
 	getpagesizes;
+	getutxent;
+	getutxid;
+	getutxline;
+	getutxuser;
+	pututxline;
 	sem_close;
 	sem_destroy;
 	sem_getvalue;
 	sem_init;
 	sem_open;
+	sem_post;
 	sem_timedwait;
 	sem_trywait;
-	sem_post;
-	sem_wait;
 	sem_unlink;
+	sem_wait;
+	setutxdb;
+	setutxent;
 };
 
 FBSDprivate_1.0 {

Added: head/lib/libc/gen/getutxent.3
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libc/gen/getutxent.3	Wed Jan 13 17:29:55 2010	(r202188)
@@ -0,0 +1,440 @@
+.\" Copyright (c) 2010 Ed Schouten <ed at FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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$
+.\"
+.Dd January 8, 2010
+.Os
+.Dt GETUTXENT 3
+.Sh NAME
+.Nm endutxent ,
+.Nm getutxent ,
+.Nm getutxid ,
+.Nm getutxline ,
+.Nm getutxuser ,
+.Nm pututxline ,
+.Nm setutxdb ,
+.Nm setutxent
+.Nd user accounting database functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In utmpx.h
+.Ft void
+.Fn endutxent "void"
+.Ft struct utmpx *
+.Fn getutxent "void"
+.Ft struct utmpx *
+.Fn getutxid "const struct utmpx *id"
+.Ft struct utmpx *
+.Fn getutxline "const struct utmpx *line"
+.Ft struct utmpx *
+.Fn getutxuser "const char *user"
+.Ft struct utmpx *
+.Fn pututxline "const struct utmpx *utmpx"
+.Ft int
+.Fn setutxdb "int type" "const char *file"
+.Ft void
+.Fn setutxent "void"
+.Sh DESCRIPTION
+These functions operate on the user accounting database which stores
+records of various system activities, such as user login and logouts,
+but also system startups and shutdowns and modifications to the system's
+clock.
+The system stores these records in three databases, each having a
+different purpose:
+.Bl -tag -width indent
+.It Pa /var/run/utx.active
+Log of currently active user login sessions.
+This file is similar to the traditional
+.Pa utmp
+file.
+This file only contains process related entries, such as user login and
+logout records.
+.It Pa /var/log/utx.lastlogin
+Log of last user login entries per user.
+This file is similar to the traditional
+.Pa lastlog
+file.
+This file only contains user login records for users who have at least
+logged in once.
+.It Pa /var/log/utx.log
+Log of all entries, sorted by date of addition.
+This file is similar to the traditional
+.Pa wtmp
+file.
+This file may contain any type of record described below.
+.El
+.Pp
+Each entry in these databases is defined by the structure
+.Vt utmpx
+found in the include file
+.In utmpx.h :
+.Bd -literal -offset indent
+struct utmpx {
+	short           ut_type;    /* Type of entry. */
+	struct timeval  ut_tv;      /* Time entry was made. */
+	char            ut_id[];    /* Record identifier. */
+	pid_t           ut_pid;     /* Process ID. */
+	char            ut_user[];  /* User login name. */
+	char            ut_line[];  /* Device name. */
+	char            ut_host[];  /* Remote hostname. */
+};
+.Ed
+.Pp
+The
+.Fa ut_type
+field indicates the type of the log entry, which can have one of the
+following values:
+.Bl -tag -width LOGIN_PROCESS
+.It Dv EMPTY
+No valid user accounting information.
+.It Dv BOOT_TIME
+Identifies time of system boot.
+.It Dv SHUTDOWN_TIME
+Identifies time of system shutdown.
+.It Dv OLD_TIME
+Identifies time when system clock changed.
+.It Dv NEW_TIME
+Identifies time after system clock changed.
+.It Dv USER_PROCESS
+Identifies a process.
+.It Dv INIT_PROCESS
+Identifies a process spawned by the init process.
+.It Dv LOGIN_PROCESS
+Identifies the session leader of a logged-in user.
+.It Dv DEAD_PROCESS
+Identifies a session leader who has exited.
+.El
+.Pp
+Entries of type
+.Dv INIT_PROCESS
+and
+.Dv LOGIN_PROCESS
+are not processed by this implementation.
+.Pp
+Other fields inside the structure are:
+.Bl -tag -width ut_user
+.It Fa ut_tv
+The time the event occured.
+This field is used for all types of entries.
+.It Fa ut_id
+An identifier that is used to refer to the entry.
+This identifier can be used to remove or replace a login entry by
+writing a new entry to the database containing the same value for
+.Fa ut_id .
+This field is only applicable to entries of type
+.Dv USER_PROCESS ,
+.Dv INIT_PROCESS ,
+.Dv LOGIN_PROCESS
+and
+.Dv DEAD_PROCESS .
+.It Fa ut_pid
+The process identifier of the session leader of the login session.
+This field is only applicable to entries of type
+.Dv USER_PROCESS ,
+.Dv INIT_PROCESS ,
+.Dv LOGIN_PROCESS
+and
+.Dv DEAD_PROCESS .
+.It Fa ut_user
+The user login name corresponding with the login session.
+This field is only applicable to entries of type
+.Dv USER_PROCESS
+and
+.Dv INIT_PROCESS .
+For
+.Dv INIT_PROCESS
+entries this entry typically contains the name of the login process.
+.It Fa ut_line
+The name of the TTY character device, without the leading
+.Pa /dev/
+prefix, corresponding with the device used to facilitate the user login
+session.
+If no TTY character device is used, this field is left blank.
+This field is only applicable to entries of type
+.Dv USER_PROCESS .
+.It Fa ut_host
+The network hostname of the remote system, connecting to perform a user
+login.
+If the user login session is not performed across a network, this field
+is left blank.
+This field is only applicable to entries of type
+.Dv USER_PROCESS .
+.El
+.Pp
+This implementation guarantees all inapplicable fields are discarded.
+The
+.Fa ut_user ,
+.Fa ut_line
+and
+.Fa ut_host
+fields of the structure returned by the library functions are also
+guaranteed to be null-terminated in this implementation.
+.Pp
+The
+.Fn getutxent
+function can be used to read the next entry from the user accounting
+database.
+.Pp
+The
+.Fn getutxid
+function searches for the next entry in the database of which the
+behaviour is based on the
+.Fa ut_type
+field of
+.Fa id .
+If
+.Fa ut_type
+has a value of
+.Dv BOOT_TIME ,
+.Dv SHUTDOWN_TIME ,
+.Dv OLD_TIME
+or
+.Dv NEW_TIME ,
+it will return the next entry whose
+.Fa ut_type
+has an equal value.
+If
+.Fa ut_type
+has a value of
+.Dv USER_PROCESS ,
+.Dv INIT_PROCESS ,
+.Dv LOGIN_PROCESS
+or
+.Dv DEAD_PROCESS ,
+it will return the next entry whose
+.Fa ut_type
+has one of the previously mentioned values and whose
+.Fa ut_id
+is equal.
+.Pp
+The
+.Fn getutxline
+function searches for the next entry in the database whose
+.Fa ut_type
+has a value of
+.Dv USER_PROCESS
+or
+.Dv LOGIN_PROCESS
+and whose
+.Fa ut_line
+is equal to the the same field in
+.Fa line .
+.Pp
+The
+.Fn getutxuser
+function searches for the next entry in the database whose
+.Fa ut_type
+has a value of
+.Dv USER_PROCESS
+and whose
+.Fa ut_user
+is equal to
+.Fa user .
+.Pp
+The previously mentioned functions will automatically try to open the
+user accounting database if not already done so.
+The
+.Fn setutxdb
+and
+.Fn setutxent
+functions allow the database to be opened manually, causing the offset
+within the user accounting database to be rewound.
+The
+.Fn endutxent
+function closes the database.
+.Pp
+The
+.Fn setutxent
+database always opens the active sessions database.
+The
+.Fn setutxdb
+function opens the database identified by
+.Fa type ,
+whose value is either
+.Dv UTXDB_ACTIVE ,
+.Dv UTXDB_LASTLOGIN
+or
+.Dv UTXDB_LOG .
+It will open a custom file with filename
+.Fa file
+instead of the system-default if
+.Fa file
+is not null.
+Care must be taken that when using a custom filename,
+.Fa type
+still has to match with the actual format, since each database may use
+its own file format.
+.Pp
+The
+.Fn pututxline
+function writes record
+.Fa utmpx
+to the system-default user accounting databases.
+The value of
+.Fa ut_type
+determines which databases are modified.
+.Pp
+Entries of type
+.Dv BOOT_TIME ,
+.Dv SHUTDOWN_TIME ,
+.Dv OLD_TIME
+and
+.Dv NEW_TIME
+will only be written to
+.Pa /var/log/utx.log .
+.Pp
+Entries of type
+.Dv USER_PROCESS
+will also be written to
+.Pa /var/run/utx.active .
+It will only be written to
+.Pa /var/log/utx.lastlogin
+if
+.Fa ut_tv
+for that user has a greater value than the existing entry or when no
+entry for the user has been found.
+.Pp
+Entries of type
+.Dv DEAD_PROCESS
+will only be written to
+.Pa /var/log/utx.log
+and
+.Pa /var/run/utx.active
+if a corresponding
+.Dv USER_PROCESS ,
+.Dv INIT_PROCESS
+or
+.Dv LOGIN_PROCESS
+entry whose
+.Fa ut_id
+is equal has been found in the latter.
+.Pp
+In addition, entries of type
+.Dv BOOT_TIME
+and
+.Dv SHUTDOWN_TIME
+will cause all entries in
+.Pa /var/run/utx.active
+to be discarded.
+.Pp
+All entries whose type has not been mentioned previously, are discarded
+by this implementation of
+.Fn pututxline .
+.Sh RETURN VALUES
+The
+.Fn getutxent ,
+.Fn getutxid ,
+.Fn getutxline ,
+and
+.Fn getutxuser
+functions return a pointer to an
+.Vt utmpx
+structure that matches the mentioned constraints on success or
+.Dv NULL
+when reaching the end-of-file or when an error occurs.
+.Pp
+The
+.Fn pututxline
+function returns a pointer to an
+.Vt utmpx
+structure containing a copy of the structure written to disk upon
+success.
+It returns
+.Dv NULL
+when the provided
+.Vt utmpx
+is invalid.
+This may be because
+.Fa ut_type
+is invalid or
+.Fa ut_type
+has a value of
+.Dv DEAD_PROCESS
+and an entry with an identifier with a value equal to the field
+.Fa ut_id
+was not found.
+.Pp
+The
+.Fn setutxdb
+function returns 0 if the user accounting database was opened
+successfully.
+Otherwise, -1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+In addition to the error conditions described in
+.Xr fopen 3 ,
+the
+.Fn setutxdb
+function can generate the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa type
+argument contains a value not supported by this implementation.
+.It Bq Er EFTYPE
+The file format is invalid.
+.El
+.Sh SEE ALSO
+.Xr last 1 ,
+.Xr write 1 ,
+.Xr getpid 2 ,
+.Xr gettimeofday 2 ,
+.Xr tty 4 ,
+.Xr ac 8 ,
+.Xr newsyslog 8
+.Sh STANDARDS
+The
+.Fn endutxent ,
+.Fn getutxent ,
+.Fn getutxid ,
+.Fn getutxline ,
+.Fn pututxline
+and
+.Fn setutxent
+functions are expected to conform to
+.St -p1003.1-2008 .
+.Pp
+The
+.Fn getutxuser
+and
+.Fn setutxdb
+functions,
+the
+.Fa ut_host
+field of the
+.Vt utmpx
+structure and
+.Dv SHUTDOWN_TIME
+are extensions.
+.Sh HISTORY
+These functions appeared in
+.Fx 9.0 .
+They replaced the 
+.In utmp.h
+interface.
+.Sh AUTHORS
+.An Ed Schouten Aq ed at FreeBSD.org

Added: head/lib/libc/gen/getutxent.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libc/gen/getutxent.c	Wed Jan 13 17:29:55 2010	(r202188)
@@ -0,0 +1,232 @@
+/*-
+ * Copyright (c) 2010 Ed Schouten <ed at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/stat.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)
+{
+	struct stat sb;
+
+	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);
+
+	/* Safety check: never use broken files. */
+	if (db != UTXDB_LOG && _fstat(fileno(uf), &sb) != -1 &&
+	    sb.st_size % sizeof(struct futx) != 0) {
+		fclose(uf);
+		uf = NULL;
+		errno = EFTYPE;
+		return (-1);
+	}
+
+	udb = db;
+	return (0);
+}
+
+void
+setutxent(void)
+{
+
+	setutxdb(UTXDB_ACTIVE, NULL);
+}
+
+void
+endutxent(void)
+{
+
+	if (uf != NULL) {
+		fclose(uf);
+		uf = NULL;
+	}
+}
+
+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);
+		}
+	} else {
+		if (fread(&fu, sizeof fu, 1, uf) != 1)
+			return (NULL);
+	}
+	return (&fu);
+}
+
+struct utmpx *
+getutxent(void)
+{
+	struct futx *fu;
+
+	fu = getfutxent();
+	if (fu == NULL)
+		return (NULL);
+	futx_to_utx(fu, &utx);
+	return (&utx);
+}
+
+struct utmpx *
+getutxid(const struct utmpx *id)
+{
+	struct futx *fu;
+
+	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 (memcmp(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;
+
+	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);
+}
+
+struct utmpx *
+getutxuser(const char *user)
+{
+	struct futx *fu;
+
+	for (;;) {
+		fu = getfutxent();
+		if (fu == NULL)
+			return (NULL);
+
+		switch (fu->fu_type) {
+		case USER_PROCESS:
+			if (strncmp(fu->fu_user, user, sizeof fu->fu_user) == 0)
+				goto found;
+		}
+	}
+
+found:
+	futx_to_utx(fu, &utx);
+	return (&utx);
+}

Added: head/lib/libc/gen/pututxline.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libc/gen/pututxline.c	Wed Jan 13 17:29:55 2010	(r202188)
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 2010 Ed Schouten <ed at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/endian.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include "utxdb.h"
+#include "un-namespace.h"
+
+static FILE *
+futx_open(const char *file)
+{
+	int fd;
+	FILE *fp;
+	struct stat sb;
+
+	fd = _open(file, O_CREAT|O_RDWR|O_EXLOCK, 0644);
+	if (fd < 0)
+		return (NULL);
+
+	/* Safety check: never use broken files. */
+	if (_fstat(fd, &sb) != -1 && sb.st_size % sizeof(struct futx) != 0) {
+		_close(fd);
+		return (NULL);
+	}
+	
+	fp = fdopen(fd, "r+");
+	if (fp == NULL) {
+		_close(fd);
+		return (NULL);
+	}
+
+	return (fp);
+}
+
+static void
+utx_active_add(const struct futx *fu)
+{
+	FILE *fp;
+	struct futx fe;
+	off_t partial = -1;
+
+	/*
+	 * Register user login sessions.  Overwrite entries of sessions
+	 * that have already been terminated.
+	 */
+	fp = futx_open(_PATH_UTX_ACTIVE);
+	if (fp == NULL)
+		return;
+	while (fread(&fe, sizeof fe, 1, fp) == 1) {
+		switch (fe.fu_type) {
+		case USER_PROCESS:
+		case INIT_PROCESS:
+		case LOGIN_PROCESS:
+		case DEAD_PROCESS:
+			/* Overwrite when ut_id matches. */
+			if (memcmp(fu->fu_id, fe.fu_id, sizeof fe.fu_id) == 0) {
+				fseeko(fp, -sizeof fe, SEEK_CUR);
+				goto exact;
+			}
+			if (fe.fu_type != DEAD_PROCESS)
+				break;
+			/* FALLTHROUGH */
+		default:
+			/* Allow us to overwrite unused records. */
+			if (partial == -1)
+				partial = fseeko(fp, 0, SEEK_CUR) - sizeof fe;
+			break;
+		}
+	}
+	
+	/*
+	 * No exact match found.  Use the partial match.  If no partial
+	 * match was found, just append a new record.
+	 */
+	if (partial != -1)
+		fseeko(fp, partial, SEEK_SET);
+exact:
+	fwrite(fu, sizeof *fu, 1, fp);
+	fclose(fp);
+}
+
+static int
+utx_active_remove(struct futx *fu)
+{
+	FILE *fp;
+	struct futx fe;
+
+	/*
+	 * Remove user login sessions, having the same ut_id.
+	 */
+	fp = futx_open(_PATH_UTX_ACTIVE);
+	if (fp == NULL)
+		return (0);
+	while (fread(&fe, sizeof fe, 1, fp) == 1) {
+		switch (fe.fu_type) {
+		case USER_PROCESS:
+		case INIT_PROCESS:
+		case LOGIN_PROCESS:
+			if (memcmp(fu->fu_id, fe.fu_id, sizeof fe.fu_id) != 0)
+				continue;
+
+			/*
+			 * Prevent login sessions from having a negative
+			 * timespan.
+			 */
+			if (be64toh(fu->fu_tv) < be64toh(fe.fu_tv))

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list