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

Annotation of src/usr.bin/top/top.c, Revision 1.20

1.20    ! deraadt     1: /*     $OpenBSD: top.c,v 1.19 2003/06/12 22:30:23 pvalchev Exp $       */
1.1       downsj      2:
                      3: /*
                      4:  *  Top users/processes display for Unix
                      5:  *  Version 3
                      6:  *
1.18      deraadt     7:  * Copyright (c) 1984, 1989, William LeFebvre, Rice University
                      8:  * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
1.1       downsj      9:  *
1.18      deraadt    10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     21:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     22:  * IN NO EVENT SHALL THE AUTHOR OR HIS EMPLOYER BE LIABLE FOR ANY DIRECT, INDIRECT,
                     23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     24:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     25:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     26:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     27:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     28:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1       downsj     29:  */
                     30:
1.20    ! deraadt    31: const char      copyright[] = "Copyright (c) 1984 through 1996, William LeFebvre";
1.1       downsj     32:
1.2       downsj     33: #include <sys/types.h>
                     34: #include <stdio.h>
                     35: #include <ctype.h>
1.1       downsj     36: #include <signal.h>
                     37: #include <setjmp.h>
1.2       downsj     38: #include <string.h>
                     39: #include <stdlib.h>
                     40: #include <unistd.h>
1.5       deraadt    41: #include <errno.h>
1.1       downsj     42: #include <sys/time.h>
                     43:
                     44: /* includes specific to top */
                     45: #include "display.h"           /* interface to display package */
                     46: #include "screen.h"            /* interface to screen package */
                     47: #include "top.h"
                     48: #include "top.local.h"
                     49: #include "boolean.h"
                     50: #include "machine.h"
                     51: #include "utils.h"
                     52:
                     53: /* Size of the stdio buffer given to stdout */
1.20    ! deraadt    54: #define BUFFERSIZE     2048
1.1       downsj     55:
                     56: /* The buffer that stdio will use */
1.20    ! deraadt    57: char            stdoutbuf[BUFFERSIZE];
1.1       downsj     58:
1.20    ! deraadt    59: extern int      overstrike;
1.1       downsj     60:
                     61: /* signal handling routines */
1.20    ! deraadt    62: static void     leave(int);
        !            63: static void     onalrm(int);
        !            64: static void     tstop(int);
1.1       downsj     65: #ifdef SIGWINCH
1.20    ! deraadt    66: static void     winch(int);
1.1       downsj     67: #endif
                     68:
1.13      deraadt    69: volatile sig_atomic_t leaveflag;
                     70: volatile sig_atomic_t tstopflag;
                     71: volatile sig_atomic_t winchflag;
1.7       deraadt    72:
1.20    ! deraadt    73: static void     reset_display(void);
        !            74: int            rundisplay(void);
1.1       downsj     75:
                     76: /* values which need to be accessed by signal handlers */
1.20    ! deraadt    77: static int      max_topn;      /* maximum displayable processes */
1.1       downsj     78:
                     79: /* miscellaneous things */
1.20    ! deraadt    80: jmp_buf         jmp_int;
1.1       downsj     81:
                     82: /* routines that don't return int */
                     83:
1.20    ! deraadt    84: extern char *__progname;
1.1       downsj     85:
1.20    ! deraadt    86: extern int      (*proc_compares[])(const void *, const void *);
        !            87: int order_index;
1.1       downsj     88:
                     89: /* pointers to display routines */
1.20    ! deraadt    90: void            (*d_loadave) () = i_loadave;
        !            91: void            (*d_procstates) () = i_procstates;
        !            92: void            (*d_cpustates) () = i_cpustates;
        !            93: void            (*d_memory) () = i_memory;
        !            94: void            (*d_message) () = i_message;
        !            95: void            (*d_header) () = i_header;
        !            96: void            (*d_process) () = i_process;
        !            97:
        !            98: int displays = 0;      /* indicates unspecified */
        !            99: char do_unames = Yes;
        !           100: struct process_select ps;
        !           101: char dostates = No;
        !           102: char interactive = Maybe;
        !           103: char warnings = 0;
        !           104: double delay = Default_DELAY;
        !           105: char *order_name = NULL;
        !           106: int topn = Default_TOPN;
        !           107: int no_command = 1;
1.1       downsj    108:
                    109: #if Default_TOPN == Infinity
1.20    ! deraadt   110: char topn_specified = No;
1.1       downsj    111: #endif
                    112:
