]> git.saurik.com Git - apple/libc.git/blob - gen/NetBSD/utmpx.c.patch
Libc-594.1.4.tar.gz
[apple/libc.git] / gen / NetBSD / utmpx.c.patch
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
4 #include <sys/time.h>
5 #include <sys/wait.h>
6
7 -#include <assert.h>
8 -#include <db.h>
9 -#include <errno.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 +#ifdef LEGACY_UTMP_APIS
16 #include <utmp.h>
17 -/* don't define earlier, has side effects in fcntl.h */
18 -#define __LIBC12_SOURCE__
19 +#endif /* LEGACY_UTMP_APIS */
20 #include <utmpx.h>
21 +#include <utmpx-darwin.h>
22 +#include <errno.h>
23 #include <vis.h>
24 -
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()")
29 +#include <notify.h>
30
31 static FILE *fp;
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;
38
39 -static struct utmpx *utmp_update(const struct utmpx *);
40 +static struct utmpx *_getutxid(const struct utmpx *);
41
42 -static const char vers[] = "utmpx-1.00";
43 +__private_extern__ const char _utmpx_vers[] = "utmpx-1.00";
44
45 -void
46 -setutxent()
47 +__private_extern__ void
48 +_setutxent()
49 {
50
51 (void)memset(&ut, 0, sizeof(ut));
52 if (fp == NULL)
53 return;
54 +#ifdef __LP64__
55 + (void)fseeko(fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
56 +#else /* __LP64__ */
57 (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
58 +#endif /* __LP64__ */
59 }
60
61
62 void
63 -endutxent()
64 +setutxent()
65 +{
66 + UTMPX_LOCK;
67 + _setutxent();
68 + UTMPX_UNLOCK;
69 +}
70 +
71 +
72 +__private_extern__ void
73 +_endutxent()
74 {
75
76 (void)memset(&ut, 0, sizeof(ut));
77 @@ -102,9 +111,21 @@ endutxent()
78 }
79
80
81 -struct utmpx *
82 -getutxent()
83 +void
84 +endutxent()
85 {
86 + UTMPX_LOCK;
87 + _endutxent();
88 + UTMPX_UNLOCK;
89 +}
90 +
91 +
92 +static struct utmpx *
93 +_getutxent()
94 +{
95 +#ifdef __LP64__
96 + struct utmpx32 ut32;
97 +#endif /* __LP64__ */
98
99 if (fp == NULL) {
100 struct stat st;
101 @@ -116,7 +137,8 @@ getutxent()
102 else
103 readonly = 1;
104 }
105 -
106 +
107 + fcntl(fileno(fp), F_SETFD, 1); /* set close-on-exec flag */
108
109 /* get file size in order to check if new file */
110 if (fstat(fileno(fp), &st) == -1)
111 @@ -124,27 +146,51 @@ getutxent()
112
113 if (st.st_size == 0) {
114 /* new file, add signature record */
115 +#ifdef __LP64__
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__ */
127 goto failclose;
128 } else {
129 /* old file, read signature record */
130 +#ifdef __LP64__
131 + if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
132 +#else /* __LP64__ */
133 if (fread(&ut, sizeof(ut), 1, fp) != 1)
134 +#endif /* __LP64__ */
135 goto failclose;
136 - if (memcmp(ut.ut_user, vers, sizeof(vers)) != 0 ||
137 +#ifdef __LP64__
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__ */
144 goto failclose;
145 }
146 }
147
148 +#ifdef __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__ */
153 goto fail;
154
155 +#ifdef __LP64__
156 + _utmpx32_64(&ut32, &ut);
157 +#endif /* __LP64__ */
158 return &ut;
159 failclose:
160 (void)fclose(fp);
161 + fp = NULL;
162 fail:
163 (void)memset(&ut, 0, sizeof(ut));
164 return NULL;
165 @@ -152,14 +198,45 @@ fail:
166
167
168 struct utmpx *
169 +getutxent()
170 +{
171 + struct utmpx *ret;
172 + UTMPX_LOCK;
173 + ret = _getutxent();
174 + UTMPX_UNLOCK;
175 + return ret;
176 +}
177 +
178 +struct utmpx *
179 getutxid(const struct utmpx *utx)
180 {
181 + struct utmpx temp;
182 + const struct utmpx *ux;
183 + struct utmpx *ret;
184
185 _DIAGASSERT(utx != NULL);
186
187 if (utx->ut_type == EMPTY)
188 return NULL;
189
190 + UTMPX_LOCK;
191 + /* make a copy as needed, and auto-fill if requested */
192 + ux = _utmpx_working_copy(utx, &temp, 1);
193 + if (!ux) {
194 + UTMPX_UNLOCK;
195 + return NULL;
196 + }
197 +
198 + ret = _getutxid(ux);
199 + UTMPX_UNLOCK;
200 + return ret;
201 +}
202 +
203 +
204 +static struct utmpx *
205 +_getutxid(const struct utmpx *utx)
206 +{
207 +
208 do {
209 if (ut.ut_type == EMPTY)
210 continue;
211 @@ -193,7 +270,7 @@ getutxid(const struct utmpx *utx)
212 default:
213 return NULL;
214 }
215 - } while (getutxent() != NULL);
216 + } while (_getutxent() != NULL);
217 return NULL;
218 }
219
220 @@ -204,6 +281,7 @@ getutxline(const struct utmpx *utx)
221
222 _DIAGASSERT(utx != NULL);
223
224 + UTMPX_LOCK;
225 do {
226 switch (ut.ut_type) {
227 case EMPTY:
228 @@ -211,13 +289,16 @@ getutxline(const struct utmpx *utx)
229 case LOGIN_PROCESS:
230 case USER_PROCESS:
231 if (strncmp(ut.ut_line, utx->ut_line,
232 - sizeof(ut.ut_line)) == 0)
233 + sizeof(ut.ut_line)) == 0) {
234 + UTMPX_UNLOCK;
235 return &ut;
236 + }
237 break;
238 default:
239 break;
240 }
241 - } while (getutxent() != NULL);
242 + } while (_getutxent() != NULL);
243 + UTMPX_UNLOCK;
244 return NULL;
245 }
246
247 @@ -225,156 +306,180 @@ getutxline(const struct utmpx *utx)
248 struct utmpx *
249 pututxline(const struct utmpx *utx)
250 {
251 - struct utmpx temp, *u = NULL;
252 - int gotlock = 0;
253 + struct utmpx *ux;
254
255 _DIAGASSERT(utx != NULL);
256
257 - if (utx == NULL)
258 + if (utx == NULL) {
259 + errno = EINVAL;
260 return NULL;
261 + }
262
263 - if (strcmp(_PATH_UTMPX, utfile) == 0)
264 - if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0))
265 - return utmp_update(utx);
266 -
267 + UTMPX_LOCK;
268 + if ((ux = _pututxline(utx)) != NULL && utfile_system) {
269 + _utmpx_asl(ux); /* the equivalent of wtmpx and lastlogx */
270 +#ifdef UTMP_COMPAT
271 + _write_utmp_compat(ux);
272 +#endif /* UTMP_COMPAT */
273 + }
274 + UTMPX_UNLOCK;
275 + return ux;
276 +}
277
278 - (void)memcpy(&temp, utx, sizeof(temp));
279 +__private_extern__ struct utmpx *
280 +_pututxline(const struct utmpx *utx)
281 +{
282 + struct utmpx temp, *u = NULL, *x;
283 + const struct utmpx *ux;
284 +#ifdef __LP64__
285 + struct utmpx32 ut32;
286 +#endif /* __LP64__ */
287 + struct flock fl;
288 +#define gotlock (fl.l_start >= 0)
289 +
290 + fl.l_start = -1; /* also means we haven't locked */
291 + if (utfile_system)
292 + if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0)) {
293 + errno = EPERM;
294 + return NULL;
295 + }
296
297 if (fp == NULL) {
298 - (void)getutxent();
299 - if (fp == NULL || readonly)
300 + (void)_getutxent();
301 + if (fp == NULL || readonly) {
302 + errno = EPERM;
303 return NULL;
304 + }
305 }
306
307 - if (getutxid(&temp) == NULL) {
308 - setutxent();
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);
313 + if (!ux)
314 + return NULL;
315 +
316 + if ((x = _getutxid(ux)) == NULL) {
317 + _setutxent();
318 + if ((x = _getutxid(ux)) == NULL) {
319 + /*
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.
325 + */
326 + if (ux->ut_type == DEAD_PROCESS &&
327 + (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK)) {
328 + errno = EINVAL;
329 + return NULL;
330 + }
331 + /*
332 + * Replace lockf() with fcntl() and a fixed start
333 + * value. We should already be at EOF.
334 + */
335 + if ((fl.l_start = lseek(fileno(fp), 0, SEEK_CUR)) < 0)
336 + return NULL;
337 + fl.l_len = 0;
338 + fl.l_whence = SEEK_SET;
339 + fl.l_type = F_WRLCK;
340 + if (fcntl(fileno(fp), F_SETLKW, &fl) == -1)
341 return NULL;
342 - gotlock++;
343 if (fseeko(fp, (off_t)0, SEEK_END) == -1)
344 goto fail;
345 }
346 }
347
348 if (!gotlock) {
349 + /*
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.
355 + */
356 + if (ux->ut_type == DEAD_PROCESS &&
357 + (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK) &&
358 + x->ut_type != USER_PROCESS) {
359 + errno = EINVAL;
360 + return NULL;
361 + }
362 /* we are not appending */
363 +#ifdef __LP64__
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__ */
368 return NULL;
369 }
370
371 - if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
372 +#ifdef __LP64__
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__ */
378 goto fail;
379
380 if (fflush(fp) == -1)
381 goto fail;
382
383 - u = memcpy(&ut, &temp, sizeof(ut));
384 + u = memcpy(&ut, ux, sizeof(ut));
385 + notify_post(UTMPX_CHANGE_NOTIFICATION);
386 fail:
387 if (gotlock) {
388 - if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
389 + int save = errno;
390 + fl.l_type = F_UNLCK;
391 + if (fcntl(fileno(fp), F_SETLK, &fl) == -1)
392 return NULL;
393 + errno = save;
394 }
395 return u;
396 }
397
398
399 -static struct utmpx *
400 -utmp_update(const struct utmpx *utx)
401 -{
402 - char buf[sizeof(*utx) * 4 + 1];
403 - pid_t pid;
404 - int status;
405 -
406 - _DIAGASSERT(utx != NULL);
407 -
408 - (void)strvisx(buf, (const char *)(const void *)utx, sizeof(*utx),
409 - VIS_WHITE);
410 - switch (pid = fork()) {
411 - case 0:
412 - (void)execl(_PATH_UTMP_UPDATE,
413 - strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
414 - exit(1);
415 - /*NOTREACHED*/
416 - case -1:
417 - return NULL;
418 - default:
419 - if (waitpid(pid, &status, 0) == -1)
420 - return NULL;
421 - if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
422 - return memcpy(&ut, utx, sizeof(ut));
423 - return NULL;
424 - }
425 -
426 -}
427 -
428 /*
429 * The following are extensions and not part of the X/Open spec.
430 */
431 int
432 -updwtmpx(const char *file, const struct utmpx *utx)
433 -{
434 - int fd;
435 - int saved_errno;
436 -
437 - _DIAGASSERT(file != NULL);
438 - _DIAGASSERT(utx != NULL);
439 -
440 - fd = open(file, O_WRONLY|O_APPEND|O_SHLOCK);
441 -
442 - if (fd == -1) {
443 - if ((fd = open(file, O_CREAT|O_WRONLY|O_EXLOCK, 0644)) == -1)
444 - return -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)
449 - goto failed;
450 - }
451 - if (write(fd, utx, sizeof(*utx)) == -1)
452 - goto failed;
453 - if (close(fd) == -1)
454 - return -1;
455 - return 0;
456 -
457 - failed:
458 - saved_errno = errno;
459 - (void) close(fd);
460 - errno = saved_errno;
461 - return -1;
462 -}
463 -
464 -
465 -int
466 utmpxname(const char *fname)
467 {
468 size_t len;
469
470 - _DIAGASSERT(fname != NULL);
471 + UTMPX_LOCK;
472 + if (fname == NULL) {
473 + strcpy(utfile, _PATH_UTMPX);
474 + utfile_system = 1;
475 + _endutxent();
476 + UTMPX_UNLOCK;
477 + return 1;
478 + }
479
480 len = strlen(fname);
481
482 - if (len >= sizeof(utfile))
483 + if (len >= sizeof(utfile)) {
484 + UTMPX_UNLOCK;
485 return 0;
486 + }
487
488 /* must end in x! */
489 - if (fname[len - 1] != 'x')
490 + if (fname[len - 1] != 'x') {
491 + UTMPX_UNLOCK;
492 return 0;
493 + }
494
495 (void)strlcpy(utfile, fname, sizeof(utfile));
496 - endutxent();
497 + _endutxent();
498 + utfile_system = 0;
499 + UTMPX_UNLOCK;
500 return 1;
501 }
502
503 -
504 +#ifdef LEGACY_UTMP_APIS
505 void
506 getutmp(const struct utmpx *ux, struct utmp *u)
507 {
508
509 - _DIAGASSERT(ux != NULL);
510 - _DIAGASSERT(u != NULL);
511 -
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)
520 {
521
522 - _DIAGASSERT(ux != NULL);
523 - _DIAGASSERT(u != NULL);
524 -
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));
536 - ux->ut_pid = 0;
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;
542 -}
543 -
544 -int
545 -lastlogxname(const char *fname)
546 -{
547 - size_t len;
548 -
549 - _DIAGASSERT(fname != NULL);
550 -
551 - len = strlen(fname);
552 -
553 - if (len >= sizeof(llfile))
554 - return 0;
555 -
556 - /* must end in x! */
557 - if (fname[len - 1] != 'x')
558 - return 0;
559 -
560 - (void)strlcpy(llfile, fname, sizeof(llfile));
561 - return 1;
562 -}
563 -
564 -struct lastlogx *
565 -getlastlogx(uid_t uid, struct lastlogx *ll)
566 -{
567 -
568 - return __getlastlogx13(_PATH_LASTLOGX, uid, ll);
569 -}
570 -
571 -struct lastlogx *
572 -__getlastlogx13(const char *fname, uid_t uid, struct lastlogx *ll)
573 -{
574 - DBT key, data;
575 - DB *db;
576 -
577 - _DIAGASSERT(fname != NULL);
578 - _DIAGASSERT(ll != NULL);
579 -
580 - db = dbopen(fname, O_RDONLY|O_SHLOCK, 0, DB_HASH, NULL);
581 -
582 - if (db == NULL)
583 - return NULL;
584 -
585 - key.data = &uid;
586 - key.size = sizeof(uid);
587 -
588 - if ((db->get)(db, &key, &data, 0) != 0)
589 - goto error;
590 -
591 - if (data.size != sizeof(*ll)) {
592 - errno = EFTYPE;
593 - goto error;
594 - }
595 -
596 - if (ll == NULL)
597 - if ((ll = malloc(sizeof(*ll))) == NULL)
598 - goto done;
599 -
600 - (void)memcpy(ll, data.data, sizeof(*ll));
601 - goto done;
602 -error:
603 - ll = NULL;
604 -done:
605 - (db->close)(db);
606 - return ll;
607 -}
608 -
609 -int
610 -updlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
611 -{
612 - DBT key, data;
613 - int error = 0;
614 - DB *db;
615 -
616 - _DIAGASSERT(fname != NULL);
617 - _DIAGASSERT(ll != NULL);
618 -
619 - db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0, DB_HASH, NULL);
620 -
621 - if (db == NULL)
622 - return -1;
623 -
624 - key.data = &uid;
625 - key.size = sizeof(uid);
626 - data.data = ll;
627 - data.size = sizeof(*ll);
628 - if ((db->put)(db, &key, &data, 0) != 0)
629 - error = -1;
630 -
631 - (db->close)(db);
632 - return error;
633 }
634 +#endif /* LEGACY_UTMP_APIS */