|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3: #include <sys/param.h>
4: #include <sys/types.h>
5: #include <pwd.h>
6: #include <signal.h>
7: #include <sgtty.h>
8: #include "defs.h"
9: #include "load.h"
10: #include "msg.h"
11: #include "scanmail.h"
12:
13: /* structures */
14: struct machdef {
15: struct ld m_old; /* previous set of poal numbers */
16: struct ld m_new; /* current set of load numbers */
17: bool m_cpnew; /* TRUE-> a new cpu percentage exists */
18: bool m_rqnew; /* TRUE-> a new run queue exists */
19: bool m_init; /* first sample should not be displayed */
20: char *m_name; /* name of this node */
21: int m_fd; /* stream for connection to remote machine */
22: };
23:
24: #define MAGIC '_' /* message introduction */
25:
26: /* globals */
27: static int vismon;
28: static struct scanmail sm; /* mail for local machine */
29: static struct machdef md[MAXMACHS]; /* connections are fd limited */
30: static int local; /* offset into md of local machine */
31: static int nm; /* the number of machines */
32: static fd_set g_fd; /* select set for the generators */
33: static char *blitfile; /* binary file to load into blit */
34: static int deathknell; /* true if we should die */
35: #define DEBUG if (debug)
36:
37: /* exported */
38: int debug = 0;
39: int onlymail = 0;
40: int lucaversion = 0;
41: char *thissys;
42:
43: int sendjerq();
44:
45: /* imports */
46: extern int errno;
47:
48: extern int getopt();
49: extern char * getsysname();
50: extern int initload();
51: extern int genload();
52: extern void sminit();
53: extern char *smnext();
54: extern char *strrchr(), *strncpy(), *strcpy();
55: extern long lseek();
56: extern long time();
57: extern char *malloc();
58: extern unsigned int sleep();
59: extern int getutmp();
60: extern int setutmp();
61: extern void resetutmp();
62: extern char *getlogin(), *getenv();
63:
64: /* predefined */
65: static void die();
66: static int catchint();
67: static int forkexec();
68: static void error();
69:
70: /*
71: "user",
72: "nice",
73: "sys",
74: "queue",
75: "idle",
76: */
77:
78: main(ac, av)
79: int ac;
80: char *av[];
81: {
82: int ticks;
83: int per15secs = 15;
84: int permin = 60;
85: int per2mins = 120;
86: char *p;
87:
88: /* get the info for a utmp entry */
89: if (getutmp() < 0)
90: error("can't get login or terminal name");
91:
92: /* make sure we clean up the utmp entry on termination */
93: signal (SIGPIPE, catchint);
94: signal (SIGHUP, catchint);
95: signal (SIGINT, catchint);
96: signal (SIGQUIT, catchint);
97: signal (SIGKILL, catchint);
98:
99: /* put an entry into utmp */
100: if (setutmp() < 0)
101: error("can't set utmp entry");
102:
103: /* initialize load gathering */
104: initload();
105:
106: /* initialize mail spying */
107: thissys = getsysname();
108: p = getenv ("MAIL");
109: sminit (&sm, p, getlogin());
110:
111: ticks = getargs (ac, av);
112: dotime();
113: while (TRUE) {
114: getinfo();
115: docpu();
116: if(per2mins++ >= 120/ticks){
117: doconnect();
118: per2mins = 0;
119: }
120: if(permin++ >= 60/ticks){
121: dotime();
122: doload();
123: permin = 0;
124: }
125: if(per15secs++ >= 15/ticks){
126: domail();
127: per15secs = 0;
128: }
129: scanjerq(0);
130: sleep(ticks);
131: }
132: }
133:
134: /*
135: * Get a request from the jerq. Return
136: * 0 if no request or a request other than R or A
137: * 1 if request is A
138: * -1 if request is R
139: */
140: static int
141: scanjerq(replyflag)
142: int replyflag; /* non-zero to indicate waiting for reply */
143: {
144: int i;
145: fd_set fds;
146: char name[64];
147: char *np, *np2;
148:
149: FD_ZERO(fds);
150: FD_SET(0, fds);
151: if (select(NOFILE, (int *)&fds, (int *)0, 0) != 0) {
152:
153: /* read the command */
154: if ((i = read(0, name, sizeof(name)))<=0)
155: die();
156:
157: /* switch on command type (first letter) */
158: name[i-1] = 0;
159: switch (name[0]) {
160: case 'A':
161: /* accept */
162: return 1;
163:
164: case 'R':
165: /* refuse */
166: return -1;
167:
168: case 'Q':
169: /* quit */
170: die();
171:
172: case 'M':
173: /* monitor request, are we already monitoring it ? */
174: if (replyflag)
175: break;
176: np = strrchr(name, '/');
177: np = np==NULL ? name+1 : np+1;
178: for (i=0; i<nm; i++) {
179: np2 = strrchr(md[i].m_name, '/');
180: np2 = np2==NULL ? md[i].m_name : np2+1;
181: if (strcmp(np, np2)==0)
182: break;
183: }
184: if (i < nm) {
185: /* remove the system */
186: remove_sys(i);
187: } else {
188: /* add the system */
189: add_sys(name+1);
190: }
191:
192: default:
193: /* Oh well */
194: break;
195: }
196: }
197: return 0;
198: }
199:
200: /* try to connect unconnected generators */
201: static int
202: doconnect ()
203: {
204: register int i;
205:
206: /* don't connect to local system (i = 0) */
207: for (i = 0; i < nm; i++)
208: if (md[i].m_fd < 0 && i != local)
209: connectto(i);
210: }
211:
212: /* look for new load information */
213: static int
214: getinfo()
215: {
216: register int i, fd;
217: fd_set rdfd;
218: int len;
219: char buf[128];
220: char noise[10], noise2[10], noise3[10];
221:
222: /* look for waiting input */
223: rdfd = g_fd;
224: while (select (NOFILE, (int *)&rdfd, (int *)0, 0) > 0) {
225:
226: /* find out which machine it's from */
227: for (i = 0; i < nm; i++) {
228: fd = md[i].m_fd;
229: if (fd < 0 || !FD_ISSET(fd, rdfd))
230: continue;
231:
232: /* read the message */
233: DEBUG fprintf(stderr,"info for %s\n", md[i].m_name);
234: if ((len = read(fd, buf, sizeof(buf))) <= 0) {
235: DEBUG fprintf (stderr, "closing\n");
236: close (fd);
237: FD_CLR(fd, g_fd);
238: md[i].m_fd = -1;
239: continue;
240: }
241: if (buf[len-1] == '\n')
242: buf[len-1] = '\0';
243:
244: /* switch on message type */
245: switch (buf[0]) {
246: case 'l':
247: sscanf(buf,"%s%f%s%d%s%d%d%d%d%d",
248: noise, &md[i].m_new.l_runq,
249: noise2, &md[i].m_new.l_time,
250: noise3, &md[i].m_new.l_cp[0],
251: &md[i].m_new.l_cp[1],
252: &md[i].m_new.l_cp[2],
253: &md[i].m_new.l_cp[3],
254: &md[i].m_new.l_cp[4]);
255: md[i].m_cpnew = md[i].m_rqnew = TRUE;
256: break;
257: case 'f':
258: sendmail (buf+5, i);
259: break;
260: }
261: }
262: rdfd = g_fd;
263: }
264:
265: /* get local info */
266: if (local >= 0) {
267: genload();
268: md[local].m_new = load;
269: md[local].m_cpnew = md[local].m_rqnew = TRUE;
270: }
271: }
272:
273: /* display CPU percentages */
274: char vec[NOFILE*6 + 3];
275: static int
276: docpu()
277: {
278: register int i, j, sum;
279: char *vp = vec;
280: int diff[5];
281: long l;
282:
283: for (i = 0; i < (onlymail ? 1 : nm); i++) {
284: if (md[i].m_cpnew) {
285: l = md[i].m_new.l_cp[3];
286: md[i].m_new.l_cp[3] = md[i].m_new.l_cp[4];
287: md[i].m_new.l_cp[4] = l;
288: *vp++ = i + '0';
289: for (sum=j=0; j<5; j++)
290: sum += (diff[j] = (md[i].m_new.l_cp[j] - md[i].m_old.l_cp[j]));
291: sum = sum ? sum : 1;
292: for (j=0; j<5; j++) {
293: *vp++ = (diff[j] * 100) / sum;
294: md[i].m_old.l_cp[j] = md[i].m_new.l_cp[j];
295: }
296: if (md[i].m_init) {
297: md[i].m_init = FALSE;
298: vp -= 6;
299: }
300: md[i].m_cpnew = FALSE;
301: }
302: }
303: if (vp != vec)
304: sendjerq('V', vec, vp - vec);
305: }
306:
307:
308: /* read the arguments */
309: static int
310: getargs (ac, av)
311: int ac;
312: char *av[];
313: {
314: int i;
315: int ticks = 5;
316: char *myname, *p;
317:
318: myname = strrchr(av[0], '/');
319: myname = myname == NULL ? av[0] : myname+1;
320:
321: /* read the tick value and arguments */
322: if (ac > 1 && av[1][0] == '-') {
323: switch (av[1][1] & 0xff) {
324: case 'f':
325: blitfile = av[2];
326: av++, ac--;
327: break;
328: case 'd':
329: debug = 1;
330: break;
331: case 'm':
332: onlymail = 1;
333: break;
334: case 'l':
335: lucaversion = 1;
336: break;
337: default:
338: ticks = -atoi(av[1]);
339: if (ticks < 2)
340: ticks = 2;
341: }
342: av++, ac--;
343: }
344:
345: /* initialize entries */
346: for (i = 0; i<MAXMACHS; i++)
347: md[i].m_fd = -1;
348:
349: /* set up the communications */
350: if (!debug)
351: (void)startblit();
352:
353: /* are we vismon? */
354: if (strcmp(myname, "vismon") == 0) {
355: sendjerq('Q', (char *)0, 0);
356: while(!(i=scanjerq(1)));
357: if (i > 0)
358: vismon++;
359: }
360:
361: /* who to watch */
362: for (nm = 0, p = getsysname(); ac > 0; av++, ac--, p = *av) {
363: add_sys (p);
364: }
365:
366: /* get symbols and things */
367: return (ticks);
368: }
369:
370: static int
371: add_sys(p)
372: char *p;
373: {
374: int i;
375:
376: md[nm].m_name = (char *)strcpy(malloc(strlen(p)+1), p);
377: for (i = 0; i < 5; i++)
378: md[nm].m_old.l_cp[i] = 0;
379: md[nm].m_cpnew = FALSE;
380: md[nm].m_rqnew = FALSE;
381: md[nm].m_init = TRUE;
382: md[nm].m_fd = -1;
383: if (!onlymail || nm == 0) {
384: p = strrchr(p, '/');
385: p = p==NULL ? md[nm].m_name : p+1;
386: sendjerq('N', p, strlen(p));
387: while(!(i=scanjerq(1)));
388: if (i < 0)
389: return;
390: }
391: if (nm != local)
392: connectto(nm);
393: nm++;
394: }
395:
396: static int
397: remove_sys(i)
398: int i;
399: {
400: char which;
401:
402: /* tell jerq to forget it */
403: which = i + '0';
404: sendjerq('R', &which, sizeof(which));
405:
406: /* special case for local machine */
407: if (local == i)
408: local = -1;
409:
410: /* close connection to server */
411: if (md[i].m_fd >= 0) {
412: close(md[i].m_fd);
413: FD_CLR(md[i].m_fd, g_fd);
414: }
415:
416: /* compact what's left */
417: for (; i < nm; i++)
418: md[i] = md[i+1];
419: --nm;
420: }
421:
422: static int
423: startblit()
424: {
425: char *getenv();
426: char *term = getenv("TERM");
427: int status;
428: int pid;
429: struct sgttyb sttybuf, savebuf;
430:
431: ioctl(0, TIOCGETP, &savebuf);
432: sttybuf = savebuf;
433: sttybuf.sg_flags|=RAW;
434: sttybuf.sg_flags&=~ECHO;
435: ioctl(0, TIOCSETP, &sttybuf);
436:
437: if (term != 0 && strcmp(term, "blit") == 0) {
438: if (blitfile == 0)
439: blitfile = lucaversion ? "/usr/blit/mbin/lucamon.m"
440: : "/usr/blit/mbin/sysmon.m";
441: pid = forkexec("/usr/blit/bin/68ld", "68ld", blitfile, (char *)0);
442: } else {
443: if (blitfile == 0)
444: blitfile = lucaversion ? "/usr/jerq/mbin/lucamon.m"
445: : "/usr/jerq/mbin/sysmon.m";
446: pid = forkexec("/usr/jerq/bin/32ld", "32ld", blitfile, (char *)0);
447: }
448: if (pid == -1) {
449: fprintf (stderr, "couldn't load jerq\n", status>>8);
450: die();
451: }
452:
453: /* wait for loading to finish */
454: while (wait(&status) != pid)
455: ;
456: if (status != 0) {
457: ioctl(0, TIOCSETP, &savebuf);
458: error ("jerq load returns error status");
459: }
460: }
461:
462: static int
463: connectto (i)
464: int i;
465: {
466: fprintf(stderr, "Connectto called\n");
467: /*
468: int fd;
469:
470: senddiag("dialing", i);
471: if ((fd = calldaemon (md[i].m_name, "mon")) <= 0) {
472: md[i].m_fd = -1;
473: senddiag("failed", i);
474: } else {
475: DEBUG fprintf (stderr, "connected to %s on %d\n", md[i].m_name, fd);
476: md[i].m_fd = fd;
477: FD_SET(fd, g_fd);
478: senddiag("connected", i);
479: }
480: */
481: }
482:
483: char timevec[]="T01234\n";
484: static int
485: dotime(){
486: char *p, *ctime();
487: long l;
488:
489: l = time ((long *)0);
490: p = ctime(&l);
491: sendjerq ('T', p+11, 5);
492: }
493:
494:
495: /* send the new run queue to the blit */
496: static int
497: doload()
498: {
499: register int i;
500: char buf[132];
501: char *bp = buf;
502: double fabs();
503:
504: for (i = 0; i < (onlymail ? 1 : nm); i++) {
505: if (md[i].m_rqnew) {
506: sprintf(bp, "%c %.2f %c%.2f\t", i + '0', md[i].m_new.l_runq,
507: "-+"[md[i].m_new.l_runq>md[i].m_old.l_runq],
508: fabs(md[i].m_new.l_runq-md[i].m_old.l_runq));
509: bp += strlen(bp);
510: md[i].m_old.l_runq = md[i].m_new.l_runq;
511: md[i].m_rqnew = FALSE;
512: }
513: }
514: if (bp != buf)
515: sendjerq ('L', buf, bp-buf);
516: }
517:
518: /*
519: * mail stuff
520: */
521: static int
522: domail ()
523: {
524: char *p;
525:
526: if (local < 0)
527: return;
528:
529: /* check local mail */
530: while ((p = smnext (&sm, (FILE *)NULL)) != NULL)
531: sendmail (p, local);
532: }
533:
534: static int
535: sendmail(p, i)
536: char *p;
537: int i;
538: {
539: char sender[64];
540: char machine[64];
541: char buf[132];
542:
543: from (p, machine, sender);
544: buf[0] = '0' + (onlymail ? 0 : i);
545: buf[1] = '\0';
546: if (*machine != '\0') {
547: strcat(buf+1, machine);
548: strcat(buf+1, "!");
549: }
550: strcat(buf+1, sender);
551: buf[MAXMAIL+1] = '\0';
552: sendjerq ('M', buf, strlen(buf));
553: if (vismon)
554: sendicon(machine, sender);
555: }
556:
557: static int
558: senddiag(p, i)
559: char *p;
560: int i;
561: {
562: char buf[MAXMAIL+3];
563:
564: buf[0] = '0' + (onlymail ? 0 : i);
565: strncpy(buf+1, p, MAXMAIL);
566: buf[MAXMAIL+1] = '\0';
567: sendjerq ('L', buf, strlen(buf));
568: }
569:
570: /*
571: * send a message to the jerq
572: */
573: extern int
574: sendjerq(type, msg, len)
575: char type; /* message type */
576: char *msg; /* a null terminated message */
577: {
578: char buf[300];
579: char *bp = buf;
580: int n;
581:
582: *bp++ = MAGIC;
583: *bp++ = type;
584: for (; len > 0; len--) {
585: if (*msg == '\n' || *msg == '\\')
586: *bp++ = '\\';
587: *bp++ = *msg++;
588: }
589: *bp++ = '\n';
590: n = write (1, buf, bp-buf);
591: if (n != bp-buf)
592: error("display terminated abnormally");
593: }
594:
595: static int
596: forkexec(a1, a2, a3, a4)
597: char *a1, *a2, *a3, *a4;
598: {
599: int pid;
600:
601: switch (pid = fork()) {
602: case 0:
603: execl (a1, a2, a3, a4);
604: error ("can't execl");
605: case -1:
606: fprintf(stderr, "out of processes");
607: }
608: return pid;
609: }
610:
611: /* catch interrupts and exit */
612: static int
613: catchint()
614: {
615: die();
616: }
617:
618: /* cleanup and exit */
619: static void
620: die()
621: {
622: signal (SIGPIPE, SIG_IGN);
623: signal (SIGALRM, SIG_IGN);
624: signal (SIGHUP, SIG_IGN);
625: signal (SIGINT, SIG_IGN);
626: signal (SIGQUIT, SIG_IGN);
627: signal (SIGKILL, SIG_IGN);
628: resetutmp();
629: exit (0);
630: }
631:
632: /* error messges */
633: static void
634: error (s)
635: char *s;
636: {
637: fprintf(stderr, "sysmon: %s\n", s);
638: die();
639: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.