BSD 4_4 release
[unix-history] / usr / src / usr.bin / systat / pigs.c
index 83e2c92..2e6b097 100644 (file)
@@ -1,23 +1,71 @@
-/*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * Copyright (c) 1980, 1992, 1993
+ *     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
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)pigs.c     5.7 (Berkeley) 5/29/89";
-#endif not lint
+static char sccsid[] = "@(#)pigs.c     8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
 
 /*
  * Pigs display from Bill Reeves at Lucasfilm
  */
 
 
 /*
  * Pigs display from Bill Reeves at Lucasfilm
  */
 
-#include "systat.h"
+#include <sys/param.h>
+#include <sys/dkstat.h>
 #include <sys/dir.h>
 #include <sys/time.h>
 #include <sys/proc.h>
 #include <sys/dir.h>
 #include <sys/time.h>
 #include <sys/proc.h>
+#include <sys/sysctl.h>
+
+#include <curses.h>
+#include <math.h>
+#include <nlist.h>
 #include <pwd.h>
 #include <pwd.h>
-#include <paths.h>
+#include <stdlib.h>
+
+#include "extern.h"
+#include "systat.h"
+
+int compar __P((const void *, const void *));
+
+static int nproc;
+static struct p_times {
+       float pt_pctcpu;
+       struct kinfo_proc *pt_kp;
+} *pt;
+
+static long stime[CPUSTATES];
+static int     fscale;
+static double  lccpu;
 
 WINDOW *
 openpigs()
 
 WINDOW *
 openpigs()
@@ -25,6 +73,7 @@ openpigs()
        return (subwin(stdscr, LINES-5-1, 0, 5, 0));
 }
 
        return (subwin(stdscr, LINES-5-1, 0, 5, 0));
 }
 
+void
 closepigs(w)
        WINDOW *w;
 {
 closepigs(w)
        WINDOW *w;
 {
@@ -35,206 +84,162 @@ closepigs(w)
        delwin(w);
 }
 
        delwin(w);
 }
 
