386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Sat, 18 Apr 1992 03:23:25 +0000 (19:23 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Sat, 18 Apr 1992 03:23:25 +0000 (19:23 -0800)
Work on file usr/src/usr.bin/w/w.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/usr.bin/w/w.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/w/w.c b/usr/src/usr.bin/w/w.c
new file mode 100644 (file)
index 0000000..ee86f2a
--- /dev/null
@@ -0,0 +1,377 @@
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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
+char copyright[] =
+"@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)w.c        5.29 (Berkeley) 4/23/91";
+#endif /* not lint */
+
+/*
+ * w - print system status (who and what)
+ *
+ * This program is similar to the systat command on Tenex/Tops 10/20
+ *
+ */
+#include <sys/param.h>
+#include <utmp.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <nlist.h>
+#include <kvm.h>
+#include <ctype.h>
+#include <paths.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef SPPWAIT
+#define NEWVM
+#endif
+#ifndef NEWVM
+#include <machine/pte.h>
+#include <sys/vm.h>
+#endif
+
+char   *program;
+int    ttywidth;               /* width of tty */
+int    argwidth;               /* width of tty */
+int    header = 1;             /* true if -h flag: don't print heading */
+int    wcmd = 1;               /* true if this is w(1), and not uptime(1) */
+int    nusers;                 /* number of users logged in now */
+char * sel_user;               /* login of particular user selected */
+time_t now;                    /* the current time of day */
+struct timeval boottime;
+time_t uptime;                 /* time of last reboot & elapsed time since */
+struct utmp utmp;
+struct winsize ws;
+int    sortidle;               /* sort bu idle time */
+
+
+/*
+ * One of these per active utmp entry.  
+ */
+struct entry {
+       struct  entry *next;
+       struct  utmp utmp;
+       dev_t   tdev;           /* dev_t of terminal */
+       int     idle;           /* idle time of terminal in minutes */
+       struct  proc *proc;     /* list of procs in foreground */
+       char    *args;          /* arg list of interesting process */
+} *ep, *ehead = NULL, **nextp = &ehead;
+
+struct nlist nl[] = {
+       { "_boottime" },
+#define X_BOOTTIME     0
+#if defined(hp300) || defined(i386)
+       { "_cn_tty" },
+#define X_CNTTY                1
+#endif
+       { "" },
+};
+
+#define USAGE "[ -hi ] [ user ]"
+#define usage()        fprintf(stderr, "usage: %s: %s\n", program, USAGE)
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       register int i;
+       struct winsize win;
+       register struct proc *p;
+       struct eproc *e;
+       struct stat *stp, *ttystat();
+       FILE *ut;
+       char *cp;
+       int ch;
+       extern char *optarg;
+       extern int optind;
+       char *attime();
+
+       program = argv[0];
+       /*
+        * are we w(1) or uptime(1)
+        */
+       if ((cp = rindex(program, '/')) || *(cp = program) == '-')
+               cp++;
+       if (*cp == 'u')
+               wcmd = 0;
+
+       while ((ch = getopt(argc, argv, "hiflsuw")) != EOF)
+               switch((char)ch) {
+               case 'h':
+                       header = 0;
+                       break;
+               case 'i':
+                       sortidle++;
+                       break;
+               case 'f': case 'l': case 's': case 'u': case 'w':
+                       error("[-flsuw] no longer supported");
+                       usage();
+                       exit(1);
+               case '?':
+               default:
+                       usage();
+                       exit(1);
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (*argv)
+               sel_user = *argv;
+
+       if (header && kvm_nlist(nl) != 0) {
+               error("can't get namelist");
+               exit (1);
+       }
+       time(&now);
+       ut = fopen(_PATH_UTMP, "r");
+       while (fread(&utmp, sizeof(utmp), 1, ut)) {
+               if (utmp.ut_name[0] == '\0')
+                       continue;
+               nusers++;
+               if (wcmd == 0 || (sel_user && 
+                   strncmp(utmp.ut_name, sel_user, UT_NAMESIZE) != 0))
+                       continue;
+               if ((ep = (struct entry *)
+                    calloc(1, sizeof (struct entry))) == NULL) {
+                       error("out of memory");
+                       exit(1);
+               }
+               *nextp = ep;
+               nextp = &(ep->next);
+               bcopy(&utmp, &(ep->utmp), sizeof (struct utmp));
+               stp = ttystat(ep->utmp.ut_line);
+               ep->tdev = stp->st_rdev;
+#if defined(hp300) || defined(i386)
+               /*
+                * XXX  If this is the console device, attempt to ascertain
+                * the true console device dev_t.
+                */
+               if (ep->tdev == 0) {
+                       static dev_t cn_dev;
+
+                       if (nl[X_CNTTY].n_value) {
+                               struct tty cn_tty, *cn_ttyp;
+                               
+                               if (kvm_read((void *)nl[X_CNTTY].n_value,
+                                   &cn_ttyp, sizeof(cn_ttyp)) > 0) {
+                                       (void)kvm_read(cn_ttyp, &cn_tty,
+                                           sizeof (cn_tty));
+                                       cn_dev = cn_tty.t_dev;
+                               }
+                               nl[X_CNTTY].n_value = 0;
+                       }
+                       ep->tdev = cn_dev;
+               }
+#endif
+               ep->idle = ((now - stp->st_atime) + 30) / 60; /* secs->mins */
+               if (ep->idle < 0)
+                       ep->idle = 0;
+       }
+       fclose(ut);
+
+       if (header || wcmd == 0) {
+               double  avenrun[3];
+               int days, hrs, mins;
+
+               /*
+                * Print time of day 
+                */
+               fputs(attime(&now), stdout);
+               /*
+                * Print how long system has been up.
+                * (Found by looking for "boottime" in kernel)
+                */
+               (void)kvm_read((void *)nl[X_BOOTTIME].n_value, &boottime, 
+                   sizeof (boottime));
+               uptime = now - boottime.tv_sec;
+               uptime += 30;
+               days = uptime / (60*60*24);
+               uptime %= (60*60*24);
+               hrs = uptime / (60*60);
+               uptime %= (60*60);
+               mins = uptime / 60;
+
+               printf("  up");
+               if (days > 0)
+                       printf(" %d day%s,", days, days>1?"s":"");
+               if (hrs > 0 && mins > 0) {
+                       printf(" %2d:%02d,", hrs, mins);
+               } else {
+                       if (hrs > 0)
+                               printf(" %d hr%s,", hrs, hrs>1?"s":"");
+                       if (mins > 0)
+                               printf(" %d min%s,", mins, mins>1?"s":"");
+               }
+
+               /* Print number of users logged in to system */
+               printf("  %d user%s", nusers, nusers>1?"s":"");
+
+               /*
+                * Print 1, 5, and 15 minute load averages.
+                */
+               printf(",  load average:");
+               (void)getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
+               for (i = 0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) {
+                       if (i > 0)
+                               printf(",");
+                       printf(" %.2f", avenrun[i]);
+               }
+               printf("\n");
+               if (wcmd == 0)          /* if uptime(1) then done */
+                       exit(0);
+#define HEADER "USER    TTY FROM              LOGIN@  IDLE WHAT\n"
+#define WUSED  (sizeof (HEADER) - sizeof ("WHAT\n"))
+               printf(HEADER);
+       }
+
+       while ((p = kvm_nextproc()) != NULL) {
+               if (p->p_stat == SZOMB || (p->p_flag & SCTTY) == 0)
+                       continue;
+               e = kvm_geteproc(p);
+               for (ep = ehead; ep != NULL; ep = ep->next) {
+                       if (ep->tdev == e->e_tdev && e->e_pgid == e->e_tpgid) {
+                               /*
+                                * Proc is in foreground of this terminal
+                                */
+                               if (proc_compare(ep->proc, p))
+                                       ep->proc = p;
+                               break;
+                       }
+               }
+       }
+       if ((ioctl(1, TIOCGWINSZ, &ws) == -1 &&
+            ioctl(2, TIOCGWINSZ, &ws) == -1 &&
+            ioctl(0, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
+              ttywidth = 79;
+        else
+              ttywidth = ws.ws_col - 1;
+       argwidth = ttywidth - WUSED;
+       if (argwidth < 4)
+               argwidth = 8;
+       for (ep = ehead; ep != NULL; ep = ep->next) {
+               ep->args = strdup(kvm_getargs(ep->proc, kvm_getu(ep->proc)));
+               if (ep->args == NULL) {
+                       error("out of memory");
+                       exit(1);
+               }
+       }
+       /* sort by idle time */
+       if (sortidle && ehead != NULL) {
+               struct entry *from = ehead, *save;
+               
+               ehead = NULL;
+               while (from != NULL) {
+                       for (nextp = &ehead; 
+                           (*nextp) && from->idle >= (*nextp)->idle;
+                           nextp = &(*nextp)->next)
+                               ;
+                       save = from;
+                       from = from->next;
+                       save->next = *nextp;
+                       *nextp = save;
+               }
+       }
+                       
+       for (ep = ehead; ep != NULL; ep = ep->next) {
+               printf("%-*.*s %-2.2s %-*.*s %s",
+                       UT_NAMESIZE, UT_NAMESIZE, ep->utmp.ut_name,
+                       strncmp(ep->utmp.ut_line, "tty", 3) == 0 ? 
+                               ep->utmp.ut_line+3 : ep->utmp.ut_line,
+                       UT_HOSTSIZE, UT_HOSTSIZE, *ep->utmp.ut_host ?
+                               ep->utmp.ut_host : "-",
+                       attime(&ep->utmp.ut_time));
+               if (ep->idle >= 36 * 60)
+                       printf(" %ddays ", (ep->idle + 12 * 60) / (24 * 60));
+               else
+                       prttime(ep->idle, " ");
+               printf("%.*s\n", argwidth, ep->args);
+       }
+       exit(0);
+}
+
+struct stat *
+ttystat(line)
+{
+       static struct stat statbuf;
+       char ttybuf[sizeof (_PATH_DEV) + UT_LINESIZE + 1];
+
+       sprintf(ttybuf, "%s/%.*s", _PATH_DEV, UT_LINESIZE, line);
+       (void) stat(ttybuf, &statbuf);
+
+       return (&statbuf);
+}
+
+/*
+ * 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".
+ */
+prttime(tim, tail)
+       time_t tim;
+       char *tail;
+{
+
+       if (tim >= 60) {
+               printf(" %2d:", tim/60);
+               tim %= 60;
+               printf("%02d", tim);
+       } else if (tim >= 0)
+               printf("    %2d", tim);
+       printf("%s", tail);
+}
+
+#include <varargs.h>
+
+error(va_alist)
+       va_dcl
+{
+       char *fmt;
+       va_list ap;
+
+       fprintf(stderr, "%s: ", program);
+       va_start(ap);
+       fmt = va_arg(ap, char *);
+       (void) vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       fprintf(stderr, "\n");
+}