|
Lines 62-67
Link Here
|
| 62 |
|
62 |
|
| 63 |
#define NO 0 /* false/no */ |
63 |
#define NO 0 /* false/no */ |
| 64 |
#define YES 1 /* true/yes */ |
64 |
#define YES 1 /* true/yes */ |
|
|
65 |
#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2; |
| 65 |
|
66 |
|
| 66 |
static struct utmp buf[1024]; /* utmp read buffer */ |
67 |
static struct utmp buf[1024]; /* utmp read buffer */ |
| 67 |
|
68 |
|
|
Lines 89-99
Link Here
|
| 89 |
static int sflag = 0; /* show delta in seconds */ |
90 |
static int sflag = 0; /* show delta in seconds */ |
| 90 |
static int width = 5; /* show seconds in delta */ |
91 |
static int width = 5; /* show seconds in delta */ |
| 91 |
static int d_first; |
92 |
static int d_first; |
|
|
93 |
static time_t snaptime; /* if != 0, we will only |
| 94 |
* report users logged in |
| 95 |
* at this snapshot time |
| 96 |
*/ |
| 92 |
|
97 |
|
| 93 |
void addarg __P((int, char *)); |
98 |
void addarg __P((int, char *)); |
| 94 |
void hostconv __P((char *)); |
99 |
void hostconv __P((char *)); |
| 95 |
void onintr __P((int)); |
100 |
void onintr __P((int)); |
| 96 |
char *ttyconv __P((char *)); |
101 |
char *ttyconv __P((char *)); |
|
|
102 |
time_t dateconv __P((char *)); |
| 97 |
int want __P((struct utmp *)); |
103 |
int want __P((struct utmp *)); |
| 98 |
void wtmp __P((void)); |
104 |
void wtmp __P((void)); |
| 99 |
|
105 |
|
|
Lines 117-123
Link Here
|
| 117 |
d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); |
123 |
d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); |
| 118 |
|
124 |
|
| 119 |
maxrec = -1; |
125 |
maxrec = -1; |
| 120 |
while ((ch = getopt(argc, argv, "0123456789f:h:st:w")) != -1) |
126 |
snaptime = 0; |
|
|
127 |
while ((ch = getopt(argc, argv, "0123456789d:f:h:st:w")) != -1) |
| 121 |
switch (ch) { |
128 |
switch (ch) { |
| 122 |
case '0': case '1': case '2': case '3': case '4': |
129 |
case '0': case '1': case '2': case '3': case '4': |
| 123 |
case '5': case '6': case '7': case '8': case '9': |
130 |
case '5': case '6': case '7': case '8': case '9': |
|
Lines 135-140
Link Here
|
| 135 |
exit(0); |
142 |
exit(0); |
| 136 |
} |
143 |
} |
| 137 |
break; |
144 |
break; |
|
|
145 |
case 'd': |
| 146 |
snaptime = dateconv(optarg); |
| 147 |
break; |
| 138 |
case 'f': |
148 |
case 'f': |
| 139 |
file = optarg; |
149 |
file = optarg; |
| 140 |
break; |
150 |
break; |
|
Lines 189-194
Link Here
|
| 189 |
char *crmsg; |
199 |
char *crmsg; |
| 190 |
char ct[80]; |
200 |
char ct[80]; |
| 191 |
struct tm *tm; |
201 |
struct tm *tm; |
|
|
202 |
int snapfound = 0; /* found snapshot entry? */ |
| 192 |
|
203 |
|
| 193 |
LIST_INIT(&ttylist); |
204 |
LIST_INIT(&ttylist); |
| 194 |
|
205 |
|
|
Lines 220-226
Link Here
|
| 220 |
currentout = -bp->ut_time; |
231 |
currentout = -bp->ut_time; |
| 221 |
crmsg = strncmp(bp->ut_name, "shutdown", |
232 |
crmsg = strncmp(bp->ut_name, "shutdown", |
| 222 |
UT_NAMESIZE) ? "crash" : "shutdown"; |
233 |
UT_NAMESIZE) ? "crash" : "shutdown"; |
| 223 |
if (want(bp)) { |
234 |
/* |
|
|
235 |
* if we're in snapshot mode, we want to |
| 236 |
* exit if this shutdown/reboot appears |
| 237 |
* while we we are tracking the active |
| 238 |
* range |
| 239 |
*/ |
| 240 |
if (snaptime && snapfound) |
| 241 |
return; |
| 242 |
/* |
| 243 |
* don't print shutdown/reboot entries |
| 244 |
* unless flagged for |
| 245 |
*/ |
| 246 |
if (!snaptime && want(bp)) { |
| 224 |
tm = localtime(&bp->ut_time); |
247 |
tm = localtime(&bp->ut_time); |
| 225 |
(void) strftime(ct, sizeof(ct), |
248 |
(void) strftime(ct, sizeof(ct), |
| 226 |
d_first ? "%a %e %b %R" : |
249 |
d_first ? "%a %e %b %R" : |
|
Lines 243-249
Link Here
|
| 243 |
*/ |
266 |
*/ |
| 244 |
if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|') |
267 |
if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|') |
| 245 |
&& !bp->ut_line[1]) { |
268 |
&& !bp->ut_line[1]) { |
| 246 |
if (want(bp)) { |
269 |
if (want(bp) && !snaptime) { |
| 247 |
tm = localtime(&bp->ut_time); |
270 |
tm = localtime(&bp->ut_time); |
| 248 |
(void) strftime(ct, sizeof(ct), |
271 |
(void) strftime(ct, sizeof(ct), |
| 249 |
d_first ? "%a %e %b %R" : |
272 |
d_first ? "%a %e %b %R" : |
|
Lines 259-335
Link Here
|
| 259 |
} |
282 |
} |
| 260 |
continue; |
283 |
continue; |
| 261 |
} |
284 |
} |
| 262 |
if (bp->ut_name[0] == '\0' || want(bp)) { |
285 |
/* find associated tty */ |
| 263 |
/* find associated tty */ |
286 |
LIST_FOREACH(tt, &ttylist, list) |
| 264 |
LIST_FOREACH(tt, &ttylist, list) |
287 |
if (!strncmp(tt->tty, bp->ut_line, UT_LINESIZE)) |
| 265 |
if (!strncmp(tt->tty, bp->ut_line, UT_LINESIZE)) |
288 |
break; |
| 266 |
break; |
289 |
|
| 267 |
|
290 |
if (tt == NULL) { |
| 268 |
if (tt == NULL) { |
291 |
/* add new one */ |
| 269 |
/* add new one */ |
292 |
tt = malloc(sizeof(struct ttytab)); |
| 270 |
tt = malloc(sizeof(struct ttytab)); |
293 |
if (tt == NULL) |
| 271 |
if (tt == NULL) |
294 |
err(1, "malloc failure"); |
| 272 |
err(1, "malloc failure"); |
295 |
tt->logout = currentout; |
| 273 |
tt->logout = currentout; |
296 |
strncpy(tt->tty, bp->ut_line, UT_LINESIZE); |
| 274 |
strncpy(tt->tty, bp->ut_line, UT_LINESIZE); |
297 |
LIST_INSERT_HEAD(&ttylist, tt, list); |
| 275 |
LIST_INSERT_HEAD(&ttylist, tt, list); |
298 |
} |
| 276 |
} |
299 |
|
| 277 |
|
300 |
/* |
| 278 |
if (bp->ut_name[0]) { |
301 |
* print record if not in snapshot mode and wanted |
| 279 |
/* |
302 |
* or in snapshot mode and in snapshot range |
| 280 |
* when uucp and ftp log in over a network, the entry in |
303 |
*/ |
| 281 |
* the utmp file is the name plus their process id. See |
304 |
if (bp->ut_name[0] && (want(bp) || |
| 282 |
* etc/ftpd.c and usr.bin/uucp/uucpd.c for more information. |
305 |
(bp->ut_time < snaptime && |
| 283 |
*/ |
306 |
(tt->logout > snaptime || tt->logout < 1)))) { |
| 284 |
if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1)) |
307 |
snapfound = 1; |
| 285 |
bp->ut_line[3] = '\0'; |
308 |
/* |
| 286 |
else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1)) |
309 |
* when uucp and ftp log in over a network, the entry in |
| 287 |
bp->ut_line[4] = '\0'; |
310 |
* the utmp file is the name plus their process id. See |
| 288 |
tm = localtime(&bp->ut_time); |
311 |
* etc/ftpd.c and usr.bin/uucp/uucpd.c for more information. |
| 289 |
(void) strftime(ct, sizeof(ct), |
312 |
*/ |
| 290 |
d_first ? "%a %e %b %R" : |
313 |
if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1)) |
| 291 |
"%a %b %e %R", |
314 |
bp->ut_line[3] = '\0'; |
| 292 |
tm); |
315 |
else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1)) |
| 293 |
printf("%-*.*s %-*.*s %-*.*s %s ", |
316 |
bp->ut_line[4] = '\0'; |
| 294 |
UT_NAMESIZE, UT_NAMESIZE, bp->ut_name, |
317 |
tm = localtime(&bp->ut_time); |
| 295 |
UT_LINESIZE, UT_LINESIZE, bp->ut_line, |
318 |
(void) strftime(ct, sizeof(ct), |
| 296 |
UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host, |
319 |
d_first ? "%a %e %b %R" : |
| 297 |
ct); |
320 |
"%a %b %e %R", |
| 298 |
if (!tt->logout) |
321 |
tm); |
| 299 |
puts(" still logged in"); |
322 |
printf("%-*.*s %-*.*s %-*.*s %s ", |
|
|
323 |
UT_NAMESIZE, UT_NAMESIZE, bp->ut_name, |
| 324 |
UT_LINESIZE, UT_LINESIZE, bp->ut_line, |
| 325 |
UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host, |
| 326 |
ct); |
| 327 |
if (!tt->logout) |
| 328 |
puts(" still logged in"); |
| 329 |
else { |
| 330 |
if (tt->logout < 0) { |
| 331 |
tt->logout = -tt->logout; |
| 332 |
printf("- %s", crmsg); |
| 333 |
} |
| 300 |
else { |
334 |
else { |
| 301 |
if (tt->logout < 0) { |
335 |
tm = localtime(&tt->logout); |
| 302 |
tt->logout = -tt->logout; |
336 |
(void) strftime(ct, sizeof(ct), "%R", tm); |
| 303 |
printf("- %s", crmsg); |
337 |
printf("- %s", ct); |
| 304 |
} |
338 |
} |
| 305 |
else { |
339 |
delta = tt->logout - bp->ut_time; |
| 306 |
tm = localtime(&tt->logout); |
340 |
if ( sflag ) { |
| 307 |
(void) strftime(ct, sizeof(ct), "%R", tm); |
341 |
printf(" (%8lu)\n", |
| 308 |
printf("- %s", ct); |
342 |
delta); |
| 309 |
} |
343 |
} else { |
| 310 |
delta = tt->logout - bp->ut_time; |
344 |
tm = gmtime(&delta); |
| 311 |
if ( sflag ) { |
345 |
(void) strftime(ct, sizeof(ct), |
| 312 |
printf(" (%8lu)\n", |
346 |
width >= 8 ? "%T" : "%R", |
| 313 |
delta); |
347 |
tm); |
| 314 |
} else { |
348 |
if (delta < 86400) |
| 315 |
tm = gmtime(&delta); |
|
|
| 316 |
(void) strftime(ct, sizeof(ct), |
| 317 |
width >= 8 ? "%T" : "%R", |
| 318 |
tm); |
| 319 |
if (delta < 86400) |
| 320 |
printf(" (%s)\n", ct); |
349 |
printf(" (%s)\n", ct); |
| 321 |
else |
350 |
else |
| 322 |
printf(" (%ld+%s)\n", |
351 |
printf(" (%ld+%s)\n", |
| 323 |
delta / 86400, ct); |
352 |
delta / 86400, ct); |
| 324 |
} |
|
|
| 325 |
} |
353 |
} |
| 326 |
LIST_REMOVE(tt, list); |
|
|
| 327 |
free(tt); |
| 328 |
if (maxrec != -1 && !--maxrec) |
| 329 |
return; |
| 330 |
} else { |
| 331 |
tt->logout = bp->ut_time; |
| 332 |
} |
354 |
} |
|
|
355 |
LIST_REMOVE(tt, list); |
| 356 |
free(tt); |
| 357 |
if (maxrec != -1 && !--maxrec) |
| 358 |
return; |
| 359 |
} else { |
| 360 |
tt->logout = bp->ut_time; |
| 333 |
} |
361 |
} |
| 334 |
} |
362 |
} |
| 335 |
} |
363 |
} |
|
Lines 348-353
Link Here
|
| 348 |
{ |
376 |
{ |
| 349 |
ARG *step; |
377 |
ARG *step; |
| 350 |
|
378 |
|
|
|
379 |
if (snaptime) |
| 380 |
return (NO); |
| 381 |
|
| 351 |
if (!arglist) |
382 |
if (!arglist) |
| 352 |
return (YES); |
383 |
return (YES); |
| 353 |
|
384 |
|
|
Lines 444-449
Link Here
|
| 444 |
return (arg + 5); |
475 |
return (arg + 5); |
| 445 |
return (arg); |
476 |
return (arg); |
| 446 |
} |
477 |
} |
|
|
478 |
|
| 479 |
/* |
| 480 |
* dateconv -- |
| 481 |
* Convert the snapshot time in command line given in the format |
| 482 |
* [[CC]YY]MMDDhhmm[.SS]] to a time_t. |
| 483 |
* Derived from atime_arg1() in usr.bin/touch/touch.c |
| 484 |
*/ |
| 485 |
time_t |
| 486 |
dateconv(arg) |
| 487 |
char *arg; |
| 488 |
{ |
| 489 |
time_t timet; |
| 490 |
struct tm *t; |
| 491 |
int yearset; |
| 492 |
char *p; |
| 493 |
|
| 494 |
/* Start with the current time. */ |
| 495 |
if (time(&timet) < 0) |
| 496 |
err(1, "time"); |
| 497 |
if ((t = localtime(&timet)) == NULL) |
| 498 |
err(1, "localtime"); |
| 499 |
|
| 500 |
/* [[CC]YY]MMDDhhmm[.SS] */ |
| 501 |
if ((p = strchr(arg, '.')) == NULL) |
| 502 |
t->tm_sec = 0; /* Seconds defaults to 0. */ |
| 503 |
else { |
| 504 |
if (strlen(p + 1) != 2) |
| 505 |
goto terr; |
| 506 |
*p++ = '\0'; |
| 507 |
t->tm_sec = ATOI2(p); |
| 508 |
} |
| 509 |
|
| 510 |
yearset = 0; |
| 511 |
switch (strlen(arg)) { |
| 512 |
case 12: /* CCYYMMDDhhmm */ |
| 513 |
t->tm_year = ATOI2(arg); |
| 514 |
t->tm_year *= 100; |
| 515 |
yearset = 1; |
| 516 |
/* FALLTHOUGH */ |
| 517 |
case 10: /* YYMMDDhhmm */ |
| 518 |
if (yearset) { |
| 519 |
yearset = ATOI2(arg); |
| 520 |
t->tm_year += yearset; |
| 521 |
} else { |
| 522 |
yearset = ATOI2(arg); |
| 523 |
if (yearset < 69) |
| 524 |
t->tm_year = yearset + 2000; |
| 525 |
else |
| 526 |
t->tm_year = yearset + 1900; |
| 527 |
} |
| 528 |
t->tm_year -= 1900; /* Convert to UNIX time. */ |
| 529 |
/* FALLTHROUGH */ |
| 530 |
case 8: /* MMDDhhmm */ |
| 531 |
t->tm_mon = ATOI2(arg); |
| 532 |
--t->tm_mon; /* Convert from 01-12 to 00-11 */ |
| 533 |
t->tm_mday = ATOI2(arg); |
| 534 |
t->tm_hour = ATOI2(arg); |
| 535 |
t->tm_min = ATOI2(arg); |
| 536 |
break; |
| 537 |
case 4: /* hhmm */ |
| 538 |
t->tm_hour = ATOI2(arg); |
| 539 |
t->tm_min = ATOI2(arg); |
| 540 |
break; |
| 541 |
default: |
| 542 |
goto terr; |
| 543 |
} |
| 544 |
t->tm_isdst = -1; /* Figure out DST. */ |
| 545 |
timet = mktime(t); |
| 546 |
if (timet == -1) |
| 547 |
terr: errx(1, |
| 548 |
"out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]"); |
| 549 |
return timet; |
| 550 |
} |
| 551 |
|
| 447 |
|
552 |
|
| 448 |
/* |
553 |
/* |
| 449 |
* onintr -- |
554 |
* onintr -- |