-int    maxind;
-int     factor;
-float   total;
-struct  passwd *getpwuid();
-char    pidname[30];
-long   stime[CPUSTATES];
-double idle;
 
 
+void
 showpigs()
 {
 showpigs()
 {
-       register short auid;
-       register int i, j, y;
-       register float max;
-       register struct p_times *ptptr;
-       struct p_times temppt;
-       register struct users *knptr;
-       char *getpname(), *pnamp;
+       register int i, j, y, k;
+       struct  eproc *ep;
+       float total;
+       int factor;
+       char *uname, *pname, pidname[30];
 
        if (pt == NULL)
                return;
        /* Accumulate the percent of cpu per user. */
 
        if (pt == NULL)
                return;
        /* Accumulate the percent of cpu per user. */
-       ptptr = pt;
-       numprocs = 0;
        total = 0.0;
        total = 0.0;
-       for (i = 0; i < nproc; i++) {
-               /* discard inactive processes */
-               if (ptptr->pt_uid == -1) {
-                       ptptr++;
-                       continue;
-               }
+       for (i = 0; i <= nproc; i++) {
                /* Accumulate the percentage. */
                /* Accumulate the percentage. */
-               total += ptptr->pt_pctcpu;
-               numprocs++;
-               ptptr++;
+               total += pt[i].pt_pctcpu;
        }
 
        }
 
-       pt[numprocs].pt_pctcpu = idle;
-       total += idle;
-       pt[numprocs].pt_uid = -1;
-       pt[numprocs].pt_pid = -1;
-       pt[numprocs].pt_pp = NULL;
-
        if (total < 1.0)
        if (total < 1.0)
-               total = 1.0;
+               total = 1.0;
        factor = 50.0/total;
 
        factor = 50.0/total;
 
-       /* Find the top few by executing a "bubble pass" ten times. */
-       y = numprocs + 1;
-       if (y > wnd->_maxy-1)
-               y = wnd->_maxy-1;
-       for (i = 0; i < y; i++) {
-               ptptr = &pt[i];
-               max = -10000.0;
-               maxind = i;
-               for (j = i; j < numprocs + 1; j++) {
-                       if (ptptr->pt_pctcpu > max) {
-                               max = ptptr->pt_pctcpu;
-                               maxind = j;
-                       }
-                       ptptr++;
-               }
-               if (maxind != i) {
-                       temppt = pt[i];
-                       pt[i] = pt[maxind];
-                       pt[maxind] = temppt;
-               }
-       }
+        qsort(pt, nproc + 1, sizeof (struct p_times), compar);
        y = 1;
        y = 1;
-       ptptr = pt;
-       i = numprocs + 1;
-       if (i > wnd->_maxy-1)
-               i = wnd->_maxy-1;
-       for (; i > 0 && ptptr->pt_pctcpu > 0.01; i--) {
-               /* Find the user's name. */
-               knptr = known;
-               auid = ptptr->pt_uid;
-               for (j = numknown - 1; j >= 0; j--) {
-                       if (knptr->k_uid == auid) {
-                               namp = knptr->k_name;
-                               break;
-                       }
-                       knptr++;
+       i = nproc + 1;
+       if (i > wnd->maxy-1)
+               i = wnd->maxy-1;
+       for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
+               if (pt[k].pt_kp == NULL) {
+                       uname = "";
+                       pname = "<idle>";
                }
                }
-               if (j < 0) {
-                       if (numknown < 30) {
-                               knptr = &known[numknown];
-                               namp = strncpy(knptr->k_name,
-                                   getpwuid(auid)->pw_name, 15);
-                               knptr->k_name[15] = '\0';
-                               knptr->k_uid = auid;
-                               numknown++;
-                       } else
-                               namp = getpwuid(auid)-> pw_name;
+               else {
+                       ep = &pt[k].pt_kp->kp_eproc;
+                       uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0);
+                       pname = pt[k].pt_kp->kp_proc.p_comm;
                }
                }
-               pnamp = getpname(ptptr->pt_pid, ptptr->pt_pp);
                wmove(wnd, y, 0);
                wclrtoeol(wnd);
                wmove(wnd, y, 0);
                wclrtoeol(wnd);
-               mvwaddstr(wnd, y, 0, namp);
-               sprintf(pidname, "%10.10s", pnamp);
+               mvwaddstr(wnd, y, 0, uname);
+               sprintf(pidname, "%10.10s", pname, 0);
                mvwaddstr(wnd, y, 9, pidname);
                mvwaddstr(wnd, y, 9, pidname);
-               wmove(wnd, y++, 20);
-               for (j = ptptr->pt_pctcpu*factor + 0.5; j > 0; j--)
+               wmove(wnd, y, 20);
+               for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--)
                        waddch(wnd, 'X');
                        waddch(wnd, 'X');
-               ptptr++;
        }
        wmove(wnd, y, 0); wclrtobot(wnd);
 }
 
        }
        wmove(wnd, y, 0); wclrtobot(wnd);
 }
 
-static struct nlist nlst[] = {
-#define X_PROC          0
-       { "_proc" },
-#define X_NPROC         1
-       { "_nproc" },
-#define X_USRPTMAP      2
-       { "_Usrptmap" },
-#define X_USRPT         3
-       { "_usrpt" },
-#define X_CPTIME       4
+static struct nlist namelist[] = {
+#define X_FIRST                0
+#define X_CPTIME       0
        { "_cp_time" },
        { "_cp_time" },
+#define X_CCPU          1
+       { "_ccpu" },
+#define X_FSCALE        2
+       { "_fscale" },
+
        { "" }
 };
 
        { "" }
 };
 
+int
 initpigs()
 {
 initpigs()
 {
-       if (nlst[X_PROC].n_type == 0) {
-               nlist(_PATH_UNIX, nlst);
-               if (nlst[X_PROC].n_type == 0) {
-                       error("namelist on %s failed", _PATH_UNIX);
+       fixpt_t ccpu;
+
+       if (namelist[X_FIRST].n_type == 0) {
+               if (kvm_nlist(kd, namelist)) {
+                       nlisterr(namelist);
+                       return(0);
+               }
+               if (namelist[X_FIRST].n_type == 0) {
+                       error("namelist failed");
                        return(0);
                }
        }
                        return(0);
                }
        }
-       if (procp == NULL) {
-               procp = getw(nlst[X_PROC].n_value);
-               nproc = getw(nlst[X_NPROC].n_value);
-       }
-       if (kprocp == NULL)
-               kprocp = (struct proc *)calloc(nproc, sizeof (struct proc));
-       if (usrpt != NULL)
-               return(1);
-       usrpt = (struct pte *)nlst[X_USRPT].n_value;
-       Usrptma = (struct pte *)nlst[X_USRPTMAP].n_value;
-       if (pt == NULL)
-               pt = (struct p_times *)calloc(nproc, sizeof (struct p_times));
-       lseek(kmem, (long)nlst[X_CPTIME].n_value, L_SET);
-       read(kmem, stime, sizeof stime);
+       KREAD(NPTR(X_CPTIME), stime, sizeof (stime));
+       NREAD(X_CCPU, &ccpu, LONG);
+       NREAD(X_FSCALE,  &fscale, LONG);
+       lccpu = log((double) ccpu / fscale);
+
        return(1);
 }
 
        return(1);
 }
 
