BSD 4_4_Lite1 release
[unix-history] / usr / src / usr.bin / last / last.c
index 4ba2265..662a663 100644 (file)
@@ -1,43 +1,61 @@
 /*
 /*
- * Copyright (c) 1987 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1987 Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1987, 1993, 1994\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)last.c     5.15 (Berkeley) %G%";
+static char sccsid[] = "@(#)last.c     8.2 (Berkeley) 4/2/94";
 #endif /* not lint */
 
 #endif /* not lint */
 
-/*
- * last
- */
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/stat.h>
-#include <sys/file.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <paths.h>
 #include <signal.h>
 #include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <time.h>
 #include <time.h>
+#include <tzfile.h>
+#include <unistd.h>
 #include <utmp.h>
 #include <utmp.h>
-#include <stdio.h>
-#include <paths.h>
 
 
-#define        SECDAY  (24*60*60)                      /* seconds in a day */
 #define        NO      0                               /* false/no */
 #define        YES     1                               /* true/yes */
 
 #define        NO      0                               /* false/no */
 #define        YES     1                               /* true/yes */
 
@@ -64,19 +82,27 @@ static long currentout,                     /* current logout value */
                maxrec;                         /* records to display */
 static char    *file = _PATH_WTMP;             /* wtmp file */
 
                maxrec;                         /* records to display */
 static char    *file = _PATH_WTMP;             /* wtmp file */
 
+void    addarg __P((int, char *));
+TTY    *addtty __P((char *));
+void    hostconv __P((char *));
+void    onintr __P((int));
+char   *ttyconv __P((char *));
+int     want __P((struct utmp *, int));
+void    wtmp __P((void));
+
+int
 main(argc, argv)
        int argc;
 main(argc, argv)
        int argc;
-       char **argv;
+       char *argv[];
 {
        extern int optind;
        extern char *optarg;
        int ch;
 {
        extern int optind;
        extern char *optarg;
        int ch;
-       long atol();
-       char *p, *ttyconv();
+       char *p;
 
        maxrec = -1;
        while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF)
 
        maxrec = -1;
        while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF)
-               switch((char)ch) {
+               switch (ch) {
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                        /*
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                        /*
@@ -105,16 +131,21 @@ main(argc, argv)
                        break;
                case '?':
                default:
                        break;
                case '?':
                default:
-                       fputs("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", stderr);
+                       (void)fprintf(stderr,
+       "usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n");
                        exit(1);
                }
                        exit(1);
                }
-       for (argv += optind; *argv; ++argv) {
+
+       if (argc) {
+               setlinebuf(stdout);
+               for (argv += optind; *argv; ++argv) {
 #define        COMPATIBILITY
 #ifdef COMPATIBILITY
 #define        COMPATIBILITY
 #ifdef COMPATIBILITY
-               /* code to allow "last p5" to work */
-               addarg(TTY_TYPE, ttyconv(*argv));
+                       /* code to allow "last p5" to work */
+                       addarg(TTY_TYPE, ttyconv(*argv));
 #endif
 #endif
-               addarg(USER_TYPE, *argv);
+                       addarg(USER_TYPE, *argv);
+               }
        }
        wtmp();
        exit(0);
        }
        wtmp();
        exit(0);
@@ -124,24 +155,18 @@ main(argc, argv)
  * wtmp --
  *     read through the wtmp file
  */
  * wtmp --
  *     read through the wtmp file
  */
-static
+void
 wtmp()
 {
 wtmp()
 {
-       register struct utmp    *bp;            /* current structure */
-       register TTY    *T;                     /* tty list entry */
+       struct utmp     *bp;                    /* current structure */
+       TTY     *T;                             /* tty list entry */
        struct stat     stb;                    /* stat of file for size */
        struct stat     stb;                    /* stat of file for size */
-       long    bl, delta,                      /* time difference */
-               lseek(), time();
-       int     bytes, wfd,
-               onintr();
-       char    *ct, *crmsg,
-               *asctime(), *ctime(), *strcpy();
-       TTY     *addtty();
+       long    bl, delta;                      /* time difference */
+       int     bytes, wfd;
+       char    *ct, *crmsg;
 
 
-       if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) {
-               perror(file);
-               exit(1);
-       }
+       if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1)
+               err(1, "%s", file);
        bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
 
        (void)time(&buf[0].ut_time);
        bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
 
        (void)time(&buf[0].ut_time);
