1 --- utmpx.c.orig 2009-04-01 04:01:12.000000000 -0700
2 +++ utmpx.c 2009-04-01 04:09:50.000000000 -0700
3 @@ -49,48 +49,57 @@ __RCSID("$NetBSD: utmpx.c,v 1.21 2003/09
15 +#ifdef LEGACY_UTMP_APIS
17 -/* don't define earlier, has side effects in fcntl.h */
18 -#define __LIBC12_SOURCE__
19 +#endif /* LEGACY_UTMP_APIS */
21 +#include <utmpx-darwin.h>
25 -__warn_references(getlastlogx,
26 - "warning: reference to compatibility getlastlogx(); include <utmpx.h> for correct reference")
27 -__warn_references(lastlogxname,
28 - "warning: reference to deprecated lastlogxname()")
32 static int readonly = 0;
33 static struct utmpx ut;
34 static char utfile[MAXPATHLEN] = _PATH_UTMPX;
35 -static char llfile[MAXPATHLEN] = _PATH_LASTLOGX;
36 +__private_extern__ int utfile_system = 1; /* are we using _PATH_UTMPX? */
37 +__private_extern__ pthread_mutex_t utmpx_mutex = PTHREAD_MUTEX_INITIALIZER;
39 -static struct utmpx *utmp_update(const struct utmpx *);
40 +static struct utmpx *_getutxid(const struct utmpx *);
42 -static const char vers[] = "utmpx-1.00";
43 +__private_extern__ const char _utmpx_vers[] = "utmpx-1.00";
47 +__private_extern__ void
51 (void)memset(&ut, 0, sizeof(ut));
55 + (void)fseeko(fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
57 (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
58 +#endif /* __LP64__ */
72 +__private_extern__ void
76 (void)memset(&ut, 0, sizeof(ut));
77 @@ -102,9 +111,21 @@ endutxent()
92 +static struct utmpx *
96 + struct utmpx32 ut32;
97 +#endif /* __LP64__ */
101 @@ -116,7 +137,8 @@ getutxent()
107 + fcntl(fileno(fp), F_SETFD, 1); /* set close-on-exec flag */
109 /* get file size in order to check if new file */
110 if (fstat(fileno(fp), &st) == -1)
111 @@ -124,27 +146,51 @@ getutxent()
113 if (st.st_size == 0) {
114 /* new file, add signature record */
116 + (void)memset(&ut32, 0, sizeof(ut32));
117 + ut32.ut_type = SIGNATURE;
118 + (void)memcpy(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
119 + if (fwrite(&ut32, sizeof(ut32), 1, fp) != 1)
120 +#else /* __LP64__ */
121 (void)memset(&ut, 0, sizeof(ut));
122 ut.ut_type = SIGNATURE;
123 - (void)memcpy(ut.ut_user, vers, sizeof(vers));
124 + (void)memcpy(ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
125 if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
126 +#endif /* __LP64__ */
129 /* old file, read signature record */
131 + if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
132 +#else /* __LP64__ */
133 if (fread(&ut, sizeof(ut), 1, fp) != 1)
134 +#endif /* __LP64__ */
136 - if (memcmp(ut.ut_user, vers, sizeof(vers)) != 0 ||
138 + if (memcmp(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
139 + ut32.ut_type != SIGNATURE)
140 +#else /* __LP64__ */
141 + if (memcmp(ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
142 ut.ut_type != SIGNATURE)
143 +#endif /* __LP64__ */
149 + if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
150 +#else /* __LP64__ */
151 if (fread(&ut, sizeof(ut), 1, fp) != 1)
152 +#endif /* __LP64__ */
156 + _utmpx32_64(&ut32, &ut);
157 +#endif /* __LP64__ */
163 (void)memset(&ut, 0, sizeof(ut));
165 @@ -152,14 +198,45 @@ fail:
173 + ret = _getutxent();
179 getutxid(const struct utmpx *utx)
182 + const struct utmpx *ux;
185 _DIAGASSERT(utx != NULL);
187 if (utx->ut_type == EMPTY)
191 + /* make a copy as needed, and auto-fill if requested */
192 + ux = _utmpx_working_copy(utx, &temp, 1);
198 + ret = _getutxid(ux);
204 +static struct utmpx *
205 +_getutxid(const struct utmpx *utx)
209 if (ut.ut_type == EMPTY)
211 @@ -193,7 +270,7 @@ getutxid(const struct utmpx *utx)
215 - } while (getutxent() != NULL);
216 + } while (_getutxent() != NULL);
220 @@ -204,6 +281,7 @@ getutxline(const struct utmpx *utx)
222 _DIAGASSERT(utx != NULL);
226 switch (ut.ut_type) {
228 @@ -211,13 +289,16 @@ getutxline(const struct utmpx *utx)
231 if (strncmp(ut.ut_line, utx->ut_line,
232 - sizeof(ut.ut_line)) == 0)
233 + sizeof(ut.ut_line)) == 0) {
241 - } while (getutxent() != NULL);
242 + } while (_getutxent() != NULL);
247 @@ -225,156 +306,180 @@ getutxline(const struct utmpx *utx)
249 pututxline(const struct utmpx *utx)
251 - struct utmpx temp, *u = NULL;
255 _DIAGASSERT(utx != NULL);
263 - if (strcmp(_PATH_UTMPX, utfile) == 0)
264 - if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0))
265 - return utmp_update(utx);
268 + if ((ux = _pututxline(utx)) != NULL && utfile_system) {
269 + _utmpx_asl(ux); /* the equivalent of wtmpx and lastlogx */
271 + _write_utmp_compat(ux);
272 +#endif /* UTMP_COMPAT */
278 - (void)memcpy(&temp, utx, sizeof(temp));
279 +__private_extern__ struct utmpx *
280 +_pututxline(const struct utmpx *utx)
282 + struct utmpx temp, *u = NULL, *x;
283 + const struct utmpx *ux;
285 + struct utmpx32 ut32;
286 +#endif /* __LP64__ */
288 +#define gotlock (fl.l_start >= 0)
290 + fl.l_start = -1; /* also means we haven't locked */
292 + if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0)) {
299 - if (fp == NULL || readonly)
300 + (void)_getutxent();
301 + if (fp == NULL || readonly) {
307 - if (getutxid(&temp) == NULL) {
309 - if (getutxid(&temp) == NULL) {
310 - if (lockf(fileno(fp), F_LOCK, (off_t)0) == -1)
311 + /* make a copy as needed, and auto-fill if requested */
312 + ux = _utmpx_working_copy(utx, &temp, 0);
316 + if ((x = _getutxid(ux)) == NULL) {
318 + if ((x = _getutxid(ux)) == NULL) {
320 + * utx->ut_type has any original mask bits, while
321 + * ux->ut_type has those mask bits removed. If we
322 + * are trying to record a dead process, and
323 + * UTMPX_DEAD_IF_CORRESPONDING_MASK is set, then since
324 + * there is no matching entry, we return NULL.
326 + if (ux->ut_type == DEAD_PROCESS &&
327 + (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK)) {
332 + * Replace lockf() with fcntl() and a fixed start
333 + * value. We should already be at EOF.
335 + if ((fl.l_start = lseek(fileno(fp), 0, SEEK_CUR)) < 0)
338 + fl.l_whence = SEEK_SET;
339 + fl.l_type = F_WRLCK;
340 + if (fcntl(fileno(fp), F_SETLKW, &fl) == -1)
343 if (fseeko(fp, (off_t)0, SEEK_END) == -1)
350 + * utx->ut_type has any original mask bits, while
351 + * ux->ut_type has those mask bits removed. If we
352 + * are trying to record a dead process, if
353 + * UTMPX_DEAD_IF_CORRESPONDING_MASK is set, but the found
354 + * entry is not a (matching) USER_PROCESS, then return NULL.
356 + if (ux->ut_type == DEAD_PROCESS &&
357 + (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK) &&
358 + x->ut_type != USER_PROCESS) {
362 /* we are not appending */
364 + if (fseeko(fp, -(off_t)sizeof(ut32), SEEK_CUR) == -1)
365 +#else /* __LP64__ */
366 if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
367 +#endif /* __LP64__ */
371 - if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
373 + _utmpx64_32(ux, &ut32);
374 + if (fwrite(&ut32, sizeof (ut32), 1, fp) != 1)
375 +#else /* __LP64__ */
376 + if (fwrite(ux, sizeof (*ux), 1, fp) != 1)
377 +#endif /* __LP64__ */
380 if (fflush(fp) == -1)
383 - u = memcpy(&ut, &temp, sizeof(ut));
384 + u = memcpy(&ut, ux, sizeof(ut));
385 + notify_post(UTMPX_CHANGE_NOTIFICATION);
388 - if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
390 + fl.l_type = F_UNLCK;
391 + if (fcntl(fileno(fp), F_SETLK, &fl) == -1)
399 -static struct utmpx *
400 -utmp_update(const struct utmpx *utx)
402 - char buf[sizeof(*utx) * 4 + 1];
406 - _DIAGASSERT(utx != NULL);
408 - (void)strvisx(buf, (const char *)(const void *)utx, sizeof(*utx),
410 - switch (pid = fork()) {
412 - (void)execl(_PATH_UTMP_UPDATE,
413 - strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
419 - if (waitpid(pid, &status, 0) == -1)
421 - if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
422 - return memcpy(&ut, utx, sizeof(ut));
429 * The following are extensions and not part of the X/Open spec.
432 -updwtmpx(const char *file, const struct utmpx *utx)
437 - _DIAGASSERT(file != NULL);
438 - _DIAGASSERT(utx != NULL);
440 - fd = open(file, O_WRONLY|O_APPEND|O_SHLOCK);
443 - if ((fd = open(file, O_CREAT|O_WRONLY|O_EXLOCK, 0644)) == -1)
445 - (void)memset(&ut, 0, sizeof(ut));
446 - ut.ut_type = SIGNATURE;
447 - (void)memcpy(ut.ut_user, vers, sizeof(vers));
448 - if (write(fd, &ut, sizeof(ut)) == -1)
451 - if (write(fd, utx, sizeof(*utx)) == -1)
453 - if (close(fd) == -1)
458 - saved_errno = errno;
460 - errno = saved_errno;
466 utmpxname(const char *fname)
470 - _DIAGASSERT(fname != NULL);
472 + if (fname == NULL) {
473 + strcpy(utfile, _PATH_UTMPX);
482 - if (len >= sizeof(utfile))
483 + if (len >= sizeof(utfile)) {
489 - if (fname[len - 1] != 'x')
490 + if (fname[len - 1] != 'x') {
495 (void)strlcpy(utfile, fname, sizeof(utfile));
504 +#ifdef LEGACY_UTMP_APIS
506 getutmp(const struct utmpx *ux, struct utmp *u)
509 - _DIAGASSERT(ux != NULL);
510 - _DIAGASSERT(u != NULL);
512 - (void)memcpy(u->ut_name, ux->ut_name, sizeof(u->ut_name));
513 + bzero(u, sizeof(*u));
514 + (void)memcpy(u->ut_name, ux->ut_user, sizeof(u->ut_name));
515 (void)memcpy(u->ut_line, ux->ut_line, sizeof(u->ut_line));
516 (void)memcpy(u->ut_host, ux->ut_host, sizeof(u->ut_host));
517 u->ut_time = ux->ut_tv.tv_sec;
518 @@ -384,109 +489,16 @@ void
519 getutmpx(const struct utmp *u, struct utmpx *ux)
522 - _DIAGASSERT(ux != NULL);
523 - _DIAGASSERT(u != NULL);
525 - (void)memcpy(ux->ut_name, u->ut_name, sizeof(u->ut_name));
526 + bzero(ux, sizeof(*ux));
527 + (void)memcpy(ux->ut_user, u->ut_name, sizeof(u->ut_name));
528 + ux->ut_user[sizeof(u->ut_name)] = 0;
529 (void)memcpy(ux->ut_line, u->ut_line, sizeof(u->ut_line));
530 + ux->ut_line[sizeof(u->ut_line)] = 0;
531 (void)memcpy(ux->ut_host, u->ut_host, sizeof(u->ut_host));
532 + ux->ut_host[sizeof(u->ut_host)] = 0;
533 ux->ut_tv.tv_sec = u->ut_time;
534 ux->ut_tv.tv_usec = 0;
535 - (void)memset(&ux->ut_ss, 0, sizeof(ux->ut_ss));
537 + ux->ut_pid = getpid();
538 ux->ut_type = USER_PROCESS;
539 - ux->ut_session = 0;
540 - ux->ut_exit.e_termination = 0;
541 - ux->ut_exit.e_exit = 0;
545 -lastlogxname(const char *fname)
549 - _DIAGASSERT(fname != NULL);
551 - len = strlen(fname);
553 - if (len >= sizeof(llfile))
556 - /* must end in x! */
557 - if (fname[len - 1] != 'x')
560 - (void)strlcpy(llfile, fname, sizeof(llfile));
565 -getlastlogx(uid_t uid, struct lastlogx *ll)
568 - return __getlastlogx13(_PATH_LASTLOGX, uid, ll);
572 -__getlastlogx13(const char *fname, uid_t uid, struct lastlogx *ll)
577 - _DIAGASSERT(fname != NULL);
578 - _DIAGASSERT(ll != NULL);
580 - db = dbopen(fname, O_RDONLY|O_SHLOCK, 0, DB_HASH, NULL);
586 - key.size = sizeof(uid);
588 - if ((db->get)(db, &key, &data, 0) != 0)
591 - if (data.size != sizeof(*ll)) {
597 - if ((ll = malloc(sizeof(*ll))) == NULL)
600 - (void)memcpy(ll, data.data, sizeof(*ll));
610 -updlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
616 - _DIAGASSERT(fname != NULL);
617 - _DIAGASSERT(ll != NULL);
619 - db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0, DB_HASH, NULL);
625 - key.size = sizeof(uid);
627 - data.size = sizeof(*ll);
628 - if ((db->put)(db, &key, &data, 0) != 0)
634 +#endif /* LEGACY_UTMP_APIS */