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