1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)last.c 5.3 (Berkeley) 5/15/86"; 15: #endif not lint 16: 17: /* 18: * last 19: */ 20: #include <sys/types.h> 21: #include <stdio.h> 22: #include <signal.h> 23: #include <sys/stat.h> 24: #include <utmp.h> 25: 26: #define NMAX sizeof(buf[0].ut_name) 27: #define LMAX sizeof(buf[0].ut_line) 28: #define HMAX sizeof(buf[0].ut_host) 29: #define SECDAY (24*60*60) 30: 31: #define lineq(a,b) (!strncmp(a,b,LMAX)) 32: #define nameq(a,b) (!strncmp(a,b,NMAX)) 33: #define hosteq(a,b) (!strncmp(a,b,HMAX)) 34: 35: #define MAXTTYS 256 36: 37: char **argv; 38: int argc; 39: int nameargs; 40: 41: struct utmp buf[128]; 42: char ttnames[MAXTTYS][LMAX+1]; 43: long logouts[MAXTTYS]; 44: 45: char *ctime(), *strspl(); 46: int onintr(); 47: 48: main(ac, av) 49: char **av; 50: { 51: register int i, k; 52: int bl, wtmp; 53: char *ct; 54: register struct utmp *bp; 55: long otime; 56: struct stat stb; 57: int print; 58: char * crmsg = (char *)0; 59: long crtime; 60: long outrec = 0; 61: long maxrec = 0x7fffffffL; 62: 63: time(&buf[0].ut_time); 64: ac--, av++; 65: nameargs = argc = ac; 66: argv = av; 67: for (i = 0; i < argc; i++) { 68: if (argv[i][0] == '-' && 69: argv[i][1] >= '0' && argv[i][1] <= '9') { 70: maxrec = atoi(argv[i]+1); 71: nameargs--; 72: continue; 73: } 74: if (strlen(argv[i])>2) 75: continue; 76: if (!strcmp(argv[i], "~")) 77: continue; 78: if (!strcmp(argv[i], "ftp")) 79: continue; 80: if (!strcmp(argv[i], "uucp")) 81: continue; 82: if (getpwnam(argv[i])) 83: continue; 84: argv[i] = strspl("tty", argv[i]); 85: } 86: wtmp = open("/usr/adm/wtmp", 0); 87: if (wtmp < 0) { 88: perror("/usr/adm/wtmp"); 89: exit(1); 90: } 91: fstat(wtmp, &stb); 92: bl = (stb.st_size + sizeof (buf)-1) / sizeof (buf); 93: if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 94: signal(SIGINT, onintr); 95: signal(SIGQUIT, onintr); 96: } 97: for (bl--; bl >= 0; bl--) { 98: lseek(wtmp, bl * sizeof (buf), 0); 99: bp = &buf[read(wtmp, buf, sizeof (buf)) / sizeof(buf[0]) - 1]; 100: for ( ; bp >= buf; bp--) { 101: print = want(bp); 102: if (print) { 103: ct = ctime(&bp->ut_time); 104: printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ", 105: NMAX, NMAX, bp->ut_name, 106: LMAX, LMAX, bp->ut_line, 107: HMAX, HMAX, bp->ut_host, 108: ct, 11+ct); 109: } 110: for (i = 0; i < MAXTTYS; i++) { 111: if (ttnames[i][0] == 0) { 112: strncpy(ttnames[i], bp->ut_line, 113: sizeof(bp->ut_line)); 114: otime = logouts[i]; 115: logouts[i] = bp->ut_time; 116: break; 117: } 118: if (lineq(ttnames[i], bp->ut_line)) { 119: otime = logouts[i]; 120: logouts[i] = bp->ut_time; 121: break; 122: } 123: } 124: if (print) { 125: if (lineq(bp->ut_line, "~")) 126: printf("\n"); 127: else if (otime == 0) 128: printf(" still logged in\n"); 129: else { 130: long delta; 131: if (otime < 0) { 132: otime = -otime; 133: printf("- %s", crmsg); 134: } else 135: printf("- %5.5s", 136: ctime(&otime)+11); 137: delta = otime - bp->ut_time; 138: if (delta < SECDAY) 139: printf(" (%5.5s)\n", 140: asctime(gmtime(&delta))+11); 141: else 142: printf(" (%ld+%5.5s)\n", 143: delta / SECDAY, 144: asctime(gmtime(&delta))+11); 145: } 146: fflush(stdout); 147: if (++outrec >= maxrec) 148: exit(0); 149: } 150: if (lineq(bp->ut_line, "~")) { 151: for (i = 0; i < MAXTTYS; i++) 152: logouts[i] = -bp->ut_time; 153: if (nameq(bp->ut_name, "shutdown")) 154: crmsg = "down "; 155: else 156: crmsg = "crash"; 157: } 158: } 159: } 160: ct = ctime(&buf[0].ut_time); 161: printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11); 162: exit(0); 163: } 164: 165: onintr(signo) 166: int signo; 167: { 168: char *ct; 169: 170: if (signo == SIGQUIT) 171: signal(SIGQUIT, onintr); 172: ct = ctime(&buf[0].ut_time); 173: printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11); 174: fflush(stdout); 175: if (signo == SIGINT) 176: exit(1); 177: } 178: 179: want(bp) 180: struct utmp *bp; 181: { 182: register char **av; 183: register int ac; 184: 185: if (bp->ut_line[0] == '~' && bp->ut_name[0] == '\0') 186: strcpy(bp->ut_name, "reboot"); /* bandaid */ 187: if (strncmp(bp->ut_line, "ftp", 3) == 0) 188: bp->ut_line[3] = '\0'; 189: if (strncmp(bp->ut_line, "uucp", 4) == 0) 190: bp->ut_line[4] = '\0'; 191: if (bp->ut_name[0] == 0) 192: return (0); 193: if (nameargs == 0) 194: return (1); 195: av = argv; 196: for (ac = 0; ac < argc; ac++, av++) { 197: if (av[0][0] == '-') 198: continue; 199: if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line)) 200: return (1); 201: } 202: return (0); 203: } 204: 205: char * 206: strspl(left, right) 207: char *left, *right; 208: { 209: char *res = (char *)malloc(strlen(left)+strlen(right)+1); 210: 211: strcpy(res, left); 212: strcat(res, right); 213: return (res); 214: }