1.20    ! deraadt   113: /*
        !           114:  * these defines enumerate the "strchr"s of the commands in
        !           115:  * command_chars
        !           116:  */
1.1       downsj    117: #define CMD_redraw     0
                    118: #define CMD_update     1
                    119: #define CMD_quit       2
                    120: #define CMD_help1      3
                    121: #define CMD_help2      4
1.20    ! deraadt   122: #define CMD_OSLIMIT    4       /* terminals with OS can only handle commands */
        !           123: #define CMD_errors     5       /* less than or equal to CMD_OSLIMIT       */
1.1       downsj    124: #define CMD_number1    6
                    125: #define CMD_number2    7
                    126: #define CMD_delay      8
                    127: #define CMD_displays   9
                    128: #define CMD_kill       10
                    129: #define CMD_renice     11
                    130: #define CMD_idletog     12
                    131: #define CMD_idletog2    13
                    132: #define CMD_user       14
1.12      fgsch     133: #define CMD_system     15
                    134: #define CMD_order       16
1.1       downsj    135:
1.20    ! deraadt   136: void
        !           137: usage(void)
        !           138: {
        !           139:        fprintf(stderr,
        !           140:            "Top version %s\n"
        !           141:            "Usage: %s [-ISbinqu] [-d x] [-s x] [-o field] [-U username] [number]\n",
        !           142:            version_string(), __progname);
        !           143: }
        !           144:
        !           145: void
        !           146: parseargs(int ac, char **av)
        !           147: {
        !           148:        char *endp;
        !           149:        int i;
        !           150:
        !           151:        while ((i = getopt(ac, av, "SIbinqus:d:U:o:")) != -1) {
        !           152:                switch (i) {
        !           153:                case 'u':       /* toggle uid/username display */
        !           154:                        do_unames = !do_unames;
        !           155:                        break;
        !           156:
        !           157:                case 'U':       /* display only username's processes */
        !           158:                        if ((ps.uid = userid(optarg)) == -1) {
        !           159:                                fprintf(stderr, "%s: unknown user\n", optarg);
        !           160:                                exit(1);
        !           161:                        }
        !           162:                        break;
1.1       downsj    163:
1.20    ! deraadt   164:                case 'S':       /* show system processes */
        !           165:                        ps.system = !ps.system;
        !           166:                        break;
        !           167:
        !           168:                case 'I':       /* show idle processes */
        !           169:                        ps.idle = !ps.idle;
        !           170:                        break;
        !           171:
        !           172:                case 'i':       /* go interactive regardless */
        !           173:                        interactive = Yes;
        !           174:                        break;
        !           175:
        !           176:                case 'n':       /* batch, or non-interactive */
        !           177:                case 'b':
        !           178:                        interactive = No;
        !           179:                        break;
        !           180:
        !           181:                case 'd':       /* number of displays to show */
        !           182:                        if ((i = atoiwi(optarg)) != Invalid && i != 0) {
        !           183:                                displays = i;
        !           184:                                break;
        !           185:                        }
        !           186:                        fprintf(stderr,
        !           187:                            "%s: warning: display count should be positive "
        !           188:                            "-- option ignored\n",
        !           189:                            __progname);
        !           190:                        warnings++;
        !           191:                        break;
        !           192:
        !           193:                case 's':
        !           194:                        delay = strtod(optarg, &endp);
        !           195:
        !           196:                        if (delay > 0 && delay <= 1000000 && *endp == '\0')
        !           197:                                break;
        !           198:
        !           199:                        fprintf(stderr,
        !           200:                            "%s: warning: delay should be a non-negative number"
        !           201:                            " -- using default\n",
        !           202:                            __progname);
        !           203:                        delay = Default_DELAY;
        !           204:                        warnings++;
        !           205:                        break;
        !           206:
        !           207:                case 'q':       /* be quick about it */
        !           208:                        /* only allow this if user is really root */
        !           209:                        if (getuid() == 0) {
        !           210:                                /* be very un-nice! */
        !           211:                                (void) nice(-20);
        !           212:                                break;
        !           213:                        }
        !           214:                        fprintf(stderr,
        !           215:                            "%s: warning: `-q' option can only be used by root\n",
        !           216:                            __progname);
        !           217:                        warnings++;
        !           218:                        break;
        !           219:
        !           220:                case 'o':       /* select sort order */
        !           221:                        order_name = optarg;
        !           222:                        break;
        !           223:
        !           224:                default:
        !           225:                        usage();
        !           226:                        exit(1);
1.1       downsj    227:                }
1.20    ! deraadt   228:        }
1.1       downsj    229:
1.20    ! deraadt   230:        /* get count of top processes to display (if any) */
        !           231:        if (optind < ac) {
        !           232:                if ((topn = atoiwi(av[optind])) == Invalid) {
        !           233:                        fprintf(stderr,
        !           234:                            "%s: warning: process display count should "
        !           235:                            "be non-negative -- using default\n",
        !           236:                            __progname);
        !           237:                        warnings++;
1.1       downsj    238:                }
1.20    ! deraadt   239: #if Default_TOPN == Infinity
1.1       downsj    240:                else
1.20    ! deraadt   241:                        topn_specified = Yes;
        !           242: #endif
        !           243:        }
        !           244: }
