/* * wtmp -- * read through the wtmp file */ void wtmp(const char *file, int namesz, int linesz, int hostsz) { struct utmp *bp; /* current structure */ TTY *T; /* tty list entry */ struct stat stb; /* stat of file for sz */ time_t delta; /* time difference */ off_t bl; int bytes, wfd; char *ct; const char *crmsg; size_t len = sizeof(*buf) * MAXUTMP; if ((buf = malloc(len)) == NULL) err(1, "Cannot allocate utmp buffer"); crmsg = NULL; if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) err(1, "%s", file); bl = (stb.st_size + len - 1) / len; buf[FIRSTVALID].ut_timefld = time(NULL); (void)signal(SIGINT, onintr); (void)signal(SIGQUIT, onintr); while (--bl >= 0) { if (lseek(wfd, bl * len, SEEK_SET) == -1 || (bytes = read(wfd, buf, len)) == -1) err(1, "%s", file); for (bp = &buf[bytes / sizeof(*buf) - 1]; bp >= buf; --bp) { /* * if the terminal line is '~', the machine stopped. * see utmp(5) for more info. */ if (bp->ut_line[0] == '~' && !bp->ut_line[1]) { /* everybody just logged out */ for (T = ttylist; T; T = T->next) T->logout = -bp->ut_timefld; currentout = -bp->ut_timefld; crmsg = strncmp(bp->ut_name, "shutdown", namesz) ? "crash" : "shutdown"; if (want(bp, NO)) { ct = fmttime(bp->ut_timefld, fulltime); printf("%-*.*s %-*.*s %-*.*s %s\n", namesz, namesz, bp->ut_name, linesz, linesz, bp->ut_line, hostsz, hostsz, bp->ut_host, ct); if (maxrec != -1 && !--maxrec) return; } continue; } /* * if the line is '{' or '|', date got set; see * utmp(5) for more info. */ if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|') && !bp->ut_line[1]) { if (want(bp, NO)) { ct = fmttime(bp->ut_timefld, fulltime); printf("%-*.*s %-*.*s %-*.*s %s\n", namesz, namesz, bp->ut_name, linesz, linesz, bp->ut_line, hostsz, hostsz, bp->ut_host, ct); if (maxrec && !--maxrec) return; } continue; } /* find associated tty */ for (T = ttylist;; T = T->next) { if (!T) { /* add new one */ T = addtty(bp->ut_line); break; } if (!strncmp(T->tty, bp->ut_line, LINESIZE)) break; } if (TYPE(bp) == SIGNATURE) continue; if (bp->ut_name[0] && want(bp, YES)) { ct = fmttime(bp->ut_timefld, fulltime); printf("%-*.*s %-*.*s %-*.*s %s ", namesz, namesz, bp->ut_name, linesz, linesz, bp->ut_line, hostsz, hostsz, bp->ut_host, ct); if (!T->logout) puts(" still logged in"); else { if (T->logout < 0) { T->logout = -T->logout; printf("- %s", crmsg); } else printf("- %s", fmttime(T->logout, fulltime | TIMEONLY)); delta = T->logout - bp->ut_timefld; if (delta < SECSPERDAY) printf(" (%s)\n", fmttime(delta, fulltime | TIMEONLY | GMT)); else printf(" (%ld+%s)\n", delta / SECSPERDAY, fmttime(delta, fulltime | TIMEONLY | GMT)); } if (maxrec != -1 && !--maxrec) return; } T->logout = bp->ut_timefld; } } fulltime = 1; /* show full time */ crmsg = fmttime(buf[FIRSTVALID].ut_timefld, FULLTIME); if ((ct = strrchr(file, '/')) != NULL) ct++; printf("\n%s begins %s\n", ct ? ct : file, crmsg); }
/* * read through the wtmp file */ void wtmp(void) { time_t delta, total = 0; int timesize, wfd, snapfound = 0; char *ct, *crmsg, tim[40]; struct utmp *bp; struct stat stb; ssize_t bytes; off_t bl; struct ttytab *T; if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) err(1, "%s", file); bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf); if (fulltime) timesize = 8; /* HH:MM:SS */ else timesize = 5; /* HH:MM */ (void)time(&buf[0].ut_time); (void)signal(SIGINT, onintr); (void)signal(SIGQUIT, onintr); while (--bl >= 0) { if (lseek(wfd, bl * sizeof(buf), SEEK_SET) == -1 || (bytes = read(wfd, buf, sizeof(buf))) == -1) err(1, "%s", file); for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) { /* * if the terminal line is '~', the machine stopped. * see utmp(5) for more info. */ if (bp->ut_line[0] == '~' && !bp->ut_line[1]) { /* everybody just logged out */ for (T = ttylist; T; T = T->next) T->logout = -bp->ut_time; currentout = -bp->ut_time; crmsg = strncmp(bp->ut_name, "shutdown", UT_NAMESIZE) ? "crash" : "shutdown"; /* * if we're in snapshot mode, we want to * exit if this shutdown/reboot appears * while we we are tracking the active * range */ if (snaptime && snapfound) { close(wfd); return; } /* * don't print shutdown/reboot entries * unless flagged for */ if (want(bp, NO)) { if (seconds) { snprintf(tim, sizeof tim, "%ld", (long)bp->ut_time); } else { ct = ctime(&bp->ut_time); snprintf(tim, sizeof tim, "%10.10s %*.*s", ct, timesize, timesize, ct + 11); } printf("%-*.*s %-*.*s %-*.*s %s \n", NAME_WIDTH, UT_NAMESIZE, bp->ut_name, UT_LINESIZE, UT_LINESIZE, bp->ut_line, HOST_WIDTH, UT_HOSTSIZE, bp->ut_host, tim); if (maxrec != -1 && !--maxrec) { close(wfd); return; } } continue; } /* * if the line is '{' or '|', date got set; see * utmp(5) for more info. */ if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|') && !bp->ut_line[1]) { if (want(bp, NO)) { if (seconds) { snprintf(tim, sizeof tim, "%ld", (long)bp->ut_time); } else { ct = ctime(&bp->ut_time); snprintf(tim, sizeof tim, "%10.10s %*.*s", ct, timesize, timesize, ct + 11); } printf("%-*.*s %-*.*s %-*.*s %s \n", NAME_WIDTH, UT_NAMESIZE, bp->ut_name, UT_LINESIZE, UT_LINESIZE, bp->ut_line, HOST_WIDTH, UT_HOSTSIZE, bp->ut_host, tim); if (maxrec && !--maxrec) { close(wfd); return; } } continue; } /* find associated tty */ for (T = ttylist;; T = T->next) { if (!T) { /* add new one */ T = addtty(bp->ut_line); break; } if (!strncmp(T->tty, bp->ut_line, UT_LINESIZE)) break; } /* * print record if not in snapshot mode and wanted * or in snapshot mode and in snapshot range */ if (bp->ut_name[0] && ((want(bp, YES)) || (bp->ut_time < snaptime && (T->logout > snaptime || !T->logout || T->logout < 0)))) { snapfound = 1; if (seconds) { snprintf(tim, sizeof tim, "%ld", (long)bp->ut_time); } else { ct = ctime(&bp->ut_time); snprintf(tim, sizeof tim, "%10.10s %*.*s", ct, timesize, timesize, ct + 11); } printf("%-*.*s %-*.*s %-*.*s %s ", NAME_WIDTH, UT_NAMESIZE, bp->ut_name, UT_LINESIZE, UT_LINESIZE, bp->ut_line, HOST_WIDTH, UT_HOSTSIZE, bp->ut_host, tim); if (!T->logout) puts(" still logged in"); else { if (T->logout < 0) { T->logout = -T->logout; printf("- %s", crmsg); } else { if (seconds) printf("- %ld", (long)T->logout); else printf("- %*.*s", timesize, timesize, ctime(&T->logout)+11); } delta = T->logout - bp->ut_time; if (seconds) printf(" (%ld)\n", (long)delta); else { if (delta < SECSPERDAY) printf(" (%*.*s)\n", timesize, timesize, asctime(gmtime(&delta))+11); else printf(" (%ld+%*.*s)\n", delta / SECSPERDAY, timesize, timesize, asctime(gmtime(&delta))+11); } if (calculate) total += delta; } if (maxrec != -1 && !--maxrec) { close(wfd); return; } } T->logout = bp->ut_time; } } close(wfd); if (calculate) { if ((total / SECSPERDAY) > 0) { int days = (total / SECSPERDAY); total -= (days * SECSPERDAY); printf("\nTotal time: %d days, %*.*s\n", days, timesize, timesize, asctime(gmtime(&total))+11); } else printf("\nTotal time: %*.*s\n", timesize, timesize, asctime(gmtime(&total))+11); } ct = ctime(&buf[0].ut_time); printf("\nwtmp begins %10.10s %*.*s %4.4s\n", ct, timesize, timesize, ct + 11, ct + 20); }
/* * wtmp -- * read through the wtmp file */ static void wtmp(void) { register struct utmp *bp; /* current structure */ register TTY *T; /* tty list entry */ long delta; /* time difference */ char *crmsg = NULL; char *ct = NULL; int fd; struct utmp *utl; struct stat st; int utl_len; int listnr = 0; int i; utmpname(file); { #if defined(_HAVE_UT_TV) struct timeval tv; gettimeofday(&tv, NULL); utmpbuf.ut_tv.tv_sec = tv.tv_sec; utmpbuf.ut_tv.tv_usec = tv.tv_usec; #else time_t t; time(&t); utmpbuf.ut_time = t; #endif } (void)signal(SIGINT, onintr); (void)signal(SIGQUIT, onintr); if ((fd = open(file,O_RDONLY)) < 0) exit(1); fstat(fd, &st); utl_len = st.st_size; utl = mmap(NULL, utl_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FILE, fd, 0); if (utl == NULL) exit(1); listnr = utl_len/sizeof(struct utmp); if(listnr) ct = utmp_ctime(&utl[0]); for(i = listnr - 1; i >= 0; i--) { bp = utl+i; /* * if the terminal line is '~', the machine stopped. * see utmp(5) for more info. */ if (!strncmp(bp->ut_line, "~", LMAX)) { /* * utmp(5) also mentions that the user * name should be 'shutdown' or 'reboot'. * Not checking the name causes e.g. runlevel * changes to be displayed as 'crash'. -thaele */ if (!strncmp(bp->ut_user, "reboot", NMAX) || !strncmp(bp->ut_user, "shutdown", NMAX)) { /* everybody just logged out */ for (T = ttylist; T; T = T->next) T->logout = -bp->ut_time; } currentout = -bp->ut_time; crmsg = (strncmp(bp->ut_name, "shutdown", NMAX) ? "crash" : "down "); if (!bp->ut_name[0]) (void)strcpy(bp->ut_name, "reboot"); if (want(bp, NO)) { ct = utmp_ctime(bp); if(bp->ut_type != LOGIN_PROCESS) { print_partial_line(bp); putchar('\n'); } if (maxrec && !--maxrec) return; } continue; } /* find associated tty */ for (T = ttylist;; T = T->next) { if (!T) { /* add new one */ T = addtty(bp->ut_line); break; } if (!strncmp(T->tty, bp->ut_line, LMAX)) break; } if (bp->ut_name[0] && bp->ut_type != LOGIN_PROCESS && bp->ut_type != DEAD_PROCESS && want(bp, YES)) { print_partial_line(bp); if (!T->logout) puts(_(" still logged in")); else { if (T->logout < 0) { T->logout = -T->logout; printf("- %s", crmsg); } else printf("- %5.5s", ctime(&T->logout)+11); delta = T->logout - bp->ut_time; if (delta < SECDAY) printf(" (%5.5s)\n", asctime(gmtime(&delta))+11); else printf(" (%ld+%5.5s)\n", delta / SECDAY, asctime(gmtime(&delta))+11); } if (maxrec != -1 && !--maxrec) return; } T->logout = bp->ut_time; utmpbuf.ut_time = bp->ut_time; } munmap(utl,utl_len); close(fd); if(ct) printf(_("\nwtmp begins %s"), ct); /* ct already ends in \n */ }