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

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