]> git.saurik.com Git - apple/libc.git/blob - gen/NetBSD/utmpx.c.patch
Libc-498.1.5.tar.gz
[apple/libc.git] / gen / NetBSD / utmpx.c.patch
1 --- utmpx.c.orig 2008-07-17 11:34:16.000000000 -0700
2 +++ utmpx.c 2008-07-17 12:05:58.000000000 -0700
3 @@ -49,34 +49,29 @@ __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
38 -static struct utmpx *utmp_update(const struct utmpx *);
39 +static struct utmpx *_getutxid(const struct utmpx *);
40
41 -static const char vers[] = "utmpx-1.00";
42 +__private_extern__ const char _utmpx_vers[] = "utmpx-1.00";
43
44 void
45 setutxent()
46 @@ -85,7 +80,11 @@ setutxent()
47 (void)memset(&ut, 0, sizeof(ut));
48 if (fp == NULL)
49 return;
50 +#ifdef __LP64__
51 + (void)fseeko(fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
52 +#else /* __LP64__ */
53 (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
54 +#endif /* __LP64__ */
55 }
56
57
58 @@ -105,6 +104,9 @@ endutxent()
59 struct utmpx *
60 getutxent()
61 {
62 +#ifdef __LP64__
63 + struct utmpx32 ut32;
64 +#endif /* __LP64__ */
65
66 if (fp == NULL) {
67 struct stat st;
68 @@ -124,42 +126,80 @@ getutxent()
69
70 if (st.st_size == 0) {
71 /* new file, add signature record */
72 +#ifdef __LP64__
73 + (void)memset(&ut32, 0, sizeof(ut32));
74 + ut32.ut_type = SIGNATURE;
75 + (void)memcpy(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
76 + if (fwrite(&ut32, sizeof(ut32), 1, fp) != 1)
77 +#else /* __LP64__ */
78 (void)memset(&ut, 0, sizeof(ut));
79 ut.ut_type = SIGNATURE;
80 - (void)memcpy(ut.ut_user, vers, sizeof(vers));
81 + (void)memcpy(ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
82 if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
83 +#endif /* __LP64__ */
84 goto failclose;
85 } else {
86 /* old file, read signature record */
87 +#ifdef __LP64__
88 + if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
89 +#else /* __LP64__ */
90 if (fread(&ut, sizeof(ut), 1, fp) != 1)
91 +#endif /* __LP64__ */
92 goto failclose;
93 - if (memcmp(ut.ut_user, vers, sizeof(vers)) != 0 ||
94 +#ifdef __LP64__
95 + if (memcmp(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
96 + ut32.ut_type != SIGNATURE)
97 +#else /* __LP64__ */
98 + if (memcmp(ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
99 ut.ut_type != SIGNATURE)
100 +#endif /* __LP64__ */
101 goto failclose;
102 }
103 }
104
105 +#ifdef __LP64__
106 + if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
107 +#else /* __LP64__ */
108 if (fread(&ut, sizeof(ut), 1, fp) != 1)
109 +#endif /* __LP64__ */
110 goto fail;
111
112 +#ifdef __LP64__
113 + _utmpx32_64(&ut32, &ut);
114 +#endif /* __LP64__ */
115 return &ut;
116 failclose:
117 (void)fclose(fp);
118 + fp = NULL;
119 fail:
120 (void)memset(&ut, 0, sizeof(ut));
121 return NULL;
122 }
123
124 -
125 struct utmpx *
126 getutxid(const struct utmpx *utx)
127 {
128 + struct utmpx temp;
129 + const struct utmpx *ux;
130
131 _DIAGASSERT(utx != NULL);
132
133 if (utx->ut_type == EMPTY)
134 return NULL;
135
136 + /* make a copy as needed, and auto-fill if requested */
137 + ux = _utmpx_working_copy(utx, &temp, 1);
138 + if (!ux)
139 + return NULL;
140 +
141 + return _getutxid(ux);
142 +}
143 +
144 +
145 +static struct utmpx *
146 +_getutxid(const struct utmpx *utx)
147 +{
148 +
149 do {
150 if (ut.ut_type == EMPTY)
151 continue;
152 @@ -225,30 +265,68 @@ getutxline(const struct utmpx *utx)
153 struct utmpx *
154 pututxline(const struct utmpx *utx)
155 {
156 - struct utmpx temp, *u = NULL;
157 - int gotlock = 0;
158 + struct utmpx *ux;
159
160 _DIAGASSERT(utx != NULL);
161
162 - if (utx == NULL)
163 + if (utx == NULL) {
164 + errno = EINVAL;
165 return NULL;
166 + }
167
168 - if (strcmp(_PATH_UTMPX, utfile) == 0)
169 - if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0))
170 - return utmp_update(utx);
171 + if ((ux = _pututxline(utx)) != NULL && utfile_system) {
172 + _utmpx_asl(ux); /* the equivalent of wtmpx and lastlogx */
173 +#ifdef UTMP_COMPAT
174 + _write_utmp_compat(ux);
175 +#endif /* UTMP_COMPAT */
176 + }
177 + return ux;
178 +}
179
180 +__private_extern__ struct utmpx *
181 +_pututxline(const struct utmpx *utx)
182 +{
183 + struct utmpx temp, *u = NULL, *x;
184 + const struct utmpx *ux;
185 +#ifdef __LP64__
186 + struct utmpx32 ut32;
187 +#endif /* __LP64__ */
188 + int gotlock = 0;
189
190 - (void)memcpy(&temp, utx, sizeof(temp));
191 + if (utfile_system)
192 + if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0)) {
193 + errno = EPERM;
194 + return NULL;
195 + }
196
197 if (fp == NULL) {
198 (void)getutxent();
199 - if (fp == NULL || readonly)
200 + if (fp == NULL || readonly) {
201 + errno = EPERM;
202 return NULL;
203 + }
204 }
205
206 - if (getutxid(&temp) == NULL) {
207 + /* make a copy as needed, and auto-fill if requested */
208 + ux = _utmpx_working_copy(utx, &temp, 0);
209 + if (!ux)
210 + return NULL;
211 +
212 + if ((x = _getutxid(ux)) == NULL) {
213 setutxent();
214 - if (getutxid(&temp) == NULL) {
215 + if ((x = _getutxid(ux)) == NULL) {
216 + /*
217 + * utx->ut_type has any original mask bits, while
218 + * ux->ut_type has those mask bits removed. If we
219 + * are trying to record a dead process, and
220 + * UTMPX_DEAD_IF_CORRESPONDING_MASK is set, then since
221 + * there is no matching entry, we return NULL.
222 + */
223 + if (ux->ut_type == DEAD_PROCESS &&
224 + (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK)) {
225 + errno = EINVAL;
226 + return NULL;
227 + }
228 if (lockf(fileno(fp), F_LOCK, (off_t)0) == -1)
229 return NULL;
230 gotlock++;
231 @@ -258,99 +336,66 @@ pututxline(const struct utmpx *utx)
232 }
233
234 if (!gotlock) {
235 + /*
236 + * utx->ut_type has any original mask bits, while
237 + * ux->ut_type has those mask bits removed. If we
238 + * are trying to record a dead process, if
239 + * UTMPX_DEAD_IF_CORRESPONDING_MASK is set, but the found
240 + * entry is not a (matching) USER_PROCESS, then return NULL.
241 + */
242 + if (ux->ut_type == DEAD_PROCESS &&
243 + (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK) &&
244 + x->ut_type != USER_PROCESS) {
245 + errno = EINVAL;
246 + return NULL;
247 + }
248 /* we are not appending */
249 +#ifdef __LP64__
250 + if (fseeko(fp, -(off_t)sizeof(ut32), SEEK_CUR) == -1)
251 +#else /* __LP64__ */
252 if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
253 +#endif /* __LP64__ */
254 return NULL;
255 }
256
257 - if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
258 +#ifdef __LP64__
259 + _utmpx64_32(ux, &ut32);
260 + if (fwrite(&ut32, sizeof (ut32), 1, fp) != 1)
261 +#else /* __LP64__ */
262 + if (fwrite(ux, sizeof (*ux), 1, fp) != 1)
263 +#endif /* __LP64__ */
264 goto fail;
265
266 if (fflush(fp) == -1)
267 goto fail;
268
269 - u = memcpy(&ut, &temp, sizeof(ut));
270 + u = memcpy(&ut, ux, sizeof(ut));
271 + notify_post(UTMPX_CHANGE_NOTIFICATION);
272 fail:
273 if (gotlock) {
274 + int save = errno;
275 if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
276 return NULL;
277 + errno = save;
278 }
279 return u;
280 }
281
282
283 -static struct utmpx *
284 -utmp_update(const struct utmpx *utx)
285 -{
286 - char buf[sizeof(*utx) * 4 + 1];
287 - pid_t pid;
288 - int status;
289 -
290 - _DIAGASSERT(utx != NULL);
291 -
292 - (void)strvisx(buf, (const char *)(const void *)utx, sizeof(*utx),
293 - VIS_WHITE);
294 - switch (pid = fork()) {
295 - case 0:
296 - (void)execl(_PATH_UTMP_UPDATE,
297 - strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
298 - exit(1);
299 - /*NOTREACHED*/
300 - case -1:
301 - return NULL;
302 - default:
303 - if (waitpid(pid, &status, 0) == -1)
304 - return NULL;
305 - if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
306 - return memcpy(&ut, utx, sizeof(ut));
307 - return NULL;
308 - }
309 -
310 -}
311 -
312 /*
313 * The following are extensions and not part of the X/Open spec.
314 */
315 int
316 -updwtmpx(const char *file, const struct utmpx *utx)
317 -{
318 - int fd;
319 - int saved_errno;
320 -
321 - _DIAGASSERT(file != NULL);
322 - _DIAGASSERT(utx != NULL);
323 -
324 - fd = open(file, O_WRONLY|O_APPEND|O_SHLOCK);
325 -
326 - if (fd == -1) {
327 - if ((fd = open(file, O_CREAT|O_WRONLY|O_EXLOCK, 0644)) == -1)
328 - return -1;
329 - (void)memset(&ut, 0, sizeof(ut));
330 - ut.ut_type = SIGNATURE;
331 - (void)memcpy(ut.ut_user, vers, sizeof(vers));
332 - if (write(fd, &ut, sizeof(ut)) == -1)
333 - goto failed;
334 - }
335 - if (write(fd, utx, sizeof(*utx)) == -1)
336 - goto failed;
337 - if (close(fd) == -1)
338 - return -1;
339 - return 0;
340 -
341 - failed:
342 - saved_errno = errno;
343 - (void) close(fd);
344 - errno = saved_errno;
345 - return -1;
346 -}
347 -
348 -
349 -int
350 utmpxname(const char *fname)
351 {
352 size_t len;
353
354 - _DIAGASSERT(fname != NULL);
355 + if (fname == NULL) {
356 + strcpy(utfile, _PATH_UTMPX);
357 + utfile_system = 1;
358 + endutxent();
359 + return 1;
360 + }
361
362 len = strlen(fname);
363
364 @@ -363,18 +408,17 @@ utmpxname(const char *fname)
365
366 (void)strlcpy(utfile, fname, sizeof(utfile));
367 endutxent();
368 + utfile_system = 0;
369 return 1;
370 }
371
372 -
373 +#ifdef LEGACY_UTMP_APIS
374 void
375 getutmp(const struct utmpx *ux, struct utmp *u)
376 {
377
378 - _DIAGASSERT(ux != NULL);
379 - _DIAGASSERT(u != NULL);
380 -
381 - (void)memcpy(u->ut_name, ux->ut_name, sizeof(u->ut_name));
382 + bzero(u, sizeof(*u));
383 + (void)memcpy(u->ut_name, ux->ut_user, sizeof(u->ut_name));
384 (void)memcpy(u->ut_line, ux->ut_line, sizeof(u->ut_line));
385 (void)memcpy(u->ut_host, ux->ut_host, sizeof(u->ut_host));
386 u->ut_time = ux->ut_tv.tv_sec;
387 @@ -384,109 +428,16 @@ void
388 getutmpx(const struct utmp *u, struct utmpx *ux)
389 {
390
391 - _DIAGASSERT(ux != NULL);
392 - _DIAGASSERT(u != NULL);
393 -
394 - (void)memcpy(ux->ut_name, u->ut_name, sizeof(u->ut_name));
395 + bzero(ux, sizeof(*ux));
396 + (void)memcpy(ux->ut_user, u->ut_name, sizeof(u->ut_name));
397 + ux->ut_user[sizeof(u->ut_name)] = 0;
398 (void)memcpy(ux->ut_line, u->ut_line, sizeof(u->ut_line));
399 + ux->ut_line[sizeof(u->ut_line)] = 0;
400 (void)memcpy(ux->ut_host, u->ut_host, sizeof(u->ut_host));
401 + ux->ut_host[sizeof(u->ut_host)] = 0;
402 ux->ut_tv.tv_sec = u->ut_time;
403 ux->ut_tv.tv_usec = 0;
404 - (void)memset(&ux->ut_ss, 0, sizeof(ux->ut_ss));
405 - ux->ut_pid = 0;
406 + ux->ut_pid = getpid();
407 ux->ut_type = USER_PROCESS;
408 - ux->ut_session = 0;
409 - ux->ut_exit.e_termination = 0;
410 - ux->ut_exit.e_exit = 0;
411 -}
412 -
413 -int
414 -lastlogxname(const char *fname)
415 -{
416 - size_t len;
417 -
418 - _DIAGASSERT(fname != NULL);
419 -
420 - len = strlen(fname);
421 -
422 - if (len >= sizeof(llfile))
423 - return 0;
424 -
425 - /* must end in x! */
426 - if (fname[len - 1] != 'x')
427 - return 0;
428 -
429 - (void)strlcpy(llfile, fname, sizeof(llfile));
430 - return 1;
431 -}
432 -
433 -struct lastlogx *
434 -getlastlogx(uid_t uid, struct lastlogx *ll)
435 -{
436 -
437 - return __getlastlogx13(_PATH_LASTLOGX, uid, ll);
438 -}
439 -
440 -struct lastlogx *
441 -__getlastlogx13(const char *fname, uid_t uid, struct lastlogx *ll)
442 -{
443 - DBT key, data;
444 - DB *db;
445 -
446 - _DIAGASSERT(fname != NULL);
447 - _DIAGASSERT(ll != NULL);
448 -
449 - db = dbopen(fname, O_RDONLY|O_SHLOCK, 0, DB_HASH, NULL);
450 -
451 - if (db == NULL)
452 - return NULL;
453 -
454 - key.data = &uid;
455 - key.size = sizeof(uid);
456 -
457 - if ((db->get)(db, &key, &data, 0) != 0)
458 - goto error;
459 -
460 - if (data.size != sizeof(*ll)) {
461 - errno = EFTYPE;
462 - goto error;
463 - }
464 -
465 - if (ll == NULL)
466 - if ((ll = malloc(sizeof(*ll))) == NULL)
467 - goto done;
468 -
469 - (void)memcpy(ll, data.data, sizeof(*ll));
470 - goto done;
471 -error:
472 - ll = NULL;
473 -done:
474 - (db->close)(db);
475 - return ll;
476 -}
477 -
478 -int
479 -updlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
480 -{
481 - DBT key, data;
482 - int error = 0;
483 - DB *db;
484 -
485 - _DIAGASSERT(fname != NULL);
486 - _DIAGASSERT(ll != NULL);
487 -
488 - db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0, DB_HASH, NULL);
489 -
490 - if (db == NULL)
491 - return -1;
492 -
493 - key.data = &uid;
494 - key.size = sizeof(uid);
495 - data.data = ll;
496 - data.size = sizeof(*ll);
497 - if ((db->put)(db, &key, &data, 0) != 0)
498 - error = -1;
499 -
500 - (db->close)(db);
501 - return error;
502 }
503 +#endif /* LEGACY_UTMP_APIS */