[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.9

1.9     ! downsj      1: /*     $OpenBSD: last.c,v 1.8 1997/08/25 23:11:12 deraadt Exp $        */
1.1       deraadt     2: /*     $NetBSD: last.c,v 1.6 1994/12/24 16:49:02 cgd Exp $     */
                      3:
                      4: /*
                      5:  * Copyright (c) 1987, 1993, 1994
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  */
                     36:
                     37: #ifndef lint
                     38: static char copyright[] =
                     39: "@(#) Copyright (c) 1987, 1993, 1994\n\
                     40:        The Regents of the University of California.  All rights reserved.\n";
                     41: #endif /* not lint */
                     42:
                     43: #ifndef lint
                     44: #if 0
                     45: static char sccsid[] = "@(#)last.c     8.2 (Berkeley) 4/2/94";
                     46: #endif
1.9     ! downsj     47: static char rcsid[] = "$OpenBSD: last.c,v 1.8 1997/08/25 23:11:12 deraadt Exp $";
1.1       deraadt    48: #endif /* not lint */
                     49:
                     50: #include <sys/param.h>
                     51: #include <sys/stat.h>
                     52:
                     53: #include <err.h>
                     54: #include <fcntl.h>
                     55: #include <paths.h>
                     56: #include <signal.h>
                     57: #include <stdio.h>
                     58: #include <stdlib.h>
                     59: #include <string.h>
                     60: #include <time.h>
                     61: #include <tzfile.h>
                     62: #include <unistd.h>
                     63: #include <utmp.h>
                     64:
                     65: #define        NO      0                               /* false/no */
                     66: #define        YES     1                               /* true/yes */
1.4       jdm        67: #define ATOI2(ar)       ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
1.1       deraadt    68:
                     69: static struct utmp     buf[1024];              /* utmp read buffer */
                     70:
                     71: typedef struct arg {
                     72:        char    *name;                          /* argument */
                     73: #define        HOST_TYPE       -2
                     74: #define        TTY_TYPE        -3
                     75: #define        USER_TYPE       -4
                     76:        int     type;                           /* type of arg */
                     77:        struct arg      *next;                  /* linked list pointer */
                     78: } ARG;
                     79: ARG    *arglist;                               /* head of linked list */
                     80:
                     81: typedef struct ttytab {
                     82:        time_t  logout;                         /* log out time */
                     83:        char    tty[UT_LINESIZE + 1];           /* terminal name */
                     84:        struct ttytab   *next;                  /* linked list pointer */
                     85: } TTY;
                     86: TTY    *ttylist;                               /* head of linked list */
                     87:
                     88: static time_t  currentout;                     /* current logout value */
                     89: static long    maxrec;                         /* records to display */
                     90: static char    *file = _PATH_WTMP;             /* wtmp file */
1.6       mickey     91: static int     fulltime = 0;                   /* Display seconds? */
1.7       deraadt    92: static time_t  snaptime;                       /* if != 0, we will only
                     93:                                                 * report users logged in
                     94:                                                 * at this snapshot time
1.4       jdm        95:                                                 */
1.9     ! downsj     96: static int calculate = 0;
        !            97: static int seconds = 0;
1.1       deraadt    98:
                     99: void    addarg __P((int, char *));
                    100: TTY    *addtty __P((char *));
                    101: void    hostconv __P((char *));
                    102: void    onintr __P((int));
                    103: char   *ttyconv __P((char *));
1.4       jdm       104: time_t  dateconv __P((char *));
1.1       deraadt   105: int     want __P((struct utmp *, int));
                    106: void    wtmp __P((void));
1.5       jdm       107: void    checkargs __P((void));
1.1       deraadt   108:
                    109: int
                    110: main(argc, argv)
                    111:        int argc;
                    112:        char *argv[];
                    113: {
                    114:        extern int optind;
                    115:        extern char *optarg;
                    116:        int ch;
                    117:        char *p;
                    118:
                    119:        maxrec = -1;
1.4       jdm       120:        snaptime = 0;
1.9     ! downsj    121:        while ((ch = getopt(argc, argv, "0123456789cf:h:st:d:T")) != -1)
1.1       deraadt   122:                switch (ch) {
                    123:                case '0': case '1': case '2': case '3': case '4':
                    124:                case '5': case '6': case '7': case '8': case '9':
                    125:                        /*
                    126:                         * kludge: last was originally designed to take
                    127:                         * a number after a dash.
                    128:                         */
                    129:                        if (maxrec == -1) {
                    130:                                p = argv[optind - 1];
                    131:                                if (p[0] == '-' && p[1] == ch && !p[2])
                    132:                                        maxrec = atol(++p);
                    133:                                else
                    134:                                        maxrec = atol(argv[optind] + 1);
                    135:                                if (!maxrec)
                    136:                                        exit(0);
                    137:                        }
                    138:                        break;
1.9     ! downsj    139:                case 'c':
        !           140:                        calculate++;
        !           141:                        break;
1.1       deraadt   142:                case 'f':
                    143:                        file = optarg;
                    144:                        break;
                    145:                case 'h':
                    146:                        hostconv(optarg);
                    147:                        addarg(HOST_TYPE, optarg);
                    148:                        break;
1.9     ! downsj    149:                case 's':
        !           150:                        seconds++;
        !           151:                        break;
1.1       deraadt   152:                case 't':
                    153:                        addarg(TTY_TYPE, ttyconv(optarg));
                    154:                        break;
1.4       jdm       155:                case 'd':
                    156:                        snaptime = dateconv(optarg);
                    157:                        break;
1.6       mickey    158:                case 'T':
1.9     ! downsj    159:                        fulltime = 1;
1.6       mickey    160:                        break;
1.1       deraadt   161:                case '?':
                    162:                default:
                    163:                        (void)fprintf(stderr,
1.9     ! downsj    164:                            "usage: last [-#] [-cns] [-f file] [-T] [-t tty]"
1.7       deraadt   165:                            " [-h host] [-d [[yy]yy[mm[dd[hh]]]]mm[.ss]]"
                    166:                            " [user ...]\n");
1.1       deraadt   167:                        exit(1);
                    168:                }
                    169:
                    170:        if (argc) {
                    171:                setlinebuf(stdout);
                    172:                for (argv += optind; *argv; ++argv) {
                    173: #define        COMPATIBILITY
                    174: #ifdef COMPATIBILITY
                    175:                        /* code to allow "last p5" to work */
                    176:                        addarg(TTY_TYPE, ttyconv(*argv));
                    177: #endif
                    178:                        addarg(USER_TYPE, *argv);
                    179:                }
                    180:        }
1.5       jdm       181:
                    182:        checkargs();
1.1       deraadt   183:        wtmp();
                    184:        exit(0);
                    185: }
                    186:
                    187: /*
1.5       jdm       188:  * checkargs --
                    189:  *     if snaptime is set, print warning if usernames, or -t or -h
                    190:  *     flags are also provided
                    191:  */
                    192:
                    193: void
                    194: checkargs()
                    195: {
                    196:        ARG     *step;
                    197:        int     ttyflag = 0;
                    198:
                    199:        if (!snaptime)
                    200:                return;
                    201:
                    202:        if (!arglist)
                    203:                return;
                    204:
                    205:        for (step = arglist; step; step = step->next)
                    206:                switch (step->type) {
                    207:                case HOST_TYPE:
1.7       deraadt   208:                        (void)fprintf(stderr,
                    209:                            "Warning: Ignoring hostname flag\n");
1.5       jdm       210:                        break;
                    211:                case TTY_TYPE:
                    212:                        if (!ttyflag) { /* don't print this twice */
1.7       deraadt   213:                                (void)fprintf(stderr,
                    214:                                    "Warning: Ignoring tty flag\n");
1.5       jdm       215:                                ttyflag = 1;
                    216:                        }
                    217:                        break;
                    218:                case USER_TYPE:
1.7       deraadt   219:                        (void)fprintf(stderr,
                    220:                            "Warning: Ignoring username[s]\n");
1.5       jdm       221:                        break;
                    222:                default:
                    223:                        /* PRINT NOTHING */
                    224:                }
                    225: }
                    226:
                    227:
                    228: /*
1.1       deraadt   229:  * wtmp --
                    230:  *     read through the wtmp file
                    231:  */
                    232: void
                    233: wtmp()
                    234: {
1.6       mickey    235:        struct utmp     *bp;            /* current structure */
                    236:        TTY     *T;                     /* tty list entry */
                    237:        struct stat     stb;            /* stat of file for size */
1.8       deraadt   238:        time_t  delta;                  /* time difference */
1.9     ! downsj    239:        time_t  total;
1.8       deraadt   240:        off_t   bl;
1.6       mickey    241:        int     timesize;               /* how long time string gonna be */
1.1       deraadt   242:        int     bytes, wfd;
                    243:        char    *ct, *crmsg;
1.6       mickey    244:        int     snapfound = 0;          /* found snapshot entry? */
1.1       deraadt   245:        if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1)
                    246:                err(1, "%s", file);
                    247:        bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
                    248:
1.6       mickey    249:        if (fulltime)
                    250:                timesize = 8;   /* HH:MM:SS */
                    251:        else
                    252:                timesize = 5;   /* HH:MM */
                    253:
1.1       deraadt   254:        (void)time(&buf[0].ut_time);
                    255:        (void)signal(SIGINT, onintr);
                    256:        (void)signal(SIGQUIT, onintr);
                    257:
                    258:        while (--bl >= 0) {
1.8       deraadt   259:                if (lseek(wfd, bl * sizeof(buf), L_SET) == -1 ||
1.1       deraadt   260:                    (bytes = read(wfd, buf, sizeof(buf))) == -1)
                    261:                        err(1, "%s", file);
                    262:                for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
                    263:                        /*
                    264:                         * if the terminal line is '~', the machine stopped.
                    265:                         * see utmp(5) for more info.
                    266:                         */
                    267:                        if (bp->ut_line[0] == '~' && !bp->ut_line[1]) {
                    268:                                /* everybody just logged out */
                    269:                                for (T = ttylist; T; T = T->next)
                    270:                                        T->logout = -bp->ut_time;
                    271:                                currentout = -bp->ut_time;
                    272:                                crmsg = strncmp(bp->ut_name, "shutdown",
                    273:                                    UT_NAMESIZE) ? "crash" : "shutdown";
1.4       jdm       274:                                /*
                    275:                                 * if we're in snapshop mode, we want to
                    276:                                 * exit if this shutdown/reboot appears
                    277:                                 * while we we are tracking the active
                    278:                                 * range
                    279:                                 */
                    280:                                if (snaptime && snapfound)
                    281:                                        return;
                    282:                                /*
                    283:                                 * don't print shutdown/reboot entries
1.5       jdm       284:                                 * unless flagged for
1.4       jdm       285:                                 */
1.5       jdm       286:                                if (want(bp, NO)) {
1.9     ! downsj    287:                                        if (seconds) {
        !           288:                                printf("%-*.*s %-*.*s %-*.*s %ld \n",
        !           289:                                                UT_NAMESIZE, UT_NAMESIZE,
        !           290:                                                bp->ut_name, UT_LINESIZE,
        !           291:                                                UT_LINESIZE, bp->ut_line,
        !           292:                                                UT_HOSTSIZE, UT_HOSTSIZE,
        !           293:                                                bp->ut_host, bp->ut_time);
        !           294:                                        } else {
        !           295:                                                ct = ctime(&bp->ut_time);
1.6       mickey    296:                                printf("%-*.*s  %-*.*s %-*.*s %10.10s %*.*s \n",
1.9     ! downsj    297:                                                UT_NAMESIZE, UT_NAMESIZE,
        !           298:                                                bp->ut_name, UT_LINESIZE,
        !           299:                                                UT_LINESIZE, bp->ut_line,
        !           300:                                                UT_HOSTSIZE, UT_HOSTSIZE,
        !           301:                                                bp->ut_host, ct, timesize,
        !           302:                                                timesize, ct + 11);
        !           303:                                        }
1.1       deraadt   304:                                        if (maxrec != -1 && !--maxrec)
                    305:                                                return;
                    306:                                }
                    307:                                continue;
                    308:                        }
                    309:                        /*
                    310:                         * if the line is '{' or '|', date got set; see
                    311:                         * utmp(5) for more info.
                    312:                         */
                    313:                        if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|')
                    314:                            && !bp->ut_line[1]) {
1.5       jdm       315:                                if (want(bp, NO)) {
1.9     ! downsj    316:                                        if (seconds) {
        !           317:                                printf("%-*.*s %-*.*s %-*.*s %ld \n",
        !           318:                                        UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
        !           319:                                        UT_LINESIZE, UT_LINESIZE, bp->ut_line,
        !           320:                                        UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
        !           321:                                        bp->ut_time);
        !           322:                                        } else {
        !           323:                                                ct = ctime(&bp->ut_time);
1.6       mickey    324:                                printf("%-*.*s  %-*.*s %-*.*s %10.10s %*.*s \n",
1.9     ! downsj    325:                                        UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
        !           326:                                        UT_LINESIZE, UT_LINESIZE, bp->ut_line,
        !           327:                                        UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
        !           328:                                        ct, timesize, timesize, ct + 11);
        !           329:                                        }
1.1       deraadt   330:                                        if (maxrec && !--maxrec)
                    331:                                                return;
                    332:                                }
                    333:                                continue;
                    334:                        }
                    335:                        /* find associated tty */
                    336:                        for (T = ttylist;; T = T->next) {
                    337:                                if (!T) {
                    338:                                        /* add new one */
                    339:                                        T = addtty(bp->ut_line);
                    340:                                        break;
                    341:                                }
                    342:                                if (!strncmp(T->tty, bp->ut_line, UT_LINESIZE))
                    343:                                        break;
                    344:                        }
1.4       jdm       345:                        /*
                    346:                         * print record if not in snapshot mode and wanted
                    347:                         * or in snapshot mode and in snapshot range
                    348:                         */
                    349:                        if (bp->ut_name[0] &&
1.5       jdm       350:                            ((want(bp, YES)) ||
1.4       jdm       351:                             (bp->ut_time < snaptime &&
                    352:                              (T->logout > snaptime || !T->logout ||
                    353:                               T->logout < 0)))) {
                    354:                                snapfound = 1;
1.9     ! downsj    355:                                if (seconds) {
        !           356:                                printf("%-*.*s %-*.*s %-*.*s %ld ",
        !           357:                                        UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
        !           358:                                        UT_LINESIZE, UT_LINESIZE, bp->ut_line,
        !           359:                                        UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
        !           360:                                        bp->ut_time);
        !           361:                                } else {
        !           362:                                        ct = ctime(&bp->ut_time);
1.6       mickey    363:                                printf("%-*.*s  %-*.*s %-*.*s %10.10s %*.*s ",
                    364:                                        UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
                    365:                                        UT_LINESIZE, UT_LINESIZE, bp->ut_line,
                    366:                                        UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
                    367:                                        ct, timesize, timesize, ct + 11);
1.9     ! downsj    368:                                }
1.1       deraadt   369:                                if (!T->logout)
                    370:                                        puts("  still logged in");
                    371:                                else {
                    372:                                        if (T->logout < 0) {
                    373:                                                T->logout = -T->logout;
                    374:                                                printf("- %s", crmsg);
1.9     ! downsj    375:                                        } else {
        !           376:                                                if (seconds)
        !           377:                                                        printf("- %ld",
        !           378:                                                            T->logout);
        !           379:                                                else
        !           380:                                                        printf("- %*.*s",
        !           381:                                                            timesize, timesize,
        !           382:                                                            ctime(&T->logout)+11);
1.1       deraadt   383:                                        }
                    384:                                        delta = T->logout - bp->ut_time;
1.9     ! downsj    385:                                        if (seconds)
        !           386:                                                printf("  (%ld)\n", delta);
        !           387:                                        else {
        !           388:                                                if (delta < SECSPERDAY)
        !           389:                                                        printf("  (%*.*s)\n",
        !           390:                                                            timesize, timesize,
        !           391:                                                            asctime(gmtime(&delta))+11);
        !           392:                                                else
        !           393:                                                        printf(" (%ld+%*.*s)\n",
        !           394:                                                            delta / SECSPERDAY,
        !           395:                                                            timesize, timesize,
        !           396:                                                            asctime(gmtime(&delta))+11);
        !           397:                                        }
        !           398:                                        if (calculate)
        !           399:                                                total += delta;
1.1       deraadt   400:                                }
                    401:                                if (maxrec != -1 && !--maxrec)
                    402:                                        return;
                    403:                        }
                    404:                        T->logout = bp->ut_time;
                    405:                }
