Annotation of researchv9/jerq/src/sysmon/sysmon.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.