1*0a6a1f1dSLionel Sambuc /* $NetBSD: utmpx.c,v 1.35 2015/05/23 11:48:13 christos Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras * Copyright (c) 2002 The NetBSD Foundation, Inc.
52fe8fb19SBen Gras * All rights reserved.
62fe8fb19SBen Gras *
72fe8fb19SBen Gras * This code is derived from software contributed to The NetBSD Foundation
82fe8fb19SBen Gras * by Christos Zoulas.
92fe8fb19SBen Gras *
102fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without
112fe8fb19SBen Gras * modification, are permitted provided that the following conditions
122fe8fb19SBen Gras * are met:
132fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright
142fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer.
152fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
162fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the
172fe8fb19SBen Gras * documentation and/or other materials provided with the distribution.
182fe8fb19SBen Gras *
192fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
202fe8fb19SBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
212fe8fb19SBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
222fe8fb19SBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
232fe8fb19SBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
242fe8fb19SBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
252fe8fb19SBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
262fe8fb19SBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
272fe8fb19SBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
282fe8fb19SBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
292fe8fb19SBen Gras * POSSIBILITY OF SUCH DAMAGE.
302fe8fb19SBen Gras */
312fe8fb19SBen Gras #include <sys/cdefs.h>
322fe8fb19SBen Gras
332fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
34*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: utmpx.c,v 1.35 2015/05/23 11:48:13 christos Exp $");
352fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
362fe8fb19SBen Gras
372fe8fb19SBen Gras #include "namespace.h"
382fe8fb19SBen Gras #include <sys/types.h>
392fe8fb19SBen Gras #include <sys/param.h>
402fe8fb19SBen Gras #include <sys/socket.h>
412fe8fb19SBen Gras #include <sys/stat.h>
422fe8fb19SBen Gras #include <sys/time.h>
432fe8fb19SBen Gras #include <sys/wait.h>
442fe8fb19SBen Gras
452fe8fb19SBen Gras #include <assert.h>
462fe8fb19SBen Gras #include <db.h>
472fe8fb19SBen Gras #include <errno.h>
482fe8fb19SBen Gras #include <fcntl.h>
492fe8fb19SBen Gras #include <stdio.h>
502fe8fb19SBen Gras #include <stdlib.h>
512fe8fb19SBen Gras #include <string.h>
522fe8fb19SBen Gras #include <unistd.h>
532fe8fb19SBen Gras #include <utmp.h>
542fe8fb19SBen Gras #include <utmpx.h>
552fe8fb19SBen Gras #include <vis.h>
562fe8fb19SBen Gras
572fe8fb19SBen Gras static FILE *fp;
582fe8fb19SBen Gras static int readonly = 0;
592fe8fb19SBen Gras static int version = 1;
602fe8fb19SBen Gras static struct utmpx ut;
612fe8fb19SBen Gras static char utfile[MAXPATHLEN] = _PATH_UTMPX;
622fe8fb19SBen Gras
632fe8fb19SBen Gras static struct utmpx *utmp_update(const struct utmpx *);
642fe8fb19SBen Gras
652fe8fb19SBen Gras static const char vers[] = "utmpx-2.00";
662fe8fb19SBen Gras
672fe8fb19SBen Gras struct otimeval {
682fe8fb19SBen Gras long tv_sec;
692fe8fb19SBen Gras long tv_usec;
702fe8fb19SBen Gras };
712fe8fb19SBen Gras
722fe8fb19SBen Gras static void
old2new(struct utmpx * utx)732fe8fb19SBen Gras old2new(struct utmpx *utx)
742fe8fb19SBen Gras {
752fe8fb19SBen Gras struct otimeval otv;
762fe8fb19SBen Gras struct timeval *tv = &utx->ut_tv;
772fe8fb19SBen Gras (void)memcpy(&otv, tv, sizeof(otv));
782fe8fb19SBen Gras tv->tv_sec = otv.tv_sec;
79f14fb602SLionel Sambuc tv->tv_usec = (suseconds_t)otv.tv_usec;
802fe8fb19SBen Gras }
812fe8fb19SBen Gras
822fe8fb19SBen Gras static void
new2old(struct utmpx * utx)832fe8fb19SBen Gras new2old(struct utmpx *utx)
842fe8fb19SBen Gras {
85*0a6a1f1dSLionel Sambuc struct otimeval otv;
8684d9c625SLionel Sambuc struct timeval *tv = &utx->ut_tv;
8784d9c625SLionel Sambuc
8884d9c625SLionel Sambuc otv.tv_sec = (long)tv->tv_sec;
8984d9c625SLionel Sambuc otv.tv_usec = (long)tv->tv_usec;
9084d9c625SLionel Sambuc (void)memcpy(tv, &otv, sizeof(otv));
912fe8fb19SBen Gras }
922fe8fb19SBen Gras
932fe8fb19SBen Gras void
setutxent(void)94f14fb602SLionel Sambuc setutxent(void)
952fe8fb19SBen Gras {
962fe8fb19SBen Gras
972fe8fb19SBen Gras (void)memset(&ut, 0, sizeof(ut));
982fe8fb19SBen Gras if (fp == NULL)
992fe8fb19SBen Gras return;
1002fe8fb19SBen Gras (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
1012fe8fb19SBen Gras }
1022fe8fb19SBen Gras
1032fe8fb19SBen Gras
1042fe8fb19SBen Gras void
endutxent(void)105f14fb602SLionel Sambuc endutxent(void)
1062fe8fb19SBen Gras {
1072fe8fb19SBen Gras
1082fe8fb19SBen Gras (void)memset(&ut, 0, sizeof(ut));
1092fe8fb19SBen Gras if (fp != NULL) {
1102fe8fb19SBen Gras (void)fclose(fp);
1112fe8fb19SBen Gras fp = NULL;
1122fe8fb19SBen Gras readonly = 0;
1132fe8fb19SBen Gras }
1142fe8fb19SBen Gras }
1152fe8fb19SBen Gras
1162fe8fb19SBen Gras
1172fe8fb19SBen Gras struct utmpx *
getutxent(void)118f14fb602SLionel Sambuc getutxent(void)
1192fe8fb19SBen Gras {
1202fe8fb19SBen Gras
1212fe8fb19SBen Gras if (fp == NULL) {
1222fe8fb19SBen Gras struct stat st;
1232fe8fb19SBen Gras
124f14fb602SLionel Sambuc if ((fp = fopen(utfile, "re+")) == NULL)
125*0a6a1f1dSLionel Sambuc if ((fp = fopen(utfile, "we+")) == NULL) {
126*0a6a1f1dSLionel Sambuc if ((fp = fopen(utfile, "re")) == NULL)
1272fe8fb19SBen Gras goto fail;
1282fe8fb19SBen Gras else
1292fe8fb19SBen Gras readonly = 1;
1302fe8fb19SBen Gras }
1312fe8fb19SBen Gras
1322fe8fb19SBen Gras
1332fe8fb19SBen Gras /* get file size in order to check if new file */
1342fe8fb19SBen Gras if (fstat(fileno(fp), &st) == -1)
1352fe8fb19SBen Gras goto failclose;
1362fe8fb19SBen Gras
1372fe8fb19SBen Gras if (st.st_size == 0) {
1382fe8fb19SBen Gras /* new file, add signature record */
1392fe8fb19SBen Gras (void)memset(&ut, 0, sizeof(ut));
1402fe8fb19SBen Gras ut.ut_type = SIGNATURE;
1412fe8fb19SBen Gras (void)memcpy(ut.ut_user, vers, sizeof(vers));
1422fe8fb19SBen Gras if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
1432fe8fb19SBen Gras goto failclose;
1442fe8fb19SBen Gras } else {
1452fe8fb19SBen Gras /* old file, read signature record */
1462fe8fb19SBen Gras if (fread(&ut, sizeof(ut), 1, fp) != 1)
1472fe8fb19SBen Gras goto failclose;
1482fe8fb19SBen Gras if (memcmp(ut.ut_user, vers, 5) != 0 ||
1492fe8fb19SBen Gras ut.ut_type != SIGNATURE)
1502fe8fb19SBen Gras goto failclose;
1512fe8fb19SBen Gras }
1522fe8fb19SBen Gras version = ut.ut_user[6] - '0';
1532fe8fb19SBen Gras }
1542fe8fb19SBen Gras
1552fe8fb19SBen Gras if (fread(&ut, sizeof(ut), 1, fp) != 1)
1562fe8fb19SBen Gras goto fail;
1572fe8fb19SBen Gras if (version == 1)
1582fe8fb19SBen Gras old2new(&ut);
1592fe8fb19SBen Gras
1602fe8fb19SBen Gras return &ut;
1612fe8fb19SBen Gras failclose:
1622fe8fb19SBen Gras (void)fclose(fp);
1632fe8fb19SBen Gras fail:
1642fe8fb19SBen Gras (void)memset(&ut, 0, sizeof(ut));
1652fe8fb19SBen Gras return NULL;
1662fe8fb19SBen Gras }
1672fe8fb19SBen Gras
1682fe8fb19SBen Gras
1692fe8fb19SBen Gras struct utmpx *
getutxid(const struct utmpx * utx)1702fe8fb19SBen Gras getutxid(const struct utmpx *utx)
1712fe8fb19SBen Gras {
1722fe8fb19SBen Gras
1732fe8fb19SBen Gras _DIAGASSERT(utx != NULL);
1742fe8fb19SBen Gras
1752fe8fb19SBen Gras if (utx->ut_type == EMPTY)
1762fe8fb19SBen Gras return NULL;
1772fe8fb19SBen Gras
1782fe8fb19SBen Gras do {
1792fe8fb19SBen Gras if (ut.ut_type == EMPTY)
1802fe8fb19SBen Gras continue;
1812fe8fb19SBen Gras switch (utx->ut_type) {
1822fe8fb19SBen Gras case EMPTY:
1832fe8fb19SBen Gras return NULL;
1842fe8fb19SBen Gras case RUN_LVL:
1852fe8fb19SBen Gras case BOOT_TIME:
1862fe8fb19SBen Gras case OLD_TIME:
1872fe8fb19SBen Gras case NEW_TIME:
1882fe8fb19SBen Gras if (ut.ut_type == utx->ut_type)
1892fe8fb19SBen Gras return &ut;
1902fe8fb19SBen Gras break;
1912fe8fb19SBen Gras case INIT_PROCESS:
1922fe8fb19SBen Gras case LOGIN_PROCESS:
1932fe8fb19SBen Gras case USER_PROCESS:
1942fe8fb19SBen Gras case DEAD_PROCESS:
1952fe8fb19SBen Gras switch (ut.ut_type) {
1962fe8fb19SBen Gras case INIT_PROCESS:
1972fe8fb19SBen Gras case LOGIN_PROCESS:
1982fe8fb19SBen Gras case USER_PROCESS:
1992fe8fb19SBen Gras case DEAD_PROCESS:
2002fe8fb19SBen Gras if (memcmp(ut.ut_id, utx->ut_id,
2012fe8fb19SBen Gras sizeof(ut.ut_id)) == 0)
2022fe8fb19SBen Gras return &ut;
2032fe8fb19SBen Gras break;
2042fe8fb19SBen Gras default:
2052fe8fb19SBen Gras break;
2062fe8fb19SBen Gras }
2072fe8fb19SBen Gras break;
2082fe8fb19SBen Gras default:
2092fe8fb19SBen Gras return NULL;
2102fe8fb19SBen Gras }
2112fe8fb19SBen Gras } while (getutxent() != NULL);
2122fe8fb19SBen Gras return NULL;
2132fe8fb19SBen Gras }
2142fe8fb19SBen Gras
2152fe8fb19SBen Gras
2162fe8fb19SBen Gras struct utmpx *
getutxline(const struct utmpx * utx)2172fe8fb19SBen Gras getutxline(const struct utmpx *utx)
2182fe8fb19SBen Gras {
2192fe8fb19SBen Gras
2202fe8fb19SBen Gras _DIAGASSERT(utx != NULL);
2212fe8fb19SBen Gras
2222fe8fb19SBen Gras do {
2232fe8fb19SBen Gras switch (ut.ut_type) {
2242fe8fb19SBen Gras case EMPTY:
2252fe8fb19SBen Gras break;
2262fe8fb19SBen Gras case LOGIN_PROCESS:
2272fe8fb19SBen Gras case USER_PROCESS:
2282fe8fb19SBen Gras if (strncmp(ut.ut_line, utx->ut_line,
2292fe8fb19SBen Gras sizeof(ut.ut_line)) == 0)
2302fe8fb19SBen Gras return &ut;
2312fe8fb19SBen Gras break;
2322fe8fb19SBen Gras default:
2332fe8fb19SBen Gras break;
2342fe8fb19SBen Gras }
2352fe8fb19SBen Gras } while (getutxent() != NULL);
2362fe8fb19SBen Gras return NULL;
2372fe8fb19SBen Gras }
2382fe8fb19SBen Gras
2392fe8fb19SBen Gras
2402fe8fb19SBen Gras struct utmpx *
pututxline(const struct utmpx * utx)2412fe8fb19SBen Gras pututxline(const struct utmpx *utx)
2422fe8fb19SBen Gras {
2432fe8fb19SBen Gras struct utmpx temp, *u = NULL;
2442fe8fb19SBen Gras int gotlock = 0;
2452fe8fb19SBen Gras
2462fe8fb19SBen Gras _DIAGASSERT(utx != NULL);
2472fe8fb19SBen Gras
2482fe8fb19SBen Gras if (utx == NULL)
2492fe8fb19SBen Gras return NULL;
2502fe8fb19SBen Gras
251f14fb602SLionel Sambuc if (strcmp(_PATH_UTMPX, utfile) == 0) {
252f14fb602SLionel Sambuc if (geteuid() == 0) {
253f14fb602SLionel Sambuc if (fp != NULL && readonly)
254f14fb602SLionel Sambuc endutxent();
255f14fb602SLionel Sambuc } else {
256f14fb602SLionel Sambuc if (fp == NULL || readonly)
2572fe8fb19SBen Gras return utmp_update(utx);
258f14fb602SLionel Sambuc }
259f14fb602SLionel Sambuc }
2602fe8fb19SBen Gras
2612fe8fb19SBen Gras
2622fe8fb19SBen Gras (void)memcpy(&temp, utx, sizeof(temp));
2632fe8fb19SBen Gras
2642fe8fb19SBen Gras if (fp == NULL) {
2652fe8fb19SBen Gras (void)getutxent();
2662fe8fb19SBen Gras if (fp == NULL || readonly)
2672fe8fb19SBen Gras return NULL;
2682fe8fb19SBen Gras }
2692fe8fb19SBen Gras
2702fe8fb19SBen Gras if (getutxid(&temp) == NULL) {
2712fe8fb19SBen Gras setutxent();
2722fe8fb19SBen Gras if (getutxid(&temp) == NULL) {
2732fe8fb19SBen Gras if (lockf(fileno(fp), F_LOCK, (off_t)0) == -1)
2742fe8fb19SBen Gras return NULL;
2752fe8fb19SBen Gras gotlock++;
2762fe8fb19SBen Gras if (fseeko(fp, (off_t)0, SEEK_END) == -1)
2772fe8fb19SBen Gras goto fail;
2782fe8fb19SBen Gras }
2792fe8fb19SBen Gras }
2802fe8fb19SBen Gras
2812fe8fb19SBen Gras if (!gotlock) {
2822fe8fb19SBen Gras /* we are not appending */
2832fe8fb19SBen Gras if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
2842fe8fb19SBen Gras return NULL;
2852fe8fb19SBen Gras }
2862fe8fb19SBen Gras
2872fe8fb19SBen Gras if (version == 1)
2882fe8fb19SBen Gras new2old(&temp);
2892fe8fb19SBen Gras if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
2902fe8fb19SBen Gras goto fail;
2912fe8fb19SBen Gras
2922fe8fb19SBen Gras if (fflush(fp) == -1)
2932fe8fb19SBen Gras goto fail;
2942fe8fb19SBen Gras
2952fe8fb19SBen Gras u = memcpy(&ut, &temp, sizeof(ut));
2962fe8fb19SBen Gras fail:
2972fe8fb19SBen Gras if (gotlock) {
2982fe8fb19SBen Gras if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
2992fe8fb19SBen Gras return NULL;
3002fe8fb19SBen Gras }
3012fe8fb19SBen Gras return u;
3022fe8fb19SBen Gras }
3032fe8fb19SBen Gras
3042fe8fb19SBen Gras
3052fe8fb19SBen Gras static struct utmpx *
utmp_update(const struct utmpx * utx)3062fe8fb19SBen Gras utmp_update(const struct utmpx *utx)
3072fe8fb19SBen Gras {
3082fe8fb19SBen Gras char buf[sizeof(*utx) * 4 + 1];
3092fe8fb19SBen Gras pid_t pid;
3102fe8fb19SBen Gras int status;
3112fe8fb19SBen Gras
3122fe8fb19SBen Gras _DIAGASSERT(utx != NULL);
3132fe8fb19SBen Gras
3142fe8fb19SBen Gras (void)strvisx(buf, (const char *)(const void *)utx, sizeof(*utx),
315*0a6a1f1dSLionel Sambuc VIS_WHITE | VIS_NOLOCALE);
3162fe8fb19SBen Gras switch (pid = fork()) {
3172fe8fb19SBen Gras case 0:
3182fe8fb19SBen Gras (void)execl(_PATH_UTMP_UPDATE,
3192fe8fb19SBen Gras strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
3202fe8fb19SBen Gras _exit(1);
3212fe8fb19SBen Gras /*NOTREACHED*/
3222fe8fb19SBen Gras case -1:
3232fe8fb19SBen Gras return NULL;
3242fe8fb19SBen Gras default:
3252fe8fb19SBen Gras if (waitpid(pid, &status, 0) == -1)
3262fe8fb19SBen Gras return NULL;
3272fe8fb19SBen Gras if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
3282fe8fb19SBen Gras return memcpy(&ut, utx, sizeof(ut));
3292fe8fb19SBen Gras return NULL;
3302fe8fb19SBen Gras }
3312fe8fb19SBen Gras
3322fe8fb19SBen Gras }
3332fe8fb19SBen Gras
3342fe8fb19SBen Gras /*
3352fe8fb19SBen Gras * The following are extensions and not part of the X/Open spec.
3362fe8fb19SBen Gras */
3372fe8fb19SBen Gras int
updwtmpx(const char * file,const struct utmpx * utx)3382fe8fb19SBen Gras updwtmpx(const char *file, const struct utmpx *utx)
3392fe8fb19SBen Gras {
3402fe8fb19SBen Gras int fd;
3412fe8fb19SBen Gras int saved_errno;
3422fe8fb19SBen Gras
3432fe8fb19SBen Gras _DIAGASSERT(file != NULL);
3442fe8fb19SBen Gras _DIAGASSERT(utx != NULL);
3452fe8fb19SBen Gras
346*0a6a1f1dSLionel Sambuc fd = open(file, O_WRONLY|O_APPEND|O_SHLOCK|O_CLOEXEC);
3472fe8fb19SBen Gras
3482fe8fb19SBen Gras if (fd == -1) {
349*0a6a1f1dSLionel Sambuc if ((fd = open(file, O_CREAT|O_WRONLY|O_EXLOCK|O_CLOEXEC, 0644)) == -1)
3502fe8fb19SBen Gras return -1;
3512fe8fb19SBen Gras (void)memset(&ut, 0, sizeof(ut));
3522fe8fb19SBen Gras ut.ut_type = SIGNATURE;
3532fe8fb19SBen Gras (void)memcpy(ut.ut_user, vers, sizeof(vers));
3542fe8fb19SBen Gras if (write(fd, &ut, sizeof(ut)) == -1)
3552fe8fb19SBen Gras goto failed;
3562fe8fb19SBen Gras }
3572fe8fb19SBen Gras if (write(fd, utx, sizeof(*utx)) == -1)
3582fe8fb19SBen Gras goto failed;
3592fe8fb19SBen Gras if (close(fd) == -1)
3602fe8fb19SBen Gras return -1;
3612fe8fb19SBen Gras return 0;
3622fe8fb19SBen Gras
3632fe8fb19SBen Gras failed:
3642fe8fb19SBen Gras saved_errno = errno;
3652fe8fb19SBen Gras (void) close(fd);
3662fe8fb19SBen Gras errno = saved_errno;
3672fe8fb19SBen Gras return -1;
3682fe8fb19SBen Gras }
3692fe8fb19SBen Gras
3702fe8fb19SBen Gras
3712fe8fb19SBen Gras int
utmpxname(const char * fname)3722fe8fb19SBen Gras utmpxname(const char *fname)
3732fe8fb19SBen Gras {
3742fe8fb19SBen Gras size_t len;
3752fe8fb19SBen Gras
3762fe8fb19SBen Gras _DIAGASSERT(fname != NULL);
3772fe8fb19SBen Gras
3782fe8fb19SBen Gras len = strlen(fname);
3792fe8fb19SBen Gras
3802fe8fb19SBen Gras if (len >= sizeof(utfile))
3812fe8fb19SBen Gras return 0;
3822fe8fb19SBen Gras
3832fe8fb19SBen Gras /* must end in x! */
3842fe8fb19SBen Gras if (fname[len - 1] != 'x')
3852fe8fb19SBen Gras return 0;
3862fe8fb19SBen Gras
3872fe8fb19SBen Gras (void)strlcpy(utfile, fname, sizeof(utfile));
3882fe8fb19SBen Gras endutxent();
3892fe8fb19SBen Gras return 1;
3902fe8fb19SBen Gras }
3912fe8fb19SBen Gras
3922fe8fb19SBen Gras
3932fe8fb19SBen Gras void
getutmp(const struct utmpx * ux,struct utmp * u)3942fe8fb19SBen Gras getutmp(const struct utmpx *ux, struct utmp *u)
3952fe8fb19SBen Gras {
3962fe8fb19SBen Gras
3972fe8fb19SBen Gras _DIAGASSERT(ux != NULL);
3982fe8fb19SBen Gras _DIAGASSERT(u != NULL);
3992fe8fb19SBen Gras
4002fe8fb19SBen Gras (void)memcpy(u->ut_name, ux->ut_name, sizeof(u->ut_name));
4012fe8fb19SBen Gras (void)memcpy(u->ut_line, ux->ut_line, sizeof(u->ut_line));
4022fe8fb19SBen Gras (void)memcpy(u->ut_host, ux->ut_host, sizeof(u->ut_host));
4032fe8fb19SBen Gras u->ut_time = ux->ut_tv.tv_sec;
4042fe8fb19SBen Gras }
4052fe8fb19SBen Gras
4062fe8fb19SBen Gras void
getutmpx(const struct utmp * u,struct utmpx * ux)4072fe8fb19SBen Gras getutmpx(const struct utmp *u, struct utmpx *ux)
4082fe8fb19SBen Gras {
4092fe8fb19SBen Gras
4102fe8fb19SBen Gras _DIAGASSERT(ux != NULL);
4112fe8fb19SBen Gras _DIAGASSERT(u != NULL);
4122fe8fb19SBen Gras
4132fe8fb19SBen Gras (void)memcpy(ux->ut_name, u->ut_name, sizeof(u->ut_name));
4142fe8fb19SBen Gras (void)memcpy(ux->ut_line, u->ut_line, sizeof(u->ut_line));
4152fe8fb19SBen Gras (void)memcpy(ux->ut_host, u->ut_host, sizeof(u->ut_host));
4162fe8fb19SBen Gras ux->ut_tv.tv_sec = u->ut_time;
4172fe8fb19SBen Gras ux->ut_tv.tv_usec = 0;
4182fe8fb19SBen Gras (void)memset(&ux->ut_ss, 0, sizeof(ux->ut_ss));
4192fe8fb19SBen Gras ux->ut_pid = 0;
4202fe8fb19SBen Gras ux->ut_type = USER_PROCESS;
4212fe8fb19SBen Gras ux->ut_session = 0;
4222fe8fb19SBen Gras ux->ut_exit.e_termination = 0;
4232fe8fb19SBen Gras ux->ut_exit.e_exit = 0;
4242fe8fb19SBen Gras }
4252fe8fb19SBen Gras
4262fe8fb19SBen Gras struct lastlogx *
getlastlogx(const char * fname,uid_t uid,struct lastlogx * ll)4272fe8fb19SBen Gras getlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
4282fe8fb19SBen Gras {
4292fe8fb19SBen Gras DBT key, data;
4302fe8fb19SBen Gras DB *db;
4312fe8fb19SBen Gras
4322fe8fb19SBen Gras _DIAGASSERT(fname != NULL);
4332fe8fb19SBen Gras _DIAGASSERT(ll != NULL);
4342fe8fb19SBen Gras
435*0a6a1f1dSLionel Sambuc db = dbopen(fname, O_RDONLY|O_SHLOCK|O_CLOEXEC, 0, DB_HASH, NULL);
4362fe8fb19SBen Gras
4372fe8fb19SBen Gras if (db == NULL)
4382fe8fb19SBen Gras return NULL;
4392fe8fb19SBen Gras
4402fe8fb19SBen Gras key.data = &uid;
4412fe8fb19SBen Gras key.size = sizeof(uid);
4422fe8fb19SBen Gras
4432fe8fb19SBen Gras if ((db->get)(db, &key, &data, 0) != 0)
4442fe8fb19SBen Gras goto error;
4452fe8fb19SBen Gras
4462fe8fb19SBen Gras if (data.size != sizeof(*ll)) {
4472fe8fb19SBen Gras errno = EFTYPE;
4482fe8fb19SBen Gras goto error;
4492fe8fb19SBen Gras }
4502fe8fb19SBen Gras
4512fe8fb19SBen Gras if (ll == NULL)
4522fe8fb19SBen Gras if ((ll = malloc(sizeof(*ll))) == NULL)
4532fe8fb19SBen Gras goto done;
4542fe8fb19SBen Gras
4552fe8fb19SBen Gras (void)memcpy(ll, data.data, sizeof(*ll));
4562fe8fb19SBen Gras goto done;
4572fe8fb19SBen Gras error:
4582fe8fb19SBen Gras ll = NULL;
4592fe8fb19SBen Gras done:
4602fe8fb19SBen Gras (db->close)(db);
4612fe8fb19SBen Gras return ll;
4622fe8fb19SBen Gras }
4632fe8fb19SBen Gras
4642fe8fb19SBen Gras int
updlastlogx(const char * fname,uid_t uid,struct lastlogx * ll)4652fe8fb19SBen Gras updlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
4662fe8fb19SBen Gras {
4672fe8fb19SBen Gras DBT key, data;
4682fe8fb19SBen Gras int error = 0;
4692fe8fb19SBen Gras DB *db;
4702fe8fb19SBen Gras
4712fe8fb19SBen Gras _DIAGASSERT(fname != NULL);
4722fe8fb19SBen Gras _DIAGASSERT(ll != NULL);
4732fe8fb19SBen Gras
474*0a6a1f1dSLionel Sambuc db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK|O_CLOEXEC, 0644, DB_HASH, NULL);
4752fe8fb19SBen Gras
4762fe8fb19SBen Gras if (db == NULL)
4772fe8fb19SBen Gras return -1;
4782fe8fb19SBen Gras
4792fe8fb19SBen Gras key.data = &uid;
4802fe8fb19SBen Gras key.size = sizeof(uid);
4812fe8fb19SBen Gras data.data = ll;
4822fe8fb19SBen Gras data.size = sizeof(*ll);
4832fe8fb19SBen Gras if ((db->put)(db, &key, &data, 0) != 0)
4842fe8fb19SBen Gras error = -1;
4852fe8fb19SBen Gras
4862fe8fb19SBen Gras (db->close)(db);
4872fe8fb19SBen Gras return error;
4882fe8fb19SBen Gras }
489