124139Sjoergchar *copyright =
224139Sjoerg    "Copyright (c) 1984 through 1996, William LeFebvre";
324139Sjoerg
424139Sjoerg/*
524139Sjoerg *  Top users/processes display for Unix
624139Sjoerg *  Version 3
724139Sjoerg *
824139Sjoerg *  This program may be freely redistributed,
924139Sjoerg *  but this entire comment MUST remain intact.
1024139Sjoerg *
1124139Sjoerg *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
1289757Sdwmalone *  Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University
1389757Sdwmalone *  Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory
1489757Sdwmalone *  Copyright (c) 1996, William LeFebvre, Group sys Consulting
1566641Simp *
1666641Simp * $FreeBSD: stable/11/contrib/top/top.c 332948 2018-04-24 17:37:29Z lidl $
1724139Sjoerg */
1824139Sjoerg
1924139Sjoerg/*
2024139Sjoerg *  See the file "Changes" for information on version-to-version changes.
2124139Sjoerg */
2224139Sjoerg
2324139Sjoerg/*
2424139Sjoerg *  This file contains "main" and other high-level routines.
2524139Sjoerg */
2624139Sjoerg
2724139Sjoerg/*
2824139Sjoerg * The following preprocessor variables, when defined, are used to
2924139Sjoerg * distinguish between different Unix implementations:
3024139Sjoerg *
3124139Sjoerg *	SIGHOLD  - use SVR4 sighold function when defined
3224139Sjoerg *	SIGRELSE - use SVR4 sigrelse function when defined
3324139Sjoerg *	FD_SET   - macros FD_SET and FD_ZERO are used when defined
3424139Sjoerg */
3524139Sjoerg
3624139Sjoerg#include "os.h"
37300395Sngie
38265249Sbdrewery#include <sys/jail.h>
3924139Sjoerg#include <sys/time.h>
40300395Sngie
41300395Sngie#include <ctype.h>
42332948Slidl#include <curses.h>
43300395Sngie#include <errno.h>
44265249Sbdrewery#include <jail.h>
45300395Sngie#include <setjmp.h>
46300395Sngie#include <signal.h>
47300395Sngie#include <unistd.h>
4824139Sjoerg
4924139Sjoerg/* includes specific to top */
50300395Sngie#include "commands.h"
5124139Sjoerg#include "display.h"		/* interface to display package */
5224139Sjoerg#include "screen.h"		/* interface to screen package */
5324139Sjoerg#include "top.h"
5424139Sjoerg#include "top.local.h"
5524139Sjoerg#include "boolean.h"
5624139Sjoerg#include "machine.h"
5724139Sjoerg#include "utils.h"
58300395Sngie#include "username.h"
5924139Sjoerg
6024139Sjoerg/* Size of the stdio buffer given to stdout */
6124139Sjoerg#define Buffersize	2048
6224139Sjoerg
6324139Sjoerg/* The buffer that stdio will use */
6424139Sjoergchar stdoutbuf[Buffersize];
6524139Sjoerg
6624139Sjoerg/* build Signal masks */
6724139Sjoerg#define Smask(s)	(1 << ((s) - 1))
6824139Sjoerg
6924139Sjoerg/* for getopt: */
7024139Sjoergextern int  optind;
7124139Sjoergextern char *optarg;
7224139Sjoerg
7324139Sjoerg/* imported from screen.c */
7424139Sjoergextern int overstrike;
7524139Sjoerg
76168710Sstasstatic int fmt_flags = 0;
77175420Speterint pcpu_stats = No;
78168710Sstas
7924139Sjoerg/* signal handling routines */
8024139Sjoergsigret_t leave();
8124139Sjoergsigret_t tstop();
8224139Sjoerg#ifdef SIGWINCH
83332948Slidlsigret_t top_winch(int);
8424139Sjoerg#endif
8524139Sjoerg
8681187Skrisvolatile sig_atomic_t leaveflag;
8781187Skrisvolatile sig_atomic_t tstopflag;
8881187Skrisvolatile sig_atomic_t winchflag;
8981187Skris
9024139Sjoerg/* internal routines */
9124139Sjoergvoid quit();
9224139Sjoerg
9324139Sjoerg/* values which need to be accessed by signal handlers */
9424139Sjoergstatic int max_topn;		/* maximum displayable processes */
9524139Sjoerg
9624139Sjoerg/* miscellaneous things */
97145073Skeramidastruct process_select ps;
9824139Sjoergchar *myname = "top";
9924139Sjoergjmp_buf jmp_int;
10024139Sjoerg
10124139Sjoerg/* routines that don't return int */
10224139Sjoerg
10324139Sjoergchar *username();
10424139Sjoergchar *ctime();
10524139Sjoergchar *kill_procs();
10624139Sjoergchar *renice_procs();
10724139Sjoerg
10824139Sjoerg#ifdef ORDER
109133817Salfredextern int (*compares[])();
11024139Sjoerg#else
11124139Sjoergextern int proc_compare();
112131829Skeramidaextern int io_compare();
11324139Sjoerg#endif
11424139Sjoergtime_t time();
11524139Sjoerg
11624139Sjoergcaddr_t get_process_info();
11724139Sjoerg
11824139Sjoerg/* different routines for displaying the user's identification */
11924139Sjoerg/* (values assigned to get_userid) */
12024139Sjoergchar *username();
12124139Sjoergchar *itoa7();
12224139Sjoerg
12324139Sjoerg/* pointers to display routines */
124300395Sngievoid (*d_loadave)() = i_loadave;
125300395Sngievoid (*d_procstates)() = i_procstates;
126300395Sngievoid (*d_cpustates)() = i_cpustates;
127300395Sngievoid (*d_memory)() = i_memory;
128300395Sngievoid (*d_arc)() = i_arc;
129318449Sallanjudevoid (*d_carc)() = i_carc;
130300395Sngievoid (*d_swap)() = i_swap;
131300395Sngievoid (*d_message)() = i_message;
132300395Sngievoid (*d_header)() = i_header;
133300395Sngievoid (*d_process)() = i_process;
13424139Sjoerg
135300395Sngievoid reset_display(void);
13624139Sjoerg
137322509Sgahrstatic void
138322509Sgahrreset_uids()
139322509Sgahr{
140322509Sgahr    for (size_t i = 0; i < TOP_MAX_UIDS; ++i)
141322509Sgahr	ps.uid[i] = -1;
142322509Sgahr}
143300395Sngie
144322509Sgahrstatic int
145322509Sgahradd_uid(int uid)
146322509Sgahr{
147322509Sgahr    size_t i = 0;
148322509Sgahr
149322509Sgahr    /* Add the uid if there's room */
150322509Sgahr    for (; i < TOP_MAX_UIDS; ++i)
151322509Sgahr    {
152322509Sgahr	if (ps.uid[i] == -1 || ps.uid[i] == uid)
153322509Sgahr	{
154322509Sgahr	    ps.uid[i] = uid;
155322509Sgahr	    break;
156322509Sgahr	}
157322509Sgahr    }
158322509Sgahr
159322509Sgahr    return (i == TOP_MAX_UIDS);
160322509Sgahr}
161322509Sgahr
162322509Sgahrstatic void
163322509Sgahrrem_uid(int uid)
164322509Sgahr{
165322509Sgahr    size_t i = 0;
166322509Sgahr    size_t where = TOP_MAX_UIDS;
167322509Sgahr
168322509Sgahr    /* Look for the user to remove - no problem if it's not there */
169322509Sgahr    for (; i < TOP_MAX_UIDS; ++i)
170322509Sgahr    {
171322509Sgahr	if (ps.uid[i] == -1)
172322509Sgahr	    break;
173322509Sgahr	if (ps.uid[i] == uid)
174322509Sgahr	    where = i;
175322509Sgahr    }
176322509Sgahr
177322509Sgahr    /* Make sure we don't leave a hole in the middle */
178322509Sgahr    if (where != TOP_MAX_UIDS)
179322509Sgahr    {
180322509Sgahr	ps.uid[where] = ps.uid[i-1];
181322509Sgahr	ps.uid[i-1] = -1;
182322509Sgahr    }
183322509Sgahr}
184322509Sgahr
185322509Sgahrstatic int
186322509Sgahrhandle_user(char *buf, size_t buflen)
187322509Sgahr{
188322509Sgahr    int rc = 0;
189322509Sgahr    int uid = -1;
190322509Sgahr    char *buf2 = buf;
191322509Sgahr
192322509Sgahr    new_message(MT_standout, "Username to show (+ for all): ");
193322509Sgahr    if (readline(buf, buflen, No) <= 0)
194322509Sgahr    {
195322509Sgahr	clear_message();
196322509Sgahr	return rc;
197322509Sgahr    }
198322509Sgahr
199322509Sgahr    if (buf[0] == '+' || buf[0] == '-')
200322509Sgahr    {
201322509Sgahr	if (buf[1] == '\0')
202322509Sgahr	{
203322509Sgahr	    reset_uids();
204322509Sgahr	    goto end;
205322509Sgahr	}
206322509Sgahr	else
207322509Sgahr	    ++buf2;
208322509Sgahr    }
209322509Sgahr
210322509Sgahr    if ((uid = userid(buf2)) == -1)
211322509Sgahr    {
212322509Sgahr	new_message(MT_standout, " %s: unknown user", buf2);
213322509Sgahr	rc = 1;
214322509Sgahr	goto end;
215322509Sgahr    }
216322509Sgahr
217322509Sgahr    if (buf2 == buf)
218322509Sgahr    {
219322509Sgahr	reset_uids();
220322509Sgahr	ps.uid[0] = uid;
221322509Sgahr	goto end;
222322509Sgahr    }
223322509Sgahr
224322509Sgahr    if (buf[0] == '+')
225322509Sgahr    {
226322509Sgahr	if (add_uid(uid))
227322509Sgahr	{
228322509Sgahr	    new_message(MT_standout, " too many users, reset with '+'");
229322509Sgahr	    rc = 1;
230322509Sgahr	    goto end;
231322509Sgahr	}
232322509Sgahr    }
233322509Sgahr    else
234322509Sgahr	rem_uid(uid);
235322509Sgahr
236322509Sgahrend:
237322509Sgahr    putchar('\r');
238322509Sgahr    return rc;
239322509Sgahr}
240322509Sgahr
241300395Sngieint
24224139Sjoergmain(argc, argv)
24324139Sjoerg
24424139Sjoergint  argc;
24524139Sjoergchar *argv[];
24624139Sjoerg
24724139Sjoerg{
24824139Sjoerg    register int i;
24924139Sjoerg    register int active_procs;
25024139Sjoerg    register int change;
25124139Sjoerg
25224139Sjoerg    struct system_info system_info;
25324139Sjoerg    struct statics statics;
25424139Sjoerg    caddr_t processes;
25524139Sjoerg
25624139Sjoerg    static char tempbuf1[50];
25724139Sjoerg    static char tempbuf2[50];
25824139Sjoerg    int old_sigmask;		/* only used for BSD-style signals */
25924139Sjoerg    int topn = Default_TOPN;
26024139Sjoerg    int delay = Default_DELAY;
26124139Sjoerg    int displays = 0;		/* indicates unspecified */
26286042Sdwmalone    int sel_ret = 0;
26324139Sjoerg    time_t curr_time;
26424139Sjoerg    char *(*get_userid)() = username;
26524139Sjoerg    char *uname_field = "USERNAME";
26624139Sjoerg    char *header_text;
26724139Sjoerg    char *env_top;
26824139Sjoerg    char **preset_argv;
26924139Sjoerg    int  preset_argc = 0;
27024139Sjoerg    char **av;
27124139Sjoerg    int  ac;
27224139Sjoerg    char dostates = No;
27324139Sjoerg    char do_unames = Yes;
27424139Sjoerg    char interactive = Maybe;
27524139Sjoerg    char warnings = 0;
27624139Sjoerg#if Default_TOPN == Infinity
27724139Sjoerg    char topn_specified = No;
27824139Sjoerg#endif
27924139Sjoerg    char ch;
28024139Sjoerg    char *iptr;
28124139Sjoerg    char no_command = 1;
28224139Sjoerg    struct timeval timeout;
28324139Sjoerg#ifdef ORDER
28424139Sjoerg    char *order_name = NULL;
28524139Sjoerg    int order_index = 0;
28624139Sjoerg#endif
28724139Sjoerg#ifndef FD_SET
28824139Sjoerg    /* FD_SET and friends are not present:  fake it */
28924139Sjoerg    typedef int fd_set;
29024139Sjoerg#define FD_ZERO(x)     (*(x) = 0)
29189757Sdwmalone#define FD_SET(f, x)   (*(x) = 1<<f)
29224139Sjoerg#endif
29324139Sjoerg    fd_set readfds;
29424139Sjoerg
29524139Sjoerg#ifdef ORDER
296307757Sdes    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
29724139Sjoerg#else
298307757Sdes    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJw";
29924139Sjoerg#endif
30024139Sjoerg/* these defines enumerate the "strchr"s of the commands in command_chars */
30124139Sjoerg#define CMD_redraw	0
30224139Sjoerg#define CMD_update	1
30324139Sjoerg#define CMD_quit	2
30424139Sjoerg#define CMD_help1	3
30524139Sjoerg#define CMD_help2	4
30624139Sjoerg#define CMD_OSLIMIT	4    /* terminals with OS can only handle commands */
30724139Sjoerg#define CMD_errors	5    /* less than or equal to CMD_OSLIMIT	   */
30824139Sjoerg#define CMD_number1	6
30924139Sjoerg#define CMD_number2	7
31024139Sjoerg#define CMD_delay	8
31124139Sjoerg#define CMD_displays	9
31224139Sjoerg#define CMD_kill	10
31324139Sjoerg#define CMD_renice	11
31424139Sjoerg#define CMD_idletog     12
31524139Sjoerg#define CMD_idletog2    13
31624139Sjoerg#define CMD_user	14
31738090Sdes#define CMD_selftog	15
318117709Sjulian#define CMD_thrtog	16
319131402Salfred#define CMD_viewtog	17
320132005Salfred#define CMD_viewsys	18
321146342Skeramida#define	CMD_wcputog	19
322168710Sstas#define	CMD_showargs	20
323168799Srafan#define	CMD_jidtog	21
324222530Sjhb#define CMD_kidletog	22
325223936Sjhb#define CMD_pcputog	23
326265249Sbdrewery#define CMD_jail	24
327307757Sdes#define CMD_swaptog	25
32824139Sjoerg#ifdef ORDER
329307757Sdes#define CMD_order       26
33024139Sjoerg#endif
33124139Sjoerg
33224139Sjoerg    /* set the buffer for stdout */
33324139Sjoerg#ifdef DEBUG
33489757Sdwmalone    extern FILE *debug;
33589757Sdwmalone    debug = fopen("debug.run", "w");
33624139Sjoerg    setbuffer(stdout, NULL, 0);
33724139Sjoerg#else
33824139Sjoerg    setbuffer(stdout, stdoutbuf, Buffersize);
33924139Sjoerg#endif
34024139Sjoerg
34124139Sjoerg    /* get our name */
34224139Sjoerg    if (argc > 0)
34324139Sjoerg    {
34424139Sjoerg	if ((myname = strrchr(argv[0], '/')) == 0)
34524139Sjoerg	{
34624139Sjoerg	    myname = argv[0];
34724139Sjoerg	}
34824139Sjoerg	else
34924139Sjoerg	{
35024139Sjoerg	    myname++;
35124139Sjoerg	}
35224139Sjoerg    }
35324139Sjoerg
35424139Sjoerg    /* initialize some selection options */
35524139Sjoerg    ps.idle    = Yes;
35638090Sdes    ps.self    = -1;
35724139Sjoerg    ps.system  = No;
358322509Sgahr    reset_uids();
359117709Sjulian    ps.thread  = No;
360146342Skeramida    ps.wcpu    = 1;
361265249Sbdrewery    ps.jid     = -1;
362168799Srafan    ps.jail    = No;
363307757Sdes    ps.swap    = No;
364222530Sjhb    ps.kidle   = Yes;
36524139Sjoerg    ps.command = NULL;
36624139Sjoerg
36724139Sjoerg    /* get preset options from the environment */
36824139Sjoerg    if ((env_top = getenv("TOP")) != NULL)
36924139Sjoerg    {
37024139Sjoerg	av = preset_argv = argparse(env_top, &preset_argc);
37124139Sjoerg	ac = preset_argc;
37224139Sjoerg
37324139Sjoerg	/* set the dummy argument to an explanatory message, in case
37424139Sjoerg	   getopt encounters a bad argument */
37524139Sjoerg	preset_argv[0] = "while processing environment";
37624139Sjoerg    }
37724139Sjoerg
37824139Sjoerg    /* process options */
37924139Sjoerg    do {
38024139Sjoerg	/* if we're done doing the presets, then process the real arguments */
38124139Sjoerg	if (preset_argc == 0)
38224139Sjoerg	{
38324139Sjoerg	    ac = argc;
38424139Sjoerg	    av = argv;
38524139Sjoerg
38624139Sjoerg	    /* this should keep getopt happy... */
38724139Sjoerg	    optind = 1;
38824139Sjoerg	}
38924139Sjoerg
390307757Sdes	while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
39124139Sjoerg	{
39224139Sjoerg	    switch(i)
39324139Sjoerg	    {
39489757Sdwmalone	      case 'v':			/* show version number */
39589757Sdwmalone		fprintf(stderr, "%s: version %s\n",
39689757Sdwmalone			myname, version_string());
39789757Sdwmalone		exit(1);
39889757Sdwmalone		break;
39989757Sdwmalone
40024139Sjoerg	      case 'u':			/* toggle uid/username display */
40124139Sjoerg		do_unames = !do_unames;
40224139Sjoerg		break;
40324139Sjoerg
40424139Sjoerg	      case 'U':			/* display only username's processes */
405322509Sgahr		if ((ps.uid[0] = userid(optarg)) == -1)
40624139Sjoerg		{
40724139Sjoerg		    fprintf(stderr, "%s: unknown user\n", optarg);
40824139Sjoerg		    exit(1);
40924139Sjoerg		}
41024139Sjoerg		break;
41124139Sjoerg
41224139Sjoerg	      case 'S':			/* show system processes */
41324139Sjoerg		ps.system = !ps.system;
41424139Sjoerg		break;
41524139Sjoerg
41624139Sjoerg	      case 'I':                   /* show idle processes */
41724139Sjoerg		ps.idle = !ps.idle;
41824139Sjoerg		break;
41924139Sjoerg
42024139Sjoerg	      case 'i':			/* go interactive regardless */
42124139Sjoerg		interactive = Yes;
42224139Sjoerg		break;
42324139Sjoerg
42424139Sjoerg	      case 'n':			/* batch, or non-interactive */
42524139Sjoerg	      case 'b':
42624139Sjoerg		interactive = No;
42724139Sjoerg		break;
42824139Sjoerg
429168710Sstas	      case 'a':
430168710Sstas		fmt_flags ^= FMT_SHOWARGS;
431168710Sstas		break;
432168710Sstas
43324139Sjoerg	      case 'd':			/* number of displays to show */
43424139Sjoerg		if ((i = atoiwi(optarg)) == Invalid || i == 0)
43524139Sjoerg		{
43624139Sjoerg		    fprintf(stderr,
43724139Sjoerg			"%s: warning: display count should be positive -- option ignored\n",
43824139Sjoerg			myname);
43924139Sjoerg		    warnings++;
44024139Sjoerg		}
44124139Sjoerg		else
44224139Sjoerg		{
44324139Sjoerg		    displays = i;
44424139Sjoerg		}
44524139Sjoerg		break;
44624139Sjoerg
44724139Sjoerg	      case 's':
44889757Sdwmalone		if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
44924139Sjoerg		{
45024139Sjoerg		    fprintf(stderr,
45189757Sdwmalone			"%s: warning: seconds delay should be positive -- using default\n",
45224139Sjoerg			myname);
45324139Sjoerg		    delay = Default_DELAY;
45424139Sjoerg		    warnings++;
45524139Sjoerg		}
45624139Sjoerg		break;
45724139Sjoerg
45824139Sjoerg	      case 'q':		/* be quick about it */
45924139Sjoerg		/* only allow this if user is really root */
46024139Sjoerg		if (getuid() == 0)
46124139Sjoerg		{
46224139Sjoerg		    /* be very un-nice! */
46324139Sjoerg		    (void) nice(-20);
46424139Sjoerg		}
46524139Sjoerg		else
46624139Sjoerg		{
46724139Sjoerg		    fprintf(stderr,
46824139Sjoerg			"%s: warning: `-q' option can only be used by root\n",
46924139Sjoerg			myname);
47024139Sjoerg		    warnings++;
47124139Sjoerg		}
47224139Sjoerg		break;
47324139Sjoerg
474131616Sdes	      case 'm':		/* select display mode */
475131402Salfred		if (strcmp(optarg, "io") == 0) {
476131402Salfred			displaymode = DISP_IO;
477131402Salfred		} else if (strcmp(optarg, "cpu") == 0) {
478131402Salfred			displaymode = DISP_CPU;
479131402Salfred		} else {
480131402Salfred			fprintf(stderr,
481131402Salfred			"%s: warning: `-m' option can only take args "
482131402Salfred			"'io' or 'cpu'\n",
483131402Salfred			myname);
484131402Salfred			exit(1);
485131402Salfred		}
486131402Salfred		break;
487131402Salfred
48824139Sjoerg	      case 'o':		/* select sort order */
48924139Sjoerg#ifdef ORDER
49024139Sjoerg		order_name = optarg;
49124139Sjoerg#else
49224139Sjoerg		fprintf(stderr,
49324139Sjoerg			"%s: this platform does not support arbitrary ordering.  Sorry.\n",
49424139Sjoerg			myname);
49524139Sjoerg		warnings++;
49624139Sjoerg#endif
49724139Sjoerg		break;
49824139Sjoerg
49938090Sdes	      case 't':
50038090Sdes		ps.self = (ps.self == -1) ? getpid() : -1;
50138090Sdes		break;
502146342Skeramida
503146342Skeramida	      case 'C':
504146342Skeramida		ps.wcpu = !ps.wcpu;
505146342Skeramida		break;
506146342Skeramida
507117709Sjulian	      case 'H':
508117709Sjulian		ps.thread = !ps.thread;
509117709Sjulian		break;
510146342Skeramida
511168799Srafan	      case 'j':
512168799Srafan		ps.jail = !ps.jail;
513168799Srafan		break;
514168799Srafan
515265249Sbdrewery	      case 'J':			/* display only jail's processes */
516265249Sbdrewery		if ((ps.jid = jail_getid(optarg)) == -1)
517265249Sbdrewery		{
518265249Sbdrewery		    fprintf(stderr, "%s: unknown jail\n", optarg);
519265249Sbdrewery		    exit(1);
520265249Sbdrewery		}
521265249Sbdrewery		ps.jail = 1;
522265249Sbdrewery		break;
523265249Sbdrewery
524175420Speter	      case 'P':
525223936Sjhb		pcpu_stats = !pcpu_stats;
526175420Speter		break;
527175420Speter
528307757Sdes	      case 'w':
529307757Sdes		ps.swap = 1;
530307757Sdes		break;
531307757Sdes
532222530Sjhb	      case 'z':
533222530Sjhb		ps.kidle = !ps.kidle;
534222530Sjhb		break;
535222530Sjhb
53624139Sjoerg	      default:
537157842Sru		fprintf(stderr,
538157842Sru"Top version %s\n"
539330630Seadler"Usage: %s [-abCHIijnPqStuvwz] [-d count] [-m io | cpu] [-o field] [-s time]\n"
540265249Sbdrewery"       [-J jail] [-U username] [number]\n",
54124139Sjoerg			version_string(), myname);
54224139Sjoerg		exit(1);
54324139Sjoerg	    }
54424139Sjoerg	}
54524139Sjoerg
54624139Sjoerg	/* get count of top processes to display (if any) */
54724139Sjoerg	if (optind < ac)
54824139Sjoerg	{
54924139Sjoerg	    if ((topn = atoiwi(av[optind])) == Invalid)
55024139Sjoerg	    {
55124139Sjoerg		fprintf(stderr,
55224139Sjoerg			"%s: warning: process display count should be non-negative -- using default\n",
55324139Sjoerg			myname);
55424139Sjoerg		warnings++;
55524139Sjoerg	    }
55624139Sjoerg#if Default_TOPN == Infinity
55724139Sjoerg            else
55824139Sjoerg	    {
55924139Sjoerg		topn_specified = Yes;
56024139Sjoerg	    }
56124139Sjoerg#endif
56224139Sjoerg	}
56324139Sjoerg
56424139Sjoerg	/* tricky:  remember old value of preset_argc & set preset_argc = 0 */
56524139Sjoerg	i = preset_argc;
56624139Sjoerg	preset_argc = 0;
56724139Sjoerg
56824139Sjoerg    /* repeat only if we really did the preset arguments */
56924139Sjoerg    } while (i != 0);
57024139Sjoerg
57124139Sjoerg    /* set constants for username/uid display correctly */
57224139Sjoerg    if (!do_unames)
57324139Sjoerg    {
57424139Sjoerg	uname_field = "   UID  ";
57524139Sjoerg	get_userid = itoa7;
57624139Sjoerg    }
57724139Sjoerg
57824139Sjoerg    /* initialize the kernel memory interface */
579175195Sobrien    if (machine_init(&statics, do_unames) == -1)
58024139Sjoerg    {
58124139Sjoerg	exit(1);
58224139Sjoerg    }
58324139Sjoerg
58424139Sjoerg#ifdef ORDER
58524139Sjoerg    /* determine sorting order index, if necessary */
58624139Sjoerg    if (order_name != NULL)
58724139Sjoerg    {
58824139Sjoerg	if ((order_index = string_index(order_name, statics.order_names)) == -1)
58924139Sjoerg	{
59024139Sjoerg	    char **pp;
59124139Sjoerg
59224139Sjoerg	    fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
59324139Sjoerg		    myname, order_name);
59424139Sjoerg	    fprintf(stderr, "\tTry one of these:");
59524139Sjoerg	    pp = statics.order_names;
59624139Sjoerg	    while (*pp != NULL)
59724139Sjoerg	    {
59824139Sjoerg		fprintf(stderr, " %s", *pp++);
59924139Sjoerg	    }
60024139Sjoerg	    fputc('\n', stderr);
60124139Sjoerg	    exit(1);
60224139Sjoerg	}
60324139Sjoerg    }
60424139Sjoerg#endif
60524139Sjoerg
60624139Sjoerg#ifdef no_initialization_needed
60724139Sjoerg    /* initialize the hashing stuff */
60824139Sjoerg    if (do_unames)
60924139Sjoerg    {
61024139Sjoerg	init_hash();
61124139Sjoerg    }
61224139Sjoerg#endif
61324139Sjoerg
61424139Sjoerg    /* initialize termcap */
61524139Sjoerg    init_termcap(interactive);
61624139Sjoerg
61724139Sjoerg    /* get the string to use for the process area header */
61824139Sjoerg    header_text = format_header(uname_field);
61924139Sjoerg
62024139Sjoerg    /* initialize display interface */
62124139Sjoerg    if ((max_topn = display_init(&statics)) == -1)
62224139Sjoerg    {
62324139Sjoerg	fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);
62424139Sjoerg	exit(4);
62524139Sjoerg    }
62624139Sjoerg
62724139Sjoerg    /* print warning if user requested more processes than we can display */
62824139Sjoerg    if (topn > max_topn)
62924139Sjoerg    {
63024139Sjoerg	fprintf(stderr,
63124139Sjoerg		"%s: warning: this terminal can only display %d processes.\n",
63224139Sjoerg		myname, max_topn);
63324139Sjoerg	warnings++;
63424139Sjoerg    }
63524139Sjoerg
63624139Sjoerg    /* adjust for topn == Infinity */
63724139Sjoerg    if (topn == Infinity)
63824139Sjoerg    {
63924139Sjoerg	/*
64024139Sjoerg	 *  For smart terminals, infinity really means everything that can
64124139Sjoerg	 *  be displayed, or Largest.
64224139Sjoerg	 *  On dumb terminals, infinity means every process in the system!
64324139Sjoerg	 *  We only really want to do that if it was explicitly specified.
64424139Sjoerg	 *  This is always the case when "Default_TOPN != Infinity".  But if
64524139Sjoerg	 *  topn wasn't explicitly specified and we are on a dumb terminal
64624139Sjoerg	 *  and the default is Infinity, then (and only then) we use
64724139Sjoerg	 *  "Nominal_TOPN" instead.
64824139Sjoerg	 */
64924139Sjoerg#if Default_TOPN == Infinity
65024139Sjoerg	topn = smart_terminal ? Largest :
65124139Sjoerg		    (topn_specified ? Largest : Nominal_TOPN);
65224139Sjoerg#else
65324139Sjoerg	topn = Largest;
65424139Sjoerg#endif
65524139Sjoerg    }
65624139Sjoerg
65724139Sjoerg    /* set header display accordingly */
65824139Sjoerg    display_header(topn > 0);
65924139Sjoerg
66024139Sjoerg    /* determine interactive state */
66124139Sjoerg    if (interactive == Maybe)
66224139Sjoerg    {
66324139Sjoerg	interactive = smart_terminal;
66424139Sjoerg    }
66524139Sjoerg
66624139Sjoerg    /* if # of displays not specified, fill it in */
66724139Sjoerg    if (displays == 0)
66824139Sjoerg    {
66924139Sjoerg	displays = smart_terminal ? Infinity : 1;
67024139Sjoerg    }
67124139Sjoerg
67224139Sjoerg    /* hold interrupt signals while setting up the screen and the handlers */
67324139Sjoerg#ifdef SIGHOLD
67424139Sjoerg    sighold(SIGINT);
67524139Sjoerg    sighold(SIGQUIT);
67624139Sjoerg    sighold(SIGTSTP);
67724139Sjoerg#else
67824139Sjoerg    old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));
67924139Sjoerg#endif
68024139Sjoerg    init_screen();
68124139Sjoerg    (void) signal(SIGINT, leave);
68224139Sjoerg    (void) signal(SIGQUIT, leave);
68324139Sjoerg    (void) signal(SIGTSTP, tstop);
68424139Sjoerg#ifdef SIGWINCH
685332948Slidl    (void) signal(SIGWINCH, top_winch);
68624139Sjoerg#endif
68724139Sjoerg#ifdef SIGRELSE
68824139Sjoerg    sigrelse(SIGINT);
68924139Sjoerg    sigrelse(SIGQUIT);
69024139Sjoerg    sigrelse(SIGTSTP);
69124139Sjoerg#else
69224139Sjoerg    (void) sigsetmask(old_sigmask);
69324139Sjoerg#endif
69424139Sjoerg    if (warnings)
69524139Sjoerg    {
69624139Sjoerg	fputs("....", stderr);
69724139Sjoerg	fflush(stderr);			/* why must I do this? */
69824139Sjoerg	sleep((unsigned)(3 * warnings));
69924139Sjoerg	fputc('\n', stderr);
70024139Sjoerg    }
70124139Sjoerg
70281187Skrisrestart:
70324139Sjoerg
70424139Sjoerg    /*
70524139Sjoerg     *  main loop -- repeat while display count is positive or while it
70624139Sjoerg     *		indicates infinity (by being -1)
70724139Sjoerg     */
70824139Sjoerg
70924139Sjoerg    while ((displays == -1) || (displays-- > 0))
71024139Sjoerg    {
711131402Salfred	int (*compare)();
712131402Salfred
713131402Salfred
71424139Sjoerg	/* get the current stats */
71524139Sjoerg	get_system_info(&system_info);
71624139Sjoerg
71724139Sjoerg#ifdef ORDER
718133817Salfred	compare = compares[order_index];
71924139Sjoerg#else
720131829Skeramida	if (displaymode == DISP_CPU)
721131402Salfred		compare = proc_compare;
722131829Skeramida	else
723131829Skeramida		compare = io_compare;
72424139Sjoerg#endif
72524139Sjoerg
726131402Salfred	/* get the current set of processes */
727131402Salfred	processes =
728131402Salfred		get_process_info(&system_info, &ps, compare);
729131402Salfred
73024139Sjoerg	/* display the load averages */
73124139Sjoerg	(*d_loadave)(system_info.last_pid,
73224139Sjoerg		     system_info.load_avg);
73324139Sjoerg
73424139Sjoerg	/* display the current time */
73524139Sjoerg	/* this method of getting the time SHOULD be fairly portable */
73624139Sjoerg	time(&curr_time);
73742447Sobrien	i_uptime(&system_info.boottime, &curr_time);
73824139Sjoerg	i_timeofday(&curr_time);
73924139Sjoerg
74024139Sjoerg	/* display process state breakdown */
74124139Sjoerg	(*d_procstates)(system_info.p_total,
74224139Sjoerg			system_info.procstates);
74324139Sjoerg
74424139Sjoerg	/* display the cpu state percentage breakdown */
74524139Sjoerg	if (dostates)	/* but not the first time */
74624139Sjoerg	{
74724139Sjoerg	    (*d_cpustates)(system_info.cpustates);
74824139Sjoerg	}
74924139Sjoerg	else
75024139Sjoerg	{
75124139Sjoerg	    /* we'll do it next time */
75224139Sjoerg	    if (smart_terminal)
75324139Sjoerg	    {
75424139Sjoerg		z_cpustates();
75524139Sjoerg	    }
75624139Sjoerg	    else
75724139Sjoerg	    {
75824139Sjoerg		putchar('\n');
75924139Sjoerg	    }
76024139Sjoerg	    dostates = Yes;
76124139Sjoerg	}
76224139Sjoerg
76324139Sjoerg	/* display memory stats */
76424139Sjoerg	(*d_memory)(system_info.memory);
765237656Sjhb	(*d_arc)(system_info.arc);
766318449Sallanjude	(*d_carc)(system_info.carc);
76724139Sjoerg
76824142Sjoerg	/* display swap stats */
76924142Sjoerg	(*d_swap)(system_info.swap);
77024142Sjoerg
77124139Sjoerg	/* handle message area */
77224139Sjoerg	(*d_message)();
77324139Sjoerg
77424139Sjoerg	/* update the header area */
77524139Sjoerg	(*d_header)(header_text);
77624139Sjoerg
77724139Sjoerg	if (topn > 0)
77824139Sjoerg	{
77924139Sjoerg	    /* determine number of processes to actually display */
78024139Sjoerg	    /* this number will be the smallest of:  active processes,
78124139Sjoerg	       number user requested, number current screen accomodates */
78289757Sdwmalone	    active_procs = system_info.P_ACTIVE;
78324139Sjoerg	    if (active_procs > topn)
78424139Sjoerg	    {
78524139Sjoerg		active_procs = topn;
78624139Sjoerg	    }
78724139Sjoerg	    if (active_procs > max_topn)
78824139Sjoerg	    {
78924139Sjoerg		active_procs = max_topn;
79024139Sjoerg	    }
79124139Sjoerg
79224139Sjoerg	    /* now show the top "n" processes. */
79324139Sjoerg	    for (i = 0; i < active_procs; i++)
79424139Sjoerg	    {
795168710Sstas		(*d_process)(i, format_next_process(processes, get_userid,
796168710Sstas			     fmt_flags));
79724139Sjoerg	    }
79824139Sjoerg	}
79924139Sjoerg	else
80024139Sjoerg	{
80124139Sjoerg	    i = 0;
80224139Sjoerg	}
80324139Sjoerg
80424139Sjoerg	/* do end-screen processing */
80524139Sjoerg	u_endscreen(i);
80624139Sjoerg
80724139Sjoerg	/* now, flush the output buffer */
80889757Sdwmalone	if (fflush(stdout) != 0)
80989757Sdwmalone	{
81089757Sdwmalone	    new_message(MT_standout, " Write error on stdout");
81189757Sdwmalone	    putchar('\r');
81289757Sdwmalone	    quit(1);
81389757Sdwmalone	    /*NOTREACHED*/
81489757Sdwmalone	}
81524139Sjoerg
81624139Sjoerg	/* only do the rest if we have more displays to show */
81724139Sjoerg	if (displays)
81824139Sjoerg	{
81924139Sjoerg	    /* switch out for new display on smart terminals */
82024139Sjoerg	    if (smart_terminal)
82124139Sjoerg	    {
82224139Sjoerg		if (overstrike)
82324139Sjoerg		{
82424139Sjoerg		    reset_display();
82524139Sjoerg		}
82624139Sjoerg		else
82724139Sjoerg		{
82824139Sjoerg		    d_loadave = u_loadave;
82924139Sjoerg		    d_procstates = u_procstates;
83024139Sjoerg		    d_cpustates = u_cpustates;
83124139Sjoerg		    d_memory = u_memory;
832237656Sjhb		    d_arc = u_arc;
833318449Sallanjude		    d_carc = u_carc;
83424142Sjoerg		    d_swap = u_swap;
83524139Sjoerg		    d_message = u_message;
83624139Sjoerg		    d_header = u_header;
83724139Sjoerg		    d_process = u_process;
83824139Sjoerg		}
83924139Sjoerg	    }
84024139Sjoerg
84124139Sjoerg	    no_command = Yes;
84224139Sjoerg	    if (!interactive)
84324139Sjoerg	    {
844232239Skib		sleep(delay);
845232660Skib		if (leaveflag) {
846232660Skib		    end_screen();
847232660Skib		    exit(0);
848232660Skib		}
84924139Sjoerg	    }
85024139Sjoerg	    else while (no_command)
85124139Sjoerg	    {
85224139Sjoerg		/* assume valid command unless told otherwise */
85324139Sjoerg		no_command = No;
85424139Sjoerg
85524139Sjoerg		/* set up arguments for select with timeout */
85624139Sjoerg		FD_ZERO(&readfds);
85789757Sdwmalone		FD_SET(0, &readfds);		/* for standard input */
85824139Sjoerg		timeout.tv_sec  = delay;
85924139Sjoerg		timeout.tv_usec = 0;
86024139Sjoerg
86181187Skris		if (leaveflag) {
86281187Skris		    end_screen();
86381187Skris		    exit(0);
86481187Skris		}
86581187Skris
86681187Skris		if (tstopflag) {
86781187Skris		    /* move to the lower left */
86881187Skris		    end_screen();
86981187Skris		    fflush(stdout);
87081187Skris
87181187Skris		    /* default the signal handler action */
87281187Skris		    (void) signal(SIGTSTP, SIG_DFL);
87381187Skris
87481187Skris		    /* unblock the signal and send ourselves one */
87581187Skris#ifdef SIGRELSE
87681187Skris		    sigrelse(SIGTSTP);
87781187Skris#else
87881187Skris		    (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
87981187Skris#endif
88081187Skris		    (void) kill(0, SIGTSTP);
88181187Skris
88281187Skris		    /* reset the signal handler */
88381187Skris		    (void) signal(SIGTSTP, tstop);
88481187Skris
88581187Skris		    /* reinit screen */
88681187Skris		    reinit_screen();
88781187Skris		    reset_display();
88881187Skris		    tstopflag = 0;
88981187Skris		    goto restart;
89081187Skris		}
89181187Skris
89281187Skris		if (winchflag) {
89381187Skris		    /* reascertain the screen dimensions */
89481187Skris		    get_screensize();
89581187Skris
89681187Skris		    /* tell display to resize */
89781187Skris		    max_topn = display_resize();
89881187Skris
89981187Skris		    /* reset the signal handler */
900332948Slidl		    (void) signal(SIGWINCH, top_winch);
90181187Skris
90281187Skris		    reset_display();
90381187Skris		    winchflag = 0;
90481187Skris		    goto restart;
90581187Skris		}
90681187Skris
90724139Sjoerg		/* wait for either input or the end of the delay period */
90886042Sdwmalone		sel_ret = select(2, &readfds, NULL, NULL, &timeout);
90986042Sdwmalone		if (sel_ret < 0 && errno != EINTR)
91086042Sdwmalone		    quit(0);
91186042Sdwmalone		if (sel_ret > 0)
91224139Sjoerg		{
91324139Sjoerg		    int newval;
91424139Sjoerg		    char *errmsg;
91524139Sjoerg
91624139Sjoerg		    /* something to read -- clear the message area first */
91724139Sjoerg		    clear_message();
91824139Sjoerg
91924139Sjoerg		    /* now read it and convert to command strchr */
92024139Sjoerg		    /* (use "change" as a temporary to hold strchr) */
92186042Sdwmalone		    if (read(0, &ch, 1) != 1)
92289757Sdwmalone		    {
92389757Sdwmalone			/* read error: either 0 or -1 */
92489757Sdwmalone			new_message(MT_standout, " Read error on stdin");
92589757Sdwmalone			putchar('\r');
92689757Sdwmalone			quit(1);
92789757Sdwmalone			/*NOTREACHED*/
92889757Sdwmalone		    }
92924139Sjoerg		    if ((iptr = strchr(command_chars, ch)) == NULL)
93024139Sjoerg		    {
93124142Sjoerg			if (ch != '\r' && ch != '\n')
93224142Sjoerg			{
93324142Sjoerg			    /* illegal command */
93424142Sjoerg			    new_message(MT_standout, " Command not understood");
93524142Sjoerg			}
93624139Sjoerg			putchar('\r');
93724139Sjoerg			no_command = Yes;
93824139Sjoerg		    }
93924139Sjoerg		    else
94024139Sjoerg		    {
94124139Sjoerg			change = iptr - command_chars;
94224139Sjoerg			if (overstrike && change > CMD_OSLIMIT)
94324139Sjoerg			{
94424139Sjoerg			    /* error */
94524139Sjoerg			    new_message(MT_standout,
94624139Sjoerg			    " Command cannot be handled by this terminal");
94724139Sjoerg			    putchar('\r');
94824139Sjoerg			    no_command = Yes;
94924139Sjoerg			}
95024139Sjoerg			else switch(change)
95124139Sjoerg			{
95224139Sjoerg			    case CMD_redraw:	/* redraw screen */
95324139Sjoerg				reset_display();
95424139Sjoerg				break;
95524139Sjoerg
95624139Sjoerg			    case CMD_update:	/* merely update display */
95724139Sjoerg				/* is the load average high? */
95824139Sjoerg				if (system_info.load_avg[0] > LoadMax)
95924139Sjoerg				{
96024139Sjoerg				    /* yes, go home for visual feedback */
96124139Sjoerg				    go_home();
96224139Sjoerg				    fflush(stdout);
96324139Sjoerg				}
96424139Sjoerg				break;
96524139Sjoerg
96624139Sjoerg			    case CMD_quit:	/* quit */
96724139Sjoerg				quit(0);
96824139Sjoerg				/*NOTREACHED*/
96924139Sjoerg				break;
97024139Sjoerg
97124139Sjoerg			    case CMD_help1:	/* help */
97224139Sjoerg			    case CMD_help2:
97324139Sjoerg				reset_display();
974332948Slidl				top_clear();
97524139Sjoerg				show_help();
976332948Slidl				top_standout("Hit any key to continue: ");
97724139Sjoerg				fflush(stdout);
97824139Sjoerg				(void) read(0, &ch, 1);
97924139Sjoerg				break;
98024139Sjoerg
98124139Sjoerg			    case CMD_errors:	/* show errors */
98224139Sjoerg				if (error_count() == 0)
98324139Sjoerg				{
98424139Sjoerg				    new_message(MT_standout,
98524139Sjoerg					" Currently no errors to report.");
98624139Sjoerg				    putchar('\r');
98724139Sjoerg				    no_command = Yes;
98824139Sjoerg				}
98924139Sjoerg				else
99024139Sjoerg				{
99124139Sjoerg				    reset_display();
992332948Slidl				    top_clear();
99324139Sjoerg				    show_errors();
994332948Slidl				    top_standout("Hit any key to continue: ");
99524139Sjoerg				    fflush(stdout);
99624139Sjoerg				    (void) read(0, &ch, 1);
99724139Sjoerg				}
99824139Sjoerg				break;
99924139Sjoerg
100024139Sjoerg			    case CMD_number1:	/* new number */
100124139Sjoerg			    case CMD_number2:
100224139Sjoerg				new_message(MT_standout,
100324139Sjoerg				    "Number of processes to show: ");
100424139Sjoerg				newval = readline(tempbuf1, 8, Yes);
100524139Sjoerg				if (newval > -1)
100624139Sjoerg				{
100724139Sjoerg				    if (newval > max_topn)
100824139Sjoerg				    {
100924139Sjoerg					new_message(MT_standout | MT_delayed,
101024139Sjoerg					  " This terminal can only display %d processes.",
101124139Sjoerg					  max_topn);
101224139Sjoerg					putchar('\r');
101324139Sjoerg				    }
101424139Sjoerg
101524139Sjoerg				    if (newval == 0)
101624139Sjoerg				    {
101724139Sjoerg					/* inhibit the header */
101824139Sjoerg					display_header(No);
101924139Sjoerg				    }
102024139Sjoerg				    else if (newval > topn && topn == 0)
102124139Sjoerg				    {
102224139Sjoerg					/* redraw the header */
102324139Sjoerg					display_header(Yes);
102424139Sjoerg					d_header = i_header;
102524139Sjoerg				    }
102624139Sjoerg				    topn = newval;
102724139Sjoerg				}
102824139Sjoerg				break;
102924139Sjoerg
103024139Sjoerg			    case CMD_delay:	/* new seconds delay */
103124139Sjoerg				new_message(MT_standout, "Seconds to delay: ");
103224139Sjoerg				if ((i = readline(tempbuf1, 8, Yes)) > -1)
103324139Sjoerg				{
103489757Sdwmalone				    if ((delay = i) == 0 && getuid() != 0)
103589757Sdwmalone				    {
103689757Sdwmalone					delay = 1;
103789757Sdwmalone				    }
103824139Sjoerg				}
103924139Sjoerg				clear_message();
104024139Sjoerg				break;
104124139Sjoerg
104224139Sjoerg			    case CMD_displays:	/* change display count */
104324139Sjoerg				new_message(MT_standout,
104424139Sjoerg					"Displays to show (currently %s): ",
104524139Sjoerg					displays == -1 ? "infinite" :
104624139Sjoerg							 itoa(displays));
104724139Sjoerg				if ((i = readline(tempbuf1, 10, Yes)) > 0)
104824139Sjoerg				{
104924139Sjoerg				    displays = i;
105024139Sjoerg				}
105124139Sjoerg				else if (i == 0)
105224139Sjoerg				{
105324139Sjoerg				    quit(0);
105424139Sjoerg				}
105524139Sjoerg				clear_message();
105624139Sjoerg				break;
105724139Sjoerg
105824139Sjoerg			    case CMD_kill:	/* kill program */
105924139Sjoerg				new_message(0, "kill ");
106024139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
106124139Sjoerg				{
106224139Sjoerg				    if ((errmsg = kill_procs(tempbuf2)) != NULL)
106324139Sjoerg				    {
106466641Simp					new_message(MT_standout, "%s", errmsg);
106524139Sjoerg					putchar('\r');
106624139Sjoerg					no_command = Yes;
106724139Sjoerg				    }
106824139Sjoerg				}
106924139Sjoerg				else
107024139Sjoerg				{
107124139Sjoerg				    clear_message();
107224139Sjoerg				}
107324139Sjoerg				break;
107424139Sjoerg
107524139Sjoerg			    case CMD_renice:	/* renice program */
107624139Sjoerg				new_message(0, "renice ");
107724139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
107824139Sjoerg				{
107924139Sjoerg				    if ((errmsg = renice_procs(tempbuf2)) != NULL)
108024139Sjoerg				    {
108168293Simp					new_message(MT_standout, "%s", errmsg);
108224139Sjoerg					putchar('\r');
108324139Sjoerg					no_command = Yes;
108424139Sjoerg				    }
108524139Sjoerg				}
108624139Sjoerg				else
108724139Sjoerg				{
108824139Sjoerg				    clear_message();
108924139Sjoerg				}
109024139Sjoerg				break;
109124139Sjoerg
109224139Sjoerg			    case CMD_idletog:
109324139Sjoerg			    case CMD_idletog2:
109424139Sjoerg				ps.idle = !ps.idle;
109524139Sjoerg				new_message(MT_standout | MT_delayed,
109624139Sjoerg				    " %sisplaying idle processes.",
109724139Sjoerg				    ps.idle ? "D" : "Not d");
109824139Sjoerg				putchar('\r');
109924139Sjoerg				break;
110024139Sjoerg
110138090Sdes			    case CMD_selftog:
110238090Sdes				ps.self = (ps.self == -1) ? getpid() : -1;
110338090Sdes				new_message(MT_standout | MT_delayed,
110438090Sdes				    " %sisplaying self.",
110538090Sdes				    (ps.self == -1) ? "D" : "Not d");
110638090Sdes				putchar('\r');
110738090Sdes				break;
110838090Sdes
110924139Sjoerg			    case CMD_user:
1110322509Sgahr				if (handle_user(tempbuf2, sizeof(tempbuf2)))
1111322509Sgahr				    no_command = Yes;
111224139Sjoerg				break;
111324139Sjoerg
1114117709Sjulian			    case CMD_thrtog:
1115117709Sjulian				ps.thread = !ps.thread;
1116117709Sjulian				new_message(MT_standout | MT_delayed,
1117223937Sjhb				    " Displaying threads %s",
1118145073Skeramida				    ps.thread ? "separately" : "as a count");
1119145073Skeramida				header_text = format_header(uname_field);
1120145073Skeramida				reset_display();
1121117709Sjulian				putchar('\r');
1122117709Sjulian				break;
1123146342Skeramida			    case CMD_wcputog:
1124146342Skeramida				ps.wcpu = !ps.wcpu;
1125146342Skeramida				new_message(MT_standout | MT_delayed,
1126224204Sjhb				    " Displaying %s CPU",
1127224204Sjhb				    ps.wcpu ? "weighted" : "raw");
1128146342Skeramida				header_text = format_header(uname_field);
1129146342Skeramida				reset_display();
1130146342Skeramida				putchar('\r');
1131146342Skeramida				break;
1132131402Salfred			    case CMD_viewtog:
1133131402Salfred				if (++displaymode == DISP_MAX)
1134131402Salfred					displaymode = 0;
1135131402Salfred				header_text = format_header(uname_field);
1136131402Salfred				display_header(Yes);
1137131402Salfred				d_header = i_header;
1138131402Salfred				reset_display();
1139131402Salfred				break;
1140132005Salfred			    case CMD_viewsys:
1141132005Salfred				ps.system = !ps.system;
1142132005Salfred				break;
1143168710Sstas			    case CMD_showargs:
1144168710Sstas				fmt_flags ^= FMT_SHOWARGS;
1145168710Sstas				break;
114624139Sjoerg#ifdef ORDER
114724139Sjoerg			    case CMD_order:
114824139Sjoerg				new_message(MT_standout,
114924139Sjoerg				    "Order to sort: ");
115024139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
115124139Sjoerg				{
115224139Sjoerg				  if ((i = string_index(tempbuf2, statics.order_names)) == -1)
115324139Sjoerg					{
115424139Sjoerg					  new_message(MT_standout,
115524139Sjoerg					      " %s: unrecognized sorting order", tempbuf2);
115624139Sjoerg					  no_command = Yes;
115724139Sjoerg				    }
115824139Sjoerg				    else
115924139Sjoerg				    {
116024139Sjoerg					order_index = i;
116124139Sjoerg				    }
116224139Sjoerg				    putchar('\r');
116324139Sjoerg				}
116424139Sjoerg				else
116524139Sjoerg				{
116624139Sjoerg				    clear_message();
116724139Sjoerg				}
116824139Sjoerg				break;
116924139Sjoerg#endif
1170168799Srafan			    case CMD_jidtog:
1171168799Srafan				ps.jail = !ps.jail;
1172168799Srafan				new_message(MT_standout | MT_delayed,
1173169257Srafan				    " %sisplaying jail ID.",
1174168799Srafan				    ps.jail ? "D" : "Not d");
1175168799Srafan				header_text = format_header(uname_field);
1176168799Srafan				reset_display();
1177168799Srafan				putchar('\r');
1178168799Srafan				break;
1179265249Sbdrewery
1180265249Sbdrewery			    case CMD_jail:
1181265249Sbdrewery				new_message(MT_standout,
1182265250Sbdrewery				    "Jail to show (+ for all): ");
1183265249Sbdrewery				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
1184265249Sbdrewery				{
1185265249Sbdrewery				    if (tempbuf2[0] == '+' &&
1186265249Sbdrewery					tempbuf2[1] == '\0')
1187265249Sbdrewery				    {
1188265249Sbdrewery					ps.jid = -1;
1189265249Sbdrewery				    }
1190265249Sbdrewery				    else if ((i = jail_getid(tempbuf2)) == -1)
1191265249Sbdrewery				    {
1192265249Sbdrewery					new_message(MT_standout,
1193265249Sbdrewery					    " %s: unknown jail", tempbuf2);
1194265249Sbdrewery					no_command = Yes;
1195265249Sbdrewery				    }
1196265249Sbdrewery				    else
1197265249Sbdrewery				    {
1198265249Sbdrewery					ps.jid = i;
1199265249Sbdrewery				    }
1200265249Sbdrewery				    if (ps.jail == 0) {
1201265249Sbdrewery					    ps.jail = 1;
1202265249Sbdrewery					    new_message(MT_standout |
1203265249Sbdrewery						MT_delayed, " Displaying jail "
1204265249Sbdrewery						"ID.");
1205265249Sbdrewery					    header_text =
1206265249Sbdrewery						format_header(uname_field);
1207265249Sbdrewery					    reset_display();
1208265249Sbdrewery				    }
1209265249Sbdrewery				    putchar('\r');
1210265249Sbdrewery				}
1211265249Sbdrewery				else
1212265249Sbdrewery				{
1213265249Sbdrewery				    clear_message();
1214265249Sbdrewery				}
1215265249Sbdrewery				break;
1216265249Sbdrewery
1217222530Sjhb			    case CMD_kidletog:
1218222530Sjhb				ps.kidle = !ps.kidle;
1219222530Sjhb				new_message(MT_standout | MT_delayed,
1220222530Sjhb				    " %sisplaying system idle process.",
1221222530Sjhb				    ps.kidle ? "D" : "Not d");
1222222530Sjhb				putchar('\r');
1223222530Sjhb				break;
1224223936Sjhb			    case CMD_pcputog:
1225223936Sjhb				pcpu_stats = !pcpu_stats;
1226223936Sjhb				new_message(MT_standout | MT_delayed,
1227223936Sjhb				    " Displaying %sCPU statistics.",
1228223936Sjhb				    pcpu_stats ? "per-" : "global ");
1229224205Sjhb				toggle_pcpustats();
1230223936Sjhb				max_topn = display_updatecpus(&statics);
1231223936Sjhb				reset_display();
1232223936Sjhb				putchar('\r');
1233223936Sjhb				break;
1234307757Sdes			    case CMD_swaptog:
1235307757Sdes				ps.swap = !ps.swap;
1236307757Sdes				new_message(MT_standout | MT_delayed,
1237307757Sdes				    " %sisplaying per-process swap usage.",
1238307757Sdes				    ps.swap ? "D" : "Not d");
1239307757Sdes				header_text = format_header(uname_field);
1240307757Sdes				reset_display();
1241307757Sdes				putchar('\r');
1242307757Sdes				break;
124324139Sjoerg			    default:
124424139Sjoerg				new_message(MT_standout, " BAD CASE IN SWITCH!");
124524139Sjoerg				putchar('\r');
124624139Sjoerg			}
124724139Sjoerg		    }
124824139Sjoerg
124924139Sjoerg		    /* flush out stuff that may have been written */
125024139Sjoerg		    fflush(stdout);
125124139Sjoerg		}
125224139Sjoerg	    }
125324139Sjoerg	}
125424139Sjoerg    }
125524139Sjoerg
125689757Sdwmalone#ifdef DEBUG
125789757Sdwmalone    fclose(debug);
125889757Sdwmalone#endif
125924139Sjoerg    quit(0);
126024139Sjoerg    /*NOTREACHED*/
126124139Sjoerg}
126224139Sjoerg
126324139Sjoerg/*
126424139Sjoerg *  reset_display() - reset all the display routine pointers so that entire
126524139Sjoerg *	screen will get redrawn.
126624139Sjoerg */
126724139Sjoerg
1268300395Sngievoid
126924139Sjoergreset_display()
127024139Sjoerg
127124139Sjoerg{
127224139Sjoerg    d_loadave    = i_loadave;
127324139Sjoerg    d_procstates = i_procstates;
127424139Sjoerg    d_cpustates  = i_cpustates;
127524139Sjoerg    d_memory     = i_memory;
1276237656Sjhb    d_arc        = i_arc;
1277318449Sallanjude    d_carc       = i_carc;
127824142Sjoerg    d_swap       = i_swap;
127924139Sjoerg    d_message	 = i_message;
128024139Sjoerg    d_header	 = i_header;
128124139Sjoerg    d_process	 = i_process;
128224139Sjoerg}
128324139Sjoerg
128424139Sjoerg/*
128524139Sjoerg *  signal handlers
128624139Sjoerg */
128724139Sjoerg
128824139Sjoergsigret_t leave()	/* exit under normal conditions -- INT handler */
128924139Sjoerg
129024139Sjoerg{
129181187Skris    leaveflag = 1;
129224139Sjoerg}
129324139Sjoerg
129424139Sjoergsigret_t tstop(i)	/* SIGTSTP handler */
129524139Sjoerg
129624139Sjoergint i;
129724139Sjoerg
129824139Sjoerg{
129981187Skris    tstopflag = 1;
130024139Sjoerg}
130124139Sjoerg
130224139Sjoerg#ifdef SIGWINCH
1303332948Slidlsigret_t top_winch(int i)		/* SIGWINCH handler */
130424139Sjoerg{
130581187Skris    winchflag = 1;
130624139Sjoerg}
130724139Sjoerg#endif
130824139Sjoerg
130924139Sjoergvoid quit(status)		/* exit under duress */
131024139Sjoerg
131124139Sjoergint status;
131224139Sjoerg
131324139Sjoerg{
131424139Sjoerg    end_screen();
131524139Sjoerg    exit(status);
131624139Sjoerg    /*NOTREACHED*/
131724139Sjoerg}
1318