1.1       downsj    245:
1.20    ! deraadt   246: struct system_info system_info;
        !           247: struct statics  statics;
1.1       downsj    248:
1.20    ! deraadt   249: int
        !           250: main(int argc, char *argv[])
        !           251: {
        !           252:        char *uname_field = "USERNAME", *header_text, *env_top;
        !           253:        char *(*get_userid)() = username, **preset_argv, **av;
        !           254:        int preset_argc = 0, ac, active_procs, i;
        !           255:        sigset_t mask, oldmask;
        !           256:        time_t curr_time;
        !           257:        caddr_t processes;
1.1       downsj    258:
1.20    ! deraadt   259:        /* set the buffer for stdout */
        !           260: #ifdef DEBUG
        !           261:        setbuffer(stdout, NULL, 0);
1.1       downsj    262: #else
1.20    ! deraadt   263:        setbuffer(stdout, stdoutbuf, sizeof stdoutbuf);
1.1       downsj    264: #endif
                    265:
1.20    ! deraadt   266:        /* initialize some selection options */
        !           267:        ps.idle = Yes;
        !           268:        ps.system = No;
        !           269:        ps.uid = -1;
        !           270:        ps.command = NULL;
        !           271:
        !           272:        /* get preset options from the environment */
        !           273:        if ((env_top = getenv("TOP")) != NULL) {
        !           274:                av = preset_argv = argparse(env_top, &preset_argc);
        !           275:                ac = preset_argc;
        !           276:
        !           277:                /*
        !           278:                 * set the dummy argument to an explanatory message, in case
        !           279:                 * getopt encounters a bad argument
        !           280:                 */
        !           281:                preset_argv[0] = "while processing environment";
        !           282:        }
        !           283:        /* process options */
        !           284:        do {
        !           285:                /*
        !           286:                 * if we're done doing the presets, then process the real
        !           287:                 * arguments
        !           288:                 */
        !           289:                if (preset_argc == 0) {
        !           290:                        ac = argc;
        !           291:                        av = argv;
        !           292:                        optind = 1;
        !           293:                }
        !           294:                parseargs(ac, av);
        !           295:                i = preset_argc;
        !           296:                preset_argc = 0;
        !           297:        } while (i != 0);
        !           298:
        !           299:        /* set constants for username/uid display correctly */
        !           300:        if (!do_unames) {
        !           301:                uname_field = "   UID  ";
        !           302:                get_userid = itoa7;
        !           303:        }
        !           304:        /* initialize the kernel memory interface */
        !           305:        if (machine_init(&statics) == -1)
1.1       downsj    306:                exit(1);
1.20    ! deraadt   307:
        !           308:        /* determine sorting order index, if necessary */
        !           309:        if (order_name != NULL) {
        !           310:                if ((order_index = string_index(order_name,
        !           311:                    statics.order_names)) == -1) {
        !           312:                        char **pp;
        !           313:
        !           314:                        fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
        !           315:                            __progname, order_name);
        !           316:                        fprintf(stderr, "\tTry one of these:");
        !           317:                        pp = statics.order_names;
        !           318:                        while (*pp != NULL)
        !           319:                                fprintf(stderr, " %s", *pp++);
        !           320:                        fputc('\n', stderr);
        !           321:                        exit(1);
        !           322:                }
1.1       downsj    323:        }
                    324:
