date and time created 87/02/15 16:03:36 by lepreau
[unix-history] / usr / src / usr.bin / w / w.c
index 83c8088..f707f7b 100644 (file)
@@ -1,6 +1,19 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)w.c 4.11 (Berkeley) %G%";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif not lint
+
+#ifndef lint
+static char sccsid[] = "@(#)w.c        5.4 (Berkeley) %G%";
+#endif not lint
+
 /*
  * w - print system status (who and what)
  *
 /*
  * w - print system status (who and what)
  *
@@ -16,11 +29,13 @@ static char *sccsid = "@(#)w.c      4.11 (Berkeley) %G%";
 #include <sys/dir.h>
 #include <sys/user.h>
 #include <sys/proc.h>
 #include <sys/dir.h>
 #include <sys/user.h>
 #include <sys/proc.h>
+#include <sys/ioctl.h>
 #include <machine/pte.h>
 #include <sys/vm.h>
 
 #define NMAX sizeof(utmp.ut_name)
 #define LMAX sizeof(utmp.ut_line)
 #include <machine/pte.h>
 #include <sys/vm.h>
 
 #define NMAX sizeof(utmp.ut_name)
 #define LMAX sizeof(utmp.ut_line)
+#define HMAX sizeof(utmp.ut_host)
 
 #define ARGWIDTH       33      /* # chars left on 80 col crt for args */
 
 
 #define ARGWIDTH       33      /* # chars left on 80 col crt for args */
 
@@ -34,6 +49,7 @@ struct pr {
        time_t  w_time;                 /* CPU time used by this process */
        time_t  w_ctime;                /* CPU time used by children */
        dev_t   w_tty;                  /* tty device of process */
        time_t  w_time;                 /* CPU time used by this process */
        time_t  w_ctime;                /* CPU time used by children */
        dev_t   w_tty;                  /* tty device of process */
+       int     w_uid;                  /* uid of process */
        char    w_comm[15];             /* user.u_comm, null terminated */
        char    w_args[ARGWIDTH+1];     /* args if interesting process */
 } *pr;
        char    w_comm[15];             /* user.u_comm, null terminated */
        char    w_args[ARGWIDTH+1];     /* args if interesting process */
 } *pr;
@@ -72,13 +88,14 @@ int swap;                   /* /dev/kmem, mem, and swap */
 int    nswap;
 int    dmmin, dmmax;
 dev_t  tty;
 int    nswap;
 int    dmmin, dmmax;
 dev_t  tty;
+int    uid;
 char   doing[520];             /* process attached to terminal */
 time_t proctime;               /* cpu time of process in doing */
 double avenrun[3];
 struct proc *aproc;
 
 #define        DIV60(t)        ((t+30)/60)    /* x/60 rounded */ 
 char   doing[520];             /* process attached to terminal */
 time_t proctime;               /* cpu time of process in doing */
 double avenrun[3];
 struct proc *aproc;
 
 #define        DIV60(t)        ((t+30)/60)    /* x/60 rounded */ 
-#define        TTYEQ           (tty == pr[i].w_tty)
+#define        TTYEQ           (tty == pr[i].w_tty && uid == pr[i].w_uid)
 #define IGINT          (1+3*1)         /* ignoring both SIGINT & SIGQUIT */
 
 char   *getargs();
 #define IGINT          (1+3*1)         /* ignoring both SIGINT & SIGQUIT */
 
 char   *getargs();
@@ -87,18 +104,20 @@ char       *ctime();
 char   *rindex();
 FILE   *popen();
 struct tm *localtime();
 char   *rindex();
 FILE   *popen();
 struct tm *localtime();
+time_t findidle();
 
 int    debug;                  /* true if -d flag: debugging output */
 
 int    debug;                  /* true if -d flag: debugging output */
+int    ttywidth = 80;          /* width of tty */
 int    header = 1;             /* true if -h flag: don't print heading */
 int    lflag = 1;              /* true if -l flag: long style output */
 int    header = 1;             /* true if -h flag: don't print heading */
 int    lflag = 1;              /* true if -l flag: long style output */
+int    prfrom = 1;             /* true if not -f flag: print host from */
 int    login;                  /* true if invoked as login shell */
 int    login;                  /* true if invoked as login shell */
