[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / systat

Annotation of src/usr.bin/systat/main.c, Revision 1.68

1.68    ! krw         1: /* $Id: main.c,v 1.67 2018/02/08 07:00:33 martijn Exp $         */
1.38      canacar     2: /*
                      3:  * Copyright (c) 2001, 2007 Can Erkin Acar
                      4:  * Copyright (c) 2001 Daniel Hartmeier
                      5:  * All rights reserved.
1.1       deraadt     6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  *
1.38      canacar    11:  *    - Redistributions of source code must retain the above copyright
                     12:  *      notice, this list of conditions and the following disclaimer.
                     13:  *    - Redistributions in binary form must reproduce the above
                     14:  *      copyright notice, this list of conditions and the following
                     15:  *      disclaimer in the documentation and/or other materials provided
                     16:  *      with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
                     19:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
                     20:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
                     21:  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
                     22:  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
                     23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     24:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     25:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                     26:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     28:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  *
1.1       deraadt    31:  */
                     32:
1.38      canacar    33: #include <sys/types.h>
1.21      deraadt    34: #include <sys/sysctl.h>
1.1       deraadt    35:
1.38      canacar    36:
                     37: #include <ctype.h>
                     38: #include <curses.h>
1.1       deraadt    39: #include <err.h>
1.38      canacar    40: #include <errno.h>
                     41: #include <fcntl.h>
                     42: #include <limits.h>
                     43: #include <netdb.h>
1.1       deraadt    44: #include <signal.h>
                     45: #include <stdio.h>
1.38      canacar    46: #include <stdlib.h>
1.1       deraadt    47: #include <string.h>
1.38      canacar    48: #include <stdarg.h>
1.3       deraadt    49: #include <unistd.h>
1.35      deraadt    50: #include <utmp.h>
1.1       deraadt    51:
1.38      canacar    52: #include "engine.h"
1.1       deraadt    53: #include "systat.h"
                     54:
1.66      otto       55: #define TIMEPOS (80 - 8 - 20 - 1)
1.58      lum        56:
1.21      deraadt    57: double dellave;
1.1       deraadt    58:
1.21      deraadt    59: kvm_t  *kd;
                     60: char   *nlistf = NULL;
1.20      pvalchev   61: char   *memf = NULL;
1.21      deraadt    62: double avenrun[3];
1.36      tedu       63: double naptime = 5.0;
1.21      deraadt    64: int    verbose = 1;            /* to report kvm read errs */
1.38      canacar    65: int    nflag = 1;
1.35      deraadt    66: int    ut, hz, stathz;
1.61      deraadt    67: char    hostname[HOST_NAME_MAX+1];
1.1       deraadt    68: WINDOW  *wnd;
1.32      deraadt    69: int    CMDLINE;
1.58      lum        70: char   timebuf[26];
                     71: char   uloadbuf[TIMEPOS];
1.1       deraadt    72:
1.38      canacar    73:
1.50      canacar    74: int  ucount(void);
                     75: void usage(void);
                     76:
1.38      canacar    77: /* command prompt */
                     78:
1.46      canacar    79: void cmd_delay(const char *);
                     80: void cmd_count(const char *);
                     81: void cmd_compat(const char *);
1.38      canacar    82:
                     83: struct command cm_compat = {"Command", cmd_compat};
                     84: struct command cm_delay = {"Seconds to delay", cmd_delay};
                     85: struct command cm_count = {"Number of lines to display", cmd_count};
1.1       deraadt    86:
1.38      canacar    87:
                     88: /* display functions */
1.3       deraadt    89:
1.2       deraadt    90: int
1.38      canacar    91: print_header(void)
1.1       deraadt    92: {
1.50      canacar    93:        time_t now;
1.40      deraadt    94:        int start = dispstart + 1, end = dispstart + maxprint;
1.58      lum        95:        char tmpbuf[TIMEPOS];
                     96:        char header[MAX_LINE_BUF];
1.38      canacar    97:
                     98:        if (end > num_disp)
                     99:                end = num_disp;
                    100:
                    101:        tb_start();
1.35      deraadt   102:
1.58      lum       103:        if (!paused) {
1.65      tedu      104:                char *ctim;
                    105:
1.58      lum       106:                getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
1.38      canacar   107:
1.58      lum       108:                snprintf(uloadbuf, sizeof(uloadbuf),
1.66      otto      109:                    "%4d users Load %.2f %.2f %.2f",
1.58      lum       110:                    ucount(), avenrun[0], avenrun[1], avenrun[2]);
1.25      deraadt   111:
1.58      lum       112:                time(&now);
1.65      tedu      113:                ctim = ctime(&now);
                    114:                ctim[11+8] = '\0';
                    115:                strlcpy(timebuf, ctim + 11, sizeof(timebuf));
1.58      lum       116:        }
1.25      deraadt   117:
1.58      lum       118:        if (num_disp && (start > 1 || end != num_disp))
                    119:                snprintf(tmpbuf, sizeof(tmpbuf),
                    120:                    "%s (%u-%u of %u) %s", uloadbuf, start, end, num_disp,
                    121:                    paused ? "PAUSED" : "");
                    122:        else
                    123:                snprintf(tmpbuf, sizeof(tmpbuf),
                    124:                    "%s %s", uloadbuf,
                    125:                    paused ? "PAUSED" : "");
                    126:
1.66      otto      127:        snprintf(header, sizeof(header), "%-*s %19.19s %s", TIMEPOS - 1,
                    128:            tmpbuf, hostname, timebuf);
1.58      lum       129:
                    130:        if (rawmode)
                    131:                printf("\n\n%s\n", header);
                    132:        else
                    133:                mvprintw(0, 0, "%s", header);
1.24      deraadt   134:
1.38      canacar   135:        return (1);
1.1       deraadt   136: }
1.3       deraadt   137:
1.38      canacar   138: /* compatibility functions, rearrange later */
1.21      deraadt   139: void
1.38      canacar   140: error(const char *fmt, ...)
1.21      deraadt   141: {
1.38      canacar   142:        va_list ap;
                    143:        char buf[MAX_LINE_BUF];
                    144:
                    145:        va_start(ap, fmt);
                    146:        vsnprintf(buf, sizeof buf, fmt, ap);
                    147:        va_end(ap);
1.21      deraadt   148:
1.38      canacar   149:        message_set(buf);
1.21      deraadt   150: }
                    151:
1.38      canacar   152: void
                    153: nlisterr(struct nlist namelist[])
1.3       deraadt   154: {
1.38      canacar   155:        int i, n;
                    156:
                    157:        n = 0;
                    158:        clear();
                    159:        mvprintw(2, 10, "systat: nlist: can't find following symbols:");
                    160:        for (i = 0;
                    161:            namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
                    162:                if (namelist[i].n_value == 0)
                    163:                        mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
                    164:        move(CMDLINE, 0);
                    165:        clrtoeol();
                    166:        refresh();
                    167:        endwin();
1.3       deraadt   168:        exit(1);
                    169: }
                    170:
1.1       deraadt   171: void
1.38      canacar   172: die(void)
1.1       deraadt   173: {
1.38      canacar   174:        if (!rawmode)
                    175:                endwin();
                    176:        exit(0);
1.1       deraadt   177: }
                    178:
1.38      canacar   179:
                    180: int
                    181: prefix(char *s1, char *s2)
1.1       deraadt   182: {
1.38      canacar   183:
                    184:        while (*s1 == *s2) {
                    185:                if (*s1 == '\0')
                    186:                        return (1);
                    187:                s1++, s2++;
                    188:        }
                    189:        return (*s1 == '\0');
1.21      deraadt   190: }
                    191:
1.38      canacar   192: /* calculate number of users on the system */
                    193: int
                    194: ucount(void)
1.21      deraadt   195: {
1.38      canacar   196:        int nusers = 0;
                    197:        struct  utmp utmp;
1.35      deraadt   198:
1.38      canacar   199:        if (ut < 0)
                    200:                return (0);
                    201:        lseek(ut, (off_t)0, SEEK_SET);
                    202:        while (read(ut, &utmp, sizeof(utmp)))
                    203:                if (utmp.ut_name[0] != '\0')
                    204:                        nusers++;
1.35      deraadt   205:
1.38      canacar   206:        return (nusers);
1.1       deraadt   207: }
                    208:
1.38      canacar   209: /* main program functions */
                    210:
1.1       deraadt   211: void
1.50      canacar   212: usage(void)
1.1       deraadt   213: {
1.38      canacar   214:        extern char *__progname;
1.60      reyk      215:        fprintf(stderr, "usage: %s [-aBbiNn] [-d count] "
1.43      matthieu  216:            "[-s delay] [-w width] [view] [delay]\n", __progname);
1.38      canacar   217:        exit(1);
1.1       deraadt   218: }
                    219:
1.45      canacar   220: void
                    221: show_view(void)
                    222: {
                    223:        if (rawmode)
                    224:                return;
                    225:
                    226:        tb_start();
                    227:        tbprintf("%s %g", curr_view->name, naptime);
                    228:        tb_end();
                    229:        message_set(tmp_buf);
                    230: }
1.21      deraadt   231:
1.1       deraadt   232: void
1.38      canacar   233: add_view_tb(field_view *v)
1.1       deraadt   234: {
1.38      canacar   235:        if (curr_view == v)
                    236:                tbprintf("[%s] ", v->name);
                    237:        else
                    238:                tbprintf("%s ", v->name);
1.29      deraadt   239: }
                    240:
                    241: void
1.38      canacar   242: show_help(void)
1.29      deraadt   243: {
1.38      canacar   244:        if (rawmode)
                    245:                return;
                    246:
                    247:        tb_start();
                    248:        foreach_view(add_view_tb);
                    249:        tb_end();
                    250:        message_set(tmp_buf);
1.21      deraadt   251: }
                    252:
                    253: void
1.67      martijn   254: add_order_tb(order_type *o)
                    255: {
                    256:        if (curr_view->mgr->order_curr == o)
                    257:                tbprintf("[%s%s(%c)] ", o->name,
                    258:                    o->func != NULL && sortdir == -1 ? "^" : "",
                    259:                    (char) o->hotkey);
                    260:        else
                    261:                tbprintf("%s(%c) ", o->name, (char) o->hotkey);
                    262: }
                    263:
                    264: void
                    265: show_order(void)
                    266: {
                    267:        if (rawmode)
                    268:                return;
                    269:
                    270:        tb_start();
                    271:        if (foreach_order(add_order_tb) == -1) {
                    272:                tbprintf("No orders available");
                    273:        }
                    274:        tb_end();
                    275:        message_set(tmp_buf);
                    276: }
                    277:
                    278: void
1.46      canacar   279: cmd_compat(const char *buf)
1.21      deraadt   280: {
1.46      canacar   281:        const char *s;
1.38      canacar   282:
1.46      canacar   283:        if (strcasecmp(buf, "help") == 0) {
1.38      canacar   284:                show_help();
                    285:                need_update = 1;
                    286:                return;
                    287:        }
1.46      canacar   288:        if (strcasecmp(buf, "quit") == 0 || strcasecmp(buf, "q") == 0) {
1.38      canacar   289:                gotsig_close = 1;
                    290:                return;
                    291:        }
1.46      canacar   292:        if (strcasecmp(buf, "stop") == 0) {
                    293:                paused = 1;
                    294:                gotsig_alarm = 1;
                    295:                return;
                    296:        }
                    297:        if (strncasecmp(buf, "start", 5) == 0) {
                    298:                paused = 0;
                    299:                gotsig_alarm = 1;
1.47      canacar   300:                cmd_delay(buf + 5);
1.67      martijn   301:                return;
                    302:        }
                    303:        if (strncasecmp(buf, "order", 5) == 0) {
                    304:                show_order();
                    305:                need_update = 1;
1.46      canacar   306:                return;
                    307:        }
1.38      canacar   308:
1.46      canacar   309:        for (s = buf; *s && strchr("0123456789+-.eE", *s) != NULL; s++)
1.38      canacar   310:                ;
                    311:        if (*s) {
1.46      canacar   312:                if (set_view(buf))
1.49      espie     313:                        error("Invalid/ambiguous view: %s", buf);
1.38      canacar   314:        } else
1.46      canacar   315:                cmd_delay(buf);
1.38      canacar   316: }
                    317:
                    318: void
1.46      canacar   319: cmd_delay(const char *buf)
1.38      canacar   320: {
                    321:        double del;
1.46      canacar   322:        del = atof(buf);
1.39      canacar   323:
1.38      canacar   324:        if (del > 0) {
                    325:                udelay = (useconds_t)(del * 1000000);
                    326:                gotsig_alarm = 1;
1.39      canacar   327:                naptime = del;
1.13      deraadt   328:        }
1.1       deraadt   329: }
1.14      kstailey  330:
                    331: void
1.46      canacar   332: cmd_count(const char *buf)
1.14      kstailey  333: {
1.63      deraadt   334:        const char *errstr;
1.38      canacar   335:
1.63      deraadt   336:        maxprint = strtonum(buf, 1, lines - HEADER_LINES, &errstr);
                    337:        if (errstr)
1.38      canacar   338:                maxprint = lines - HEADER_LINES;
1.14      kstailey  339: }
                    340:
1.38      canacar   341:
                    342: int
                    343: keyboard_callback(int ch)
1.1       deraadt   344: {
1.38      canacar   345:        switch (ch) {
                    346:        case '?':
                    347:                /* FALLTHROUGH */
                    348:        case 'h':
                    349:                show_help();
1.45      canacar   350:                need_update = 1;
                    351:                break;
                    352:        case CTRL_G:
                    353:                show_view();
1.38      canacar   354:                need_update = 1;
                    355:                break;
                    356:        case 'l':
                    357:                command_set(&cm_count, NULL);
                    358:                break;
                    359:        case 's':
                    360:                command_set(&cm_delay, NULL);
1.59      mpf       361:                break;
                    362:        case ',':
                    363:                separate_thousands = !separate_thousands;
                    364:                gotsig_alarm = 1;
1.38      canacar   365:                break;
                    366:        case ':':
                    367:                command_set(&cm_compat, NULL);
                    368:                break;
                    369:        default:
                    370:                return 0;
                    371:        };
                    372:
                    373:        return 1;
                    374: }
1.23      millert   375:
1.38      canacar   376: void
                    377: initialize(void)
                    378: {
                    379:        engine_initialize();
                    380:
                    381:        initvmstat();
                    382:        initpigs();
                    383:        initifstat();
                    384:        initiostat();
                    385:        initsensors();
                    386:        initmembufs();
                    387:        initnetstat();
                    388:        initswap();
                    389:        initpftop();
                    390:        initpf();
1.48      canacar   391:        initpool();
1.51      canacar   392:        initmalloc();
1.52      jasper    393:        initnfs();
1.60      reyk      394:        initcpu();
1.68    ! krw       395:        inituvm();
1.1       deraadt   396: }
                    397:
                    398: void
1.38      canacar   399: gethz(void)
1.1       deraadt   400: {
1.38      canacar   401:        struct clockinfo cinf;
                    402:        size_t  size = sizeof(cinf);
                    403:        int     mib[2];
1.1       deraadt   404:
1.38      canacar   405:        mib[0] = CTL_KERN;
                    406:        mib[1] = KERN_CLOCKRATE;
                    407:        if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
                    408:                return;
                    409:        stathz = cinf.stathz;
                    410:        hz = cinf.hz;
1.35      deraadt   411: }
                    412:
                    413: int
1.38      canacar   414: main(int argc, char *argv[])
1.35      deraadt   415: {
1.38      canacar   416:        char errbuf[_POSIX2_LINE_MAX];
1.63      deraadt   417:        const char *errstr;
1.38      canacar   418:        extern char *optarg;
                    419:        extern int optind;
                    420:        double delay = 5;
                    421:
                    422:        char *viewstr = NULL;
                    423:
                    424:        gid_t gid;
                    425:        int countmax = 0;
                    426:        int maxlines = 0;
                    427:
                    428:        int ch;
                    429:
                    430:        ut = open(_PATH_UTMP, O_RDONLY);
                    431:        if (ut < 0) {
                    432:                warn("No utmp");
                    433:        }
                    434:
1.62      claudio   435:        kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
1.38      canacar   436:
                    437:        gid = getgid();
                    438:        if (setresgid(gid, gid, gid) == -1)
                    439:                err(1, "setresgid");
                    440:
1.60      reyk      441:        while ((ch = getopt(argc, argv, "BNabd:ins:w:")) != -1) {
1.38      canacar   442:                switch (ch) {
                    443:                case 'a':
                    444:                        maxlines = -1;
                    445:                        break;
1.60      reyk      446:                case 'B':
                    447:                        averageonly = 1;
                    448:                        if (countmax < 2)
                    449:                                countmax = 2;
                    450:                        /* FALLTHROUGH */
1.38      canacar   451:                case 'b':
                    452:                        rawmode = 1;
                    453:                        interactive = 0;
                    454:                        break;
                    455:                case 'd':
1.63      deraadt   456:                        countmax = strtonum(optarg, 1, INT_MAX, &errstr);
                    457:                        if (errstr)
                    458:                                errx(1, "-d %s: %s", optarg, errstr);
1.38      canacar   459:                        break;
                    460:                case 'i':
                    461:                        interactive = 1;
                    462:                        break;
1.55      sthen     463:                case 'N':
                    464:                        nflag = 0;
                    465:                        break;
1.38      canacar   466:                case 'n':
1.55      sthen     467:                        /* this is a noop, -n is the default */
1.38      canacar   468:                        nflag = 1;
                    469:                        break;
                    470:                case 's':
                    471:                        delay = atof(optarg);
1.39      canacar   472:                        if (delay <= 0)
1.38      canacar   473:                                delay = 5;
                    474:                        break;
                    475:                case 'w':
1.63      deraadt   476:                        rawwidth = strtonum(optarg, 1, MAX_LINE_BUF-1, &errstr);
                    477:                        if (errstr)
                    478:                                errx(1, "-w %s: %s", optarg, errstr);
1.38      canacar   479:                        break;
                    480:                default:
                    481:                        usage();
                    482:                        /* NOTREACHED */
                    483:                }
                    484:        }
1.43      matthieu  485:
                    486:        if (kd == NULL)
                    487:                warnx("kvm_openfiles: %s", errbuf);
1.38      canacar   488:
                    489:        argc -= optind;
                    490:        argv += optind;
                    491:
                    492:        if (argc == 1) {
                    493:                double del = atof(argv[0]);
                    494:                if (del == 0)
                    495:                        viewstr = argv[0];
                    496:                else
                    497:                        delay = del;
                    498:        } else if (argc == 2) {
                    499:                viewstr = argv[0];
                    500:                delay = atof(argv[1]);
1.42      canacar   501:                if (delay <= 0)
                    502:                        delay = 5;
1.38      canacar   503:        }
                    504:
                    505:        udelay = (useconds_t)(delay * 1000000.0);
                    506:        if (udelay < 1)
                    507:                udelay = 1;
1.39      canacar   508:
                    509:        naptime = (double)udelay / 1000000.0;
1.38      canacar   510:
                    511:        gethostname(hostname, sizeof (hostname));
                    512:        gethz();
                    513:
                    514:        initialize();
                    515:
                    516:        set_order(NULL);
                    517:        if (viewstr && set_view(viewstr)) {
1.49      espie     518:                fprintf(stderr, "Unknown/ambiguous view name: %s\n", viewstr);
1.38      canacar   519:                return 1;
                    520:        }
                    521:
1.57      lum       522:        if (check_termcap()) {
1.38      canacar   523:                rawmode = 1;
                    524:                interactive = 0;
                    525:        }
                    526:
                    527:        setup_term(maxlines);
                    528:
                    529:        if (rawmode && countmax == 0)
                    530:                countmax = 1;
                    531:
                    532:        gotsig_alarm = 1;
1.35      deraadt   533:
1.38      canacar   534:        engine_loop(countmax);
1.35      deraadt   535:
1.38      canacar   536:        return 0;
1.1       deraadt   537: }