@@ -149,12 +174,9 @@ wtmp()
        (void)signal(SIGQUIT, onintr);
 
        while (--bl >= 0) {
        (void)signal(SIGQUIT, onintr);
 
        while (--bl >= 0) {
-               if (lseek(wfd, (long)(bl * sizeof(buf)), L_SET) == -1 ||
-                   (bytes = read(wfd, (char *)buf, sizeof(buf))) == -1) {
-                       fprintf(stderr, "last: %s: ", file);
-                       perror((char *)NULL);
-                       exit(1);
-               }
+               if (lseek(wfd, (off_t)(bl * sizeof(buf)), L_SET) == -1 ||
+                   (bytes = read(wfd, buf, sizeof(buf))) == -1)
+                       err(1, "%s", file);
                for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
                        /*
                         * if the terminal line is '~', the machine stopped.
                for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
                        /*
                         * if the terminal line is '~', the machine stopped.
@@ -169,7 +191,12 @@ wtmp()
                                    UT_NAMESIZE) ? "crash" : "shutdown";
                                if (want(bp, NO)) {
                                        ct = ctime(&bp->ut_time);
                                    UT_NAMESIZE) ? "crash" : "shutdown";
                                if (want(bp, NO)) {
                                        ct = ctime(&bp->ut_time);
-                                       printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n", UT_NAMESIZE, UT_NAMESIZE, bp->ut_name, UT_LINESIZE, UT_LINESIZE, bp->ut_line, UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host, ct, ct + 11);
+                               printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n",
+                                           UT_NAMESIZE, UT_NAMESIZE,
+                                           bp->ut_name, UT_LINESIZE,
+                                           UT_LINESIZE, bp->ut_line,
+                                           UT_HOSTSIZE, UT_HOSTSIZE,
+                                           bp->ut_host, ct, ct + 11);
                                        if (maxrec != -1 && !--maxrec)
                                                return;
                                }
                                        if (maxrec != -1 && !--maxrec)
                                                return;
                                }
@@ -183,7 +210,11 @@ wtmp()
                            && !bp->ut_line[1]) {
                                if (want(bp, NO)) {
                                        ct = ctime(&bp->ut_time);
                            && !bp->ut_line[1]) {
                                if (want(bp, NO)) {
                                        ct = ctime(&bp->ut_time);
-                                       printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n", UT_NAMESIZE, UT_NAMESIZE, bp->ut_name, UT_LINESIZE, UT_LINESIZE, bp->ut_line, UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host, ct, ct + 11);
+                               printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n",
+                                   UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
+                                   UT_LINESIZE, UT_LINESIZE, bp->ut_line,
+                                   UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
+                                   ct, ct + 11);
                                        if (maxrec && !--maxrec)
                                                return;
                                }
                                        if (maxrec && !--maxrec)
                                                return;
                                }
@@ -201,7 +232,11 @@ wtmp()
                        }
                        if (bp->ut_name[0] && want(bp, YES)) {
                                ct = ctime(&bp->ut_time);
                        }
                        if (bp->ut_name[0] && want(bp, YES)) {
                                ct = ctime(&bp->ut_time);
-                               printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s ", UT_NAMESIZE, UT_NAMESIZE, bp->ut_name, UT_LINESIZE, UT_LINESIZE, bp->ut_line, UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host, ct, ct + 11);
+                               printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s ",
+                               UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
+                               UT_LINESIZE, UT_LINESIZE, bp->ut_line,
+                               UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
+                               ct, ct + 11);
                                if (!T->logout)
                                        puts("  still logged in");
                                else {
                                if (!T->logout)
                                        puts("  still logged in");
                                else {
@@ -210,12 +245,16 @@ wtmp()
                                                printf("- %s", crmsg);
                                        }
                                        else
                                                printf("- %s", crmsg);
                                        }
                                        else
-                                               printf("- %5.5s", ctime(&T->logout)+11);
+                                               printf("- %5.5s",
+                                                   ctime(&T->logout)+11);
                                        delta = T->logout - bp->ut_time;
                                        delta = T->logout - bp->ut_time;
-                                       if (delta < SECDAY)
-                                               printf("  (%5.5s)\n", asctime(gmtime(&delta))+11);
+                                       if (delta < SECSPERDAY)
+                                               printf("  (%5.5s)\n",
+                                                   asctime(gmtime(&delta))+11);
                                        else
                                        else
-                                               printf(" (%ld+%5.5s)\n", delta / SECDAY, asctime(gmtime(&delta))+11);
+                                               printf(" (%ld+%5.5s)\n",
+                                                   delta / SECSPERDAY,
+                                                   asctime(gmtime(&delta))+11);
                                }
                                if (maxrec != -1 && !--maxrec)
                                        return;
                                }
                                if (maxrec != -1 && !--maxrec)
                                        return;
@@ -231,12 +270,12 @@ wtmp()
  * want --
  *     see if want this entry
  */
  * want --
  *     see if want this entry
  */
-static
+int
 want(bp, check)
 want(bp, check)
-       register struct utmp *bp;
+       struct utmp *bp;
        int check;
 {
        int check;
 {
-       register ARG *step;
+       ARG *step;
 
        if (check)
                /*
 
        if (check)
                /*
@@ -249,42 +288,39 @@ want(bp, check)
                else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
                        bp->ut_line[4] = '\0';
        if (!arglist)
                else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
                        bp->ut_line[4] = '\0';
        if (!arglist)
-               return(YES);
+               return (YES);
 
        for (step = arglist; step; step = step->next)
                switch(step->type) {
                case HOST_TYPE:
                        if (!strncasecmp(step->name, bp->ut_host, UT_HOSTSIZE))
 
        for (step = arglist; step; step = step->next)
                switch(step->type) {
                case HOST_TYPE:
                        if (!strncasecmp(step->name, bp->ut_host, UT_HOSTSIZE))
-                               return(YES);
+                               return (YES);
                        break;
                case TTY_TYPE:
                        if (!strncmp(step->name, bp->ut_line, UT_LINESIZE))
                        break;
                case TTY_TYPE:
                        if (!strncmp(step->name, bp->ut_line, UT_LINESIZE))
-                               return(YES);
+                               return (YES);
                        break;
                case USER_TYPE:
                        if (!strncmp(step->name, bp->ut_name, UT_NAMESIZE))
                        break;
                case USER_TYPE:
                        if (!strncmp(step->name, bp->ut_name, UT_NAMESIZE))
-                               return(YES);
+                               return (YES);
                        break;
        }
                        break;
        }
-       return(NO);
+       return (NO);
 }
 
 /*
  * addarg --
  *     add an entry to a linked list of arguments
  */
 }
 
 /*
  * addarg --
  *     add an entry to a linked list of arguments
  */
-static
+void
 addarg(type, arg)
        int type;
        char *arg;
 {
 addarg(type, arg)
        int type;
        char *arg;
 {
-       register ARG *cur;
-       char *malloc();
+       ARG *cur;
 
 
-       if (!(cur = (ARG *)malloc((u_int)sizeof(ARG)))) {
-               fputs("last: malloc failure.\n", stderr);
-               exit(1);
-       }
+       if (!(cur = (ARG *)malloc((u_int)sizeof(ARG))))
+               err(1, "malloc failure");
        cur->next = arglist;
        cur->type = type;
        cur->name = arg;
        cur->next = arglist;
        cur->type = type;
        cur->name = arg;
@@ -295,21 +331,18 @@ addarg(type, arg)
  * addtty --
  *     add an entry to a linked list of ttys
  */
  * addtty --
  *     add an entry to a linked list of ttys
  */
-static TTY *
+TTY *
 addtty(ttyname)
        char *ttyname;
 {
 addtty(ttyname)
        char *ttyname;
 {
-       register TTY *cur;
-       char *malloc();
+       TTY *cur;
 
 
-       if (!(cur = (TTY *)malloc((u_int)sizeof(TTY)))) {
-               fputs("last: malloc failure.\n", stderr);
-               exit(1);
-       }
+       if (!(cur = (TTY *)malloc((u_int)sizeof(TTY))))
+               err(1, "malloc failure");
        cur->next = ttylist;
        cur->logout = currentout;
        cur->next = ttylist;
        cur->logout = currentout;
-       bcopy(ttyname, cur->tty, UT_LINESIZE);
-       return(ttylist = cur);
+       memmove(cur->tty, ttyname, UT_LINESIZE);
+       return (ttylist = cur);
 }
 
 /*
 }
 
 /*
@@ -318,23 +351,21 @@ addtty(ttyname)
  *     has a domain attached that is the same as the current domain, rip
  *     off the domain suffix since that's what login(1) does.
  */
  *     has a domain attached that is the same as the current domain, rip
  *     off the domain suffix since that's what login(1) does.
  */
-static
+void
 hostconv(arg)
        char *arg;
 {
        static int first = 1;
        static char *hostdot, name[MAXHOSTNAMELEN];
 hostconv(arg)
        char *arg;
 {
        static int first = 1;
        static char *hostdot, name[MAXHOSTNAMELEN];
-       char *argdot, *index();
+       char *argdot;
 
 
-       if (!(argdot = index(arg, '.')))
+       if (!(argdot = strchr(arg, '.')))
                return;
        if (first) {
                first = 0;
                return;
        if (first) {
                first = 0;
-               if (gethostname(name, sizeof(name))) {
-                       perror("last: gethostname");
-                       exit(1);
-               }
-               hostdot = index(name, '.');
+               if (gethostname(name, sizeof(name)))
+                       err(1, "gethostname");
+               hostdot = strchr(name, '.');
        }
        if (hostdot && !strcasecmp(hostdot, argdot))
                *argdot = '\0';
        }
        if (hostdot && !strcasecmp(hostdot, argdot))
                *argdot = '\0';
@@ -344,11 +375,11 @@ hostconv(arg)
  * ttyconv --
  *     convert tty to correct name.
  */
  * ttyconv --
  *     convert tty to correct name.
  */
-static char *
+char *
 ttyconv(arg)
        char *arg;
 {
 ttyconv(arg)
        char *arg;
 {
-       char *mval, *malloc(), *strcpy();
+       char *mval;
 
        /*
         * kludge -- we assume that all tty's end with
 
        /*
         * kludge -- we assume that all tty's end with
@@ -356,32 +387,30 @@ ttyconv(arg)
         */
        if (strlen(arg) == 2) {
                /* either 6 for "ttyxx" or 8 for "console" */
         */
        if (strlen(arg) == 2) {
                /* either 6 for "ttyxx" or 8 for "console" */
-               if (!(mval = malloc((u_int)8))) {
-                       fputs("last: malloc failure.\n", stderr);
-                       exit(1);
-               }
+               if (!(mval = malloc((u_int)8)))
+                       err(1, "malloc failure");
                if (!strcmp(arg, "co"))
                        (void)strcpy(mval, "console");
                else {
                        (void)strcpy(mval, "tty");
                        (void)strcpy(mval + 3, arg);
                }
                if (!strcmp(arg, "co"))
                        (void)strcpy(mval, "console");
                else {
                        (void)strcpy(mval, "tty");
                        (void)strcpy(mval + 3, arg);
                }
-               return(mval);
+               return (mval);
        }
        if (!strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1))
        }
        if (!strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1))
-               return(arg + 5);
-       return(arg);
+               return (arg + 5);
+       return (arg);
 }
 
 /*
  * onintr --
  *     on interrupt, we inform the user how far we've gotten
  */
 }
 
 /*
  * onintr --
  *     on interrupt, we inform the user how far we've gotten
  */
-static
+void
 onintr(signo)
        int signo;
 {
 onintr(signo)
        int signo;
 {
-       char *ct, *ctime();
+       char *ct;
 
        ct = ctime(&buf[0].ut_time);
        printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
 
        ct = ctime(&buf[0].ut_time);
        printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);