|
|
1.1 ! root 1: /* ! 2: * loadst -- print current time and load statistics. ! 3: * -- James Gosling @ CMU, May 1981 ! 4: * loadst [ -n ] [ interval ] ! 5: */ ! 6: ! 7: #define NO_SHORTNAMES /* Do not want config to try to include remap.h */ ! 8: #include "../src/config.h" ! 9: #include <stdio.h> ! 10: #include <pwd.h> ! 11: ! 12: /* Define two macros KERNEL_FILE (file to find kernel symtab in) ! 13: and LDAV_SYMBOL (symbol name to look for), based on system type. ! 14: Also define NLIST_STRUCT if the type `nlist' is a structure we ! 15: can get from nlist.h; otherwise must use a.out.h and initialize ! 16: with strcpy. Note that config.h may define NLIST_STRUCT ! 17: for more modern USG systems. */ ! 18: ! 19: ! 20: #ifdef LOAD_AVE_TYPE ! 21: #ifndef NLIST_STRUCT ! 22: #include <a.out.h> ! 23: #else /* NLIST_STRUCT */ ! 24: #include <nlist.h> ! 25: #endif /* NLIST_STRUCT */ ! 26: #endif /* LOAD_AVE_TYPE */ ! 27: ! 28: /* All this serves to #include <param.h> and clean up the consequences. */ ! 29: #ifdef BSD ! 30: /* It appears param.h defines BSD and BSD4_3 in 4.3 ! 31: and is not considerate enough to avoid bombing out ! 32: if they are already defined. */ ! 33: #undef BSD ! 34: #ifdef BSD4_3 ! 35: #undef BSD4_3 ! 36: #define XBSD4_3 /* XBSD4_3 says BSD4_3 is supposed to be defined. */ ! 37: #endif ! 38: #include <sys/param.h> ! 39: /* Now if BSD or BSD4_3 was defined and is no longer, ! 40: define it again. */ ! 41: #ifndef BSD ! 42: #define BSD ! 43: #endif ! 44: #ifdef XBSD4_3 ! 45: #ifndef BSD4_3 ! 46: #define BSD4_3 ! 47: #endif ! 48: #endif /* XBSD4_3 */ ! 49: #endif /* BSD */ ! 50: ! 51: #ifdef USG ! 52: #include <time.h> ! 53: #include <sys/types.h> ! 54: #else /* not USG */ ! 55: #include <sys/time.h> ! 56: #ifdef LOAD_AVE_TYPE ! 57: #include <sys/dkstat.h> ! 58: #endif /* LOAD_AVE_TYPE */ ! 59: #endif /* USG */ ! 60: ! 61: #include <sys/stat.h> ! 62: ! 63: #ifdef BSD ! 64: #include <sys/ioctl.h> ! 65: #endif /* BSD */ ! 66: ! 67: #ifdef UMAX ! 68: /* ! 69: * UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not ! 70: * have a /dev/kmem. Information about the workings of the running kernel ! 71: * can be gathered with inq_stats system calls. ! 72: */ ! 73: #include <sys/sysdefs.h> ! 74: #include <sys/syscall.h> ! 75: #include <sys/statistics.h> ! 76: #include <sys/procstats.h> ! 77: #include <sys/sysstats.h> ! 78: #endif /* UMAX */ ! 79: ! 80: /* We don't want Emacs's macro definitions for these USG primitives. */ ! 81: ! 82: #undef open ! 83: #undef read ! 84: #undef close ! 85: ! 86: struct tm *localtime (); ! 87: ! 88: #ifndef DKXFER_SYMBOL ! 89: #define DKXFER_SYMBOL "_dk_xfer" ! 90: #endif ! 91: #ifndef CPTIME_SYMBOL ! 92: #define CPTIME_SYMBOL "_cp_time" ! 93: #endif ! 94: ! 95: #ifdef LOAD_AVE_TYPE ! 96: #ifndef NLIST_STRUCT ! 97: struct nlist nl[2]; ! 98: #else /* NLIST_STRUCT */ ! 99: struct nlist nl[] = ! 100: { ! 101: { LDAV_SYMBOL }, ! 102: #if defined (CPUSTATES) && defined (DK_NDRIVE) ! 103: #define X_CPTIME 1 ! 104: { CPTIME_SYMBOL }, ! 105: #define X_DKXFER 2 ! 106: { DKXFER_SYMBOL }, ! 107: #endif /* have CPUSTATES and DK_NDRIVE */ ! 108: { 0 }, ! 109: }; ! 110: #endif /* NLIST_STRUCT */ ! 111: #endif /* LOAD_AVE_TYPE */ ! 112: ! 113: #if defined (CPUSTATES) && defined (DK_NDRIVE) ! 114: ! 115: struct ! 116: { ! 117: long time[CPUSTATES]; ! 118: long xfer[DK_NDRIVE]; ! 119: } s, s1; ! 120: ! 121: double etime; ! 122: ! 123: #endif /* have CPUSTATES and DK_NDRIVE */ ! 124: ! 125: int nflag; /* -n flag -- no newline */ ! 126: int uflag; /* -u flag -- user current user ID rather ! 127: than login user ID */ ! 128: int repetition; /* repetition interval */ ! 129: ! 130: #ifdef LOAD_AVE_TYPE ! 131: LOAD_AVE_TYPE load_average (); ! 132: #endif /* LOAD_AVE_TYPE */ ! 133: ! 134: main (argc, argv) ! 135: char **argv; ! 136: { ! 137: register int kmem, i; ! 138: char *mail; ! 139: char *user_name; ! 140: struct stat st; ! 141: #ifdef LOAD_AVE_TYPE ! 142: LOAD_AVE_TYPE load; ! 143: #endif /* LOAD_AVE_TYPE */ ! 144: ! 145: kmem = open ("/dev/kmem", 0); ! 146: ! 147: #ifdef LOAD_AVE_TYPE ! 148: #ifndef NLIST_STRUCT ! 149: strcpy (nl[0].n_name, LDAV_SYMBOL); ! 150: strcpy (nl[1].n_name, ""); ! 151: #endif /* not NLIST_STRUCT */ ! 152: ! 153: nlist (KERNEL_FILE, nl); ! 154: #endif /* LOAD_AVE_TYPE */ ! 155: ! 156: while (--argc > 0) ! 157: { ! 158: argv++; ! 159: if (strcmp (*argv, "-n") == 0) ! 160: nflag++; ! 161: else if (strcmp (*argv, "-u") == 0) ! 162: uflag++; ! 163: else ! 164: if ((repetition = atoi (*argv)) <= 0) ! 165: { ! 166: fprintf (stderr, "Bogus argument: %s\n", *argv); ! 167: exit (1); ! 168: } ! 169: } ! 170: ! 171: user_name = uflag ? ((struct passwd *) getpwuid (getuid ())) -> pw_name ! 172: #ifdef USG ! 173: : (char *) getenv ("LOGNAME"); ! 174: #else ! 175: : (char *) getenv ("USER"); ! 176: #endif ! 177: ! 178: mail = (char *) getenv ("MAIL"); ! 179: ! 180: if (mail == 0) ! 181: { ! 182: mail = (char *) malloc (strlen (user_name) + 30); ! 183: ! 184: #if defined (USG) && ! defined (XENIX) ! 185: sprintf (mail, "/usr/mail/%s", user_name); ! 186: #else /* Xenix, or not USG */ ! 187: #ifdef BSD4_4 ! 188: sprintf (mail, "/var/mail/%s", user_name); ! 189: #else ! 190: sprintf (mail, "/usr/spool/mail/%s", user_name); ! 191: #endif ! 192: #endif /* Xenix, or not USG */ ! 193: } ! 194: ! 195: if (stat (mail, &st) >= 0 ! 196: && (st.st_mode & S_IFMT) == S_IFDIR) ! 197: { ! 198: strcat (mail, "/"); ! 199: strcat (mail, user_name); ! 200: } ! 201: ! 202: while (1) ! 203: { ! 204: register struct tm *nowt; ! 205: long now; ! 206: ! 207: time (&now); ! 208: nowt = localtime (&now); ! 209: ! 210: printf ("%d:%02d%s ", ! 211: ((nowt->tm_hour + 11) % 12) + 1, ! 212: nowt->tm_min, ! 213: nowt->tm_hour >= 12 ? "pm" : "am"); ! 214: ! 215: #ifdef LOAD_AVE_TYPE ! 216: load = load_average (kmem); ! 217: if (load != (LOAD_AVE_TYPE) -1) ! 218: printf("%.2f", LOAD_AVE_CVT (load) / 100.0); ! 219: #endif /* LOAD_AVE_TYPE */ ! 220: ! 221: printf ("%s", ! 222: ((stat (mail, &st) >= 0 && st.st_size > 0) ! 223: ? " Mail" ! 224: : "")); ! 225: ! 226: #if defined (CPUSTATES) && defined (DK_NDRIVE) ! 227: if (kmem >= 0) ! 228: { ! 229: lseek (kmem, (long) nl[X_CPTIME].n_value, 0); ! 230: read (kmem, s.time, sizeof s.time); ! 231: lseek (kmem, (long) nl[X_DKXFER].n_value, 0); ! 232: read (kmem, s.xfer, sizeof s.xfer); ! 233: etime = 0; ! 234: for (i = 0; i < DK_NDRIVE; i++) ! 235: { ! 236: register t = s.xfer[i]; ! 237: s.xfer[i] -= s1.xfer[i]; ! 238: s1.xfer[i] = t; ! 239: } ! 240: #ifndef BSD4_3 ! 241: for (i = 0; i < CPUSTATES; i++) ! 242: { ! 243: register t = s.time[i]; ! 244: s.time[i] -= s1.time[i]; ! 245: s1.time[i] = t; ! 246: etime += s.time[i]; ! 247: } ! 248: if (etime == 0.) ! 249: etime = 1.; ! 250: etime /= 60.; ! 251: ! 252: #else ! 253: { ! 254: static struct timeval tv, tv1; ! 255: gettimeofday (&tv, 0); ! 256: etime = (tv.tv_sec - tv1.tv_sec) ! 257: + (tv.tv_usec - tv1.tv_usec) / 1.0e6; ! 258: tv1 = tv; ! 259: } ! 260: #endif ! 261: { register max = s.xfer[0]; ! 262: for (i = 1; i < DK_NDRIVE; i++) ! 263: if (s.xfer[i] > max) ! 264: max = s.xfer[i]; ! 265: printf ("[%d]", (int) (max / etime + 0.5)); ! 266: } ! 267: } ! 268: #endif /* have CPUSTATES and DK_NDRIVE */ ! 269: if (!nflag) ! 270: putchar ('\n'); ! 271: fflush (stdout); ! 272: if (repetition <= 0) ! 273: break; ! 274: sleep (repetition); ! 275: ! 276: #ifdef BSD ! 277: /* We are about to loop back and write another unit of output. */ ! 278: /* If previous output has not yet been read by Emacs, flush it ! 279: so the pty output buffer never gets full and Emacs ! 280: can always get the latest update right away. */ ! 281: /* ??? Someone should write a USG version of this code! */ ! 282: { ! 283: int zero = 0; ! 284: ! 285: ioctl (fileno (stdout), TIOCFLUSH, &zero); ! 286: } ! 287: #endif ! 288: } ! 289: } ! 290: ! 291: #ifdef LOAD_AVE_TYPE ! 292: ! 293: LOAD_AVE_TYPE ! 294: load_average (kmem) ! 295: int kmem; ! 296: { ! 297: #ifdef UMAX ! 298: ! 299: int i, j; ! 300: double sum; ! 301: struct proc_summary proc_sum_data; ! 302: struct stat_descr proc_info; ! 303: ! 304: proc_info.sd_next = NULL; ! 305: proc_info.sd_subsys = SUBSYS_PROC; ! 306: proc_info.sd_type = PROCTYPE_SUMMARY; ! 307: proc_info.sd_addr = (char *) &proc_sum_data; ! 308: proc_info.sd_size = sizeof (struct proc_summary); ! 309: proc_info.sd_sizeused = 0; ! 310: ! 311: if (inq_stats (1, &proc_info) != 0 ) ! 312: { ! 313: perror ("sysline proc summary inq_stats"); ! 314: exit (1); ! 315: } ! 316: /* ! 317: * Generate current load average. ! 318: */ ! 319: sum = 0; ! 320: for (i = proc_sum_data.ps_nrunidx, j = 0; j < 12; j++) ! 321: { ! 322: sum += proc_sum_data.ps_nrun[i]; ! 323: if (--i < 0) ! 324: i = 179; ! 325: } ! 326: return sum / 12; ! 327: ! 328: #else /* not UMAX */ ! 329: ! 330: if (kmem >= 0) ! 331: { ! 332: LOAD_AVE_TYPE avenrun[3]; ! 333: avenrun[0] = 0; ! 334: lseek (kmem, (long) nl[0].n_value, 0); ! 335: read (kmem, avenrun, sizeof (avenrun)); ! 336: return avenrun[0]; ! 337: } ! 338: else ! 339: return (LOAD_AVE_TYPE) -1; ! 340: ! 341: #endif /* UMAX */ ! 342: } ! 343: ! 344: #endif /* LOAD_AVE_TYPE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.