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 ((long)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 wtmp; 53: off_t bl; 54: char *ct; 55: char wtmpfile[256]; 56: char progname[256]; 57: register struct utmp *bp; 58: long otime; 59: struct stat stb; 60: int print; 61: int sinput = 0; 62: char * crmsg = (char *)0; 63: long crtime; 64: long outrec = 0; 65: long maxrec = 0x7fffffffL; 66: 67: time(&buf[0].ut_time); 68: strcpy(wtmpfile,"/usr/adm/wtmp"); 69: strcpy(progname,av[0]); 70: ac--, av++; 71: nameargs = argc = ac; 72: argv = av; 73: for (i = 0; i < argc; i++) { 74: if (argv[i][0] == '-' ) { 75: if ( argv[i][1] >= '0' && argv[i][1] <= '9') { 76: maxrec = atoi(argv[i]+1); 77: nameargs--; 78: continue; 79: } else { 80: if (argv[i][1] == 'f') { 81: i++; 82: if ( i < argc) { 83: strcpy(wtmpfile,argv[i]); 84: nameargs = nameargs -2; 85: continue; 86: } else { 87: usage(progname); 88: } 89: } else { 90: usage(progname); 91: } 92: } 93: } 94: if (strlen(argv[i])>2) 95: continue; 96: if (!strcmp(argv[i], "~")) 97: continue; 98: if (!strcmp(argv[i], "ftp")) 99: continue; 100: if (!strcmp(argv[i], "uucp")) 101: continue; 102: if (getpwnam(argv[i])) 103: continue; 104: argv[i] = strspl("tty", argv[i]); 105: } 106: wtmp = open(wtmpfile, 0); 107: if (wtmp < 0) { 108: perror(wtmpfile); 109: exit(1); 110: } 111: fstat(wtmp, &stb); 112: bl = (stb.st_size + sizeof (buf)-1) / sizeof (buf); 113: if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 114: signal(SIGINT, onintr); 115: signal(SIGQUIT, onintr); 116: } 117: for (bl--; bl >= 0; bl--) { 118: lseek(wtmp, bl * sizeof (buf), 0); 119: bp = &buf[read(wtmp, buf, sizeof (buf)) / sizeof(buf[0]) - 1]; 120: for ( ; bp >= buf; bp--) { 121: print = want(bp); 122: if (print) { 123: ct = ctime(&bp->ut_time); 124: printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ", 125: NMAX, NMAX, bp->ut_name, 126: LMAX, LMAX, bp->ut_line, 127: HMAX, HMAX, bp->ut_host, 128: ct, 11+ct); 129: } 130: for (i = 0; i < MAXTTYS; i++) { 131: if (ttnames[i][0] == 0) { 132: strncpy(ttnames[i], bp->ut_line, 133: sizeof(bp->ut_line)); 134: otime = logouts[i]; 135: logouts[i] = bp->ut_time; 136: break; 137: } 138: if (lineq(ttnames[i], bp->ut_line)) { 139: otime = logouts[i]; 140: logouts[i] = bp->ut_time; 141: break; 142: } 143: } 144: if (print) { 145: if (lineq(bp->ut_line, "~")) 146: printf("\n"); 147: else if (otime == 0) 148: printf(" still logged in\n"); 149: else { 150: long delta; 151: if (otime < 0) { 152: otime = -otime; 153: printf("- %s", crmsg); 154: } else 155: printf("- %5.5s", 156: ctime(&otime)+11); 157: delta = otime - bp->ut_time; 158: if (delta < SECDAY) 159: printf(" (%5.5s)\n", 160: asctime(gmtime(&delta))+11); 161: else 162: printf(" (%ld+%5.5s)\n", 163: delta / SECDAY, 164: asctime(gmtime(&delta))+11); 165: } 166: fflush(stdout); 167: if (++outrec >= maxrec) 168: exit(0); 169: } 170: if (lineq(bp->ut_line, "~")) { 171: for (i = 0; i < MAXTTYS; i++) 172: logouts[i] = -bp->ut_time; 173: if (nameq(bp->ut_name, "shutdown")) 174: crmsg = "down "; 175: else 176: crmsg = "crash"; 177: } 178: } 179: } 180: ct = ctime(&buf[0].ut_time); 181: printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11); 182: exit(0); 183: } 184: 185: onintr(signo) 186: int signo; 187: { 188: char *ct; 189: 190: if (signo == SIGQUIT) 191: signal(SIGQUIT, onintr); 192: ct = ctime(&buf[0].ut_time); 193: printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11); 194: fflush(stdout); 195: if (signo == SIGINT) 196: exit(1); 197: } 198: 199: want(bp) 200: struct utmp *bp; 201: { 202: register char **av; 203: register int ac; 204: 205: if (bp->ut_line[0] == '~' && bp->ut_name[0] == '\0') 206: strcpy(bp->ut_name, "reboot"); /* bandaid */ 207: if (strncmp(bp->ut_line, "ftp", 3) == 0) 208: bp->ut_line[3] = '\0'; 209: if (strncmp(bp->ut_line, "uucp", 4) == 0) 210: bp->ut_line[4] = '\0'; 211: if (bp->ut_name[0] == 0) 212: return (0); 213: if (nameargs == 0) 214: return (1); 215: av = argv; 216: for (ac = 0; ac < argc; ac++, av++) { 217: if (av[0][0] == '-') 218: continue; 219: if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line)) 220: return (1); 221: } 222: return (0); 223: } 224: 225: char * 226: strspl(left, right) 227: char *left, *right; 228: { 229: char *res = (char *)malloc(strlen(left)+strlen(right)+1); 230: 231: strcpy(res, left); 232: strcat(res, right); 233: return (res); 234: } 235: 236: void 237: usage(progname) 238: char *progname; 239: { 240: printf("Usage: %s [ -f filename ] [-number] [name...] [tty...]\n", 241: progname); 242: exit(1); 243: }