fix silly indirect-through-zero bug
[unix-history] / usr / src / usr.sbin / sa / sa.c
index 411709a..93c28e2 100644 (file)
@@ -1,6 +1,19 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.proprietary.c%
+ */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)sa.c        4.5 (Berkeley) 83/10/07";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)sa.c       4.14 (Berkeley) %G%";
+#endif /* not lint */
 
 /*
  *     Extensive modifications to internal data structures
 
 /*
  *     Extensive modifications to internal data structures
@@ -18,11 +31,13 @@ static      char *sccsid = "@(#)sa.c        4.5 (Berkeley) 83/10/07";
  *     31jan81
  */
 #include <stdio.h>
  *     31jan81
  */
 #include <stdio.h>
+#include <ctype.h>
 #include <sys/types.h>
 #include <sys/acct.h>
 #include <signal.h>
 #include <utmp.h>
 #include <pwd.h>
 #include <sys/types.h>
 #include <sys/acct.h>
 #include <signal.h>
 #include <utmp.h>
 #include <pwd.h>
+#include "pathnames.h"
 
 /* interpret command time accounting */
 
 
 /* interpret command time accounting */
 
@@ -249,12 +264,15 @@ char      *getname();
 #define        SAVACCT "./savacct"
 #define        ACCT    "./acct"
 #else
 #define        SAVACCT "./savacct"
 #define        ACCT    "./acct"
 #else
-#define        USRACCT "/usr/adm/usracct"
-#define        SAVACCT "/usr/adm/savacct"
-#define        ACCT    "/usr/adm/acct"
+#define        USRACCT _PATH_USRACCT
+#define        SAVACCT _PATH_SAVACCT
+#define        ACCT    _PATH_ACCT
 #endif DEBUG
 \f
 
 #endif DEBUG
 \f
 
+char *usracct = USRACCT;
+char *savacct = SAVACCT;
+
 int    cellcmp();
 cell   *junkp = 0;
 /*
 int    cellcmp();
 cell   *junkp = 0;
 /*
@@ -269,7 +287,11 @@ int        htabinstall = 1;
 int    maxuser = -1;
 int    (*cmp)();
 
 int    maxuser = -1;
 int    (*cmp)();
 
-extern tcmp(), ncmp(), bcmp(), dcmp(), Dcmp(), kcmp(), Kcmp();
+/* we assume pagesize is at least 1k */
+int    pgdiv;
+#define        pgtok(x)        ((x) * pgdiv)
+
+extern tcmp(), ncmp(), bflgcmp(), dcmp(), Dcmp(), kcmp(), Kcmp();
 extern double sum();
 
 main(argc, argv)
 extern double sum();
 
 main(argc, argv)
@@ -282,6 +304,9 @@ main(argc, argv)
        int i, j, size, nchunks, smallest;
        struct chunkdesc *chunkvector;
 
        int i, j, size, nchunks, smallest;
        struct chunkdesc *chunkvector;
 
+       pgdiv = getpagesize() / 1024;
+       if (pgdiv == 0)
+               pgdiv = 1;
        maxuser = USERSLOP + getmaxuid();
 
        tabinit();
        maxuser = USERSLOP + getmaxuid();
 
        tabinit();
@@ -303,7 +328,7 @@ main(argc, argv)
 
                case 'b':
                        bflg++;
 
                case 'b':
                        bflg++;
-                       cmp = bcmp;
+                       cmp = bflgcmp;
                        break;
 
                case 'l':
                        break;
 
                case 'l':
@@ -388,16 +413,51 @@ main(argc, argv)
                case 'm':
                        mflg++;
                        break;
                case 'm':
                        mflg++;
                        break;
+
+               case 'U':
+               case 'S':
+                       if (i != 1 || argv[0][2]) {     /* gross! */
+                               fprintf(stderr, "-U and -S options must be separate\n");
+                               exit(1);
+                       }
+                       argc++, argv--;                 /* backup - yuk */
+                       goto doUS;
+
+               default:
+                       fprintf(stderr, "Invalid option %c\n", argv[0][1]);
+                       exit(1);
+               }
+       }
+
+#define optfile(f) {if (argc < 2) \
+                       { fprintf(stderr, "Missing filename\n"); exit(1); } \
+                       argc--, argv++; f = argv[0]; }
+
+doUS:
+       for (argc--, argv++; argc && argv[0][0] == '-'; argc--, argv++) {
+               switch(argv[0][1]) {
+                   case 'U':
+                       optfile(usracct);
+                       break;
+
+                   case 'S':
+                       optfile(savacct);
+                       break;
+
+                   default:
+                       fprintf(stderr, "Invalid option %c\n", argv[0][1]);
+                       exit(1);
                }
        }
                }
        }
