[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.56

1.56    ! lum         1: /* $Id: main.c,v 1.55 2009/07/21 17:07:38 sthen 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.1       deraadt    34: #include <sys/param.h>
1.21      deraadt    35: #include <sys/sysctl.h>
1.1       deraadt    36:
1.38      canacar    37:
                     38: #include <ctype.h>
                     39: #include <curses.h>
1.1       deraadt    40: #include <err.h>
1.38      canacar    41: #include <errno.h>
                     42: #include <fcntl.h>
                     43: #include <limits.h>
                     44: #include <netdb.h>
1.1       deraadt    45: #include <signal.h>
                     46: #include <stdio.h>
1.38      canacar    47: #include <stdlib.h>
1.1       deraadt    48: #include <string.h>
1.38      canacar    49: #include <stdarg.h>
1.3       deraadt    50: #include <unistd.h>
1.35      deraadt    51: #include <utmp.h>
1.1       deraadt    52:
1.38      canacar    53: #include "engine.h"
1.1       deraadt    54: #include "systat.h"
                     55:
1.21      deraadt    56: double dellave;
1.1       deraadt    57:
1.21      deraadt    58: kvm_t  *kd;
                     59: char   *nlistf = NULL;
1.20      pvalchev   60: char   *memf = NULL;
1.21      deraadt    61: double avenrun[3];
1.36      tedu       62: double naptime = 5.0;
1.21      deraadt    63: int    verbose = 1;            /* to report kvm read errs */
1.38      canacar    64: int    nflag = 1;
1.35      deraadt    65: int    ut, hz, stathz;
1.1       deraadt    66: char    hostname[MAXHOSTNAMELEN];
                     67: WINDOW  *wnd;
1.32      deraadt    68: int    CMDLINE;
1.1       deraadt    69:
1.38      canacar    70: #define TIMEPOS 55
                     71:
1.50      canacar    72: int  ucount(void);
                     73: void usage(void);
                     74:
1.38      canacar    75: /* command prompt */
                     76:
1.46      canacar    77: void cmd_delay(const char *);
                     78: void cmd_count(const char *);
                     79: void cmd_compat(const char *);
1.38      canacar    80:
                     81: struct command cm_compat = {"Command", cmd_compat};
                     82: struct command cm_delay = {"Seconds to delay", cmd_delay};
                     83: struct command cm_count = {"Number of lines to display", cmd_count};
1.1       deraadt    84:
1.38      canacar    85:
                     86: /* display functions */
1.3       deraadt    87:
1.2       deraadt    88: int
1.38      canacar    89: print_header(void)
1.1       deraadt    90: {
1.50      canacar    91:        time_t now;
1.40      deraadt    92:        int start = dispstart + 1, end = dispstart + maxprint;
                     93:        char tbuf[26];
1.38      canacar    94:
                     95:        if (end > num_disp)
                     96:                end = num_disp;
                     97:
                     98:        tb_start();
1.35      deraadt    99:
1.54      deraadt   100:        getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
1.38      canacar   101:
                    102:        time(&now);
                    103:        strlcpy(tbuf, ctime(&now), sizeof tbuf);
                    104:        tbprintf("   %d users", ucount());
                    105:        tbprintf("    Load %.2f %.2f %.2f", avenrun[0], avenrun[1], avenrun[2]);
                    106:        if (num_disp && (start > 1 || end != num_disp))
                    107:                tbprintf("  (%u-%u of %u)", start, end, num_disp);
1.25      deraadt   108:
1.38      canacar   109:        if (paused)
                    110:                tbprintf(" PAUSED");
1.25      deraadt   111:
1.56    ! lum       112:        if (rawmode) {
        !           113:                printf("\n\n%-55s%s\n", tmp_buf, tbuf);
        !           114:        } else {
1.38      canacar   115:                mvprintw(0, 0, "%s", tmp_buf);
1.56    ! lum       116:                mvprintw(0, TIMEPOS, "%s", tbuf);
        !           117:        }
1.24      deraadt   118:
1.38      canacar   119:        return (1);
1.1       deraadt   120: }
1.3       deraadt   121:
1.38      canacar   122: /* compatibility functions, rearrange later */
1.21      deraadt   123: void
1.38      canacar   124: error(const char *fmt, ...)
1.21      deraadt   125: {
1.38      canacar   126:        va_list ap;
                    127:        char buf[MAX_LINE_BUF];
                    128:
                    129:        va_start(ap, fmt);
                    130:        vsnprintf(buf, sizeof buf, fmt, ap);
                    131:        va_end(ap);
1.21      deraadt   132:
1.38      canacar   133:        message_set(buf);
1.21      deraadt   134: }
                    135:
1.38      canacar   136: void
                    137: nlisterr(struct nlist namelist[])
1.3       deraadt   138: {
1.38      canacar   139:        int i, n;
                    140:
                    141:        n = 0;
                    142:        clear();
                    143:        mvprintw(2, 10, "systat: nlist: can't find following symbols:");
                    144:        for (i = 0;
                    145:            namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
                    146:                if (namelist[i].n_value == 0)
                    147:                        mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
                    148:        move(CMDLINE, 0);
                    149:        clrtoeol();
                    150:        refresh();
                    151:        endwin();
1.3       deraadt   152:        exit(1);
                    153: }
                    154:
1.1       deraadt   155: void
1.38      canacar   156: die(void)
1.1       deraadt   157: {
1.38      canacar   158:        if (!rawmode)
                    159:                endwin();
                    160:        exit(0);
1.1       deraadt   161: }
                    162:
1.38      canacar   163:
                    164: int
                    165: prefix(char *s1, char *s2)
1.1       deraadt   166: {
1.38      canacar   167:
                    168:        while (*s1 == *s2) {
                    169:                if (*s1 == '\0')
                    170:                        return (1);
                    171:                s1++, s2++;
                    172:        }
                    173:        return (*s1 == '\0');
1.21      deraadt   174: }
                    175:
1.38      canacar   176: /* calculate number of users on the system */
                    177: int
                    178: ucount(void)
1.21      deraadt   179: {
1.38      canacar   180:        int nusers = 0;
                    181:        struct  utmp utmp;
1.35      deraadt   182:
1.38      canacar   183:        if (ut < 0)
                    184:                return (0);
                    185:        lseek(ut, (off_t)0, SEEK_SET);
                    186:        while (read(ut, &utmp, sizeof(utmp)))
                    187:                if (utmp.ut_name[0] != '\0')
                    188:                        nusers++;
1.35      deraadt   189:
1.38      canacar   190:        return (nusers);
1.1       deraadt   191: }
                    192:
1.38      canacar   193: /* main program functions */
                    194:
1.1       deraadt   195: void
1.50      canacar   196: usage(void)
1.1       deraadt   197: {
1.38      canacar   198:        extern char *__progname;
1.55      sthen     199:        fprintf(stderr, "usage: %s [-abiNn] [-d count] "
1.43      matthieu  200:            "[-s delay] [-w width] [view] [delay]\n", __progname);
1.38      canacar   201:        exit(1);
1.1       deraadt   202: }
                    203:
1.45      canacar   204: void
                    205: show_view(void)
                    206: {
                    207:        if (rawmode)
                    208:                return;
                    209:
                    210:        tb_start();
                    211:        tbprintf("%s %g", curr_view->name, naptime);
                    212:        tb_end();
                    213:        message_set(tmp_buf);
                    214: }
1.21      deraadt   215:
1.1       deraadt   216: void
1.38      canacar   217: add_view_tb(field_view *v)
1.1       deraadt   218: {
1.38      canacar   219:        if (curr_view == v)
                    220:                tbprintf("[%s] ", v->name);
                    221:        else
                    222:                tbprintf("%s ", v->name);
1.29      deraadt   223: }
                    224:
                    225: void
1.38      canacar   226: show_help(void)
1.29      deraadt   227: {
1.38      canacar   228:        if (rawmode)
                    229:                return;
                    230:
                    231:        tb_start();
                    232:        foreach_view(add_view_tb);
                    233:        tb_end();
                    234:        message_set(tmp_buf);
1.21      deraadt   235: }
                    236:
                    237: void
1.46      canacar   238: cmd_compat(const char *buf)
1.21      deraadt   239: {
1.46      canacar   240:        const char *s;
1.38      canacar   241:
1.46      canacar   242:        if (strcasecmp(buf, "help") == 0) {
1.38      canacar   243:                show_help();
                    244:                need_update = 1;
                    245:                return;
                    246:        }
1.46      canacar   247:        if (strcasecmp(buf, "quit") == 0 || strcasecmp(buf, "q") == 0) {
1.38      canacar   248:                gotsig_close = 1;
                    249:                return;
                    250:        }
1.46      canacar   251:        if (strcasecmp(buf, "stop") == 0) {
                    252:                paused = 1;
                    253:                gotsig_alarm = 1;
                    254:                return;
                    255:        }
                    256:        if (strncasecmp(buf, "start", 5) == 0) {
                    257:                paused = 0;
                    258:                gotsig_alarm = 1;
1.47      canacar   259:                cmd_delay(buf + 5);
1.46      canacar   260:                return;
                    261:        }
1.38      canacar   262:
1.46      canacar   263:        for (s = buf; *s && strchr("0123456789+-.eE", *s) != NULL; s++)
1.38      canacar   264:                ;
                    265:        if (*s) {
1.46      canacar   266:                if (set_view(buf))
1.49      espie     267:                        error("Invalid/ambiguous view: %s", buf);
1.38      canacar   268:        } else
1.46      canacar   269:                cmd_delay(buf);
1.38      canacar   270: }
                    271:
                    272: void
1.46      canacar   273: cmd_delay(const char *buf)
1.38      canacar   274: {
                    275:        double del;
1.46      canacar   276:        del = atof(buf);
1.39      canacar   277:
1.38      canacar   278:        if (del > 0) {
                    279:                udelay = (useconds_t)(del * 1000000);
                    280:                gotsig_alarm = 1;
1.39      canacar   281:                naptime = del;
1.13      deraadt   282:        }
1.1       deraadt   283: }
1.14      kstailey  284:
                    285: void
1.46      canacar   286: cmd_count(const char *buf)
1.14      kstailey  287: {
1.38      canacar   288:        int ms;
1.46      canacar   289:        ms = atoi(buf);
1.38      canacar   290:
                    291:        if (ms <= 0 || ms > lines - HEADER_LINES)
                    292:                maxprint = lines - HEADER_LINES;
                    293:        else
                    294:                maxprint = ms;
1.14      kstailey  295: }
                    296:
1.38      canacar   297:
                    298: int
                    299: keyboard_callback(int ch)
1.1       deraadt   300: {
1.38      canacar   301:        switch (ch) {
                    302:        case '?':
                    303:                /* FALLTHROUGH */
                    304:        case 'h':
                    305:                show_help();
1.45      canacar   306:                need_update = 1;
                    307:                break;
                    308:        case CTRL_G:
                    309:                show_view();
1.38      canacar   310:                need_update = 1;
                    311:                break;
                    312:        case 'l':
                    313:                command_set(&cm_count, NULL);
                    314:                break;
                    315:        case 's':
                    316:                command_set(&cm_delay, NULL);
                    317:                break;
                    318:        case ':':
                    319:                command_set(&cm_compat, NULL);
                    320:                break;
                    321:        default:
                    322:                return 0;
                    323:        };
                    324:
                    325:        return 1;
                    326: }
1.23      millert   327:
1.38      canacar   328: void
                    329: initialize(void)
                    330: {
                    331:        engine_initialize();
                    332:
                    333:        initvmstat();
                    334:        initpigs();
                    335:        initifstat();
                    336:        initiostat();
                    337:        initsensors();
                    338:        initmembufs();
                    339:        initnetstat();
                    340:        initswap();
                    341:        initpftop();
                    342:        initpf();
1.48      canacar   343:        initpool();
1.51      canacar   344:        initmalloc();
1.52      jasper    345:        initnfs();
1.1       deraadt   346: }
                    347:
                    348: void
1.38      canacar   349: gethz(void)
1.1       deraadt   350: {
1.38      canacar   351:        struct clockinfo cinf;
                    352:        size_t  size = sizeof(cinf);
                    353:        int     mib[2];
1.1       deraadt   354:
1.38      canacar   355:        mib[0] = CTL_KERN;
                    356:        mib[1] = KERN_CLOCKRATE;
                    357:        if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
                    358:                return;
                    359:        stathz = cinf.stathz;
                    360:        hz = cinf.hz;
1.35      deraadt   361: }
                    362:
                    363: int
1.38      canacar   364: main(int argc, char *argv[])
1.35      deraadt   365: {
1.38      canacar   366:        char errbuf[_POSIX2_LINE_MAX];
                    367:        extern char *optarg;
                    368:        extern int optind;
                    369:        double delay = 5;
                    370:
                    371:        char *viewstr = NULL;
                    372:
                    373:        gid_t gid;
                    374:        int countmax = 0;
                    375:        int maxlines = 0;
                    376:
                    377:        int ch;
                    378:
                    379:        ut = open(_PATH_UTMP, O_RDONLY);
                    380:        if (ut < 0) {
                    381:                warn("No utmp");
                    382:        }
                    383:
                    384:        kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
                    385:
                    386:        gid = getgid();
                    387:        if (setresgid(gid, gid, gid) == -1)
                    388:                err(1, "setresgid");
                    389:
1.55      sthen     390:        while ((ch = getopt(argc, argv, "Nabd:ins:w:")) != -1) {
1.38      canacar   391:                switch (ch) {
                    392:                case 'a':
                    393:                        maxlines = -1;
                    394:                        break;
                    395:                case 'b':
                    396:                        rawmode = 1;
                    397:                        interactive = 0;
                    398:                        break;
                    399:                case 'd':
                    400:                        countmax = atoi(optarg);
                    401:                        if (countmax < 0)
                    402:                                countmax = 0;
                    403:                        break;
                    404:                case 'i':
                    405:                        interactive = 1;
                    406:                        break;
1.55      sthen     407:                case 'N':
                    408:                        nflag = 0;
                    409:                        break;
1.38      canacar   410:                case 'n':
1.55      sthen     411:                        /* this is a noop, -n is the default */
1.38      canacar   412:                        nflag = 1;
                    413:                        break;
                    414:                case 's':
                    415:                        delay = atof(optarg);
1.39      canacar   416:                        if (delay <= 0)
1.38      canacar   417:                                delay = 5;
                    418:                        break;
                    419:                case 'w':
                    420:                        rawwidth = atoi(optarg);
                    421:                        if (rawwidth < 1)
                    422:                                rawwidth = DEFAULT_WIDTH;
                    423:                        if (rawwidth >= MAX_LINE_BUF)
                    424:                                rawwidth = MAX_LINE_BUF - 1;
                    425:                        break;
                    426:                default:
                    427:                        usage();
                    428:                        /* NOTREACHED */
                    429:                }
                    430:        }
1.43      matthieu  431:
                    432:        if (kd == NULL)
                    433:                warnx("kvm_openfiles: %s", errbuf);
1.38      canacar   434:
                    435:        argc -= optind;
                    436:        argv += optind;
                    437:
                    438:        if (argc == 1) {
                    439:                double del = atof(argv[0]);
                    440:                if (del == 0)
                    441:                        viewstr = argv[0];
                    442:                else
                    443:                        delay = del;
                    444:        } else if (argc == 2) {
                    445:                viewstr = argv[0];
                    446:                delay = atof(argv[1]);
1.42      canacar   447:                if (delay <= 0)
                    448:                        delay = 5;
1.38      canacar   449:        }
                    450:
                    451:        udelay = (useconds_t)(delay * 1000000.0);
                    452:        if (udelay < 1)
                    453:                udelay = 1;
1.39      canacar   454:
                    455:        naptime = (double)udelay / 1000000.0;
1.38      canacar   456:
                    457:        gethostname(hostname, sizeof (hostname));
                    458:        gethz();
                    459:
                    460:        initialize();
                    461:
                    462:        set_order(NULL);
                    463:        if (viewstr && set_view(viewstr)) {
1.49      espie     464:                fprintf(stderr, "Unknown/ambiguous view name: %s\n", viewstr);
1.38      canacar   465:                return 1;
                    466:        }
                    467:
                    468:        if (!isatty(STDOUT_FILENO)) {
                    469:                rawmode = 1;
                    470:                interactive = 0;
                    471:        }
                    472:
                    473:        setup_term(maxlines);
                    474:
                    475:        if (rawmode && countmax == 0)
                    476:                countmax = 1;
                    477:
                    478:        gotsig_alarm = 1;
1.35      deraadt   479:
1.38      canacar   480:        engine_loop(countmax);
1.35      deraadt   481:
1.38      canacar   482:        return 0;
1.1       deraadt   483: }