159336Sbostic /*
259336Sbostic * loadst -- print current time and load statistics.
359336Sbostic * -- James Gosling @ CMU, May 1981
459336Sbostic * loadst [ -n ] [ interval ]
559336Sbostic */
659336Sbostic
759336Sbostic #define NO_SHORTNAMES /* Do not want config to try to include remap.h */
859336Sbostic #include "../src/config.h"
959336Sbostic #include <stdio.h>
1059336Sbostic #include <pwd.h>
1159336Sbostic
1259336Sbostic /* Define two macros KERNEL_FILE (file to find kernel symtab in)
1359336Sbostic and LDAV_SYMBOL (symbol name to look for), based on system type.
1459336Sbostic Also define NLIST_STRUCT if the type `nlist' is a structure we
1559336Sbostic can get from nlist.h; otherwise must use a.out.h and initialize
1659336Sbostic with strcpy. Note that config.h may define NLIST_STRUCT
1759336Sbostic for more modern USG systems. */
1859336Sbostic
1959336Sbostic
2059336Sbostic #ifdef LOAD_AVE_TYPE
2159336Sbostic #ifndef NLIST_STRUCT
2259336Sbostic #include <a.out.h>
2359336Sbostic #else /* NLIST_STRUCT */
2459336Sbostic #include <nlist.h>
2559336Sbostic #endif /* NLIST_STRUCT */
2659336Sbostic #endif /* LOAD_AVE_TYPE */
2759336Sbostic
2859336Sbostic /* All this serves to #include <param.h> and clean up the consequences. */
2959336Sbostic #ifdef BSD
3059336Sbostic /* It appears param.h defines BSD and BSD4_3 in 4.3
3159336Sbostic and is not considerate enough to avoid bombing out
3259336Sbostic if they are already defined. */
3359336Sbostic #undef BSD
3459336Sbostic #ifdef BSD4_3
3559336Sbostic #undef BSD4_3
3659336Sbostic #define XBSD4_3 /* XBSD4_3 says BSD4_3 is supposed to be defined. */
3759336Sbostic #endif
3859336Sbostic #include <sys/param.h>
3959336Sbostic /* Now if BSD or BSD4_3 was defined and is no longer,
4059336Sbostic define it again. */
4159336Sbostic #ifndef BSD
4259336Sbostic #define BSD
4359336Sbostic #endif
4459336Sbostic #ifdef XBSD4_3
4559336Sbostic #ifndef BSD4_3
4659336Sbostic #define BSD4_3
4759336Sbostic #endif
4859336Sbostic #endif /* XBSD4_3 */
4959336Sbostic #endif /* BSD */
5059336Sbostic
5159336Sbostic #ifdef USG
5259336Sbostic #include <time.h>
5359336Sbostic #include <sys/types.h>
5459336Sbostic #else /* not USG */
5559336Sbostic #include <sys/time.h>
5659336Sbostic #ifdef LOAD_AVE_TYPE
5759336Sbostic #ifndef RTU
5859336Sbostic #ifndef UMAX
5959336Sbostic #ifdef DKSTAT_HEADER_FILE
6059336Sbostic #include <sys/dkstat.h>
6159336Sbostic #else
6259336Sbostic #include <sys/dk.h>
6359336Sbostic #endif /* not DKSTAT_HEADER_FILE */
6459336Sbostic #endif /* UMAX */
6559336Sbostic #endif /* not RTU */
6659336Sbostic #endif /* LOAD_AVE_TYPE */
6759336Sbostic #endif /* USG */
6859336Sbostic
6959336Sbostic #include <sys/stat.h>
7059336Sbostic
7159336Sbostic #ifdef BSD
7259336Sbostic #include <sys/ioctl.h>
7359336Sbostic #endif /* BSD */
7459336Sbostic
7559336Sbostic #ifdef UMAX
7659336Sbostic /*
7759336Sbostic * UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
7859336Sbostic * have a /dev/kmem. Information about the workings of the running kernel
7959336Sbostic * can be gathered with inq_stats system calls.
8059336Sbostic */
8159336Sbostic #include <sys/sysdefs.h>
8259336Sbostic #include <sys/syscall.h>
8359336Sbostic #include <sys/statistics.h>
8459336Sbostic #include <sys/procstats.h>
8559336Sbostic #include <sys/sysstats.h>
8659336Sbostic #endif /* UMAX */
8759336Sbostic
8859336Sbostic /* We don't want Emacs's macro definitions for these USG primitives. */
8959336Sbostic
9059336Sbostic #undef open
9159336Sbostic #undef read
9259336Sbostic #undef close
9359336Sbostic
9459336Sbostic struct tm *localtime ();
9559336Sbostic
9659336Sbostic #ifndef DKXFER_SYMBOL
9759336Sbostic #define DKXFER_SYMBOL "_dk_xfer"
9859336Sbostic #endif
9959336Sbostic #ifndef CPTIME_SYMBOL
10059336Sbostic #define CPTIME_SYMBOL "_cp_time"
10159336Sbostic #endif
10259336Sbostic
10359336Sbostic #ifdef LOAD_AVE_TYPE
10459336Sbostic #ifndef NLIST_STRUCT
10559336Sbostic struct nlist nl[2];
10659336Sbostic #else /* NLIST_STRUCT */
10759336Sbostic struct nlist nl[] =
10859336Sbostic {
10959336Sbostic { LDAV_SYMBOL },
11059336Sbostic #if defined (CPUSTATES) && defined (DK_NDRIVE)
11159336Sbostic #define X_CPTIME 1
11259336Sbostic { CPTIME_SYMBOL },
11359336Sbostic #define X_DKXFER 2
11459336Sbostic { DKXFER_SYMBOL },
11559336Sbostic #endif /* have CPUSTATES and DK_NDRIVE */
11659336Sbostic { 0 },
11759336Sbostic };
11859336Sbostic #endif /* NLIST_STRUCT */
11959336Sbostic #endif /* LOAD_AVE_TYPE */
12059336Sbostic
12159336Sbostic #if defined (CPUSTATES) && defined (DK_NDRIVE)
12259336Sbostic
12359336Sbostic struct
12459336Sbostic {
12559336Sbostic long time[CPUSTATES];
12659336Sbostic long xfer[DK_NDRIVE];
12759336Sbostic } s, s1;
12859336Sbostic
12959336Sbostic double etime;
13059336Sbostic
13159336Sbostic #endif /* have CPUSTATES and DK_NDRIVE */
13259336Sbostic
13359336Sbostic int nflag; /* -n flag -- no newline */
13459336Sbostic int uflag; /* -u flag -- user current user ID rather
13559336Sbostic than login user ID */
13659336Sbostic int repetition; /* repetition interval */
13759336Sbostic
13859336Sbostic #ifdef LOAD_AVE_TYPE
13959336Sbostic LOAD_AVE_TYPE load_average ();
14059336Sbostic #endif /* LOAD_AVE_TYPE */
14159336Sbostic
main(argc,argv)14259336Sbostic main (argc, argv)
14359336Sbostic char **argv;
14459336Sbostic {
14559336Sbostic register int kmem, i;
14659336Sbostic char *mail;
14759336Sbostic char *user_name;
14859336Sbostic struct stat st;
14959336Sbostic #ifdef LOAD_AVE_TYPE
15059336Sbostic LOAD_AVE_TYPE load;
15159336Sbostic #endif /* LOAD_AVE_TYPE */
15259336Sbostic
15359336Sbostic kmem = open ("/dev/kmem", 0);
15459336Sbostic
15559336Sbostic #ifdef LOAD_AVE_TYPE
15659336Sbostic #ifndef NLIST_STRUCT
15759336Sbostic strcpy (nl[0].n_name, LDAV_SYMBOL);
15859336Sbostic strcpy (nl[1].n_name, "");
15959336Sbostic #endif /* not NLIST_STRUCT */
16059336Sbostic
16159336Sbostic nlist (KERNEL_FILE, nl);
16259336Sbostic #endif /* LOAD_AVE_TYPE */
16359336Sbostic
16459336Sbostic while (--argc > 0)
16559336Sbostic {
16659336Sbostic argv++;
16759336Sbostic if (strcmp (*argv, "-n") == 0)
16859336Sbostic nflag++;
16959336Sbostic else if (strcmp (*argv, "-u") == 0)
17059336Sbostic uflag++;
17159336Sbostic else
17259336Sbostic if ((repetition = atoi (*argv)) <= 0)
17359336Sbostic {
17459336Sbostic fprintf (stderr, "Bogus argument: %s\n", *argv);
17559336Sbostic exit (1);
17659336Sbostic }
17759336Sbostic }
17859336Sbostic
17959336Sbostic user_name = uflag ? ((struct passwd *) getpwuid (getuid ())) -> pw_name
18059336Sbostic #ifdef USG
18159336Sbostic : (char *) getenv ("LOGNAME");
18259336Sbostic #else
18359336Sbostic : (char *) getenv ("USER");
18459336Sbostic #endif
18559336Sbostic
18659336Sbostic mail = (char *) getenv ("MAIL");
18759336Sbostic
18859336Sbostic if (mail == 0)
18959336Sbostic {
19059336Sbostic mail = (char *) malloc (strlen (user_name) + 30);
19159336Sbostic
192*59337Sbostic #ifdef BSD4_4
193*59337Sbostic sprintf (mail, "/var/mail/%s", user_name);
194*59337Sbostic #elif defined (USG) && ! defined (XENIX)
19559336Sbostic sprintf (mail, "/usr/mail/%s", user_name);
19659336Sbostic #else /* Xenix, or not USG */
19759336Sbostic sprintf (mail, "/usr/spool/mail/%s", user_name);
19859336Sbostic #endif /* Xenix, or not USG */
19959336Sbostic }
20059336Sbostic
20159336Sbostic if (stat (mail, &st) >= 0
20259336Sbostic && (st.st_mode & S_IFMT) == S_IFDIR)
20359336Sbostic {
20459336Sbostic strcat (mail, "/");
20559336Sbostic strcat (mail, user_name);
20659336Sbostic }
20759336Sbostic
20859336Sbostic while (1)
20959336Sbostic {
21059336Sbostic register struct tm *nowt;
21159336Sbostic long now;
21259336Sbostic
21359336Sbostic time (&now);
21459336Sbostic nowt = localtime (&now);
21559336Sbostic
21659336Sbostic printf ("%d:%02d%s ",
21759336Sbostic ((nowt->tm_hour + 11) % 12) + 1,
21859336Sbostic nowt->tm_min,
21959336Sbostic nowt->tm_hour >= 12 ? "pm" : "am");
22059336Sbostic
22159336Sbostic #ifdef LOAD_AVE_TYPE
22259336Sbostic load = load_average (kmem);
22359336Sbostic if (load != (LOAD_AVE_TYPE) -1)
22459336Sbostic printf("%.2f", LOAD_AVE_CVT (load) / 100.0);
22559336Sbostic #endif /* LOAD_AVE_TYPE */
22659336Sbostic
22759336Sbostic printf ("%s",
22859336Sbostic ((stat (mail, &st) >= 0 && st.st_size > 0)
22959336Sbostic ? " Mail"
23059336Sbostic : ""));
23159336Sbostic
23259336Sbostic #if defined (CPUSTATES) && defined (DK_NDRIVE)
23359336Sbostic if (kmem >= 0)
23459336Sbostic {
23559336Sbostic lseek (kmem, (long) nl[X_CPTIME].n_value, 0);
23659336Sbostic read (kmem, s.time, sizeof s.time);
23759336Sbostic lseek (kmem, (long) nl[X_DKXFER].n_value, 0);
23859336Sbostic read (kmem, s.xfer, sizeof s.xfer);
23959336Sbostic etime = 0;
24059336Sbostic for (i = 0; i < DK_NDRIVE; i++)
24159336Sbostic {
24259336Sbostic register t = s.xfer[i];
24359336Sbostic s.xfer[i] -= s1.xfer[i];
24459336Sbostic s1.xfer[i] = t;
24559336Sbostic }
24659336Sbostic #ifndef BSD4_3
24759336Sbostic for (i = 0; i < CPUSTATES; i++)
24859336Sbostic {
24959336Sbostic register t = s.time[i];
25059336Sbostic s.time[i] -= s1.time[i];
25159336Sbostic s1.time[i] = t;
25259336Sbostic etime += s.time[i];
25359336Sbostic }
25459336Sbostic if (etime == 0.)
25559336Sbostic etime = 1.;
25659336Sbostic etime /= 60.;
25759336Sbostic
25859336Sbostic #else
25959336Sbostic {
26059336Sbostic static struct timeval tv, tv1;
26159336Sbostic gettimeofday (&tv, 0);
26259336Sbostic etime = (tv.tv_sec - tv1.tv_sec)
26359336Sbostic + (tv.tv_usec - tv1.tv_usec) / 1.0e6;
26459336Sbostic tv1 = tv;
26559336Sbostic }
26659336Sbostic #endif
26759336Sbostic { register max = s.xfer[0];
26859336Sbostic for (i = 1; i < DK_NDRIVE; i++)
26959336Sbostic if (s.xfer[i] > max)
27059336Sbostic max = s.xfer[i];
27159336Sbostic printf ("[%d]", (int) (max / etime + 0.5));
27259336Sbostic }
27359336Sbostic }
27459336Sbostic #endif /* have CPUSTATES and DK_NDRIVE */
27559336Sbostic if (!nflag)
27659336Sbostic putchar ('\n');
27759336Sbostic fflush (stdout);
27859336Sbostic if (repetition <= 0)
27959336Sbostic break;
28059336Sbostic sleep (repetition);
28159336Sbostic
28259336Sbostic #ifdef BSD
28359336Sbostic /* We are about to loop back and write another unit of output. */
28459336Sbostic /* If previous output has not yet been read by Emacs, flush it
28559336Sbostic so the pty output buffer never gets full and Emacs
28659336Sbostic can always get the latest update right away. */
28759336Sbostic /* ??? Someone should write a USG version of this code! */
28859336Sbostic {
28959336Sbostic int zero = 0;
29059336Sbostic
29159336Sbostic ioctl (fileno (stdout), TIOCFLUSH, &zero);
29259336Sbostic }
29359336Sbostic #endif
29459336Sbostic }
29559336Sbostic }
29659336Sbostic
29759336Sbostic #ifdef LOAD_AVE_TYPE
29859336Sbostic
29959336Sbostic LOAD_AVE_TYPE
load_average(kmem)30059336Sbostic load_average (kmem)
30159336Sbostic int kmem;
30259336Sbostic {
30359336Sbostic #ifdef UMAX
30459336Sbostic
30559336Sbostic int i, j;
30659336Sbostic double sum;
30759336Sbostic struct proc_summary proc_sum_data;
30859336Sbostic struct stat_descr proc_info;
30959336Sbostic
31059336Sbostic proc_info.sd_next = NULL;
31159336Sbostic proc_info.sd_subsys = SUBSYS_PROC;
31259336Sbostic proc_info.sd_type = PROCTYPE_SUMMARY;
31359336Sbostic proc_info.sd_addr = (char *) &proc_sum_data;
31459336Sbostic proc_info.sd_size = sizeof (struct proc_summary);
31559336Sbostic proc_info.sd_sizeused = 0;
31659336Sbostic
31759336Sbostic if (inq_stats (1, &proc_info) != 0 )
31859336Sbostic {
31959336Sbostic perror ("sysline proc summary inq_stats");
32059336Sbostic exit (1);
32159336Sbostic }
32259336Sbostic /*
32359336Sbostic * Generate current load average.
32459336Sbostic */
32559336Sbostic sum = 0;
32659336Sbostic for (i = proc_sum_data.ps_nrunidx, j = 0; j < 12; j++)
32759336Sbostic {
32859336Sbostic sum += proc_sum_data.ps_nrun[i];
32959336Sbostic if (--i < 0)
33059336Sbostic i = 179;
33159336Sbostic }
33259336Sbostic return sum / 12;
33359336Sbostic
33459336Sbostic #else /* not UMAX */
33559336Sbostic
33659336Sbostic if (kmem >= 0)
33759336Sbostic {
33859336Sbostic LOAD_AVE_TYPE avenrun[3];
33959336Sbostic avenrun[0] = 0;
34059336Sbostic #ifdef HAVE_GETLOADAVG
34159336Sbostic (void) getloadavg(avenrun, 3);
34259336Sbostic #else
34359336Sbostic lseek (kmem, (long) nl[0].n_value, 0);
34459336Sbostic read (kmem, avenrun, sizeof (avenrun));
34559336Sbostic #endif
34659336Sbostic return avenrun[0];
34759336Sbostic }
34859336Sbostic else
34959336Sbostic return (LOAD_AVE_TYPE) -1;
35059336Sbostic
35159336Sbostic #endif /* UMAX */
35259336Sbostic }
35359336Sbostic
35459336Sbostic #endif /* LOAD_AVE_TYPE */
355