1.20    ! deraadt   325:        /* initialize termcap */
        !           326:        init_termcap(interactive);
        !           327:
        !           328:        /* get the string to use for the process area header */
        !           329:        header_text = format_header(uname_field);
        !           330:
        !           331:        /* initialize display interface */
        !           332:        if ((max_topn = display_init(&statics)) == -1) {
        !           333:                fprintf(stderr, "%s: can't allocate sufficient memory\n", __progname);
        !           334:                exit(4);
        !           335:        }
        !           336:        /* print warning if user requested more processes than we can display */
        !           337:        if (topn > max_topn) {
1.1       downsj    338:                fprintf(stderr,
1.20    ! deraadt   339:                    "%s: warning: this terminal can only display %d processes.\n",
        !           340:                    __progname, max_topn);
1.1       downsj    341:                warnings++;
1.20    ! deraadt   342:        }
        !           343:        /* adjust for topn == Infinity */
        !           344:        if (topn == Infinity) {
        !           345:                /*
        !           346:                 *  For smart terminals, infinity really means everything that can
        !           347:                 *  be displayed, or Largest.
        !           348:                 *  On dumb terminals, infinity means every process in the system!
        !           349:                 *  We only really want to do that if it was explicitly specified.
        !           350:                 *  This is always the case when "Default_TOPN != Infinity".  But if
        !           351:                 *  topn wasn't explicitly specified and we are on a dumb terminal
        !           352:                 *  and the default is Infinity, then (and only then) we use
        !           353:                 *  "Nominal_TOPN" instead.
        !           354:                 */
1.1       downsj    355: #if Default_TOPN == Infinity
1.20    ! deraadt   356:                topn = smart_terminal ? Largest :
        !           357:                    (topn_specified ? Largest : Nominal_TOPN);
        !           358: #else
        !           359:                topn = Largest;
1.1       downsj    360: #endif
                    361:        }
1.20    ! deraadt   362:        /* set header display accordingly */
        !           363:        display_header(topn > 0);
1.1       downsj    364:
1.20    ! deraadt   365:        /* determine interactive state */
        !           366:        if (interactive == Maybe)
        !           367:                interactive = smart_terminal;
1.1       downsj    368:
1.20    ! deraadt   369:        /* if # of displays not specified, fill it in */
        !           370:        if (displays == 0)
        !           371:                displays = smart_terminal ? Infinity : 1;
1.1       downsj    372:
                    373:        /*
1.20    ! deraadt   374:         * block interrupt signals while setting up the screen and the
        !           375:         * handlers
1.1       downsj    376:         */
1.20    ! deraadt   377:        sigemptyset(&mask);
        !           378:        sigaddset(&mask, SIGINT);
        !           379:        sigaddset(&mask, SIGQUIT);
        !           380:        sigaddset(&mask, SIGTSTP);
        !           381:        sigprocmask(SIG_BLOCK, &mask, &oldmask);
        !           382:        init_screen();
        !           383:        (void) signal(SIGINT, leave);
        !           384:        (void) signal(SIGQUIT, leave);
        !           385:        (void) signal(SIGTSTP, tstop);
1.1       downsj    386: #ifdef SIGWINCH
1.20    ! deraadt   387:        (void) signal(SIGWINCH, winch);
1.1       downsj    388: #endif
1.20    ! deraadt   389:        sigprocmask(SIG_SETMASK, &oldmask, NULL);
        !           390:        if (warnings) {
        !           391:                fputs("....", stderr);
        !           392:                fflush(stderr); /* why must I do this? */
        !           393:                sleep((unsigned) (3 * warnings));
        !           394:                fputc('\n', stderr);
        !           395:        }