-int    idle;                   /* number of minutes user is idle */
+time_t idle;                   /* number of minutes user is idle */
 int    nusers;                 /* number of users logged in now */
 char * sel_user;               /* login of particular user selected */
 char firstchar;                        /* first char of name of prog invoked as */
 time_t jobtime;                /* total cpu time visible */
 time_t now;                    /* the current time of day */
 int    nusers;                 /* number of users logged in now */
 char * sel_user;               /* login of particular user selected */
 char firstchar;                        /* first char of name of prog invoked as */
 time_t jobtime;                /* total cpu time visible */
 time_t now;                    /* the current time of day */
-struct tm *nowt;               /* current time as time struct */
 struct timeval boottime;
 time_t uptime;                 /* time of last reboot & elapsed time since */
 int    np;                     /* number of processes currently active */
 struct timeval boottime;
 time_t uptime;                 /* time of last reboot & elapsed time since */
 int    np;                     /* number of processes currently active */
@@ -117,9 +136,8 @@ main(argc, argv)
        register int i, j;
        char *cp;
        register int curpid, empty;
        register int i, j;
        char *cp;
        register int curpid, empty;
-       char obuf[BUFSIZ];
+       struct winsize win;
 
 
-       setbuf(stdout, obuf);
        login = (argv[0][0] == '-');
        cp = rindex(argv[0], '/');
        firstchar = login ? argv[0][1] : (cp==0) ? argv[0][0] : cp[1];
        login = (argv[0][0] == '-');
        cp = rindex(argv[0], '/');
        firstchar = login ? argv[0][1] : (cp==0) ? argv[0][0] : cp[1];
@@ -134,6 +152,10 @@ main(argc, argv)
                                        debug++;
                                        break;
 
                                        debug++;
                                        break;
 
+                               case 'f':
+                                       prfrom = !prfrom;
+                                       break;
+
                                case 'h':
                                        header = 0;
                                        break;
                                case 'h':
                                        header = 0;
                                        break;
@@ -158,7 +180,7 @@ main(argc, argv)
                        }
                } else {
                        if (!isalnum(argv[1][0]) || argc > 2) {
                        }
                } else {
                        if (!isalnum(argv[1][0]) || argc > 2) {
-                               printf("Usage: %s [ -hlsuw ] [ user ]\n", cp);
+                               printf("Usage: %s [ -hlsfuw ] [ user ]\n", cp);
                                exit(1);
                        } else
                                sel_user = argv[1];
                                exit(1);
                        } else
                                sel_user = argv[1];
@@ -166,6 +188,8 @@ main(argc, argv)
                argc--; argv++;
        }
 
                argc--; argv++;
        }
 
