1 static char *sccsid = "@(#)last.c 4.1 (Berkeley) 10/01/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 = 0; 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 (lineq(bp->ut_line, "~") || 113 lineq(bp->ut_line, "tty~")) 114 for (i = 0; *ttnames[i] && i < MAXTTYS; i++) 115 logouts[i] = -bp->ut_time; 116 } 117 } 118 ct = ctime(&buf[0].ut_time); 119 printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11); 120 exit(0); 121 } 122 123 onintr(signo) 124 int signo; 125 { 126 char *ct; 127 128 if (signo == SIGQUIT) 129 signal(SIGQUIT, onintr); 130 ct = ctime(&buf[0].ut_time); 131 printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11); 132 if (signo == SIGINT) 133 exit(1); 134 } 135 136 want(bp) 137 struct utmp *bp; 138 { 139 register char **av; 140 register int ac; 141 142 if (bp->ut_line[0] == '~') 143 strcpy(bp->ut_name, "reboot"); /* bandaid */ 144 if (bp->ut_name[0] == 0) 145 return (0); 146 if (argc == 0) 147 return (1); 148 av = argv; 149 for (ac = 0; ac < argc; ac++) { 150 if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line)) 151 return (1); 152 av++; 153 } 154 return (0); 155 } 156 157 char * 158 strspl(left, right) 159 char *left, *right; 160 { 161 char *res = (char *)malloc(strlen(left)+strlen(right)+1); 162 163 strcpy(res, left); 164 strcat(res, right); 165 return (res); 166 } 167