Annotation of 43BSDTahoe/ucb/last.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1987 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that the above copyright notice and this paragraph are
        !             7:  * duplicated in all such forms and that any documentation,
        !             8:  * advertising materials, and other materials related to such
        !             9:  * distribution and use acknowledge that the software was developed
        !            10:  * by the University of California, Berkeley.  The name of the
        !            11:  * University may not be used to endorse or promote products derived
        !            12:  * from this software without specific prior written permission.
        !            13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            16:  */
        !            17: 
        !            18: #ifndef lint
        !            19: char copyright[] =
        !            20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
        !            21:  All rights reserved.\n";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #ifndef lint
        !            25: static char sccsid[] = "@(#)last.c     5.11 (Berkeley) 6/29/88";
        !            26: #endif /* not lint */
        !            27: 
        !            28: /*
        !            29:  * last
        !            30:  */
        !            31: #include <sys/param.h>
        !            32: #include <sys/stat.h>
        !            33: #include <sys/file.h>
        !            34: #include <signal.h>
        !            35: #include <time.h>
        !            36: #include <utmp.h>
        !            37: #include <stdio.h>
        !            38: 
        !            39: #define        SECDAY  (24*60*60)                      /* seconds in a day */
        !            40: #define        NO      0                               /* false/no */
        !            41: #define        YES     1                               /* true/yes */
        !            42: 
        !            43: static struct utmp     buf[1024];              /* utmp read buffer */
        !            44: 
        !            45: #define        HMAX    sizeof(buf[0].ut_host)          /* size of utmp host field */
        !            46: #define        LMAX    sizeof(buf[0].ut_line)          /* size of utmp tty field */
        !            47: #define        NMAX    sizeof(buf[0].ut_name)          /* size of utmp name field */
        !            48: 
        !            49: typedef struct arg {
        !            50:        char    *name;                          /* argument */
        !            51: #define        HOST_TYPE       -2
        !            52: #define        TTY_TYPE        -3
        !            53: #define        USER_TYPE       -4
        !            54:        int     type;                           /* type of arg */
        !            55:        struct arg      *next;                  /* linked list pointer */
        !            56: } ARG;
        !            57: ARG    *arglist;                               /* head of linked list */
        !            58: 
        !            59: typedef struct ttytab {
        !            60:        long    logout;                         /* log out time */
        !            61:        char    tty[LMAX + 1];                  /* terminal name */
        !            62:        struct ttytab   *next;                  /* linked list pointer */
        !            63: } TTY;
        !            64: TTY    *ttylist;                               /* head of linked list */
        !            65: 
        !            66: static long    currentout,                     /* current logout value */
        !            67:                maxrec;                         /* records to display */
        !            68: static char    *file = "/usr/adm/wtmp";        /* wtmp file */
        !            69: 
        !            70: main(argc, argv)
        !            71:        int     argc;
        !            72:        char    **argv;
        !            73: {
        !            74:        extern int      optind;
        !            75:        extern char     *optarg;
        !            76:        int     ch;
        !            77:        long    atol();
        !            78:        char    *ttyconv();
        !            79: 
        !            80:        while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF)
        !            81:                switch((char)ch) {
        !            82:                case '0': case '1': case '2': case '3': case '4':
        !            83:                case '5': case '6': case '7': case '8': case '9':
        !            84:                        /*
        !            85:                         * kludge: last was originally designed to take
        !            86:                         * a number after a dash.
        !            87:                         */
        !            88:                        if (!maxrec)
        !            89:                                maxrec = atol(argv[optind - 1] + 1);
        !            90:                        break;
        !            91:                case 'f':
        !            92:                        file = optarg;
        !            93:                        break;
        !            94:                case 'h':
        !            95:                        hostconv(optarg);
        !            96:                        addarg(HOST_TYPE, optarg);
        !            97:                        break;
        !            98:                case 't':
        !            99:                        addarg(TTY_TYPE, ttyconv(optarg));
        !           100:                        break;
        !           101:                case '?':
        !           102:                default:
        !           103:                        fputs("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", stderr);
        !           104:                        exit(1);
        !           105:                }
        !           106:        for (argv += optind; *argv; ++argv) {
        !           107: #define        COMPATIBILITY
        !           108: #ifdef COMPATIBILITY
        !           109:                /* code to allow "last p5" to work */
        !           110:                addarg(TTY_TYPE, ttyconv(*argv));
        !           111: #endif
        !           112:                addarg(USER_TYPE, *argv);
        !           113:        }
        !           114:        wtmp();
        !           115:        exit(0);
        !           116: }
        !           117: 
        !           118: /*
        !           119:  * wtmp --
        !           120:  *     read through the wtmp file
        !           121:  */
        !           122: static
        !           123: wtmp()
        !           124: {
        !           125:        register struct utmp    *bp;            /* current structure */
        !           126:        register TTY    *T;                     /* tty list entry */
        !           127:        struct stat     stb;                    /* stat of file for size */
        !           128:        long    bl, delta,                      /* time difference */
        !           129:                lseek(), time();
        !           130:        int     bytes, wfd,
        !           131:                onintr();
        !           132:        char    *ct, *crmsg,
        !           133:                *asctime(), *ctime(), *strcpy();
        !           134:        TTY     *addtty();
        !           135: 
        !           136:        if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) {
        !           137:                perror(file);
        !           138:                exit(1);
        !           139:        }
        !           140:        bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
        !           141: 
        !           142:        (void)time(&buf[0].ut_time);
        !           143:        (void)signal(SIGINT, onintr);
        !           144:        (void)signal(SIGQUIT, onintr);
        !           145: 
        !           146:        while (--bl >= 0) {
        !           147:                if (lseek(wfd, (long)(bl * sizeof(buf)), L_SET) == -1 ||
        !           148:                    (bytes = read(wfd, (char *)buf, sizeof(buf))) == -1) {
        !           149:                        fprintf(stderr, "last: %s: ", file);
        !           150:                        perror((char *)NULL);
        !           151:                        exit(1);
        !           152:                }
        !           153:                for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
        !           154:                        /*
        !           155:                         * if the terminal line is '~', the machine stopped.
        !           156:                         * see utmp(5) for more info.
        !           157:                         */
        !           158:                        if (!strncmp(bp->ut_line, "~", LMAX)) {
        !           159:                                /* everybody just logged out */
        !           160:                                for (T = ttylist; T; T = T->next)
        !           161:                                        T->logout = -bp->ut_time;
        !           162:                                currentout = -bp->ut_time;
        !           163:                                crmsg = strncmp(bp->ut_name, "shutdown", NMAX) ? "crash" : "down ";
        !           164:                                if (!bp->ut_name[0])
        !           165:                                        (void)strcpy(bp->ut_name, "reboot");
        !           166:                                if (want(bp, NO)) {
        !           167:                                        ct = ctime(&bp->ut_time);
        !           168:                                        printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11);
        !           169:                                        if (maxrec && !--maxrec)
        !           170:                                                return;
        !           171:                                }
        !           172:                                continue;
        !           173:                        }
        !           174:                        /* find associated tty */
        !           175:                        for (T = ttylist;; T = T->next) {
        !           176:                                if (!T) {
        !           177:                                        /* add new one */
        !           178:                                        T = addtty(bp->ut_line);
        !           179:                                        break;
        !           180:                                }
        !           181:                                if (!strncmp(T->tty, bp->ut_line, LMAX))
        !           182:                                        break;
        !           183:                        }
        !           184:                        if (bp->ut_name[0] && want(bp, YES)) {
        !           185:                                ct = ctime(&bp->ut_time);
        !           186:                                printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s ", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11);
        !           187:                                if (!T->logout)
        !           188:                                        puts("  still logged in");
        !           189:                                else {
        !           190:                                        if (T->logout < 0) {
        !           191:                                                T->logout = -T->logout;
        !           192:                                                printf("- %s", crmsg);
        !           193:                                        }
        !           194:                                        else
        !           195:                                                printf("- %5.5s", ctime(&T->logout)+11);
        !           196:                                        delta = T->logout - bp->ut_time;
        !           197:                                        if (delta < SECDAY)
        !           198:                                                printf("  (%5.5s)\n", asctime(gmtime(&delta))+11);
        !           199:                                        else
        !           200:                                                printf(" (%ld+%5.5s)\n", delta / SECDAY, asctime(gmtime(&delta))+11);
        !           201:                                }
        !           202:                                if (maxrec != -1 && !--maxrec)
        !           203:                                        return;
        !           204:                        }
        !           205:                        T->logout = bp->ut_time;
        !           206:                }
        !           207:        }
        !           208:        ct = ctime(&buf[0].ut_time);
        !           209:        printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
        !           210: }
        !           211: 
        !           212: /*
        !           213:  * want --
        !           214:  *     see if want this entry
        !           215:  */
        !           216: static
        !           217: want(bp, check)
        !           218:        register struct utmp    *bp;
        !           219:        int     check;
        !           220: {
        !           221:        register ARG    *step;
        !           222: 
        !           223:        if (check)
        !           224:                /*
        !           225:                 * when uucp and ftp log in over a network, the entry in
        !           226:                 * the utmp file is the name plus their process id.  See
        !           227:                 * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
        !           228:                 */
        !           229:                if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
        !           230:                        bp->ut_line[3] = '\0';
        !           231:                else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
        !           232:                        bp->ut_line[4] = '\0';
        !           233:        if (!arglist)
        !           234:                return(YES);
        !           235: 
        !           236:        for (step = arglist; step; step = step->next)
        !           237:                switch(step->type) {
        !           238:                case HOST_TYPE:
        !           239:                        if (!strncasecmp(step->name, bp->ut_host, HMAX))
        !           240:                                return(YES);
        !           241:                        break;
        !           242:                case TTY_TYPE:
        !           243:                        if (!strncmp(step->name, bp->ut_line, LMAX))
        !           244:                                return(YES);
        !           245:                        break;
        !           246:                case USER_TYPE:
        !           247:                        if (!strncmp(step->name, bp->ut_name, NMAX))
        !           248:                                return(YES);
        !           249:                        break;
        !           250:        }
        !           251:        return(NO);
        !           252: }
        !           253: 
        !           254: /*
        !           255:  * addarg --
        !           256:  *     add an entry to a linked list of arguments
        !           257:  */
        !           258: static
        !           259: addarg(type, arg)
        !           260:        int     type;
        !           261:        char    *arg;
        !           262: {
        !           263:        register ARG    *cur;
        !           264:        char    *malloc();
        !           265: 
        !           266:        if (!(cur = (ARG *)malloc((u_int)sizeof(ARG)))) {
        !           267:                fputs("last: malloc failure.\n", stderr);
        !           268:                exit(1);
        !           269:        }
        !           270:        cur->next = arglist;
        !           271:        cur->type = type;
        !           272:        cur->name = arg;
        !           273:        arglist = cur;
        !           274: }
        !           275: 
        !           276: /*
        !           277:  * addtty --
        !           278:  *     add an entry to a linked list of ttys
        !           279:  */
        !           280: static TTY *
        !           281: addtty(ttyname)
        !           282:        char    *ttyname;
        !           283: {
        !           284:        register TTY    *cur;
        !           285:        char    *malloc();
        !           286: 
        !           287:        if (!(cur = (TTY *)malloc((u_int)sizeof(TTY)))) {
        !           288:                fputs("last: malloc failure.\n", stderr);
        !           289:                exit(1);
        !           290:        }
        !           291:        cur->next = ttylist;
        !           292:        cur->logout = currentout;
        !           293:        bcopy(ttyname, cur->tty, LMAX);
        !           294:        return(ttylist = cur);
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * hostconv --
        !           299:  *     convert the hostname to search pattern; if the supplied host name
        !           300:  *     has a domain attached that is the same as the current domain, rip
        !           301:  *     off the domain suffix since that's what login(1) does.
        !           302:  */
        !           303: static
        !           304: hostconv(arg)
        !           305:        char    *arg;
        !           306: {
        !           307:        static int      first = 1;
        !           308:        static char     *hostdot,
        !           309:                        name[MAXHOSTNAMELEN];
        !           310:        char    *argdot, *index();
        !           311: 
        !           312:        if (!(argdot = index(arg, '.')))
        !           313:                return;
        !           314:        if (first) {
        !           315:                first = 0;
        !           316:                if (gethostname(name, sizeof(name))) {
        !           317:                        perror("last: gethostname");
        !           318:                        exit(1);
        !           319:                }
        !           320:                hostdot = index(name, '.');
        !           321:        }
        !           322:        if (hostdot && !strcasecmp(hostdot, argdot))
        !           323:                *argdot = '\0';
        !           324: }
        !           325: 
        !           326: /*
        !           327:  * ttyconv --
        !           328:  *     convert tty to correct name.
        !           329:  */
        !           330: static char *
        !           331: ttyconv(arg)
        !           332:        char    *arg;
        !           333: {
        !           334:        char    *mval,
        !           335:                *malloc(), *strcpy();
        !           336: 
        !           337:        /*
        !           338:         * kludge -- we assume that all tty's end with
        !           339:         * a two character suffix.
        !           340:         */
        !           341:        if (strlen(arg) == 2) {
        !           342:                /* either 6 for "ttyxx" or 8 for "console" */
        !           343:                if (!(mval = malloc((u_int)8))) {
        !           344:                        fputs("last: malloc failure.\n", stderr);
        !           345:                        exit(1);
        !           346:                }
        !           347:                if (!strcmp(arg, "co"))
        !           348:                        (void)strcpy(mval, "console");
        !           349:                else {
        !           350:                        (void)strcpy(mval, "tty");
        !           351:                        (void)strcpy(mval + 3, arg);
        !           352:                }
        !           353:                return(mval);
        !           354:        }
        !           355:        if (!strncmp(arg, "/dev/", sizeof("/dev/") - 1))
        !           356:                return(arg + 5);
        !           357:        return(arg);
        !           358: }
        !           359: 
        !           360: /*
        !           361:  * onintr --
        !           362:  *     on interrupt, we inform the user how far we've gotten
        !           363:  */
        !           364: static
        !           365: onintr(signo)
        !           366:        int     signo;
        !           367: {
        !           368:        char    *ct, *ctime();
        !           369: 
        !           370:        ct = ctime(&buf[0].ut_time);
        !           371:        printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
        !           372:        if (signo == SIGINT)
        !           373:                exit(1);
        !           374:        (void)fflush(stdout);                   /* fix required for rsh */
        !           375: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.