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