Annotation of 42BSD/ucb/sysline/sysline.c, revision 1.1.1.1

1.1       root        1: static char rcsid[] = "$Header: sysline.c,v 1.4 83/07/31 23:47:49 layer Exp $";
                      2: 
                      3: /*
                      4:  * sysline - system status display on 25th line of terminal
                      5:  * j.k.foderaro
                      6:  *
                      7:  * Prints a variety of information on the special status line of terminals
                      8:  * that have a status display capability.  Cursor motions, status commands,
                      9:  * etc. are gleamed from /etc/termcap.
                     10:  * By default, all information is printed, and flags are given on the command
                     11:  * line to disable the printing of information.  The information and
                     12:  * disabling flags are:
                     13:  *
                     14:  *  flag       what
                     15:  *  -----      ----
                     16:  *             time of day
                     17:  *             load average and change in load average in the last 5 mins
                     18:  *             number of user logged on
                     19:  *   -p                # of processes the users owns which are runnable and the
                     20:  *               number which are suspended.  Processes whose parent is 1
                     21:  *               are not counted.
                     22:  *   -l                users who've logged on and off.
                     23:  *   -m                summarize new mail which has arrived
                     24:  * 
                     25:  *  <other flags>
                     26:  *   -r                use non reverse video
                     27:  *   -c                turn off 25th line for 5 seconds before redisplaying.
                     28:  *   -b                beep once one the half hour, twice on the hour
                     29:  *   +N                refresh display every N seconds.
                     30:  *   -i                print pid first thing
                     31:  *   -e                do simple print designed for an emacs buffer line
                     32:  *   -h                print hostname between time and load average
                     33:  *   -D                print day/date before time of day
                     34:  *   -d                debug mode - print status line data in human readable format
                     35:  *   -q                quiet mode - don't output diagnostic messages
                     36:  *   -s                print Short (left-justified) line if escapes not allowed
                     37:  *   -j                Print left Justified line regardless
                     38:  *
                     39:  */
                     40: 
                     41: /* for 4.2 BSD */
                     42: #define BSD4_2
                     43: 
                     44: #define NETPREFIX "ucb"
                     45: 
                     46: /* turn this on always */
                     47: #define WHO
                     48: 
                     49: /* turn this on if you are on running 4.1a or greater (i.e. a system
                     50:    with the gethostname() function */
                     51: #define HOSTNAME
                     52: #define RWHO
                     53: 
                     54: /* turn this on if you are running on vmunix */
                     55: #define VMUNIX
                     56: 
                     57: /* turn this on if you are running on 4.1c or greater */
                     58: #define NEW_BOOTTIME 
                     59: 
                     60: #include <sys/param.h>
                     61: #include <signal.h>
                     62: #include <stdio.h>
                     63: #include <utmp.h>
                     64: #include <ctype.h>
                     65: #ifndef BSD4_2
                     66: #include <unctrl.h>
                     67: #endif
                     68: #include <sys/time.h>
                     69: #include <sys/stat.h>
                     70: #ifdef VMUNIX
                     71: #include <nlist.h>
                     72: #include <sys/vtimes.h>
                     73: #include <sys/proc.h>
                     74: #endif
                     75: #ifdef pdp11
                     76: #include <a.out.h>
                     77: #include <sys/proc.h>
                     78: #define strcmpn strncmp
                     79: #endif
                     80: #include <curses.h>
                     81: #undef nl
                     82: #ifdef TERMINFO
                     83: #include <term.h>
                     84: #endif
                     85: 
                     86: #ifdef RWHO
                     87: #define        DOWN_THRESHOLD  (2 * 60)
                     88: #define        RWHOLEADER      "/usr/spool/rwho/whod."
                     89: #define        MAXFILENAME     128
                     90: 
                     91: struct whod {
                     92:     char       wd_vers;
                     93:     char       wd_type;
                     94:     char       wd_fill[2];
                     95:     int                wd_sendtime;
                     96:     int                wd_recvtime;
                     97:     char       wd_hostname[32];
                     98:     int                wd_loadav[3];
                     99:     int                wd_boottime;
                    100: };
                    101: 
                    102: struct outmp {
                    103:     char       out_line[8];    /* tty name */
                    104:     char       out_name[8];    /* user id */
                    105:     long       out_time;       /* time on */
                    106: };
                    107: #endif RWHO
                    108: 
                    109: #ifdef VMUNIX
                    110: #define MAXUSERS 100
                    111: #else
                    112: #define MAXUSERS 40
                    113: #endif
                    114: #define DEFDELAY 60    /* update status once per minute */
                    115: #define MAILDIR "/usr/spool/mail"
                    116: 
                    117: /* if MaxLoad is defined, then if the load average exceeded MaxLoad
                    118:  * then the process table will not be scanned and the log in/out data
                    119:  * will not be checked.   The purpose of this is to reduced the load
                    120:  * on the system when it is loaded.
                    121:  */
                    122: #define MaxLoad 6.0
                    123: 
                    124: 
                    125: struct nlist nl[] =
                    126: #ifdef NEW_BOOTTIME
                    127:   { { "_boottime" },   /* After 4.1a the label changed to "boottime" */
                    128: #else
                    129:   { { "_bootime" },    /* Under 4.1a and earlier it is "bootime" */
                    130: #endif
                    131: #define        NL_BOOT 0
                    132:     { "_proc" },
                    133: #define NL_PROC 1
                    134:     { "_avenrun" },
                    135: #define NL_AVEN 2
                    136: #ifdef VMUNIX
                    137:     { "_nproc" },
                    138: #define NL_NPROC 3
                    139: #endif
                    140:     { 0 }};
                    141: 
                    142: struct proc *pr;
                    143: int nproc;
                    144: int procadr;
                    145: 
                    146: double avenrun[3];     /* used for storing load averages */
                    147: 
                    148: int kmem;              /* file pointers for memory */
                    149: int ut;
                    150: int users, nentries;
                    151: 
                    152: #ifdef WHO
                    153: char whofilename[100];
                    154: #endif
                    155: 
                    156: #ifdef RWHO
                    157: char *remotehost[10];
                    158: int nremotes = 0;
                    159: #endif RWHO
                    160: 
                    161: #ifdef HOSTNAME
                    162: char hostname[32];
                    163: #endif
                    164: 
                    165: char lockfilename[100];        /* if exists, will prevent us from running */
                    166: 
                    167: /* flags which determine which info is printed */
                    168: int mailcheck = 1;     /* m - do biff like checking of mail    */
                    169: int proccheck = 1;     /* p - give information on processes    */
                    170: int logcheck  = 1;     /* l - tell who logs in and out         */
                    171: int hostprint = 0;     /* h - print out hostname               */
                    172: int dateprint = 0;     /* h - print out day/date               */
                    173: int quiet     = 0;     /* q - hush diagnostic messages         */
                    174: 
                    175: /* flags which determine how things are printed */
                    176: int clr_bet_ref = 0;   /* c - clear line between refeshes      */
                    177: int reverse     = 1;   /* r - use reverse video                */
                    178: int shortline   = 0;   /* s - short (left-justified) if escapes not allowed */
                    179: int leftline    = 0;   /* j - left-justified even if escapes allowed */
                    180: int sawmail;   /* remember mail was seen to print bells        */
                    181: 
                    182: /* flags which have terminal do random things  */
                    183: int beep      = 0;     /* b - beep every half hour and twice every hour */
                    184: int synch     = 1;     /* synchronize with clock               */
                    185: int printid   = 0;     /* print pid of this process at startup */
                    186: 
                    187: /*
                    188:  * used to turn off reverse video every REVOFF times
                    189:  * in an attempt to not wear out the phospher.
                    190:  */
                    191: #define REVOFF 5
                    192: int revtime = 1;
                    193: 
                    194: /* select output device (status display or straight output (emacs window)) */
                    195: int emacs = 0;         /* assume status display */
                    196: int dbug = 0;
                    197: 
                    198: /* used by mail checker */
                    199: off_t mailsize = 0;
                    200: off_t linebeg = 0;             /* place where we last left off reading */
                    201: 
                    202: /* globals */
                    203: int mailprocessed;
                    204: char *username;
                    205: struct stat stbuf, mstbuf;     /* mstbuf for mail check only */
                    206: char *ourtty,*ttyname();       /* keep track of what tty we're on */
                    207: char *getenv();
                    208: char *tparm(), *tgoto();
                    209: unsigned delay = DEFDELAY;
                    210: int chars;
                    211: short uid;
                    212: double loadavg = 0.0;          /* current load average */
                    213: int fullprocess;
                    214: int users = 0;
                    215: 
                    216: /* strings which control status line display */
                    217: #ifdef TERMINFO
                    218: 
                    219: char   *rev_out, *rev_end, *arrows;
                    220: 
                    221: #else  /* TERMCAP */
                    222: 
                    223: char   to_status_line[64];
                    224: char   from_status_line[64];
                    225: char   dis_status_line[64];
                    226: char   rev_out[20], rev_end[20];
                    227: char   *arrows, *bell = "\007";
                    228: int    eslok;  /* escapes on status line okay (reverse, cursor addressing) */
                    229: int    columns;
                    230: #endif
                    231: 
                    232: /* 
                    233:  * In order to determine how many people are logged on and who has
                    234:  * logged in or out, we read in the /etc/utmp file. We also keep track of 
                    235:  * the previous utmp file.
                    236:  */
                    237: struct utmp uts[2][MAXUSERS];
                    238: 
                    239: outc(c)
                    240: char c;
                    241: {
                    242:        if (dbug)
                    243:                printf("%s", unctrl(c));
                    244:        else putchar(c);
                    245: }
                    246: 
                    247: erroutc(c)
                    248: char c;
                    249: {
                    250:        if (dbug)
                    251:                fprintf(stderr,"%s", unctrl(c));
                    252:        else fputc(c,stderr);
                    253: }
                    254: 
                    255: main(argc,argv)
                    256: char **argv;
                    257: {
                    258:     register new,old,tmp;
                    259:     int clearbotl();
                    260:     char *cp;
                    261:     extern char _sobuf[];
                    262: 
                    263: 
                    264:     setbuf(stdout, _sobuf);
                    265:     signal(SIGINT,SIG_IGN);
                    266:     signal(SIGQUIT,SIG_IGN);
                    267:     signal(SIGALRM,SIG_IGN);
                    268: #ifdef VMUNIX
                    269:     signal(SIGTTOU,SIG_IGN);
                    270: #endif
                    271:     /*
                    272:      * When we logoff, init will do a "vhangup()" on this
                    273:      * tty which turns off I/O access and sends a SIGHUP
                    274:      * signal.  We catch this and thereby clear the status
                    275:      * display.  Note that a bug in 4.1bsd caused the SIGHUP
                    276:      * signal to be sent to the wrong process, so you had to
                    277:      * `kill -HUP' yourself in your .logout file.
                    278:      */
                    279:     signal(SIGHUP,clearbotl);
                    280: 
                    281: #ifdef HOSTNAME
                    282:     gethostname(hostname,sizeof(hostname));
                    283: #endif
                    284: 
                    285:     argv++;
                    286:     while(--argc > 0) {
                    287:        switch(argv[0][0]) {
                    288:            case '-': for(cp = &argv[0][1]; *cp ; cp++)
                    289:                      { 
                    290:                        switch(*cp) {
                    291:                        case 'r' : reverse = 0; /* turn off reverse video */
                    292:                                   break;
                    293:                        case 'c':  clr_bet_ref = 1;
                    294:                                   break;
                    295:                        case 'h':  hostprint = 1;
                    296:                                   break;
                    297:                        case 'D':  dateprint = 1;
                    298:                                   break;
                    299: #ifdef RWHO
                    300:                        case 'H':  if(!strcmp(hostname,argv[1]) ||
                    301:                                      !strcmp(&hostname[strlen(NETPREFIX)]
                    302:                                                ,argv[1]))
                    303:                                   {
                    304:                                           argv++, argc--;
                    305:                                           break;
                    306:                                   }
                    307:                                   remotehost[nremotes++] = argv[1];
                    308:                                   argv++, argc--;
                    309:                                   break;
                    310: #endif RWHO
                    311:                        case 'm':  mailcheck = 0;
                    312:                                   break;
                    313:                        case 'p':  proccheck = 0;
                    314:                                   break;
                    315:                        case 'l':  logcheck = 0;
                    316:                                   break;
                    317:                        case 'b':  beep = 1;    
                    318:                                   break;
                    319:                        case 'i':  printid = 1;
                    320:                                   break;
                    321:                        case 'e':  emacs = 1;
                    322:                                   break;
                    323:                        case 'd':  dbug = 1;
                    324:                                   signal(SIGINT, SIG_DFL);
                    325:                                   signal(SIGQUIT, SIG_DFL);
                    326:                                   break;
                    327:                        case 'q':  quiet = 1;
                    328:                                   break;
                    329:                        case 's':  shortline = 1;
                    330:                                   break;
                    331:                        case 'j':  leftline = 1;
                    332:                                   break;
                    333:                        default:   fprintf(stderr,
                    334:                                        "sysline: bad flag: %c\n",*cp);
                    335:                        }
                    336:                      }
                    337:                      break;
                    338:            case '+': delay = atoi(&argv[0][1]);
                    339:                      if((delay <= 10) || (delay > 500)) delay = DEFDELAY;
                    340:                      synch = 0;        /* no more sync */
                    341:                      break;
                    342:            default:  fprintf(stderr,"sysline: illegal argument %s\n",argv[0]);
                    343:        }
                    344:        argv++;
                    345:     }
                    346:     if(emacs) {
                    347:        columns = 80;
                    348:     } else {
                    349:        /* if not to emacs window, initialize terminal dependent info */
                    350:        initterm();
                    351:     }
                    352:     
                    353:     /* immediately fork and let the parent die if not emacs mode */
                    354:     if(!emacs && !dbug && fork()) exit(0); 
                    355:     uid = getuid();
                    356: 
                    357:     ourtty = ttyname(2);       /* remember what tty we are on */
                    358:     if(printid) { printf("%d\n",getpid()); fflush(stdout);}
                    359:     close(1);
                    360:     dup2(2, 1);
                    361: 
                    362:     strcpy(whofilename,getenv("HOME"));
                    363:     strcat(whofilename,"/.who");
                    364: 
                    365:     strcpy(lockfilename,getenv("HOME"));
                    366:     strcat(lockfilename,"/.syslinelock");
                    367:     
                    368:     if((ut = open("/etc/utmp",0)) < 0)
                    369:     {
                    370:        fprintf(stderr,"Can't open utmp");
                    371:        exit(1);
                    372:     }
                    373: 
                    374:     if((kmem = open("/dev/kmem",0)) < 0)
                    375:     {
                    376:        fprintf(stderr,"Can't open kmem");
                    377:        exit(1);
                    378:     }
                    379: 
                    380:     /* read in namelist in order to get location of symbols */
                    381:     readnamelist();
                    382: 
                    383:     if(proccheck) initprocread();
                    384: 
                    385:     if(mailcheck) 
                    386:     {
                    387:        chdir(MAILDIR);
                    388:        username = getenv("USER");
                    389:        if(stat(username,&mstbuf) != -1)
                    390:        {
                    391:                mailsize = mstbuf.st_size;
                    392:        }
                    393:        else mailsize = 0;
                    394:     }
                    395: 
                    396:     old = 0;
                    397:     new = 1;
                    398: 
                    399:     while(emacs || isloggedin())
                    400:     {
                    401:        if(access(lockfilename,0))
                    402:        {
                    403:            mailprocessed = 0;
                    404:            prtinfo(old,new);
                    405:            sleep(delay);
                    406:            if(clr_bet_ref)
                    407:            {
                    408:                tputs(dis_status_line, 1, outc);
                    409:                fflush(stdout);
                    410:                sleep(5);
                    411:            }
                    412:            revtime = (1 + revtime) % REVOFF;
                    413: 
                    414:            /*
                    415:             * if we have processed mail, then dont switch utmp pointers
                    416:             * since we havent printed the people whove logged in and out
                    417:             */
                    418:            if(!mailprocessed || !fullprocess)
                    419:            {
                    420:                tmp = old;
                    421:                old = new;
                    422:                new = tmp;
                    423:            }
                    424:        } else sleep(60);
                    425:     }
                    426:     clearbotl();
                    427:     /* NOTREACHED */
                    428: }
                    429: 
                    430: isloggedin()
                    431: {
                    432:    /*
                    433:     * you can tell if a person has logged out if the owner of
                    434:     * the tty has changed
                    435:     */
                    436:     struct stat statbuf;
                    437:     if(fstat(2,&statbuf) == 0)
                    438:     {
                    439:        if(statbuf.st_uid == uid) return(1);
                    440:     }
                    441:     return(0); /* not logged in */
                    442: }
                    443: 
                    444: 
                    445: readnamelist()
                    446: {
                    447:        time_t bootime, clock, nintv, time();
                    448: 
                    449: #ifdef pdp11
                    450:        nlist("/unix",nl);
                    451: #else
                    452:        nlist("/vmunix",nl);
                    453: #endif
                    454:        if(nl[0].n_value == 0) {
                    455:            if (!quiet)
                    456:                fprintf(stderr, "No namelist\n");
                    457:            return;
                    458:        }
                    459:        lseek(kmem, (long)nl[NL_BOOT].n_value, 0);
                    460:        read(kmem, &bootime, sizeof(bootime));
                    461:        (void) time(&clock);
                    462:        nintv = clock - bootime;
                    463:        if (nintv <= 0L || nintv > 60L*60L*24L*365L) {
                    464:           if (!quiet)
                    465:                fprintf(stderr, "Time makes no sense... namelist must be wrong\n");
                    466:           nl[NL_PROC].n_value = nl[NL_AVEN].n_value = 0;
                    467:        }
                    468: }
                    469: 
                    470: readutmp(n)
                    471: {
                    472:        lseek(ut,0L,0);
                    473:        nentries = read(ut,&uts[n][0],MAXUSERS*sizeof(struct utmp)) 
                    474:                   / sizeof(struct utmp);
                    475: }
                    476: 
                    477: /* 
                    478:  * read in the process table locations and sizes, and allocate space
                    479:  * for storing the process table.  This is done only once.
                    480:  */
                    481: initprocread()
                    482: {
                    483:        if (nl[NL_PROC].n_value == 0) return;
                    484: #ifdef VMUNIX
                    485:        lseek(kmem,(long)nl[NL_PROC].n_value,0);
                    486:        read(kmem,&procadr,sizeof(procadr));
                    487:        lseek(kmem,(long)nl[NL_NPROC].n_value,0);
                    488:        read(kmem,&nproc,sizeof(nproc));
                    489: #endif
                    490: #ifdef pdp11
                    491:        procadr = nl[NL_PROC].n_value;
                    492:        nproc = NPROC;  /* from param.h */
                    493: #endif
                    494:        pr = (struct proc *) calloc(nproc,sizeof(struct proc));
                    495: }
                    496: 
                    497: /*
                    498:  * read in the process table.  This assumes that initprocread has alread been
                    499:  * called to set up storage.
                    500:  */
                    501: readproctab()
                    502: {
                    503:        if (nl[NL_PROC].n_value == 0) return(0);
                    504:        /* printf("There are %d entries beginning at %x\n",nproc,procadr); */
                    505:        lseek(kmem,(long)procadr,0);
                    506:        read(kmem,pr,nproc * sizeof(struct proc));
                    507:        return(1);
                    508: }
                    509: 
                    510: /*
                    511:  * codes to say what has happened to a particular entry in utmp
                    512:  * NOCH means no change, ON means new person logged on,
                    513:  * OFF means person logged off.
                    514:  */
                    515: #define NOCH 0;
                    516: #define ON 0x1
                    517: #define OFF 0x2
                    518: 
                    519: prtinfo(old,new)
                    520: int old,new;
                    521: {
                    522:        int procrun,procstop;
                    523:        int on,off;
                    524:        int status[MAXUSERS];
                    525:        register int i;
                    526:        double diff;
                    527:        char *sysrup();
                    528: 
                    529:        stringinit();
                    530: 
                    531: #ifdef WHO
                    532:        /* check for file named .who in the home directory */
                    533:        whocheck();
                    534: #endif
                    535: 
                    536:        timeprint();
                    537: 
                    538:        /*
                    539:         * if mail is seen, don't print rest of info, just the mail
                    540:         * reverse new and old so that next time we run, we won't lose log
                    541:         * in and out information
                    542:         */
                    543:        if(mailcheck && (sawmail = mailseen()) )
                    544:        {
                    545:            mailprocessed = 1;
                    546:            goto bottom;
                    547:        }
                    548: 
                    549: #ifdef HOSTNAME
                    550: #ifdef RWHO
                    551:        if(remotehost)
                    552:        {
                    553:                for(i=0; i < nremotes; i++)
                    554:                        stringprt(" %s", sysrup(remotehost[i]));
                    555:        }
                    556: #endif
                    557:        /*
                    558:         * print hostname info if requested
                    559:         */
                    560:        if(hostprint)
                    561:        {
                    562:            stringspace();
                    563:            stringcat(hostname,strlen(hostname),1);
                    564:        }
                    565: #endif
                    566: 
                    567:        /* 
                    568:         * print load average and difference between current load average
                    569:         * and the load average 5 minutes ago
                    570:         */
                    571:        if (nl[NL_AVEN].n_value != 0) {
                    572:                stringspace();
                    573: #ifdef VMUNIX
                    574:                lseek(kmem,(long)nl[NL_AVEN].n_value,0);
                    575:                read(kmem,avenrun,sizeof(avenrun));
                    576: #endif
                    577: #ifdef pdp11
                    578:                loadav(avenrun);
                    579: #endif
                    580:                stringprt("%.1f ",avenrun[0]);
                    581:                if((diff = avenrun[0] - avenrun[1]) < 0.0)
                    582:                     stringprt("%.1f",diff);
                    583:                else stringprt("+%.1f",diff);
                    584:                loadavg = avenrun[0];   /* remember load average */
                    585:        }
                    586: 
                    587:        /*
                    588:         * print log on and off information
                    589:         */
                    590:        stringspace();
                    591: 
                    592:        fullprocess = 1;
                    593:        
                    594: #ifdef MaxLoad 
                    595:        if(loadavg > MaxLoad) fullprocess = 0;  /* too loaded to run */
                    596: #endif
                    597:        /* read utmp file (logged in data) only if we are doing a full
                    598:           process or if this is the first time and we are calculating
                    599:           the number of users
                    600:         */
                    601:        if(fullprocess || (users == 0)) readutmp(new);
                    602: 
                    603: 
                    604:        /* 
                    605:         * make a pass through utmp, checking if person has logged off
                    606:         * or on.  Results are stored in status[]
                    607:         */
                    608:        on = off = 0;
                    609:        /* only do this if it hasn't been done yet (users == 0) or
                    610:         * if the load average is low enough to permit it
                    611:         */
                    612:        if(fullprocess || (users == 0 ))
                    613:        {
                    614:            users = 0;
                    615:            for(i=0 ; i < nentries ; i++)
                    616:            {
                    617:                if(strcmpn(uts[old][i].ut_name,uts[new][i].ut_name,8) != 0)
                    618:                {
                    619:                    if(uts[old][i].ut_name[0] == '\0')
                    620:                    {
                    621:                        status[i] = ON;
                    622:                        on++;
                    623:                    }
                    624:                    else if (uts[new][i].ut_name[0] == '\0')
                    625:                    {
                    626:                        status[i] = OFF;
                    627:                        off++;
                    628:                    }
                    629:                    else {
                    630:                        status[i] = ON | OFF;
                    631:                        on++;
                    632:                        off++;
                    633:                    }
                    634:                }
                    635:                else status[i] = NOCH;
                    636: 
                    637:                if(uts[new][i].ut_name[0]) users++;
                    638:            }
                    639:        }
                    640: 
                    641:        /* at this point we know how many users there are */
                    642:        stringprt("%du",users);
                    643: 
                    644:        /* if there is any unread mail, put out a star */
                    645:        /* fprintf(stderr,"mailsz:%d,mtime:%d,atime:%d\n",
                    646:                mailsize,mstbuf.st_mtime,mstbuf.st_atime); */
                    647:        if((mailsize > 0) && (mstbuf.st_mtime >= mstbuf.st_atime))
                    648:                stringcat("*",1,1);
                    649: 
                    650:        /* if the load is too high, then we indicate that with a - sign */
                    651:        if(!fullprocess && (proccheck || logcheck)) stringcat("-",1,1);
                    652:        
                    653:        /* if we are to check on number of process running, do so now */
                    654:        if(fullprocess && proccheck && readproctab())
                    655:        { 
                    656:            /* 
                    657:             * we are only interested in processes which have the same
                    658:             * uid as us, and whose parent process id is not 1.
                    659:             */
                    660:            procrun = procstop = 0;
                    661:            for(i=0; i < nproc ; i++)
                    662:            {
                    663:                if((pr[i].p_stat == 0) || (pr[i].p_pgrp == 0)) continue; 
                    664:                if((pr[i].p_uid == uid) && (pr[i].p_ppid != 1)) 
                    665:                {
                    666:                    /* printf("found pid %d, stat=%o\n", pr[i].p_pid, pr[i].p_stat); */
                    667:                    switch (pr[i].p_stat) {
                    668: 
                    669:                    case SSTOP:
                    670:                            procstop++;
                    671:                            break;
                    672: 
                    673:                    case SSLEEP:
                    674:                            /*
                    675:                             * sleep can mean waiting for a signal or just
                    676:                             * in a disk or page wait queue ready to run.
                    677:                             * We can tell if it is the later by the pri being
                    678:                             * negative
                    679:                             */
                    680:                            if (pr[i].p_pri < PZERO) procrun++;
                    681:                            break;
                    682: 
                    683:                    case SWAIT:
                    684:                    case SRUN:
                    685:                    case SIDL:
                    686:                            procrun++;
                    687: 
                    688:                    }
                    689:                }
                    690:            }
                    691: 
                    692:            if((procrun > 0) || (procstop > 0))
                    693:            {
                    694:                stringspace();
                    695:                if((procrun > 0) && (procstop > 0)) 
                    696:                {
                    697:                   stringprt("%dr",procrun);
                    698:                   stringprt(" %ds",procstop);
                    699:                }
                    700:                else if(procrun > 0) stringprt("%dr",procrun);
                    701:                     else stringprt("%ds",procstop);
                    702:            }
                    703:        }   
                    704: 
                    705:        /* 
                    706:         * if anyone has logged on or off, and we are interested in it,
                    707:         * print it out
                    708:         */
                    709:        if(logcheck && on)
                    710:        {
                    711:            stringspace();
                    712:            stringprt("on:",on);
                    713:            for(i = 0 ; i < nentries ; i++)
                    714:            {
                    715:                if(status[i] & ON)
                    716:                { 
                    717:                    stringprt(" %.8s",uts[new][i].ut_name);
                    718:                    ttyprint(uts[new][i].ut_line);
                    719:                }
                    720:            }
                    721:        }
                    722: 
                    723:        /* 
                    724:         * check for people logging off if we are intereste
                    725:         */
                    726:        if(logcheck && off)
                    727:        {
                    728:            stringspace();
                    729:            stringprt("off:",off);
                    730:            for(i = 0 ; i < nentries ; i++)
                    731:            {
                    732:                if(status[i] & OFF)
                    733:                { 
                    734:                    stringprt(" %.8s",uts[old][i].ut_name);
                    735:                    ttyprint(uts[old][i].ut_line);
                    736:                }
                    737:            }
                    738:        }
                    739: bottom:
                    740:        /* dump out what we know */
                    741:        stringdump();
                    742: }
                    743: 
                    744: timeprint()
                    745: {
                    746:        long curtime;
                    747:        struct tm *tp, *localtime();
                    748:        static int beepable=0;
                    749: 
                    750:        /* always print time */
                    751:        time(&curtime);
                    752:        tp = localtime(&curtime);
                    753: 
                    754:        if (dateprint)
                    755:                stringprt("%.11s", ctime(&curtime));
                    756:        stringprt("%d:",(tp->tm_hour > 12 ? tp->tm_hour - 12 
                    757:                                     : (tp->tm_hour == 0 ? 12 : tp->tm_hour)));
                    758:        stringprt("%02d",tp->tm_min);
                    759: 
                    760:        if(synch) delay = 60 - tp->tm_sec;      /* sync with clock */
                    761: 
                    762:        /* beepable is used to insure that we get at most one set of beeps
                    763:            every half hour */
                    764:        if(beep && beepable && (tp->tm_min == 30)) 
                    765:        {   
                    766:            tputs(bell, 1, outc); fflush(stdout);
                    767:            beepable = 0;
                    768:        }
                    769:        else if(beep && beepable && (tp->tm_min == 00)) 
                    770:        {
                    771:            tputs(bell, 1, outc); fflush(stdout);
                    772:            sleep(2);
                    773:            tputs(bell, 1, outc); fflush(stdout);
                    774:            beepable = 0;
                    775:        }
                    776:        else if(beep && ((tp->tm_min != 00) || (tp->tm_min != 30)))
                    777:            beepable = 1;
                    778: 
                    779: }
                    780: 
                    781: /*
                    782:  * whocheck -- check for file named .who and print it on the who line first
                    783:  */
                    784: whocheck()
                    785: {
                    786:     register wf,i,chss;
                    787:     char buff[81];
                    788: 
                    789:     if((wf = open(whofilename,0)) >= 0)
                    790:     {
                    791:        chss = read(wf,buff,80);
                    792:        if(chss == 0) 
                    793:        {
                    794:            close(wf);
                    795:            return;
                    796:        }
                    797:        buff[chss] = '\0';
                    798:        /* 
                    799:         * remove all line feeds, and replace by spaces if they are within
                    800:         * the message, else replace them by nulls.
                    801:         */
                    802:        for(i = chss; i >= 0; i--)
                    803:        {
                    804:            if(buff[i] == '\n') 
                    805:            {
                    806:                if(buff[i+1]) buff[i] = ' ';
                    807:                else buff[i] = '\0';
                    808:            }
                    809:        }
                    810:        stringprt("%s",buff);
                    811:        stringspace();
                    812:        close(wf);
                    813:     }
                    814: }
                    815: 
                    816: /* 
                    817:  * ttyprint -- given the name of a tty, print in the string buffer its
                    818:  * short name surrounded by parenthesis.
                    819:  * ttyxx is printed as (xx)
                    820:  * console is printed as (cty)
                    821:  */
                    822: ttyprint(name)
                    823: char *name;
                    824: {
                    825:     char buff[10];
                    826: 
                    827:     if(strcmpn(name,"tty",3)==0)
                    828:     {
                    829:        sprintf(buff,"(%s)",name+3);
                    830:     }
                    831:     else if(strcmp(name,"console")== 0)
                    832:     {
                    833:        sprintf(buff,"(cty)");
                    834:     }
                    835:     else sprintf(buff,"(%s)",name);
                    836: 
                    837:     stringcat(buff,strlen(buff),0);
                    838: }
                    839: 
                    840: /* 
                    841:  * mail checking function 
                    842:  * returns 0 if no mail seen
                    843:  */
                    844: mailseen()
                    845: {
                    846:     FILE *mfd;
                    847:     int retval = 0;
                    848:     int chs,initchs;
                    849:     register char *rp,*cp;
                    850:     char lbuf[100], sendbuf[100];
                    851:     int toprint,seenspace = 0;
                    852: 
                    853:     if(stat(username,&mstbuf) != -1)
                    854:     {
                    855:        if((mstbuf.st_size > mailsize) && ((mfd=fopen(username,"r")) != NULL))
                    856:        {
                    857:            /* fprintf(stderr,"Mail gotten was %db, now %db\n",
                    858:                                 mailsize,stbuf.st_size); */
                    859:            fseek(mfd,mailsize,0);
                    860:            while((initchs = readline(mfd, lbuf, sizeof(lbuf))) != EOF)
                    861:            {
                    862:                if(strcmpn(lbuf,"From",4) == 0)
                    863:                {
                    864:                    cp = lbuf+5;        /* start after the From */
                    865:                    while(*cp && (*++cp != ' ')); /* skip to blank */
                    866:                    *cp = '\0';         /* terminate name */
                    867:                    stringspace();
                    868:                    /*  if(!emacs) stringcat(bell,0,0);   BELL MOVED */
                    869:                    sprintf(sendbuf,"Mail from %s ",lbuf+5);
                    870:                    stringcat(sendbuf,strlen(sendbuf),0);
                    871:                    /* print message preceeded by little arrow */
                    872:                    /* skip over the headers and look for blank line */
                    873:                    while(((chs = readline(mfd, lbuf, sizeof(lbuf))) != EOF) && (chs != 0))
                    874:                        if(strcmpn(lbuf,"Subject",7)==0)
                    875:                        {
                    876:                            sprintf(sendbuf,"on %s",lbuf+9);
                    877:                            stringcat(sendbuf,strlen(sendbuf),1);
                    878:                        }
                    879:                    if(!emacs) stringcat(arrows,2,0);
                    880:                    else stringcat(" : ",3,0);
                    881: 
                    882:                    if(chs != EOF)
                    883:                    {
                    884:                        cp = sendbuf;
                    885:                        toprint = columns - chars; /* space left on line */
                    886:                        lbuf[0] = '\0';
                    887:                        while((chs = readline(mfd, lbuf, sizeof(lbuf))) != EOF)
                    888:                        {
                    889:                            if(toprint > 0)
                    890:                            {
                    891:                                *cp++ = ' ';    /* space before lines */
                    892:                                toprint--;
                    893:                            }
                    894:                            rp = lbuf;
                    895:                            if(strcmpn(lbuf,"From",4) == 0) break;
                    896:                            while(*rp && (toprint > 0))
                    897:                            {
                    898:                                if(isspace(*rp))
                    899:                                { 
                    900:                                    if(!seenspace)
                    901:                                    {
                    902:                                        *cp++ = ' ';
                    903:                                        seenspace = 1;
                    904:                                        toprint--;
                    905:                                    }
                    906:                                }
                    907:                                else {
                    908:                                    *cp++ = *rp;
                    909:                                    seenspace = 0;
                    910:                                    toprint--;
                    911:                                }
                    912:                                rp++;
                    913:                            }
                    914:                        }
                    915:                        *cp = '\0';
                    916:                        stringcat(sendbuf,strlen(sendbuf),1);
                    917:                        /*  if(!emacs) stringcat(bell,0,0);   BELL MOVED */
                    918:                        retval = 1;
                    919:                    }
                    920:                break;
                    921:                }
                    922:            }
                    923:            if(initchs == EOF) 
                    924:            {
                    925:                stringprt("Mail has just arrived",chs);
                    926:            }
                    927:        /*
                    928:         * want to update write time  so a star will
                    929:         * appear after the number of users until the
                    930:         * user reads his mail 
                    931:         */
                    932:        mailsize = linebeg;     
                    933:        touch(username,mfd);
                    934:        fclose(mfd);
                    935:        }
                    936:        else mailsize = mstbuf.st_size;
                    937:     }
                    938:     else mailsize = 0;
                    939:     return(retval);
                    940: }
                    941: 
                    942: /* 
                    943:  * readline -- read a line from fp and store it in buf.
                    944:  * return the number of characters read.
                    945:  */
                    946: readline(fp, buf, maxch)
                    947: FILE *fp;
                    948: char *buf;
                    949: {
                    950:     register char *cp, ch;
                    951:     int size = maxch;
                    952:     long ftell();
                    953: 
                    954:     linebeg = ftell(fp);               /* remember loc where line begins */
                    955:     cp = buf;
                    956:     while(((ch=getc(fp)) != EOF) && (ch != '\n') && (size-- > 0)) *cp++ = ch;
                    957:     *cp = '\0';
                    958:     if((size == maxch) && (ch == EOF)) return (EOF);
                    959:     else return(maxch - size);
                    960: }
                    961:     
                    962: 
                    963: /* string hacking functions */
                    964: 
                    965: int eol;       /* non zero when we have hit the end of line */
                    966: char *sp;
                    967: char strarr[120];
                    968: 
                    969: stringinit()
                    970: {
                    971:     sp = strarr;
                    972:     chars = 0;
                    973:     eol = 0;
                    974: }
                    975: 
                    976: stringprt(format,value)
                    977: char *format;
                    978: {
                    979:     char tempbuf[150];
                    980:     int bufsiz;
                    981: 
                    982:     sprintf(tempbuf,format,value);
                    983:     bufsiz = strlen(tempbuf);
                    984:     stringcat(tempbuf,bufsiz,0);
                    985: }
                    986: 
                    987: stringdump()
                    988: {
                    989:     char bigbuf[200];
                    990:     register char *cp;
                    991:     register int i;
                    992:     char blanks[80];
                    993: 
                    994:     *sp = '\0';
                    995:     bigbuf[0] = 0;
                    996:     if(!emacs) {
                    997:        if (sawmail) strcat(bigbuf, bell);
                    998:        if (eslok) {
                    999:            if(!leftline)
                   1000:                cp = tparm(to_status_line, columns - chars);
                   1001:            else 
                   1002:                cp = tparm(to_status_line, 0);
                   1003:            strcat(bigbuf, cp);
                   1004:        } else {
                   1005:            strcat(bigbuf, to_status_line);
                   1006:            if (!shortline & !leftline) {
                   1007:                for (i=0; i < (columns-chars); i++)
                   1008:                    blanks[i] = ' ';
                   1009:                blanks[columns-chars] = '\0';
                   1010:                strcat(bigbuf, blanks);
                   1011:            }
                   1012:        }
                   1013:        if(reverse && !(revtime == 0)) strcat(bigbuf, rev_out);
                   1014:     }
                   1015:     strcat(bigbuf,strarr);
                   1016:     if (!emacs) {
                   1017:        if (reverse) strcat(bigbuf, rev_end);
                   1018:        strcat(bigbuf, from_status_line);
                   1019:        if (sawmail) {
                   1020:            strcat(bigbuf, bell);
                   1021:            strcat(bigbuf, bell);
                   1022:        }
                   1023:        tputs(bigbuf, 1, outc);
                   1024:        if (dbug) putchar('\n');
                   1025:        fflush(stdout);
                   1026:     } else
                   1027:        write(2,bigbuf,strlen(bigbuf));
                   1028: }
                   1029: 
                   1030: stringspace()
                   1031: {
                   1032:     if(!emacs && reverse && !(revtime == 0)) {
                   1033: #ifdef TERMINFO
                   1034:        stringcat(rev_end, magic_cookie_glitch<=0?0:magic_cookie_glitch, 0);
                   1035:        stringcat(" ",1,0);
                   1036:        stringcat(rev_out, magic_cookie_glitch<=0?0:magic_cookie_glitch, 0);
                   1037: #else
                   1038:        stringcat(rev_end,0,0);
                   1039:        stringcat(" ",1,0);
                   1040:        stringcat(rev_out,0,0);
                   1041: #endif
                   1042:     } else stringcat(" ",1,0);
                   1043: }
                   1044: 
                   1045: /* 
                   1046:  * stringcat :: concatenate the characters in string str to the list we are 
                   1047:  *             building to send out.
                   1048:  *  
                   1049:  * the three args are
                   1050:  *    str - the string to print. may contain funny (terminal control) chars.
                   1051:  *    chrs - the number of printable characters in the string
                   1052:  *    trunc - a flag which is non zero if we should truncate strings which
                   1053:  *           don't fit.  If this is 0 then if a string doesn't completely
                   1054:  *           fit it wont' be printed, this prevents us from getting 1/2
                   1055:  *           way through an escape sequence.
                   1056:  */
                   1057: stringcat(str,chrs,trunc)
                   1058: char *str;
                   1059: {
                   1060: 
                   1061:     if((chrs == 0) || (!eol && chars + chrs <= columns)
                   1062:                   || (!eol && trunc && (chars < columns)))
                   1063:     {
                   1064:        while(*sp++ = *str++)
                   1065:            if(trunc)
                   1066:            {   
                   1067:                if(++chars >= columns)  /* check for trunc */
                   1068:                {
                   1069:                    eol = 1;
                   1070:                    return;
                   1071:                }
                   1072:            }
                   1073:        sp--;
                   1074:        if(!trunc) chars += chrs;
                   1075:     }
                   1076:     else eol = 1;
                   1077: }
                   1078: 
                   1079: /*
                   1080:  * touch :: update the modify time of a file.
                   1081:  */
                   1082: touch(name,filedes)
                   1083: char *name;            /* name of file */
                   1084: FILE *filedes;         /* already open for read file descriptor */
                   1085: {
                   1086:        register fd;
                   1087:        char buf[1];
                   1088: 
                   1089:        lseek(fileno(filedes),0L,0);
                   1090:        read(fileno(filedes),buf,1);    /* get first byte */
                   1091:        if((fd = open(name,2)) >= 0)    /* open in append mode */
                   1092:        {
                   1093:            lseek(fd,0L,0);             /* go to beginning */
                   1094:            write(fd,buf,1);            /* and rewrite first byte */
                   1095:            close(fd);
                   1096:        }
                   1097: }
                   1098: 
                   1099: 
                   1100: /* 
                   1101:  * clearbotl :: clear bottom line.  
                   1102:  * called when process quits or is killed.
                   1103:  * it clears the bottom line of the terminal.
                   1104:  */
                   1105: clearbotl()
                   1106: {
                   1107:        register int fd;
                   1108:        int exit();
                   1109: 
                   1110:        signal(SIGALRM,exit);
                   1111:        alarm(30);      /* if can't open in 30 secs, just die */
                   1112:        if( !emacs && (fd = open(ourtty,1)) >=0)
                   1113:        {
                   1114:            write(fd,dis_status_line,strlen(dis_status_line));
                   1115:            close(fd);
                   1116:        }
                   1117:        exit(0);
                   1118: }
                   1119: 
                   1120: #ifdef TERMINFO
                   1121: initterm()
                   1122: {
                   1123:        static char standbuf[40];
                   1124: 
                   1125:        setupterm(0, 1, 0);
                   1126:        if (!has_status_line) {
                   1127:                /* not an appropriate terminal */
                   1128:                if (!quiet)
                   1129:                   fprintf(stderr, "sysline: no status capability for %s\n",
                   1130:                        getenv("TERM"));
                   1131:                exit(1);
                   1132:        }
                   1133:        if (status_line_esc_ok) {
                   1134:                if (set_attributes) {
                   1135:                        /* reverse video mode */
                   1136:                        strcpy(standbuf, tparm(set_attributes,0,0,1,0,0,0,0,0,0));
                   1137:                        rev_out = standbuf;
                   1138:                        rev_end = exit_attribute_mode;
                   1139:                } else if (enter_standout_mode && exit_standout_mode) {
                   1140:                        rev_out = enter_standout_mode;
                   1141:                        rev_end = exit_standout_mode;
                   1142:                } else {
                   1143:                        rev_out = rev_end = "";
                   1144:                }
                   1145:        } else
                   1146:                rev_out = rev_end = "";
                   1147:        columns--;      /* avoid cursor wraparound */
                   1148: }
                   1149: 
                   1150: #else  /* TERMCAP */
                   1151: 
                   1152: initterm()
                   1153: {
                   1154:        char *term, *cp;
                   1155:        char tbuf[1024], is2[40];
                   1156:        extern char *UP;
                   1157:        
                   1158:        if ((term=getenv("TERM")) == NULL) {
                   1159:                if (!quiet)
                   1160:                   fprintf(stderr, "sysline: No TERM variable in enviroment\n");
                   1161:                exit(1);
                   1162:        }
                   1163:        if (tgetent(tbuf, term) <= 0) {
                   1164:                if (!quiet)
                   1165:                   fprintf(stderr, "sysline: Unknown terminal type: %s\n", term);
                   1166:                exit(1);
                   1167:        }
                   1168:        if (tgetflag("hs") <= 0) {
                   1169:                if (!strcmpn(term, "h19", 3)) {
                   1170:                        /* for upward compatability with h19sys */
                   1171:                        strcpy(to_status_line, "\033j\033x5\033x1\033Y8%+ \033o");
                   1172:                        strcpy(from_status_line, "\033k\033y5");
                   1173:                        strcpy(dis_status_line, "\033y1");
                   1174:                        strcpy(rev_out, "\033p");
                   1175:                        strcpy(rev_end, "\033q");
                   1176:                        arrows = "\033Fhh\033G";
                   1177:                        columns = 80;
                   1178:                        UP = "\b";
                   1179:                        return;
                   1180:                }
                   1181:                if (!quiet)
                   1182:                   fprintf(stderr, "sysline: No status capability for %s\n", term);
                   1183:                exit(1);
                   1184:        }
                   1185:        cp = is2;
                   1186:        if (tgetstr("i2", &cp) != NULL) {
                   1187:                /* someday tset will do this */
                   1188:                tputs(is2, 1, erroutc);
                   1189:                fflush(stdout);
                   1190:        }
                   1191: 
                   1192:        /* the "-1" below is to avoid cursor wraparound problems */
                   1193:        columns = tgetnum("co") - 1;
                   1194:        cp = to_status_line;
                   1195:        tgetstr("ts", &cp);
                   1196:        cp = from_status_line;
                   1197:        tgetstr("fs", &cp);
                   1198:        cp = dis_status_line;
                   1199:        tgetstr("ds", &cp);
                   1200:        eslok = tgetflag("es");
                   1201:        if (eslok) {
                   1202:                cp = rev_out;
                   1203:                tgetstr("so", &cp);
                   1204:                cp = rev_end;
                   1205:                tgetstr("se", &cp);
                   1206:        } else {
                   1207:                reverse = 0;    /* turn off reverse video */
                   1208:        };
                   1209:        UP = "\b";
                   1210:        if (!strcmpn(term, "h19", 3))
                   1211:                arrows = "\033Fhh\033G";        /* "two tiny graphic arrows" */
                   1212:        else
                   1213:                arrows = "->";
                   1214: }
                   1215: 
                   1216: char *
                   1217: tparm(cap, parm)
                   1218: char *cap;
                   1219: int parm;
                   1220: {
                   1221:        return tgoto(cap, 0, parm);
                   1222: }
                   1223: #endif
                   1224: 
                   1225: #ifdef pdp11
                   1226: loadav(ap)
                   1227: double ap[];
                   1228: {
                   1229:        register int i;
                   1230:        short s_avenrun[3];
                   1231: 
                   1232:        lseek(kmem, (long)nl[NL_AVEN].n_value, 0);
                   1233:        read(kmem, s_avenrun, sizeof(s_avenrun));
                   1234:        for (i=0; i < (sizeof(s_avenrun)/sizeof(s_avenrun[0])); i++)
                   1235:                ap[i] = s_avenrun[i] / 256.0;
                   1236: }
                   1237: #endif
                   1238: 
                   1239: #ifdef RWHO
                   1240: char *
                   1241: sysrup(hostname)
                   1242:     char       *hostname;
                   1243: {
                   1244:     char       filename[MAXFILENAME];
                   1245:     FILE       *rwhofile;
                   1246:     struct whod        wd;
                   1247:     char       buffer[BUFSIZ];
                   1248:     long       now;
                   1249: 
                   1250:        /*
                   1251:         *      try rwho hostname file, and if that fails try ucbhostname.
                   1252:         */
                   1253:     (void) strcpy(filename, RWHOLEADER);
                   1254:     (void) strcat(filename, hostname);
                   1255:     rwhofile = fopen(filename, "r");
                   1256:     if (rwhofile == NULL) {
                   1257:        (void) strcpy(filename, RWHOLEADER);
                   1258:        (void) strcat(filename, "ucb");
                   1259:        (void) strcat(filename, hostname);
                   1260:        rwhofile = fopen(filename, "r");
                   1261:        if (rwhofile == NULL) {
                   1262:            (void) sprintf(buffer, "%s?", hostname);
                   1263:            return buffer;
                   1264:        }
                   1265:     }
                   1266:     if (fread(&wd, sizeof wd, 1, rwhofile) != 1) {
                   1267:        (void) sprintf(buffer, "%s ?", hostname);
                   1268:        fclose(rwhofile);
                   1269:        return buffer;
                   1270:     }
                   1271:     (void) time(&now);
                   1272:     if (now - wd.wd_recvtime > DOWN_THRESHOLD) {
                   1273:        long    interval;
                   1274:        long    days, hours, minutes;
                   1275: 
                   1276:        interval = now - wd.wd_recvtime;
                   1277:        minutes = (interval + 59) / 60; /* round to minutes */
                   1278:        hours = minutes / 60;           /* extract hours from minutes */
                   1279:        minutes %= 60;                  /* remove hours from minutes */
                   1280:        days = hours / 24;              /* extract days from hours */
                   1281:        hours %= 24;                    /* remove days from hours */
                   1282:        if (days > 7 || days < 0) {
                   1283:            (void) sprintf(buffer, "%s down", hostname);
                   1284:        } else if (days > 0) {
                   1285:            (void) sprintf(buffer, "%s %d+%d:%02d",
                   1286:                            hostname, days, hours, minutes);
                   1287:        } else {
                   1288:            (void) sprintf(buffer, "%s %d:%02d", hostname, hours, minutes);
                   1289:        }
                   1290:     } else {
                   1291:        (void) sprintf(buffer, "%s %.1f", hostname, wd.wd_loadav[0]/100.0);
                   1292:     }
                   1293:     if (rwhofile != NULL) {
                   1294:        fclose(rwhofile);
                   1295:     }
                   1296:     return buffer;
                   1297: }
                   1298: #endif RWHO

unix.superglobalmegacorp.com

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