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

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