fixed a bug in multi-subscript calculation
[unix-history] / usr / src / usr.bin / lastcomm / lastcomm.c
index 82a0f3e..bb25565 100644 (file)
@@ -1,27 +1,39 @@
-static char *sccsid = "@(#)lastcomm.c  4.2 (Berkeley) %G%";
-#
+static char *sccsid = "@(#)lastcomm.c  4.4 (Berkeley) 82/07/17";
 
 /*
  * last command
  */
 
 # include <stdio.h>
 
 /*
  * last command
  */
 
 # include <stdio.h>
-# include <sys/types.h>
+# include <sys/param.h>
 # include <sys/acct.h>
 # include <sys/acct.h>
+# include <sys/dir.h>
 # include <signal.h>
 # include <pwd.h>
 # include <stat.h>
 # include <signal.h>
 # include <pwd.h>
 # include <stat.h>
+# include <utmp.h>
+# include <struct.h>
 
 
-# define N_USER                1000
+# define N_USER                4000            /* highest alloc user # */
+# define N_DEVS                43              /* hash value for device names */
+# define NDEVS         500             /* max number of file names in /dev */
 
 struct acct    acct_buff [BUFSIZ / sizeof (struct acct)];
 
 
 struct acct    acct_buff [BUFSIZ / sizeof (struct acct)];
 
-char   yes   = 1,
-       no    = 0,
+char   user_list [N_USER][fldsiz(utmp, ut_name) + 1];
 
 
-       user_list [1000][9];
+struct devhash {
+       dev_t   dev_dev;
+       char    dev_name [fldsiz(utmp, ut_line) + 1];
+       struct  devhash * dev_nxt;
+}
+       * dev_hash [ N_DEVS ],
+       * dev_chain ;
+# define HASH(d)       (((int) d) % N_DEVS)
 
 time_t expand ();
 
 time_t expand ();
+char   * flagbits();
+char   * tername();
 
 struct passwd
        *passwd,
 
 struct passwd
        *passwd,
@@ -29,6 +41,8 @@ struct passwd
 
 struct stat stat_buff;
 
 
 struct stat stat_buff;
 
