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