From 510f6a45d47e5870206fd9a71bbfcf5bbaf387dd Mon Sep 17 00:00:00 2001 From: christos Date: Fri, 22 Feb 2002 20:11:44 +0000 Subject: [PATCH] A simple utmpx implementation. Nothing uses it yet. TODO: write the lastlog*() stuff. --- lib/libc/gen/Makefile.inc | 7 +- lib/libc/gen/utmpx.c | 293 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 297 insertions(+), 3 deletions(-) create mode 100644 lib/libc/gen/utmpx.c diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 566acde02e0d..4803c4d1e087 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.109 2002/01/24 02:46:35 lukem Exp $ +# $NetBSD: Makefile.inc,v 1.110 2002/02/22 20:11:44 christos Exp $ # from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95 # gen sources @@ -22,8 +22,9 @@ SRCS+= _errno.c alarm.c assert.c basename.c clock.c closedir.c \ __signame14.c signame.c __sigsetops14.c sigsetops.c sleep.c \ stringlist.c sysconf.c sysctl.c syslog.c telldir.c time.c times.c \ timezone.c toascii.c tolower_.c ttyname.c ttyslot.c toupper_.c \ - ualarm.c ulimit.c uname.c unvis.c usleep.c utime.c valloc.c vis.c \ - wait.c wait3.c waitpid.c warn.c warnx.c vwarn.c vwarnx.c verr.c verrx.c + ualarm.c ulimit.c uname.c unvis.c usleep.c utime.c utmpx.c valloc.c \ + vis.c wait.c wait3.c waitpid.c warn.c warnx.c vwarn.c vwarnx.c verr.c \ + verrx.c # indirect reference stubs, to be removed soon. SRCS+= _err.c _errx.c _sys_errlist.c _sys_nerr.c _sys_siglist.c \ diff --git a/lib/libc/gen/utmpx.c b/lib/libc/gen/utmpx.c new file mode 100644 index 000000000000..13aa98f65d59 --- /dev/null +++ b/lib/libc/gen/utmpx.c @@ -0,0 +1,293 @@ +/* $NetBSD: utmpx.c,v 1.1 2002/02/22 20:11:44 christos Exp $ */ + +/*- + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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 + +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: utmpx.c,v 1.1 2002/02/22 20:11:44 christos Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static FILE *fp; +static struct utmpx ut; +static char utfile[MAXPATHLEN] = _PATH_UTMPX; + +static struct utmpx *utmp_update(const struct utmpx *); + +static const char vers[] = "utmpx-1.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); +} + + +struct utmpx * +getutxent() +{ + if (fp == NULL) { + struct stat st; + + if ((fp = fopen(utfile, "r+")) == NULL) + if ((fp = fopen(utfile, "r")) == NULL) + goto fail; + + /* 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_name, vers, sizeof(vers)); + if (fwrite(&ut, sizeof(ut), 1, fp) != sizeof(ut)) + goto failclose; + } else { + /* old file, read signature record */ + if (fread(&ut, sizeof(ut), 1, fp) != sizeof(ut)) + goto failclose; + if (memcmp(ut.ut_name, vers, sizeof(vers)) != 0 || + ut.ut_type != SIGNATURE) + goto failclose; + } + } + + if (fread(&ut, sizeof(ut), 1, fp) != sizeof(ut)) + goto fail; + + return &ut; +failclose: + (void)fclose(fp); +fail: + (void)memset(&ut, 0, sizeof(ut)); + return NULL; +} + + +struct utmpx * +getutxid(const struct utmpx *utx) +{ + 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) +{ + 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; + + if (strcmp(_PATH_UTMPX, utfile) == 0 && geteuid() != 0) + return utmp_update(utx); + + if (utx == NULL) + return NULL; + + (void)memcpy(&temp, utx, sizeof(temp)); + + if (fp == NULL) { + (void)getutxent(); + if (fp == NULL) + 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; + + (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); + 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 +utmpxname(const char *fname) +{ + size_t len = strlen(fname); + + if (len >= sizeof(utfile)) + return 0; + + /* must end in x! */ + if (fname[len - 1] != 'x') + return 0; + + (void)strcpy(utfile, fname); + endutxent(); + return 1; +}