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: }

Defined functions

main defined in line 48; never used
onintr defined in line 185; used 4 times
strspl defined in line 225; used 2 times
usage defined in line 236; used 2 times
want defined in line 199; used 1 times

Defined variables

argc defined in line 38; used 4 times
argv defined in line 37; used 15 times
buf defined in line 41; used 14 times
copyright defined in line 8; never used
logouts defined in line 43; used 5 times
nameargs defined in line 39; used 5 times
sccsid defined in line 14; never used
ttnames defined in line 42; used 3 times

Defined macros

HMAX defined in line 28; used 3 times
LMAX defined in line 27; used 4 times
MAXTTYS defined in line 35; used 4 times
NMAX defined in line 26; used 3 times
SECDAY defined in line 29; used 2 times
hosteq defined in line 33; never used
lineq defined in line 31; used 4 times
nameq defined in line 32; used 2 times
Last modified: 1993-01-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1087
Valid CSS Valid XHTML 1.0 Strict