+
        if (thres == 0)
                thres = 1;
        if (iflg==0)
                init();
        if (thres == 0)
                thres = 1;
        if (iflg==0)
                init();
-       if (argc<2)
+       if (argc<1)
                doacct(ACCT);
                doacct(ACCT);
-       else while (--argc)
-               doacct(*++argv);
+       else while (argc--)
+               doacct(*argv++);
        if (uflg) {
                return;
        }
        if (uflg) {
                return;
        }
@@ -429,7 +489,7 @@ main(argc, argv)
        }
        if (sflg) {
                signal(SIGINT, SIG_IGN);
        }
        if (sflg) {
                signal(SIGINT, SIG_IGN);
-               if ((ff = fopen(USRACCT, "w")) != NULL) {
+               if ((ff = fopen(usracct, "w")) != NULL) {
                        static  struct  user ZeroUser = {0};
                        struct  user    *up;
                        int     uid;
                        static  struct  user ZeroUser = {0};
                        struct  user    *up;
                        int     uid;
@@ -449,7 +509,7 @@ main(argc, argv)
                                                sizeof(struct Olduser),1,ff);
                        }
                }
                                                sizeof(struct Olduser),1,ff);
                        }
                }
-               if ((ff = fopen(SAVACCT, "w")) == NULL) {
+               if ((ff = fopen(savacct, "w")) == NULL) {
                        printf("Can't save\n");
                        exit(0);
                }
                        printf("Can't save\n");
                        exit(0);
                }
@@ -532,7 +592,7 @@ printmoney()
                                printf("%7u %9.2fcpu %10.0ftio %12.0fk*sec\n",
                                        up->us_cnt, up->us_ctime / 60,
                                        up->us_io,
                                printf("%7u %9.2fcpu %10.0ftio %12.0fk*sec\n",
                                        up->us_cnt, up->us_ctime / 60,
                                        up->us_io,
-                                       up->us_imem / (60 * 2));
+                                       up->us_imem / AHZ);
                        }
                }
        }
                        }
                }
        }
@@ -550,22 +610,22 @@ column(n, a, b, c, d, e)
        }
        col(n, a, treal, "re");
        if (oflg)
        }
        col(n, a, treal, "re");
        if (oflg)
-               col(n, 3600*(b/(b+c)), tcpu+tsys, "u/s");
+               col(n, 60*AHZ*(b/(b+c)), tcpu+tsys, "u/s");
        else if(lflg) {
                col(n, b, tcpu, "u");
                col(n, c, tsys, "s");
        } else
                col(n, b+c, tcpu+tsys, "cp");
        if(tflg)
        else if(lflg) {
                col(n, b, tcpu, "u");
                col(n, c, tsys, "s");
        } else
                col(n, b+c, tcpu+tsys, "cp");
        if(tflg)
-               printf("%8.1f", a/(b+c), "re/cp");
+               printf("%8.1fre/cp", a/(b+c));
        if(dflg || !Dflg)
                printf("%10.0favio", e/(n?n:1));
        else
                printf("%10.0ftio", e);
        if (kflg || !Kflg)
        if(dflg || !Dflg)
                printf("%10.0favio", e/(n?n:1));
        else
                printf("%10.0ftio", e);
        if (kflg || !Kflg)
-               printf("%10.0fk", d/(2*((b+c)!=0.0?(b+c):1.0)));
+               printf("%10.0fk", d/((b+c)!=0.0?(b+c):1.0));
        else
        else
-               printf("%10.0fk*sec", d/(2*60));
+               printf("%10.0fk*sec", d/AHZ);
 }
 
 col(n, a, m, cp)
 }
 
 col(n, a, m, cp)