+void
 fetchpigs()
 {
        register int i;
 fetchpigs()
 {
        register int i;
-       register struct p_times *prt;
        register float time;
        register struct proc *pp;
        register float time;
        register struct proc *pp;
+       register float *pctp;
+       struct kinfo_proc *kpp;
        long ctime[CPUSTATES];
        double t;
        long ctime[CPUSTATES];
        double t;
+       static int lastnproc = 0;
 
 
-       if (nlst[X_PROC].n_type == 0)
+       if (namelist[X_FIRST].n_type == 0)
+               return;
+       if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
+               error("%s", kvm_geterr(kd));
+               if (pt)
+                       free(pt);
                return;
                return;
-       if (kprocp == NULL) {
-               kprocp = (struct proc *)calloc(nproc, sizeof (struct proc));
-               if (kprocp == NULL)
-                       return;
        }
        }
-       if (pt == NULL) {
-               pt = (struct p_times *)calloc(nproc, sizeof (struct p_times));
-               if (pt == NULL)
-                       return;
+       if (nproc > lastnproc) {
+               free(pt);
+               if ((pt = (struct p_times *) malloc 
+                   ((nproc + 1) * sizeof(struct p_times))) == NULL) {
+                   error("Out of memory");
+                   die(0);
+           }
+
        }
        }
-       prt = pt;
-       lseek(kmem, procp, L_SET);
-       read(kmem, kprocp, sizeof (struct proc) * nproc);
-       for (i = 0, pp = kprocp; i < nproc; i++, pp++) {
+       lastnproc = nproc;
+       /*
+        * calculate %cpu for each proc
+        */
+       for (i = 0; i < nproc; i++) {
+               pt[i].pt_kp = &kpp[i];
+               pp = &kpp[i].kp_proc;
+               pctp = &pt[i].pt_pctcpu;
                time = pp->p_time;
                if (time == 0 || (pp->p_flag & SLOAD) == 0)
                time = pp->p_time;
                if (time == 0 || (pp->p_flag & SLOAD) == 0)
-                       continue;
-               prt->pt_pid = pp->p_pid;
-               prt->pt_pp = pp;
-               prt->pt_pctcpu = ((double) pp->p_pctcpu / fscale) /
-                               (1.0 - exp(time * lccpu));
-               prt->pt_uid = pp->p_uid;
-               prt++;
+                       *pctp = 0;
+               else
+                       *pctp = ((double) pp->p_pctcpu / 
+                                       fscale) / (1.0 - exp(time * lccpu));
        }
        }
-       for (; prt < &pt[nproc]; prt++)
-               prt->pt_uid = -1;
-       lseek(kmem, (long)nlst[X_CPTIME].n_value, L_SET);
-       read(kmem, ctime, sizeof ctime);
+       /*
+        * and for the imaginary "idle" process
+        */
+       KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime));
        t = 0;
        for (i = 0; i < CPUSTATES; i++)
                t += ctime[i] - stime[i];
        if (t == 0.0)
                t = 1.0;
        t = 0;
        for (i = 0; i < CPUSTATES; i++)
                t += ctime[i] - stime[i];
        if (t == 0.0)
                t = 1.0;
-       idle = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
+       pt[nproc].pt_kp = NULL;
+       pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
        for (i = 0; i < CPUSTATES; i++)
                stime[i] = ctime[i];
 }
 
        for (i = 0; i < CPUSTATES; i++)
                stime[i] = ctime[i];
 }
 
+void
 labelpigs()
 {
        wmove(wnd, 0, 0); wclrtoeol(wnd);
        mvwaddstr(wnd, 0, 20,
            "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
 }
 labelpigs()
 {
        wmove(wnd, 0, 0); wclrtoeol(wnd);
        mvwaddstr(wnd, 0, 20,
            "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
 }
+
+int
+compar(a, b)
+       const void *a, *b;
+{
+       return (((struct p_times *) a)->pt_pctcpu >
+               ((struct p_times *) b)->pt_pctcpu)? -1: 1;
+}