1.7       deraadt   396: restart:
1.1       downsj    397:
1.20    ! deraadt   398:        /*
        !           399:         *  main loop -- repeat while display count is positive or while it
        !           400:         *              indicates infinity (by being -1)
        !           401:         */
        !           402:        while ((displays == -1) || (displays-- > 0)) {
        !           403:                /* get the current stats */
        !           404:                get_system_info(&system_info);
        !           405:
        !           406:                /* get the current set of processes */
        !           407:                processes = get_process_info(&system_info, &ps,
        !           408:                    proc_compares[order_index]);
        !           409:
        !           410:                /* display the load averages */
        !           411:                (*d_loadave)(system_info.last_pid, system_info.load_avg);
        !           412:
        !           413:                /* display the current time */
        !           414:                /* this method of getting the time SHOULD be fairly portable */
        !           415:                time(&curr_time);
        !           416:                i_timeofday(&curr_time);
        !           417:
        !           418:                /* display process state breakdown */
        !           419:                (*d_procstates)(system_info.p_total, system_info.procstates);
        !           420:
        !           421:                /* display the cpu state percentage breakdown */
        !           422:                if (dostates) { /* but not the first time */
        !           423:                        (*d_cpustates) (system_info.cpustates);
        !           424:                } else {
        !           425:                        /* we'll do it next time */
        !           426:                        if (smart_terminal)
        !           427:                                z_cpustates();
        !           428:                        else {
        !           429:                                if (putchar('\n') == EOF)
        !           430:                                        exit(1);
        !           431:                        }
        !           432:                        dostates = Yes;
        !           433:                }
1.1       downsj    434:
1.20    ! deraadt   435:                /* display memory stats */
        !           436:                (*d_memory) (system_info.memory);
1.1       downsj    437:
1.20    ! deraadt   438:                /* handle message area */
        !           439:                (*d_message) ();
1.1       downsj    440:
1.20    ! deraadt   441:                /* update the header area */
        !           442:                (*d_header) (header_text);
        !           443:
        !           444:                if (topn > 0) {
        !           445:                        /* determine number of processes to actually display */
        !           446:                        /*
        !           447:                         * this number will be the smallest of:  active
        !           448:                         * processes, number user requested, number current
        !           449:                         * screen accommodates
        !           450:                         */
        !           451:                        active_procs = system_info.p_active;
        !           452:                        if (active_procs > topn)
        !           453:                                active_procs = topn;
        !           454:                        if (active_procs > max_topn)
        !           455:                                active_procs = max_topn;
        !           456:                        /* now show the top "n" processes. */
        !           457:                        for (i = 0; i < active_procs; i++)
        !           458:                                (*d_process)(i, format_next_process(processes,
        !           459:                                    get_userid));
        !           460:                } else
        !           461:                        i = 0;
        !           462:
        !           463:                /* do end-screen processing */
        !           464:                u_endscreen(i);
        !           465:
        !           466:                /* now, flush the output buffer */
        !           467:                fflush(stdout);
        !           468:
        !           469:                /* only do the rest if we have more displays to show */
        !           470:                if (displays) {
        !           471:                        /* switch out for new display on smart terminals */
        !           472:                        if (smart_terminal) {
        !           473:                                if (overstrike) {
        !           474:                                        reset_display();
        !           475:                                } else {
        !           476:                                        d_loadave = u_loadave;
        !           477:                                        d_procstates = u_procstates;
        !           478:                                        d_cpustates = u_cpustates;
        !           479:                                        d_memory = u_memory;
        !           480:                                        d_message = u_message;
        !           481:                                        d_header = u_header;
        !           482:                                        d_process = u_process;
        !           483:                                }
        !           484:                        }
        !           485:                        no_command = Yes;
        !           486:                        if (!interactive) {
        !           487:                                /* set up alarm */
        !           488:                                (void) signal(SIGALRM, onalrm);
        !           489:                                (void) alarm((unsigned) delay);
        !           490:
        !           491:                                /* wait for the rest of it .... */
        !           492:                                pause();
        !           493:                        } else {
        !           494:                                while (no_command)
        !           495:                                        if (rundisplay())
        !           496:                                                goto restart;
        !           497:                        }
        !           498:                }
        !           499:        }
1.1       downsj    500:
1.20    ! deraadt   501:        quit(0);
        !           502:        /* NOTREACHED */
        !           503:        return (0);
        !           504: }