@@ -574,8 +634,8 @@ col(n, a, m, cp)
 {
 
        if(jflg)
 {
 
        if(jflg)
-               printf("%11.2f%s", a/(n*60.), cp); else
-               printf("%11.2f%s", a/3600., cp);
+               printf("%11.2f%s", a/(n*(double)AHZ), cp); else
+               printf("%11.2f%s", a/(60.*(double)AHZ), cp);
        if(cflg) {
                if(a == m)
                        printf("%9s", ""); else
        if(cflg) {
                if(a == m)
                        printf("%9s", ""); else
@@ -613,35 +673,31 @@ char *f;
                        printf("Input record from %s number %d\n",
                                f, nrecords);
 #endif DEBUG
                        printf("Input record from %s number %d\n",
                                f, nrecords);
 #endif DEBUG
-               if (fbuf.ac_comm[0]==0) {
-                       fbuf.ac_comm[0] = '?';
-               }
-               for (cp = fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++) {
-                       c = *cp & 0377;
-                       if (c && (c < ' ' || c >= 0200)) {
+               for (cp = fbuf.ac_comm; *cp && cp < &fbuf.ac_comm[NC]; cp++)
+                       if (!isascii(*cp) || iscntrl(*cp))
                                *cp = '?';
                                *cp = '?';
-                       }
-               }
+               if (cp == fbuf.ac_comm)
+                       *cp++ = '?';
                if (fbuf.ac_flag&AFORK) {
                if (fbuf.ac_flag&AFORK) {
-                       for (cp=fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++)
-                               if (*cp==0) {
-                                       *cp = '*';
-                                       break;
-                               }
+                       if (cp >= &fbuf.ac_comm[NC])
+                               cp = &fbuf.ac_comm[NC-1];
+                       *cp++ = '*';
                }
                }
+               if (cp < &fbuf.ac_comm[NC])
+                       *cp = '\0';
                x = expand(fbuf.ac_utime) + expand(fbuf.ac_stime);
                x = expand(fbuf.ac_utime) + expand(fbuf.ac_stime);
-               y = fbuf.ac_mem;
-               z = expand(fbuf.ac_io);
+               y = pgtok((u_short)fbuf.ac_mem);
+               z = expand(fbuf.ac_io) / AHZ;
                if (uflg) {
                if (uflg) {
-                       printf("%3d%6.1fcp %6dmem %6dio %.14s\n",
-                           fbuf.ac_uid, x, y, z, fbuf.ac_comm);
+                       printf("%3d %6.2f cpu %8luk mem %6ld io %.*s\n",
+                           fbuf.ac_uid, x/(double)AHZ, y, z, NC, fbuf.ac_comm);
                        continue;
                }
                up = finduser(fbuf.ac_uid);
                if (up == 0)
                        continue;       /* preposterous user id */
                up->us_cnt++;
                        continue;
                }
                up = finduser(fbuf.ac_uid);
                if (up == 0)
                        continue;       /* preposterous user id */
                up->us_cnt++;
-               up->us_ctime += x;
+               up->us_ctime += x/(double)AHZ;
                up->us_imem += x * y;
                up->us_io += z;
                ncom += 1.0;
                up->us_imem += x * y;
                up->us_io += z;
                ncom += 1.0;
@@ -692,7 +748,7 @@ ncmp(p1, p2)
        return(p2->p.count - p1->p.count);
 }
 
        return(p2->p.count - p1->p.count);
 }
 
-bcmp(p1, p2)
+bflgcmp(p1, p2)
        cell *p1, *p2;
 {
        double f1, f2;
        cell *p1, *p2;
 {
        double f1, f2;
@@ -826,7 +882,7 @@ init()
        int uid;
        FILE *f;
 
        int uid;
        FILE *f;
 
-       if ((f = fopen(SAVACCT, "r")) == NULL)
+       if ((f = fopen(savacct, "r")) == NULL)
                goto gshm;
        while (fread((char *)&tbuf, sizeof(struct process), 1, f) == 1) {
                tp = enter(tbuf.name);
                goto gshm;
        while (fread((char *)&tbuf, sizeof(struct process), 1, f) == 1) {
                tp = enter(tbuf.name);
@@ -845,7 +901,7 @@ init()
        }
        fclose(f);
  gshm:
        }
        fclose(f);
  gshm:
-       if ((f = fopen(USRACCT, "r")) == NULL)
+       if ((f = fopen(usracct, "r")) == NULL)
                return;
        for(uid = 0;
            fread((char *)&(userbuf.oldu), sizeof(struct Olduser), 1, f) == 1;
                return;
        for(uid = 0;
            fread((char *)&(userbuf.oldu), sizeof(struct Olduser), 1, f) == 1;
@@ -911,7 +967,7 @@ char *
 makekey(uid)
        int uid;
 {
 makekey(uid)
        int uid;
 {
-       sprintf(UserKey+1, "%04x", uid);
+       (void)sprintf(UserKey+1, "%04x", uid);
        UserKey[0] = USERKEY;
        return(UserKey);
 }
        UserKey[0] = USERKEY;
        return(UserKey);
 }
@@ -955,7 +1011,8 @@ getnames()
 
        setpwent();
        while (pw = getpwent()){
 
        setpwent();
        while (pw = getpwent()){
-               if ( (tp = wasuser(pw->pw_uid)) != 0)
+               /* use first name in passwd file for duplicate uid's */
+               if ((tp = wasuser(pw->pw_uid)) != 0 && !isalpha(tp->us_name[0]))
                        strncpy(tp->us_name, pw->pw_name, NAMELG);
        }
        endpwent();
                        strncpy(tp->us_name, pw->pw_name, NAMELG);
        }
        endpwent();