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