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

Diff for /src/usr.bin/top/top.c between version 1.19 and 1.20

version 1.19, 2003/06/12 22:30:23 version 1.20, 2003/06/13 21:52:25
Line 1 
Line 1 
 /*      $OpenBSD$       */  /*      $OpenBSD$       */
   
 const char copyright[] = "Copyright (c) 1984 through 1996, William LeFebvre";  
   
 /*  /*
  *  Top users/processes display for Unix   *  Top users/processes display for Unix
  *  Version 3   *  Version 3
Line 30 
Line 28 
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */   */
   
 /*  const char      copyright[] = "Copyright (c) 1984 through 1996, William LeFebvre";
  *  See the file "Changes" for information on version-to-version changes.  
  */  
   
 /*  
  *  This file contains "main" and other high-level routines.  
  */  
   
 /*  
  * The following preprocessor variables, when defined, are used to  
  * distinguish between different Unix implementations:  
  *  
  *      FD_SET   - macros FD_SET and FD_ZERO are used when defined  
  */  
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <stdio.h>  #include <stdio.h>
 #include <ctype.h>  #include <ctype.h>
Line 66 
Line 51 
 #include "utils.h"  #include "utils.h"
   
 /* Size of the stdio buffer given to stdout */  /* Size of the stdio buffer given to stdout */
 #define Buffersize      2048  #define BUFFERSIZE      2048
   
 /* The buffer that stdio will use */  /* The buffer that stdio will use */
 char stdoutbuf[Buffersize];  char            stdoutbuf[BUFFERSIZE];
   
 /* imported from screen.c */  extern int      overstrike;
 extern int overstrike;  
   
 /* signal handling routines */  /* signal handling routines */
 static void leave(int);  static void     leave(int);
 static void onalrm(int);  static void     onalrm(int);
 static void tstop(int);  static void     tstop(int);
 #ifdef SIGWINCH  #ifdef SIGWINCH
 static void winch(int);  static void     winch(int);
 #endif  #endif
   
 volatile sig_atomic_t leaveflag;  volatile sig_atomic_t leaveflag;
 volatile sig_atomic_t tstopflag;  volatile sig_atomic_t tstopflag;
 volatile sig_atomic_t winchflag;  volatile sig_atomic_t winchflag;
   
 static void reset_display(void);  static void     reset_display(void);
   int             rundisplay(void);
   
 /* values which need to be accessed by signal handlers */  /* values which need to be accessed by signal handlers */
 static int max_topn;            /* maximum displayable processes */  static int      max_topn;       /* maximum displayable processes */
   
 /* miscellaneous things */  /* miscellaneous things */
 char *myname = "top";  jmp_buf         jmp_int;
 jmp_buf jmp_int;  
   
 /* routines that don't return int */  /* routines that don't return int */
   
 #ifdef ORDER  extern char *__progname;
 extern int (*proc_compares[])();  
 #else  
 extern int proc_compare();  
 #endif  
 time_t time();  
   
 caddr_t get_process_info();  extern int      (*proc_compares[])(const void *, const void *);
   int order_index;
   
 /* pointers to display routines */  /* pointers to display routines */
 void (*d_loadave)() = i_loadave;  void            (*d_loadave) () = i_loadave;
 void (*d_procstates)() = i_procstates;  void            (*d_procstates) () = i_procstates;
 void (*d_cpustates)() = i_cpustates;  void            (*d_cpustates) () = i_cpustates;
 void (*d_memory)() = i_memory;  void            (*d_memory) () = i_memory;
 void (*d_message)() = i_message;  void            (*d_message) () = i_message;
 void (*d_header)() = i_header;  void            (*d_header) () = i_header;
 void (*d_process)() = i_process;  void            (*d_process) () = i_process;
   
   int displays = 0;       /* indicates unspecified */
   char do_unames = Yes;
   struct process_select ps;
   char dostates = No;
   char interactive = Maybe;
   char warnings = 0;
   double delay = Default_DELAY;
   char *order_name = NULL;
   int topn = Default_TOPN;
   int no_command = 1;
   
 int  
 main(int argc, char *argv[])  
 {  
     int i;  
     int active_procs;  
     int change;  
   
     struct system_info system_info;  
     struct statics statics;  
     caddr_t processes;  
   
     static char tempbuf1[50];  
     static char tempbuf2[50];  
     sigset_t mask, oldmask;  
     int topn = Default_TOPN;  
     double delay = Default_DELAY;  
     int displays = 0;           /* indicates unspecified */  
     time_t curr_time;  
     char *(*get_userid)() = username;  
     char *uname_field = "USERNAME";  
     char *header_text;  
     char *env_top;  
     char **preset_argv;  
     int  preset_argc = 0;  
     char **av;  
     int  ac;  
     char dostates = No;  
     char do_unames = Yes;  
     char interactive = Maybe;  
     char warnings = 0;  
 #if Default_TOPN == Infinity  #if Default_TOPN == Infinity
     char topn_specified = No;  char topn_specified = No;
 #endif  #endif
     char ch;  
     char *iptr;  
     char no_command = 1;  
     struct timeval timeout;  
     struct process_select ps;  
 #ifdef ORDER  
     char *order_name = NULL;  
     int order_index = 0;  
 #endif  
 #ifndef FD_SET  
     /* FD_SET and friends are not present:  fake it */  
     typedef int fd_set;  
 #define FD_ZERO(x)     (*(x) = 0)  
 #define FD_SET(f, x)   (*(x) = f)  
 #endif  
     fd_set readfds;  
   
 #ifdef ORDER  /*
     static char command_chars[] = "\f qh?en#sdkriIuSo";   * these defines enumerate the "strchr"s of the commands in
 #else   * command_chars
     static char command_chars[] = "\f qh?en#sdkriIuS";   */
 #endif  
 /* these defines enumerate the "strchr"s of the commands in command_chars */  
 #define CMD_redraw      0  #define CMD_redraw      0
 #define CMD_update      1  #define CMD_update      1
 #define CMD_quit        2  #define CMD_quit        2
 #define CMD_help1       3  #define CMD_help1       3
 #define CMD_help2       4  #define CMD_help2       4
 #define CMD_OSLIMIT     4    /* terminals with OS can only handle commands */  #define CMD_OSLIMIT     4       /* terminals with OS can only handle commands */
 #define CMD_errors      5    /* less than or equal to CMD_OSLIMIT          */  #define CMD_errors      5       /* less than or equal to CMD_OSLIMIT       */
 #define CMD_number1     6  #define CMD_number1     6
 #define CMD_number2     7  #define CMD_number2     7
 #define CMD_delay       8  #define CMD_delay       8
Line 189 
Line 131 
 #define CMD_idletog2    13  #define CMD_idletog2    13
 #define CMD_user        14  #define CMD_user        14
 #define CMD_system      15  #define CMD_system      15
 #ifdef ORDER  
 #define CMD_order       16  #define CMD_order       16
 #endif  
   
     /* set the buffer for stdout */  void
 #ifdef DEBUG  usage(void)
     setbuffer(stdout, NULL, 0);  {
 #else          fprintf(stderr,
     setbuffer(stdout, stdoutbuf, Buffersize);              "Top version %s\n"
 #endif              "Usage: %s [-ISbinqu] [-d x] [-s x] [-o field] [-U username] [number]\n",
               version_string(), __progname);
   }
   
     /* get our name */  void
     if (argc > 0)  parseargs(int ac, char **av)
     {  {
         if ((myname = strrchr(argv[0], '/')) == 0)          char *endp;
         {          int i;
             myname = argv[0];  
         }  
         else  
         {  
             myname++;  
         }  
     }  
   
     /* initialize some selection options */          while ((i = getopt(ac, av, "SIbinqus:d:U:o:")) != -1) {
     ps.idle    = Yes;                  switch (i) {
     ps.system  = No;                  case 'u':       /* toggle uid/username display */
     ps.uid     = -1;                          do_unames = !do_unames;
     ps.command = NULL;                          break;
   
     /* get preset options from the environment */                  case 'U':       /* display only username's processes */
     if ((env_top = getenv("TOP")) != NULL)                          if ((ps.uid = userid(optarg)) == -1) {
     {                                  fprintf(stderr, "%s: unknown user\n", optarg);
         av = preset_argv = argparse(env_top, &preset_argc);                                  exit(1);
         ac = preset_argc;                          }
                           break;
   
         /* set the dummy argument to an explanatory message, in case                  case 'S':       /* show system processes */
            getopt encounters a bad argument */                          ps.system = !ps.system;
         preset_argv[0] = "while processing environment";                          break;
     }  
   
     /* process options */                  case 'I':       /* show idle processes */
     do {                          ps.idle = !ps.idle;
         /* if we're done doing the presets, then process the real arguments */                          break;
         if (preset_argc == 0)  
         {  
             ac = argc;  
             av = argv;  
   
             /* this should keep getopt happy... */                  case 'i':       /* go interactive regardless */
             optind = 1;                          interactive = Yes;
         }                          break;
   
         while ((i = getopt(ac, av, "SIbinqus:d:U:o:")) != -1)                  case 'n':       /* batch, or non-interactive */
         {                  case 'b':
             switch(i)                          interactive = No;
             {                          break;
               case 'u':                 /* toggle uid/username display */  
                 do_unames = !do_unames;  
                 break;  
   
               case 'U':                 /* display only username's processes */                  case 'd':       /* number of displays to show */
                 if ((ps.uid = userid(optarg)) == -1)                          if ((i = atoiwi(optarg)) != Invalid && i != 0) {
                 {                                  displays = i;
                     fprintf(stderr, "%s: unknown user\n", optarg);                                  break;
                     exit(1);                          }
                 }                          fprintf(stderr,
                 break;                              "%s: warning: display count should be positive "
                               "-- option ignored\n",
                               __progname);
                           warnings++;
                           break;
   
               case 'S':                 /* show system processes */                  case 's':
                 ps.system = !ps.system;                          delay = strtod(optarg, &endp);
                 break;  
   
               case 'I':                   /* show idle processes */                          if (delay > 0 && delay <= 1000000 && *endp == '\0')
                 ps.idle = !ps.idle;                                  break;
                 break;  
   
               case 'i':                 /* go interactive regardless */                          fprintf(stderr,
                 interactive = Yes;                              "%s: warning: delay should be a non-negative number"
                 break;                              " -- using default\n",
                               __progname);
                           delay = Default_DELAY;
                           warnings++;
                           break;
   
               case 'n':                 /* batch, or non-interactive */                  case 'q':       /* be quick about it */
               case 'b':                          /* only allow this if user is really root */
                 interactive = No;                          if (getuid() == 0) {
                 break;                                  /* be very un-nice! */
                                   (void) nice(-20);
                                   break;
                           }
                           fprintf(stderr,
                               "%s: warning: `-q' option can only be used by root\n",
                               __progname);
                           warnings++;
                           break;
   
               case 'd':                 /* number of displays to show */                  case 'o':       /* select sort order */
                 if ((i = atoiwi(optarg)) == Invalid || i == 0)                          order_name = optarg;
                 {                          break;
                     fprintf(stderr,  
                         "%s: warning: display count should be positive -- option ignored\n",  
                         myname);  
                     warnings++;  
                 }  
                 else  
                 {  
                     displays = i;  
                 }  
                 break;  
   
               case 's':                  default:
                 {                          usage();
                   char *endp;                          exit(1);
   
                   delay = strtod(optarg, &endp);  
   
                   if (delay < 0 || delay >= 1000000 || *endp != '\0')  
                   {  
                     fprintf(stderr,  
                         "%s: warning: delay should be a non-negative number -- using default\n",  
                         myname);  
                     delay = Default_DELAY;  
                     warnings++;  
                   }  
                 }                  }
                 break;  
   
               case 'q':         /* be quick about it */  
                 /* only allow this if user is really root */  
                 if (getuid() == 0)  
                 {  
                     /* be very un-nice! */  
                     (void) nice(-20);  
                 }  
                 else  
                 {  
                     fprintf(stderr,  
                         "%s: warning: `-q' option can only be used by root\n",  
                         myname);  
                     warnings++;  
                 }  
                 break;  
   
               case 'o':         /* select sort order */  
 #ifdef ORDER  
                 order_name = optarg;  
 #else  
                 fprintf(stderr,  
                         "%s: this platform does not support arbitrary ordering.  Sorry.\n",  
                         myname);  
                 warnings++;  
 #endif  
                 break;  
   
               default:  
                 fprintf(stderr, "\  
 Top version %s\n\  
 Usage: %s [-ISbinqu] [-d x] [-s x] [-o field] [-U username] [number]\n",  
                         version_string(), myname);  
                 exit(1);  
             }  
         }          }
   
         /* get count of top processes to display (if any) */          /* get count of top processes to display (if any) */
         if (optind < ac)          if (optind < ac) {
         {                  if ((topn = atoiwi(av[optind])) == Invalid) {
             if ((topn = atoiwi(av[optind])) == Invalid)                          fprintf(stderr,
             {                              "%s: warning: process display count should "
                 fprintf(stderr,                              "be non-negative -- using default\n",
                         "%s: warning: process display count should be non-negative -- using default\n",                              __progname);
                         myname);                          warnings++;
                 warnings++;                  }
             }  
 #if Default_TOPN == Infinity  #if Default_TOPN == Infinity
             else                  else
             {                          topn_specified = Yes;
                 topn_specified = Yes;  
             }  
 #endif  #endif
         }          }
   }
   
         /* tricky:  remember old value of preset_argc & set preset_argc = 0 */  struct system_info system_info;
         i = preset_argc;  struct statics  statics;
         preset_argc = 0;  
   
     /* repeat only if we really did the preset arguments */  int
     } while (i != 0);  main(int argc, char *argv[])
   {
           char *uname_field = "USERNAME", *header_text, *env_top;
           char *(*get_userid)() = username, **preset_argv, **av;
           int preset_argc = 0, ac, active_procs, i;
           sigset_t mask, oldmask;
           time_t curr_time;
           caddr_t processes;
   
     /* set constants for username/uid display correctly */          /* set the buffer for stdout */
     if (!do_unames)  #ifdef DEBUG
     {          setbuffer(stdout, NULL, 0);
         uname_field = "   UID  ";  #else
         get_userid = itoa7;          setbuffer(stdout, stdoutbuf, sizeof stdoutbuf);
     }  #endif
   
     /* initialize the kernel memory interface */          /* initialize some selection options */
     if (machine_init(&statics) == -1)          ps.idle = Yes;
     {          ps.system = No;
         exit(1);          ps.uid = -1;
     }          ps.command = NULL;
   
 #ifdef ORDER          /* get preset options from the environment */
     /* determine sorting order index, if necessary */          if ((env_top = getenv("TOP")) != NULL) {
     if (order_name != NULL)                  av = preset_argv = argparse(env_top, &preset_argc);
     {                  ac = preset_argc;
         if ((order_index = string_index(order_name, statics.order_names)) == -1)  
         {  
             char **pp;  
   
             fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",                  /*
                     myname, order_name);                   * set the dummy argument to an explanatory message, in case
             fprintf(stderr, "\tTry one of these:");                   * getopt encounters a bad argument
             pp = statics.order_names;                   */
             while (*pp != NULL)                  preset_argv[0] = "while processing environment";
             {  
                 fprintf(stderr, " %s", *pp++);  
             }  
             fputc('\n', stderr);  
             exit(1);  
         }          }
     }          /* process options */
 #endif          do {
                   /*
                    * if we're done doing the presets, then process the real
                    * arguments
                    */
                   if (preset_argc == 0) {
                           ac = argc;
                           av = argv;
                           optind = 1;
                   }
                   parseargs(ac, av);
                   i = preset_argc;
                   preset_argc = 0;
           } while (i != 0);
   
 #ifdef no_initialization_needed          /* set constants for username/uid display correctly */
     /* initialize the hashing stuff */          if (!do_unames) {
     if (do_unames)                  uname_field = "   UID  ";
     {                  get_userid = itoa7;
         init_hash();          }
     }          /* initialize the kernel memory interface */
 #endif          if (machine_init(&statics) == -1)
                   exit(1);
   
     /* initialize termcap */          /* determine sorting order index, if necessary */
     init_termcap(interactive);          if (order_name != NULL) {
                   if ((order_index = string_index(order_name,
                       statics.order_names)) == -1) {
                           char **pp;
   
     /* get the string to use for the process area header */                          fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
     header_text = format_header(uname_field);                              __progname, order_name);
                           fprintf(stderr, "\tTry one of these:");
                           pp = statics.order_names;
                           while (*pp != NULL)
                                   fprintf(stderr, " %s", *pp++);
                           fputc('\n', stderr);
                           exit(1);
                   }
           }
   
     /* initialize display interface */          /* initialize termcap */
     if ((max_topn = display_init(&statics)) == -1)          init_termcap(interactive);
     {  
         fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);  
         exit(4);  
     }  
   
     /* print warning if user requested more processes than we can display */  
     if (topn > max_topn)  
     {  
         fprintf(stderr,  
                 "%s: warning: this terminal can only display %d processes.\n",  
                 myname, max_topn);  
         warnings++;  
     }  
   
     /* adjust for topn == Infinity */          /* get the string to use for the process area header */
     if (topn == Infinity)          header_text = format_header(uname_field);
     {  
         /*          /* initialize display interface */
          *  For smart terminals, infinity really means everything that can          if ((max_topn = display_init(&statics)) == -1) {
          *  be displayed, or Largest.                  fprintf(stderr, "%s: can't allocate sufficient memory\n", __progname);
          *  On dumb terminals, infinity means every process in the system!                  exit(4);
          *  We only really want to do that if it was explicitly specified.          }
          *  This is always the case when "Default_TOPN != Infinity".  But if          /* print warning if user requested more processes than we can display */
          *  topn wasn't explicitly specified and we are on a dumb terminal          if (topn > max_topn) {
          *  and the default is Infinity, then (and only then) we use                  fprintf(stderr,
          *  "Nominal_TOPN" instead.                      "%s: warning: this terminal can only display %d processes.\n",
          */                      __progname, max_topn);
                   warnings++;
           }
           /* adjust for topn == Infinity */
           if (topn == Infinity) {
                   /*
                    *  For smart terminals, infinity really means everything that can
                    *  be displayed, or Largest.
                    *  On dumb terminals, infinity means every process in the system!
                    *  We only really want to do that if it was explicitly specified.
                    *  This is always the case when "Default_TOPN != Infinity".  But if
                    *  topn wasn't explicitly specified and we are on a dumb terminal
                    *  and the default is Infinity, then (and only then) we use
                    *  "Nominal_TOPN" instead.
                    */
 #if Default_TOPN == Infinity  #if Default_TOPN == Infinity
         topn = smart_terminal ? Largest :                  topn = smart_terminal ? Largest :
                     (topn_specified ? Largest : Nominal_TOPN);                      (topn_specified ? Largest : Nominal_TOPN);
 #else  #else
         topn = Largest;                  topn = Largest;
 #endif  #endif
     }          }
           /* set header display accordingly */
           display_header(topn > 0);
   
     /* set header display accordingly */          /* determine interactive state */
     display_header(topn > 0);          if (interactive == Maybe)
                   interactive = smart_terminal;
   
     /* determine interactive state */          /* if # of displays not specified, fill it in */
     if (interactive == Maybe)          if (displays == 0)
     {                  displays = smart_terminal ? Infinity : 1;
         interactive = smart_terminal;  
     }  
   
     /* if # of displays not specified, fill it in */          /*
     if (displays == 0)           * block interrupt signals while setting up the screen and the
     {           * handlers
         displays = smart_terminal ? Infinity : 1;           */
     }          sigemptyset(&mask);
           sigaddset(&mask, SIGINT);
     /* block interrupt signals while setting up the screen and the handlers */          sigaddset(&mask, SIGQUIT);
     sigemptyset(&mask);          sigaddset(&mask, SIGTSTP);
     sigaddset(&mask, SIGINT);          sigprocmask(SIG_BLOCK, &mask, &oldmask);
     sigaddset(&mask, SIGQUIT);          init_screen();
     sigaddset(&mask, SIGTSTP);          (void) signal(SIGINT, leave);
     sigprocmask(SIG_BLOCK, &mask, &oldmask);          (void) signal(SIGQUIT, leave);
     init_screen();          (void) signal(SIGTSTP, tstop);
     (void) signal(SIGINT, leave);  
     (void) signal(SIGQUIT, leave);  
     (void) signal(SIGTSTP, tstop);  
 #ifdef SIGWINCH  #ifdef SIGWINCH
     (void) signal(SIGWINCH, winch);          (void) signal(SIGWINCH, winch);
 #endif  #endif
     sigprocmask(SIG_SETMASK, &oldmask, NULL);          sigprocmask(SIG_SETMASK, &oldmask, NULL);
     if (warnings)          if (warnings) {
     {                  fputs("....", stderr);
         fputs("....", stderr);                  fflush(stderr); /* why must I do this? */
         fflush(stderr);                 /* why must I do this? */                  sleep((unsigned) (3 * warnings));
         sleep((unsigned)(3 * warnings));                  fputc('\n', stderr);
         fputc('\n', stderr);          }
     }  
   
 restart:  restart:
   
     /*          /*
      *  main loop -- repeat while display count is positive or while it           *  main loop -- repeat while display count is positive or while it
      *          indicates infinity (by being -1)           *              indicates infinity (by being -1)
      */           */
           while ((displays == -1) || (displays-- > 0)) {
                   /* get the current stats */
                   get_system_info(&system_info);
   
     while ((displays == -1) || (displays-- > 0))                  /* get the current set of processes */
     {                  processes = get_process_info(&system_info, &ps,
         /* get the current stats */                      proc_compares[order_index]);
         get_system_info(&system_info);  
   
         /* get the current set of processes */                  /* display the load averages */
         processes =                  (*d_loadave)(system_info.last_pid, system_info.load_avg);
                 get_process_info(&system_info,  
                                  &ps,  
 #ifdef ORDER  
                                  proc_compares[order_index]);  
 #else  
                                  proc_compare);  
 #endif  
   
         /* display the load averages */                  /* display the current time */
         (*d_loadave)(system_info.last_pid,                  /* this method of getting the time SHOULD be fairly portable */
                      system_info.load_avg);                  time(&curr_time);
                   i_timeofday(&curr_time);
   
         /* display the current time */                  /* display process state breakdown */
         /* this method of getting the time SHOULD be fairly portable */                  (*d_procstates)(system_info.p_total, system_info.procstates);
         time(&curr_time);  
         i_timeofday(&curr_time);  
   
         /* display process state breakdown */                  /* display the cpu state percentage breakdown */
         (*d_procstates)(system_info.p_total,                  if (dostates) { /* but not the first time */
                         system_info.procstates);                          (*d_cpustates) (system_info.cpustates);
                   } else {
                           /* we'll do it next time */
                           if (smart_terminal)
                                   z_cpustates();
                           else {
                                   if (putchar('\n') == EOF)
                                           exit(1);
                           }
                           dostates = Yes;
                   }
   
         /* display the cpu state percentage breakdown */                  /* display memory stats */
         if (dostates)   /* but not the first time */                  (*d_memory) (system_info.memory);
         {  
             (*d_cpustates)(system_info.cpustates);  
         }  
         else  
         {  
             /* we'll do it next time */  
             if (smart_terminal)  
             {  
                 z_cpustates();  
             }  
             else  
             {  
                 if (putchar('\n') == EOF)  
                     exit(1);  
             }  
             dostates = Yes;  
         }  
   
         /* display memory stats */                  /* handle message area */
         (*d_memory)(system_info.memory);                  (*d_message) ();
   
         /* handle message area */                  /* update the header area */
         (*d_message)();                  (*d_header) (header_text);
   
         /* update the header area */                  if (topn > 0) {
         (*d_header)(header_text);                          /* determine number of processes to actually display */
                           /*
         if (topn > 0)                           * this number will be the smallest of:  active
         {                           * processes, number user requested, number current
             /* determine number of processes to actually display */                           * screen accommodates
             /* this number will be the smallest of:  active processes,                           */
                number user requested, number current screen accommodates */                          active_procs = system_info.p_active;
             active_procs = system_info.p_active;                          if (active_procs > topn)
             if (active_procs > topn)                                  active_procs = topn;
             {                          if (active_procs > max_topn)
                 active_procs = topn;                                  active_procs = max_topn;
             }                          /* now show the top "n" processes. */
             if (active_procs > max_topn)                          for (i = 0; i < active_procs; i++)
             {                                  (*d_process)(i, format_next_process(processes,
                 active_procs = max_topn;                                      get_userid));
             }                  } else
                           i = 0;
   
             /* now show the top "n" processes. */                  /* do end-screen processing */
             for (i = 0; i < active_procs; i++)                  u_endscreen(i);
             {  
                 (*d_process)(i, format_next_process(processes, get_userid));  
             }  
         }  
         else  
         {  
             i = 0;  
         }  
   
         /* do end-screen processing */                  /* now, flush the output buffer */
         u_endscreen(i);                  fflush(stdout);
   
         /* now, flush the output buffer */                  /* only do the rest if we have more displays to show */
         fflush(stdout);                  if (displays) {
                           /* switch out for new display on smart terminals */
                           if (smart_terminal) {
                                   if (overstrike) {
                                           reset_display();
                                   } else {
                                           d_loadave = u_loadave;
                                           d_procstates = u_procstates;
                                           d_cpustates = u_cpustates;
                                           d_memory = u_memory;
                                           d_message = u_message;
                                           d_header = u_header;
                                           d_process = u_process;
                                   }
                           }
                           no_command = Yes;
                           if (!interactive) {
                                   /* set up alarm */
                                   (void) signal(SIGALRM, onalrm);
                                   (void) alarm((unsigned) delay);
   
         /* only do the rest if we have more displays to show */                                  /* wait for the rest of it .... */
         if (displays)                                  pause();
         {                          } else {
             /* switch out for new display on smart terminals */                                  while (no_command)
             if (smart_terminal)                                          if (rundisplay())
             {                                                  goto restart;
                 if (overstrike)                          }
                 {  
                     reset_display();  
                 }                  }
                 else          }
                 {  
                     d_loadave = u_loadave;  
                     d_procstates = u_procstates;  
                     d_cpustates = u_cpustates;  
                     d_memory = u_memory;  
                     d_message = u_message;  
                     d_header = u_header;  
                     d_process = u_process;  
                 }  
             }  
   
             no_command = Yes;  
             if (!interactive)  
             {  
                 /* set up alarm */  
                 (void) signal(SIGALRM, onalrm);  
                 (void) alarm((unsigned)delay);  
   
                 /* wait for the rest of it .... */  
                 pause();  
             }  
             else while (no_command)  
             {  
                 /* assume valid command unless told otherwise */  
                 no_command = No;  
   
                 /* set up arguments for select with timeout */          quit(0);
                 FD_ZERO(&readfds);          /* NOTREACHED */
                 FD_SET(STDIN_FILENO, &readfds); /* for standard input */          return (0);
                 timeout.tv_sec  = (long)delay;  }
                 timeout.tv_usec = (long)((delay - timeout.tv_sec) * 1000000);  
   
                 if (leaveflag) {  int
                     end_screen();  rundisplay(void)
                     exit(0);  {
                 }          static char tempbuf1[50], tempbuf2[50];
           struct timeval timeout;
           fd_set readfds;
           sigset_t mask;
           char ch, *iptr;
           int change, i;
           static char command_chars[] = "\f qh?en#sdkriIuSo";
   
                 if (tstopflag) {          /*
                     /* move to the lower left */           * assume valid command unless told
                     end_screen();           * otherwise
                     fflush(stdout);           */
           no_command = No;
   
                     /* default the signal handler action */          /*
                     (void) signal(SIGTSTP, SIG_DFL);           * set up arguments for select with
            * timeout
            */
           FD_ZERO(&readfds);
           FD_SET(STDIN_FILENO, &readfds);
           timeout.tv_sec = (long) delay;
           timeout.tv_usec = (long) ((delay - timeout.tv_sec) * 1000000);
   
                     /* unblock the signal and send ourselves one */          if (leaveflag) {
                     sigemptyset(&mask);                  end_screen();
                     sigaddset(&mask, SIGTSTP);                  exit(0);
                     sigprocmask(SIG_UNBLOCK, &mask, NULL);          }
                     (void) kill(0, SIGTSTP);          if (tstopflag) {
                   /* move to the lower left */
                   end_screen();
                   fflush(stdout);
   
                     /* reset the signal handler */                  /*
                     (void) signal(SIGTSTP, tstop);                   * default the signal handler
                    * action
                    */
                   (void) signal(SIGTSTP, SIG_DFL);
   
                     /* reinit screen */                  /*
                     reinit_screen();                   * unblock the signal and
                     reset_display();                   * send ourselves one
                     tstopflag = 0;                   */
                     goto restart;                  sigemptyset(&mask);
                 }                  sigaddset(&mask, SIGTSTP);
                   sigprocmask(SIG_UNBLOCK, &mask, NULL);
                   (void) kill(0, SIGTSTP);
   
                 if (winchflag) {                  /* reset the signal handler */
                     /* reascertain the screen dimensions */                  (void) signal(SIGTSTP, tstop);
                     get_screensize();  
   
                     /* tell display to resize */                  /* reinit screen */
                     max_topn = display_resize();                  reinit_screen();
                   reset_display();
                   tstopflag = 0;
                   return 1;
           }
           if (winchflag) {
                   /*
                    * reascertain the screen
                    * dimensions
                    */
                   get_screensize();
   
                     /* reset the signal handler */                  /* tell display to resize */
                     (void) signal(SIGWINCH, winch);                  max_topn = display_resize();
   
                     reset_display();                  /* reset the signal handler */
                     winchflag = 0;                  (void) signal(SIGWINCH, winch);
                     goto restart;  
                 }  
   
                 /* wait for either input or the end of the delay period */                  reset_display();
                 if (select(STDIN_FILENO + 1, &readfds, (fd_set *)NULL,                  winchflag = 0;
                   (fd_set *)NULL, &timeout) > 0)                  return 1;
                 {          }
                     int newval;          /*
                     char *errmsg;           * wait for either input or the end
            * of the delay period
                     /* something to read -- clear the message area first */           */
                     clear_message();          if (select(STDIN_FILENO + 1, &readfds, (fd_set *) NULL,
               (fd_set *) NULL, &timeout) > 0) {
                   char *errmsg;
                   int newval;
   
                     /* now read it and convert to command strchr */                  clear_message();
                     /* (use "change" as a temporary to hold strchr) */  
                     (void) read(0, &ch, 1);                  /*
                     if ((iptr = strchr(command_chars, ch)) == NULL)                   * now read it and convert to
                     {                   * command strchr
                    */
                   (void) read(0, &ch, 1);
                   if ((iptr = strchr(command_chars, ch)) == NULL) {
                         /* illegal command */                          /* illegal command */
                         new_message(MT_standout, " Command not understood");                          new_message(MT_standout, " Command not understood");
                         if (putchar('\r') == EOF)                          if (putchar('\r') == EOF)
                             exit(1);                                  exit(1);
                         no_command = Yes;                          no_command = Yes;
                     }                          fflush(stdout);
                     else                          return (0);
                     {                  }
                         change = iptr - command_chars;  
                         if (overstrike && change > CMD_OSLIMIT)                  change = iptr - command_chars;
                         {                  if (overstrike && change > CMD_OSLIMIT) {
                             /* error */                          /* error */
                             new_message(MT_standout,                          new_message(MT_standout,
                             " Command cannot be handled by this terminal");                              " Command cannot be handled by this terminal");
                             if (putchar('\r') == EOF)                          if (putchar('\r') == EOF)
                                 exit(1);                                  exit(1);
                             no_command = Yes;                          no_command = Yes;
                           fflush(stdout);
                           return (0);
                   }
   
                   switch (change) {
                   case CMD_redraw:        /* redraw screen */
                           reset_display();
                           break;
   
                   case CMD_update:        /* merely update display */
                           /*
                            * is the load average high?
                            */
                           if (system_info.load_avg[0] > LoadMax) {
                                   /* yes, go home for visual feedback */
                                   go_home();
                                   fflush(stdout);
                         }                          }
                         else switch(change)                          break;
                         {  
                             case CMD_redraw:    /* redraw screen */                  case CMD_quit:  /* quit */
                           quit(0);
                           break;
   
                   case CMD_help1: /* help */
                   case CMD_help2:
                           reset_display();
                           clear();
                           show_help();
                           standout("Hit any key to continue: ");
                           fflush(stdout);
                           (void) read(0, &ch, 1);
                           break;
   
                   case CMD_errors:        /* show errors */
                           if (error_count() == 0) {
                                   new_message(MT_standout,
                                       " Currently no errors to report.");
                                   if (putchar('\r') == EOF)
                                           exit(1);
                                   no_command = Yes;
                           } else {
                                 reset_display();                                  reset_display();
                                 break;  
   
                             case CMD_update:    /* merely update display */  
                                 /* is the load average high? */  
                                 if (system_info.load_avg[0] > LoadMax)  
                                 {  
                                     /* yes, go home for visual feedback */  
                                     go_home();  
                                     fflush(stdout);  
                                 }  
                                 break;  
   
                             case CMD_quit:      /* quit */  
                                 quit(0);  
                                 /*NOTREACHED*/  
                                 break;  
   
                             case CMD_help1:     /* help */  
                             case CMD_help2:  
                                 reset_display();  
                                 clear();                                  clear();
                                 show_help();                                  show_errors();
                                 standout("Hit any key to continue: ");                                  standout("Hit any key to continue: ");
                                 fflush(stdout);                                  fflush(stdout);
                                 (void) read(0, &ch, 1);                                  (void) read(0, &ch, 1);
                                 break;                          }
                           break;
                             case CMD_errors:    /* show errors */  
                                 if (error_count() == 0)                  case CMD_number1:       /* new number */
                                 {                  case CMD_number2:
                                     new_message(MT_standout,                          new_message(MT_standout,
                                         " Currently no errors to report.");                              "Number of processes to show: ");
                                     if (putchar('\r') == EOF)                          newval = readline(tempbuf1, 8, Yes);
                                         exit(1);                          if (newval > -1) {
                                     no_command = Yes;                                  if (newval > max_topn) {
                                 }  
                                 else  
                                 {  
                                     reset_display();  
                                     clear();  
                                     show_errors();  
                                     standout("Hit any key to continue: ");  
                                     fflush(stdout);  
                                     (void) read(0, &ch, 1);  
                                 }  
                                 break;  
   
                             case CMD_number1:   /* new number */  
                             case CMD_number2:  
                                 new_message(MT_standout,  
                                     "Number of processes to show: ");  
                                 newval = readline(tempbuf1, 8, Yes);  
                                 if (newval > -1)  
                                 {  
                                     if (newval > max_topn)  
                                     {  
                                         new_message(MT_standout | MT_delayed,                                          new_message(MT_standout | MT_delayed,
                                           " This terminal can only display %d processes.",                                              " This terminal can only "
                                           max_topn);                                              "display %d processes.",
                                               max_topn);
                                         if (putchar('\r') == EOF)                                          if (putchar('\r') == EOF)
                                             exit(1);                                                  exit(1);
                                     }                                  }
                                   if (newval == 0)
                                     if (newval == 0)  
                                     {  
                                         /* inhibit the header */  
                                         display_header(No);                                          display_header(No);
                                     }                                  else if (newval > topn && topn == 0) {
                                     else if (newval > topn && topn == 0)  
                                     {  
                                         /* redraw the header */                                          /* redraw the header */
                                         display_header(Yes);                                          display_header(Yes);
                                         d_header = i_header;                                          d_header = i_header;
                                     }  
                                     topn = newval;  
                                 }                                  }
                                 break;                                  topn = newval;
                           }
                             case CMD_delay:     /* new seconds delay */                          break;
                                 new_message(MT_standout, "Seconds to delay: ");  
                                 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)                  case CMD_delay: /* new seconds delay */
                                 {                          new_message(MT_standout, "Seconds to delay: ");
                                     char *endp;                          if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) {
                                     double newdelay = strtod(tempbuf2, &endp);                                  char *endp;
                                     if (newdelay >= 0 && newdelay < 1000000 && *endp == '\0')                                  double newdelay = strtod(tempbuf2, &endp);
                                     {  
                                   if (newdelay >= 0 && newdelay < 1000000 &&
                                       *endp == '\0')
                                         delay = newdelay;                                          delay = newdelay;
                                     }                          }
                                 }                          clear_message();
                                 clear_message();                          break;
                                 break;  
                   case CMD_displays:      /* change display count */
                             case CMD_displays:  /* change display count */                          new_message(MT_standout,
                                 new_message(MT_standout,                              "Displays to show (currently %s): ",
                                         "Displays to show (currently %s): ",                              displays == -1 ? "infinite" :
                                         displays == -1 ? "infinite" :                              itoa(displays));
                                                          itoa(displays));                          if ((i = readline(tempbuf1, 10, Yes)) > 0)
                                 if ((i = readline(tempbuf1, 10, Yes)) > 0)                                  displays = i;
                                 {                          else if (i == 0)
                                     displays = i;                                  quit(0);
                                 }  
                                 else if (i == 0)                          clear_message();
                                 {                          break;
                                     quit(0);  
                                 }                  case CMD_kill:  /* kill program */
                                 clear_message();                          new_message(0, "kill ");
                                 break;                          if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) {
                                   if ((errmsg = kill_procs(tempbuf2)) != NULL) {
                             case CMD_kill:      /* kill program */  
                                 new_message(0, "kill ");  
                                 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)  
                                 {  
                                     if ((errmsg = kill_procs(tempbuf2)) != NULL)  
                                     {  
                                         new_message(MT_standout, "%s", errmsg);                                          new_message(MT_standout, "%s", errmsg);
                                         if (putchar('\r') == EOF)                                          if (putchar('\r') == EOF)
                                             exit(1);                                                  exit(1);
                                         no_command = Yes;                                          no_command = Yes;
                                     }  
                                 }                                  }
                                 else                          } else
                                 {                                  clear_message();
                                     clear_message();                          break;
                                 }  
                                 break;                  case CMD_renice:        /* renice program */
                           new_message(0, "renice ");
                             case CMD_renice:    /* renice program */                          if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) {
                                 new_message(0, "renice ");                                  if ((errmsg = renice_procs(tempbuf2)) != NULL) {
                                 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)  
                                 {  
                                     if ((errmsg = renice_procs(tempbuf2)) != NULL)  
                                     {  
                                         new_message(MT_standout, "%s", errmsg);                                          new_message(MT_standout, "%s", errmsg);
                                         if (putchar('\r') == EOF)                                          if (putchar('\r') == EOF)
                                             exit(1);                                                  exit(1);
                                         no_command = Yes;                                          no_command = Yes;
                                     }  
                                 }                                  }
                                 else                          } else
                                 {                                  clear_message();
                                     clear_message();                          break;
                                 }  
                                 break;  
   
                             case CMD_idletog:                  case CMD_idletog:
                             case CMD_idletog2:                  case CMD_idletog2:
                                 ps.idle = !ps.idle;                          ps.idle = !ps.idle;
                                 new_message(MT_standout | MT_delayed,                          new_message(MT_standout | MT_delayed,
                                     " %sisplaying idle processes.",                              " %sisplaying idle processes.",
                                     ps.idle ? "D" : "Not d");                              ps.idle ? "D" : "Not d");
                                 if (putchar('\r') == EOF)                          if (putchar('\r') == EOF)
                                     exit(1);                                  exit(1);
                                 break;                          break;
   
                             case CMD_user:                  case CMD_user:
                                 new_message(MT_standout,                          new_message(MT_standout,
                                     "Username to show: ");                              "Username to show: ");
                                 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)                          if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) {
                                 {                                  if (tempbuf2[0] == '+' &&
                                     if (tempbuf2[0] == '+' &&                                      tempbuf2[1] == '\0') {
                                         tempbuf2[1] == '\0')  
                                     {  
                                         ps.uid = -1;                                          ps.uid = -1;
                                     }                                  } else if ((i = userid(tempbuf2)) == -1) {
                                     else if ((i = userid(tempbuf2)) == -1)  
                                     {  
                                         new_message(MT_standout,                                          new_message(MT_standout,
                                             " %s: unknown user", tempbuf2);                                              " %s: unknown user", tempbuf2);
                                         no_command = Yes;                                          no_command = Yes;
                                     }                                  } else
                                     else  
                                     {  
                                         ps.uid = i;                                          ps.uid = i;
                                     }                                  if (putchar('\r') == EOF)
                                     if (putchar('\r') == EOF)                                          exit(1);
                                         exit(1);                          } else
                                 }                                  clear_message();
                                 else                          break;
                                 {  
                                     clear_message();  
                                 }  
                                 break;  
   
                             case CMD_system:                  case CMD_system:
                                 ps.system = !ps.system;                          ps.system = !ps.system;
                                 new_message(MT_standout | MT_delayed,                          new_message(MT_standout | MT_delayed,
                                     " %sisplaying system processes.",                              " %sisplaying system processes.",
                                     ps.system ? "D" : "Not d");                              ps.system ? "D" : "Not d");
                                 break;                          break;
   
 #ifdef ORDER                  case CMD_order:
                             case CMD_order:                          new_message(MT_standout,
                                 new_message(MT_standout,                              "Order to sort: ");
                                     "Order to sort: ");                          if (readline(tempbuf2,
                                 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)                              sizeof(tempbuf2), No) > 0) {
                                 {                                  if ((i = string_index(tempbuf2,
                                   if ((i = string_index(tempbuf2, statics.order_names)) == -1)                                      statics.order_names)) == -1) {
                                         {                                          new_message(MT_standout,
                                           new_message(MT_standout,                                              " %s: unrecognized sorting order",
                                               " %s: unrecognized sorting order", tempbuf2);                                              tempbuf2);
                                           no_command = Yes;                                          no_command = Yes;
                                     }                                  } else
                                     else  
                                     {  
                                         order_index = i;                                          order_index = i;
                                     }  
                                     if (putchar('\r') == EOF)  
                                         exit(1);  
                                 }  
                                 else  
                                 {  
                                     clear_message();  
                                 }  
                                 break;  
 #endif  
   
                             default:  
                                 new_message(MT_standout, " BAD CASE IN SWITCH!");  
                                 if (putchar('\r') == EOF)                                  if (putchar('\r') == EOF)
                                     exit(1);                                          exit(1);
                         }                          } else
                     }                                  clear_message();
                           break;
   
                     /* flush out stuff that may have been written */                  default:
                     fflush(stdout);                          new_message(MT_standout, " BAD CASE IN SWITCH!");
                           if (putchar('\r') == EOF)
                                   exit(1);
                 }                  }
             }  
         }          }
     }  
   
     quit(0);          /* flush out stuff that may have been written */
     /*NOTREACHED*/          fflush(stdout);
     return(0);          return 0;
 }  }
   
   
 /*  /*
  *  reset_display() - reset all the display routine pointers so that entire   *  reset_display() - reset all the display routine pointers so that entire
  *      screen will get redrawn.   *      screen will get redrawn.
  */   */
   
 static void  static void
 reset_display(void)  reset_display(void)
 {  {
     d_loadave    = i_loadave;          d_loadave = i_loadave;
     d_procstates = i_procstates;          d_procstates = i_procstates;
     d_cpustates  = i_cpustates;          d_cpustates = i_cpustates;
     d_memory     = i_memory;          d_memory = i_memory;
     d_message    = i_message;          d_message = i_message;
     d_header     = i_header;          d_header = i_header;
     d_process    = i_process;          d_process = i_process;
 }  }
   
 /*  
  *  signal handlers  
  */  
   
 void  void
 leave(int unused)       /* exit under normal conditions -- INT handler */  leave(int signo)
 {  {
     leaveflag = 1;          leaveflag = 1;
 }  }
   
 void  void
 tstop(int i)    /* SIGTSTP handler */  tstop(int signo)
 {  {
     tstopflag = 1;          tstopflag = 1;
 }  }
   
 #ifdef SIGWINCH  #ifdef SIGWINCH
 void  void
 winch(int i)            /* SIGWINCH handler */  winch(int signo)
 {  {
     winchflag = 1;          winchflag = 1;
 }  }
 #endif  #endif
   
 void  void
 quit(int status)                /* exit under duress */  onalrm(int signo)
 {  {
     end_screen();  
     exit(status);  
     /*NOTREACHED*/  
 }  }
   
 void  void
 onalrm(int unused)      /* SIGALRM handler */  quit(int ret)
 {  {
     /* this is only used in batch mode to break out of the pause() */          end_screen();
     /* return; */          exit(ret);
 }  }
   

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.20