1.7       deraadt   505:
1.20    ! deraadt   506: int
        !           507: rundisplay(void)
        !           508: {
        !           509:        static char tempbuf1[50], tempbuf2[50];
        !           510:        struct timeval timeout;
        !           511:        fd_set readfds;
        !           512:        sigset_t mask;
        !           513:        char ch, *iptr;
        !           514:        int change, i;
        !           515:        static char command_chars[] = "\f qh?en#sdkriIuSo";
1.7       deraadt   516:
1.20    ! deraadt   517:        /*
        !           518:         * assume valid command unless told
        !           519:         * otherwise
        !           520:         */
        !           521:        no_command = No;
1.7       deraadt   522:
1.20    ! deraadt   523:        /*
        !           524:         * set up arguments for select with
        !           525:         * timeout
        !           526:         */
        !           527:        FD_ZERO(&readfds);
        !           528:        FD_SET(STDIN_FILENO, &readfds);
        !           529:        timeout.tv_sec = (long) delay;
        !           530:        timeout.tv_usec = (long) ((delay - timeout.tv_sec) * 1000000);
        !           531:
        !           532:        if (leaveflag) {
        !           533:                end_screen();
        !           534:                exit(0);
        !           535:        }
        !           536:        if (tstopflag) {
        !           537:                /* move to the lower left */
        !           538:                end_screen();
        !           539:                fflush(stdout);
        !           540:
        !           541:                /*
        !           542:                 * default the signal handler
        !           543:                 * action
        !           544:                 */
        !           545:                (void) signal(SIGTSTP, SIG_DFL);
        !           546:
        !           547:                /*
        !           548:                 * unblock the signal and
        !           549:                 * send ourselves one
        !           550:                 */
        !           551:                sigemptyset(&mask);
        !           552:                sigaddset(&mask, SIGTSTP);
        !           553:                sigprocmask(SIG_UNBLOCK, &mask, NULL);
        !           554:                (void) kill(0, SIGTSTP);
        !           555:
        !           556:                /* reset the signal handler */
        !           557:                (void) signal(SIGTSTP, tstop);
        !           558:
        !           559:                /* reinit screen */
        !           560:                reinit_screen();
        !           561:                reset_display();
        !           562:                tstopflag = 0;
        !           563:                return 1;
        !           564:        }
        !           565:        if (winchflag) {
        !           566:                /*
        !           567:                 * reascertain the screen
        !           568:                 * dimensions
        !           569:                 */
        !           570:                get_screensize();
        !           571:
        !           572:                /* tell display to resize */
        !           573:                max_topn = display_resize();
        !           574:
        !           575:                /* reset the signal handler */
        !           576:                (void) signal(SIGWINCH, winch);
        !           577:
        !           578:                reset_display();
        !           579:                winchflag = 0;
        !           580:                return 1;
        !           581:        }
        !           582:        /*
        !           583:         * wait for either input or the end
        !           584:         * of the delay period
        !           585:         */
        !           586:        if (select(STDIN_FILENO + 1, &readfds, (fd_set *) NULL,
        !           587:            (fd_set *) NULL, &timeout) > 0) {
        !           588:                char *errmsg;
        !           589:                int newval;
        !           590:
        !           591:                clear_message();
        !           592:
        !           593:                /*
        !           594:                 * now read it and convert to
        !           595:                 * command strchr
        !           596:                 */
        !           597:                (void) read(0, &ch, 1);
        !           598:                if ((iptr = strchr(command_chars, ch)) == NULL) {
1.1       downsj    599:                        /* illegal command */
                    600:                        new_message(MT_standout, " Command not understood");
1.9       deraadt   601:                        if (putchar('\r') == EOF)
1.20    ! deraadt   602:                                exit(1);
1.1       downsj    603:                        no_command = Yes;
1.20    ! deraadt   604:                        fflush(stdout);
        !           605:                        return (0);
        !           606:                }
        !           607:
        !           608:                change = iptr - command_chars;
        !           609:                if (overstrike && change > CMD_OSLIMIT) {
        !           610:                        /* error */
        !           611:                        new_message(MT_standout,
1.1       downsj    612:                            " Command cannot be handled by this terminal");
1.20    ! deraadt   613:                        if (putchar('\r') == EOF)
        !           614:                                exit(1);
        !           615:                        no_command = Yes;
        !           616:                        fflush(stdout);
        !           617:                        return (0);
        !           618:                }
        !           619:
        !           620:                switch (change) {
        !           621:                case CMD_redraw:        /* redraw screen */
        !           622:                        reset_display();
        !           623:                        break;
        !           624:
        !           625:                case CMD_update:        /* merely update display */
        !           626:                        /*
        !           627:                         * is the load average high?
        !           628:                         */
        !           629:                        if (system_info.load_avg[0] > LoadMax) {
        !           630:                                /* yes, go home for visual feedback */
        !           631:                                go_home();
        !           632:                                fflush(stdout);
1.1       downsj    633:                        }
1.20    ! deraadt   634:                        break;
        !           635:
        !           636:                case CMD_quit:  /* quit */
        !           637:                        quit(0);
        !           638:                        break;
        !           639:
        !           640:                case CMD_help1: /* help */
        !           641:                case CMD_help2:
        !           642:                        reset_display();
        !           643:                        clear();
        !           644:                        show_help();
        !           645:                        standout("Hit any key to continue: ");
        !           646:                        fflush(stdout);
        !           647:                        (void) read(0, &ch, 1);
        !           648:                        break;
        !           649:
        !           650:                case CMD_errors:        /* show errors */
        !           651:                        if (error_count() == 0) {
        !           652:                                new_message(MT_standout,
        !           653:                                    " Currently no errors to report.");
        !           654:                                if (putchar('\r') == EOF)
        !           655:                                        exit(1);
        !           656:                                no_command = Yes;
        !           657:                        } else {
1.1       downsj    658:                                reset_display();
                    659:                                clear();
1.20    ! deraadt   660:                                show_errors();
1.1       downsj    661:                                standout("Hit any key to continue: ");
                    662:                                fflush(stdout);
                    663:                                (void) read(0, &ch, 1);
1.20    ! deraadt   664:                        }
        !           665:                        break;
        !           666:
        !           667:                case CMD_number1:       /* new number */
        !           668:                case CMD_number2:
        !           669:                        new_message(MT_standout,
        !           670:                            "Number of processes to show: ");
        !           671:                        newval = readline(tempbuf1, 8, Yes);
        !           672:                        if (newval > -1) {
        !           673:                                if (newval > max_topn) {
1.1       downsj    674:                                        new_message(MT_standout | MT_delayed,
1.20    ! deraadt   675:                                            " This terminal can only "
        !           676:                                            "display %d processes.",
        !           677:                                            max_topn);
1.9       deraadt   678:                                        if (putchar('\r') == EOF)
1.20    ! deraadt   679:                                                exit(1);
        !           680:                                }
        !           681:                                if (newval == 0)
1.1       downsj    682:                                        display_header(No);
1.20    ! deraadt   683:                                else if (newval > topn && topn == 0) {
1.1       downsj    684:                                        /* redraw the header */
                    685:                                        display_header(Yes);
                    686:                                        d_header = i_header;
                    687:                                }
1.20    ! deraadt   688:                                topn = newval;
        !           689:                        }
        !           690:                        break;
        !           691:
        !           692:                case CMD_delay: /* new seconds delay */
        !           693:                        new_message(MT_standout, "Seconds to delay: ");
        !           694:                        if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) {
        !           695:                                char *endp;
        !           696:                                double newdelay = strtod(tempbuf2, &endp);
        !           697:
        !           698:                                if (newdelay >= 0 && newdelay < 1000000 &&
        !           699:                                    *endp == '\0')
1.16      hugh      700:                                        delay = newdelay;
1.20    ! deraadt   701:                        }
        !           702:                        clear_message();
        !           703:                        break;
        !           704:
        !           705:                case CMD_displays:      /* change display count */
        !           706:                        new_message(MT_standout,
        !           707:                            "Displays to show (currently %s): ",
        !           708:                            displays == -1 ? "infinite" :
        !           709:                            itoa(displays));
        !           710:                        if ((i = readline(tempbuf1, 10, Yes)) > 0)
        !           711:                                displays = i;
        !           712:                        else if (i == 0)
        !           713:                                quit(0);
        !           714:
        !           715:                        clear_message();
        !           716:                        break;
        !           717:
        !           718:                case CMD_kill:  /* kill program */
        !           719:                        new_message(0, "kill ");
        !           720:                        if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) {
        !           721:                                if ((errmsg = kill_procs(tempbuf2)) != NULL) {
1.4       millert   722:                                        new_message(MT_standout, "%s", errmsg);
1.9       deraadt   723:                                        if (putchar('\r') == EOF)
1.20    ! deraadt   724:                                                exit(1);
1.1       downsj    725:                                        no_command = Yes;
                    726:                                }
1.20    ! deraadt   727:                        } else
        !           728:                                clear_message();
        !           729:                        break;
        !           730:
        !           731:                case CMD_renice:        /* renice program */
        !           732:                        new_message(0, "renice ");
        !           733:                        if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) {
        !           734:                                if ((errmsg = renice_procs(tempbuf2)) != NULL) {
1.4       millert   735:                                        new_message(MT_standout, "%s", errmsg);
1.9       deraadt   736:                                        if (putchar('\r') == EOF)
1.20    ! deraadt   737:                                                exit(1);
1.1       downsj    738:                                        no_command = Yes;
                    739:                                }
1.20    ! deraadt   740:                        } else
        !           741:                                clear_message();
        !           742:                        break;
