1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | #include "sessreg.h" |
74 | |
75 | #include <X11/Xos.h> |
76 | #include <X11/Xfuncs.h> |
77 | #include <stdio.h> |
78 | #include <stdlib.h> |
79 | #include <time.h> |
80 | |
81 | #ifdef USE_UTMP |
82 | static void set_utmp (struct utmp *u, char *line, char *user, char *host, |
83 | time_t date, int addp); |
84 | #endif |
85 | |
86 | #ifdef USE_UTMPX |
87 | static void set_utmpx (struct utmpx *u, const char *line, const char *user, |
88 | const char *host, time_t date, int addp); |
89 | #endif |
90 | |
91 | static int wflag, uflag, lflag; |
92 | static const char *wtmp_file, *utmp_file; |
93 | static char *line; |
94 | #ifdef USE_UTMPX |
95 | #ifdef HAVE_UPDWTMPX1 |
96 | static const char *wtmpx_file = NULL((void*)0); |
97 | #endif |
98 | #ifdef HAVE_UTMPXNAME1 |
99 | static const char *utmpx_file = NULL((void*)0); |
100 | #endif |
101 | #endif |
102 | #ifndef WTMPX_FILE"/var/log/wtmp" |
103 | #define WTMPX_FILE"/var/log/wtmp" _PATH_WTMPX"/var/log/wtmp" |
104 | #endif |
105 | #ifndef UTMPX_FILE"/var/run/utmp" |
106 | #define UTMPX_FILE"/var/run/utmp" _PATH_UTMPX"/var/run/utmp" |
107 | #endif |
108 | |
109 | static int utmp_none, wtmp_none; |
110 | |
111 | |
112 | |
113 | |
114 | static int hflag, xflag, tflag; |
115 | static char *host_name = NULL((void*)0); |
116 | #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE1) |
117 | static int sflag; |
118 | static int slot_number; |
119 | #endif |
120 | static char *xservers_file, *ttys_file; |
121 | static char *user_name; |
122 | static int aflag, dflag; |
123 | #ifdef USE_LASTLOG |
124 | static const char *llog_file; |
125 | static int llog_none, Lflag; |
126 | #endif |
127 | |
128 | static char *program_name; |
129 | |
130 | #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE1) |
131 | static int findslot (char *line_name, char *host_name, int addp, int slot); |
132 | static int Xslot (char *ttys_file, char *servers_file, char *tty_line, |
133 | char *host_name, int addp); |
134 | #endif |
135 | |
136 | static int |
137 | usage (int x) |
138 | { |
139 | if (x) { |
140 | fprintf (stderrstderr, "%s: usage %s {-a -d} [-w wtmp-file] [-u utmp-file]", program_name, program_name); |
141 | #ifdef USE_LASTLOG |
142 | fprintf (stderrstderr, " [-L lastlog-file]"); |
143 | #endif |
144 | fprintf (stderrstderr, "\n"); |
145 | fprintf (stderrstderr, " [-t ttys-file] [-l line-name] [-h host-name]\n"); |
146 | fprintf (stderrstderr, " [-s slot-number] [-x servers-file] user-name\n"); |
147 | exit (1); |
148 | } |
149 | return x; |
150 | } |
151 | |
152 | static char * |
153 | getstring (char ***avp, int *flagp) |
154 | { |
155 | char **a = *avp; |
156 | |
157 | usage ((*flagp)++); |
158 | if (*++*a) |
159 | return *a; |
160 | ++a; |
161 | usage (!*a); |
162 | *avp = a; |
163 | return *a; |
164 | } |
165 | |
166 | #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE1) |
167 | static int |
168 | syserr (int x, const char *s) |
169 | { |
170 | if (x == -1) { |
171 | perror (s); |
172 | exit (1); |
173 | } |
174 | return x; |
175 | } |
176 | #endif |
177 | |
178 | static int |
179 | sysnerr (int x, const char *s) |
180 | { |
181 | if (x == 0) { |
182 | perror (s); |
183 | exit (1); |
184 | } |
185 | return x; |
186 | } |
187 | |
188 | int |
189 | main (int argc, char **argv) |
190 | { |
191 | #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE1) |
192 | int utmp; |
193 | #endif |
194 | #ifndef USE_UTMPX |
195 | int wtmp; |
196 | #endif |
197 | time_t current_time; |
198 | #ifdef USE_UTMP |
199 | struct utmp utmp_entry; |
200 | #endif |
201 | #ifdef USE_UTMPX |
202 | struct utmpx utmpx_entry; |
203 | #endif |
204 | |
205 | program_name = argv[0]; |
206 | while (*++argv && **argv == '-') { |
| 1 | Loop condition is false. Execution continues on line 252 |
|
207 | switch (*++*argv) { |
208 | case 'w': |
209 | wtmp_file = getstring (&argv, &wflag); |
210 | if (!strcmp (wtmp_file, "none")) |
211 | wtmp_none = 1; |
212 | break; |
213 | case 'u': |
214 | utmp_file = getstring (&argv, &uflag); |
215 | if (!strcmp (utmp_file, "none")) |
216 | utmp_none = 1; |
217 | break; |
218 | #ifdef USE_LASTLOG |
219 | case 'L': |
220 | llog_file = getstring (&argv, &Lflag); |
221 | if (!strcmp (llog_file, "none")) |
222 | llog_none = 1; |
223 | break; |
224 | #endif |
225 | case 't': |
226 | ttys_file = getstring (&argv, &tflag); |
227 | break; |
228 | case 'l': |
229 | line = getstring (&argv, &lflag); |
230 | break; |
231 | case 'h': |
232 | host_name = getstring (&argv, &hflag); |
233 | break; |
234 | case 's': |
235 | #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE1) |
236 | slot_number = atoi (getstring (&argv, &sflag)); |
237 | #endif |
238 | break; |
239 | case 'x': |
240 | xservers_file = getstring (&argv, &xflag); |
241 | break; |
242 | case 'a': |
243 | aflag++; |
244 | break; |
245 | case 'd': |
246 | dflag++; |
247 | break; |
248 | default: |
249 | usage (1); |
250 | } |
251 | } |
252 | usage (!(user_name = *argv++)); |
253 | usage (*argv != NULL((void*)0)); |
254 | |
255 | |
256 | |
257 | |
258 | usage (!(aflag ^ dflag)); |
259 | usage (xflag && !lflag); |
260 | |
261 | if (!wflag) { |
| 2 | Assuming 'wflag' is not equal to 0 |
|
| |
262 | wtmp_file = WTMP_FILE"/var/log/wtmp"; |
263 | #if defined(USE_UTMPX) && defined(HAVE_UPDWTMPX1) |
264 | wtmpx_file = WTMPX_FILE"/var/log/wtmp"; |
265 | #endif |
266 | } |
267 | #ifndef NO_UTMP |
268 | if (!uflag) { |
| 4 | Assuming 'uflag' is not equal to 0 |
|
| |
269 | utmp_file = UTMP_FILE"/var/run/utmp"; |
270 | #if defined(USE_UTMPX) && defined(HAVE_UTMPXNAME1) |
271 | utmpx_file = UTMPX_FILE"/var/run/utmp"; |
272 | #endif |
273 | } |
274 | #else |
275 | utmp_none = 1; |
276 | #endif |
277 | #ifdef USE_LASTLOG |
278 | if (!Lflag) |
| 6 | Assuming 'Lflag' is not equal to 0 |
|
| |
279 | llog_file = LLOG_FILE"/var/log/lastlog"; |
280 | #endif |
281 | #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE1) |
282 | if (!tflag) |
283 | ttys_file = TTYS_FILE"/etc/ttys"; |
284 | if (!sflag && !utmp_none) { |
285 | if (xflag) |
286 | sysnerr (slot_number = Xslot (ttys_file, xservers_file, line, host_name, aflag), "Xslot"); |
287 | else |
288 | sysnerr (slot_number = ttyslot (), "ttyslot"); |
289 | } |
290 | #endif |
291 | if (!lflag) { |
| 8 | Assuming 'lflag' is not equal to 0 |
|
| |
292 | sysnerr ((line = ttyname (0)) != NULL((void*)0), "ttyname"); |
293 | if (strncmp(line, "/dev/", 5) == 0) |
294 | line += 5; |
295 | } |
296 | time (¤t_time); |
297 | #ifdef USE_UTMP |
298 | set_utmp (&utmp_entry, line, user_name, host_name, current_time, aflag); |
299 | #endif |
300 | |
301 | #ifdef USE_UTMPX |
302 | |
303 | |
304 | # ifdef HAVE_UTMPXNAME1 |
305 | if (utmpx_file != NULL((void*)0)) { |
| 10 | Assuming 'utmpx_file' is equal to null |
|
| |
306 | utmpxname (utmpx_file); |
307 | } |
308 | # endif |
309 | set_utmpx (&utmpx_entry, line, user_name, |
310 | host_name, current_time, aflag); |
311 | #endif |
312 | |
313 | if (!utmp_none) { |
| 12 | Assuming 'utmp_none' is not equal to 0 |
|
| |
314 | #ifdef USE_UTMPX |
315 | # ifdef HAVE_UTMPXNAME1 |
316 | if (utmpx_file != NULL((void*)0)) |
317 | # endif |
318 | { |
319 | setutxent (); |
320 | (void) getutxid (&utmpx_entry); |
321 | pututxline (&utmpx_entry); |
322 | endutxent (); |
323 | } |
324 | #endif |
325 | #ifdef USE_UTMP |
326 | # ifdef HAVE_PUTUTLINE1 |
327 | utmpname (utmp_file); |
328 | setutent (); |
329 | (void) getutid (&utmp_entry); |
330 | pututline (&utmp_entry); |
331 | endutent (); |
332 | # else |
333 | utmp = open (utmp_file, O_RDWR02); |
334 | if (utmp != -1) { |
335 | syserr ((int) lseek (utmp, (long) slot_number * sizeof (struct utmp), 0), "lseek"); |
336 | sysnerr (write (utmp, (char *) &utmp_entry, sizeof (utmp_entry)) |
337 | == sizeof (utmp_entry), "write utmp entry"); |
338 | close (utmp); |
339 | } |
340 | # endif |
341 | #endif /* USE_UTMP */ |
342 | } |
343 | if (!wtmp_none) { |
| 14 | Assuming 'wtmp_none' is not equal to 0 |
|
| |
344 | #ifdef USE_UTMPX |
345 | # ifdef HAVE_UPDWTMPX1 |
346 | if (wtmpx_file != NULL((void*)0)) { |
347 | updwtmpx(wtmpx_file, &utmpx_entry); |
348 | } |
349 | # endif |
350 | #else |
351 | wtmp = open (wtmp_file, O_WRONLY01|O_APPEND02000); |
352 | if (wtmp != -1) { |
353 | sysnerr (write (wtmp, (char *) &utmp_entry, sizeof (utmp_entry)) |
354 | == sizeof (utmp_entry), "write wtmp entry"); |
355 | close (wtmp); |
356 | } |
357 | #endif |
358 | } |
359 | #ifdef USE_LASTLOG |
360 | if (aflag && !llog_none) { |
| 16 | Assuming 'llog_none' is 0 |
|
| |
361 | int llog; |
362 | struct passwd *pwd = getpwnam(user_name); |
363 | |
364 | sysnerr( pwd != NULL((void*)0), "get user id"); |
| 18 | Assuming 'pwd' is equal to null |
|
365 | llog = open (llog_file, O_RDWR02); |
366 | |
367 | if (llog != -1) { |
| |
368 | struct lastlog ll; |
369 | |
370 | sysnerr (lseek(llog, (long) pwd->pw_uid*sizeof(ll), 0) |
| 20 | Access to field 'pw_uid' results in a dereference of a null pointer (loaded from variable 'pwd') |
|
371 | != -1, "seeking lastlog entry"); |
372 | memset(&ll, 0, sizeof(ll)); |
373 | ll.ll_time = current_time; |
374 | if (line) |
375 | (void) strncpy (ll.ll_line, line, sizeof (ll.ll_line)); |
376 | if (host_name) |
377 | (void) strncpy (ll.ll_host, host_name, sizeof (ll.ll_host)); |
378 | |
379 | sysnerr (write (llog, (char *) &ll, sizeof (ll)) |
380 | == sizeof (ll), "write lastlog entry"); |
381 | close (llog); |
382 | } |
383 | } |
384 | #endif |
385 | return 0; |
386 | } |
387 | |
388 | |
389 | |
390 | |
391 | |
392 | #ifdef USE_UTMP |
393 | static void |
394 | set_utmp (struct utmp *u, char *line, char *user, char *host, time_t date, int addp) |
395 | { |
396 | memset (u, 0, sizeof (*u)); |
397 | if (line) |
398 | (void) strncpy (u->ut_line, line, sizeof (u->ut_line)); |
399 | else |
400 | memset (u->ut_line, 0, sizeof (u->ut_line)); |
401 | if (addp && user) |
402 | (void) strncpy (u->ut_nameut_user, user, sizeof (u->ut_nameut_user)); |
403 | else |
404 | memset (u->ut_nameut_user, 0, sizeof (u->ut_nameut_user)); |
405 | #ifdef HAVE_STRUCT_UTMP_UT_ID1 |
406 | if (line) { |
407 | int i; |
408 | |
409 | |
410 | |
411 | |
412 | |
413 | |
414 | |
415 | i = strlen (line); |
416 | if (i >= sizeof (u->ut_id)) |
417 | i -= sizeof (u->ut_id); |
418 | else |
419 | i = 0; |
420 | (void) strncpy (u->ut_id, line + i, sizeof (u->ut_id)); |
421 | } else |
422 | memset (u->ut_id, 0, sizeof (u->ut_id)); |
423 | #endif |
424 | #ifdef HAVE_STRUCT_UTMP_UT_PID1 |
425 | if (addp) |
426 | u->ut_pid = getppid (); |
427 | else |
428 | u->ut_pid = 0; |
429 | #endif |
430 | #ifdef HAVE_STRUCT_UTMP_UT_TYPE1 |
431 | if (addp) |
432 | u->ut_type = USER_PROCESS7; |
433 | else |
434 | u->ut_type = DEAD_PROCESS8; |
435 | #endif |
436 | #ifdef HAVE_STRUCT_UTMP_UT_HOST1 |
437 | if (addp && host) |
438 | (void) strncpy (u->ut_host, host, sizeof (u->ut_host)); |
439 | else |
440 | memset (u->ut_host, 0, sizeof (u->ut_host)); |
441 | #endif |
442 | u->ut_timeut_tv.tv_sec = date; |
443 | } |
444 | #endif /* USE_UTMP */ |
445 | |
446 | #ifdef USE_UTMPX |
447 | static int |
448 | UtmpxIdOpen( char *utmpId ) |
449 | { |
450 | struct utmpx *u; |
451 | int status = 1; |
452 | |
453 | setutxent(); |
454 | |
455 | while ( (u = getutxent()) != NULL((void*)0) ) { |
456 | |
457 | if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) && |
458 | u->ut_type != DEAD_PROCESS8 ) { |
459 | |
460 | status = 0; |
461 | break; |
462 | } |
463 | } |
464 | |
465 | endutxent(); |
466 | return (status); |
467 | } |
468 | |
469 | static void |
470 | set_utmpx (struct utmpx *u, const char *line, const char *user, |
471 | const char *host, time_t date, int addp) |
472 | { |
473 | static const char letters[] = |
474 | "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
475 | |
476 | if (line) |
477 | { |
478 | if(strcmp(line, ":0") == 0) |
479 | (void) strcpy(u->ut_line, "console"); |
480 | else |
481 | (void) strncpy (u->ut_line, line, sizeof (u->ut_line)); |
482 | |
483 | strncpy(u->ut_host, line, sizeof(u->ut_host)); |
484 | #ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN |
485 | u->ut_syslen = strlen(line); |
486 | #endif |
487 | } |
488 | else |
489 | memset (u->ut_line, 0, sizeof (u->ut_line)); |
490 | if (addp && user) |
491 | (void) strncpy (u->ut_user, user, sizeof (u->ut_user)); |
492 | else |
493 | memset (u->ut_user, 0, sizeof (u->ut_user)); |
494 | |
495 | if (line) { |
496 | int i; |
497 | |
498 | |
499 | |
500 | |
501 | |
502 | |
503 | |
504 | i = strlen (line); |
505 | if (i >= sizeof (u->ut_id)) |
506 | i -= sizeof (u->ut_id); |
507 | else |
508 | i = 0; |
509 | (void) strncpy (u->ut_id, line + i, sizeof (u->ut_id)); |
510 | |
511 | |
512 | if (!UtmpxIdOpen(u->ut_id) && addp) { |
513 | int limit = sizeof(letters) - 1; |
514 | int t = 0; |
515 | |
516 | u->ut_id[1] = line[i]; |
517 | u->ut_id[2] = line[i+1]; |
518 | u->ut_id[3] = line[i+2]; |
519 | do { |
520 | u->ut_id[0] = letters[t]; |
521 | t++; |
522 | } while (!UtmpxIdOpen(u->ut_id) && (t < limit)); |
523 | } |
524 | if (!addp && strstr(line, ":") != NULL((void*)0)) { |
525 | struct utmpx *tmpu; |
526 | |
527 | while ( (tmpu = getutxent()) != NULL((void*)0) ) { |
528 | if ( (strcmp(tmpu->ut_host, line) == 0 ) && |
529 | tmpu->ut_type != DEAD_PROCESS8 ) { |
530 | strncpy(u->ut_id, tmpu->ut_id, |
531 | sizeof(u->ut_id)); |
532 | break; |
533 | } |
534 | } |
535 | endutxent(); |
536 | } |
537 | } else |
538 | memset (u->ut_id, 0, sizeof (u->ut_id)); |
539 | |
540 | if (addp) { |
541 | u->ut_pid = getppid (); |
542 | u->ut_type = USER_PROCESS7; |
543 | } else { |
544 | u->ut_pid = 0; |
545 | u->ut_type = DEAD_PROCESS8; |
546 | } |
547 | u->ut_tv.tv_sec = date; |
548 | u->ut_tv.tv_usec = 0; |
549 | } |
550 | #endif /* USE_UTMPX */ |
551 | |
552 | #if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE1) |
553 | |
554 | |
555 | |
556 | |
557 | |
558 | |
559 | |
560 | |
561 | |
562 | static int |
563 | Xslot (char *ttys_file, char *servers_file, char *tty_line, char *host_name, |
564 | int addp) |
565 | { |
566 | FILE *ttys, *servers; |
567 | int c; |
568 | int slot = 1; |
569 | int column0 = 1; |
570 | char servers_line[1024]; |
571 | char disp_name[512]; |
572 | int len; |
573 | char *pos; |
574 | |
575 | |
576 | memset(disp_name, 0, sizeof(disp_name)); |
577 | strncpy(disp_name, host_name ? host_name : tty_line, sizeof(disp_name)-1); |
578 | pos = strrchr(disp_name, ':'); |
579 | if (pos) { |
580 | pos = strchr(pos, '.'); |
581 | if (pos) |
582 | *pos = '\0'; |
583 | } |
584 | sysnerr ((int)(long)(ttys = fopen (ttys_file, "r")), ttys_file); |
585 | while ((c = getc (ttys)_IO_getc (ttys)) != EOF(-1)) |
586 | if (c == '\n') { |
587 | ++slot; |
588 | column0 = 1; |
589 | } else |
590 | column0 = 0; |
591 | if (!column0) |
592 | ++slot; |
593 | (void) fclose (ttys); |
594 | sysnerr ((int)(long)(servers = fopen (servers_file, "r")), servers_file); |
595 | |
596 | len = strlen (disp_name); |
597 | column0 = 1; |
598 | while (fgets (servers_line, sizeof (servers_line), servers)) { |
599 | if (column0 && *servers_line != '#') { |
600 | if (!strncmp (disp_name, servers_line, len) && |
601 | (servers_line[len] == ' ' || |
602 | servers_line[len] == '\t')) |
603 | return slot; |
604 | ++slot; |
605 | } |
606 | if (servers_line[strlen(servers_line)-1] != '\n') |
607 | column0 = 0; |
608 | else |
609 | column0 = 1; |
610 | } |
611 | |
612 | |
613 | |
614 | return findslot (tty_line, host_name, addp, slot); |
615 | } |
616 | |
617 | |
618 | |
619 | |
620 | |
621 | |
622 | static int |
623 | findslot (char *line_name, char *host_name, int addp, int slot) |
624 | { |
625 | int utmp; |
626 | struct utmp entry; |
627 | int found = 0; |
628 | int freeslot = -1; |
629 | |
630 | syserr(utmp = open (utmp_file, O_RDONLY00), "open utmp"); |
631 | |
632 | |
633 | |
634 | |
635 | |
636 | syserr ((int) lseek (utmp, (long) slot * sizeof (struct utmp), 0), "lseek"); |
637 | |
638 | if (!host_name) |
639 | host_name = ""; |
640 | |
641 | while (read (utmp, (char *) &entry, sizeof (entry)) == sizeof (entry)) { |
642 | if (strncmp(entry.ut_line, line_name, |
643 | sizeof(entry.ut_line)) == 0 |
644 | #ifdef HAVE_STRUCT_UTMP_UT_HOST1 |
645 | && |
646 | strncmp(entry.ut_host, host_name, |
647 | sizeof(entry.ut_host)) == 0 |
648 | #endif |
649 | ) { |
650 | found = 1; |
651 | break; |
652 | } |
653 | if (freeslot < 0 && *entry.ut_nameut_user == '\0') |
654 | freeslot = slot; |
655 | ++slot; |
656 | } |
657 | |
658 | close (utmp); |
659 | |
660 | if (found) |
661 | return slot; |
662 | else if (!addp) |
663 | return 0; |
664 | else if (freeslot < 0) |
665 | return slot; |
666 | else |
667 | return freeslot; |
668 | } |
669 | #endif |