utmpx - Initial commit
authorAlex Hornung <ahornung@gmail.com>
Sun, 4 Oct 2009 17:44:56 +0000 (18:44 +0100)
committerAlex Hornung <ahornung@gmail.com>
Wed, 15 Dec 2010 17:46:01 +0000 (17:46 +0000)
utmpx - Initial commit

include/Makefile
include/utmpx.h [new file with mode: 0644]
lib/libc/gen/Makefile.inc
lib/libc/gen/utmpx.c [new file with mode: 0644]
lib/libutil/Makefile
lib/libutil/libutil.h
lib/libutil/loginx.c [new file with mode: 0644]
lib/libutil/logoutx.c [new file with mode: 0644]
lib/libutil/logwtmpx.c [new file with mode: 0644]

index b478e2e..4c5c0e0 100644 (file)
@@ -25,7 +25,7 @@ INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h ctype.h db.h \
        string.h stringlist.h strings.h struct.h sysexits.h tar.h time.h \
        timeconv.h \
        timers.h ttyent.h unistd.h ulimit.h utime.h utmp.h uuid.h vis.h \
-       wchar.h wctype.h wordexp.h
+       utmpx.h wchar.h wctype.h wordexp.h
 
 .if defined(WANT_HESIOD)
 INCS+= hesiod.h
diff --git a/include/utmpx.h b/include/utmpx.h
new file mode 100644 (file)
index 0000000..3531082
--- /dev/null
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef        _UTMPX_H_
+#define        _UTMPX_H_
+
+#include <sys/cdefs.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#define        _PATH_UTMPX             "/var/run/utmpx"
+#define        _PATH_WTMPX             "/var/log/wtmpx"
+#define        _PATH_LASTLOGX          "/var/log/lastlogx"
+#define        _PATH_UTMP_UPDATE       "/usr/libexec/utmp_update"
+
+#define _UTX_USERSIZE  32
+#define _UTX_LINESIZE  32
+#define        _UTX_IDSIZE     4
+#define _UTX_HOSTSIZE  256
+
+#define UTX_USERSIZE   _UTX_USERSIZE
+#define UTX_LINESIZE   _UTX_LINESIZE
+#define        UTX_IDSIZE      _UTX_IDSIZE
+#define UTX_HOSTSIZE   _UTX_HOSTSIZE
+
+
+#define EMPTY          0
+#define RUN_LVL                1
+#define BOOT_TIME      2
+#define OLD_TIME       3
+#define NEW_TIME       4
+#define INIT_PROCESS   5
+#define LOGIN_PROCESS  6
+#define USER_PROCESS   7
+#define DEAD_PROCESS   8
+
+#define ACCOUNTING     9
+#define SIGNATURE      10
+#define DOWN_TIME      11
+
+/*
+ * Strings placed in the ut_line field to indicate special type entries
+ */
+#define        RUNLVL_MSG      "run-level %c"
+#define        BOOT_MSG        "system boot"
+#define        OTIME_MSG       "old time"
+#define        NTIME_MSG       "new time"
+#define        DOWN_MSG        "system down"
+
+#define ut_user ut_name
+#define ut_xtime ut_tv.tv_sec
+
+struct exit_status
+{
+       uint16_t e_termination;         /* termination status */
+       uint16_t e_exit;                /* exit status */
+};
+
+struct utmpx {
+       char ut_name[_UTX_USERSIZE];    /* login name */
+       char ut_id[_UTX_IDSIZE];        /* inittab id */
+       char ut_line[_UTX_LINESIZE];    /* tty name */
+       char ut_host[_UTX_HOSTSIZE];    /* host name */
+       uint8_t ut_unused[16];          /* reserved for future use */
+       uint16_t ut_session;            /* session id used for windowing */
+       uint16_t ut_type;               /* type of this entry */
+       pid_t ut_pid;                   /* process id creating the entry */
+       struct exit_status ut_exit;     /* process termination/exit status */
+       struct sockaddr_storage ut_ss;  /* address where entry was made from */
+       struct timeval ut_tv;           /* time entry was created */
+       uint8_t ut_unused2[16];         /* reserved for future use */
+};
+
+
+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);
+
+/* NON-STANDARD functions, NetBSD specific stuff */
+struct lastlogx {
+       struct timeval ll_tv;           /* time entry was created */
+       char ll_line[_UTX_LINESIZE];    /* tty name */
+       char ll_host[_UTX_HOSTSIZE];    /* host name */
+       struct sockaddr_storage ll_ss;  /* address where entry was made from */
+};
+
+int updwtmpx(const char *, const struct utmpx *);
+struct lastlogx *getlastlogx(const char *, uid_t, struct lastlogx *);
+int updlastlogx(const char *, uid_t, struct lastlogx *);
+struct utmp;
+void getutmp(const struct utmpx *, struct utmp *);
+void getutmpx(const struct utmp *, struct utmpx *);
+int utmpxname(const char *);
+
+#endif /* _UTMPX_H_ */
+
index 4a7c246..faf62a1 100644 (file)
@@ -36,6 +36,7 @@ SRCS+=  _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \
        sysctlnametomib.c syslog.c telldir.c termios.c time.c times.c \
        toascii.c tolower.c toupper.c ttyname.c ttyslot.c \
        ualarm.c ucontext.c ulimit.c uname.c unvis.c usleep.c utime.c \