1.9     ! downsj    406:        }
        !           407:        if (calculate) {
        !           408:                if ((total / SECSPERDAY) > 0) {
        !           409:                        int days = (total / SECSPERDAY);
        !           410:                        total -= (days * SECSPERDAY);
        !           411:
        !           412:                        printf("\nTotal time: %d days, %*.*s\n",
        !           413:                                days, timesize, timesize,
        !           414:                                asctime(gmtime(&total))+11);
        !           415:                } else
        !           416:                        printf("\nTotal time: %*.*s\n",
        !           417:                                timesize, timesize,
        !           418:                                asctime(gmtime(&total))+11);
1.1       deraadt   419:        }
                    420:        ct = ctime(&buf[0].ut_time);
1.6       mickey    421:        printf("\nwtmp begins %10.10s %*.*s \n", ct, timesize, timesize, ct + 11);
1.1       deraadt   422: }
                    423:
                    424: /*
                    425:  * want --
                    426:  *     see if want this entry
                    427:  */
                    428: int
                    429: want(bp, check)
                    430:        struct utmp *bp;
                    431:        int check;
                    432: {
                    433:        ARG *step;
                    434:
                    435:        if (check)
                    436:                /*
                    437:                 * when uucp and ftp log in over a network, the entry in
                    438:                 * the utmp file is the name plus their process id.  See
                    439:                 * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
                    440:                 */
                    441:                if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
                    442:                        bp->ut_line[3] = '\0';
                    443:                else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
                    444:                        bp->ut_line[4] = '\0';
1.5       jdm       445:
                    446:        if (snaptime)           /* if snaptime is set, return NO */
                    447:                return (NO);
                    448:
1.1       deraadt   449:        if (!arglist)
                    450:                return (YES);
                    451:
                    452:        for (step = arglist; step; step = step->next)
                    453:                switch(step->type) {
                    454:                case HOST_TYPE:
                    455:                        if (!strncasecmp(step->name, bp->ut_host, UT_HOSTSIZE))
                    456:                                return (YES);
                    457:                        break;
                    458:                case TTY_TYPE:
                    459:                        if (!strncmp(step->name, bp->ut_line, UT_LINESIZE))
                    460:                                return (YES);
                    461:                        break;
                    462:                case USER_TYPE:
                    463:                        if (!strncmp(step->name, bp->ut_name, UT_NAMESIZE))
                    464:                                return (YES);
                    465:                        break;
1.5       jdm       466:                }
                    467:
1.1       deraadt   468:        return (NO);
                    469: }
                    470:
                    471: /*
                    472:  * addarg --
                    473:  *     add an entry to a linked list of arguments
                    474:  */
                    475: void
                    476: addarg(type, arg)
                    477:        int type;
                    478:        char *arg;
                    479: {
                    480:        ARG *cur;
                    481:
                    482:        if (!(cur = (ARG *)malloc((u_int)sizeof(ARG))))
                    483:                err(1, "malloc failure");
                    484:        cur->next = arglist;
                    485:        cur->type = type;
                    486:        cur->name = arg;
                    487:        arglist = cur;
                    488: }
                    489:
                    490: /*
                    491:  * addtty --
                    492:  *     add an entry to a linked list of ttys
                    493:  */
                    494: TTY *
                    495: addtty(ttyname)
                    496:        char *ttyname;
                    497: {
                    498:        TTY *cur;
                    499:
                    500:        if (!(cur = (TTY *)malloc((u_int)sizeof(TTY))))
                    501:                err(1, "malloc failure");
                    502:        cur->next = ttylist;
                    503:        cur->logout = currentout;
                    504:        memmove(cur->tty, ttyname, UT_LINESIZE);
                    505:        return (ttylist = cur);
                    506: }
                    507:
                    508: /*
                    509:  * hostconv --
                    510:  *     convert the hostname to search pattern; if the supplied host name
                    511:  *     has a domain attached that is the same as the current domain, rip
                    512:  *     off the domain suffix since that's what login(1) does.
                    513:  */
                    514: void
                    515: hostconv(arg)
                    516:        char *arg;
                    517: {
                    518:        static int first = 1;
                    519:        static char *hostdot, name[MAXHOSTNAMELEN];
                    520:        char *argdot;
                    521:
                    522:        if (!(argdot = strchr(arg, '.')))
                    523:                return;
                    524:        if (first) {
                    525:                first = 0;
                    526:                if (gethostname(name, sizeof(name)))
                    527:                        err(1, "gethostname");
                    528:                hostdot = strchr(name, '.');
                    529:        }
                    530:        if (hostdot && !strcasecmp(hostdot, argdot))
                    531:                *argdot = '\0';
                    532: }
                    533:
                    534: /*
                    535:  * ttyconv --
                    536:  *     convert tty to correct name.
                    537:  */
                    538: char *
                    539: ttyconv(arg)
                    540:        char *arg;
                    541: {
                    542:        char *mval;
                    543:
                    544:        /*
                    545:         * kludge -- we assume that all tty's end with
                    546:         * a two character suffix.
                    547:         */
                    548:        if (strlen(arg) == 2) {
                    549:                /* either 6 for "ttyxx" or 8 for "console" */
                    550:                if (!(mval = malloc((u_int)8)))
                    551:                        err(1, "malloc failure");
                    552:                if (!strcmp(arg, "co"))
                    553:                        (void)strcpy(mval, "console");
                    554:                else {
                    555:                        (void)strcpy(mval, "tty");
                    556:                        (void)strcpy(mval + 3, arg);
                    557:                }
                    558:                return (mval);
                    559:        }
                    560:        if (!strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1))
                    561:                return (arg + 5);
                    562:        return (arg);
                    563: }