1.1       downsj    743:
1.20    ! deraadt   744:                case CMD_idletog:
        !           745:                case CMD_idletog2:
        !           746:                        ps.idle = !ps.idle;
        !           747:                        new_message(MT_standout | MT_delayed,
        !           748:                            " %sisplaying idle processes.",
        !           749:                            ps.idle ? "D" : "Not d");
        !           750:                        if (putchar('\r') == EOF)
        !           751:                                exit(1);
        !           752:                        break;
1.1       downsj    753:
1.20    ! deraadt   754:                case CMD_user:
        !           755:                        new_message(MT_standout,
        !           756:                            "Username to show: ");
        !           757:                        if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) {
        !           758:                                if (tempbuf2[0] == '+' &&
        !           759:                                    tempbuf2[1] == '\0') {
1.1       downsj    760:                                        ps.uid = -1;
1.20    ! deraadt   761:                                } else if ((i = userid(tempbuf2)) == -1) {
1.1       downsj    762:                                        new_message(MT_standout,
                    763:                                            " %s: unknown user", tempbuf2);
                    764:                                        no_command = Yes;
1.20    ! deraadt   765:                                } else
1.1       downsj    766:                                        ps.uid = i;
1.20    ! deraadt   767:                                if (putchar('\r') == EOF)
        !           768:                                        exit(1);
        !           769:                        } else
        !           770:                                clear_message();
        !           771:                        break;
