[BACK]Return to last.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / last

Annotation of src/usr.bin/last/last.c, Revision 1.1

1.1     ! deraadt     1: /*     $NetBSD: last.c,v 1.6 1994/12/24 16:49:02 cgd Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1987, 1993, 1994
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by the University of
        !            18:  *     California, Berkeley and its contributors.
        !            19:  * 4. Neither the name of the University nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  */
        !            35:
        !            36: #ifndef lint
        !            37: static char copyright[] =
        !            38: "@(#) Copyright (c) 1987, 1993, 1994\n\
        !            39:        The Regents of the University of California.  All rights reserved.\n";
        !            40: #endif /* not lint */
        !            41:
        !            42: #ifndef lint
        !            43: #if 0
        !            44: static char sccsid[] = "@(#)last.c     8.2 (Berkeley) 4/2/94";
        !            45: #endif
        !            46: static char rcsid[] = "$NetBSD: last.c,v 1.6 1994/12/24 16:49:02 cgd Exp $";
        !            47: #endif /* not lint */
        !            48:
        !            49: #include <sys/param.h>
        !            50: #include <sys/stat.h>
        !            51:
        !            52: #include <err.h>
        !            53: #include <fcntl.h>
        !            54: #include <paths.h>
        !            55: #include <signal.h>
        !            56: #include <stdio.h>
        !            57: #include <stdlib.h>
        !            58: #include <string.h>
        !            59: #include <time.h>
        !            60: #include <tzfile.h>
        !            61: #include <unistd.h>
        !            62: #include <utmp.h>
        !            63:
        !            64: #define        NO      0                               /* false/no */
        !            65: #define        YES     1                               /* true/yes */
        !            66:
        !            67: static struct utmp     buf[1024];              /* utmp read buffer */
        !            68:
        !            69: typedef struct arg {
        !            70:        char    *name;                          /* argument */
        !            71: #define        HOST_TYPE       -2
        !            72: #define        TTY_TYPE        -3
        !            73: #define        USER_TYPE       -4
        !            74:        int     type;                           /* type of arg */
        !            75:        struct arg      *next;                  /* linked list pointer */
        !            76: } ARG;
        !            77: ARG    *arglist;                               /* head of linked list */
        !            78:
        !            79: typedef struct ttytab {
        !            80:        time_t  logout;                         /* log out time */
        !            81:        char    tty[UT_LINESIZE + 1];           /* terminal name */
        !            82:        struct ttytab   *next;                  /* linked list pointer */
        !            83: } TTY;
        !            84: TTY    *ttylist;                               /* head of linked list */
        !            85:
        !            86: static time_t  currentout;                     /* current logout value */
        !            87: static long    maxrec;                         /* records to display */
        !            88: static char    *file = _PATH_WTMP;             /* wtmp file */
        !            89:
        !            90: void    addarg __P((int, char *));
        !            91: TTY    *addtty __P((char *));
        !            92: void    hostconv __P((char *));
        !            93: void    onintr __P((int));
        !            94: char   *ttyconv __P((char *));
        !            95: int     want __P((struct utmp *, int));
        !            96: void    wtmp __P((void));
        !            97:
        !            98: int
        !            99: main(argc, argv)
        !           100:        int argc;
        !           101:        char *argv[];
        !           102: {
        !           103:        extern int optind;
        !           104:        extern char *optarg;
        !           105:        int ch;
        !           106:        char *p;
        !           107:
        !           108:        maxrec = -1;
        !           109:        while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF)
        !           110:                switch (ch) {
        !           111:                case '0': case '1': case '2': case '3': case '4':
        !           112:                case '5': case '6': case '7': case '8': case '9':
        !           113:                        /*
        !           114:                         * kludge: last was originally designed to take
        !           115:                         * a number after a dash.
        !           116:                         */
        !           117:                        if (maxrec == -1) {
        !           118:                                p = argv[optind - 1];
        !           119:                                if (p[0] == '-' && p[1] == ch && !p[2])
        !           120:                                        maxrec = atol(++p);
        !           121:                                else
        !           122:                                        maxrec = atol(argv[optind] + 1);
        !           123:                                if (!maxrec)
        !           124:                                        exit(0);
        !           125:                        }
        !           126:                        break;
        !           127:                case 'f':
        !           128:                        file = optarg;
        !           129:                        break;
        !           130:                case 'h':
        !           131:                        hostconv(optarg);
        !           132:                        addarg(HOST_TYPE, optarg);
        !           133:                        break;
        !           134:                case 't':
        !           135:                        addarg(TTY_TYPE, ttyconv(optarg));
        !           136:                        break;
        !           137:                case '?':
        !           138:                default:
        !           139:                        (void)fprintf(stderr,
        !           140:        "usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n");
        !           141:                        exit(1);
        !           142:                }
        !           143:
        !           144:        if (argc) {
        !           145:                setlinebuf(stdout);
        !           146:                for (argv += optind; *argv; ++argv) {
        !           147: #define        COMPATIBILITY
        !           148: #ifdef COMPATIBILITY
        !           149:                        /* code to allow "last p5" to work */
        !           150:                        addarg(TTY_TYPE, ttyconv(*argv));
        !           151: #endif
        !           152:                        addarg(USER_TYPE, *argv);
        !           153:                }
        !           154:        }
        !           155:        wtmp();
        !           156:        exit(0);
        !           157: }
        !           158:
        !           159: /*
        !           160:  * wtmp --
        !           161:  *     read through the wtmp file
        !           162:  */
        !           163: void
        !           164: wtmp()
        !           165: {
        !           166:        struct utmp     *bp;                    /* current structure */
        !           167:        TTY     *T;                             /* tty list entry */
        !           168:        struct stat     stb;                    /* stat of file for size */
        !           169:        time_t  bl, delta;                      /* time difference */
        !           170:        int     bytes, wfd;
        !           171:        char    *ct, *crmsg;
        !           172:
        !           173:        if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1)
        !           174:                err(1, "%s", file);
        !           175:        bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
        !           176:
        !           177:        (void)time(&buf[0].ut_time);
        !           178:        (void)signal(SIGINT, onintr);
        !           179:        (void)signal(SIGQUIT, onintr);
        !           180:
        !           181:        while (--bl >= 0) {
        !           182:                if (lseek(wfd, (off_t)(bl * sizeof(buf)), L_SET) == -1 ||
        !           183:                    (bytes = read(wfd, buf, sizeof(buf))) == -1)
        !           184:                        err(1, "%s", file);
        !           185:                for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
        !           186:                        /*
        !           187:                         * if the terminal line is '~', the machine stopped.
        !           188:                         * see utmp(5) for more info.
        !           189:                         */
        !           190:                        if (bp->ut_line[0] == '~' && !bp->ut_line[1]) {
        !           191:                                /* everybody just logged out */
        !           192:                                for (T = ttylist; T; T = T->next)
        !           193:                                        T->logout = -bp->ut_time;
        !           194:                                currentout = -bp->ut_time;
        !           195:                                crmsg = strncmp(bp->ut_name, "shutdown",
        !           196:                                    UT_NAMESIZE) ? "crash" : "shutdown";
        !           197:                                if (want(bp, NO)) {
        !           198:                                        ct = ctime(&bp->ut_time);
        !           199:                                printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n",
        !           200:                                            UT_NAMESIZE, UT_NAMESIZE,
        !           201:                                            bp->ut_name, UT_LINESIZE,
        !           202:                                            UT_LINESIZE, bp->ut_line,
        !           203:                                            UT_HOSTSIZE, UT_HOSTSIZE,
        !           204:                                            bp->ut_host, ct, ct + 11);
        !           205:                                        if (maxrec != -1 && !--maxrec)
        !           206:                                                return;
        !           207:                                }
        !           208:                                continue;
        !           209:                        }
        !           210:                        /*
        !           211:                         * if the line is '{' or '|', date got set; see
        !           212:                         * utmp(5) for more info.
        !           213:                         */
        !           214:                        if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|')
        !           215:                            && !bp->ut_line[1]) {
        !           216:                                if (want(bp, NO)) {
        !           217:                                        ct = ctime(&bp->ut_time);
        !           218:                                printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n",
        !           219:                                    UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
        !           220:                                    UT_LINESIZE, UT_LINESIZE, bp->ut_line,
        !           221:                                    UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
        !           222:                                    ct, ct + 11);
        !           223:                                        if (maxrec && !--maxrec)
        !           224:                                                return;
        !           225:                                }
        !           226:                                continue;
        !           227:                        }
        !           228:                        /* find associated tty */
        !           229:                        for (T = ttylist;; T = T->next) {
        !           230:                                if (!T) {
        !           231:                                        /* add new one */
        !           232:                                        T = addtty(bp->ut_line);
        !           233:                                        break;
        !           234:                                }
        !           235:                                if (!strncmp(T->tty, bp->ut_line, UT_LINESIZE))
        !           236:                                        break;
        !           237:                        }
        !           238:                        if (bp->ut_name[0] && want(bp, YES)) {
        !           239:                                ct = ctime(&bp->ut_time);
        !           240:                                printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s ",
        !           241:                                UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
        !           242:                                UT_LINESIZE, UT_LINESIZE, bp->ut_line,
        !           243:                                UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
        !           244:                                ct, ct + 11);
        !           245:                                if (!T->logout)
        !           246:                                        puts("  still logged in");
        !           247:                                else {
        !           248:                                        if (T->logout < 0) {
        !           249:                                                T->logout = -T->logout;
        !           250:                                                printf("- %s", crmsg);
        !           251:                                        }
        !           252:                                        else
        !           253:                                                printf("- %5.5s",
        !           254:                                                    ctime(&T->logout)+11);
        !           255:                                        delta = T->logout - bp->ut_time;
        !           256:                                        if (delta < SECSPERDAY)
        !           257:                                                printf("  (%5.5s)\n",
        !           258:                                                    asctime(gmtime(&delta))+11);
        !           259:                                        else
        !           260:                                                printf(" (%ld+%5.5s)\n",
        !           261:                                                    delta / SECSPERDAY,
        !           262:                                                    asctime(gmtime(&delta))+11);
        !           263:                                }
        !           264:                                if (maxrec != -1 && !--maxrec)
        !           265:                                        return;
        !           266:                        }
        !           267:                        T->logout = bp->ut_time;
        !           268:                }
        !           269:        }
        !           270:        ct = ctime(&buf[0].ut_time);
        !           271:        printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
        !           272: }
        !           273:
        !           274: /*
        !           275:  * want --
        !           276:  *     see if want this entry
        !           277:  */
        !           278: int
        !           279: want(bp, check)
        !           280:        struct utmp *bp;
        !           281:        int check;
        !           282: {
        !           283:        ARG *step;
        !           284:
        !           285:        if (check)
        !           286:                /*
        !           287:                 * when uucp and ftp log in over a network, the entry in
        !           288:                 * the utmp file is the name plus their process id.  See
        !           289:                 * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
        !           290:                 */
        !           291:                if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
        !           292:                        bp->ut_line[3] = '\0';
        !           293:                else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
        !           294:                        bp->ut_line[4] = '\0';
        !           295:        if (!arglist)
        !           296:                return (YES);
        !           297:
        !           298:        for (step = arglist; step; step = step->next)
        !           299:                switch(step->type) {
        !           300:                case HOST_TYPE:
        !           301:                        if (!strncasecmp(step->name, bp->ut_host, UT_HOSTSIZE))
        !           302:                                return (YES);
        !           303:                        break;
        !           304:                case TTY_TYPE:
        !           305:                        if (!strncmp(step->name, bp->ut_line, UT_LINESIZE))
        !           306:                                return (YES);
        !           307:                        break;
        !           308:                case USER_TYPE:
        !           309:                        if (!strncmp(step->name, bp->ut_name, UT_NAMESIZE))
        !           310:                                return (YES);
        !           311:                        break;
        !           312:        }
        !           313:        return (NO);
        !           314: }
        !           315:
        !           316: /*
        !           317:  * addarg --
        !           318:  *     add an entry to a linked list of arguments
        !           319:  */
        !           320: void
        !           321: addarg(type, arg)
        !           322:        int type;
        !           323:        char *arg;
        !           324: {
        !           325:        ARG *cur;
        !           326:
        !           327:        if (!(cur = (ARG *)malloc((u_int)sizeof(ARG))))
        !           328:                err(1, "malloc failure");
        !           329:        cur->next = arglist;
        !           330:        cur->type = type;
        !           331:        cur->name = arg;
        !           332:        arglist = cur;
        !           333: }
        !           334:
        !           335: /*
        !           336:  * addtty --
        !           337:  *     add an entry to a linked list of ttys
        !           338:  */
        !           339: TTY *
        !           340: addtty(ttyname)
        !           341:        char *ttyname;
        !           342: {
        !           343:        TTY *cur;
        !           344:
        !           345:        if (!(cur = (TTY *)malloc((u_int)sizeof(TTY))))
        !           346:                err(1, "malloc failure");
        !           347:        cur->next = ttylist;
        !           348:        cur->logout = currentout;
        !           349:        memmove(cur->tty, ttyname, UT_LINESIZE);
        !           350:        return (ttylist = cur);
        !           351: }
        !           352:
        !           353: /*
        !           354:  * hostconv --
        !           355:  *     convert the hostname to search pattern; if the supplied host name
        !           356:  *     has a domain attached that is the same as the current domain, rip
        !           357:  *     off the domain suffix since that's what login(1) does.
        !           358:  */
        !           359: void
        !           360: hostconv(arg)
        !           361:        char *arg;
        !           362: {
        !           363:        static int first = 1;
        !           364:        static char *hostdot, name[MAXHOSTNAMELEN];
        !           365:        char *argdot;
        !           366:
        !           367:        if (!(argdot = strchr(arg, '.')))
        !           368:                return;
        !           369:        if (first) {
        !           370:                first = 0;
        !           371:                if (gethostname(name, sizeof(name)))
        !           372:                        err(1, "gethostname");
        !           373:                hostdot = strchr(name, '.');
        !           374:        }
        !           375:        if (hostdot && !strcasecmp(hostdot, argdot))
        !           376:                *argdot = '\0';
        !           377: }
        !           378:
        !           379: /*
        !           380:  * ttyconv --
        !           381:  *     convert tty to correct name.
        !           382:  */
        !           383: char *
        !           384: ttyconv(arg)
        !           385:        char *arg;
        !           386: {
        !           387:        char *mval;
        !           388:
        !           389:        /*
        !           390:         * kludge -- we assume that all tty's end with
        !           391:         * a two character suffix.
        !           392:         */
        !           393:        if (strlen(arg) == 2) {
        !           394:                /* either 6 for "ttyxx" or 8 for "console" */
        !           395:                if (!(mval = malloc((u_int)8)))
        !           396:                        err(1, "malloc failure");
        !           397:                if (!strcmp(arg, "co"))
        !           398:                        (void)strcpy(mval, "console");
        !           399:                else {
        !           400:                        (void)strcpy(mval, "tty");
        !           401:                        (void)strcpy(mval + 3, arg);
        !           402:                }
        !           403:                return (mval);
        !           404:        }
        !           405:        if (!strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1))
        !           406:                return (arg + 5);
        !           407:        return (arg);
        !           408: }
        !           409:
        !           410: /*
        !           411:  * onintr --
        !           412:  *     on interrupt, we inform the user how far we've gotten
        !           413:  */
        !           414: void
        !           415: onintr(signo)
        !           416:        int signo;
        !           417: {
        !           418:        char *ct;
        !           419:
        !           420:        ct = ctime(&buf[0].ut_time);
        !           421:        printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
        !           422:        if (signo == SIGINT)
        !           423:                exit(1);
        !           424:        (void)fflush(stdout);                   /* fix required for rsh */
        !           425: }