home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / top-0.5-MI / top.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-29  |  19.4 KB  |  918 lines

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