1.12      fgsch     772:
1.20    ! deraadt   773:                case CMD_system:
        !           774:                        ps.system = !ps.system;
        !           775:                        new_message(MT_standout | MT_delayed,
        !           776:                            " %sisplaying system processes.",
        !           777:                            ps.system ? "D" : "Not d");
        !           778:                        break;
        !           779:
        !           780:                case CMD_order:
        !           781:                        new_message(MT_standout,
        !           782:                            "Order to sort: ");
        !           783:                        if (readline(tempbuf2,
        !           784:                            sizeof(tempbuf2), No) > 0) {
        !           785:                                if ((i = string_index(tempbuf2,
        !           786:                                    statics.order_names)) == -1) {
        !           787:                                        new_message(MT_standout,
        !           788:                                            " %s: unrecognized sorting order",
        !           789:                                            tempbuf2);
        !           790:                                        no_command = Yes;
        !           791:                                } else
1.1       downsj    792:                                        order_index = i;
1.9       deraadt   793:                                if (putchar('\r') == EOF)
1.20    ! deraadt   794:                                        exit(1);
        !           795:                        } else
        !           796:                                clear_message();
        !           797:                        break;
1.1       downsj    798:
1.20    ! deraadt   799:                default:
        !           800:                        new_message(MT_standout, " BAD CASE IN SWITCH!");
        !           801:                        if (putchar('\r') == EOF)
        !           802:                                exit(1);
1.1       downsj    803:                }
                    804:        }
                    805:
1.20    ! deraadt   806:        /* flush out stuff that may have been written */
        !           807:        fflush(stdout);
        !           808:        return 0;
1.1       downsj    809: }
                    810:
1.20    ! deraadt   811:
1.1       downsj    812: /*
                    813:  *  reset_display() - reset all the display routine pointers so that entire
                    814:  *     screen will get redrawn.
                    815:  */
1.19      pvalchev  816: static void
                    817: reset_display(void)
1.1       downsj    818: {
1.20    ! deraadt   819:        d_loadave = i_loadave;
        !           820:        d_procstates = i_procstates;
        !           821:        d_cpustates = i_cpustates;
        !           822:        d_memory = i_memory;
        !           823:        d_message = i_message;
        !           824:        d_header = i_header;
        !           825:        d_process = i_process;
1.1       downsj    826: }
                    827:
1.19      pvalchev  828: void
1.20    ! deraadt   829: leave(int signo)
1.1       downsj    830: {
1.20    ! deraadt   831:        leaveflag = 1;
1.1       downsj    832: }
                    833:
1.19      pvalchev  834: void
1.20    ! deraadt   835: tstop(int signo)
1.1       downsj    836: {
1.20    ! deraadt   837:        tstopflag = 1;
1.1       downsj    838: }
                    839:
                    840: #ifdef SIGWINCH
1.19      pvalchev  841: void
1.20    ! deraadt   842: winch(int signo)
1.1       downsj    843: {
1.20    ! deraadt   844:        winchflag = 1;
1.1       downsj    845: }
                    846: #endif
                    847:
1.19      pvalchev  848: void
1.20    ! deraadt   849: onalrm(int signo)
1.1       downsj    850: {
                    851: }
                    852:
1.19      pvalchev  853: void
1.20    ! deraadt   854: quit(int ret)
1.1       downsj    855: {
1.20    ! deraadt   856:        end_screen();
        !           857:        exit(ret);
1.1       downsj    858: }