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

1.45    ! canacar     1: /* $Id: main.c,v 1.44 2008/08/13 06:20:48 jmc 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:
                     72: /* command prompt */
                     73:
                     74: void cmd_delay(void);
                     75: void cmd_count(void);
                     76: void cmd_compat(void);
                     77:
                     78: struct command cm_compat = {"Command", cmd_compat};
                     79: struct command cm_delay = {"Seconds to delay", cmd_delay};
                     80: struct command cm_count = {"Number of lines to display", cmd_count};
1.1       deraadt    81:
1.38      canacar    82:
                     83: /* display functions */
1.3       deraadt    84:
1.2       deraadt    85: int
1.38      canacar    86: print_header(void)
1.1       deraadt    87: {
1.38      canacar    88:        struct tm *tp;
1.40      deraadt    89:        time_t t, now;
1.38      canacar    90:        order_type *ordering;
1.40      deraadt    91:        int start = dispstart + 1, end = dispstart + maxprint;
                     92:        extern int ucount();
                     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.38      canacar   100: #if 0
                    101:        if (curr_mgr && curr_mgr->sort_fn != NULL) {
                    102:                ordering = curr_mgr->order_curr;
                    103:                if (ordering != NULL) {
                    104:                        tbprintf(", Order: %s", ordering->name);
                    105:                        if (sortdir < 0 && ordering->func != NULL)
                    106:                                tbprintf(" (rev)");
                    107:                }
1.35      deraadt   108:        }
1.38      canacar   109: #endif
1.1       deraadt   110:
1.38      canacar   111:        getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
                    112:
                    113:        time(&now);
                    114:        strlcpy(tbuf, ctime(&now), sizeof tbuf);
                    115:        tbprintf("   %d users", ucount());
                    116:        tbprintf("    Load %.2f %.2f %.2f", avenrun[0], avenrun[1], avenrun[2]);
                    117:        if (num_disp && (start > 1 || end != num_disp))
                    118:                tbprintf("  (%u-%u of %u)", start, end, num_disp);
1.25      deraadt   119:
1.38      canacar   120:        if (paused)
                    121:                tbprintf(" PAUSED");
1.25      deraadt   122:
1.38      canacar   123:        if (rawmode)
                    124:                printf("\n\n%s\n", tmp_buf);
                    125:        else
                    126:                mvprintw(0, 0, "%s", tmp_buf);
1.36      tedu      127:
1.38      canacar   128:        mvprintw(0, TIMEPOS, "%s", tbuf);
1.3       deraadt   129:
1.24      deraadt   130:
1.38      canacar   131:        return (1);
1.1       deraadt   132: }
1.3       deraadt   133:
1.38      canacar   134: /* compatibility functions, rearrange later */
1.21      deraadt   135: void
1.38      canacar   136: error(const char *fmt, ...)
1.21      deraadt   137: {
1.38      canacar   138:        va_list ap;
                    139:        char buf[MAX_LINE_BUF];
                    140:
                    141:        va_start(ap, fmt);
                    142:        vsnprintf(buf, sizeof buf, fmt, ap);
                    143:        va_end(ap);
1.21      deraadt   144:
1.38      canacar   145:        message_set(buf);
1.21      deraadt   146: }
                    147:
1.38      canacar   148: void
                    149: nlisterr(struct nlist namelist[])
