top.c revision 265249
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: head/contrib/top/top.c 265249 2014-05-02 23:30:39Z bdrewery $
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"
3786042Sdwmalone#include <errno.h>
3824139Sjoerg#include <signal.h>
3924139Sjoerg#include <setjmp.h>
4024139Sjoerg#include <ctype.h>
41265249Sbdrewery#include <sys/jail.h>
4224139Sjoerg#include <sys/time.h>
43265249Sbdrewery#include <jail.h>
4424139Sjoerg
4524139Sjoerg/* includes specific to top */
4624139Sjoerg#include "display.h"		/* interface to display package */
4724139Sjoerg#include "screen.h"		/* interface to screen package */
4824139Sjoerg#include "top.h"
4924139Sjoerg#include "top.local.h"
5024139Sjoerg#include "boolean.h"
5124139Sjoerg#include "machine.h"
5224139Sjoerg#include "utils.h"
5324139Sjoerg
5424139Sjoerg/* Size of the stdio buffer given to stdout */
5524139Sjoerg#define Buffersize	2048
5624139Sjoerg
5724139Sjoerg/* The buffer that stdio will use */
5824139Sjoergchar stdoutbuf[Buffersize];
5924139Sjoerg
6024139Sjoerg/* build Signal masks */
6124139Sjoerg#define Smask(s)	(1 << ((s) - 1))
6224139Sjoerg
6324139Sjoerg/* for getopt: */
6424139Sjoergextern int  optind;
6524139Sjoergextern char *optarg;
6624139Sjoerg
6724139Sjoerg/* imported from screen.c */
6824139Sjoergextern int overstrike;
6924139Sjoerg
70168710Sstasstatic int fmt_flags = 0;
71175420Speterint pcpu_stats = No;
72168710Sstas
7324139Sjoerg/* signal handling routines */
7424139Sjoergsigret_t leave();
7524139Sjoergsigret_t tstop();
7624139Sjoerg#ifdef SIGWINCH
7724139Sjoergsigret_t winch();
7824139Sjoerg#endif
7924139Sjoerg
8081187Skrisvolatile sig_atomic_t leaveflag;
8181187Skrisvolatile sig_atomic_t tstopflag;
8281187Skrisvolatile sig_atomic_t winchflag;
8381187Skris
8424139Sjoerg/* internal routines */
8524139Sjoergvoid quit();
8624139Sjoerg
8724139Sjoerg/* values which need to be accessed by signal handlers */
8824139Sjoergstatic int max_topn;		/* maximum displayable processes */
8924139Sjoerg
9024139Sjoerg/* miscellaneous things */
91145073Skeramidastruct process_select ps;
9224139Sjoergchar *myname = "top";
9324139Sjoergjmp_buf jmp_int;
9424139Sjoerg
9524139Sjoerg/* routines that don't return int */
9624139Sjoerg
9724139Sjoergchar *username();
9824139Sjoergchar *ctime();
9924139Sjoergchar *kill_procs();
10024139Sjoergchar *renice_procs();
10124139Sjoerg
10224139Sjoerg#ifdef ORDER
103133817Salfredextern int (*compares[])();
10424139Sjoerg#else
10524139Sjoergextern int proc_compare();
106131829Skeramidaextern int io_compare();
10724139Sjoerg#endif
10824139Sjoergtime_t time();
10924139Sjoerg
11024139Sjoergcaddr_t get_process_info();
11124139Sjoerg
11224139Sjoerg/* different routines for displaying the user's identification */
11324139Sjoerg/* (values assigned to get_userid) */
11424139Sjoergchar *username();
11524139Sjoergchar *itoa7();
11624139Sjoerg
11724139Sjoerg/* display routines that need to be predeclared */
11824139Sjoergint i_loadave();
11924139Sjoergint u_loadave();
12024139Sjoergint i_procstates();
12124139Sjoergint u_procstates();
12224139Sjoergint i_cpustates();
12324139Sjoergint u_cpustates();
12424139Sjoergint i_memory();
12524139Sjoergint u_memory();
126237656Sjhbint i_arc();
127237656Sjhbint u_arc();
12824142Sjoergint i_swap();
12924142Sjoergint u_swap();
13024139Sjoergint i_message();
13124139Sjoergint u_message();
13224139Sjoergint i_header();
13324139Sjoergint u_header();
13424139Sjoergint i_process();
13524139Sjoergint u_process();
13624139Sjoerg
13724139Sjoerg/* pointers to display routines */
13824139Sjoergint (*d_loadave)() = i_loadave;
13924139Sjoergint (*d_procstates)() = i_procstates;
14024139Sjoergint (*d_cpustates)() = i_cpustates;
14124139Sjoergint (*d_memory)() = i_memory;
142237656Sjhbint (*d_arc)() = i_arc;
14324142Sjoergint (*d_swap)() = i_swap;
14424139Sjoergint (*d_message)() = i_message;
14524139Sjoergint (*d_header)() = i_header;
14624139Sjoergint (*d_process)() = i_process;
14724139Sjoerg
14824139Sjoerg
14924139Sjoergmain(argc, argv)
15024139Sjoerg
15124139Sjoergint  argc;
15224139Sjoergchar *argv[];
15324139Sjoerg
15424139Sjoerg{
15524139Sjoerg    register int i;
15624139Sjoerg    register int active_procs;
15724139Sjoerg    register int change;
15824139Sjoerg
15924139Sjoerg    struct system_info system_info;
16024139Sjoerg    struct statics statics;
16124139Sjoerg    caddr_t processes;
16224139Sjoerg
16324139Sjoerg    static char tempbuf1[50];
16424139Sjoerg    static char tempbuf2[50];
16524139Sjoerg    int old_sigmask;		/* only used for BSD-style signals */
16624139Sjoerg    int topn = Default_TOPN;
16724139Sjoerg    int delay = Default_DELAY;
16824139Sjoerg    int displays = 0;		/* indicates unspecified */
16986042Sdwmalone    int sel_ret = 0;
17024139Sjoerg    time_t curr_time;
17124139Sjoerg    char *(*get_userid)() = username;
17224139Sjoerg    char *uname_field = "USERNAME";
17324139Sjoerg    char *header_text;
17424139Sjoerg    char *env_top;
17524139Sjoerg    char **preset_argv;
17624139Sjoerg    int  preset_argc = 0;
17724139Sjoerg    char **av;
17824139Sjoerg    int  ac;
17924139Sjoerg    char dostates = No;
18024139Sjoerg    char do_unames = Yes;
18124139Sjoerg    char interactive = Maybe;
18224139Sjoerg    char warnings = 0;
18324139Sjoerg#if Default_TOPN == Infinity
18424139Sjoerg    char topn_specified = No;
18524139Sjoerg#endif
18624139Sjoerg    char ch;
18724139Sjoerg    char *iptr;
18824139Sjoerg    char no_command = 1;
18924139Sjoerg    struct timeval timeout;
19024139Sjoerg#ifdef ORDER
19124139Sjoerg    char *order_name = NULL;
19224139Sjoerg    int order_index = 0;
19324139Sjoerg#endif
19424139Sjoerg#ifndef FD_SET
19524139Sjoerg    /* FD_SET and friends are not present:  fake it */
19624139Sjoerg    typedef int fd_set;
19724139Sjoerg#define FD_ZERO(x)     (*(x) = 0)
19889757Sdwmalone#define FD_SET(f, x)   (*(x) = 1<<f)
19924139Sjoerg#endif
20024139Sjoerg    fd_set readfds;
20124139Sjoerg
20224139Sjoerg#ifdef ORDER
203265249Sbdrewery    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJo";
20424139Sjoerg#else
205265249Sbdrewery    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJ";
20624139Sjoerg#endif
20724139Sjoerg/* these defines enumerate the "strchr"s of the commands in command_chars */
20824139Sjoerg#define CMD_redraw	0
20924139Sjoerg#define CMD_update	1
21024139Sjoerg#define CMD_quit	2
21124139Sjoerg#define CMD_help1	3
21224139Sjoerg#define CMD_help2	4
21324139Sjoerg#define CMD_OSLIMIT	4    /* terminals with OS can only handle commands */
21424139Sjoerg#define CMD_errors	5    /* less than or equal to CMD_OSLIMIT	   */
21524139Sjoerg#define CMD_number1	6
21624139Sjoerg#define CMD_number2	7
21724139Sjoerg#define CMD_delay	8
21824139Sjoerg#define CMD_displays	9
21924139Sjoerg#define CMD_kill	10
22024139Sjoerg#define CMD_renice	11
22124139Sjoerg#define CMD_idletog     12
22224139Sjoerg#define CMD_idletog2    13
22324139Sjoerg#define CMD_user	14
22438090Sdes#define CMD_selftog	15
225117709Sjulian#define CMD_thrtog	16
226131402Salfred#define CMD_viewtog	17
227132005Salfred#define CMD_viewsys	18
228146342Skeramida#define	CMD_wcputog	19
229168710Sstas#define	CMD_showargs	20
230168799Srafan#define	CMD_jidtog	21
231222530Sjhb#define CMD_kidletog	22
232223936Sjhb#define CMD_pcputog	23
233265249Sbdrewery#define CMD_jail	24
23424139Sjoerg#ifdef ORDER
235265249Sbdrewery#define CMD_order       25
23624139Sjoerg#endif
23724139Sjoerg
23824139Sjoerg    /* set the buffer for stdout */
23924139Sjoerg#ifdef DEBUG
24089757Sdwmalone    extern FILE *debug;
24189757Sdwmalone    debug = fopen("debug.run", "w");
24224139Sjoerg    setbuffer(stdout, NULL, 0);
24324139Sjoerg#else
24424139Sjoerg    setbuffer(stdout, stdoutbuf, Buffersize);
24524139Sjoerg#endif
24624139Sjoerg
24724139Sjoerg    /* get our name */
24824139Sjoerg    if (argc > 0)
24924139Sjoerg    {
25024139Sjoerg	if ((myname = strrchr(argv[0], '/')) == 0)
25124139Sjoerg	{
25224139Sjoerg	    myname = argv[0];
25324139Sjoerg	}
25424139Sjoerg	else
25524139Sjoerg	{
25624139Sjoerg	    myname++;
25724139Sjoerg	}
25824139Sjoerg    }
25924139Sjoerg
26024139Sjoerg    /* initialize some selection options */
26124139Sjoerg    ps.idle    = Yes;
26238090Sdes    ps.self    = -1;
26324139Sjoerg    ps.system  = No;
26424139Sjoerg    ps.uid     = -1;
265117709Sjulian    ps.thread  = No;
266146342Skeramida    ps.wcpu    = 1;
267265249Sbdrewery    ps.jid     = -1;
268168799Srafan    ps.jail    = No;
269222530Sjhb    ps.kidle   = Yes;
27024139Sjoerg    ps.command = NULL;
27124139Sjoerg
27224139Sjoerg    /* get preset options from the environment */
27324139Sjoerg    if ((env_top = getenv("TOP")) != NULL)
27424139Sjoerg    {
27524139Sjoerg	av = preset_argv = argparse(env_top, &preset_argc);
27624139Sjoerg	ac = preset_argc;
27724139Sjoerg
27824139Sjoerg	/* set the dummy argument to an explanatory message, in case
27924139Sjoerg	   getopt encounters a bad argument */
28024139Sjoerg	preset_argv[0] = "while processing environment";
28124139Sjoerg    }
28224139Sjoerg
28324139Sjoerg    /* process options */
28424139Sjoerg    do {
28524139Sjoerg	/* if we're done doing the presets, then process the real arguments */
28624139Sjoerg	if (preset_argc == 0)
28724139Sjoerg	{
28824139Sjoerg	    ac = argc;
28924139Sjoerg	    av = argv;
29024139Sjoerg
29124139Sjoerg	    /* this should keep getopt happy... */
29224139Sjoerg	    optind = 1;
29324139Sjoerg	}
29424139Sjoerg
295265249Sbdrewery	while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:t")) != EOF)
29624139Sjoerg	{
29724139Sjoerg	    switch(i)
29824139Sjoerg	    {
29989757Sdwmalone	      case 'v':			/* show version number */
30089757Sdwmalone		fprintf(stderr, "%s: version %s\n",
30189757Sdwmalone			myname, version_string());
30289757Sdwmalone		exit(1);
30389757Sdwmalone		break;
30489757Sdwmalone
30524139Sjoerg	      case 'u':			/* toggle uid/username display */
30624139Sjoerg		do_unames = !do_unames;
30724139Sjoerg		break;
30824139Sjoerg
30924139Sjoerg	      case 'U':			/* display only username's processes */
31024139Sjoerg		if ((ps.uid = userid(optarg)) == -1)
31124139Sjoerg		{
31224139Sjoerg		    fprintf(stderr, "%s: unknown user\n", optarg);
31324139Sjoerg		    exit(1);
31424139Sjoerg		}
31524139Sjoerg		break;
31624139Sjoerg
31724139Sjoerg	      case 'S':			/* show system processes */
31824139Sjoerg		ps.system = !ps.system;
31924139Sjoerg		break;
32024139Sjoerg
32124139Sjoerg	      case 'I':                   /* show idle processes */
32224139Sjoerg		ps.idle = !ps.idle;
32324139Sjoerg		break;
32424139Sjoerg
32524139Sjoerg	      case 'i':			/* go interactive regardless */
32624139Sjoerg		interactive = Yes;
32724139Sjoerg		break;
32824139Sjoerg
32924139Sjoerg	      case 'n':			/* batch, or non-interactive */
33024139Sjoerg	      case 'b':
33124139Sjoerg		interactive = No;
33224139Sjoerg		break;
33324139Sjoerg
334168710Sstas	      case 'a':
335168710Sstas		fmt_flags ^= FMT_SHOWARGS;
336168710Sstas		break;
337168710Sstas
33824139Sjoerg	      case 'd':			/* number of displays to show */
33924139Sjoerg		if ((i = atoiwi(optarg)) == Invalid || i == 0)
34024139Sjoerg		{
34124139Sjoerg		    fprintf(stderr,
34224139Sjoerg			"%s: warning: display count should be positive -- option ignored\n",
34324139Sjoerg			myname);
34424139Sjoerg		    warnings++;
34524139Sjoerg		}
34624139Sjoerg		else
34724139Sjoerg		{
34824139Sjoerg		    displays = i;
34924139Sjoerg		}
35024139Sjoerg		break;
35124139Sjoerg
35224139Sjoerg	      case 's':
35389757Sdwmalone		if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
35424139Sjoerg		{
35524139Sjoerg		    fprintf(stderr,
35689757Sdwmalone			"%s: warning: seconds delay should be positive -- using default\n",
35724139Sjoerg			myname);
35824139Sjoerg		    delay = Default_DELAY;
35924139Sjoerg		    warnings++;
36024139Sjoerg		}
36124139Sjoerg		break;
36224139Sjoerg
36324139Sjoerg	      case 'q':		/* be quick about it */
36424139Sjoerg		/* only allow this if user is really root */
36524139Sjoerg		if (getuid() == 0)
36624139Sjoerg		{
36724139Sjoerg		    /* be very un-nice! */
36824139Sjoerg		    (void) nice(-20);
36924139Sjoerg		}
37024139Sjoerg		else
37124139Sjoerg		{
37224139Sjoerg		    fprintf(stderr,
37324139Sjoerg			"%s: warning: `-q' option can only be used by root\n",
37424139Sjoerg			myname);
37524139Sjoerg		    warnings++;
37624139Sjoerg		}
37724139Sjoerg		break;
37824139Sjoerg
379131616Sdes	      case 'm':		/* select display mode */
380131402Salfred		if (strcmp(optarg, "io") == 0) {
381131402Salfred			displaymode = DISP_IO;
382131402Salfred		} else if (strcmp(optarg, "cpu") == 0) {
383131402Salfred			displaymode = DISP_CPU;
384131402Salfred		} else {
385131402Salfred			fprintf(stderr,
386131402Salfred			"%s: warning: `-m' option can only take args "
387131402Salfred			"'io' or 'cpu'\n",
388131402Salfred			myname);
389131402Salfred			exit(1);
390131402Salfred		}
391131402Salfred		break;
392131402Salfred
39324139Sjoerg	      case 'o':		/* select sort order */
39424139Sjoerg#ifdef ORDER
39524139Sjoerg		order_name = optarg;
39624139Sjoerg#else
39724139Sjoerg		fprintf(stderr,
39824139Sjoerg			"%s: this platform does not support arbitrary ordering.  Sorry.\n",
39924139Sjoerg			myname);
40024139Sjoerg		warnings++;
40124139Sjoerg#endif
40224139Sjoerg		break;
40324139Sjoerg
40438090Sdes	      case 't':
40538090Sdes		ps.self = (ps.self == -1) ? getpid() : -1;
40638090Sdes		break;
407146342Skeramida
408146342Skeramida	      case 'C':
409146342Skeramida		ps.wcpu = !ps.wcpu;
410146342Skeramida		break;
411146342Skeramida
412117709Sjulian	      case 'H':
413117709Sjulian		ps.thread = !ps.thread;
414117709Sjulian		break;
415146342Skeramida
416168799Srafan	      case 'j':
417168799Srafan		ps.jail = !ps.jail;
418168799Srafan		break;
419168799Srafan
420265249Sbdrewery	      case 'J':			/* display only jail's processes */
421265249Sbdrewery		if ((ps.jid = jail_getid(optarg)) == -1)
422265249Sbdrewery		{
423265249Sbdrewery		    fprintf(stderr, "%s: unknown jail\n", optarg);
424265249Sbdrewery		    exit(1);
425265249Sbdrewery		}
426265249Sbdrewery		ps.jail = 1;
427265249Sbdrewery		break;
428265249Sbdrewery
429175420Speter	      case 'P':
430223936Sjhb		pcpu_stats = !pcpu_stats;
431175420Speter		break;
432175420Speter
433222530Sjhb	      case 'z':
434222530Sjhb		ps.kidle = !ps.kidle;
435222530Sjhb		break;
436222530Sjhb
43724139Sjoerg	      default:
438157842Sru		fprintf(stderr,
439157842Sru"Top version %s\n"
440222530Sjhb"Usage: %s [-abCHIijnPqStuvz] [-d count] [-m io | cpu] [-o field] [-s time]\n"
441265249Sbdrewery"       [-J jail] [-U username] [number]\n",
44224139Sjoerg			version_string(), myname);
44324139Sjoerg		exit(1);
44424139Sjoerg	    }
44524139Sjoerg	}
44624139Sjoerg
44724139Sjoerg	/* get count of top processes to display (if any) */
44824139Sjoerg	if (optind < ac)
44924139Sjoerg	{
45024139Sjoerg	    if ((topn = atoiwi(av[optind])) == Invalid)
45124139Sjoerg	    {
45224139Sjoerg		fprintf(stderr,
45324139Sjoerg			"%s: warning: process display count should be non-negative -- using default\n",
45424139Sjoerg			myname);
45524139Sjoerg		warnings++;
45624139Sjoerg	    }
45724139Sjoerg#if Default_TOPN == Infinity
45824139Sjoerg            else
45924139Sjoerg	    {
46024139Sjoerg		topn_specified = Yes;
46124139Sjoerg	    }
46224139Sjoerg#endif
46324139Sjoerg	}
46424139Sjoerg
46524139Sjoerg	/* tricky:  remember old value of preset_argc & set preset_argc = 0 */
46624139Sjoerg	i = preset_argc;
46724139Sjoerg	preset_argc = 0;
46824139Sjoerg
46924139Sjoerg    /* repeat only if we really did the preset arguments */
47024139Sjoerg    } while (i != 0);
47124139Sjoerg
47224139Sjoerg    /* set constants for username/uid display correctly */
47324139Sjoerg    if (!do_unames)
47424139Sjoerg    {
47524139Sjoerg	uname_field = "   UID  ";
47624139Sjoerg	get_userid = itoa7;
47724139Sjoerg    }
47824139Sjoerg
47924139Sjoerg    /* initialize the kernel memory interface */
480175195Sobrien    if (machine_init(&statics, do_unames) == -1)
48124139Sjoerg    {
48224139Sjoerg	exit(1);
48324139Sjoerg    }
48424139Sjoerg
48524139Sjoerg#ifdef ORDER
48624139Sjoerg    /* determine sorting order index, if necessary */
48724139Sjoerg    if (order_name != NULL)
48824139Sjoerg    {
48924139Sjoerg	if ((order_index = string_index(order_name, statics.order_names)) == -1)
49024139Sjoerg	{
49124139Sjoerg	    char **pp;
49224139Sjoerg
49324139Sjoerg	    fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
49424139Sjoerg		    myname, order_name);
49524139Sjoerg	    fprintf(stderr, "\tTry one of these:");
49624139Sjoerg	    pp = statics.order_names;
49724139Sjoerg	    while (*pp != NULL)
49824139Sjoerg	    {
49924139Sjoerg		fprintf(stderr, " %s", *pp++);
50024139Sjoerg	    }
50124139Sjoerg	    fputc('\n', stderr);
50224139Sjoerg	    exit(1);
50324139Sjoerg	}
50424139Sjoerg    }
50524139Sjoerg#endif
50624139Sjoerg
50724139Sjoerg#ifdef no_initialization_needed
50824139Sjoerg    /* initialize the hashing stuff */
50924139Sjoerg    if (do_unames)
51024139Sjoerg    {
51124139Sjoerg	init_hash();
51224139Sjoerg    }
51324139Sjoerg#endif
51424139Sjoerg
51524139Sjoerg    /* initialize termcap */
51624139Sjoerg    init_termcap(interactive);
51724139Sjoerg
51824139Sjoerg    /* get the string to use for the process area header */
51924139Sjoerg    header_text = format_header(uname_field);
52024139Sjoerg
52124139Sjoerg    /* initialize display interface */
52224139Sjoerg    if ((max_topn = display_init(&statics)) == -1)
52324139Sjoerg    {
52424139Sjoerg	fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);
52524139Sjoerg	exit(4);
52624139Sjoerg    }
52724139Sjoerg
52824139Sjoerg    /* print warning if user requested more processes than we can display */
52924139Sjoerg    if (topn > max_topn)
53024139Sjoerg    {
53124139Sjoerg	fprintf(stderr,
53224139Sjoerg		"%s: warning: this terminal can only display %d processes.\n",
53324139Sjoerg		myname, max_topn);
53424139Sjoerg	warnings++;
53524139Sjoerg    }
53624139Sjoerg
53724139Sjoerg    /* adjust for topn == Infinity */
53824139Sjoerg    if (topn == Infinity)
53924139Sjoerg    {
54024139Sjoerg	/*
54124139Sjoerg	 *  For smart terminals, infinity really means everything that can
54224139Sjoerg	 *  be displayed, or Largest.
54324139Sjoerg	 *  On dumb terminals, infinity means every process in the system!
54424139Sjoerg	 *  We only really want to do that if it was explicitly specified.
54524139Sjoerg	 *  This is always the case when "Default_TOPN != Infinity".  But if
54624139Sjoerg	 *  topn wasn't explicitly specified and we are on a dumb terminal
54724139Sjoerg	 *  and the default is Infinity, then (and only then) we use
54824139Sjoerg	 *  "Nominal_TOPN" instead.
54924139Sjoerg	 */
55024139Sjoerg#if Default_TOPN == Infinity
55124139Sjoerg	topn = smart_terminal ? Largest :
55224139Sjoerg		    (topn_specified ? Largest : Nominal_TOPN);
55324139Sjoerg#else
55424139Sjoerg	topn = Largest;
55524139Sjoerg#endif
55624139Sjoerg    }
55724139Sjoerg
55824139Sjoerg    /* set header display accordingly */
55924139Sjoerg    display_header(topn > 0);
56024139Sjoerg
56124139Sjoerg    /* determine interactive state */
56224139Sjoerg    if (interactive == Maybe)
56324139Sjoerg    {
56424139Sjoerg	interactive = smart_terminal;
56524139Sjoerg    }
56624139Sjoerg
56724139Sjoerg    /* if # of displays not specified, fill it in */
56824139Sjoerg    if (displays == 0)
56924139Sjoerg    {
57024139Sjoerg	displays = smart_terminal ? Infinity : 1;
57124139Sjoerg    }
57224139Sjoerg
57324139Sjoerg    /* hold interrupt signals while setting up the screen and the handlers */
57424139Sjoerg#ifdef SIGHOLD
57524139Sjoerg    sighold(SIGINT);
57624139Sjoerg    sighold(SIGQUIT);
57724139Sjoerg    sighold(SIGTSTP);
57824139Sjoerg#else
57924139Sjoerg    old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));
58024139Sjoerg#endif
58124139Sjoerg    init_screen();
58224139Sjoerg    (void) signal(SIGINT, leave);
58324139Sjoerg    (void) signal(SIGQUIT, leave);
58424139Sjoerg    (void) signal(SIGTSTP, tstop);
58524139Sjoerg#ifdef SIGWINCH
58624139Sjoerg    (void) signal(SIGWINCH, winch);
58724139Sjoerg#endif
58824139Sjoerg#ifdef SIGRELSE
58924139Sjoerg    sigrelse(SIGINT);
59024139Sjoerg    sigrelse(SIGQUIT);
59124139Sjoerg    sigrelse(SIGTSTP);
59224139Sjoerg#else
59324139Sjoerg    (void) sigsetmask(old_sigmask);
59424139Sjoerg#endif
59524139Sjoerg    if (warnings)
59624139Sjoerg    {
59724139Sjoerg	fputs("....", stderr);
59824139Sjoerg	fflush(stderr);			/* why must I do this? */
59924139Sjoerg	sleep((unsigned)(3 * warnings));
60024139Sjoerg	fputc('\n', stderr);
60124139Sjoerg    }
60224139Sjoerg
60381187Skrisrestart:
60424139Sjoerg
60524139Sjoerg    /*
60624139Sjoerg     *  main loop -- repeat while display count is positive or while it
60724139Sjoerg     *		indicates infinity (by being -1)
60824139Sjoerg     */
60924139Sjoerg
61024139Sjoerg    while ((displays == -1) || (displays-- > 0))
61124139Sjoerg    {
612131402Salfred	int (*compare)();
613131402Salfred
614131402Salfred
61524139Sjoerg	/* get the current stats */
61624139Sjoerg	get_system_info(&system_info);
61724139Sjoerg
61824139Sjoerg#ifdef ORDER
619133817Salfred	compare = compares[order_index];
62024139Sjoerg#else
621131829Skeramida	if (displaymode == DISP_CPU)
622131402Salfred		compare = proc_compare;
623131829Skeramida	else
624131829Skeramida		compare = io_compare;
62524139Sjoerg#endif
62624139Sjoerg
627131402Salfred	/* get the current set of processes */
628131402Salfred	processes =
629131402Salfred		get_process_info(&system_info, &ps, compare);
630131402Salfred
63124139Sjoerg	/* display the load averages */
63224139Sjoerg	(*d_loadave)(system_info.last_pid,
63324139Sjoerg		     system_info.load_avg);
63424139Sjoerg
63524139Sjoerg	/* display the current time */
63624139Sjoerg	/* this method of getting the time SHOULD be fairly portable */
63724139Sjoerg	time(&curr_time);
63842447Sobrien	i_uptime(&system_info.boottime, &curr_time);
63924139Sjoerg	i_timeofday(&curr_time);
64024139Sjoerg
64124139Sjoerg	/* display process state breakdown */
64224139Sjoerg	(*d_procstates)(system_info.p_total,
64324139Sjoerg			system_info.procstates);
64424139Sjoerg
64524139Sjoerg	/* display the cpu state percentage breakdown */
64624139Sjoerg	if (dostates)	/* but not the first time */
64724139Sjoerg	{
64824139Sjoerg	    (*d_cpustates)(system_info.cpustates);
64924139Sjoerg	}
65024139Sjoerg	else
65124139Sjoerg	{
65224139Sjoerg	    /* we'll do it next time */
65324139Sjoerg	    if (smart_terminal)
65424139Sjoerg	    {
65524139Sjoerg		z_cpustates();
65624139Sjoerg	    }
65724139Sjoerg	    else
65824139Sjoerg	    {
65924139Sjoerg		putchar('\n');
66024139Sjoerg	    }
66124139Sjoerg	    dostates = Yes;
66224139Sjoerg	}
66324139Sjoerg
66424139Sjoerg	/* display memory stats */
66524139Sjoerg	(*d_memory)(system_info.memory);
666237656Sjhb	(*d_arc)(system_info.arc);
66724139Sjoerg
66824142Sjoerg	/* display swap stats */
66924142Sjoerg	(*d_swap)(system_info.swap);
67024142Sjoerg
67124139Sjoerg	/* handle message area */
67224139Sjoerg	(*d_message)();
67324139Sjoerg
67424139Sjoerg	/* update the header area */
67524139Sjoerg	(*d_header)(header_text);
67624139Sjoerg
67724139Sjoerg	if (topn > 0)
67824139Sjoerg	{
67924139Sjoerg	    /* determine number of processes to actually display */
68024139Sjoerg	    /* this number will be the smallest of:  active processes,
68124139Sjoerg	       number user requested, number current screen accomodates */
68289757Sdwmalone	    active_procs = system_info.P_ACTIVE;
68324139Sjoerg	    if (active_procs > topn)
68424139Sjoerg	    {
68524139Sjoerg		active_procs = topn;
68624139Sjoerg	    }
68724139Sjoerg	    if (active_procs > max_topn)
68824139Sjoerg	    {
68924139Sjoerg		active_procs = max_topn;
69024139Sjoerg	    }
69124139Sjoerg
69224139Sjoerg	    /* now show the top "n" processes. */
69324139Sjoerg	    for (i = 0; i < active_procs; i++)
69424139Sjoerg	    {
695168710Sstas		(*d_process)(i, format_next_process(processes, get_userid,
696168710Sstas			     fmt_flags));
69724139Sjoerg	    }
69824139Sjoerg	}
69924139Sjoerg	else
70024139Sjoerg	{
70124139Sjoerg	    i = 0;
70224139Sjoerg	}
70324139Sjoerg
70424139Sjoerg	/* do end-screen processing */
70524139Sjoerg	u_endscreen(i);
70624139Sjoerg
70724139Sjoerg	/* now, flush the output buffer */
70889757Sdwmalone	if (fflush(stdout) != 0)
70989757Sdwmalone	{
71089757Sdwmalone	    new_message(MT_standout, " Write error on stdout");
71189757Sdwmalone	    putchar('\r');
71289757Sdwmalone	    quit(1);
71389757Sdwmalone	    /*NOTREACHED*/
71489757Sdwmalone	}
71524139Sjoerg
71624139Sjoerg	/* only do the rest if we have more displays to show */
71724139Sjoerg	if (displays)
71824139Sjoerg	{
71924139Sjoerg	    /* switch out for new display on smart terminals */
72024139Sjoerg	    if (smart_terminal)
72124139Sjoerg	    {
72224139Sjoerg		if (overstrike)
72324139Sjoerg		{
72424139Sjoerg		    reset_display();
72524139Sjoerg		}
72624139Sjoerg		else
72724139Sjoerg		{
72824139Sjoerg		    d_loadave = u_loadave;
72924139Sjoerg		    d_procstates = u_procstates;
73024139Sjoerg		    d_cpustates = u_cpustates;
73124139Sjoerg		    d_memory = u_memory;
732237656Sjhb		    d_arc = u_arc;
73324142Sjoerg		    d_swap = u_swap;
73424139Sjoerg		    d_message = u_message;
73524139Sjoerg		    d_header = u_header;
73624139Sjoerg		    d_process = u_process;
73724139Sjoerg		}
73824139Sjoerg	    }
73924139Sjoerg
74024139Sjoerg	    no_command = Yes;
74124139Sjoerg	    if (!interactive)
74224139Sjoerg	    {
743232239Skib		sleep(delay);
744232660Skib		if (leaveflag) {
745232660Skib		    end_screen();
746232660Skib		    exit(0);
747232660Skib		}
74824139Sjoerg	    }
74924139Sjoerg	    else while (no_command)
75024139Sjoerg	    {
75124139Sjoerg		/* assume valid command unless told otherwise */
75224139Sjoerg		no_command = No;
75324139Sjoerg
75424139Sjoerg		/* set up arguments for select with timeout */
75524139Sjoerg		FD_ZERO(&readfds);
75689757Sdwmalone		FD_SET(0, &readfds);		/* for standard input */
75724139Sjoerg		timeout.tv_sec  = delay;
75824139Sjoerg		timeout.tv_usec = 0;
75924139Sjoerg
76081187Skris		if (leaveflag) {
76181187Skris		    end_screen();
76281187Skris		    exit(0);
76381187Skris		}
76481187Skris
76581187Skris		if (tstopflag) {
76681187Skris		    /* move to the lower left */
76781187Skris		    end_screen();
76881187Skris		    fflush(stdout);
76981187Skris
77081187Skris		    /* default the signal handler action */
77181187Skris		    (void) signal(SIGTSTP, SIG_DFL);
77281187Skris
77381187Skris		    /* unblock the signal and send ourselves one */
77481187Skris#ifdef SIGRELSE
77581187Skris		    sigrelse(SIGTSTP);
77681187Skris#else
77781187Skris		    (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
77881187Skris#endif
77981187Skris		    (void) kill(0, SIGTSTP);
78081187Skris
78181187Skris		    /* reset the signal handler */
78281187Skris		    (void) signal(SIGTSTP, tstop);
78381187Skris
78481187Skris		    /* reinit screen */
78581187Skris		    reinit_screen();
78681187Skris		    reset_display();
78781187Skris		    tstopflag = 0;
78881187Skris		    goto restart;
78981187Skris		}
79081187Skris
79181187Skris		if (winchflag) {
79281187Skris		    /* reascertain the screen dimensions */
79381187Skris		    get_screensize();
79481187Skris
79581187Skris		    /* tell display to resize */
79681187Skris		    max_topn = display_resize();
79781187Skris
79881187Skris		    /* reset the signal handler */
79981187Skris		    (void) signal(SIGWINCH, winch);
80081187Skris
80181187Skris		    reset_display();
80281187Skris		    winchflag = 0;
80381187Skris		    goto restart;
80481187Skris		}
80581187Skris
80624139Sjoerg		/* wait for either input or the end of the delay period */
80786042Sdwmalone		sel_ret = select(2, &readfds, NULL, NULL, &timeout);
80886042Sdwmalone		if (sel_ret < 0 && errno != EINTR)
80986042Sdwmalone		    quit(0);
81086042Sdwmalone		if (sel_ret > 0)
81124139Sjoerg		{
81224139Sjoerg		    int newval;
81324139Sjoerg		    char *errmsg;
81424139Sjoerg
81524139Sjoerg		    /* something to read -- clear the message area first */
81624139Sjoerg		    clear_message();
81724139Sjoerg
81824139Sjoerg		    /* now read it and convert to command strchr */
81924139Sjoerg		    /* (use "change" as a temporary to hold strchr) */
82086042Sdwmalone		    if (read(0, &ch, 1) != 1)
82189757Sdwmalone		    {
82289757Sdwmalone			/* read error: either 0 or -1 */
82389757Sdwmalone			new_message(MT_standout, " Read error on stdin");
82489757Sdwmalone			putchar('\r');
82589757Sdwmalone			quit(1);
82689757Sdwmalone			/*NOTREACHED*/
82789757Sdwmalone		    }
82824139Sjoerg		    if ((iptr = strchr(command_chars, ch)) == NULL)
82924139Sjoerg		    {
83024142Sjoerg			if (ch != '\r' && ch != '\n')
83124142Sjoerg			{
83224142Sjoerg			    /* illegal command */
83324142Sjoerg			    new_message(MT_standout, " Command not understood");
83424142Sjoerg			}
83524139Sjoerg			putchar('\r');
83624139Sjoerg			no_command = Yes;
83724139Sjoerg		    }
83824139Sjoerg		    else
83924139Sjoerg		    {
84024139Sjoerg			change = iptr - command_chars;
84124139Sjoerg			if (overstrike && change > CMD_OSLIMIT)
84224139Sjoerg			{
84324139Sjoerg			    /* error */
84424139Sjoerg			    new_message(MT_standout,
84524139Sjoerg			    " Command cannot be handled by this terminal");
84624139Sjoerg			    putchar('\r');
84724139Sjoerg			    no_command = Yes;
84824139Sjoerg			}
84924139Sjoerg			else switch(change)
85024139Sjoerg			{
85124139Sjoerg			    case CMD_redraw:	/* redraw screen */
85224139Sjoerg				reset_display();
85324139Sjoerg				break;
85424139Sjoerg
85524139Sjoerg			    case CMD_update:	/* merely update display */
85624139Sjoerg				/* is the load average high? */
85724139Sjoerg				if (system_info.load_avg[0] > LoadMax)
85824139Sjoerg				{
85924139Sjoerg				    /* yes, go home for visual feedback */
86024139Sjoerg				    go_home();
86124139Sjoerg				    fflush(stdout);
86224139Sjoerg				}
86324139Sjoerg				break;
86424139Sjoerg
86524139Sjoerg			    case CMD_quit:	/* quit */
86624139Sjoerg				quit(0);
86724139Sjoerg				/*NOTREACHED*/
86824139Sjoerg				break;
86924139Sjoerg
87024139Sjoerg			    case CMD_help1:	/* help */
87124139Sjoerg			    case CMD_help2:
87224139Sjoerg				reset_display();
87324139Sjoerg				clear();
87424139Sjoerg				show_help();
87524139Sjoerg				standout("Hit any key to continue: ");
87624139Sjoerg				fflush(stdout);
87724139Sjoerg				(void) read(0, &ch, 1);
87824139Sjoerg				break;
87924139Sjoerg
88024139Sjoerg			    case CMD_errors:	/* show errors */
88124139Sjoerg				if (error_count() == 0)
88224139Sjoerg				{
88324139Sjoerg				    new_message(MT_standout,
88424139Sjoerg					" Currently no errors to report.");
88524139Sjoerg				    putchar('\r');
88624139Sjoerg				    no_command = Yes;
88724139Sjoerg				}
88824139Sjoerg				else
88924139Sjoerg				{
89024139Sjoerg				    reset_display();
89124139Sjoerg				    clear();
89224139Sjoerg				    show_errors();
89324139Sjoerg				    standout("Hit any key to continue: ");
89424139Sjoerg				    fflush(stdout);
89524139Sjoerg				    (void) read(0, &ch, 1);
89624139Sjoerg				}
89724139Sjoerg				break;
89824139Sjoerg
89924139Sjoerg			    case CMD_number1:	/* new number */
90024139Sjoerg			    case CMD_number2:
90124139Sjoerg				new_message(MT_standout,
90224139Sjoerg				    "Number of processes to show: ");
90324139Sjoerg				newval = readline(tempbuf1, 8, Yes);
90424139Sjoerg				if (newval > -1)
90524139Sjoerg				{
90624139Sjoerg				    if (newval > max_topn)
90724139Sjoerg				    {
90824139Sjoerg					new_message(MT_standout | MT_delayed,
90924139Sjoerg					  " This terminal can only display %d processes.",
91024139Sjoerg					  max_topn);
91124139Sjoerg					putchar('\r');
91224139Sjoerg				    }
91324139Sjoerg
91424139Sjoerg				    if (newval == 0)
91524139Sjoerg				    {
91624139Sjoerg					/* inhibit the header */
91724139Sjoerg					display_header(No);
91824139Sjoerg				    }
91924139Sjoerg				    else if (newval > topn && topn == 0)
92024139Sjoerg				    {
92124139Sjoerg					/* redraw the header */
92224139Sjoerg					display_header(Yes);
92324139Sjoerg					d_header = i_header;
92424139Sjoerg				    }
92524139Sjoerg				    topn = newval;
92624139Sjoerg				}
92724139Sjoerg				break;
92824139Sjoerg
92924139Sjoerg			    case CMD_delay:	/* new seconds delay */
93024139Sjoerg				new_message(MT_standout, "Seconds to delay: ");
93124139Sjoerg				if ((i = readline(tempbuf1, 8, Yes)) > -1)
93224139Sjoerg				{
93389757Sdwmalone				    if ((delay = i) == 0 && getuid() != 0)
93489757Sdwmalone				    {
93589757Sdwmalone					delay = 1;
93689757Sdwmalone				    }
93724139Sjoerg				}
93824139Sjoerg				clear_message();
93924139Sjoerg				break;
94024139Sjoerg
94124139Sjoerg			    case CMD_displays:	/* change display count */
94224139Sjoerg				new_message(MT_standout,
94324139Sjoerg					"Displays to show (currently %s): ",
94424139Sjoerg					displays == -1 ? "infinite" :
94524139Sjoerg							 itoa(displays));
94624139Sjoerg				if ((i = readline(tempbuf1, 10, Yes)) > 0)
94724139Sjoerg				{
94824139Sjoerg				    displays = i;
94924139Sjoerg				}
95024139Sjoerg				else if (i == 0)
95124139Sjoerg				{
95224139Sjoerg				    quit(0);
95324139Sjoerg				}
95424139Sjoerg				clear_message();
95524139Sjoerg				break;
95624139Sjoerg
95724139Sjoerg			    case CMD_kill:	/* kill program */
95824139Sjoerg				new_message(0, "kill ");
95924139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
96024139Sjoerg				{
96124139Sjoerg				    if ((errmsg = kill_procs(tempbuf2)) != NULL)
96224139Sjoerg				    {
96366641Simp					new_message(MT_standout, "%s", errmsg);
96424139Sjoerg					putchar('\r');
96524139Sjoerg					no_command = Yes;
96624139Sjoerg				    }
96724139Sjoerg				}
96824139Sjoerg				else
96924139Sjoerg				{
97024139Sjoerg				    clear_message();
97124139Sjoerg				}
97224139Sjoerg				break;
97324139Sjoerg
97424139Sjoerg			    case CMD_renice:	/* renice program */
97524139Sjoerg				new_message(0, "renice ");
97624139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
97724139Sjoerg				{
97824139Sjoerg				    if ((errmsg = renice_procs(tempbuf2)) != NULL)
97924139Sjoerg				    {
98068293Simp					new_message(MT_standout, "%s", errmsg);
98124139Sjoerg					putchar('\r');
98224139Sjoerg					no_command = Yes;
98324139Sjoerg				    }
98424139Sjoerg				}
98524139Sjoerg				else
98624139Sjoerg				{
98724139Sjoerg				    clear_message();
98824139Sjoerg				}
98924139Sjoerg				break;
99024139Sjoerg
99124139Sjoerg			    case CMD_idletog:
99224139Sjoerg			    case CMD_idletog2:
99324139Sjoerg				ps.idle = !ps.idle;
99424139Sjoerg				new_message(MT_standout | MT_delayed,
99524139Sjoerg				    " %sisplaying idle processes.",
99624139Sjoerg				    ps.idle ? "D" : "Not d");
99724139Sjoerg				putchar('\r');
99824139Sjoerg				break;
99924139Sjoerg
100038090Sdes			    case CMD_selftog:
100138090Sdes				ps.self = (ps.self == -1) ? getpid() : -1;
100238090Sdes				new_message(MT_standout | MT_delayed,
100338090Sdes				    " %sisplaying self.",
100438090Sdes				    (ps.self == -1) ? "D" : "Not d");
100538090Sdes				putchar('\r');
100638090Sdes				break;
100738090Sdes
100824139Sjoerg			    case CMD_user:
100924139Sjoerg				new_message(MT_standout,
101024139Sjoerg				    "Username to show: ");
101124139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
101224139Sjoerg				{
101324139Sjoerg				    if (tempbuf2[0] == '+' &&
101424139Sjoerg					tempbuf2[1] == '\0')
101524139Sjoerg				    {
101624139Sjoerg					ps.uid = -1;
101724139Sjoerg				    }
101824139Sjoerg				    else if ((i = userid(tempbuf2)) == -1)
101924139Sjoerg				    {
102024139Sjoerg					new_message(MT_standout,
102124139Sjoerg					    " %s: unknown user", tempbuf2);
102224139Sjoerg					no_command = Yes;
102324139Sjoerg				    }
102424139Sjoerg				    else
102524139Sjoerg				    {
102624139Sjoerg					ps.uid = i;
102724139Sjoerg				    }
102824139Sjoerg				    putchar('\r');
102924139Sjoerg				}
103024139Sjoerg				else
103124139Sjoerg				{
103224139Sjoerg				    clear_message();
103324139Sjoerg				}
103424139Sjoerg				break;
103524139Sjoerg
1036117709Sjulian			    case CMD_thrtog:
1037117709Sjulian				ps.thread = !ps.thread;
1038117709Sjulian				new_message(MT_standout | MT_delayed,
1039223937Sjhb				    " Displaying threads %s",
1040145073Skeramida				    ps.thread ? "separately" : "as a count");
1041145073Skeramida				header_text = format_header(uname_field);
1042145073Skeramida				reset_display();
1043117709Sjulian				putchar('\r');
1044117709Sjulian				break;
1045146342Skeramida			    case CMD_wcputog:
1046146342Skeramida				ps.wcpu = !ps.wcpu;
1047146342Skeramida				new_message(MT_standout | MT_delayed,
1048224204Sjhb				    " Displaying %s CPU",
1049224204Sjhb				    ps.wcpu ? "weighted" : "raw");
1050146342Skeramida				header_text = format_header(uname_field);
1051146342Skeramida				reset_display();
1052146342Skeramida				putchar('\r');
1053146342Skeramida				break;
1054131402Salfred			    case CMD_viewtog:
1055131402Salfred				if (++displaymode == DISP_MAX)
1056131402Salfred					displaymode = 0;
1057131402Salfred				header_text = format_header(uname_field);
1058131402Salfred				display_header(Yes);
1059131402Salfred				d_header = i_header;
1060131402Salfred				reset_display();
1061131402Salfred				break;
1062132005Salfred			    case CMD_viewsys:
1063132005Salfred				ps.system = !ps.system;
1064132005Salfred				break;
1065168710Sstas			    case CMD_showargs:
1066168710Sstas				fmt_flags ^= FMT_SHOWARGS;
1067168710Sstas				break;
106824139Sjoerg#ifdef ORDER
106924139Sjoerg			    case CMD_order:
107024139Sjoerg				new_message(MT_standout,
107124139Sjoerg				    "Order to sort: ");
107224139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
107324139Sjoerg				{
107424139Sjoerg				  if ((i = string_index(tempbuf2, statics.order_names)) == -1)
107524139Sjoerg					{
107624139Sjoerg					  new_message(MT_standout,
107724139Sjoerg					      " %s: unrecognized sorting order", tempbuf2);
107824139Sjoerg					  no_command = Yes;
107924139Sjoerg				    }
108024139Sjoerg				    else
108124139Sjoerg				    {
108224139Sjoerg					order_index = i;
108324139Sjoerg				    }
108424139Sjoerg				    putchar('\r');
108524139Sjoerg				}
108624139Sjoerg				else
108724139Sjoerg				{
108824139Sjoerg				    clear_message();
108924139Sjoerg				}
109024139Sjoerg				break;
109124139Sjoerg#endif
1092168799Srafan			    case CMD_jidtog:
1093168799Srafan				ps.jail = !ps.jail;
1094168799Srafan				new_message(MT_standout | MT_delayed,
1095169257Srafan				    " %sisplaying jail ID.",
1096168799Srafan				    ps.jail ? "D" : "Not d");
1097168799Srafan				header_text = format_header(uname_field);
1098168799Srafan				reset_display();
1099168799Srafan				putchar('\r');
1100168799Srafan				break;
1101265249Sbdrewery
1102265249Sbdrewery			    case CMD_jail:
1103265249Sbdrewery				new_message(MT_standout,
1104265249Sbdrewery				    "Jail to show: ");
1105265249Sbdrewery				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
1106265249Sbdrewery				{
1107265249Sbdrewery				    if (tempbuf2[0] == '+' &&
1108265249Sbdrewery					tempbuf2[1] == '\0')
1109265249Sbdrewery				    {
1110265249Sbdrewery					ps.jid = -1;
1111265249Sbdrewery				    }
1112265249Sbdrewery				    else if ((i = jail_getid(tempbuf2)) == -1)
1113265249Sbdrewery				    {
1114265249Sbdrewery					new_message(MT_standout,
1115265249Sbdrewery					    " %s: unknown jail", tempbuf2);
1116265249Sbdrewery					no_command = Yes;
1117265249Sbdrewery				    }
1118265249Sbdrewery				    else
1119265249Sbdrewery				    {
1120265249Sbdrewery					ps.jid = i;
1121265249Sbdrewery				    }
1122265249Sbdrewery				    if (ps.jail == 0) {
1123265249Sbdrewery					    ps.jail = 1;
1124265249Sbdrewery					    new_message(MT_standout |
1125265249Sbdrewery						MT_delayed, " Displaying jail "
1126265249Sbdrewery						"ID.");
1127265249Sbdrewery					    header_text =
1128265249Sbdrewery						format_header(uname_field);
1129265249Sbdrewery					    reset_display();
1130265249Sbdrewery				    }
1131265249Sbdrewery				    putchar('\r');
1132265249Sbdrewery				}
1133265249Sbdrewery				else
1134265249Sbdrewery				{
1135265249Sbdrewery				    clear_message();
1136265249Sbdrewery				}
1137265249Sbdrewery				break;
1138265249Sbdrewery
1139222530Sjhb			    case CMD_kidletog:
1140222530Sjhb				ps.kidle = !ps.kidle;
1141222530Sjhb				new_message(MT_standout | MT_delayed,
1142222530Sjhb				    " %sisplaying system idle process.",
1143222530Sjhb				    ps.kidle ? "D" : "Not d");
1144222530Sjhb				putchar('\r');
1145222530Sjhb				break;
1146223936Sjhb			    case CMD_pcputog:
1147223936Sjhb				pcpu_stats = !pcpu_stats;
1148223936Sjhb				new_message(MT_standout | MT_delayed,
1149223936Sjhb				    " Displaying %sCPU statistics.",
1150223936Sjhb				    pcpu_stats ? "per-" : "global ");
1151224205Sjhb				toggle_pcpustats();
1152223936Sjhb				max_topn = display_updatecpus(&statics);
1153223936Sjhb				reset_display();
1154223936Sjhb				putchar('\r');
1155223936Sjhb				break;
115624139Sjoerg			    default:
115724139Sjoerg				new_message(MT_standout, " BAD CASE IN SWITCH!");
115824139Sjoerg				putchar('\r');
115924139Sjoerg			}
116024139Sjoerg		    }
116124139Sjoerg
116224139Sjoerg		    /* flush out stuff that may have been written */
116324139Sjoerg		    fflush(stdout);
116424139Sjoerg		}
116524139Sjoerg	    }
116624139Sjoerg	}
116724139Sjoerg    }
116824139Sjoerg
116989757Sdwmalone#ifdef DEBUG
117089757Sdwmalone    fclose(debug);
117189757Sdwmalone#endif
117224139Sjoerg    quit(0);
117324139Sjoerg    /*NOTREACHED*/
117424139Sjoerg}
117524139Sjoerg
117624139Sjoerg/*
117724139Sjoerg *  reset_display() - reset all the display routine pointers so that entire
117824139Sjoerg *	screen will get redrawn.
117924139Sjoerg */
118024139Sjoerg
118124139Sjoergreset_display()
118224139Sjoerg
118324139Sjoerg{
118424139Sjoerg    d_loadave    = i_loadave;
118524139Sjoerg    d_procstates = i_procstates;
118624139Sjoerg    d_cpustates  = i_cpustates;
118724139Sjoerg    d_memory     = i_memory;
1188237656Sjhb    d_arc        = i_arc;
118924142Sjoerg    d_swap       = i_swap;
119024139Sjoerg    d_message	 = i_message;
119124139Sjoerg    d_header	 = i_header;
119224139Sjoerg    d_process	 = i_process;
119324139Sjoerg}
119424139Sjoerg
119524139Sjoerg/*
119624139Sjoerg *  signal handlers
119724139Sjoerg */
119824139Sjoerg
119924139Sjoergsigret_t leave()	/* exit under normal conditions -- INT handler */
120024139Sjoerg
120124139Sjoerg{
120281187Skris    leaveflag = 1;
120324139Sjoerg}
120424139Sjoerg
120524139Sjoergsigret_t tstop(i)	/* SIGTSTP handler */
120624139Sjoerg
120724139Sjoergint i;
120824139Sjoerg
120924139Sjoerg{
121081187Skris    tstopflag = 1;
121124139Sjoerg}
121224139Sjoerg
121324139Sjoerg#ifdef SIGWINCH
121424139Sjoergsigret_t winch(i)		/* SIGWINCH handler */
121524139Sjoerg
121624139Sjoergint i;
121724139Sjoerg
121824139Sjoerg{
121981187Skris    winchflag = 1;
122024139Sjoerg}
122124139Sjoerg#endif
122224139Sjoerg
122324139Sjoergvoid quit(status)		/* exit under duress */
122424139Sjoerg
122524139Sjoergint status;
122624139Sjoerg
122724139Sjoerg{
122824139Sjoerg    end_screen();
122924139Sjoerg    exit(status);
123024139Sjoerg    /*NOTREACHED*/
123124139Sjoerg}
1232