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$
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"
37301836Sngie
38266280Sbdrewery#include <sys/jail.h>
3924139Sjoerg#include <sys/time.h>
40301836Sngie
41301836Sngie#include <ctype.h>
42301836Sngie#include <errno.h>
43266280Sbdrewery#include <jail.h>
44301836Sngie#include <setjmp.h>
45301836Sngie#include <signal.h>
46301836Sngie#include <unistd.h>
4724139Sjoerg
4824139Sjoerg/* includes specific to top */
49301836Sngie#include "commands.h"
5024139Sjoerg#include "display.h"		/* interface to display package */
5124139Sjoerg#include "screen.h"		/* interface to screen package */
5224139Sjoerg#include "top.h"
5324139Sjoerg#include "top.local.h"
5424139Sjoerg#include "boolean.h"
5524139Sjoerg#include "machine.h"
5624139Sjoerg#include "utils.h"
57301836Sngie#include "username.h"
5824139Sjoerg
5924139Sjoerg/* Size of the stdio buffer given to stdout */
6024139Sjoerg#define Buffersize	2048
6124139Sjoerg
6224139Sjoerg/* The buffer that stdio will use */
6324139Sjoergchar stdoutbuf[Buffersize];
6424139Sjoerg
6524139Sjoerg/* build Signal masks */
6624139Sjoerg#define Smask(s)	(1 << ((s) - 1))
6724139Sjoerg
6824139Sjoerg/* for getopt: */
6924139Sjoergextern int  optind;
7024139Sjoergextern char *optarg;
7124139Sjoerg
7224139Sjoerg/* imported from screen.c */
7324139Sjoergextern int overstrike;
7424139Sjoerg
75168710Sstasstatic int fmt_flags = 0;
76175420Speterint pcpu_stats = No;
77168710Sstas
7824139Sjoerg/* signal handling routines */
7924139Sjoergsigret_t leave();
8024139Sjoergsigret_t tstop();
8124139Sjoerg#ifdef SIGWINCH
8224139Sjoergsigret_t winch();
8324139Sjoerg#endif
8424139Sjoerg
8581187Skrisvolatile sig_atomic_t leaveflag;
8681187Skrisvolatile sig_atomic_t tstopflag;
8781187Skrisvolatile sig_atomic_t winchflag;
8881187Skris
8924139Sjoerg/* internal routines */
9024139Sjoergvoid quit();
9124139Sjoerg
9224139Sjoerg/* values which need to be accessed by signal handlers */
9324139Sjoergstatic int max_topn;		/* maximum displayable processes */
9424139Sjoerg
9524139Sjoerg/* miscellaneous things */
96145073Skeramidastruct process_select ps;
9724139Sjoergchar *myname = "top";
9824139Sjoergjmp_buf jmp_int;
9924139Sjoerg
10024139Sjoerg/* routines that don't return int */
10124139Sjoerg
10224139Sjoergchar *username();
10324139Sjoergchar *ctime();
10424139Sjoergchar *kill_procs();
10524139Sjoergchar *renice_procs();
10624139Sjoerg
10724139Sjoerg#ifdef ORDER
108133817Salfredextern int (*compares[])();
10924139Sjoerg#else
11024139Sjoergextern int proc_compare();
111131829Skeramidaextern int io_compare();
11224139Sjoerg#endif
11324139Sjoergtime_t time();
11424139Sjoerg
11524139Sjoergcaddr_t get_process_info();
11624139Sjoerg
11724139Sjoerg/* different routines for displaying the user's identification */
11824139Sjoerg/* (values assigned to get_userid) */
11924139Sjoergchar *username();
12024139Sjoergchar *itoa7();
12124139Sjoerg
12224139Sjoerg/* pointers to display routines */
123301836Sngievoid (*d_loadave)() = i_loadave;
124301836Sngievoid (*d_procstates)() = i_procstates;
125301836Sngievoid (*d_cpustates)() = i_cpustates;
126301836Sngievoid (*d_memory)() = i_memory;
127301836Sngievoid (*d_arc)() = i_arc;
128301836Sngievoid (*d_swap)() = i_swap;
129301836Sngievoid (*d_message)() = i_message;
130301836Sngievoid (*d_header)() = i_header;
131301836Sngievoid (*d_process)() = i_process;
13224139Sjoerg
133301836Sngievoid reset_display(void);
13424139Sjoerg
135301836Sngie
136301836Sngieint
13724139Sjoergmain(argc, argv)
13824139Sjoerg
13924139Sjoergint  argc;
14024139Sjoergchar *argv[];
14124139Sjoerg
14224139Sjoerg{
14324139Sjoerg    register int i;
14424139Sjoerg    register int active_procs;
14524139Sjoerg    register int change;
14624139Sjoerg
14724139Sjoerg    struct system_info system_info;
14824139Sjoerg    struct statics statics;
14924139Sjoerg    caddr_t processes;
15024139Sjoerg
15124139Sjoerg    static char tempbuf1[50];
15224139Sjoerg    static char tempbuf2[50];
15324139Sjoerg    int old_sigmask;		/* only used for BSD-style signals */
15424139Sjoerg    int topn = Default_TOPN;
15524139Sjoerg    int delay = Default_DELAY;
15624139Sjoerg    int displays = 0;		/* indicates unspecified */
15786042Sdwmalone    int sel_ret = 0;
15824139Sjoerg    time_t curr_time;
15924139Sjoerg    char *(*get_userid)() = username;
16024139Sjoerg    char *uname_field = "USERNAME";
16124139Sjoerg    char *header_text;
16224139Sjoerg    char *env_top;
16324139Sjoerg    char **preset_argv;
16424139Sjoerg    int  preset_argc = 0;
16524139Sjoerg    char **av;
16624139Sjoerg    int  ac;
16724139Sjoerg    char dostates = No;
16824139Sjoerg    char do_unames = Yes;
16924139Sjoerg    char interactive = Maybe;
17024139Sjoerg    char warnings = 0;
17124139Sjoerg#if Default_TOPN == Infinity
17224139Sjoerg    char topn_specified = No;
17324139Sjoerg#endif
17424139Sjoerg    char ch;
17524139Sjoerg    char *iptr;
17624139Sjoerg    char no_command = 1;
17724139Sjoerg    struct timeval timeout;
17824139Sjoerg#ifdef ORDER
17924139Sjoerg    char *order_name = NULL;
18024139Sjoerg    int order_index = 0;
18124139Sjoerg#endif
18224139Sjoerg#ifndef FD_SET
18324139Sjoerg    /* FD_SET and friends are not present:  fake it */
18424139Sjoerg    typedef int fd_set;
18524139Sjoerg#define FD_ZERO(x)     (*(x) = 0)
18689757Sdwmalone#define FD_SET(f, x)   (*(x) = 1<<f)
18724139Sjoerg#endif
18824139Sjoerg    fd_set readfds;
18924139Sjoerg
19024139Sjoerg#ifdef ORDER
191266280Sbdrewery    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJo";
19224139Sjoerg#else
193266280Sbdrewery    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJ";
19424139Sjoerg#endif
19524139Sjoerg/* these defines enumerate the "strchr"s of the commands in command_chars */
19624139Sjoerg#define CMD_redraw	0
19724139Sjoerg#define CMD_update	1
19824139Sjoerg#define CMD_quit	2
19924139Sjoerg#define CMD_help1	3
20024139Sjoerg#define CMD_help2	4
20124139Sjoerg#define CMD_OSLIMIT	4    /* terminals with OS can only handle commands */
20224139Sjoerg#define CMD_errors	5    /* less than or equal to CMD_OSLIMIT	   */
20324139Sjoerg#define CMD_number1	6
20424139Sjoerg#define CMD_number2	7
20524139Sjoerg#define CMD_delay	8
20624139Sjoerg#define CMD_displays	9
20724139Sjoerg#define CMD_kill	10
20824139Sjoerg#define CMD_renice	11
20924139Sjoerg#define CMD_idletog     12
21024139Sjoerg#define CMD_idletog2    13
21124139Sjoerg#define CMD_user	14
21238090Sdes#define CMD_selftog	15
213117709Sjulian#define CMD_thrtog	16
214131402Salfred#define CMD_viewtog	17
215132005Salfred#define CMD_viewsys	18
216146342Skeramida#define	CMD_wcputog	19
217168710Sstas#define	CMD_showargs	20
218168799Srafan#define	CMD_jidtog	21
219222530Sjhb#define CMD_kidletog	22
220223936Sjhb#define CMD_pcputog	23
221266280Sbdrewery#define CMD_jail	24
22224139Sjoerg#ifdef ORDER
223266280Sbdrewery#define CMD_order       25
22424139Sjoerg#endif
22524139Sjoerg
22624139Sjoerg    /* set the buffer for stdout */
22724139Sjoerg#ifdef DEBUG
22889757Sdwmalone    extern FILE *debug;
22989757Sdwmalone    debug = fopen("debug.run", "w");
23024139Sjoerg    setbuffer(stdout, NULL, 0);
23124139Sjoerg#else
23224139Sjoerg    setbuffer(stdout, stdoutbuf, Buffersize);
23324139Sjoerg#endif
23424139Sjoerg
23524139Sjoerg    /* get our name */
23624139Sjoerg    if (argc > 0)
23724139Sjoerg    {
23824139Sjoerg	if ((myname = strrchr(argv[0], '/')) == 0)
23924139Sjoerg	{
24024139Sjoerg	    myname = argv[0];
24124139Sjoerg	}
24224139Sjoerg	else
24324139Sjoerg	{
24424139Sjoerg	    myname++;
24524139Sjoerg	}
24624139Sjoerg    }
24724139Sjoerg
24824139Sjoerg    /* initialize some selection options */
24924139Sjoerg    ps.idle    = Yes;
25038090Sdes    ps.self    = -1;
25124139Sjoerg    ps.system  = No;
25224139Sjoerg    ps.uid     = -1;
253117709Sjulian    ps.thread  = No;
254146342Skeramida    ps.wcpu    = 1;
255266280Sbdrewery    ps.jid     = -1;
256168799Srafan    ps.jail    = No;
257222530Sjhb    ps.kidle   = Yes;
25824139Sjoerg    ps.command = NULL;
25924139Sjoerg
26024139Sjoerg    /* get preset options from the environment */
26124139Sjoerg    if ((env_top = getenv("TOP")) != NULL)
26224139Sjoerg    {
26324139Sjoerg	av = preset_argv = argparse(env_top, &preset_argc);
26424139Sjoerg	ac = preset_argc;
26524139Sjoerg
26624139Sjoerg	/* set the dummy argument to an explanatory message, in case
26724139Sjoerg	   getopt encounters a bad argument */
26824139Sjoerg	preset_argv[0] = "while processing environment";
26924139Sjoerg    }
27024139Sjoerg
27124139Sjoerg    /* process options */
27224139Sjoerg    do {
27324139Sjoerg	/* if we're done doing the presets, then process the real arguments */
27424139Sjoerg	if (preset_argc == 0)
27524139Sjoerg	{
27624139Sjoerg	    ac = argc;
27724139Sjoerg	    av = argv;
27824139Sjoerg
27924139Sjoerg	    /* this should keep getopt happy... */
28024139Sjoerg	    optind = 1;
28124139Sjoerg	}
28224139Sjoerg
283266280Sbdrewery	while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:t")) != EOF)
28424139Sjoerg	{
28524139Sjoerg	    switch(i)
28624139Sjoerg	    {
28789757Sdwmalone	      case 'v':			/* show version number */
28889757Sdwmalone		fprintf(stderr, "%s: version %s\n",
28989757Sdwmalone			myname, version_string());
29089757Sdwmalone		exit(1);
29189757Sdwmalone		break;
29289757Sdwmalone
29324139Sjoerg	      case 'u':			/* toggle uid/username display */
29424139Sjoerg		do_unames = !do_unames;
29524139Sjoerg		break;
29624139Sjoerg
29724139Sjoerg	      case 'U':			/* display only username's processes */
29824139Sjoerg		if ((ps.uid = userid(optarg)) == -1)
29924139Sjoerg		{
30024139Sjoerg		    fprintf(stderr, "%s: unknown user\n", optarg);
30124139Sjoerg		    exit(1);
30224139Sjoerg		}
30324139Sjoerg		break;
30424139Sjoerg
30524139Sjoerg	      case 'S':			/* show system processes */
30624139Sjoerg		ps.system = !ps.system;
30724139Sjoerg		break;
30824139Sjoerg
30924139Sjoerg	      case 'I':                   /* show idle processes */
31024139Sjoerg		ps.idle = !ps.idle;
31124139Sjoerg		break;
31224139Sjoerg
31324139Sjoerg	      case 'i':			/* go interactive regardless */
31424139Sjoerg		interactive = Yes;
31524139Sjoerg		break;
31624139Sjoerg
31724139Sjoerg	      case 'n':			/* batch, or non-interactive */
31824139Sjoerg	      case 'b':
31924139Sjoerg		interactive = No;
32024139Sjoerg		break;
32124139Sjoerg
322168710Sstas	      case 'a':
323168710Sstas		fmt_flags ^= FMT_SHOWARGS;
324168710Sstas		break;
325168710Sstas
32624139Sjoerg	      case 'd':			/* number of displays to show */
32724139Sjoerg		if ((i = atoiwi(optarg)) == Invalid || i == 0)
32824139Sjoerg		{
32924139Sjoerg		    fprintf(stderr,
33024139Sjoerg			"%s: warning: display count should be positive -- option ignored\n",
33124139Sjoerg			myname);
33224139Sjoerg		    warnings++;
33324139Sjoerg		}
33424139Sjoerg		else
33524139Sjoerg		{
33624139Sjoerg		    displays = i;
33724139Sjoerg		}
33824139Sjoerg		break;
33924139Sjoerg
34024139Sjoerg	      case 's':
34189757Sdwmalone		if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
34224139Sjoerg		{
34324139Sjoerg		    fprintf(stderr,
34489757Sdwmalone			"%s: warning: seconds delay should be positive -- using default\n",
34524139Sjoerg			myname);
34624139Sjoerg		    delay = Default_DELAY;
34724139Sjoerg		    warnings++;
34824139Sjoerg		}
34924139Sjoerg		break;
35024139Sjoerg
35124139Sjoerg	      case 'q':		/* be quick about it */
35224139Sjoerg		/* only allow this if user is really root */
35324139Sjoerg		if (getuid() == 0)
35424139Sjoerg		{
35524139Sjoerg		    /* be very un-nice! */
35624139Sjoerg		    (void) nice(-20);
35724139Sjoerg		}
35824139Sjoerg		else
35924139Sjoerg		{
36024139Sjoerg		    fprintf(stderr,
36124139Sjoerg			"%s: warning: `-q' option can only be used by root\n",
36224139Sjoerg			myname);
36324139Sjoerg		    warnings++;
36424139Sjoerg		}
36524139Sjoerg		break;
36624139Sjoerg
367131616Sdes	      case 'm':		/* select display mode */
368131402Salfred		if (strcmp(optarg, "io") == 0) {
369131402Salfred			displaymode = DISP_IO;
370131402Salfred		} else if (strcmp(optarg, "cpu") == 0) {
371131402Salfred			displaymode = DISP_CPU;
372131402Salfred		} else {
373131402Salfred			fprintf(stderr,
374131402Salfred			"%s: warning: `-m' option can only take args "
375131402Salfred			"'io' or 'cpu'\n",
376131402Salfred			myname);
377131402Salfred			exit(1);
378131402Salfred		}
379131402Salfred		break;
380131402Salfred
38124139Sjoerg	      case 'o':		/* select sort order */
38224139Sjoerg#ifdef ORDER
38324139Sjoerg		order_name = optarg;
38424139Sjoerg#else
38524139Sjoerg		fprintf(stderr,
38624139Sjoerg			"%s: this platform does not support arbitrary ordering.  Sorry.\n",
38724139Sjoerg			myname);
38824139Sjoerg		warnings++;
38924139Sjoerg#endif
39024139Sjoerg		break;
39124139Sjoerg
39238090Sdes	      case 't':
39338090Sdes		ps.self = (ps.self == -1) ? getpid() : -1;
39438090Sdes		break;
395146342Skeramida
396146342Skeramida	      case 'C':
397146342Skeramida		ps.wcpu = !ps.wcpu;
398146342Skeramida		break;
399146342Skeramida
400117709Sjulian	      case 'H':
401117709Sjulian		ps.thread = !ps.thread;
402117709Sjulian		break;
403146342Skeramida
404168799Srafan	      case 'j':
405168799Srafan		ps.jail = !ps.jail;
406168799Srafan		break;
407168799Srafan
408266280Sbdrewery	      case 'J':			/* display only jail's processes */
409266280Sbdrewery		if ((ps.jid = jail_getid(optarg)) == -1)
410266280Sbdrewery		{
411266280Sbdrewery		    fprintf(stderr, "%s: unknown jail\n", optarg);
412266280Sbdrewery		    exit(1);
413266280Sbdrewery		}
414266280Sbdrewery		ps.jail = 1;
415266280Sbdrewery		break;
416266280Sbdrewery
417175420Speter	      case 'P':
418223936Sjhb		pcpu_stats = !pcpu_stats;
419175420Speter		break;
420175420Speter
421222530Sjhb	      case 'z':
422222530Sjhb		ps.kidle = !ps.kidle;
423222530Sjhb		break;
424222530Sjhb
42524139Sjoerg	      default:
426157842Sru		fprintf(stderr,
427157842Sru"Top version %s\n"
428222530Sjhb"Usage: %s [-abCHIijnPqStuvz] [-d count] [-m io | cpu] [-o field] [-s time]\n"
429266280Sbdrewery"       [-J jail] [-U username] [number]\n",
43024139Sjoerg			version_string(), myname);
43124139Sjoerg		exit(1);
43224139Sjoerg	    }
43324139Sjoerg	}
43424139Sjoerg
43524139Sjoerg	/* get count of top processes to display (if any) */
43624139Sjoerg	if (optind < ac)
43724139Sjoerg	{
43824139Sjoerg	    if ((topn = atoiwi(av[optind])) == Invalid)
43924139Sjoerg	    {
44024139Sjoerg		fprintf(stderr,
44124139Sjoerg			"%s: warning: process display count should be non-negative -- using default\n",
44224139Sjoerg			myname);
44324139Sjoerg		warnings++;
44424139Sjoerg	    }
44524139Sjoerg#if Default_TOPN == Infinity
44624139Sjoerg            else
44724139Sjoerg	    {
44824139Sjoerg		topn_specified = Yes;
44924139Sjoerg	    }
45024139Sjoerg#endif
45124139Sjoerg	}
45224139Sjoerg
45324139Sjoerg	/* tricky:  remember old value of preset_argc & set preset_argc = 0 */
45424139Sjoerg	i = preset_argc;
45524139Sjoerg	preset_argc = 0;
45624139Sjoerg
45724139Sjoerg    /* repeat only if we really did the preset arguments */
45824139Sjoerg    } while (i != 0);
45924139Sjoerg
46024139Sjoerg    /* set constants for username/uid display correctly */
46124139Sjoerg    if (!do_unames)
46224139Sjoerg    {
46324139Sjoerg	uname_field = "   UID  ";
46424139Sjoerg	get_userid = itoa7;
46524139Sjoerg    }
46624139Sjoerg
46724139Sjoerg    /* initialize the kernel memory interface */
468175195Sobrien    if (machine_init(&statics, do_unames) == -1)
46924139Sjoerg    {
47024139Sjoerg	exit(1);
47124139Sjoerg    }
47224139Sjoerg
47324139Sjoerg#ifdef ORDER
47424139Sjoerg    /* determine sorting order index, if necessary */
47524139Sjoerg    if (order_name != NULL)
47624139Sjoerg    {
47724139Sjoerg	if ((order_index = string_index(order_name, statics.order_names)) == -1)
47824139Sjoerg	{
47924139Sjoerg	    char **pp;
48024139Sjoerg
48124139Sjoerg	    fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
48224139Sjoerg		    myname, order_name);
48324139Sjoerg	    fprintf(stderr, "\tTry one of these:");
48424139Sjoerg	    pp = statics.order_names;
48524139Sjoerg	    while (*pp != NULL)
48624139Sjoerg	    {
48724139Sjoerg		fprintf(stderr, " %s", *pp++);
48824139Sjoerg	    }
48924139Sjoerg	    fputc('\n', stderr);
49024139Sjoerg	    exit(1);
49124139Sjoerg	}
49224139Sjoerg    }
49324139Sjoerg#endif
49424139Sjoerg
49524139Sjoerg#ifdef no_initialization_needed
49624139Sjoerg    /* initialize the hashing stuff */
49724139Sjoerg    if (do_unames)
49824139Sjoerg    {
49924139Sjoerg	init_hash();
50024139Sjoerg    }
50124139Sjoerg#endif
50224139Sjoerg
50324139Sjoerg    /* initialize termcap */
50424139Sjoerg    init_termcap(interactive);
50524139Sjoerg
50624139Sjoerg    /* get the string to use for the process area header */
50724139Sjoerg    header_text = format_header(uname_field);
50824139Sjoerg
50924139Sjoerg    /* initialize display interface */
51024139Sjoerg    if ((max_topn = display_init(&statics)) == -1)
51124139Sjoerg    {
51224139Sjoerg	fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);
51324139Sjoerg	exit(4);
51424139Sjoerg    }
51524139Sjoerg
51624139Sjoerg    /* print warning if user requested more processes than we can display */
51724139Sjoerg    if (topn > max_topn)
51824139Sjoerg    {
51924139Sjoerg	fprintf(stderr,
52024139Sjoerg		"%s: warning: this terminal can only display %d processes.\n",
52124139Sjoerg		myname, max_topn);
52224139Sjoerg	warnings++;
52324139Sjoerg    }
52424139Sjoerg
52524139Sjoerg    /* adjust for topn == Infinity */
52624139Sjoerg    if (topn == Infinity)
52724139Sjoerg    {
52824139Sjoerg	/*
52924139Sjoerg	 *  For smart terminals, infinity really means everything that can
53024139Sjoerg	 *  be displayed, or Largest.
53124139Sjoerg	 *  On dumb terminals, infinity means every process in the system!
53224139Sjoerg	 *  We only really want to do that if it was explicitly specified.
53324139Sjoerg	 *  This is always the case when "Default_TOPN != Infinity".  But if
53424139Sjoerg	 *  topn wasn't explicitly specified and we are on a dumb terminal
53524139Sjoerg	 *  and the default is Infinity, then (and only then) we use
53624139Sjoerg	 *  "Nominal_TOPN" instead.
53724139Sjoerg	 */
53824139Sjoerg#if Default_TOPN == Infinity
53924139Sjoerg	topn = smart_terminal ? Largest :
54024139Sjoerg		    (topn_specified ? Largest : Nominal_TOPN);
54124139Sjoerg#else
54224139Sjoerg	topn = Largest;
54324139Sjoerg#endif
54424139Sjoerg    }
54524139Sjoerg
54624139Sjoerg    /* set header display accordingly */
54724139Sjoerg    display_header(topn > 0);
54824139Sjoerg
54924139Sjoerg    /* determine interactive state */
55024139Sjoerg    if (interactive == Maybe)
55124139Sjoerg    {
55224139Sjoerg	interactive = smart_terminal;
55324139Sjoerg    }
55424139Sjoerg
55524139Sjoerg    /* if # of displays not specified, fill it in */
55624139Sjoerg    if (displays == 0)
55724139Sjoerg    {
55824139Sjoerg	displays = smart_terminal ? Infinity : 1;
55924139Sjoerg    }
56024139Sjoerg
56124139Sjoerg    /* hold interrupt signals while setting up the screen and the handlers */
56224139Sjoerg#ifdef SIGHOLD
56324139Sjoerg    sighold(SIGINT);
56424139Sjoerg    sighold(SIGQUIT);
56524139Sjoerg    sighold(SIGTSTP);
56624139Sjoerg#else
56724139Sjoerg    old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));
56824139Sjoerg#endif
56924139Sjoerg    init_screen();
57024139Sjoerg    (void) signal(SIGINT, leave);
57124139Sjoerg    (void) signal(SIGQUIT, leave);
57224139Sjoerg    (void) signal(SIGTSTP, tstop);
57324139Sjoerg#ifdef SIGWINCH
57424139Sjoerg    (void) signal(SIGWINCH, winch);
57524139Sjoerg#endif
57624139Sjoerg#ifdef SIGRELSE
57724139Sjoerg    sigrelse(SIGINT);
57824139Sjoerg    sigrelse(SIGQUIT);
57924139Sjoerg    sigrelse(SIGTSTP);
58024139Sjoerg#else
58124139Sjoerg    (void) sigsetmask(old_sigmask);
58224139Sjoerg#endif
58324139Sjoerg    if (warnings)
58424139Sjoerg    {
58524139Sjoerg	fputs("....", stderr);
58624139Sjoerg	fflush(stderr);			/* why must I do this? */
58724139Sjoerg	sleep((unsigned)(3 * warnings));
58824139Sjoerg	fputc('\n', stderr);
58924139Sjoerg    }
59024139Sjoerg
59181187Skrisrestart:
59224139Sjoerg
59324139Sjoerg    /*
59424139Sjoerg     *  main loop -- repeat while display count is positive or while it
59524139Sjoerg     *		indicates infinity (by being -1)
59624139Sjoerg     */
59724139Sjoerg
59824139Sjoerg    while ((displays == -1) || (displays-- > 0))
59924139Sjoerg    {
600131402Salfred	int (*compare)();
601131402Salfred
602131402Salfred
60324139Sjoerg	/* get the current stats */
60424139Sjoerg	get_system_info(&system_info);
60524139Sjoerg
60624139Sjoerg#ifdef ORDER
607133817Salfred	compare = compares[order_index];
60824139Sjoerg#else
609131829Skeramida	if (displaymode == DISP_CPU)
610131402Salfred		compare = proc_compare;
611131829Skeramida	else
612131829Skeramida		compare = io_compare;
61324139Sjoerg#endif
61424139Sjoerg
615131402Salfred	/* get the current set of processes */
616131402Salfred	processes =
617131402Salfred		get_process_info(&system_info, &ps, compare);
618131402Salfred
61924139Sjoerg	/* display the load averages */
62024139Sjoerg	(*d_loadave)(system_info.last_pid,
62124139Sjoerg		     system_info.load_avg);
62224139Sjoerg
62324139Sjoerg	/* display the current time */
62424139Sjoerg	/* this method of getting the time SHOULD be fairly portable */
62524139Sjoerg	time(&curr_time);
62642447Sobrien	i_uptime(&system_info.boottime, &curr_time);
62724139Sjoerg	i_timeofday(&curr_time);
62824139Sjoerg
62924139Sjoerg	/* display process state breakdown */
63024139Sjoerg	(*d_procstates)(system_info.p_total,
63124139Sjoerg			system_info.procstates);
63224139Sjoerg
63324139Sjoerg	/* display the cpu state percentage breakdown */
63424139Sjoerg	if (dostates)	/* but not the first time */
63524139Sjoerg	{
63624139Sjoerg	    (*d_cpustates)(system_info.cpustates);
63724139Sjoerg	}
63824139Sjoerg	else
63924139Sjoerg	{
64024139Sjoerg	    /* we'll do it next time */
64124139Sjoerg	    if (smart_terminal)
64224139Sjoerg	    {
64324139Sjoerg		z_cpustates();
64424139Sjoerg	    }
64524139Sjoerg	    else
64624139Sjoerg	    {
64724139Sjoerg		putchar('\n');
64824139Sjoerg	    }
64924139Sjoerg	    dostates = Yes;
65024139Sjoerg	}
65124139Sjoerg
65224139Sjoerg	/* display memory stats */
65324139Sjoerg	(*d_memory)(system_info.memory);
654237656Sjhb	(*d_arc)(system_info.arc);
65524139Sjoerg
65624142Sjoerg	/* display swap stats */
65724142Sjoerg	(*d_swap)(system_info.swap);
65824142Sjoerg
65924139Sjoerg	/* handle message area */
66024139Sjoerg	(*d_message)();
66124139Sjoerg
66224139Sjoerg	/* update the header area */
66324139Sjoerg	(*d_header)(header_text);
66424139Sjoerg
66524139Sjoerg	if (topn > 0)
66624139Sjoerg	{
66724139Sjoerg	    /* determine number of processes to actually display */
66824139Sjoerg	    /* this number will be the smallest of:  active processes,
66924139Sjoerg	       number user requested, number current screen accomodates */
67089757Sdwmalone	    active_procs = system_info.P_ACTIVE;
67124139Sjoerg	    if (active_procs > topn)
67224139Sjoerg	    {
67324139Sjoerg		active_procs = topn;
67424139Sjoerg	    }
67524139Sjoerg	    if (active_procs > max_topn)
67624139Sjoerg	    {
67724139Sjoerg		active_procs = max_topn;
67824139Sjoerg	    }
67924139Sjoerg
68024139Sjoerg	    /* now show the top "n" processes. */
68124139Sjoerg	    for (i = 0; i < active_procs; i++)
68224139Sjoerg	    {
683168710Sstas		(*d_process)(i, format_next_process(processes, get_userid,
684168710Sstas			     fmt_flags));
68524139Sjoerg	    }
68624139Sjoerg	}
68724139Sjoerg	else
68824139Sjoerg	{
68924139Sjoerg	    i = 0;
69024139Sjoerg	}
69124139Sjoerg
69224139Sjoerg	/* do end-screen processing */
69324139Sjoerg	u_endscreen(i);
69424139Sjoerg
69524139Sjoerg	/* now, flush the output buffer */
69689757Sdwmalone	if (fflush(stdout) != 0)
69789757Sdwmalone	{
69889757Sdwmalone	    new_message(MT_standout, " Write error on stdout");
69989757Sdwmalone	    putchar('\r');
70089757Sdwmalone	    quit(1);
70189757Sdwmalone	    /*NOTREACHED*/
70289757Sdwmalone	}
70324139Sjoerg
70424139Sjoerg	/* only do the rest if we have more displays to show */
70524139Sjoerg	if (displays)
70624139Sjoerg	{
70724139Sjoerg	    /* switch out for new display on smart terminals */
70824139Sjoerg	    if (smart_terminal)
70924139Sjoerg	    {
71024139Sjoerg		if (overstrike)
71124139Sjoerg		{
71224139Sjoerg		    reset_display();
71324139Sjoerg		}
71424139Sjoerg		else
71524139Sjoerg		{
71624139Sjoerg		    d_loadave = u_loadave;
71724139Sjoerg		    d_procstates = u_procstates;
71824139Sjoerg		    d_cpustates = u_cpustates;
71924139Sjoerg		    d_memory = u_memory;
720237656Sjhb		    d_arc = u_arc;
72124142Sjoerg		    d_swap = u_swap;
72224139Sjoerg		    d_message = u_message;
72324139Sjoerg		    d_header = u_header;
72424139Sjoerg		    d_process = u_process;
72524139Sjoerg		}
72624139Sjoerg	    }
72724139Sjoerg
72824139Sjoerg	    no_command = Yes;
72924139Sjoerg	    if (!interactive)
73024139Sjoerg	    {
731232239Skib		sleep(delay);
732232660Skib		if (leaveflag) {
733232660Skib		    end_screen();
734232660Skib		    exit(0);
735232660Skib		}
73624139Sjoerg	    }
73724139Sjoerg	    else while (no_command)
73824139Sjoerg	    {
73924139Sjoerg		/* assume valid command unless told otherwise */
74024139Sjoerg		no_command = No;
74124139Sjoerg
74224139Sjoerg		/* set up arguments for select with timeout */
74324139Sjoerg		FD_ZERO(&readfds);
74489757Sdwmalone		FD_SET(0, &readfds);		/* for standard input */
74524139Sjoerg		timeout.tv_sec  = delay;
74624139Sjoerg		timeout.tv_usec = 0;
74724139Sjoerg
74881187Skris		if (leaveflag) {
74981187Skris		    end_screen();
75081187Skris		    exit(0);
75181187Skris		}
75281187Skris
75381187Skris		if (tstopflag) {
75481187Skris		    /* move to the lower left */
75581187Skris		    end_screen();
75681187Skris		    fflush(stdout);
75781187Skris
75881187Skris		    /* default the signal handler action */
75981187Skris		    (void) signal(SIGTSTP, SIG_DFL);
76081187Skris
76181187Skris		    /* unblock the signal and send ourselves one */
76281187Skris#ifdef SIGRELSE
76381187Skris		    sigrelse(SIGTSTP);
76481187Skris#else
76581187Skris		    (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
76681187Skris#endif
76781187Skris		    (void) kill(0, SIGTSTP);
76881187Skris
76981187Skris		    /* reset the signal handler */
77081187Skris		    (void) signal(SIGTSTP, tstop);
77181187Skris
77281187Skris		    /* reinit screen */
77381187Skris		    reinit_screen();
77481187Skris		    reset_display();
77581187Skris		    tstopflag = 0;
77681187Skris		    goto restart;
77781187Skris		}
77881187Skris
77981187Skris		if (winchflag) {
78081187Skris		    /* reascertain the screen dimensions */
78181187Skris		    get_screensize();
78281187Skris
78381187Skris		    /* tell display to resize */
78481187Skris		    max_topn = display_resize();
78581187Skris
78681187Skris		    /* reset the signal handler */
78781187Skris		    (void) signal(SIGWINCH, winch);
78881187Skris
78981187Skris		    reset_display();
79081187Skris		    winchflag = 0;
79181187Skris		    goto restart;
79281187Skris		}
79381187Skris
79424139Sjoerg		/* wait for either input or the end of the delay period */
79586042Sdwmalone		sel_ret = select(2, &readfds, NULL, NULL, &timeout);
79686042Sdwmalone		if (sel_ret < 0 && errno != EINTR)
79786042Sdwmalone		    quit(0);
79886042Sdwmalone		if (sel_ret > 0)
79924139Sjoerg		{
80024139Sjoerg		    int newval;
80124139Sjoerg		    char *errmsg;
80224139Sjoerg
80324139Sjoerg		    /* something to read -- clear the message area first */
80424139Sjoerg		    clear_message();
80524139Sjoerg
80624139Sjoerg		    /* now read it and convert to command strchr */
80724139Sjoerg		    /* (use "change" as a temporary to hold strchr) */
80886042Sdwmalone		    if (read(0, &ch, 1) != 1)
80989757Sdwmalone		    {
81089757Sdwmalone			/* read error: either 0 or -1 */
81189757Sdwmalone			new_message(MT_standout, " Read error on stdin");
81289757Sdwmalone			putchar('\r');
81389757Sdwmalone			quit(1);
81489757Sdwmalone			/*NOTREACHED*/
81589757Sdwmalone		    }
81624139Sjoerg		    if ((iptr = strchr(command_chars, ch)) == NULL)
81724139Sjoerg		    {
81824142Sjoerg			if (ch != '\r' && ch != '\n')
81924142Sjoerg			{
82024142Sjoerg			    /* illegal command */
82124142Sjoerg			    new_message(MT_standout, " Command not understood");
82224142Sjoerg			}
82324139Sjoerg			putchar('\r');
82424139Sjoerg			no_command = Yes;
82524139Sjoerg		    }
82624139Sjoerg		    else
82724139Sjoerg		    {
82824139Sjoerg			change = iptr - command_chars;
82924139Sjoerg			if (overstrike && change > CMD_OSLIMIT)
83024139Sjoerg			{
83124139Sjoerg			    /* error */
83224139Sjoerg			    new_message(MT_standout,
83324139Sjoerg			    " Command cannot be handled by this terminal");
83424139Sjoerg			    putchar('\r');
83524139Sjoerg			    no_command = Yes;
83624139Sjoerg			}
83724139Sjoerg			else switch(change)
83824139Sjoerg			{
83924139Sjoerg			    case CMD_redraw:	/* redraw screen */
84024139Sjoerg				reset_display();
84124139Sjoerg				break;
84224139Sjoerg
84324139Sjoerg			    case CMD_update:	/* merely update display */
84424139Sjoerg				/* is the load average high? */
84524139Sjoerg				if (system_info.load_avg[0] > LoadMax)
84624139Sjoerg				{
84724139Sjoerg				    /* yes, go home for visual feedback */
84824139Sjoerg				    go_home();
84924139Sjoerg				    fflush(stdout);
85024139Sjoerg				}
85124139Sjoerg				break;
85224139Sjoerg
85324139Sjoerg			    case CMD_quit:	/* quit */
85424139Sjoerg				quit(0);
85524139Sjoerg				/*NOTREACHED*/
85624139Sjoerg				break;
85724139Sjoerg
85824139Sjoerg			    case CMD_help1:	/* help */
85924139Sjoerg			    case CMD_help2:
86024139Sjoerg				reset_display();
86124139Sjoerg				clear();
86224139Sjoerg				show_help();
86324139Sjoerg				standout("Hit any key to continue: ");
86424139Sjoerg				fflush(stdout);
86524139Sjoerg				(void) read(0, &ch, 1);
86624139Sjoerg				break;
86724139Sjoerg
86824139Sjoerg			    case CMD_errors:	/* show errors */
86924139Sjoerg				if (error_count() == 0)
87024139Sjoerg				{
87124139Sjoerg				    new_message(MT_standout,
87224139Sjoerg					" Currently no errors to report.");
87324139Sjoerg				    putchar('\r');
87424139Sjoerg				    no_command = Yes;
87524139Sjoerg				}
87624139Sjoerg				else
87724139Sjoerg				{
87824139Sjoerg				    reset_display();
87924139Sjoerg				    clear();
88024139Sjoerg				    show_errors();
88124139Sjoerg				    standout("Hit any key to continue: ");
88224139Sjoerg				    fflush(stdout);
88324139Sjoerg				    (void) read(0, &ch, 1);
88424139Sjoerg				}
88524139Sjoerg				break;
88624139Sjoerg
88724139Sjoerg			    case CMD_number1:	/* new number */
88824139Sjoerg			    case CMD_number2:
88924139Sjoerg				new_message(MT_standout,
89024139Sjoerg				    "Number of processes to show: ");
89124139Sjoerg				newval = readline(tempbuf1, 8, Yes);
89224139Sjoerg				if (newval > -1)
89324139Sjoerg				{
89424139Sjoerg				    if (newval > max_topn)
89524139Sjoerg				    {
89624139Sjoerg					new_message(MT_standout | MT_delayed,
89724139Sjoerg					  " This terminal can only display %d processes.",
89824139Sjoerg					  max_topn);
89924139Sjoerg					putchar('\r');
90024139Sjoerg				    }
90124139Sjoerg
90224139Sjoerg				    if (newval == 0)
90324139Sjoerg				    {
90424139Sjoerg					/* inhibit the header */
90524139Sjoerg					display_header(No);
90624139Sjoerg				    }
90724139Sjoerg				    else if (newval > topn && topn == 0)
90824139Sjoerg				    {
90924139Sjoerg					/* redraw the header */
91024139Sjoerg					display_header(Yes);
91124139Sjoerg					d_header = i_header;
91224139Sjoerg				    }
91324139Sjoerg				    topn = newval;
91424139Sjoerg				}
91524139Sjoerg				break;
91624139Sjoerg
91724139Sjoerg			    case CMD_delay:	/* new seconds delay */
91824139Sjoerg				new_message(MT_standout, "Seconds to delay: ");
91924139Sjoerg				if ((i = readline(tempbuf1, 8, Yes)) > -1)
92024139Sjoerg				{
92189757Sdwmalone				    if ((delay = i) == 0 && getuid() != 0)
92289757Sdwmalone				    {
92389757Sdwmalone					delay = 1;
92489757Sdwmalone				    }
92524139Sjoerg				}
92624139Sjoerg				clear_message();
92724139Sjoerg				break;
92824139Sjoerg
92924139Sjoerg			    case CMD_displays:	/* change display count */
93024139Sjoerg				new_message(MT_standout,
93124139Sjoerg					"Displays to show (currently %s): ",
93224139Sjoerg					displays == -1 ? "infinite" :
93324139Sjoerg							 itoa(displays));
93424139Sjoerg				if ((i = readline(tempbuf1, 10, Yes)) > 0)
93524139Sjoerg				{
93624139Sjoerg				    displays = i;
93724139Sjoerg				}
93824139Sjoerg				else if (i == 0)
93924139Sjoerg				{
94024139Sjoerg				    quit(0);
94124139Sjoerg				}
94224139Sjoerg				clear_message();
94324139Sjoerg				break;
94424139Sjoerg
94524139Sjoerg			    case CMD_kill:	/* kill program */
94624139Sjoerg				new_message(0, "kill ");
94724139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
94824139Sjoerg				{
94924139Sjoerg				    if ((errmsg = kill_procs(tempbuf2)) != NULL)
95024139Sjoerg				    {
95166641Simp					new_message(MT_standout, "%s", errmsg);
95224139Sjoerg					putchar('\r');
95324139Sjoerg					no_command = Yes;
95424139Sjoerg				    }
95524139Sjoerg				}
95624139Sjoerg				else
95724139Sjoerg				{
95824139Sjoerg				    clear_message();
95924139Sjoerg				}
96024139Sjoerg				break;
96124139Sjoerg
96224139Sjoerg			    case CMD_renice:	/* renice program */
96324139Sjoerg				new_message(0, "renice ");
96424139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
96524139Sjoerg				{
96624139Sjoerg				    if ((errmsg = renice_procs(tempbuf2)) != NULL)
96724139Sjoerg				    {
96868293Simp					new_message(MT_standout, "%s", errmsg);
96924139Sjoerg					putchar('\r');
97024139Sjoerg					no_command = Yes;
97124139Sjoerg				    }
97224139Sjoerg				}
97324139Sjoerg				else
97424139Sjoerg				{
97524139Sjoerg				    clear_message();
97624139Sjoerg				}
97724139Sjoerg				break;
97824139Sjoerg
97924139Sjoerg			    case CMD_idletog:
98024139Sjoerg			    case CMD_idletog2:
98124139Sjoerg				ps.idle = !ps.idle;
98224139Sjoerg				new_message(MT_standout | MT_delayed,
98324139Sjoerg				    " %sisplaying idle processes.",
98424139Sjoerg				    ps.idle ? "D" : "Not d");
98524139Sjoerg				putchar('\r');
98624139Sjoerg				break;
98724139Sjoerg
98838090Sdes			    case CMD_selftog:
98938090Sdes				ps.self = (ps.self == -1) ? getpid() : -1;
99038090Sdes				new_message(MT_standout | MT_delayed,
99138090Sdes				    " %sisplaying self.",
99238090Sdes				    (ps.self == -1) ? "D" : "Not d");
99338090Sdes				putchar('\r');
99438090Sdes				break;
99538090Sdes
99624139Sjoerg			    case CMD_user:
99724139Sjoerg				new_message(MT_standout,
998266280Sbdrewery				    "Username to show (+ for all): ");
99924139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
100024139Sjoerg				{
100124139Sjoerg				    if (tempbuf2[0] == '+' &&
100224139Sjoerg					tempbuf2[1] == '\0')
100324139Sjoerg				    {
100424139Sjoerg					ps.uid = -1;
100524139Sjoerg				    }
100624139Sjoerg				    else if ((i = userid(tempbuf2)) == -1)
100724139Sjoerg				    {
100824139Sjoerg					new_message(MT_standout,
100924139Sjoerg					    " %s: unknown user", tempbuf2);
101024139Sjoerg					no_command = Yes;
101124139Sjoerg				    }
101224139Sjoerg				    else
101324139Sjoerg				    {
101424139Sjoerg					ps.uid = i;
101524139Sjoerg				    }
101624139Sjoerg				    putchar('\r');
101724139Sjoerg				}
101824139Sjoerg				else
101924139Sjoerg				{
102024139Sjoerg				    clear_message();
102124139Sjoerg				}
102224139Sjoerg				break;
102324139Sjoerg
1024117709Sjulian			    case CMD_thrtog:
1025117709Sjulian				ps.thread = !ps.thread;
1026117709Sjulian				new_message(MT_standout | MT_delayed,
1027223937Sjhb				    " Displaying threads %s",
1028145073Skeramida				    ps.thread ? "separately" : "as a count");
1029145073Skeramida				header_text = format_header(uname_field);
1030145073Skeramida				reset_display();
1031117709Sjulian				putchar('\r');
1032117709Sjulian				break;
1033146342Skeramida			    case CMD_wcputog:
1034146342Skeramida				ps.wcpu = !ps.wcpu;
1035146342Skeramida				new_message(MT_standout | MT_delayed,
1036224204Sjhb				    " Displaying %s CPU",
1037224204Sjhb				    ps.wcpu ? "weighted" : "raw");
1038146342Skeramida				header_text = format_header(uname_field);
1039146342Skeramida				reset_display();
1040146342Skeramida				putchar('\r');
1041146342Skeramida				break;
1042131402Salfred			    case CMD_viewtog:
1043131402Salfred				if (++displaymode == DISP_MAX)
1044131402Salfred					displaymode = 0;
1045131402Salfred				header_text = format_header(uname_field);
1046131402Salfred				display_header(Yes);
1047131402Salfred				d_header = i_header;
1048131402Salfred				reset_display();
1049131402Salfred				break;
1050132005Salfred			    case CMD_viewsys:
1051132005Salfred				ps.system = !ps.system;
1052132005Salfred				break;
1053168710Sstas			    case CMD_showargs:
1054168710Sstas				fmt_flags ^= FMT_SHOWARGS;
1055168710Sstas				break;
105624139Sjoerg#ifdef ORDER
105724139Sjoerg			    case CMD_order:
105824139Sjoerg				new_message(MT_standout,
105924139Sjoerg				    "Order to sort: ");
106024139Sjoerg				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
106124139Sjoerg				{
106224139Sjoerg				  if ((i = string_index(tempbuf2, statics.order_names)) == -1)
106324139Sjoerg					{
106424139Sjoerg					  new_message(MT_standout,
106524139Sjoerg					      " %s: unrecognized sorting order", tempbuf2);
106624139Sjoerg					  no_command = Yes;
106724139Sjoerg				    }
106824139Sjoerg				    else
106924139Sjoerg				    {
107024139Sjoerg					order_index = i;
107124139Sjoerg				    }
107224139Sjoerg				    putchar('\r');
107324139Sjoerg				}
107424139Sjoerg				else
107524139Sjoerg				{
107624139Sjoerg				    clear_message();
107724139Sjoerg				}
107824139Sjoerg				break;
107924139Sjoerg#endif
1080168799Srafan			    case CMD_jidtog:
1081168799Srafan				ps.jail = !ps.jail;
1082168799Srafan				new_message(MT_standout | MT_delayed,
1083169257Srafan				    " %sisplaying jail ID.",
1084168799Srafan				    ps.jail ? "D" : "Not d");
1085168799Srafan				header_text = format_header(uname_field);
1086168799Srafan				reset_display();
1087168799Srafan				putchar('\r');
1088168799Srafan				break;
1089266280Sbdrewery
1090266280Sbdrewery			    case CMD_jail:
1091266280Sbdrewery				new_message(MT_standout,
1092266280Sbdrewery				    "Jail to show (+ for all): ");
1093266280Sbdrewery				if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
1094266280Sbdrewery				{
1095266280Sbdrewery				    if (tempbuf2[0] == '+' &&
1096266280Sbdrewery					tempbuf2[1] == '\0')
1097266280Sbdrewery				    {
1098266280Sbdrewery					ps.jid = -1;
1099266280Sbdrewery				    }
1100266280Sbdrewery				    else if ((i = jail_getid(tempbuf2)) == -1)
1101266280Sbdrewery				    {
1102266280Sbdrewery					new_message(MT_standout,
1103266280Sbdrewery					    " %s: unknown jail", tempbuf2);
1104266280Sbdrewery					no_command = Yes;
1105266280Sbdrewery				    }
1106266280Sbdrewery				    else
1107266280Sbdrewery				    {
1108266280Sbdrewery					ps.jid = i;
1109266280Sbdrewery				    }
1110266280Sbdrewery				    if (ps.jail == 0) {
1111266280Sbdrewery					    ps.jail = 1;
1112266280Sbdrewery					    new_message(MT_standout |
1113266280Sbdrewery						MT_delayed, " Displaying jail "
1114266280Sbdrewery						"ID.");
1115266280Sbdrewery					    header_text =
1116266280Sbdrewery						format_header(uname_field);
1117266280Sbdrewery					    reset_display();
1118266280Sbdrewery				    }
1119266280Sbdrewery				    putchar('\r');
1120266280Sbdrewery				}
1121266280Sbdrewery				else
1122266280Sbdrewery				{
1123266280Sbdrewery				    clear_message();
1124266280Sbdrewery				}
1125266280Sbdrewery				break;
1126266280Sbdrewery
1127222530Sjhb			    case CMD_kidletog:
1128222530Sjhb				ps.kidle = !ps.kidle;
1129222530Sjhb				new_message(MT_standout | MT_delayed,
1130222530Sjhb				    " %sisplaying system idle process.",
1131222530Sjhb				    ps.kidle ? "D" : "Not d");
1132222530Sjhb				putchar('\r');
1133222530Sjhb				break;
1134223936Sjhb			    case CMD_pcputog:
1135223936Sjhb				pcpu_stats = !pcpu_stats;
1136223936Sjhb				new_message(MT_standout | MT_delayed,
1137223936Sjhb				    " Displaying %sCPU statistics.",
1138223936Sjhb				    pcpu_stats ? "per-" : "global ");
1139224205Sjhb				toggle_pcpustats();
1140223936Sjhb				max_topn = display_updatecpus(&statics);
1141223936Sjhb				reset_display();
1142223936Sjhb				putchar('\r');
1143223936Sjhb				break;
114424139Sjoerg			    default:
114524139Sjoerg				new_message(MT_standout, " BAD CASE IN SWITCH!");
114624139Sjoerg				putchar('\r');
114724139Sjoerg			}
114824139Sjoerg		    }
114924139Sjoerg
115024139Sjoerg		    /* flush out stuff that may have been written */
115124139Sjoerg		    fflush(stdout);
115224139Sjoerg		}
115324139Sjoerg	    }
115424139Sjoerg	}
115524139Sjoerg    }
115624139Sjoerg
115789757Sdwmalone#ifdef DEBUG
115889757Sdwmalone    fclose(debug);
115989757Sdwmalone#endif
116024139Sjoerg    quit(0);
116124139Sjoerg    /*NOTREACHED*/
116224139Sjoerg}
116324139Sjoerg
116424139Sjoerg/*
116524139Sjoerg *  reset_display() - reset all the display routine pointers so that entire
116624139Sjoerg *	screen will get redrawn.
116724139Sjoerg */
116824139Sjoerg
1169301836Sngievoid
117024139Sjoergreset_display()
117124139Sjoerg
117224139Sjoerg{
117324139Sjoerg    d_loadave    = i_loadave;
117424139Sjoerg    d_procstates = i_procstates;
117524139Sjoerg    d_cpustates  = i_cpustates;
117624139Sjoerg    d_memory     = i_memory;
1177237656Sjhb    d_arc        = i_arc;
117824142Sjoerg    d_swap       = i_swap;
117924139Sjoerg    d_message	 = i_message;
118024139Sjoerg    d_header	 = i_header;
118124139Sjoerg    d_process	 = i_process;
118224139Sjoerg}
118324139Sjoerg
118424139Sjoerg/*
118524139Sjoerg *  signal handlers
118624139Sjoerg */
118724139Sjoerg
118824139Sjoergsigret_t leave()	/* exit under normal conditions -- INT handler */
118924139Sjoerg
119024139Sjoerg{
119181187Skris    leaveflag = 1;
119224139Sjoerg}
119324139Sjoerg
119424139Sjoergsigret_t tstop(i)	/* SIGTSTP handler */
119524139Sjoerg
119624139Sjoergint i;
119724139Sjoerg
119824139Sjoerg{
119981187Skris    tstopflag = 1;
120024139Sjoerg}
120124139Sjoerg
120224139Sjoerg#ifdef SIGWINCH
120324139Sjoergsigret_t winch(i)		/* SIGWINCH handler */
120424139Sjoerg
120524139Sjoergint i;
120624139Sjoerg
120724139Sjoerg{
120881187Skris    winchflag = 1;
120924139Sjoerg}
121024139Sjoerg#endif
121124139Sjoerg
121224139Sjoergvoid quit(status)		/* exit under duress */
121324139Sjoerg
121424139Sjoergint status;
121524139Sjoerg
121624139Sjoerg{
121724139Sjoerg    end_screen();
121824139Sjoerg    exit(status);
121924139Sjoerg    /*NOTREACHED*/
122024139Sjoerg}
1221