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 #ifndef RTU 58 #ifndef UMAX 59 #ifdef DKSTAT_HEADER_FILE 60 #include <sys/dkstat.h> 61 #else 62 #include <sys/dk.h> 63 #endif /* not DKSTAT_HEADER_FILE */ 64 #endif /* UMAX */ 65 #endif /* not RTU */ 66 #endif /* LOAD_AVE_TYPE */ 67 #endif /* USG */ 68 69 #include <sys/stat.h> 70 71 #ifdef BSD 72 #include <sys/ioctl.h> 73 #endif /* BSD */ 74 75 #ifdef UMAX 76 /* 77 * UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not 78 * have a /dev/kmem. Information about the workings of the running kernel 79 * can be gathered with inq_stats system calls. 80 */ 81 #include <sys/sysdefs.h> 82 #include <sys/syscall.h> 83 #include <sys/statistics.h> 84 #include <sys/procstats.h> 85 #include <sys/sysstats.h> 86 #endif /* UMAX */ 87 88 /* We don't want Emacs's macro definitions for these USG primitives. */ 89 90 #undef open 91 #undef read 92 #undef close 93 94 struct tm *localtime (); 95 96 #ifndef DKXFER_SYMBOL 97 #define DKXFER_SYMBOL "_dk_xfer" 98 #endif 99 #ifndef CPTIME_SYMBOL 100 #define CPTIME_SYMBOL "_cp_time" 101 #endif 102 103 #ifdef LOAD_AVE_TYPE 104 #ifndef NLIST_STRUCT 105 struct nlist nl[2]; 106 #else /* NLIST_STRUCT */ 107 struct nlist nl[] = 108 { 109 { LDAV_SYMBOL }, 110 #if defined (CPUSTATES) && defined (DK_NDRIVE) 111 #define X_CPTIME 1 112 { CPTIME_SYMBOL }, 113 #define X_DKXFER 2 114 { DKXFER_SYMBOL }, 115 #endif /* have CPUSTATES and DK_NDRIVE */ 116 { 0 }, 117 }; 118 #endif /* NLIST_STRUCT */ 119 #endif /* LOAD_AVE_TYPE */ 120 121 #if defined (CPUSTATES) && defined (DK_NDRIVE) 122 123 struct 124 { 125 long time[CPUSTATES]; 126 long xfer[DK_NDRIVE]; 127 } s, s1; 128 129 double etime; 130 131 #endif /* have CPUSTATES and DK_NDRIVE */ 132 133 int nflag; /* -n flag -- no newline */ 134 int uflag; /* -u flag -- user current user ID rather 135 than login user ID */ 136 int repetition; /* repetition interval */ 137 138 #ifdef LOAD_AVE_TYPE 139 LOAD_AVE_TYPE load_average (); 140 #endif /* LOAD_AVE_TYPE */ 141 142 main (argc, argv) 143 char **argv; 144 { 145 register int kmem, i; 146 char *mail; 147 char *user_name; 148 struct stat st; 149 #ifdef LOAD_AVE_TYPE 150 LOAD_AVE_TYPE load; 151 #endif /* LOAD_AVE_TYPE */ 152 153 kmem = open ("/dev/kmem", 0); 154 155 #ifdef LOAD_AVE_TYPE 156 #ifndef NLIST_STRUCT 157 strcpy (nl[0].n_name, LDAV_SYMBOL); 158 strcpy (nl[1].n_name, ""); 159 #endif /* not NLIST_STRUCT */ 160 161 nlist (KERNEL_FILE, nl); 162 #endif /* LOAD_AVE_TYPE */ 163 164 while (--argc > 0) 165 { 166 argv++; 167 if (strcmp (*argv, "-n") == 0) 168 nflag++; 169 else if (strcmp (*argv, "-u") == 0) 170 uflag++; 171 else 172 if ((repetition = atoi (*argv)) <= 0) 173 { 174 fprintf (stderr, "Bogus argument: %s\n", *argv); 175 exit (1); 176 } 177 } 178 179 user_name = uflag ? ((struct passwd *) getpwuid (getuid ())) -> pw_name 180 #ifdef USG 181 : (char *) getenv ("LOGNAME"); 182 #else 183 : (char *) getenv ("USER"); 184 #endif 185 186 mail = (char *) getenv ("MAIL"); 187 188 if (mail == 0) 189 { 190 mail = (char *) malloc (strlen (user_name) + 30); 191 192 #ifdef BSD4_4 193 sprintf (mail, "/var/mail/%s", user_name); 194 #elif defined (USG) && ! defined (XENIX) 195 sprintf (mail, "/usr/mail/%s", user_name); 196 #else /* Xenix, or not USG */ 197 sprintf (mail, "/usr/spool/mail/%s", user_name); 198 #endif /* Xenix, or not USG */ 199 } 200 201 if (stat (mail, &st) >= 0 202 && (st.st_mode & S_IFMT) == S_IFDIR) 203 { 204 strcat (mail, "/"); 205 strcat (mail, user_name); 206 } 207 208 while (1) 209 { 210 register struct tm *nowt; 211 long now; 212 213 time (&now); 214 nowt = localtime (&now); 215 216 printf ("%d:%02d%s ", 217 ((nowt->tm_hour + 11) % 12) + 1, 218 nowt->tm_min, 219 nowt->tm_hour >= 12 ? "pm" : "am"); 220 221 #ifdef LOAD_AVE_TYPE 222 load = load_average (kmem); 223 if (load != (LOAD_AVE_TYPE) -1) 224 printf("%.2f", LOAD_AVE_CVT (load) / 100.0); 225 #endif /* LOAD_AVE_TYPE */ 226 227 printf ("%s", 228 ((stat (mail, &st) >= 0 && st.st_size > 0) 229 ? " Mail" 230 : "")); 231 232 #if defined (CPUSTATES) && defined (DK_NDRIVE) 233 if (kmem >= 0) 234 { 235 lseek (kmem, (long) nl[X_CPTIME].n_value, 0); 236 read (kmem, s.time, sizeof s.time); 237 lseek (kmem, (long) nl[X_DKXFER].n_value, 0); 238 read (kmem, s.xfer, sizeof s.xfer); 239 etime = 0; 240 for (i = 0; i < DK_NDRIVE; i++) 241 { 242 register t = s.xfer[i]; 243 s.xfer[i] -= s1.xfer[i]; 244 s1.xfer[i] = t; 245 } 246 #ifndef BSD4_3 247 for (i = 0; i < CPUSTATES; i++) 248 { 249 register t = s.time[i]; 250 s.time[i] -= s1.time[i]; 251 s1.time[i] = t; 252 etime += s.time[i]; 253 } 254 if (etime == 0.) 255 etime = 1.; 256 etime /= 60.; 257 258 #else 259 { 260 static struct timeval tv, tv1; 261 gettimeofday (&tv, 0); 262 etime = (tv.tv_sec - tv1.tv_sec) 263 + (tv.tv_usec - tv1.tv_usec) / 1.0e6; 264 tv1 = tv; 265 } 266 #endif 267 { register max = s.xfer[0]; 268 for (i = 1; i < DK_NDRIVE; i++) 269 if (s.xfer[i] > max) 270 max = s.xfer[i]; 271 printf ("[%d]", (int) (max / etime + 0.5)); 272 } 273 } 274 #endif /* have CPUSTATES and DK_NDRIVE */ 275 if (!nflag) 276 putchar ('\n'); 277 fflush (stdout); 278 if (repetition <= 0) 279 break; 280 sleep (repetition); 281 282 #ifdef BSD 283 /* We are about to loop back and write another unit of output. */ 284 /* If previous output has not yet been read by Emacs, flush it 285 so the pty output buffer never gets full and Emacs 286 can always get the latest update right away. */ 287 /* ??? Someone should write a USG version of this code! */ 288 { 289 int zero = 0; 290 291 ioctl (fileno (stdout), TIOCFLUSH, &zero); 292 } 293 #endif 294 } 295 } 296 297 #ifdef LOAD_AVE_TYPE 298 299 LOAD_AVE_TYPE 300 load_average (kmem) 301 int kmem; 302 { 303 #ifdef UMAX 304 305 int i, j; 306 double sum; 307 struct proc_summary proc_sum_data; 308 struct stat_descr proc_info; 309 310 proc_info.sd_next = NULL; 311 proc_info.sd_subsys = SUBSYS_PROC; 312 proc_info.sd_type = PROCTYPE_SUMMARY; 313 proc_info.sd_addr = (char *) &proc_sum_data; 314 proc_info.sd_size = sizeof (struct proc_summary); 315 proc_info.sd_sizeused = 0; 316 317 if (inq_stats (1, &proc_info) != 0 ) 318 { 319 perror ("sysline proc summary inq_stats"); 320 exit (1); 321 } 322 /* 323 * Generate current load average. 324 */ 325 sum = 0; 326 for (i = proc_sum_data.ps_nrunidx, j = 0; j < 12; j++) 327 { 328 sum += proc_sum_data.ps_nrun[i]; 329 if (--i < 0) 330 i = 179; 331 } 332 return sum / 12; 333 334 #else /* not UMAX */ 335 336 if (kmem >= 0) 337 { 338 LOAD_AVE_TYPE avenrun[3]; 339 avenrun[0] = 0; 340 #ifdef HAVE_GETLOADAVG 341 (void) getloadavg(avenrun, 3); 342 #else 343 lseek (kmem, (long) nl[0].n_value, 0); 344 read (kmem, avenrun, sizeof (avenrun)); 345 #endif 346 return avenrun[0]; 347 } 348 else 349 return (LOAD_AVE_TYPE) -1; 350 351 #endif /* UMAX */ 352 } 353 354 #endif /* LOAD_AVE_TYPE */ 355