1.4       jdm       564:
                    565: /*
                    566:  * dateconv --
                    567:  *     Convert the snapshot time in command line given in the format
1.7       deraadt   568:  *     [[yy]yy][mmdd]hhmm[.ss]] to a time_t.
1.4       jdm       569:  *     Derived from atime_arg1() in usr.bin/touch/touch.c
                    570:  */
                    571: time_t
                    572: dateconv(arg)
1.7       deraadt   573:        char *arg;
1.4       jdm       574: {
1.7       deraadt   575:        time_t timet;
                    576:        struct tm *t;
                    577:        int yearset;
                    578:        char *p;
                    579:
                    580:        /* Start with the current time. */
                    581:        if (time(&timet) < 0)
                    582:                err(1, "time");
                    583:        if ((t = localtime(&timet)) == NULL)
                    584:                err(1, "localtime");
                    585:
                    586:        /* [[yy]yy][mmdd]hhmm[.ss] */
                    587:        if ((p = strchr(arg, '.')) == NULL)
                    588:                t->tm_sec = 0;          /* Seconds defaults to 0. */
                    589:        else {
                    590:                if (strlen(p + 1) != 2)
                    591:                        goto terr;
                    592:                *p++ = '\0';
                    593:                t->tm_sec = ATOI2(p);
                    594:        }
                    595:
                    596:        yearset = 0;
                    597:        switch (strlen(arg)) {
                    598:        case 12:                        /* ccyymmddhhmm */
                    599:                t->tm_year = ATOI2(arg);
                    600:                t->tm_year *= 100;
                    601:                yearset = 1;
                    602:                /* FALLTHOUGH */
                    603:        case 10:                        /* yymmddhhmm */
                    604:                if (yearset) {
                    605:                        yearset = ATOI2(arg);
                    606:                        t->tm_year += yearset;
                    607:                } else {
                    608:                        yearset = ATOI2(arg);
                    609:                        if (yearset < 69)
                    610:                                t->tm_year = yearset + 2000;
                    611:                        else
                    612:                                t->tm_year = yearset + 1900;
                    613:                }
                    614:                t->tm_year -= 1900;     /* Convert to UNIX time. */
                    615:                /* FALLTHROUGH */
                    616:        case 8:                         /* MMDDhhmm */
                    617:                t->tm_mon = ATOI2(arg);
                    618:                --t->tm_mon;            /* Convert from 01-12 to 00-11 */
                    619:                t->tm_mday = ATOI2(arg);
                    620:                t->tm_hour = ATOI2(arg);
                    621:                t->tm_min = ATOI2(arg);
                    622:                break;
                    623:        case 4:                         /* hhmm */
                    624:                t->tm_hour = ATOI2(arg);
                    625:                t->tm_min = ATOI2(arg);
                    626:                break;
                    627:        default:
                    628:                goto terr;
                    629:        }
                    630:        t->tm_isdst = -1;               /* Figure out DST. */
                    631:        timet = mktime(t);
                    632:        if (timet == -1)
                    633: terr:     errx(1,
                    634:        "out of range or illegal time specification: [[yy]yy][mmdd]hhmm[.ss]");
                    635:        return timet;
1.4       jdm       636: }
                    637:
1.1       deraadt   638:
                    639: /*
                    640:  * onintr --
                    641:  *     on interrupt, we inform the user how far we've gotten
                    642:  */
                    643: void
                    644: onintr(signo)
                    645:        int signo;
                    646: {
                    647:        char *ct;
                    648:
                    649:        ct = ctime(&buf[0].ut_time);
1.6       mickey    650:        printf("\ninterrupted %10.10s %8.8s \n", ct, ct + 11);
1.1       deraadt   651:        if (signo == SIGINT)
                    652:                exit(1);
                    653:        (void)fflush(stdout);                   /* fix required for rsh */
                    654: }