+       utmpx.c \
        valloc.c vis.c wait.c wait3.c waitpid.c wordexp.c
 
 .if ${LIB} != {c_rtld}
diff --git a/lib/libc/gen/utmpx.c b/lib/libc/gen/utmpx.c
new file mode 100644 (file)
index 0000000..cdae055
--- /dev/null
@@ -0,0 +1,436 @@
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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>
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#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>
+#include <utmp.h>
+#include <utmpx.h>
+#include <vis.h>
+
+static FILE *fp;
+static int readonly = 0;
+static struct utmpx ut;
+static char utfile[MAXPATHLEN] = _PATH_UTMPX;
+
+static struct utmpx *utmp_update(const struct utmpx *);
+
+static const char vers[] = "utmpx-2.00";
+
+void
+setutxent()
+{
+
+       (void)memset(&ut, 0, sizeof(ut));
+       if (fp == NULL)
+               return;
+       (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
+}
+
+void
+endutxent()
+{
+
+       (void)memset(&ut, 0, sizeof(ut));
+       if (fp != NULL) {
+               (void)fclose(fp);
+               fp = NULL;
+               readonly = 0;
+       }
+}
+
+struct utmpx *
+getutxent()
+{
+
+       if (fp == NULL) {
+               struct stat st;
+
+               if ((fp = fopen(utfile, "r+")) == NULL)
+                       if ((fp = fopen(utfile, "w+")) == NULL) {
+                               if ((fp = fopen(utfile, "r")) == NULL)
+                                       goto fail;
+                               else
+                                       readonly = 1;
+                       }
+
+
+               /* get file size in order to check if new file */
+               if (fstat(fileno(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)
+                               goto failclose;
+               } else {
+                       /* old file, read signature record */
+                       if (fread(&ut, sizeof(ut), 1, fp) != 1)
+                               goto failclose;
+                       if (memcmp(ut.ut_user, vers, 5) != 0 ||
+                           ut.ut_type != SIGNATURE)
+                               goto failclose;
+               }
+       }
+
+       if (fread(&ut, sizeof(ut), 1, fp) != 1)
+               goto fail;
+
+       return &ut;
+failclose:
+       (void)fclose(fp);
+fail:
+       (void)memset(&ut, 0, sizeof(ut));
+       return NULL;
+}
+
+struct utmpx *
+getutxid(const struct utmpx *utx)
+{
+
+       _DIAGASSERT(utx != NULL);
+
+       if (utx->ut_type == EMPTY)
+               return NULL;
+
+       do {
+               if (ut.ut_type == EMPTY)
+                       continue;
+               switch (utx->ut_type) {
+               case EMPTY:
+                       return NULL;
+               case RUN_LVL:
+               case BOOT_TIME:
+               case OLD_TIME:
+               case NEW_TIME:
+                       if (ut.ut_type == utx->ut_type)
+                               return &ut;
+                       break;
+               case INIT_PROCESS:
+               case LOGIN_PROCESS:
+               case USER_PROCESS:
+               case DEAD_PROCESS:
+                       switch (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;
+                               break;
+                       default:
+                               break;
+                       }
+                       break;
+               default:
+                       return NULL;
+               }
+       } while (getutxent() != NULL);
+       return NULL;
+}
+
+struct utmpx *
+getutxline(const struct utmpx *utx)
+{
+
+       _DIAGASSERT(utx != NULL);
+
+       do {
+               switch (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;
+                       break;
+               default:
+                       break;
+               }
+       } while (getutxent() != NULL);
+       return NULL;
+}
+
+struct utmpx *
+pututxline(const struct utmpx *utx)
+{
+       struct utmpx temp, *u = NULL;
+       int gotlock = 0;
+
+       _DIAGASSERT(utx != NULL);
+
+       if (utx == NULL)
+               return NULL;
+
+       if (strcmp(_PATH_UTMPX, utfile) == 0)
+               if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0))
+                       return utmp_update(utx);
+
+
+       (void)memcpy(&temp, utx, sizeof(temp));
+
+       if (fp == NULL) {
+               (void)getutxent();
+               if (fp == NULL || readonly)
+                       return NULL;
+       }
+
+       if (getutxid(&temp) == NULL) {
+               setutxent();
+               if (getutxid(&temp) == NULL) {
+                       if (lockf(fileno(fp), F_LOCK, (off_t)0) == -1)
+                               return NULL;
+                       gotlock++;
+                       if (fseeko(fp, (off_t)0, SEEK_END) == -1)
+                               goto fail;
+               }
+       }
+
+       if (!gotlock) {
+               /* we are not appending */
+               if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
+                       return NULL;
+       }
+
+       if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
+               goto fail;
+
+       if (fflush(fp) == -1)
+               goto fail;
+
+       u = memcpy(&ut, &temp, sizeof(ut));
+fail:
+       if (gotlock) {
+               if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
+                       return NULL;
+       }
+       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)
+{
+       size_t len;
+
+       _DIAGASSERT(fname != NULL);
+
+       len = strlen(fname);
+
+       if (len >= sizeof(utfile))
+               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)
+{
+
+       _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)
+{
+
+       _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;
+       (void)memset(&ux->ut_ss, 0, sizeof(ux->ut_ss));
+       ux->ut_pid = 0;
+       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;
+}
index 3a81293..3c8a26c 100644 (file)
@@ -6,9 +6,10 @@ LIB=   util
 SHLIB_MAJOR= 4
 CFLAGS+=-DINET6
 CFLAGS+=-D_CTYPE_H_DISABLE_MACROS_ 
