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