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 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 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