-SRCS=  flopen.c login.c login_tty.c logout.c logwtmp.c pty.c \
+SRCS=  flopen.c login.c login_tty.c logout.c logwtmp.c logwtmpx.c pty.c \
        login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
-       login_crypt.c _secure_path.c uucplock.c property.c auth.c \
+       login_crypt.c loginx.c logoutx.c _secure_path.c uucplock.c \
+       property.c auth.c \
        realhostname.c fparseln.c stub.c pidfile.c trimdomain.c \
        dehumanize_number.c humanize_number.c humanize_unsigned.c pw_util.c
 INCS=  libutil.h login_cap.h
index 77bf3df..c79b25e 100644 (file)
@@ -59,15 +59,19 @@ typedef struct _property {
 struct termios;
 struct winsize;
 struct utmp;
+struct utmpx;
 struct in_addr;
 struct sockaddr;
 
 __BEGIN_DECLS
 int    flopen(const char *, int, ...);
 void   login(struct utmp *);
+void   loginx(const struct utmpx *);
 int    login_tty(int);
 int    logout(const char *);
+int    logoutx(const char *, int, int);
 void   logwtmp(const char *, const char *, const char *);
+void   logwtmpx(const char *, const char *, const char *, int, int);
 void   trimdomain(char *, int);
 int    openpty(int *, int *, char *, struct termios *, struct winsize *);
 int    forkpty(int *, char *, struct termios *, struct winsize *);
diff --git a/lib/libutil/loginx.c b/lib/libutil/loginx.c
new file mode 100644 (file)
index 0000000..d111b3a
--- /dev/null
@@ -0,0 +1,51 @@
+/*     $NetBSD: loginx.c,v 1.2 2003/08/07 16:44:59 agc Exp $   */
+
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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>
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libutil.h>
+#include <utmp.h>
+#include <utmpx.h>
+
+void
+loginx(const struct utmpx *ut)
+{
+       (void)pututxline(ut);
+       (void)updwtmpx(_PATH_WTMPX, ut);
+}
diff --git a/lib/libutil/logoutx.c b/lib/libutil/logoutx.c
new file mode 100644 (file)
index 0000000..6793853
--- /dev/null
@@ -0,0 +1,66 @@
+/*     $NetBSD: logoutx.c,v 1.2 2003/08/07 16:44:59 agc Exp $  */
+
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <libutil.h>
+#include <utmp.h>
+#include <utmpx.h>
+
+int
+logoutx(const char *line, int status, int type)
+{
+       struct utmpx *utp, ut;
+       (void)strlcpy(ut.ut_line, line, sizeof(ut.ut_line));
+       if ((utp = getutxline(&ut)) == NULL) {
+               endutxent();
+               return 0;
+       }
+       utp->ut_type = type;
+       if (WIFEXITED(status))
+               utp->ut_exit.e_exit = (uint16_t)WEXITSTATUS(status);
+       if (WIFSIGNALED(status))
+               utp->ut_exit.e_termination = (uint16_t)WTERMSIG(status);
+       (void)gettimeofday(&utp->ut_tv, NULL);
+       (void)pututxline(utp);
+       endutxent();
+       return 1;
+}
diff --git a/lib/libutil/logwtmpx.c b/lib/libutil/logwtmpx.c
new file mode 100644 (file)
index 0000000..f703149
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: logwtmpx.c,v 1.2 2003/08/07 16:44:59 agc Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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>
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <assert.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <utmpx.h>
+#include <libutil.h>
+
+void
+logwtmpx(const char *line, const char *name, const char *host, int status,
+    int type)
+{
+       struct utmpx ut;
+
+       _DIAGASSERT(line != NULL);
+       _DIAGASSERT(name != NULL);
+       _DIAGASSERT(host != NULL);
+
+       (void)memset(&ut, 0, sizeof(ut));
+       (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+       (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
+       (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+       ut.ut_type = type;
+       if (WIFEXITED(status))
+               ut.ut_exit.e_exit = (uint16_t)WEXITSTATUS(status);
+       if (WIFSIGNALED(status))
+               ut.ut_exit.e_termination = (uint16_t)WTERMSIG(status);
+       (void)gettimeofday(&ut.ut_tv, NULL);
+       (void)updwtmpx(_PATH_WTMPX, &ut);
+}
+