159a92d18SAlex Hornung /*-
259a92d18SAlex Hornung * Copyright (c) 2002 The NetBSD Foundation, Inc.
359a92d18SAlex Hornung * All rights reserved.
459a92d18SAlex Hornung *
559a92d18SAlex Hornung * This code is derived from software contributed to The NetBSD Foundation
659a92d18SAlex Hornung * by Christos Zoulas.
759a92d18SAlex Hornung *
859a92d18SAlex Hornung * Redistribution and use in source and binary forms, with or without
959a92d18SAlex Hornung * modification, are permitted provided that the following conditions
1059a92d18SAlex Hornung * are met:
1159a92d18SAlex Hornung * 1. Redistributions of source code must retain the above copyright
1259a92d18SAlex Hornung * notice, this list of conditions and the following disclaimer.
1359a92d18SAlex Hornung * 2. Redistributions in binary form must reproduce the above copyright
1459a92d18SAlex Hornung * notice, this list of conditions and the following disclaimer in the
1559a92d18SAlex Hornung * documentation and/or other materials provided with the distribution.
1659a92d18SAlex Hornung *
1759a92d18SAlex Hornung * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1859a92d18SAlex Hornung * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1959a92d18SAlex Hornung * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2059a92d18SAlex Hornung * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2159a92d18SAlex Hornung * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2259a92d18SAlex Hornung * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2359a92d18SAlex Hornung * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2459a92d18SAlex Hornung * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2559a92d18SAlex Hornung * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2659a92d18SAlex Hornung * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2759a92d18SAlex Hornung * POSSIBILITY OF SUCH DAMAGE.
2859a92d18SAlex Hornung */
2959a92d18SAlex Hornung
3059a92d18SAlex Hornung #include "namespace.h"
3159a92d18SAlex Hornung #include <sys/types.h>
3259a92d18SAlex Hornung #include <sys/param.h>
3359a92d18SAlex Hornung #include <sys/socket.h>
3459a92d18SAlex Hornung #include <sys/stat.h>
3559a92d18SAlex Hornung #include <sys/time.h>
3659a92d18SAlex Hornung #include <sys/wait.h>
3759a92d18SAlex Hornung
3859a92d18SAlex Hornung #include <assert.h>
3959a92d18SAlex Hornung #include <errno.h>
4059a92d18SAlex Hornung #include <fcntl.h>
4159a92d18SAlex Hornung #include <stdio.h>
4259a92d18SAlex Hornung #include <stdlib.h>
4359a92d18SAlex Hornung #include <string.h>
4459a92d18SAlex Hornung #include <unistd.h>
4559a92d18SAlex Hornung #include <pwd.h>
4659a92d18SAlex Hornung #include <utmpx.h>
4759a92d18SAlex Hornung #include <vis.h>
48*625fc06fSSascha Wildner #include "un-namespace.h"
49*625fc06fSSascha Wildner
50*625fc06fSSascha Wildner #include <db.h>
5159a92d18SAlex Hornung
5265f10536SSascha Wildner static FILE *fp;
5359a92d18SAlex Hornung static int readonly = 0;
5459a92d18SAlex Hornung static struct utmpx ut;
5559a92d18SAlex Hornung static char utfile[MAXPATHLEN] = _PATH_UTMPX;
5659a92d18SAlex Hornung
5759a92d18SAlex Hornung static struct utmpx *utmp_update(const struct utmpx *);
5859a92d18SAlex Hornung
5959a92d18SAlex Hornung static const char vers[] = "utmpx-2.00";
6059a92d18SAlex Hornung static utx_db_t dbtype = UTX_DB_UTMPX;
6159a92d18SAlex Hornung DB *lastlogx_db = NULL;
6259a92d18SAlex Hornung
639ae6396eSSascha Wildner void past_getutmp(void *, void *);
649ae6396eSSascha Wildner void past_getutmpx(void *, void *);
659ae6396eSSascha Wildner
6659a92d18SAlex Hornung static int
_open_db(const char * fname)677bb7a6edSSascha Wildner _open_db(const char *fname)
6859a92d18SAlex Hornung {
6959a92d18SAlex Hornung struct stat st;
7059a92d18SAlex Hornung
7165f10536SSascha Wildner if ((fp = fopen(fname, "re+")) == NULL)
7265f10536SSascha Wildner if ((fp = fopen(fname, "we+")) == NULL) {
7365f10536SSascha Wildner if ((fp = fopen(fname, "re")) == NULL)
7459a92d18SAlex Hornung goto fail;
7559a92d18SAlex Hornung else
7659a92d18SAlex Hornung readonly = 1;
7759a92d18SAlex Hornung }
7859a92d18SAlex Hornung
7959a92d18SAlex Hornung /* get file size in order to check if new file */
80*625fc06fSSascha Wildner if (_fstat(fileno(fp), &st) == -1)
8159a92d18SAlex Hornung goto failclose;
8259a92d18SAlex Hornung
8359a92d18SAlex Hornung if (st.st_size == 0) {
8459a92d18SAlex Hornung /* new file, add signature record */
8559a92d18SAlex Hornung (void)memset(&ut, 0, sizeof(ut));
8659a92d18SAlex Hornung ut.ut_type = SIGNATURE;
8759a92d18SAlex Hornung (void)memcpy(ut.ut_user, vers, sizeof(vers));
8859a92d18SAlex Hornung if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
8959a92d18SAlex Hornung goto failclose;
9059a92d18SAlex Hornung } else {
9159a92d18SAlex Hornung /* old file, read signature record */
9259a92d18SAlex Hornung if (fread(&ut, sizeof(ut), 1, fp) != 1)
9359a92d18SAlex Hornung goto failclose;
9459a92d18SAlex Hornung if (memcmp(ut.ut_user, vers, 5) != 0 ||
9559a92d18SAlex Hornung ut.ut_type != SIGNATURE) {
9659a92d18SAlex Hornung errno = EINVAL;
9759a92d18SAlex Hornung goto failclose;
9859a92d18SAlex Hornung }
9959a92d18SAlex Hornung }
10059a92d18SAlex Hornung
10159a92d18SAlex Hornung return 0;
10259a92d18SAlex Hornung failclose:
10359a92d18SAlex Hornung (void)fclose(fp);
10459a92d18SAlex Hornung fail:
10559a92d18SAlex Hornung (void)memset(&ut, 0, sizeof(ut));
10659a92d18SAlex Hornung return -1;
10759a92d18SAlex Hornung }
10859a92d18SAlex Hornung
10959a92d18SAlex Hornung int
setutxdb(utx_db_t db_type,const char * fname)1107bb7a6edSSascha Wildner setutxdb(utx_db_t db_type, const char *fname)
11159a92d18SAlex Hornung {
11259a92d18SAlex Hornung switch (db_type) {
11359a92d18SAlex Hornung case UTX_DB_UTMPX:
11459a92d18SAlex Hornung if (fname == NULL)
11559a92d18SAlex Hornung fname = _PATH_UTMPX;
11659a92d18SAlex Hornung break;
11759a92d18SAlex Hornung
11859a92d18SAlex Hornung case UTX_DB_WTMPX:
11959a92d18SAlex Hornung if (fname == NULL)
12059a92d18SAlex Hornung fname = _PATH_WTMPX;
12159a92d18SAlex Hornung break;
12259a92d18SAlex Hornung
12359a92d18SAlex Hornung default:
12459a92d18SAlex Hornung errno = EINVAL;
12559a92d18SAlex Hornung return -1;
12659a92d18SAlex Hornung }
12759a92d18SAlex Hornung
12859a92d18SAlex Hornung /* A previous db file is still open */
12959a92d18SAlex Hornung if (fp != NULL) {
13059a92d18SAlex Hornung fclose(fp);
13159a92d18SAlex Hornung fp = NULL;
13259a92d18SAlex Hornung }
13359a92d18SAlex Hornung if ((_open_db(fname)) == -1)
13459a92d18SAlex Hornung return -1;
13559a92d18SAlex Hornung
13659a92d18SAlex Hornung dbtype = db_type;
13759a92d18SAlex Hornung return 0;
13859a92d18SAlex Hornung }
13959a92d18SAlex Hornung
14059a92d18SAlex Hornung void
setutxent(void)1415d7d35b1SSascha Wildner setutxent(void)
14259a92d18SAlex Hornung {
14359a92d18SAlex Hornung (void)memset(&ut, 0, sizeof(ut));
14459a92d18SAlex Hornung if (fp == NULL)
14559a92d18SAlex Hornung return;
14659a92d18SAlex Hornung (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
14759a92d18SAlex Hornung }
14859a92d18SAlex Hornung
14959a92d18SAlex Hornung void
endutxent(void)1505d7d35b1SSascha Wildner endutxent(void)
15159a92d18SAlex Hornung {
15259a92d18SAlex Hornung (void)memset(&ut, 0, sizeof(ut));
15359a92d18SAlex Hornung
15459a92d18SAlex Hornung if (fp != NULL) {
15559a92d18SAlex Hornung (void)fclose(fp);
15659a92d18SAlex Hornung fp = NULL;
15759a92d18SAlex Hornung readonly = 0;
15859a92d18SAlex Hornung }
15959a92d18SAlex Hornung }
16059a92d18SAlex Hornung
16159a92d18SAlex Hornung struct utmpx *
getutxent(void)1625d7d35b1SSascha Wildner getutxent(void)
16359a92d18SAlex Hornung {
16459a92d18SAlex Hornung if (fp == NULL) {
16559a92d18SAlex Hornung if ((_open_db(utfile)) == -1)
16659a92d18SAlex Hornung goto fail;
16759a92d18SAlex Hornung }
16859a92d18SAlex Hornung
16959a92d18SAlex Hornung if (fread(&ut, sizeof(ut), 1, fp) != 1)
17059a92d18SAlex Hornung goto fail;
17159a92d18SAlex Hornung
17259a92d18SAlex Hornung return &ut;
17359a92d18SAlex Hornung fail:
17459a92d18SAlex Hornung (void)memset(&ut, 0, sizeof(ut));
17559a92d18SAlex Hornung return NULL;
17659a92d18SAlex Hornung }
17759a92d18SAlex Hornung
17859a92d18SAlex Hornung struct utmpx *
getutxid(const struct utmpx * utx)17959a92d18SAlex Hornung getutxid(const struct utmpx *utx)
18059a92d18SAlex Hornung {
18159a92d18SAlex Hornung
18259a92d18SAlex Hornung _DIAGASSERT(utx != NULL);
18359a92d18SAlex Hornung
18459a92d18SAlex Hornung if (utx->ut_type == EMPTY)
18559a92d18SAlex Hornung return NULL;
18659a92d18SAlex Hornung
18759a92d18SAlex Hornung do {
18859a92d18SAlex Hornung if (ut.ut_type == EMPTY)
18959a92d18SAlex Hornung continue;
19059a92d18SAlex Hornung switch (utx->ut_type) {
19159a92d18SAlex Hornung case EMPTY:
19259a92d18SAlex Hornung return NULL;
19359a92d18SAlex Hornung case RUN_LVL:
19459a92d18SAlex Hornung case BOOT_TIME:
19559a92d18SAlex Hornung case OLD_TIME:
19659a92d18SAlex Hornung case NEW_TIME:
19759a92d18SAlex Hornung if (ut.ut_type == utx->ut_type)
19859a92d18SAlex Hornung return &ut;
19959a92d18SAlex Hornung break;
20059a92d18SAlex Hornung case INIT_PROCESS:
20159a92d18SAlex Hornung case LOGIN_PROCESS:
20259a92d18SAlex Hornung case USER_PROCESS:
20359a92d18SAlex Hornung case DEAD_PROCESS:
20459a92d18SAlex Hornung switch (ut.ut_type) {
20559a92d18SAlex Hornung case INIT_PROCESS:
20659a92d18SAlex Hornung case LOGIN_PROCESS:
20759a92d18SAlex Hornung case USER_PROCESS:
20859a92d18SAlex Hornung case DEAD_PROCESS:
20959a92d18SAlex Hornung if (memcmp(ut.ut_id, utx->ut_id,
21059a92d18SAlex Hornung sizeof(ut.ut_id)) == 0)
21159a92d18SAlex Hornung return &ut;
21259a92d18SAlex Hornung break;
21359a92d18SAlex Hornung default:
21459a92d18SAlex Hornung break;
21559a92d18SAlex Hornung }
21659a92d18SAlex Hornung break;
21759a92d18SAlex Hornung default:
21859a92d18SAlex Hornung return NULL;
21959a92d18SAlex Hornung }
22059a92d18SAlex Hornung } while (getutxent() != NULL);
22159a92d18SAlex Hornung return NULL;
22259a92d18SAlex Hornung }
22359a92d18SAlex Hornung
22459a92d18SAlex Hornung struct utmpx *
getutxline(const struct utmpx * utx)22559a92d18SAlex Hornung getutxline(const struct utmpx *utx)
22659a92d18SAlex Hornung {
22759a92d18SAlex Hornung
22859a92d18SAlex Hornung _DIAGASSERT(utx != NULL);
22959a92d18SAlex Hornung
23059a92d18SAlex Hornung do {
23159a92d18SAlex Hornung switch (ut.ut_type) {
23259a92d18SAlex Hornung case EMPTY:
23359a92d18SAlex Hornung break;
23459a92d18SAlex Hornung case LOGIN_PROCESS:
23559a92d18SAlex Hornung case USER_PROCESS:
23659a92d18SAlex Hornung if (strncmp(ut.ut_line, utx->ut_line,
23759a92d18SAlex Hornung sizeof(ut.ut_line)) == 0)
23859a92d18SAlex Hornung return &ut;
23959a92d18SAlex Hornung break;
24059a92d18SAlex Hornung default:
24159a92d18SAlex Hornung break;
24259a92d18SAlex Hornung }
24359a92d18SAlex Hornung } while (getutxent() != NULL);
24459a92d18SAlex Hornung return NULL;
24559a92d18SAlex Hornung }
24659a92d18SAlex Hornung
24759a92d18SAlex Hornung struct utmpx *
getutxuser(const char * user)248974aa081SSascha Wildner getutxuser(const char *user)
249974aa081SSascha Wildner {
250974aa081SSascha Wildner _DIAGASSERT(utx != NULL);
251974aa081SSascha Wildner
252974aa081SSascha Wildner do {
253974aa081SSascha Wildner switch (ut.ut_type) {
254974aa081SSascha Wildner case EMPTY:
255974aa081SSascha Wildner break;
256974aa081SSascha Wildner case USER_PROCESS:
257974aa081SSascha Wildner if (strncmp(ut.ut_user, user, sizeof(ut.ut_user)) == 0)
258974aa081SSascha Wildner return &ut;
259974aa081SSascha Wildner break;
260974aa081SSascha Wildner default:
261974aa081SSascha Wildner break;
262974aa081SSascha Wildner }
263974aa081SSascha Wildner } while (getutxent() != NULL);
264974aa081SSascha Wildner return NULL;
265974aa081SSascha Wildner }
266974aa081SSascha Wildner
267974aa081SSascha Wildner struct utmpx *
pututxline(const struct utmpx * utx)26859a92d18SAlex Hornung pututxline(const struct utmpx *utx)
26959a92d18SAlex Hornung {
27059a92d18SAlex Hornung struct passwd *pw;
27159a92d18SAlex Hornung struct lastlogx ll;
27259a92d18SAlex Hornung struct utmpx temp, *u = NULL;
27359a92d18SAlex Hornung int gotlock = 0;
27459a92d18SAlex Hornung
27559a92d18SAlex Hornung _DIAGASSERT(utx != NULL);
27659a92d18SAlex Hornung
27759a92d18SAlex Hornung if (utx == NULL)
27859a92d18SAlex Hornung return NULL;
27959a92d18SAlex Hornung
28059a92d18SAlex Hornung if (utx->ut_type == USER_PROCESS) {
28159a92d18SAlex Hornung ll.ll_tv = utx->ut_tv;
28259a92d18SAlex Hornung strcpy(ll.ll_host, utx->ut_host);
28359a92d18SAlex Hornung strcpy(ll.ll_line, utx->ut_line);
28459a92d18SAlex Hornung pw = getpwnam(utx->ut_name);
28559a92d18SAlex Hornung if (pw != NULL)
28659a92d18SAlex Hornung updlastlogx(_PATH_LASTLOGX, pw->pw_uid, &ll);
28759a92d18SAlex Hornung }
28859a92d18SAlex Hornung
28959a92d18SAlex Hornung if (strcmp(_PATH_UTMPX, utfile) == 0)
29059a92d18SAlex Hornung if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0))
29159a92d18SAlex Hornung return utmp_update(utx);
29259a92d18SAlex Hornung
29359a92d18SAlex Hornung
29459a92d18SAlex Hornung (void)memcpy(&temp, utx, sizeof(temp));
29559a92d18SAlex Hornung
29659a92d18SAlex Hornung if (fp == NULL) {
29759a92d18SAlex Hornung (void)getutxent();
29859a92d18SAlex Hornung if (fp == NULL || readonly)
29959a92d18SAlex Hornung return NULL;
30059a92d18SAlex Hornung }
30159a92d18SAlex Hornung
30259a92d18SAlex Hornung if (getutxid(&temp) == NULL) {
30359a92d18SAlex Hornung setutxent();
30459a92d18SAlex Hornung if (getutxid(&temp) == NULL) {
30559a92d18SAlex Hornung if (lockf(fileno(fp), F_LOCK, (off_t)0) == -1)
30659a92d18SAlex Hornung return NULL;
30759a92d18SAlex Hornung gotlock++;
30859a92d18SAlex Hornung if (fseeko(fp, (off_t)0, SEEK_END) == -1)
30959a92d18SAlex Hornung goto fail;
31059a92d18SAlex Hornung }
31159a92d18SAlex Hornung }
31259a92d18SAlex Hornung
31359a92d18SAlex Hornung if (!gotlock) {
31459a92d18SAlex Hornung /* we are not appending */
31559a92d18SAlex Hornung if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
31659a92d18SAlex Hornung return NULL;
31759a92d18SAlex Hornung }
31859a92d18SAlex Hornung
31959a92d18SAlex Hornung if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
32059a92d18SAlex Hornung goto fail;
32159a92d18SAlex Hornung
32259a92d18SAlex Hornung if (fflush(fp) == -1)
32359a92d18SAlex Hornung goto fail;
32459a92d18SAlex Hornung
32559a92d18SAlex Hornung u = memcpy(&ut, &temp, sizeof(ut));
32659a92d18SAlex Hornung fail:
32759a92d18SAlex Hornung if (gotlock) {
32859a92d18SAlex Hornung if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
32959a92d18SAlex Hornung return NULL;
33059a92d18SAlex Hornung }
33159a92d18SAlex Hornung return u;
33259a92d18SAlex Hornung }
33359a92d18SAlex Hornung
33459a92d18SAlex Hornung static struct utmpx *
utmp_update(const struct utmpx * utx)33559a92d18SAlex Hornung utmp_update(const struct utmpx *utx)
33659a92d18SAlex Hornung {
33759a92d18SAlex Hornung char buf[sizeof(*utx) * 4 + 1];
33859a92d18SAlex Hornung pid_t pid;
33959a92d18SAlex Hornung int status;
34059a92d18SAlex Hornung
34159a92d18SAlex Hornung _DIAGASSERT(utx != NULL);
34259a92d18SAlex Hornung
34359a92d18SAlex Hornung (void)strvisx(buf, (const char *)(const void *)utx, sizeof(*utx),
34465f10536SSascha Wildner VIS_WHITE | VIS_NOLOCALE);
34559a92d18SAlex Hornung switch (pid = fork()) {
34659a92d18SAlex Hornung case 0:
34759a92d18SAlex Hornung (void)execl(_PATH_UTMP_UPDATE,
34859a92d18SAlex Hornung strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
34959a92d18SAlex Hornung _exit(1);
35059a92d18SAlex Hornung /*NOTREACHED*/
35159a92d18SAlex Hornung case -1:
35259a92d18SAlex Hornung return NULL;
35359a92d18SAlex Hornung default:
354*625fc06fSSascha Wildner if (_waitpid(pid, &status, 0) == -1)
35559a92d18SAlex Hornung return NULL;
35659a92d18SAlex Hornung if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
35759a92d18SAlex Hornung return memcpy(&ut, utx, sizeof(ut));
35859a92d18SAlex Hornung return NULL;
35959a92d18SAlex Hornung }
36059a92d18SAlex Hornung
36159a92d18SAlex Hornung }
36259a92d18SAlex Hornung
36359a92d18SAlex Hornung /*
36459a92d18SAlex Hornung * The following are extensions and not part of the X/Open spec.
36559a92d18SAlex Hornung */
366bdb02cd9SAlex Hornung void
updwtmpx(const char * file,const struct utmpx * utx)36759a92d18SAlex Hornung updwtmpx(const char *file, const struct utmpx *utx)
36859a92d18SAlex Hornung {
369bdb02cd9SAlex Hornung (void)_updwtmpx(file, utx);
370bdb02cd9SAlex Hornung }
371bdb02cd9SAlex Hornung
372bdb02cd9SAlex Hornung int
_updwtmpx(const char * file,const struct utmpx * utx)373bdb02cd9SAlex Hornung _updwtmpx(const char *file, const struct utmpx *utx)
374bdb02cd9SAlex Hornung {
37559a92d18SAlex Hornung int fd;
37659a92d18SAlex Hornung int saved_errno;
37721391921SSascha Wildner struct stat st;
37859a92d18SAlex Hornung
37959a92d18SAlex Hornung _DIAGASSERT(file != NULL);
38059a92d18SAlex Hornung _DIAGASSERT(utx != NULL);
38159a92d18SAlex Hornung
382*625fc06fSSascha Wildner fd = _open(file, O_WRONLY|O_APPEND|O_SHLOCK|O_CLOEXEC);
38359a92d18SAlex Hornung
38459a92d18SAlex Hornung if (fd == -1) {
385*625fc06fSSascha Wildner if ((fd = _open(file, O_CREAT|O_WRONLY|O_EXLOCK|O_CLOEXEC, 0644)) == -1)
38621391921SSascha Wildner goto fail;
38721391921SSascha Wildner }
388*625fc06fSSascha Wildner if (_fstat(fd, &st) == -1)
38921391921SSascha Wildner goto failclose;
39021391921SSascha Wildner if (st.st_size == 0) {
39121391921SSascha Wildner /* new file, add signature record */
39259a92d18SAlex Hornung (void)memset(&ut, 0, sizeof(ut));
39359a92d18SAlex Hornung ut.ut_type = SIGNATURE;
39459a92d18SAlex Hornung (void)memcpy(ut.ut_user, vers, sizeof(vers));
395*625fc06fSSascha Wildner if (_write(fd, &ut, sizeof(ut)) == -1)
39621391921SSascha Wildner goto failclose;
39759a92d18SAlex Hornung }
398*625fc06fSSascha Wildner if (_write(fd, utx, sizeof(*utx)) == -1)
39921391921SSascha Wildner goto failclose;
400806a5ed7SSascha Wildner if (_close(fd) == -1)
40159a92d18SAlex Hornung return -1;
40259a92d18SAlex Hornung return 0;
40359a92d18SAlex Hornung
40421391921SSascha Wildner failclose:
40559a92d18SAlex Hornung saved_errno = errno;
406806a5ed7SSascha Wildner (void) _close(fd);
40759a92d18SAlex Hornung errno = saved_errno;
40821391921SSascha Wildner fail:
40959a92d18SAlex Hornung return -1;
41059a92d18SAlex Hornung }
41159a92d18SAlex Hornung
41259a92d18SAlex Hornung int
utmpxname(const char * fname)41359a92d18SAlex Hornung utmpxname(const char *fname)
41459a92d18SAlex Hornung {
41559a92d18SAlex Hornung size_t len;
41659a92d18SAlex Hornung
41759a92d18SAlex Hornung _DIAGASSERT(fname != NULL);
41859a92d18SAlex Hornung
41959a92d18SAlex Hornung len = strlen(fname);
42059a92d18SAlex Hornung
42159a92d18SAlex Hornung if (len >= sizeof(utfile))
42259a92d18SAlex Hornung return 0;
42359a92d18SAlex Hornung
42459a92d18SAlex Hornung /* must end in x! */
42559a92d18SAlex Hornung if (fname[len - 1] != 'x')
42659a92d18SAlex Hornung return 0;
42759a92d18SAlex Hornung
42859a92d18SAlex Hornung (void)strlcpy(utfile, fname, sizeof(utfile));
42959a92d18SAlex Hornung endutxent();
43059a92d18SAlex Hornung return 1;
43159a92d18SAlex Hornung }
43259a92d18SAlex Hornung
433e2e9821dSSascha Wildner
434e2e9821dSSascha Wildner __sym_compat(getutmp, past_getutmp, DF404.0);
43559a92d18SAlex Hornung void
past_getutmp(void * ux __unused,void * u __unused)436bdbb2472SSascha Wildner past_getutmp(void *ux __unused, void *u __unused)
43759a92d18SAlex Hornung {
43859a92d18SAlex Hornung }
43959a92d18SAlex Hornung
440e2e9821dSSascha Wildner __sym_compat(getutmpx, past_getutmpx, DF404.0);
44159a92d18SAlex Hornung void
past_getutmpx(void * u __unused,void * ux __unused)442bdbb2472SSascha Wildner past_getutmpx(void *u __unused, void *ux __unused)
44359a92d18SAlex Hornung {
44459a92d18SAlex Hornung }
44559a92d18SAlex Hornung
44659a92d18SAlex Hornung struct lastlogx *
getlastlogx(const char * fname,uid_t uid,struct lastlogx * ll)44759a92d18SAlex Hornung getlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
44859a92d18SAlex Hornung {
44959a92d18SAlex Hornung DBT key, data;
45059a92d18SAlex Hornung DB *db;
45159a92d18SAlex Hornung
45259a92d18SAlex Hornung _DIAGASSERT(fname != NULL);
45359a92d18SAlex Hornung _DIAGASSERT(ll != NULL);
45459a92d18SAlex Hornung
45565f10536SSascha Wildner db = dbopen(fname, O_RDONLY|O_SHLOCK|O_CLOEXEC, 0, DB_HASH, NULL);
45659a92d18SAlex Hornung
45759a92d18SAlex Hornung if (db == NULL)
45859a92d18SAlex Hornung return NULL;
45959a92d18SAlex Hornung
46059a92d18SAlex Hornung key.data = &uid;
46159a92d18SAlex Hornung key.size = sizeof(uid);
46259a92d18SAlex Hornung
46359a92d18SAlex Hornung if ((db->get)(db, &key, &data, 0) != 0)
46459a92d18SAlex Hornung goto error;
46559a92d18SAlex Hornung
46659a92d18SAlex Hornung if (data.size != sizeof(*ll)) {
46759a92d18SAlex Hornung errno = EFTYPE;
46859a92d18SAlex Hornung goto error;
46959a92d18SAlex Hornung }
47059a92d18SAlex Hornung
47159a92d18SAlex Hornung if (ll == NULL)
47259a92d18SAlex Hornung if ((ll = malloc(sizeof(*ll))) == NULL)
47359a92d18SAlex Hornung goto done;
47459a92d18SAlex Hornung
47559a92d18SAlex Hornung (void)memcpy(ll, data.data, sizeof(*ll));
47659a92d18SAlex Hornung goto done;
47759a92d18SAlex Hornung error:
47859a92d18SAlex Hornung ll = NULL;
47959a92d18SAlex Hornung done:
48059a92d18SAlex Hornung (db->close)(db);
48159a92d18SAlex Hornung return ll;
48259a92d18SAlex Hornung }
48359a92d18SAlex Hornung
48459a92d18SAlex Hornung int
updlastlogx(const char * fname,uid_t uid,struct lastlogx * ll)48559a92d18SAlex Hornung updlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
48659a92d18SAlex Hornung {
48759a92d18SAlex Hornung DBT key, data;
48859a92d18SAlex Hornung int error = 0;
48959a92d18SAlex Hornung DB *db;
49059a92d18SAlex Hornung
49159a92d18SAlex Hornung _DIAGASSERT(fname != NULL);
49259a92d18SAlex Hornung _DIAGASSERT(ll != NULL);
49359a92d18SAlex Hornung
49465f10536SSascha Wildner db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK|O_CLOEXEC, 0644, DB_HASH, NULL);
49559a92d18SAlex Hornung
49659a92d18SAlex Hornung if (db == NULL)
49759a92d18SAlex Hornung return -1;
49859a92d18SAlex Hornung
49959a92d18SAlex Hornung key.data = &uid;
50059a92d18SAlex Hornung key.size = sizeof(uid);
50159a92d18SAlex Hornung data.data = ll;
50259a92d18SAlex Hornung data.size = sizeof(*ll);
50359a92d18SAlex Hornung if ((db->put)(db, &key, &data, 0) != 0)
50459a92d18SAlex Hornung error = -1;
50559a92d18SAlex Hornung
50659a92d18SAlex Hornung (db->close)(db);
50759a92d18SAlex Hornung return error;
50859a92d18SAlex Hornung }
509