source: trunk/third/top/top.c @ 16185

Revision 16185, 21.6 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16184, which included commits to RCS files with non-trunk default branches.
Line 
1char *copyright =
2    "Copyright (c) 1984 through 1996, William LeFebvre";
3
4/*
5 *  Top users/processes display for Unix
6 *  Version 3
7 *
8 *  This program may be freely redistributed,
9 *  but this entire comment MUST remain intact.
10 *
11 *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
12 *  Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University
13 *  Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory
14 *  Copyright (c) 1996, William LeFebvre, Group sys Consulting
15 */
16
17/*
18 *  See the file "Changes" for information on version-to-version changes.
19 */
20
21/*
22 *  This file contains "main" and other high-level routines.
23 */
24
25/*
26 * The following preprocessor variables, when defined, are used to
27 * distinguish between different Unix implementations:
28 *
29 *      SIGHOLD  - use SVR4 sighold function when defined
30 *      SIGRELSE - use SVR4 sigrelse function when defined
31 *      FD_SET   - macros FD_SET and FD_ZERO are used when defined
32 */
33
34#include "os.h"
35#include <signal.h>
36#include <setjmp.h>
37#include <ctype.h>
38#include <sys/time.h>
39
40/* includes specific to top */
41#include "display.h"            /* interface to display package */
42#include "screen.h"             /* interface to screen package */
43#include "top.h"
44#include "top.local.h"
45#include "boolean.h"
46#include "machine.h"
47#include "utils.h"
48
49/* Size of the stdio buffer given to stdout */
50#define Buffersize      2048
51
52/* The buffer that stdio will use */
53char stdoutbuf[Buffersize];
54
55/* build Signal masks */
56#define Smask(s)        (1 << ((s) - 1))
57
58/* for getopt: */
59extern int  optind;
60extern char *optarg;
61
62/* imported from screen.c */
63extern int overstrike;
64
65/* signal handling routines */
66sigret_t leave();
67sigret_t onalrm();
68sigret_t tstop();
69#ifdef SIGWINCH
70sigret_t winch();
71#endif
72
73/* internal routines */
74void quit();
75
76/* values which need to be accessed by signal handlers */
77static int max_topn;            /* maximum displayable processes */
78
79/* miscellaneous things */
80char *myname = "top";
81jmp_buf jmp_int;
82
83/* routines that don't return int */
84
85char *username();
86char *ctime();
87char *kill_procs();
88char *renice_procs();
89
90#ifdef ORDER
91extern int (*proc_compares[])();
92#else
93extern int proc_compare();
94#endif
95time_t time();
96
97caddr_t get_process_info();
98
99/* different routines for displaying the user's identification */
100/* (values assigned to get_userid) */
101char *username();
102char *itoa7();
103
104/* display routines that need to be predeclared */
105int i_loadave();
106int u_loadave();
107int i_procstates();
108int u_procstates();
109int i_cpustates();
110int u_cpustates();
111int i_memory();
112int u_memory();
113int i_message();
114int u_message();
115int i_header();
116int u_header();
117int i_process();
118int u_process();
119
120/* pointers to display routines */
121int (*d_loadave)() = i_loadave;
122int (*d_procstates)() = i_procstates;
123int (*d_cpustates)() = i_cpustates;
124int (*d_memory)() = i_memory;
125int (*d_message)() = i_message;
126int (*d_header)() = i_header;
127int (*d_process)() = i_process;
128
129
130main(argc, argv)
131
132int  argc;
133char *argv[];
134
135{
136    register int i;
137    register int active_procs;
138    register int change;
139
140    struct system_info system_info;
141    struct statics statics;
142    caddr_t processes;
143
144    static char tempbuf1[50];
145    static char tempbuf2[50];
146    int old_sigmask;            /* only used for BSD-style signals */
147    int topn = Default_TOPN;
148    int delay = Default_DELAY;
149    int displays = 0;           /* indicates unspecified */
150    time_t curr_time;
151    char *(*get_userid)() = username;
152    char *uname_field = "USERNAME";
153    char *header_text;
154    char *env_top;
155    char **preset_argv;
156    int  preset_argc = 0;
157    char **av;
158    int  ac;
159    char dostates = No;
160    char do_unames = Yes;
161    char interactive = Maybe;
162    char warnings = 0;
163#if Default_TOPN == Infinity
164    char topn_specified = No;
165#endif
166    char ch;
167    char *iptr;
168    char no_command = 1;
169    struct timeval timeout;
170    struct process_select ps;
171#ifdef ORDER
172    char *order_name = NULL;
173    int order_index = 0;
174#endif
175#ifndef FD_SET
176    /* FD_SET and friends are not present:  fake it */
177    typedef int fd_set;
178#define FD_ZERO(x)     (*(x) = 0)
179#define FD_SET(f, x)   (*(x) = 1<<f)
180#endif
181    fd_set readfds;
182
183#ifdef ORDER
184    static char command_chars[] = "\f qh?en#sdkriIuo";
185#else
186    static char command_chars[] = "\f qh?en#sdkriIu";
187#endif
188/* these defines enumerate the "strchr"s of the commands in command_chars */
189#define CMD_redraw      0
190#define CMD_update      1
191#define CMD_quit        2
192#define CMD_help1       3
193#define CMD_help2       4
194#define CMD_OSLIMIT     4    /* terminals with OS can only handle commands */
195#define CMD_errors      5    /* less than or equal to CMD_OSLIMIT          */
196#define CMD_number1     6
197#define CMD_number2     7
198#define CMD_delay       8
199#define CMD_displays    9
200#define CMD_kill        10
201#define CMD_renice      11
202#define CMD_idletog     12
203#define CMD_idletog2    13
204#define CMD_user        14
205#ifdef ORDER
206#define CMD_order       15
207#endif
208
209    /* set the buffer for stdout */
210#ifdef DEBUG
211    extern FILE *debug;
212    debug = fopen("debug.run", "w");
213    setbuffer(stdout, NULL, 0);
214#else
215    setbuffer(stdout, stdoutbuf, Buffersize);
216#endif
217
218    /* get our name */
219    if (argc > 0)
220    {
221        if ((myname = strrchr(argv[0], '/')) == 0)
222        {
223            myname = argv[0];
224        }
225        else
226        {
227            myname++;
228        }
229    }
230
231    /* initialize some selection options */
232    ps.idle    = Yes;
233    ps.system  = No;
234    ps.uid     = -1;
235    ps.command = NULL;
236
237    /* get preset options from the environment */
238    if ((env_top = getenv("TOP")) != NULL)
239    {
240        av = preset_argv = argparse(env_top, &preset_argc);
241        ac = preset_argc;
242
243        /* set the dummy argument to an explanatory message, in case
244           getopt encounters a bad argument */
245        preset_argv[0] = "while processing environment";
246    }
247
248    /* process options */
249    do {
250        /* if we're done doing the presets, then process the real arguments */
251        if (preset_argc == 0)
252        {
253            ac = argc;
254            av = argv;
255
256            /* this should keep getopt happy... */
257            optind = 1;
258        }
259
260        while ((i = getopt(ac, av, "SIbinquvs:d:U:o:")) != EOF)
261        {
262            switch(i)
263            {
264              case 'v':                 /* show version number */
265                fprintf(stderr, "%s: version %s\n",
266                        myname, version_string());
267                exit(1);
268                break;
269
270              case 'u':                 /* toggle uid/username display */
271                do_unames = !do_unames;
272                break;
273
274              case 'U':                 /* display only username's processes */
275                if ((ps.uid = userid(optarg)) == -1)
276                {
277                    fprintf(stderr, "%s: unknown user\n", optarg);
278                    exit(1);
279                }
280                break;
281
282              case 'S':                 /* show system processes */
283                ps.system = !ps.system;
284                break;
285
286              case 'I':                   /* show idle processes */
287                ps.idle = !ps.idle;
288                break;
289
290              case 'i':                 /* go interactive regardless */
291                interactive = Yes;
292                break;
293
294              case 'n':                 /* batch, or non-interactive */
295              case 'b':
296                interactive = No;
297                break;
298
299              case 'd':                 /* number of displays to show */
300                if ((i = atoiwi(optarg)) == Invalid || i == 0)
301                {
302                    fprintf(stderr,
303                        "%s: warning: display count should be positive -- option ignored\n",
304                        myname);
305                    warnings++;
306                }
307                else
308                {
309                    displays = i;
310                }
311                break;
312
313              case 's':
314                if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
315                {
316                    fprintf(stderr,
317                        "%s: warning: seconds delay should be positive -- using default\n",
318                        myname);
319                    delay = Default_DELAY;
320                    warnings++;
321                }
322                break;
323
324              case 'q':         /* be quick about it */
325                /* only allow this if user is really root */
326                if (getuid() == 0)
327                {
328                    /* be very un-nice! */
329                    (void) nice(-20);
330                }
331                else
332                {
333                    fprintf(stderr,
334                        "%s: warning: `-q' option can only be used by root\n",
335                        myname);
336                    warnings++;
337                }
338                break;
339
340              case 'o':         /* select sort order */
341#ifdef ORDER
342                order_name = optarg;
343#else
344                fprintf(stderr,
345                        "%s: this platform does not support arbitrary ordering.  Sorry.\n",
346                        myname);
347                warnings++;
348#endif
349                break;
350
351              default:
352                fprintf(stderr, "\
353Top version %s\n\
354Usage: %s [-ISbinqu] [-d x] [-s x] [-o field] [-U username] [number]\n",
355                        version_string(), myname);
356                exit(1);
357            }
358        }
359
360        /* get count of top processes to display (if any) */
361        if (optind < ac)
362        {
363            if ((topn = atoiwi(av[optind])) == Invalid)
364            {
365                fprintf(stderr,
366                        "%s: warning: process display count should be non-negative -- using default\n",
367                        myname);
368                warnings++;
369            }
370#if Default_TOPN == Infinity
371            else
372            {
373                topn_specified = Yes;
374            }
375#endif
376        }
377
378        /* tricky:  remember old value of preset_argc & set preset_argc = 0 */
379        i = preset_argc;
380        preset_argc = 0;
381
382    /* repeat only if we really did the preset arguments */
383    } while (i != 0);
384
385    /* set constants for username/uid display correctly */
386    if (!do_unames)
387    {
388        uname_field = "   UID  ";
389        get_userid = itoa7;
390    }
391
392    /* initialize the kernel memory interface */
393    if (machine_init(&statics) == -1)
394    {
395        exit(1);
396    }
397
398#ifdef ORDER
399    /* determine sorting order index, if necessary */
400    if (order_name != NULL)
401    {
402        if ((order_index = string_index(order_name, statics.order_names)) == -1)
403        {
404            char **pp;
405
406            fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
407                    myname, order_name);
408            fprintf(stderr, "\tTry one of these:");
409            pp = statics.order_names;
410            while (*pp != NULL)
411            {
412                fprintf(stderr, " %s", *pp++);
413            }
414            fputc('\n', stderr);
415            exit(1);
416        }
417    }
418#endif
419
420#ifdef no_initialization_needed
421    /* initialize the hashing stuff */
422    if (do_unames)
423    {
424        init_hash();
425    }
426#endif
427
428    /* initialize termcap */
429    init_termcap(interactive);
430
431    /* get the string to use for the process area header */
432    header_text = format_header(uname_field);
433
434    /* initialize display interface */
435    if ((max_topn = display_init(&statics)) == -1)
436    {
437        fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);
438        exit(4);
439    }
440   
441    /* print warning if user requested more processes than we can display */
442    if (topn > max_topn)
443    {
444        fprintf(stderr,
445                "%s: warning: this terminal can only display %d processes.\n",
446                myname, max_topn);
447        warnings++;
448    }
449
450    /* adjust for topn == Infinity */
451    if (topn == Infinity)
452    {
453        /*
454         *  For smart terminals, infinity really means everything that can
455         *  be displayed, or Largest.
456         *  On dumb terminals, infinity means every process in the system!
457         *  We only really want to do that if it was explicitly specified.
458         *  This is always the case when "Default_TOPN != Infinity".  But if
459         *  topn wasn't explicitly specified and we are on a dumb terminal
460         *  and the default is Infinity, then (and only then) we use
461         *  "Nominal_TOPN" instead.
462         */
463#if Default_TOPN == Infinity
464        topn = smart_terminal ? Largest :
465                    (topn_specified ? Largest : Nominal_TOPN);
466#else
467        topn = Largest;
468#endif
469    }
470
471    /* set header display accordingly */
472    display_header(topn > 0);
473
474    /* determine interactive state */
475    if (interactive == Maybe)
476    {
477        interactive = smart_terminal;
478    }
479
480    /* if # of displays not specified, fill it in */
481    if (displays == 0)
482    {
483        displays = smart_terminal ? Infinity : 1;
484    }
485
486    /* hold interrupt signals while setting up the screen and the handlers */
487#ifdef SIGHOLD
488    sighold(SIGINT);
489    sighold(SIGQUIT);
490    sighold(SIGTSTP);
491#else
492    old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));
493#endif
494    init_screen();
495    (void) signal(SIGINT, leave);
496    (void) signal(SIGQUIT, leave);
497    (void) signal(SIGTSTP, tstop);
498#ifdef SIGWINCH
499    (void) signal(SIGWINCH, winch);
500#endif
501#ifdef SIGRELSE
502    sigrelse(SIGINT);
503    sigrelse(SIGQUIT);
504    sigrelse(SIGTSTP);
505#else
506    (void) sigsetmask(old_sigmask);
507#endif
508    if (warnings)
509    {
510        fputs("....", stderr);
511        fflush(stderr);                 /* why must I do this? */
512        sleep((unsigned)(3 * warnings));
513        fputc('\n', stderr);
514    }
515
516    /* setup the jump buffer for stops */
517    if (setjmp(jmp_int) != 0)
518    {
519        /* control ends up here after an interrupt */
520        reset_display();
521    }
522
523    /*
524     *  main loop -- repeat while display count is positive or while it
525     *          indicates infinity (by being -1)
526     */
527
528    while ((displays == -1) || (displays-- > 0))
529    {
530        /* get the current stats */
531        get_system_info(&system_info);
532
533        /* get the current set of processes */
534        processes =
535                get_process_info(&system_info,
536                                 &ps,
537#ifdef ORDER
538                                 proc_compares[order_index]);
539#else
540                                 proc_compare);
541#endif
542
543        /* display the load averages */
544        (*d_loadave)(system_info.last_pid,
545                     system_info.load_avg);
546
547        /* display the current time */
548        /* this method of getting the time SHOULD be fairly portable */
549        time(&curr_time);
550        i_timeofday(&curr_time);
551
552        /* display process state breakdown */
553        (*d_procstates)(system_info.p_total,
554                        system_info.procstates);
555
556        /* display the cpu state percentage breakdown */
557        if (dostates)   /* but not the first time */
558        {
559            (*d_cpustates)(system_info.cpustates);
560        }
561        else
562        {
563            /* we'll do it next time */
564            if (smart_terminal)
565            {
566                z_cpustates();
567            }
568            else
569            {
570                putchar('\n');
571            }
572            dostates = Yes;
573        }
574
575        /* display memory stats */
576        (*d_memory)(system_info.memory);
577
578        /* handle message area */
579        (*d_message)();
580
581        /* update the header area */
582        (*d_header)(header_text);
583   
584        if (topn > 0)
585        {
586            /* determine number of processes to actually display */
587            /* this number will be the smallest of:  active processes,
588               number user requested, number current screen accomodates */
589            active_procs = system_info.P_ACTIVE;
590            if (active_procs > topn)
591            {
592                active_procs = topn;
593            }
594            if (active_procs > max_topn)
595            {
596                active_procs = max_topn;
597            }
598
599            /* now show the top "n" processes. */
600            for (i = 0; i < active_procs; i++)
601            {
602                (*d_process)(i, format_next_process(processes, get_userid));
603            }
604        }
605        else
606        {
607            i = 0;
608        }
609
610        /* do end-screen processing */
611        u_endscreen(i);
612
613        /* now, flush the output buffer */
614        if (fflush(stdout) != 0)
615        {
616            new_message(MT_standout, " Write error on stdout");
617            putchar('\r');
618            quit(1);
619            /*NOTREACHED*/
620        }
621
622        /* only do the rest if we have more displays to show */
623        if (displays)
624        {
625            /* switch out for new display on smart terminals */
626            if (smart_terminal)
627            {
628                if (overstrike)
629                {
630                    reset_display();
631                }
632                else
633                {
634                    d_loadave = u_loadave;
635                    d_procstates = u_procstates;
636                    d_cpustates = u_cpustates;
637                    d_memory = u_memory;
638                    d_message = u_message;
639                    d_header = u_header;
640                    d_process = u_process;
641                }
642            }
643   
644            no_command = Yes;
645            if (!interactive)
646            {
647                /* set up alarm */
648                (void) signal(SIGALRM, onalrm);
649                (void) alarm((unsigned)delay);
650   
651                /* wait for the rest of it .... */
652                pause();
653            }
654            else while (no_command)
655            {
656                /* assume valid command unless told otherwise */
657                no_command = No;
658
659                /* set up arguments for select with timeout */
660                FD_ZERO(&readfds);
661                FD_SET(0, &readfds);            /* for standard input */
662                timeout.tv_sec  = delay;
663                timeout.tv_usec = 0;
664
665                /* wait for either input or the end of the delay period */
666                if (select(32, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timeout) > 0)
667                {
668                    int newval;
669                    char *errmsg;
670   
671                    /* something to read -- clear the message area first */
672                    clear_message();
673
674                    /* now read it and convert to command strchr */
675                    /* (use "change" as a temporary to hold strchr) */
676                    if (read(0, &ch, 1) != 1)
677                    {
678                        /* read error: either 0 or -1 */
679                        new_message(MT_standout, " Read error on stdin");
680                        putchar('\r');
681                        quit(1);
682                        /*NOTREACHED*/
683                    }
684                    if ((iptr = strchr(command_chars, ch)) == NULL)
685                    {
686                        /* illegal command */
687                        new_message(MT_standout, " Command not understood");
688                        putchar('\r');
689                        no_command = Yes;
690                    }
691                    else
692                    {
693                        change = iptr - command_chars;
694                        if (overstrike && change > CMD_OSLIMIT)
695                        {
696                            /* error */
697                            new_message(MT_standout,
698                            " Command cannot be handled by this terminal");
699                            putchar('\r');
700                            no_command = Yes;
701                        }
702                        else switch(change)
703                        {
704                            case CMD_redraw:    /* redraw screen */
705                                reset_display();
706                                break;
707   
708                            case CMD_update:    /* merely update display */
709                                /* is the load average high? */
710                                if (system_info.load_avg[0] > LoadMax)
711                                {
712                                    /* yes, go home for visual feedback */
713                                    go_home();
714                                    fflush(stdout);
715                                }
716                                break;
717           
718                            case CMD_quit:      /* quit */
719                                quit(0);
720                                /*NOTREACHED*/
721                                break;
722           
723                            case CMD_help1:     /* help */
724                            case CMD_help2:
725                                reset_display();
726                                clear();
727                                show_help();
728                                standout("Hit any key to continue: ");
729                                fflush(stdout);
730                                (void) read(0, &ch, 1);
731                                break;
732       
733                            case CMD_errors:    /* show errors */
734                                if (error_count() == 0)
735                                {
736                                    new_message(MT_standout,
737                                        " Currently no errors to report.");
738                                    putchar('\r');
739                                    no_command = Yes;
740                                }
741                                else
742                                {
743                                    reset_display();
744                                    clear();
745                                    show_errors();
746                                    standout("Hit any key to continue: ");
747                                    fflush(stdout);
748                                    (void) read(0, &ch, 1);
749                                }
750                                break;
751       
752                            case CMD_number1:   /* new number */
753                            case CMD_number2:
754                                new_message(MT_standout,
755                                    "Number of processes to show: ");
756                                newval = readline(tempbuf1, 8, Yes);
757                                if (newval > -1)
758                                {
759                                    if (newval > max_topn)
760                                    {
761                                        new_message(MT_standout | MT_delayed,
762                                          " This terminal can only display %d processes.",
763                                          max_topn);
764                                        putchar('\r');
765                                    }
766
767                                    if (newval == 0)
768                                    {
769                                        /* inhibit the header */
770                                        display_header(No);
771                                    }
772                                    else if (newval > topn && topn == 0)
773                                    {
774                                        /* redraw the header */
775                                        display_header(Yes);
776                                        d_header = i_header;
777                                    }
778                                    topn = newval;
779                                }
780                                break;
781           
782                            case CMD_delay:     /* new seconds delay */
783                                new_message(MT_standout, "Seconds to delay: ");
784                                if ((i = readline(tempbuf1, 8, Yes)) > -1)
785                                {
786                                    if ((delay = i) == 0 && getuid() != 0)
787                                    {
788                                        delay = 1;
789                                    }
790                                }
791                                clear_message();
792                                break;
793       
794                            case CMD_displays:  /* change display count */
795                                new_message(MT_standout,
796                                        "Displays to show (currently %s): ",
797                                        displays == -1 ? "infinite" :
798                                                         itoa(displays));
799                                if ((i = readline(tempbuf1, 10, Yes)) > 0)
800                                {
801                                    displays = i;
802                                }
803                                else if (i == 0)
804                                {
805                                    quit(0);
806                                }
807                                clear_message();
808                                break;
809   
810                            case CMD_kill:      /* kill program */
811                                new_message(0, "kill ");
812                                if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
813                                {
814                                    if ((errmsg = kill_procs(tempbuf2)) != NULL)
815                                    {
816                                        new_message(MT_standout, errmsg);
817                                        putchar('\r');
818                                        no_command = Yes;
819                                    }
820                                }
821                                else
822                                {
823                                    clear_message();
824                                }
825                                break;
826           
827                            case CMD_renice:    /* renice program */
828                                new_message(0, "renice ");
829                                if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
830                                {
831                                    if ((errmsg = renice_procs(tempbuf2)) != NULL)
832                                    {
833                                        new_message(MT_standout, errmsg);
834                                        putchar('\r');
835                                        no_command = Yes;
836                                    }
837                                }
838                                else
839                                {
840                                    clear_message();
841                                }
842                                break;
843
844                            case CMD_idletog:
845                            case CMD_idletog2:
846                                ps.idle = !ps.idle;
847                                new_message(MT_standout | MT_delayed,
848                                    " %sisplaying idle processes.",
849                                    ps.idle ? "D" : "Not d");
850                                putchar('\r');
851                                break;
852
853                            case CMD_user:
854                                new_message(MT_standout,
855                                    "Username to show: ");
856                                if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
857                                {
858                                    if (tempbuf2[0] == '+' &&
859                                        tempbuf2[1] == '\0')
860                                    {
861                                        ps.uid = -1;
862                                    }
863                                    else if ((i = userid(tempbuf2)) == -1)
864                                    {
865                                        new_message(MT_standout,
866                                            " %s: unknown user", tempbuf2);
867                                        no_command = Yes;
868                                    }
869                                    else
870                                    {
871                                        ps.uid = i;
872                                    }
873                                    putchar('\r');
874                                }
875                                else
876                                {
877                                    clear_message();
878                                }
879                                break;
880           
881#ifdef ORDER
882                            case CMD_order:
883                                new_message(MT_standout,
884                                    "Order to sort: ");
885                                if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
886                                {
887                                  if ((i = string_index(tempbuf2, statics.order_names)) == -1)
888                                        {
889                                          new_message(MT_standout,
890                                              " %s: unrecognized sorting order", tempbuf2);
891                                          no_command = Yes;
892                                    }
893                                    else
894                                    {
895                                        order_index = i;
896                                    }
897                                    putchar('\r');
898                                }
899                                else
900                                {
901                                    clear_message();
902                                }
903                                break;
904#endif
905           
906                            default:
907                                new_message(MT_standout, " BAD CASE IN SWITCH!");
908                                putchar('\r');
909                        }
910                    }
911
912                    /* flush out stuff that may have been written */
913                    fflush(stdout);
914                }
915            }
916        }
917    }
918
919#ifdef DEBUG
920    fclose(debug);
921#endif
922    quit(0);
923    /*NOTREACHED*/
924}
925
926/*
927 *  reset_display() - reset all the display routine pointers so that entire
928 *      screen will get redrawn.
929 */
930
931reset_display()
932
933{
934    d_loadave    = i_loadave;
935    d_procstates = i_procstates;
936    d_cpustates  = i_cpustates;
937    d_memory     = i_memory;
938    d_message    = i_message;
939    d_header     = i_header;
940    d_process    = i_process;
941}
942
943/*
944 *  signal handlers
945 */
946
947sigret_t leave()        /* exit under normal conditions -- INT handler */
948
949{
950    end_screen();
951    exit(0);
952}
953
954sigret_t tstop(i)       /* SIGTSTP handler */
955
956int i;
957
958{
959    /* move to the lower left */
960    end_screen();
961    fflush(stdout);
962
963    /* default the signal handler action */
964    (void) signal(SIGTSTP, SIG_DFL);
965
966    /* unblock the signal and send ourselves one */
967#ifdef SIGRELSE
968    sigrelse(SIGTSTP);
969#else
970    (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
971#endif
972    (void) kill(0, SIGTSTP);
973
974    /* reset the signal handler */
975    (void) signal(SIGTSTP, tstop);
976
977    /* reinit screen */
978    reinit_screen();
979
980    /* jump to appropriate place */
981    longjmp(jmp_int, 1);
982
983    /*NOTREACHED*/
984}
985
986#ifdef SIGWINCH
987sigret_t winch(i)               /* SIGWINCH handler */
988
989int i;
990
991{
992    /* reascertain the screen dimensions */
993    get_screensize();
994
995    /* tell display to resize */
996    max_topn = display_resize();
997
998    /* reset the signal handler */
999    (void) signal(SIGWINCH, winch);
1000
1001    /* jump to appropriate place */
1002    longjmp(jmp_int, 1);
1003}
1004#endif
1005
1006void quit(status)               /* exit under duress */
1007
1008int status;
1009
1010{
1011    end_screen();
1012    exit(status);
1013    /*NOTREACHED*/
1014}
1015
1016sigret_t onalrm()       /* SIGALRM handler */
1017
1018{
1019    /* this is only used in batch mode to break out of the pause() */
1020    /* return; */
1021}
1022
Note: See TracBrowser for help on using the repository browser.