+# define equal(a, b)           (strcmp(a, b) == 0)
+
 main (argc, argv)
 char **argv;
 {
 main (argc, argv)
 char **argv;
 {
@@ -49,10 +63,15 @@ char **argv;
  */
        while (passwd = getpwent ())
        {
  */
        while (passwd = getpwent ())
        {
-               if (user_list[passwd->pw_uid][0])
+               if (user_list[passwd->pw_uid][0]==0)
                        move (passwd->pw_name, user_list [passwd->pw_uid]);
        }
 
                        move (passwd->pw_name, user_list [passwd->pw_uid]);
        }
 
+ /*
+  * find dev numbers corresponding to names in /dev
+  */
+       setupdevs();
+
        acct_desc = open ("/usr/adm/acct", 0);
        if (acct_desc < 0)
        {
        acct_desc = open ("/usr/adm/acct", 0);
        if (acct_desc < 0)
        {
@@ -72,7 +91,8 @@ char **argv;
                n_entry = n_byte / sizeof acct_buff [0];
                for (i = n_entry - 1; i >= 0; i--)
                {
                n_entry = n_byte / sizeof acct_buff [0];
                for (i = n_entry - 1; i >= 0; i--)
                {
-                       if (!*user_list [acct_buff [i].ac_uid]) continue;
+                       if (!*user_list [acct_buff [i].ac_uid])
+                               continue;
                        /*
                         * get the times
                         */
                        /*
                         * get the times
                         */
@@ -95,7 +115,8 @@ char **argv;
                         */
                        for (p = acct_buff [i].ac_comm; *p; p++)
                        {
                         */
                        for (p = acct_buff [i].ac_comm; *p; p++)
                        {
-                               if (*p < '!' || '~' < *p) *p = '?';
+                               if (*p < '!' || '~' < *p)
+                                       *p = '?';
                        }
                        for (j = 1; j < argc; j++)
                        {
                        }
                        for (j = 1; j < argc; j++)
                        {
@@ -105,9 +126,15 @@ char **argv;
                                        ||
                                        equal
                                        (
                                        ||
                                        equal
                                        (
-                                       user_list [acct_buff [i].ac_uid],
+                                               user_list[acct_buff[i].ac_uid],
                                                argv [j]
                                        )
                                                argv [j]
                                        )
+                                       ||
+                                       equal
+                                       (
+                                               tername(acct_buff[i].ac_tty),
+                                               argv[j]
+                                       )
                                )
                                {
                                        break;
                                )
                                {
                                        break;
@@ -117,11 +144,16 @@ char **argv;
                        {
                                printf
                                (
                        {
                                printf
                                (
-                                       "%-10s %-8s %6.2f     %.16s\n",
-                                       acct_buff [i].ac_comm,
-                                       user_list [acct_buff [i].ac_uid],
-                                       x / 60.0,
-                                       ctime (&acct_buff [i].ac_btime)
+                                       "%-*s %s %-*s %-*s %6.2f     %.16s\n"
+                                       , fldsiz(acct, ac_comm)
+                                       , acct_buff [i].ac_comm
+                                       , flagbits(acct_buff [i].ac_flag)
+                                       , fldsiz(utmp, ut_name)
+                                       , user_list [acct_buff [i].ac_uid]
+                                       , fldsiz(utmp, ut_line)
+                                       , tername(acct_buff [i].ac_tty)
+                                       , x / 60.0
+                                       , ctime (&acct_buff [i].ac_btime)
                                );
                        }
                }
                                );
                        }
                }
@@ -147,15 +179,106 @@ unsigned t;
 move (a, b)
 char *a, *b;
 {
 move (a, b)
 char *a, *b;
 {
-       while (*b++ = *a++);
+       while (*b++ = *a++)
+               ;
 }
 
 }
 
-equal (a, b)
-char *a, *b;
+char *
+flagbits(f)
+register int f;
 {
 {
-       for (;; a++, b++)
-       {
-               if (*a != *b) return no;
-               if (!*a)      return yes;
+       register int i = 0;
+       static char flags[20];
+
+# define BIT(flag, ch) flags[i++] = ( f & flag ) ? ch : ' '
+
+       BIT( ASU,       'S');
+       BIT( AFORK,     'F');
+       BIT( ACOMPAT,   'C');
+       BIT( ACORE,     'D');
+       BIT( AXSIG,     'X');
+
+       flags[i] = '\0';
+
+       return(flags);
+}
+
+setupdevs()
+{
+       register DIR * fd;
+       register struct devhash * hashtab;
+       register ndevs = NDEVS;
+       struct direct * dp;
+
+       if ((fd = opendir("/dev")) == NULL) {
+               perror("/dev");
+               return;
+       }
+
+       if ((hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash)))
+           == (struct devhash *) 0) {
+               fprintf(stderr, "No mem for dev table\n");
+               return;
+       }
+
+       while (dp = readdir(fd)) {
+               if (dp->d_ino == 0)
+                       continue;
+#ifdef MELB
+               if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
+                       continue;
+#endif
+               strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line));
+               hashtab->dev_name[fldsiz(utmp, ut_line)] = 0;
+               hashtab->dev_nxt = dev_chain;
+               dev_chain = hashtab;
+               hashtab++;
+               if (--ndevs <= 0)
+                       break;
+       }
+       closedir(fd);
+}
+
+char *
+tername(dev)
+dev_t dev;
+{
+       register struct devhash *hp, *nhp;
+       struct stat statb;
+       char name [fldsiz(devhash, dev_name) + 6];
+       static dev_t lastdev = (dev_t) -1;
+       static char *lastname;
+
+       if (dev == NODEV)
+               return("__");
+
+       if (dev == lastdev)
+               return(lastname);
+       
+       for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
+               if (hp->dev_dev == dev) {
+                       lastdev = dev;
+                       return(lastname = hp->dev_name);
+               }
+
+       for (hp = dev_chain; hp; hp = nhp) {
+               nhp = hp->dev_nxt;
+               strcpy(name, "/dev/");
+               strcat(name, hp->dev_name);
+               if (stat(name, &statb) < 0)     /* name truncated usually */
+                       continue;
+               if ((statb.st_mode & S_IFMT) != S_IFCHR)
+                       continue;
+               hp->dev_dev = statb.st_rdev;
+               hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
+               dev_hash[HASH(hp->dev_dev)] = hp;
+               if (hp->dev_dev == dev) {
+                       dev_chain = nhp;
+                       lastdev = dev;
+                       return(lastname = hp->dev_name);
+               }
        }
        }
+
+       dev_chain = (struct devhash *) 0;
+       return("??");
 }
 }