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

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