Annotation of 43BSDReno/usr.bin/w/w.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: char copyright[] =
                      9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)w.c        5.24 (Berkeley) 7/27/90";
                     15: #endif not lint
                     16: 
                     17: /*
                     18:  * w - print system status (who and what)
                     19:  *
                     20:  * This program is similar to the systat command on Tenex/Tops 10/20
                     21:  *
                     22:  */
                     23: #include <sys/param.h>
                     24: #include <utmp.h>
                     25: #include <sys/stat.h>
                     26: #include <sys/user.h>
                     27: #include <sys/proc.h>
                     28: #include <sys/ioctl.h>
                     29: #include <machine/pte.h>
                     30: #include <sys/vm.h>
                     31: #include <sys/tty.h>
                     32: #include <nlist.h>
                     33: #include <kvm.h>
                     34: #include <ctype.h>
                     35: #include <paths.h>
                     36: #include <string.h>
                     37: #include <stdio.h>
                     38: 
                     39: char   *program;
                     40: int    ttywidth;               /* width of tty */
                     41: int    argwidth;               /* width of tty */
                     42: int    header = 1;             /* true if -h flag: don't print heading */
                     43: int    wcmd = 1;               /* true if this is w(1), and not uptime(1) */
                     44: int    nusers;                 /* number of users logged in now */
                     45: char * sel_user;               /* login of particular user selected */
                     46: time_t now;                    /* the current time of day */
                     47: struct timeval boottime;
                     48: time_t uptime;                 /* time of last reboot & elapsed time since */
                     49: struct utmp utmp;
                     50: struct winsize ws;
                     51: int    sortidle;               /* sort bu idle time */
                     52: 
                     53: 
                     54: /*
                     55:  * One of these per active utmp entry.  
                     56:  */
                     57: struct entry {
                     58:        struct  entry *next;
                     59:        struct  utmp utmp;
                     60:        dev_t   tdev;           /* dev_t of terminal */
                     61:        int     idle;           /* idle time of terminal in minutes */
                     62:        struct  proc *proc;     /* list of procs in foreground */
                     63:        char    *args;          /* arg list of interesting process */
                     64: } *ep, *ehead = NULL, **nextp = &ehead;
                     65: 
                     66: struct nlist nl[] = {
                     67:        { "_boottime" },
                     68: #define X_BOOTTIME     0
                     69: #if defined(hp300)
                     70:        { "_cn_tty" },
                     71: #define X_CNTTY                1
                     72: #endif
                     73:        { "" },
                     74: };
                     75: 
                     76: #define USAGE "[ -hi ] [ user ]"
                     77: #define usage()        fprintf(stderr, "usage: %s: %s\n", program, USAGE)
                     78: 
                     79: main(argc, argv)
                     80:        char **argv;
                     81: {
                     82:        register int i;
                     83:        struct winsize win;
                     84:        register struct proc *p;
                     85:        struct eproc *e;
                     86:        struct stat *stp, *ttystat();
                     87:        FILE *ut;
                     88:        char *cp;
                     89:        int ch;
                     90:        extern char *optarg;
                     91:        extern int optind;
                     92:        char *strsave();
                     93: 
                     94:        program = argv[0];
                     95:        /*
                     96:         * are we w(1) or uptime(1)
                     97:         */
                     98:        if ((cp = rindex(program, '/')) || *(cp = program) == '-')
                     99:                cp++;
                    100:        if (*cp == 'u')
                    101:                wcmd = 0;
                    102: 
                    103:        while ((ch = getopt(argc, argv, "hiflsuw")) != EOF)
                    104:                switch((char)ch) {
                    105:                case 'h':
                    106:                        header = 0;
                    107:                        break;
                    108:                case 'i':
                    109:                        sortidle++;
                    110:                        break;
                    111:                case 'f': case 'l': case 's': case 'u': case 'w':
                    112:                        error("[-flsuw] no longer supported");
                    113:                        usage();
                    114:                        exit(1);
                    115:                case '?':
                    116:                default:
                    117:                        usage();
                    118:                        exit(1);
                    119:                }
                    120:        argc -= optind;
                    121:        argv += optind;
                    122:        if (argc == 1) {
                    123:                sel_user = argv[0];
                    124:                argv++, argc--;
                    125:        }
                    126:        if (argc) {
                    127:                usage();
                    128:                exit(1);
                    129:        }
                    130: 
                    131:        if (header && kvm_nlist(nl) != 0) {
                    132:                error("can't get namelist");
                    133:                exit (1);
                    134:        }
                    135:        time(&now);
                    136:        ut = fopen(_PATH_UTMP, "r");
                    137:        while (fread(&utmp, sizeof(utmp), 1, ut)) {
                    138:                if (utmp.ut_name[0] == '\0')
                    139:                        continue;
                    140:                nusers++;
                    141:                if (wcmd == 0 || (sel_user && 
                    142:                    strncmp(utmp.ut_name, sel_user, UT_NAMESIZE) != 0))
                    143:                        continue;
                    144:                if ((ep = (struct entry *)
                    145:                     calloc(1, sizeof (struct entry))) == NULL) {
                    146:                        error("out of memory");
                    147:                        exit(1);
                    148:                }
                    149:                *nextp = ep;
                    150:                nextp = &(ep->next);
                    151:                bcopy(&utmp, &(ep->utmp), sizeof (struct utmp));
                    152:                stp = ttystat(ep->utmp.ut_line);
                    153:                ep->tdev = stp->st_rdev;
                    154: #if defined(hp300)
                    155:                /*
                    156:                 * XXX  If this is the console device, attempt to ascertain
                    157:                 * the true console device dev_t.
                    158:                 */
                    159:                if (ep->tdev == 0) {
                    160:                        static dev_t cn_dev;
                    161: 
                    162:                        if (nl[X_CNTTY].n_value) {
                    163:                                struct tty cn_tty, *cn_ttyp;
                    164:                                
                    165:                                if (kvm_read(nl[X_CNTTY].n_value,
                    166:                                             &cn_ttyp, sizeof (cn_ttyp)) > 0) {
                    167:                                        (void)kvm_read(cn_ttyp, &cn_tty,
                    168:                                                       sizeof (cn_tty));
                    169:                                        cn_dev = cn_tty.t_dev;
                    170:                                }
                    171:                                nl[X_CNTTY].n_value = 0;
                    172:                        }
                    173:                        ep->tdev = cn_dev;
                    174:                }
                    175: #endif
                    176:                ep->idle = ((now - stp->st_atime) + 30) / 60; /* secs->mins */
                    177:                if (ep->idle < 0)
                    178:                        ep->idle = 0;
                    179:        }
                    180:        fclose(ut);
                    181: 
                    182:        if (header || wcmd == 0) {
                    183:                double  avenrun[3];
                    184:                int days, hrs, mins;
                    185: 
                    186:                /*
                    187:                 * Print time of day 
                    188:                 */
                    189:                fputs(attime(&now), stdout);
                    190:                /*
                    191:                 * Print how long system has been up.
                    192:                 * (Found by looking for "boottime" in kernel)
                    193:                 */
                    194:                (void)kvm_read((off_t)nl[X_BOOTTIME].n_value, &boottime, 
                    195:                        sizeof (boottime));
                    196:                uptime = now - boottime.tv_sec;
                    197:                uptime += 30;
                    198:                days = uptime / (60*60*24);
                    199:                uptime %= (60*60*24);
                    200:                hrs = uptime / (60*60);
                    201:                uptime %= (60*60);
                    202:                mins = uptime / 60;
                    203: 
                    204:                printf("  up");
                    205:                if (days > 0)
                    206:                        printf(" %d day%s,", days, days>1?"s":"");
                    207:                if (hrs > 0 && mins > 0) {
                    208:                        printf(" %2d:%02d,", hrs, mins);
                    209:                } else {
                    210:                        if (hrs > 0)
                    211:                                printf(" %d hr%s,", hrs, hrs>1?"s":"");
                    212:                        if (mins > 0)
                    213:                                printf(" %d min%s,", mins, mins>1?"s":"");
                    214:                }
                    215: 
                    216:                /* Print number of users logged in to system */
                    217:                printf("  %d user%s", nusers, nusers>1?"s":"");
                    218: 
                    219:                /*
                    220:                 * Print 1, 5, and 15 minute load averages.
                    221:                 */
                    222:                printf(",  load average:");
                    223:                (void)getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
                    224:                for (i = 0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) {
                    225:                        if (i > 0)
                    226:                                printf(",");
                    227:                        printf(" %.2f", avenrun[i]);
                    228:                }
                    229:                printf("\n");
                    230:                if (wcmd == 0)          /* if uptime(1) then done */
                    231:                        exit(0);
                    232: #define HEADER "USER    TTY FROM              LOGIN@  IDLE WHAT\n"
                    233: #define WUSED  (sizeof (HEADER) - sizeof ("WHAT\n"))
                    234:                printf(HEADER);
                    235:        }
                    236: 
                    237:        while ((p = kvm_nextproc()) != NULL) {
                    238:                if (p->p_stat == SZOMB || (p->p_flag & SCTTY) == 0)
                    239:                        continue;
                    240:                e = kvm_geteproc(p);
                    241:                for (ep = ehead; ep != NULL; ep = ep->next) {
                    242:                        if (ep->tdev == e->e_tdev && e->e_pgid == e->e_tpgid) {
                    243:                                /*
                    244:                                 * Proc is in foreground of this terminal
                    245:                                 */
                    246:                                if (proc_compare(ep->proc, p))
                    247:                                        ep->proc = p;
                    248:                                break;
                    249:                        }
                    250:                }
                    251:        }
                    252:        if ((ioctl(1, TIOCGWINSZ, &ws) == -1 &&
                    253:             ioctl(2, TIOCGWINSZ, &ws) == -1 &&
                    254:             ioctl(0, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
                    255:               ttywidth = 79;
                    256:         else
                    257:               ttywidth = ws.ws_col - 1;
                    258:        argwidth = ttywidth - WUSED;
                    259:        if (argwidth < 4)
                    260:                argwidth = 8;
                    261:        for (ep = ehead; ep != NULL; ep = ep->next) {
                    262:                ep->args = strsave(kvm_getargs(ep->proc, kvm_getu(ep->proc)));
                    263:                if (ep->args == NULL) {
                    264:                        error("out of memory");
                    265:                        exit(1);
                    266:                }
                    267:        }
                    268:        /* sort by idle time */
                    269:        if (sortidle && ehead != NULL) {
                    270:                struct entry *from = ehead, *save;
                    271:                
                    272:                ehead = NULL;
                    273:                while (from != NULL) {
                    274:                        for (nextp = &ehead; 
                    275:                            (*nextp) && from->idle >= (*nextp)->idle;
                    276:                            nextp = &(*nextp)->next)
                    277:                                ;
                    278:                        save = from;
                    279:                        from = from->next;
                    280:                        save->next = *nextp;
                    281:                        *nextp = save;
                    282:                }
                    283:        }
                    284:                        
                    285:        for (ep = ehead; ep != NULL; ep = ep->next) {
                    286:                printf("%-*.*s %-2.2s %-*.*s %s",
                    287:                        UT_NAMESIZE, UT_NAMESIZE, ep->utmp.ut_name,
                    288:                        strncmp(ep->utmp.ut_line, "tty", 3) == 0 ? 
                    289:                                ep->utmp.ut_line+3 : ep->utmp.ut_line,
                    290:                        UT_HOSTSIZE, UT_HOSTSIZE, *ep->utmp.ut_host ?
                    291:                                ep->utmp.ut_host : "-",
                    292:                        attime(&ep->utmp.ut_time));
                    293:                if (ep->idle >= 36 * 60)
                    294:                        printf(" %ddays ", (ep->idle + 12 * 60) / (24 * 60));
                    295:                else
                    296:                        prttime(ep->idle, " ");
                    297:                printf("%.*s\n", argwidth, ep->args);
                    298:        }
                    299: }
                    300: 
                    301: struct stat *
                    302: ttystat(line)
                    303: {
                    304:        static struct stat statbuf;
                    305:        char ttybuf[sizeof (_PATH_DEV) + UT_LINESIZE + 1];
                    306: 
                    307:        sprintf(ttybuf, "%s/%.*s", _PATH_DEV, UT_LINESIZE, line);
                    308:        (void) stat(ttybuf, &statbuf);
                    309: 
                    310:        return (&statbuf);
                    311: }
                    312: 
                    313: char *
                    314: strsave(cp)
                    315:        char *cp;
                    316: {
                    317:        register unsigned len;
                    318:        register char *dp;
                    319: 
                    320:        len = strlen(cp);
                    321:        dp = (char *)calloc(len+1, sizeof (char));
                    322:        (void) strcpy(dp, cp);
                    323:        return (dp);
                    324: }
                    325: /*
                    326:  * prttime prints a time in hours and minutes or minutes and seconds.
                    327:  * The character string tail is printed at the end, obvious
                    328:  * strings to pass are "", " ", or "am".
                    329:  */
                    330: prttime(tim, tail)
                    331:        time_t tim;
                    332:        char *tail;
                    333: {
                    334: 
                    335:        if (tim >= 60) {
                    336:                printf(" %2d:", tim/60);
                    337:                tim %= 60;
                    338:                printf("%02d", tim);
                    339:        } else if (tim >= 0)
                    340:                printf("    %2d", tim);
                    341:        printf("%s", tail);
                    342: }
                    343: 
                    344: #include <varargs.h>
                    345: 
                    346: warning(va_alist)
                    347:        va_dcl
                    348: {
                    349:        char *fmt;
                    350:        va_list ap;
                    351: 
                    352:        fprintf(stderr, "%s: warning: ", program);
                    353:        va_start(ap);
                    354:        fmt = va_arg(ap, char *);
                    355:        (void) vfprintf(stderr, fmt, ap);
                    356:        va_end(ap);
                    357:        fprintf(stderr, "\n");
                    358: }
                    359: 
                    360: error(va_alist)
                    361:        va_dcl
                    362: {
                    363:        char *fmt;
                    364:        va_list ap;
                    365: 
                    366:        fprintf(stderr, "%s: ", program);
                    367:        va_start(ap);
                    368:        fmt = va_arg(ap, char *);
                    369:        (void) vfprintf(stderr, fmt, ap);
                    370:        va_end(ap);
                    371:        fprintf(stderr, "\n");
                    372: }
                    373: 
                    374: syserror(va_alist)
                    375:        va_dcl
                    376: {
                    377:        char *fmt;
                    378:        va_list ap;
                    379:        extern errno;
                    380: 
                    381:        fprintf(stderr, "%s: ", program);
                    382:        va_start(ap);
                    383:        fmt = va_arg(ap, char *);
                    384:        (void) vfprintf(stderr, fmt, ap);
                    385:        va_end(ap);
                    386:        fprintf(stderr, ": %s\n", strerror(errno));
                    387: }

unix.superglobalmegacorp.com

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