+       if (ioctl(1, TIOCGWINSZ, &win) == -1 || win.ws_col > 70)
+               ttywidth = win.ws_col;
        if ((kmem = open("/dev/kmem", 0)) < 0) {
                fprintf(stderr, "No kmem\n");
                exit(1);
        if ((kmem = open("/dev/kmem", 0)) < 0) {
                fprintf(stderr, "No kmem\n");
                exit(1);
@@ -180,11 +204,10 @@ main(argc, argv)
                readpr();
 
        ut = fopen("/etc/utmp","r");
                readpr();
 
        ut = fopen("/etc/utmp","r");
+       time(&now);
        if (header) {
                /* Print time of day */
        if (header) {
                /* Print time of day */
-               time(&now);
-               nowt = localtime(&now);
-               prtat(nowt);
+               prtat(&now);
 
                /*
                 * Print how long system has been up.
 
                /*
                 * Print how long system has been up.
@@ -219,7 +242,7 @@ main(argc, argv)
                                nusers++;
                }
                rewind(ut);
                                nusers++;
                }
                rewind(ut);
-               printf("  %d users", nusers);
+               printf("  %d user%s", nusers, nusers>1?"s":"");
 
                /*
                 * Print 1, 5, and 15 minute load averages.
 
                /*
                 * Print 1, 5, and 15 minute load averages.
@@ -238,8 +261,12 @@ main(argc, argv)
                        exit(0);
 
                /* Headers for rest of output */
                        exit(0);
 
                /* Headers for rest of output */
-               if (lflag)
+               if (lflag && prfrom)
+                       printf("User     tty from           login@  idle   JCPU   PCPU  what\n");
+               else if (lflag)
                        printf("User     tty       login@  idle   JCPU   PCPU  what\n");
                        printf("User     tty       login@  idle   JCPU   PCPU  what\n");
+               else if (prfrom)
+                       printf("User    tty from            idle  what\n");
                else
                        printf("User    tty  idle  what\n");
                fflush(stdout);
                else
                        printf("User    tty  idle  what\n");
                fflush(stdout);
@@ -268,7 +295,15 @@ main(argc, argv)
                                continue;
                        jobtime += pr[i].w_time + pr[i].w_ctime;
                        proctime += pr[i].w_time;
                                continue;
                        jobtime += pr[i].w_time + pr[i].w_ctime;
                        proctime += pr[i].w_time;
-                       if (debug) {
+                       /* 
+                        * Meaning of debug fields following proc name is:
+                        * & by itself: ignoring both SIGINT and QUIT.
+                        *              (==> this proc is not a candidate.)
+                        * & <i> <q>:   i is SIGINT status, q is quit.
+                        *              0 == DFL, 1 == IGN, 2 == caught.
+                        * *:           proc pgrp == tty pgrp.
+                        */
+                        if (debug) {
                                printf("\t\t%d\t%s", pr[i].w_pid, pr[i].w_args);
                                if ((j=pr[i].w_igintr) > 0)
                                        if (j==IGINT)
                                printf("\t\t%d\t%s", pr[i].w_pid, pr[i].w_args);
                                if ((j=pr[i].w_igintr) > 0)
                                        if (j==IGINT)
@@ -308,6 +343,7 @@ gettty()
        strcat(ttybuf, utmp.ut_line);
        stat(ttybuf, &statbuf);
        tty = statbuf.st_rdev;
        strcat(ttybuf, utmp.ut_line);
        stat(ttybuf, &statbuf);
        tty = statbuf.st_rdev;
+       uid = statbuf.st_uid;
 }
 
 /*
 }
 
 /*
@@ -316,38 +352,55 @@ gettty()
 putline()
 {
        register int tm;
 putline()
 {
        register int tm;
+       int width = ttywidth - 1;
 
        /* print login name of the user */
        printf("%-*.*s ", NMAX, NMAX, utmp.ut_name);
 
        /* print login name of the user */
        printf("%-*.*s ", NMAX, NMAX, utmp.ut_name);
+       width -= NMAX + 1;
 
        /* print tty user is on */
 
        /* print tty user is on */
-       if (lflag)
+       if (lflag && !prfrom) {
                /* long form: all (up to) LMAX chars */
                printf("%-*.*s", LMAX, LMAX, utmp.ut_line);
                /* long form: all (up to) LMAX chars */
                printf("%-*.*s", LMAX, LMAX, utmp.ut_line);
-       else {
+               width -= LMAX;
+        } else {
                /* short form: 2 chars, skipping 'tty' if there */
                if (utmp.ut_line[0]=='t' && utmp.ut_line[1]=='t' && utmp.ut_line[2]=='y')
                        printf("%-2.2s", &utmp.ut_line[3]);
                else
                        printf("%-2.2s", utmp.ut_line);
                /* short form: 2 chars, skipping 'tty' if there */
                if (utmp.ut_line[0]=='t' && utmp.ut_line[1]=='t' && utmp.ut_line[2]=='y')
                        printf("%-2.2s", &utmp.ut_line[3]);
                else
                        printf("%-2.2s", utmp.ut_line);
+               width -= 2;
+       }
+
+       if (prfrom) {
+               printf(" %-14.14s", utmp.ut_host);
+               width -= 15;
        }
 
        }
 
-       if (lflag)
+       if (lflag) {
                /* print when the user logged in */
                /* print when the user logged in */
-               prtat(localtime(&utmp.ut_time));
+               prtat(&utmp.ut_time);
+               width -= 8;
+       }
 
        /* print idle time */
 
        /* print idle time */
-       prttime(idle," ");
+       if (idle >= 36 * 60)
+               printf("%2ddays ", (idle + 12 * 60) / (24 * 60));
+       else
+               prttime(idle," ");
+       width -= 7;
 
        if (lflag) {
                /* print CPU time for all processes & children */
 
        if (lflag) {
                /* print CPU time for all processes & children */
-               prttime(DIV60(jobtime)," ");
+               prttime(jobtime," ");
+               width -= 7;
                /* print cpu time for interesting process */
                /* print cpu time for interesting process */
-               prttime(DIV60(proctime)," ");
+               prttime(proctime," ");
+               width -= 7;
        }
 
        /* what user is doing, either command tail or args */
        }
 
        /* what user is doing, either command tail or args */
-       printf(" %-.32s\n",doing);
+       printf(" %-.*s\n", width-1, doing);
        fflush(stdout);
 }
 
        fflush(stdout);
 }
 
@@ -369,8 +422,12 @@ findidle()
        return(diff);
 }
 
        return(diff);
 }
 
+#define        HR      (60 * 60)
+#define        DAY     (24 * HR)
+#define        MON     (30 * DAY)
+
 /*
 /*
- * prttime prints a time in hours and minutes.
+ * prttime prints a time in hours and minutes or minutes and seconds.
  * The character string tail is printed at the end, obvious
  * strings to pass are "", " ", or "am".
  */
  * The character string tail is printed at the end, obvious
  * strings to pass are "", " ", or "am".
  */
@@ -378,36 +435,42 @@ prttime(tim, tail)
        time_t tim;
        char *tail;
 {
        time_t tim;
        char *tail;
 {
-       register int didhrs = 0;
 
        if (tim >= 60) {
                printf("%3d:", tim/60);
 
        if (tim >= 60) {
                printf("%3d:", tim/60);
-               didhrs++;
-       } else {
-               printf("    ");
-       }
-       tim %= 60;
-       if (tim > 0 || didhrs) {
-               printf(didhrs&&tim<10 ? "%02d" : "%2d", tim);
-       } else {
-               printf("  ");
-       }
+               tim %= 60;
+               printf("%02d", tim);
+       } else if (tim > 0)
+               printf("    %2d", tim);
+       else
+               printf("      ");
        printf("%s", tail);
 }
 
        printf("%s", tail);
 }
 
+char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
 /* prtat prints a 12 hour time given a pointer to a time of day */
 /* prtat prints a 12 hour time given a pointer to a time of day */
-prtat(p)
-       struct tm *p;
+prtat(time)
+       long *time;
 {
 {
-       register int t, pm;
-
-       t = p -> tm_hour;
-       pm = (t > 11);
-       if (t > 11)
-               t -= 12;
-       if (t == 0)
-               t = 12;
-       prttime(t*60 + p->tm_min, pm ? "pm" : "am");
+       struct tm *p;
+       register int hr, pm;
+
+       p = localtime(time);
+       hr = p->tm_hour;
+       pm = (hr > 11);
+       if (hr > 11)
+               hr -= 12;
+       if (hr == 0)
+               hr = 12;
+       if (now - *time <= 18 * HR)
+               prttime(hr * 60 + p->tm_min, pm ? "pm" : "am");
+       else if (now - *time <= 7 * DAY)
+               printf(" %s%2d%s", weekday[p->tm_wday], hr, pm ? "pm" : "am");
+       else
+               printf(" %2d%s%2d", p->tm_mday, month[p->tm_mon], p->tm_year);
 }
 
 /*
 }
 
 /*
@@ -458,7 +521,7 @@ readpr()
                lseek(kmem, (int)(aproc + pn), 0);
                read(kmem, &mproc, sizeof mproc);
                /* decide if it's an interesting process */
                lseek(kmem, (int)(aproc + pn), 0);
                read(kmem, &mproc, sizeof mproc);
                /* decide if it's an interesting process */
-               if (mproc.p_stat==0 || mproc.p_pgrp==0)
+               if (mproc.p_stat==0 || mproc.p_stat==SZOMB || mproc.p_pgrp==0)
                        continue;
                /* find & read in the user structure */
                if ((mproc.p_flag & SLOAD) == 0) {
                        continue;
                /* find & read in the user structure */
                if ((mproc.p_flag & SLOAD) == 0) {
@@ -509,6 +572,7 @@ cont:
                pr[np].w_ctime =
                    up.u_cru.ru_utime.tv_sec + up.u_cru.ru_stime.tv_sec;
                pr[np].w_tty = up.u_ttyd;
                pr[np].w_ctime =
                    up.u_cru.ru_utime.tv_sec + up.u_cru.ru_stime.tv_sec;
                pr[np].w_tty = up.u_ttyd;
+               pr[np].w_uid = mproc.p_uid;
                up.u_comm[14] = 0;      /* Bug: This bombs next field. */
                strcpy(pr[np].w_comm, up.u_comm);
                /*
                up.u_comm[14] = 0;      /* Bug: This bombs next field. */
                strcpy(pr[np].w_comm, up.u_comm);
                /*