1.3       deraadt   150: {
1.38      canacar   151:        int i, n;
                    152:
                    153:        n = 0;
                    154:        clear();
                    155:        mvprintw(2, 10, "systat: nlist: can't find following symbols:");
                    156:        for (i = 0;
                    157:            namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
                    158:                if (namelist[i].n_value == 0)
                    159:                        mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
                    160:        move(CMDLINE, 0);
                    161:        clrtoeol();
                    162:        refresh();
                    163:        endwin();
1.3       deraadt   164:        exit(1);
                    165: }
                    166:
1.1       deraadt   167: void
1.38      canacar   168: die(void)
1.1       deraadt   169: {
1.38      canacar   170:        if (!rawmode)
                    171:                endwin();
                    172:        exit(0);
1.1       deraadt   173: }
                    174:
1.38      canacar   175:
                    176: int
                    177: prefix(char *s1, char *s2)
1.1       deraadt   178: {
1.38      canacar   179:
                    180:        while (*s1 == *s2) {
                    181:                if (*s1 == '\0')
                    182:                        return (1);
                    183:                s1++, s2++;
                    184:        }
                    185:        return (*s1 == '\0');
1.21      deraadt   186: }
                    187:
1.38      canacar   188: /* calculate number of users on the system */
                    189: int
                    190: ucount(void)
1.21      deraadt   191: {
1.38      canacar   192:        int nusers = 0;
                    193:        struct  utmp utmp;
1.35      deraadt   194:
1.38      canacar   195:        if (ut < 0)
                    196:                return (0);
                    197:        lseek(ut, (off_t)0, SEEK_SET);
                    198:        while (read(ut, &utmp, sizeof(utmp)))
                    199:                if (utmp.ut_name[0] != '\0')
                    200:                        nusers++;
1.35      deraadt   201:
1.38      canacar   202:        return (nusers);
1.1       deraadt   203: }
                    204:
1.38      canacar   205: /* main program functions */
                    206:
1.1       deraadt   207: void
1.38      canacar   208: usage()
1.1       deraadt   209: {
1.38      canacar   210:        extern char *__progname;
1.44      jmc       211:        fprintf(stderr, "usage: %s [-abin] [-d count] "
1.43      matthieu  212:            "[-s delay] [-w width] [view] [delay]\n", __progname);
1.38      canacar   213:        exit(1);
1.1       deraadt   214: }
                    215:
1.45    ! canacar   216: void
        !           217: show_view(void)
        !           218: {
        !           219:        if (rawmode)
        !           220:                return;
        !           221:
        !           222:        tb_start();
        !           223:        tbprintf("%s %g", curr_view->name, naptime);
        !           224:        tb_end();
        !           225:        message_set(tmp_buf);
        !           226: }
1.21      deraadt   227:
1.1       deraadt   228: void
1.38      canacar   229: add_view_tb(field_view *v)
1.1       deraadt   230: {
1.38      canacar   231:        if (curr_view == v)
                    232:                tbprintf("[%s] ", v->name);
                    233:        else
                    234:                tbprintf("%s ", v->name);
1.29      deraadt   235: }
                    236:
                    237: void
1.38      canacar   238: show_help(void)
1.29      deraadt   239: {
1.38      canacar   240:        int line = 0;
                    241:
                    242:        if (rawmode)
                    243:                return;
                    244:
                    245:        tb_start();
                    246:        foreach_view(add_view_tb);
                    247:        tb_end();
                    248:        message_set(tmp_buf);
                    249:
                    250: #if 0
                    251:        erase();
                    252:        mvprintw(line, 2, "Systat Help");
                    253:        line += 2;
                    254:        mvprintw(line,    5, " h  - Help (this page)");
                    255:        mvprintw(line++, 40, " l  - set number of Lines");
                    256:        mvprintw(line,    5, " p  - Pause display");
                    257:        mvprintw(line++, 40, " s  - Set update interval");
                    258:        mvprintw(line,    5, " v  - next View");
                    259:        mvprintw(line++, 40, " q  - Quit");
                    260:        line++;
                    261:        mvprintw(line++, 5, "0-7 - select view directly");
                    262:        mvprintw(line++, 5, "SPC - update immediately");
                    263:        mvprintw(line++, 5, "^L  - refresh display");
                    264:        line++;
                    265:        mvprintw(line++, 5, "cursor keys - scroll display");
                    266:        line++;
                    267:        mvprintw(line++,  3, "Netstat specific keys::");
                    268:        mvprintw(line,    5, " t  - toggle TCP display");
                    269:        mvprintw(line++, 40, " u  - toggle UDP display");
                    270:        mvprintw(line++,  5, " n  - toggle Name resolution");
                    271:        line++;
                    272:        mvprintw(line++,  3, "Ifstat specific keys::");
                    273:        mvprintw(line,    5, " r  - initialize RUN mode");
                    274:        mvprintw(line++, 40, " b  - set BOOT mode");
                    275:        mvprintw(line,    5, " t  - set TIME mode (default)");
                    276:        line++;
                    277:        line++;
                    278:        mvprintw(line++,  3, "VMstat specific keys::");
                    279:        mvprintw(line,    5, " r  - initialize RUN mode");
                    280:        mvprintw(line++, 40, " b  - set BOOT mode");
                    281:        mvprintw(line,    5, " t  - set TIME mode (default)");
                    282:        mvprintw(line++, 40, " z  - zero in RUN mode");
                    283:        line++;
                    284:        mvprintw(line++, 6, "press any key to continue ...");
                    285:
                    286:        while (getch() == ERR) {
                    287:                if (gotsig_close)
                    288:                        break;
                    289:        }
                    290: #endif
1.21      deraadt   291: }
                    292:
                    293: void
1.38      canacar   294: cmd_compat(void)
1.21      deraadt   295: {
1.38      canacar   296:        char *s;
                    297:
                    298:        if (strcasecmp(cmdbuf, "help") == 0) {
                    299:                show_help();
                    300:                need_update = 1;
                    301:                return;
                    302:        }
1.41      canacar   303:        if (strcasecmp(cmdbuf, "quit") == 0 || strcasecmp(cmdbuf, "q") == 0) {
1.38      canacar   304:                gotsig_close = 1;
                    305:                return;
                    306:        }
                    307:
                    308:        for (s = cmdbuf; *s && strchr("0123456789+-.eE", *s) != NULL; s++)
                    309:                ;
                    310:        if (*s) {
                    311:                if (set_view(cmdbuf))
                    312:                        error("Invalid/ambigious view: %s", cmdbuf);
                    313:        } else
                    314:                cmd_delay();
                    315: }
                    316:
                    317: void
                    318: cmd_delay(void)
                    319: {
                    320:        double del;
                    321:        del = atof(cmdbuf);
1.39      canacar   322:
1.38      canacar   323:        if (del > 0) {
                    324:                udelay = (useconds_t)(del * 1000000);
                    325:                gotsig_alarm = 1;
1.39      canacar   326:                naptime = del;
1.13      deraadt   327:        }
1.1       deraadt   328: }
1.14      kstailey  329:
                    330: void
1.38      canacar   331: cmd_count(void)
1.14      kstailey  332: {
1.38      canacar   333:        int ms;
                    334:        ms = atoi(cmdbuf);
                    335:
                    336:        if (ms <= 0 || ms > lines - HEADER_LINES)
                    337:                maxprint = lines - HEADER_LINES;
                    338:        else
                    339:                maxprint = ms;
1.14      kstailey  340: }
                    341:
1.38      canacar   342:
                    343: int
                    344: keyboard_callback(int ch)
1.1       deraadt   345: {
1.38      canacar   346:        switch (ch) {
                    347:        case '?':
                    348:                /* FALLTHROUGH */
                    349:        case 'h':
                    350:                show_help();
1.45    ! canacar   351:                need_update = 1;
        !           352:                break;
        !           353:        case CTRL_G:
        !           354:                show_view();
1.38      canacar   355:                need_update = 1;
                    356:                break;
                    357:        case 'l':
                    358:                command_set(&cm_count, NULL);
                    359:                break;
                    360:        case 's':
                    361:                command_set(&cm_delay, NULL);
                    362:                break;
                    363:        case ':':
                    364:                command_set(&cm_compat, NULL);
                    365:                break;
                    366:        default:
                    367:                return 0;
                    368:        };
                    369:
                    370:        return 1;
                    371: }
1.23      millert   372:
1.38      canacar   373: void
                    374: initialize(void)
                    375: {
                    376:        engine_initialize();
                    377:
                    378:        initvmstat();
                    379:        initpigs();
                    380:        initifstat();
                    381:        initiostat();
                    382:        initsensors();
                    383:        initmembufs();
                    384:        initnetstat();
                    385:        initswap();
                    386:        initpftop();
                    387:        initpf();
1.1       deraadt   388: }
                    389:
                    390: void
1.38      canacar   391: gethz(void)
1.1       deraadt   392: {
1.38      canacar   393:        struct clockinfo cinf;
                    394:        size_t  size = sizeof(cinf);
                    395:        int     mib[2];
1.1       deraadt   396:
1.38      canacar   397:        mib[0] = CTL_KERN;
                    398:        mib[1] = KERN_CLOCKRATE;
                    399:        if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
                    400:                return;
                    401:        stathz = cinf.stathz;
                    402:        hz = cinf.hz;
1.35      deraadt   403: }
                    404:
                    405: int
1.38      canacar   406: main(int argc, char *argv[])
1.35      deraadt   407: {
1.38      canacar   408:        char errbuf[_POSIX2_LINE_MAX];
                    409:        extern char *optarg;
                    410:        extern int optind;
                    411:        double delay = 5;
                    412:
                    413:        char *viewstr = NULL;
                    414:
                    415:        gid_t gid;
                    416:        int countmax = 0;
                    417:        int maxlines = 0;
                    418:
                    419:        int ch;
                    420:
                    421:        ut = open(_PATH_UTMP, O_RDONLY);
                    422:        if (ut < 0) {
                    423:                warn("No utmp");
                    424:        }
                    425:
                    426:        kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
                    427:
                    428:        gid = getgid();
                    429:        if (setresgid(gid, gid, gid) == -1)
                    430:                err(1, "setresgid");
                    431:
1.43      matthieu  432:        while ((ch = getopt(argc, argv, "abd:ins:S:w:")) != -1) {
1.38      canacar   433:                switch (ch) {
                    434:                case 'a':
                    435:                        maxlines = -1;
                    436:                        break;
                    437:                case 'b':
                    438:                        rawmode = 1;
                    439:                        interactive = 0;
                    440:                        break;
                    441:                case 'd':
                    442:                        countmax = atoi(optarg);
                    443:                        if (countmax < 0)
                    444:                                countmax = 0;
                    445:                        break;
                    446:                case 'i':
                    447:                        interactive = 1;
                    448:                        break;
                    449:                case 'n':
                    450:                        nflag = 1;
                    451:                        break;
                    452:                case 's':
                    453:                        delay = atof(optarg);
1.39      canacar   454:                        if (delay <= 0)
1.38      canacar   455:                                delay = 5;
                    456:                        break;
                    457:                case 'S':
                    458:                        dispstart = atoi(optarg);
                    459:                        if (dispstart < 0)
                    460:                                dispstart = 0;
                    461:                        break;
                    462:                case 'w':
                    463:                        rawwidth = atoi(optarg);
                    464:                        if (rawwidth < 1)
                    465:                                rawwidth = DEFAULT_WIDTH;
                    466:                        if (rawwidth >= MAX_LINE_BUF)
                    467:                                rawwidth = MAX_LINE_BUF - 1;
                    468:                        break;
                    469:                default:
                    470:                        usage();
                    471:                        /* NOTREACHED */
                    472:                }
                    473:        }
1.43      matthieu  474:
                    475:        if (kd == NULL)
                    476:                warnx("kvm_openfiles: %s", errbuf);
1.38      canacar   477:
                    478:        argc -= optind;
                    479:        argv += optind;
                    480:
                    481:        if (argc == 1) {
                    482:                double del = atof(argv[0]);
                    483:                if (del == 0)
                    484:                        viewstr = argv[0];
                    485:                else
                    486:                        delay = del;
                    487:        } else if (argc == 2) {
                    488:                viewstr = argv[0];
                    489:                delay = atof(argv[1]);
1.42      canacar   490:                if (delay <= 0)
                    491:                        delay = 5;
1.38      canacar   492:        }
                    493:
                    494:        udelay = (useconds_t)(delay * 1000000.0);
                    495:        if (udelay < 1)
                    496:                udelay = 1;
1.39      canacar   497:
                    498:        naptime = (double)udelay / 1000000.0;
1.38      canacar   499:
                    500:        gethostname(hostname, sizeof (hostname));
                    501:        gethz();
                    502:
                    503:        initialize();
                    504:
                    505:        set_order(NULL);
                    506:        if (viewstr && set_view(viewstr)) {
                    507:                fprintf(stderr, "Unknown/ambigious view name: %s\n", viewstr);
                    508:                return 1;
                    509:        }
                    510:
                    511:        if (!isatty(STDOUT_FILENO)) {
                    512:                rawmode = 1;
                    513:                interactive = 0;
                    514:        }
                    515:
                    516:        setup_term(maxlines);
                    517:
                    518:        if (rawmode && countmax == 0)
                    519:                countmax = 1;
                    520:
                    521:        gotsig_alarm = 1;
1.35      deraadt   522:
1.38      canacar   523:        engine_loop(countmax);
1.35      deraadt   524:
1.38      canacar   525:        return 0;
1.1       deraadt   526: }