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