1 --- utmpx.c.orig 2010-06-24 19:43:32.000000000 -0700
2 +++ utmpx.c 2010-06-29 11:25:57.000000000 -0700
3 @@ -42,111 +42,240 @@ __RCSID("$NetBSD: utmpx.c,v 1.25 2008/04
15 +#ifdef UNIFDEF_LEGACY_UTMP_APIS
17 +#endif /* UNIFDEF_LEGACY_UTMP_APIS */
19 +#include <utmpx-darwin.h>
25 -static int readonly = 0;
26 -static struct utmpx ut;
27 -static char utfile[MAXPATHLEN] = _PATH_UTMPX;
28 +/* This is the default struct _utmpx shared by the POSIX APIs */
30 +struct _utmpx __utx__ = {
31 + __UTX_MAGIC__, /* magic */
33 + PTHREAD_MUTEX_INITIALIZER, /* utmpx_mutex */
34 + _PATH_UTMPX, /* utfile */
36 + 1, /* utfile_system */
40 +static struct utmpx *__getutxid(struct _utmpx *, const struct utmpx *);
42 -static struct utmpx *utmp_update(const struct utmpx *);
43 +__private_extern__ const char _utmpx_vers[] = "utmpx-1.00";
45 -static const char vers[] = "utmpx-1.00";
46 +__private_extern__ void
47 +__setutxent(struct _utmpx *U)
50 + (void)memset(&U->ut, 0, sizeof(U->ut));
54 + (void)fseeko(U->fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
56 + (void)fseeko(U->fp, (off_t)sizeof(U->ut), SEEK_SET);
57 +#endif /* __LP64__ */
62 +_setutxent(struct _utmpx *U)
65 - (void)memset(&ut, 0, sizeof(ut));
68 - (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
69 + TEST_UTMPX_T("_setutxent", U);
80 + _setutxent(&__utx__);
84 - (void)memset(&ut, 0, sizeof(ut));
89 +__private_extern__ void
90 +__endutxent(struct _utmpx *U)
92 + (void)memset(&U->ut, 0, sizeof(U->ut));
93 + if (U->fp != NULL) {
94 + int saveerrno = errno;
95 + (void)fclose(U->fp);
106 +_endutxent(struct _utmpx *U)
108 + TEST_UTMPX_T("_endutxent", U);
119 + _endutxent(&__utx__);
123 +__private_extern__ struct utmpx *
124 +__getutxent(struct _utmpx *U)
128 + struct utmpx32 ut32;
129 +#endif /* __LP64__ */
131 + if (U->fp == NULL) {
134 - if ((fp = fopen(utfile, "r+")) == NULL)
135 - if ((fp = fopen(utfile, "w+")) == NULL) {
136 - if ((fp = fopen(utfile, "r")) == NULL)
137 + if ((U->fp = fopen(U->utfile, "r+")) == NULL)
138 + if ((U->fp = fopen(U->utfile, "w+")) == NULL) {
139 + if ((U->fp = fopen(U->utfile, "r")) == NULL)
147 + fcntl(fileno(U->fp), F_SETFD, 1); /* set close-on-exec flag */
149 /* get file size in order to check if new file */
150 - if (fstat(fileno(fp), &st) == -1)
151 + if (fstat(fileno(U->fp), &st) == -1)
154 if (st.st_size == 0) {
155 /* new file, add signature record */
156 - (void)memset(&ut, 0, sizeof(ut));
157 - ut.ut_type = SIGNATURE;
158 - (void)memcpy(ut.ut_user, vers, sizeof(vers));
159 - if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
161 + (void)memset(&ut32, 0, sizeof(ut32));
162 + ut32.ut_type = SIGNATURE;
163 + (void)memcpy(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
164 + if (fwrite(&ut32, sizeof(ut32), 1, U->fp) != 1)
165 +#else /* __LP64__ */
166 + (void)memset(&U->ut, 0, sizeof(U->ut));
167 + U->ut.ut_type = SIGNATURE;
168 + (void)memcpy(U->ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
169 + if (fwrite(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
170 +#endif /* __LP64__ */
173 /* old file, read signature record */
174 - if (fread(&ut, sizeof(ut), 1, fp) != 1)
176 + if (fread(&ut32, sizeof(ut32), 1, U->fp) != 1)
177 +#else /* __LP64__ */
178 + if (fread(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
179 +#endif /* __LP64__ */
181 - if (memcmp(ut.ut_user, vers, sizeof(vers)) != 0 ||
182 - ut.ut_type != SIGNATURE)
184 + if (memcmp(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
185 + ut32.ut_type != SIGNATURE)
186 +#else /* __LP64__ */
187 + if (memcmp(U->ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
188 + U->ut.ut_type != SIGNATURE)
189 +#endif /* __LP64__ */
197 - if (fread(&ut, sizeof(ut), 1, fp) != 1)
199 + if (fread(&ut32, sizeof(ut32), 1, U->fp) != 1)
200 +#else /* __LP64__ */
201 + if (fread(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
202 +#endif /* __LP64__ */
207 + _utmpx32_64(&ut32, &U->ut);
208 +#endif /* __LP64__ */
213 + (void)fclose(U->fp);
217 - (void)memset(&ut, 0, sizeof(ut));
218 + (void)memset(&U->ut, 0, sizeof(U->ut));
224 -getutxid(const struct utmpx *utx)
225 +_getutxent(struct _utmpx *U)
229 + TEST_UTMPX_T("_getutxent", U);
231 + ret = __getutxent(U);
240 + return _getutxent(&__utx__);
243 - _DIAGASSERT(utx != NULL);
246 +_getutxid(struct _utmpx *U, const struct utmpx *utx)
249 + const struct utmpx *ux;
252 if (utx->ut_type == EMPTY)
255 + TEST_UTMPX_T("_getutxid", U);
257 + /* make a copy as needed, and auto-fill if requested */
258 + ux = _utmpx_working_copy(utx, &temp, 1);
264 + ret = __getutxid(U, ux);
271 +getutxid(const struct utmpx *utx)
273 + return _getutxid(&__utx__, utx);
277 +static struct utmpx *
278 +__getutxid(struct _utmpx *U, const struct utmpx *utx)
282 - if (ut.ut_type == EMPTY)
283 + if (U->ut.ut_type == EMPTY)
285 switch (utx->ut_type) {
287 @@ -155,21 +284,21 @@ getutxid(const struct utmpx *utx)
291 - if (ut.ut_type == utx->ut_type)
293 + if (U->ut.ut_type == utx->ut_type)
300 - switch (ut.ut_type) {
301 + switch (U->ut.ut_type) {
306 - if (memcmp(ut.ut_id, utx->ut_id,
307 - sizeof(ut.ut_id)) == 0)
309 + if (memcmp(U->ut.ut_id, utx->ut_id,
310 + sizeof(U->ut.ut_id)) == 0)
315 @@ -178,188 +307,253 @@ getutxid(const struct utmpx *utx)
319 - } while (getutxent() != NULL);
320 + } while (__getutxent(U) != NULL);
326 -getutxline(const struct utmpx *utx)
327 +static struct utmpx *
328 +__getutxline(struct _utmpx *U, const struct utmpx *utx)
331 - _DIAGASSERT(utx != NULL);
334 - switch (ut.ut_type) {
335 + switch (U->ut.ut_type) {
340 - if (strncmp(ut.ut_line, utx->ut_line,
341 - sizeof(ut.ut_line)) == 0)
343 + if (strncmp(U->ut.ut_line, utx->ut_line,
344 + sizeof(U->ut.ut_line)) == 0)
350 - } while (getutxent() != NULL);
351 + } while (__getutxent(U) != NULL);
357 -pututxline(const struct utmpx *utx)
358 +_getutxline(struct _utmpx *U, const struct utmpx *utx)
362 + TEST_UTMPX_T("_getutxline", U);
364 + ret = __getutxline(U, utx);
371 +getutxline(const struct utmpx *utx)
373 - struct utmpx temp, *u = NULL;
375 + return _getutxline(&__utx__, utx);
378 - _DIAGASSERT(utx != NULL);
382 +_pututxline(struct _utmpx *U, const struct utmpx *utx)
391 - if (strcmp(_PATH_UTMPX, utfile) == 0)
392 - if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0))
393 - return utmp_update(utx);
394 + TEST_UTMPX_T("_pututxline", U);
396 + if ((ux = __pututxline(&__utx__, utx)) != NULL && __utx__.utfile_system) {
397 + _utmpx_asl(ux); /* the equivalent of wtmpx and lastlogx */
399 + _write_utmp_compat(ux);
400 +#endif /* UTMP_COMPAT */
407 - (void)memcpy(&temp, utx, sizeof(temp));
409 +pututxline(const struct utmpx *utx)
411 + return _pututxline(&__utx__, utx);
414 +__private_extern__ struct utmpx *
415 +__pututxline(struct _utmpx *U, const struct utmpx *utx)
417 + struct utmpx temp, *u = NULL, *x;
418 + const struct utmpx *ux;
420 + struct utmpx32 ut32;
421 +#endif /* __LP64__ */
423 +#define gotlock (fl.l_start >= 0)
425 + fl.l_start = -1; /* also means we haven't locked */
426 + if (U->utfile_system)
427 + if ((U->fp != NULL && U->readonly) || (U->fp == NULL && geteuid() != 0)) {
434 - if (fp == NULL || readonly)
435 + if (U->fp == NULL) {
436 + (void)__getutxent(U);
437 + if (U->fp == NULL || U->readonly) {
443 - if (getutxid(&temp) == NULL) {
445 - if (getutxid(&temp) == NULL) {
446 - if (lockf(fileno(fp), F_LOCK, (off_t)0) == -1)
447 + /* make a copy as needed, and auto-fill if requested */
448 + ux = _utmpx_working_copy(utx, &temp, 0);
452 + if ((x = __getutxid(U, ux)) == NULL) {
454 + if ((x = __getutxid(U, ux)) == NULL) {
456 + * utx->ut_type has any original mask bits, while
457 + * ux->ut_type has those mask bits removed. If we
458 + * are trying to record a dead process, and
459 + * UTMPX_DEAD_IF_CORRESPONDING_MASK is set, then since
460 + * there is no matching entry, we return NULL.
462 + if (ux->ut_type == DEAD_PROCESS &&
463 + (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK)) {
467 - if (fseeko(fp, (off_t)0, SEEK_END) == -1)
470 + * Replace lockf() with fcntl() and a fixed start
471 + * value. We should already be at EOF.
473 + if ((fl.l_start = lseek(fileno(U->fp), 0, SEEK_CUR)) < 0)
476 + fl.l_whence = SEEK_SET;
477 + fl.l_type = F_WRLCK;
478 + if (fcntl(fileno(U->fp), F_SETLKW, &fl) == -1)
480 + if (fseeko(U->fp, (off_t)0, SEEK_END) == -1)
487 + * utx->ut_type has any original mask bits, while
488 + * ux->ut_type has those mask bits removed. If we
489 + * are trying to record a dead process, if
490 + * UTMPX_DEAD_IF_CORRESPONDING_MASK is set, but the found
491 + * entry is not a (matching) USER_PROCESS, then return NULL.
493 + if (ux->ut_type == DEAD_PROCESS &&
494 + (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK) &&
495 + x->ut_type != USER_PROCESS) {
499 /* we are not appending */
500 - if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
502 + if (fseeko(U->fp, -(off_t)sizeof(ut32), SEEK_CUR) == -1)
503 +#else /* __LP64__ */
504 + if (fseeko(U->fp, -(off_t)sizeof(U->ut), SEEK_CUR) == -1)
505 +#endif /* __LP64__ */
509 - if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
511 + _utmpx64_32(ux, &ut32);
512 + if (fwrite(&ut32, sizeof (ut32), 1, U->fp) != 1)
513 +#else /* __LP64__ */
514 + if (fwrite(ux, sizeof (*ux), 1, U->fp) != 1)
515 +#endif /* __LP64__ */
518 - if (fflush(fp) == -1)
519 + if (fflush(U->fp) == -1)
522 - u = memcpy(&ut, &temp, sizeof(ut));
523 + u = memcpy(&U->ut, ux, sizeof(U->ut));
524 + notify_post(UTMPX_CHANGE_NOTIFICATION);
527 - if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
529 + fl.l_type = F_UNLCK;
530 + if (fcntl(fileno(U->fp), F_SETLK, &fl) == -1)
538 -static struct utmpx *
539 -utmp_update(const struct utmpx *utx)
541 - char buf[sizeof(*utx) * 4 + 1];
545 - _DIAGASSERT(utx != NULL);
547 - (void)strvisx(buf, (const char *)(const void *)utx, sizeof(*utx),
549 - switch (pid = fork()) {
551 - (void)execl(_PATH_UTMP_UPDATE,
552 - strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
558 - if (waitpid(pid, &status, 0) == -1)
560 - if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
561 - return memcpy(&ut, utx, sizeof(ut));
568 * The following are extensions and not part of the X/Open spec.
571 -updwtmpx(const char *file, const struct utmpx *utx)
576 - _DIAGASSERT(file != NULL);
577 - _DIAGASSERT(utx != NULL);
579 - fd = open(file, O_WRONLY|O_APPEND|O_SHLOCK);
582 - if ((fd = open(file, O_CREAT|O_WRONLY|O_EXLOCK, 0644)) == -1)
584 - (void)memset(&ut, 0, sizeof(ut));
585 - ut.ut_type = SIGNATURE;
586 - (void)memcpy(ut.ut_user, vers, sizeof(vers));
587 - if (write(fd, &ut, sizeof(ut)) == -1)
590 - if (write(fd, utx, sizeof(*utx)) == -1)
592 - if (close(fd) == -1)
597 - saved_errno = errno;
599 - errno = saved_errno;
605 -utmpxname(const char *fname)
606 +__private_extern__ int
607 +__utmpxname(struct _utmpx *U, const char *fname)
611 - _DIAGASSERT(fname != NULL);
612 + if (fname == NULL) {
613 + if(!U->utfile_system)
615 + U->utfile = _PATH_UTMPX;
616 + U->utfile_system = 1;
623 - if (len >= sizeof(utfile))
624 + if (len >= MAXPATHLEN)
628 if (fname[len - 1] != 'x')
631 - (void)strlcpy(utfile, fname, sizeof(utfile));
633 + if (U->utfile_system)
635 + U->utfile_system = 0;
636 + if ((U->utfile = reallocf(U->utfile, len + 1)) == NULL)
639 + (void)strcpy(U->utfile, fname);
645 +_utmpxname(struct _utmpx *U, const char *fname)
649 + TEST_UTMPX_T("_utmpxname", U);
651 + ret = __utmpxname(U, fname);
657 +utmpxname(const char *fname)
659 + return _utmpxname(&__utx__, fname);
662 +#ifdef UNIFDEF_LEGACY_UTMP_APIS
664 getutmp(const struct utmpx *ux, struct utmp *u)
667 - _DIAGASSERT(ux != NULL);
668 - _DIAGASSERT(u != NULL);
670 - (void)memcpy(u->ut_name, ux->ut_name, sizeof(u->ut_name));
671 + bzero(u, sizeof(*u));
672 + (void)memcpy(u->ut_name, ux->ut_user, sizeof(u->ut_name));
673 (void)memcpy(u->ut_line, ux->ut_line, sizeof(u->ut_line));
674 (void)memcpy(u->ut_host, ux->ut_host, sizeof(u->ut_host));
675 u->ut_time = ux->ut_tv.tv_sec;
676 @@ -369,82 +563,16 @@ void
677 getutmpx(const struct utmp *u, struct utmpx *ux)
680 - _DIAGASSERT(ux != NULL);
681 - _DIAGASSERT(u != NULL);
683 - (void)memcpy(ux->ut_name, u->ut_name, sizeof(u->ut_name));
684 + bzero(ux, sizeof(*ux));
685 + (void)memcpy(ux->ut_user, u->ut_name, sizeof(u->ut_name));
686 + ux->ut_user[sizeof(u->ut_name)] = 0;
687 (void)memcpy(ux->ut_line, u->ut_line, sizeof(u->ut_line));
688 + ux->ut_line[sizeof(u->ut_line)] = 0;
689 (void)memcpy(ux->ut_host, u->ut_host, sizeof(u->ut_host));
690 + ux->ut_host[sizeof(u->ut_host)] = 0;
691 ux->ut_tv.tv_sec = u->ut_time;
692 ux->ut_tv.tv_usec = 0;
693 - (void)memset(&ux->ut_ss, 0, sizeof(ux->ut_ss));
695 + ux->ut_pid = getpid();
696 ux->ut_type = USER_PROCESS;
697 - ux->ut_session = 0;
698 - ux->ut_exit.e_termination = 0;
699 - ux->ut_exit.e_exit = 0;
703 -getlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
708 - _DIAGASSERT(fname != NULL);
709 - _DIAGASSERT(ll != NULL);
711 - db = dbopen(fname, O_RDONLY|O_SHLOCK, 0, DB_HASH, NULL);
717 - key.size = sizeof(uid);
719 - if ((db->get)(db, &key, &data, 0) != 0)
722 - if (data.size != sizeof(*ll)) {
728 - if ((ll = malloc(sizeof(*ll))) == NULL)
731 - (void)memcpy(ll, data.data, sizeof(*ll));
741 -updlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
747 - _DIAGASSERT(fname != NULL);
748 - _DIAGASSERT(ll != NULL);
750 - db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0644, DB_HASH, NULL);
756 - key.size = sizeof(uid);
758 - data.size = sizeof(*ll);
759 - if ((db->put)(db, &key, &data, 0) != 0)
765 +#endif /* UNIFDEF_LEGACY_UTMP_APIS */