|
|
1.1 ! root 1: static char *sccsid = "@(#)last.c 4.2 (Berkeley) 10/9/80"; ! 2: /* ! 3: * last ! 4: */ ! 5: #include <sys/types.h> ! 6: #include <stdio.h> ! 7: #include <signal.h> ! 8: #include <stat.h> ! 9: #include <utmp.h> ! 10: ! 11: #define NMAX sizeof(buf[0].ut_name) ! 12: #define LMAX sizeof(buf[0].ut_line) ! 13: #define SECDAY (24*60*60) ! 14: ! 15: #define lineq(a,b) (!strncmp(a,b,LMAX)) ! 16: #define nameq(a,b) (!strncmp(a,b,NMAX)) ! 17: ! 18: #define MAXTTYS 256 ! 19: ! 20: char **argv; ! 21: int argc; ! 22: ! 23: struct utmp buf[128]; ! 24: char ttnames[MAXTTYS][LMAX+1]; ! 25: long logouts[MAXTTYS]; ! 26: ! 27: char *ctime(), *strspl(); ! 28: int onintr(); ! 29: ! 30: main(ac, av) ! 31: char **av; ! 32: { ! 33: register int i, k; ! 34: int bl, wtmp; ! 35: char *ct; ! 36: register struct utmp *bp; ! 37: long otime; ! 38: struct stat stb; ! 39: int print; ! 40: ! 41: time(&buf[0].ut_time); ! 42: ac--, av++; ! 43: argc = ac; ! 44: argv = av; ! 45: for (i = 0; i < argc; i++) { ! 46: if (strlen(argv[i])>2) ! 47: continue; ! 48: if (!strcmp(argv[i], "~")) ! 49: continue; ! 50: if (getpwnam(argv[i])) ! 51: continue; ! 52: argv[i] = strspl("tty", argv[i]); ! 53: } ! 54: wtmp = open("/usr/adm/wtmp", 0); ! 55: if (wtmp < 0) { ! 56: perror("/usr/adm/wtmp"); ! 57: exit(1); ! 58: } ! 59: fstat(wtmp, &stb); ! 60: bl = (stb.st_size + sizeof (buf)-1) / sizeof (buf); ! 61: if (signal(SIGINT, SIG_IGN) != SIG_IGN) { ! 62: signal(SIGINT, onintr); ! 63: signal(SIGQUIT, onintr); ! 64: } ! 65: for (bl--; bl >= 0; bl--) { ! 66: lseek(wtmp, bl * sizeof (buf), 0); ! 67: bp = &buf[read(wtmp, buf, sizeof (buf)) / sizeof(buf[0]) - 1]; ! 68: for ( ; bp >= buf; bp--) { ! 69: print = want(bp); ! 70: if (print) { ! 71: ct = ctime(&bp->ut_time); ! 72: printf("%-*.*s %-*.*s %10.10s %5.5s ", ! 73: NMAX, NMAX, bp->ut_name, ! 74: LMAX, LMAX, bp->ut_line, ct, 11+ct); ! 75: } ! 76: for (i = 0; i < MAXTTYS; i++) { ! 77: if (ttnames[i][0] == 0) { ! 78: strncpy(ttnames[i], bp->ut_line, ! 79: sizeof(bp->ut_line)); ! 80: otime = logouts[i]; ! 81: logouts[i] = bp->ut_time; ! 82: break; ! 83: } ! 84: if (lineq(ttnames[i], bp->ut_line)) { ! 85: otime = logouts[i]; ! 86: logouts[i] = bp->ut_time; ! 87: break; ! 88: } ! 89: } ! 90: if (print) { ! 91: if (otime == 0) ! 92: printf(" still logged in\n"); ! 93: else { ! 94: long delta; ! 95: if (otime < 0) { ! 96: otime = -otime; ! 97: printf("- crash"); ! 98: } else ! 99: printf("- %5.5s", ! 100: ctime(&otime)+11); ! 101: delta = otime - bp->ut_time; ! 102: if (delta < SECDAY) ! 103: printf(" (%5.5s)\n", ! 104: asctime(gmtime(&delta))+11); ! 105: else ! 106: printf(" (%ld+%5.5s)\n", ! 107: delta / SECDAY, ! 108: asctime(gmtime(&delta))+11); ! 109: } ! 110: fflush(stdout); ! 111: } ! 112: if (!strcmp(bp->ut_name, "reboot")) ! 113: for (i = 0; i < MAXTTYS; i++) ! 114: logouts[i] = -bp->ut_time; ! 115: } ! 116: } ! 117: ct = ctime(&buf[0].ut_time); ! 118: printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11); ! 119: exit(0); ! 120: } ! 121: ! 122: onintr(signo) ! 123: int signo; ! 124: { ! 125: char *ct; ! 126: ! 127: if (signo == SIGQUIT) ! 128: signal(SIGQUIT, onintr); ! 129: ct = ctime(&buf[0].ut_time); ! 130: printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11); ! 131: if (signo == SIGINT) ! 132: exit(1); ! 133: } ! 134: ! 135: want(bp) ! 136: struct utmp *bp; ! 137: { ! 138: register char **av; ! 139: register int ac; ! 140: ! 141: if (bp->ut_line[0] == '~') ! 142: strcpy(bp->ut_name, "reboot"); /* bandaid */ ! 143: if (bp->ut_name[0] == 0) ! 144: return (0); ! 145: if (argc == 0) ! 146: return (1); ! 147: av = argv; ! 148: for (ac = 0; ac < argc; ac++) { ! 149: if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line)) ! 150: return (1); ! 151: av++; ! 152: } ! 153: return (0); ! 154: } ! 155: ! 156: char * ! 157: strspl(left, right) ! 158: char *left, *right; ! 159: { ! 160: char *res = (char *)malloc(strlen(left)+strlen(right)+1); ! 161: ! 162: strcpy(res, left); ! 163: strcat(res, right); ! 164: return (res); ! 165: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.