Annotation of 43BSDTahoe/ucb/sysline/sysline.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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