top.c revision 168799
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 168799 2007-04-17 03:12:39Z rafan $ 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> 4124139Sjoerg#include <sys/time.h> 4224139Sjoerg 4324139Sjoerg/* includes specific to top */ 4424139Sjoerg#include "display.h" /* interface to display package */ 4524139Sjoerg#include "screen.h" /* interface to screen package */ 4624139Sjoerg#include "top.h" 4724139Sjoerg#include "top.local.h" 4824139Sjoerg#include "boolean.h" 4924139Sjoerg#include "machine.h" 5024139Sjoerg#include "utils.h" 5124139Sjoerg 5224139Sjoerg/* Size of the stdio buffer given to stdout */ 5324139Sjoerg#define Buffersize 2048 5424139Sjoerg 5524139Sjoerg/* The buffer that stdio will use */ 5624139Sjoergchar stdoutbuf[Buffersize]; 5724139Sjoerg 5824139Sjoerg/* build Signal masks */ 5924139Sjoerg#define Smask(s) (1 << ((s) - 1)) 6024139Sjoerg 6124139Sjoerg/* for getopt: */ 6224139Sjoergextern int optind; 6324139Sjoergextern char *optarg; 6424139Sjoerg 6524139Sjoerg/* imported from screen.c */ 6624139Sjoergextern int overstrike; 6724139Sjoerg 68168710Sstasstatic int fmt_flags = 0; 69168710Sstas 7024139Sjoerg/* signal handling routines */ 7124139Sjoergsigret_t leave(); 7224139Sjoergsigret_t onalrm(); 7324139Sjoergsigret_t tstop(); 7424139Sjoerg#ifdef SIGWINCH 7524139Sjoergsigret_t winch(); 7624139Sjoerg#endif 7724139Sjoerg 7881187Skrisvolatile sig_atomic_t leaveflag; 7981187Skrisvolatile sig_atomic_t tstopflag; 8081187Skrisvolatile sig_atomic_t winchflag; 8181187Skris 8224139Sjoerg/* internal routines */ 8324139Sjoergvoid quit(); 8424139Sjoerg 8524139Sjoerg/* values which need to be accessed by signal handlers */ 8624139Sjoergstatic int max_topn; /* maximum displayable processes */ 8724139Sjoerg 8824139Sjoerg/* miscellaneous things */ 89145073Skeramidastruct process_select ps; 9024139Sjoergchar *myname = "top"; 9124139Sjoergjmp_buf jmp_int; 9224139Sjoerg 9324139Sjoerg/* routines that don't return int */ 9424139Sjoerg 9524139Sjoergchar *username(); 9624139Sjoergchar *ctime(); 9724139Sjoergchar *kill_procs(); 9824139Sjoergchar *renice_procs(); 9924139Sjoerg 10024139Sjoerg#ifdef ORDER 101133817Salfredextern int (*compares[])(); 10224139Sjoerg#else 10324139Sjoergextern int proc_compare(); 104131829Skeramidaextern int io_compare(); 10524139Sjoerg#endif 10624139Sjoergtime_t time(); 10724139Sjoerg 10824139Sjoergcaddr_t get_process_info(); 10924139Sjoerg 11024139Sjoerg/* different routines for displaying the user's identification */ 11124139Sjoerg/* (values assigned to get_userid) */ 11224139Sjoergchar *username(); 11324139Sjoergchar *itoa7(); 11424139Sjoerg 11524139Sjoerg/* display routines that need to be predeclared */ 11624139Sjoergint i_loadave(); 11724139Sjoergint u_loadave(); 11824139Sjoergint i_procstates(); 11924139Sjoergint u_procstates(); 12024139Sjoergint i_cpustates(); 12124139Sjoergint u_cpustates(); 12224139Sjoergint i_memory(); 12324139Sjoergint u_memory(); 12424142Sjoergint i_swap(); 12524142Sjoergint u_swap(); 12624139Sjoergint i_message(); 12724139Sjoergint u_message(); 12824139Sjoergint i_header(); 12924139Sjoergint u_header(); 13024139Sjoergint i_process(); 13124139Sjoergint u_process(); 13224139Sjoerg 13324139Sjoerg/* pointers to display routines */ 13424139Sjoergint (*d_loadave)() = i_loadave; 13524139Sjoergint (*d_procstates)() = i_procstates; 13624139Sjoergint (*d_cpustates)() = i_cpustates; 13724139Sjoergint (*d_memory)() = i_memory; 13824142Sjoergint (*d_swap)() = i_swap; 13924139Sjoergint (*d_message)() = i_message; 14024139Sjoergint (*d_header)() = i_header; 14124139Sjoergint (*d_process)() = i_process; 14224139Sjoerg 14324139Sjoerg 14424139Sjoergmain(argc, argv) 14524139Sjoerg 14624139Sjoergint argc; 14724139Sjoergchar *argv[]; 14824139Sjoerg 14924139Sjoerg{ 15024139Sjoerg register int i; 15124139Sjoerg register int active_procs; 15224139Sjoerg register int change; 15324139Sjoerg 15424139Sjoerg struct system_info system_info; 15524139Sjoerg struct statics statics; 15624139Sjoerg caddr_t processes; 15724139Sjoerg 15824139Sjoerg static char tempbuf1[50]; 15924139Sjoerg static char tempbuf2[50]; 16024139Sjoerg int old_sigmask; /* only used for BSD-style signals */ 16124139Sjoerg int topn = Default_TOPN; 16224139Sjoerg int delay = Default_DELAY; 16324139Sjoerg int displays = 0; /* indicates unspecified */ 16486042Sdwmalone int sel_ret = 0; 16524139Sjoerg time_t curr_time; 16624139Sjoerg char *(*get_userid)() = username; 16724139Sjoerg char *uname_field = "USERNAME"; 16824139Sjoerg char *header_text; 16924139Sjoerg char *env_top; 17024139Sjoerg char **preset_argv; 17124139Sjoerg int preset_argc = 0; 17224139Sjoerg char **av; 17324139Sjoerg int ac; 17424139Sjoerg char dostates = No; 17524139Sjoerg char do_unames = Yes; 17624139Sjoerg char interactive = Maybe; 17724139Sjoerg char warnings = 0; 17824139Sjoerg#if Default_TOPN == Infinity 17924139Sjoerg char topn_specified = No; 18024139Sjoerg#endif 18124139Sjoerg char ch; 18224139Sjoerg char *iptr; 18324139Sjoerg char no_command = 1; 18424139Sjoerg struct timeval timeout; 18524139Sjoerg#ifdef ORDER 18624139Sjoerg char *order_name = NULL; 18724139Sjoerg int order_index = 0; 18824139Sjoerg#endif 18924139Sjoerg#ifndef FD_SET 19024139Sjoerg /* FD_SET and friends are not present: fake it */ 19124139Sjoerg typedef int fd_set; 19224139Sjoerg#define FD_ZERO(x) (*(x) = 0) 19389757Sdwmalone#define FD_SET(f, x) (*(x) = 1<<f) 19424139Sjoerg#endif 19524139Sjoerg fd_set readfds; 19624139Sjoerg 19724139Sjoerg#ifdef ORDER 198168799Srafan static char command_chars[] = "\f qh?en#sdkriIutHmSCajo"; 19924139Sjoerg#else 200168799Srafan static char command_chars[] = "\f qh?en#sdkriIutHmSCaj"; 20124139Sjoerg#endif 20224139Sjoerg/* these defines enumerate the "strchr"s of the commands in command_chars */ 20324139Sjoerg#define CMD_redraw 0 20424139Sjoerg#define CMD_update 1 20524139Sjoerg#define CMD_quit 2 20624139Sjoerg#define CMD_help1 3 20724139Sjoerg#define CMD_help2 4 20824139Sjoerg#define CMD_OSLIMIT 4 /* terminals with OS can only handle commands */ 20924139Sjoerg#define CMD_errors 5 /* less than or equal to CMD_OSLIMIT */ 21024139Sjoerg#define CMD_number1 6 21124139Sjoerg#define CMD_number2 7 21224139Sjoerg#define CMD_delay 8 21324139Sjoerg#define CMD_displays 9 21424139Sjoerg#define CMD_kill 10 21524139Sjoerg#define CMD_renice 11 21624139Sjoerg#define CMD_idletog 12 21724139Sjoerg#define CMD_idletog2 13 21824139Sjoerg#define CMD_user 14 21938090Sdes#define CMD_selftog 15 220117709Sjulian#define CMD_thrtog 16 221131402Salfred#define CMD_viewtog 17 222132005Salfred#define CMD_viewsys 18 223146342Skeramida#define CMD_wcputog 19 224168710Sstas#define CMD_showargs 20 225168799Srafan#define CMD_jidtog 21 22624139Sjoerg#ifdef ORDER 227168799Srafan#define CMD_order 22 22824139Sjoerg#endif 22924139Sjoerg 23024139Sjoerg /* set the buffer for stdout */ 23124139Sjoerg#ifdef DEBUG 23289757Sdwmalone extern FILE *debug; 23389757Sdwmalone debug = fopen("debug.run", "w"); 23424139Sjoerg setbuffer(stdout, NULL, 0); 23524139Sjoerg#else 23624139Sjoerg setbuffer(stdout, stdoutbuf, Buffersize); 23724139Sjoerg#endif 23824139Sjoerg 23924139Sjoerg /* get our name */ 24024139Sjoerg if (argc > 0) 24124139Sjoerg { 24224139Sjoerg if ((myname = strrchr(argv[0], '/')) == 0) 24324139Sjoerg { 24424139Sjoerg myname = argv[0]; 24524139Sjoerg } 24624139Sjoerg else 24724139Sjoerg { 24824139Sjoerg myname++; 24924139Sjoerg } 25024139Sjoerg } 25124139Sjoerg 25224139Sjoerg /* initialize some selection options */ 25324139Sjoerg ps.idle = Yes; 25438090Sdes ps.self = -1; 25524139Sjoerg ps.system = No; 25624139Sjoerg ps.uid = -1; 257117709Sjulian ps.thread = No; 258146342Skeramida ps.wcpu = 1; 259168799Srafan ps.jail = No; 26024139Sjoerg ps.command = NULL; 26124139Sjoerg 26224139Sjoerg /* get preset options from the environment */ 26324139Sjoerg if ((env_top = getenv("TOP")) != NULL) 26424139Sjoerg { 26524139Sjoerg av = preset_argv = argparse(env_top, &preset_argc); 26624139Sjoerg ac = preset_argc; 26724139Sjoerg 26824139Sjoerg /* set the dummy argument to an explanatory message, in case 26924139Sjoerg getopt encounters a bad argument */ 27024139Sjoerg preset_argv[0] = "while processing environment"; 27124139Sjoerg } 27224139Sjoerg 27324139Sjoerg /* process options */ 27424139Sjoerg do { 27524139Sjoerg /* if we're done doing the presets, then process the real arguments */ 27624139Sjoerg if (preset_argc == 0) 27724139Sjoerg { 27824139Sjoerg ac = argc; 27924139Sjoerg av = argv; 28024139Sjoerg 28124139Sjoerg /* this should keep getopt happy... */ 28224139Sjoerg optind = 1; 28324139Sjoerg } 28424139Sjoerg 285168799Srafan while ((i = getopt(ac, av, "CSIHabijnquvs:d:U:m:o:t")) != EOF) 28624139Sjoerg { 28724139Sjoerg switch(i) 28824139Sjoerg { 28989757Sdwmalone case 'v': /* show version number */ 29089757Sdwmalone fprintf(stderr, "%s: version %s\n", 29189757Sdwmalone myname, version_string()); 29289757Sdwmalone exit(1); 29389757Sdwmalone break; 29489757Sdwmalone 29524139Sjoerg case 'u': /* toggle uid/username display */ 29624139Sjoerg do_unames = !do_unames; 29724139Sjoerg break; 29824139Sjoerg 29924139Sjoerg case 'U': /* display only username's processes */ 30024139Sjoerg if ((ps.uid = userid(optarg)) == -1) 30124139Sjoerg { 30224139Sjoerg fprintf(stderr, "%s: unknown user\n", optarg); 30324139Sjoerg exit(1); 30424139Sjoerg } 30524139Sjoerg break; 30624139Sjoerg 30724139Sjoerg case 'S': /* show system processes */ 30824139Sjoerg ps.system = !ps.system; 30924139Sjoerg break; 31024139Sjoerg 31124139Sjoerg case 'I': /* show idle processes */ 31224139Sjoerg ps.idle = !ps.idle; 31324139Sjoerg break; 31424139Sjoerg 31524139Sjoerg case 'i': /* go interactive regardless */ 31624139Sjoerg interactive = Yes; 31724139Sjoerg break; 31824139Sjoerg 31924139Sjoerg case 'n': /* batch, or non-interactive */ 32024139Sjoerg case 'b': 32124139Sjoerg interactive = No; 32224139Sjoerg break; 32324139Sjoerg 324168710Sstas case 'a': 325168710Sstas fmt_flags ^= FMT_SHOWARGS; 326168710Sstas break; 327168710Sstas 32824139Sjoerg case 'd': /* number of displays to show */ 32924139Sjoerg if ((i = atoiwi(optarg)) == Invalid || i == 0) 33024139Sjoerg { 33124139Sjoerg fprintf(stderr, 33224139Sjoerg "%s: warning: display count should be positive -- option ignored\n", 33324139Sjoerg myname); 33424139Sjoerg warnings++; 33524139Sjoerg } 33624139Sjoerg else 33724139Sjoerg { 33824139Sjoerg displays = i; 33924139Sjoerg } 34024139Sjoerg break; 34124139Sjoerg 34224139Sjoerg case 's': 34389757Sdwmalone if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0)) 34424139Sjoerg { 34524139Sjoerg fprintf(stderr, 34689757Sdwmalone "%s: warning: seconds delay should be positive -- using default\n", 34724139Sjoerg myname); 34824139Sjoerg delay = Default_DELAY; 34924139Sjoerg warnings++; 35024139Sjoerg } 35124139Sjoerg break; 35224139Sjoerg 35324139Sjoerg case 'q': /* be quick about it */ 35424139Sjoerg /* only allow this if user is really root */ 35524139Sjoerg if (getuid() == 0) 35624139Sjoerg { 35724139Sjoerg /* be very un-nice! */ 35824139Sjoerg (void) nice(-20); 35924139Sjoerg } 36024139Sjoerg else 36124139Sjoerg { 36224139Sjoerg fprintf(stderr, 36324139Sjoerg "%s: warning: `-q' option can only be used by root\n", 36424139Sjoerg myname); 36524139Sjoerg warnings++; 36624139Sjoerg } 36724139Sjoerg break; 36824139Sjoerg 369131616Sdes case 'm': /* select display mode */ 370131402Salfred if (strcmp(optarg, "io") == 0) { 371131402Salfred displaymode = DISP_IO; 372131402Salfred } else if (strcmp(optarg, "cpu") == 0) { 373131402Salfred displaymode = DISP_CPU; 374131402Salfred } else { 375131402Salfred fprintf(stderr, 376131402Salfred "%s: warning: `-m' option can only take args " 377131402Salfred "'io' or 'cpu'\n", 378131402Salfred myname); 379131402Salfred exit(1); 380131402Salfred } 381131402Salfred break; 382131402Salfred 38324139Sjoerg case 'o': /* select sort order */ 38424139Sjoerg#ifdef ORDER 38524139Sjoerg order_name = optarg; 38624139Sjoerg#else 38724139Sjoerg fprintf(stderr, 38824139Sjoerg "%s: this platform does not support arbitrary ordering. Sorry.\n", 38924139Sjoerg myname); 39024139Sjoerg warnings++; 39124139Sjoerg#endif 39224139Sjoerg break; 39324139Sjoerg 39438090Sdes case 't': 39538090Sdes ps.self = (ps.self == -1) ? getpid() : -1; 39638090Sdes break; 397146342Skeramida 398146342Skeramida case 'C': 399146342Skeramida ps.wcpu = !ps.wcpu; 400146342Skeramida break; 401146342Skeramida 402117709Sjulian case 'H': 403117709Sjulian ps.thread = !ps.thread; 404117709Sjulian break; 405146342Skeramida 406168799Srafan case 'j': 407168799Srafan ps.jail = !ps.jail; 408168799Srafan break; 409168799Srafan 41024139Sjoerg default: 411157842Sru fprintf(stderr, 412157842Sru"Top version %s\n" 413157866Sru"Usage: %s [-bCHIinqStuv] [-d count] [-m io | cpu] [-o field] [-s time]\n" 414157842Sru" [-U username] [number]\n", 41524139Sjoerg version_string(), myname); 41624139Sjoerg exit(1); 41724139Sjoerg } 41824139Sjoerg } 41924139Sjoerg 42024139Sjoerg /* get count of top processes to display (if any) */ 42124139Sjoerg if (optind < ac) 42224139Sjoerg { 42324139Sjoerg if ((topn = atoiwi(av[optind])) == Invalid) 42424139Sjoerg { 42524139Sjoerg fprintf(stderr, 42624139Sjoerg "%s: warning: process display count should be non-negative -- using default\n", 42724139Sjoerg myname); 42824139Sjoerg warnings++; 42924139Sjoerg } 43024139Sjoerg#if Default_TOPN == Infinity 43124139Sjoerg else 43224139Sjoerg { 43324139Sjoerg topn_specified = Yes; 43424139Sjoerg } 43524139Sjoerg#endif 43624139Sjoerg } 43724139Sjoerg 43824139Sjoerg /* tricky: remember old value of preset_argc & set preset_argc = 0 */ 43924139Sjoerg i = preset_argc; 44024139Sjoerg preset_argc = 0; 44124139Sjoerg 44224139Sjoerg /* repeat only if we really did the preset arguments */ 44324139Sjoerg } while (i != 0); 44424139Sjoerg 44524139Sjoerg /* set constants for username/uid display correctly */ 44624139Sjoerg if (!do_unames) 44724139Sjoerg { 44824139Sjoerg uname_field = " UID "; 44924139Sjoerg get_userid = itoa7; 45024139Sjoerg } 45124139Sjoerg 45224139Sjoerg /* initialize the kernel memory interface */ 45324139Sjoerg if (machine_init(&statics) == -1) 45424139Sjoerg { 45524139Sjoerg exit(1); 45624139Sjoerg } 45724139Sjoerg 45824139Sjoerg#ifdef ORDER 45924139Sjoerg /* determine sorting order index, if necessary */ 46024139Sjoerg if (order_name != NULL) 46124139Sjoerg { 46224139Sjoerg if ((order_index = string_index(order_name, statics.order_names)) == -1) 46324139Sjoerg { 46424139Sjoerg char **pp; 46524139Sjoerg 46624139Sjoerg fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n", 46724139Sjoerg myname, order_name); 46824139Sjoerg fprintf(stderr, "\tTry one of these:"); 46924139Sjoerg pp = statics.order_names; 47024139Sjoerg while (*pp != NULL) 47124139Sjoerg { 47224139Sjoerg fprintf(stderr, " %s", *pp++); 47324139Sjoerg } 47424139Sjoerg fputc('\n', stderr); 47524139Sjoerg exit(1); 47624139Sjoerg } 47724139Sjoerg } 47824139Sjoerg#endif 47924139Sjoerg 48024139Sjoerg#ifdef no_initialization_needed 48124139Sjoerg /* initialize the hashing stuff */ 48224139Sjoerg if (do_unames) 48324139Sjoerg { 48424139Sjoerg init_hash(); 48524139Sjoerg } 48624139Sjoerg#endif 48724139Sjoerg 48824139Sjoerg /* initialize termcap */ 48924139Sjoerg init_termcap(interactive); 49024139Sjoerg 49124139Sjoerg /* get the string to use for the process area header */ 49224139Sjoerg header_text = format_header(uname_field); 49324139Sjoerg 49424139Sjoerg /* initialize display interface */ 49524139Sjoerg if ((max_topn = display_init(&statics)) == -1) 49624139Sjoerg { 49724139Sjoerg fprintf(stderr, "%s: can't allocate sufficient memory\n", myname); 49824139Sjoerg exit(4); 49924139Sjoerg } 50024139Sjoerg 50124139Sjoerg /* print warning if user requested more processes than we can display */ 50224139Sjoerg if (topn > max_topn) 50324139Sjoerg { 50424139Sjoerg fprintf(stderr, 50524139Sjoerg "%s: warning: this terminal can only display %d processes.\n", 50624139Sjoerg myname, max_topn); 50724139Sjoerg warnings++; 50824139Sjoerg } 50924139Sjoerg 51024139Sjoerg /* adjust for topn == Infinity */ 51124139Sjoerg if (topn == Infinity) 51224139Sjoerg { 51324139Sjoerg /* 51424139Sjoerg * For smart terminals, infinity really means everything that can 51524139Sjoerg * be displayed, or Largest. 51624139Sjoerg * On dumb terminals, infinity means every process in the system! 51724139Sjoerg * We only really want to do that if it was explicitly specified. 51824139Sjoerg * This is always the case when "Default_TOPN != Infinity". But if 51924139Sjoerg * topn wasn't explicitly specified and we are on a dumb terminal 52024139Sjoerg * and the default is Infinity, then (and only then) we use 52124139Sjoerg * "Nominal_TOPN" instead. 52224139Sjoerg */ 52324139Sjoerg#if Default_TOPN == Infinity 52424139Sjoerg topn = smart_terminal ? Largest : 52524139Sjoerg (topn_specified ? Largest : Nominal_TOPN); 52624139Sjoerg#else 52724139Sjoerg topn = Largest; 52824139Sjoerg#endif 52924139Sjoerg } 53024139Sjoerg 53124139Sjoerg /* set header display accordingly */ 53224139Sjoerg display_header(topn > 0); 53324139Sjoerg 53424139Sjoerg /* determine interactive state */ 53524139Sjoerg if (interactive == Maybe) 53624139Sjoerg { 53724139Sjoerg interactive = smart_terminal; 53824139Sjoerg } 53924139Sjoerg 54024139Sjoerg /* if # of displays not specified, fill it in */ 54124139Sjoerg if (displays == 0) 54224139Sjoerg { 54324139Sjoerg displays = smart_terminal ? Infinity : 1; 54424139Sjoerg } 54524139Sjoerg 54624139Sjoerg /* hold interrupt signals while setting up the screen and the handlers */ 54724139Sjoerg#ifdef SIGHOLD 54824139Sjoerg sighold(SIGINT); 54924139Sjoerg sighold(SIGQUIT); 55024139Sjoerg sighold(SIGTSTP); 55124139Sjoerg#else 55224139Sjoerg old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP)); 55324139Sjoerg#endif 55424139Sjoerg init_screen(); 55524139Sjoerg (void) signal(SIGINT, leave); 55624139Sjoerg (void) signal(SIGQUIT, leave); 55724139Sjoerg (void) signal(SIGTSTP, tstop); 55824139Sjoerg#ifdef SIGWINCH 55924139Sjoerg (void) signal(SIGWINCH, winch); 56024139Sjoerg#endif 56124139Sjoerg#ifdef SIGRELSE 56224139Sjoerg sigrelse(SIGINT); 56324139Sjoerg sigrelse(SIGQUIT); 56424139Sjoerg sigrelse(SIGTSTP); 56524139Sjoerg#else 56624139Sjoerg (void) sigsetmask(old_sigmask); 56724139Sjoerg#endif 56824139Sjoerg if (warnings) 56924139Sjoerg { 57024139Sjoerg fputs("....", stderr); 57124139Sjoerg fflush(stderr); /* why must I do this? */ 57224139Sjoerg sleep((unsigned)(3 * warnings)); 57324139Sjoerg fputc('\n', stderr); 57424139Sjoerg } 57524139Sjoerg 57681187Skrisrestart: 57724139Sjoerg 57824139Sjoerg /* 57924139Sjoerg * main loop -- repeat while display count is positive or while it 58024139Sjoerg * indicates infinity (by being -1) 58124139Sjoerg */ 58224139Sjoerg 58324139Sjoerg while ((displays == -1) || (displays-- > 0)) 58424139Sjoerg { 585131402Salfred int (*compare)(); 586131402Salfred 587131402Salfred 58824139Sjoerg /* get the current stats */ 58924139Sjoerg get_system_info(&system_info); 59024139Sjoerg 59124139Sjoerg#ifdef ORDER 592133817Salfred compare = compares[order_index]; 59324139Sjoerg#else 594131829Skeramida if (displaymode == DISP_CPU) 595131402Salfred compare = proc_compare; 596131829Skeramida else 597131829Skeramida compare = io_compare; 59824139Sjoerg#endif 59924139Sjoerg 600131402Salfred /* get the current set of processes */ 601131402Salfred processes = 602131402Salfred get_process_info(&system_info, &ps, compare); 603131402Salfred 60424139Sjoerg /* display the load averages */ 60524139Sjoerg (*d_loadave)(system_info.last_pid, 60624139Sjoerg system_info.load_avg); 60724139Sjoerg 60824139Sjoerg /* display the current time */ 60924139Sjoerg /* this method of getting the time SHOULD be fairly portable */ 61024139Sjoerg time(&curr_time); 61142447Sobrien i_uptime(&system_info.boottime, &curr_time); 61224139Sjoerg i_timeofday(&curr_time); 61324139Sjoerg 61424139Sjoerg /* display process state breakdown */ 61524139Sjoerg (*d_procstates)(system_info.p_total, 61624139Sjoerg system_info.procstates); 61724139Sjoerg 61824139Sjoerg /* display the cpu state percentage breakdown */ 61924139Sjoerg if (dostates) /* but not the first time */ 62024139Sjoerg { 62124139Sjoerg (*d_cpustates)(system_info.cpustates); 62224139Sjoerg } 62324139Sjoerg else 62424139Sjoerg { 62524139Sjoerg /* we'll do it next time */ 62624139Sjoerg if (smart_terminal) 62724139Sjoerg { 62824139Sjoerg z_cpustates(); 62924139Sjoerg } 63024139Sjoerg else 63124139Sjoerg { 63224139Sjoerg putchar('\n'); 63324139Sjoerg } 63424139Sjoerg dostates = Yes; 63524139Sjoerg } 63624139Sjoerg 63724139Sjoerg /* display memory stats */ 63824139Sjoerg (*d_memory)(system_info.memory); 63924139Sjoerg 64024142Sjoerg /* display swap stats */ 64124142Sjoerg (*d_swap)(system_info.swap); 64224142Sjoerg 64324139Sjoerg /* handle message area */ 64424139Sjoerg (*d_message)(); 64524139Sjoerg 64624139Sjoerg /* update the header area */ 64724139Sjoerg (*d_header)(header_text); 64824139Sjoerg 64924139Sjoerg if (topn > 0) 65024139Sjoerg { 65124139Sjoerg /* determine number of processes to actually display */ 65224139Sjoerg /* this number will be the smallest of: active processes, 65324139Sjoerg number user requested, number current screen accomodates */ 65489757Sdwmalone active_procs = system_info.P_ACTIVE; 65524139Sjoerg if (active_procs > topn) 65624139Sjoerg { 65724139Sjoerg active_procs = topn; 65824139Sjoerg } 65924139Sjoerg if (active_procs > max_topn) 66024139Sjoerg { 66124139Sjoerg active_procs = max_topn; 66224139Sjoerg } 66324139Sjoerg 66424139Sjoerg /* now show the top "n" processes. */ 66524139Sjoerg for (i = 0; i < active_procs; i++) 66624139Sjoerg { 667168710Sstas (*d_process)(i, format_next_process(processes, get_userid, 668168710Sstas fmt_flags)); 66924139Sjoerg } 67024139Sjoerg } 67124139Sjoerg else 67224139Sjoerg { 67324139Sjoerg i = 0; 67424139Sjoerg } 67524139Sjoerg 67624139Sjoerg /* do end-screen processing */ 67724139Sjoerg u_endscreen(i); 67824139Sjoerg 67924139Sjoerg /* now, flush the output buffer */ 68089757Sdwmalone if (fflush(stdout) != 0) 68189757Sdwmalone { 68289757Sdwmalone new_message(MT_standout, " Write error on stdout"); 68389757Sdwmalone putchar('\r'); 68489757Sdwmalone quit(1); 68589757Sdwmalone /*NOTREACHED*/ 68689757Sdwmalone } 68724139Sjoerg 68824139Sjoerg /* only do the rest if we have more displays to show */ 68924139Sjoerg if (displays) 69024139Sjoerg { 69124139Sjoerg /* switch out for new display on smart terminals */ 69224139Sjoerg if (smart_terminal) 69324139Sjoerg { 69424139Sjoerg if (overstrike) 69524139Sjoerg { 69624139Sjoerg reset_display(); 69724139Sjoerg } 69824139Sjoerg else 69924139Sjoerg { 70024139Sjoerg d_loadave = u_loadave; 70124139Sjoerg d_procstates = u_procstates; 70224139Sjoerg d_cpustates = u_cpustates; 70324139Sjoerg d_memory = u_memory; 70424142Sjoerg d_swap = u_swap; 70524139Sjoerg d_message = u_message; 70624139Sjoerg d_header = u_header; 70724139Sjoerg d_process = u_process; 70824139Sjoerg } 70924139Sjoerg } 71024139Sjoerg 71124139Sjoerg no_command = Yes; 71224139Sjoerg if (!interactive) 71324139Sjoerg { 71424139Sjoerg /* set up alarm */ 71524139Sjoerg (void) signal(SIGALRM, onalrm); 71624139Sjoerg (void) alarm((unsigned)delay); 71724139Sjoerg 71824139Sjoerg /* wait for the rest of it .... */ 71924139Sjoerg pause(); 72024139Sjoerg } 72124139Sjoerg else while (no_command) 72224139Sjoerg { 72324139Sjoerg /* assume valid command unless told otherwise */ 72424139Sjoerg no_command = No; 72524139Sjoerg 72624139Sjoerg /* set up arguments for select with timeout */ 72724139Sjoerg FD_ZERO(&readfds); 72889757Sdwmalone FD_SET(0, &readfds); /* for standard input */ 72924139Sjoerg timeout.tv_sec = delay; 73024139Sjoerg timeout.tv_usec = 0; 73124139Sjoerg 73281187Skris if (leaveflag) { 73381187Skris end_screen(); 73481187Skris exit(0); 73581187Skris } 73681187Skris 73781187Skris if (tstopflag) { 73881187Skris /* move to the lower left */ 73981187Skris end_screen(); 74081187Skris fflush(stdout); 74181187Skris 74281187Skris /* default the signal handler action */ 74381187Skris (void) signal(SIGTSTP, SIG_DFL); 74481187Skris 74581187Skris /* unblock the signal and send ourselves one */ 74681187Skris#ifdef SIGRELSE 74781187Skris sigrelse(SIGTSTP); 74881187Skris#else 74981187Skris (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1))); 75081187Skris#endif 75181187Skris (void) kill(0, SIGTSTP); 75281187Skris 75381187Skris /* reset the signal handler */ 75481187Skris (void) signal(SIGTSTP, tstop); 75581187Skris 75681187Skris /* reinit screen */ 75781187Skris reinit_screen(); 75881187Skris reset_display(); 75981187Skris tstopflag = 0; 76081187Skris goto restart; 76181187Skris } 76281187Skris 76381187Skris if (winchflag) { 76481187Skris /* reascertain the screen dimensions */ 76581187Skris get_screensize(); 76681187Skris 76781187Skris /* tell display to resize */ 76881187Skris max_topn = display_resize(); 76981187Skris 77081187Skris /* reset the signal handler */ 77181187Skris (void) signal(SIGWINCH, winch); 77281187Skris 77381187Skris reset_display(); 77481187Skris winchflag = 0; 77581187Skris goto restart; 77681187Skris } 77781187Skris 77824139Sjoerg /* wait for either input or the end of the delay period */ 77986042Sdwmalone sel_ret = select(2, &readfds, NULL, NULL, &timeout); 78086042Sdwmalone if (sel_ret < 0 && errno != EINTR) 78186042Sdwmalone quit(0); 78286042Sdwmalone if (sel_ret > 0) 78324139Sjoerg { 78424139Sjoerg int newval; 78524139Sjoerg char *errmsg; 78624139Sjoerg 78724139Sjoerg /* something to read -- clear the message area first */ 78824139Sjoerg clear_message(); 78924139Sjoerg 79024139Sjoerg /* now read it and convert to command strchr */ 79124139Sjoerg /* (use "change" as a temporary to hold strchr) */ 79286042Sdwmalone if (read(0, &ch, 1) != 1) 79389757Sdwmalone { 79489757Sdwmalone /* read error: either 0 or -1 */ 79589757Sdwmalone new_message(MT_standout, " Read error on stdin"); 79689757Sdwmalone putchar('\r'); 79789757Sdwmalone quit(1); 79889757Sdwmalone /*NOTREACHED*/ 79989757Sdwmalone } 80024139Sjoerg if ((iptr = strchr(command_chars, ch)) == NULL) 80124139Sjoerg { 80224142Sjoerg if (ch != '\r' && ch != '\n') 80324142Sjoerg { 80424142Sjoerg /* illegal command */ 80524142Sjoerg new_message(MT_standout, " Command not understood"); 80624142Sjoerg } 80724139Sjoerg putchar('\r'); 80824139Sjoerg no_command = Yes; 80924139Sjoerg } 81024139Sjoerg else 81124139Sjoerg { 81224139Sjoerg change = iptr - command_chars; 81324139Sjoerg if (overstrike && change > CMD_OSLIMIT) 81424139Sjoerg { 81524139Sjoerg /* error */ 81624139Sjoerg new_message(MT_standout, 81724139Sjoerg " Command cannot be handled by this terminal"); 81824139Sjoerg putchar('\r'); 81924139Sjoerg no_command = Yes; 82024139Sjoerg } 82124139Sjoerg else switch(change) 82224139Sjoerg { 82324139Sjoerg case CMD_redraw: /* redraw screen */ 82424139Sjoerg reset_display(); 82524139Sjoerg break; 82624139Sjoerg 82724139Sjoerg case CMD_update: /* merely update display */ 82824139Sjoerg /* is the load average high? */ 82924139Sjoerg if (system_info.load_avg[0] > LoadMax) 83024139Sjoerg { 83124139Sjoerg /* yes, go home for visual feedback */ 83224139Sjoerg go_home(); 83324139Sjoerg fflush(stdout); 83424139Sjoerg } 83524139Sjoerg break; 83624139Sjoerg 83724139Sjoerg case CMD_quit: /* quit */ 83824139Sjoerg quit(0); 83924139Sjoerg /*NOTREACHED*/ 84024139Sjoerg break; 84124139Sjoerg 84224139Sjoerg case CMD_help1: /* help */ 84324139Sjoerg case CMD_help2: 84424139Sjoerg reset_display(); 84524139Sjoerg clear(); 84624139Sjoerg show_help(); 84724139Sjoerg standout("Hit any key to continue: "); 84824139Sjoerg fflush(stdout); 84924139Sjoerg (void) read(0, &ch, 1); 85024139Sjoerg break; 85124139Sjoerg 85224139Sjoerg case CMD_errors: /* show errors */ 85324139Sjoerg if (error_count() == 0) 85424139Sjoerg { 85524139Sjoerg new_message(MT_standout, 85624139Sjoerg " Currently no errors to report."); 85724139Sjoerg putchar('\r'); 85824139Sjoerg no_command = Yes; 85924139Sjoerg } 86024139Sjoerg else 86124139Sjoerg { 86224139Sjoerg reset_display(); 86324139Sjoerg clear(); 86424139Sjoerg show_errors(); 86524139Sjoerg standout("Hit any key to continue: "); 86624139Sjoerg fflush(stdout); 86724139Sjoerg (void) read(0, &ch, 1); 86824139Sjoerg } 86924139Sjoerg break; 87024139Sjoerg 87124139Sjoerg case CMD_number1: /* new number */ 87224139Sjoerg case CMD_number2: 87324139Sjoerg new_message(MT_standout, 87424139Sjoerg "Number of processes to show: "); 87524139Sjoerg newval = readline(tempbuf1, 8, Yes); 87624139Sjoerg if (newval > -1) 87724139Sjoerg { 87824139Sjoerg if (newval > max_topn) 87924139Sjoerg { 88024139Sjoerg new_message(MT_standout | MT_delayed, 88124139Sjoerg " This terminal can only display %d processes.", 88224139Sjoerg max_topn); 88324139Sjoerg putchar('\r'); 88424139Sjoerg } 88524139Sjoerg 88624139Sjoerg if (newval == 0) 88724139Sjoerg { 88824139Sjoerg /* inhibit the header */ 88924139Sjoerg display_header(No); 89024139Sjoerg } 89124139Sjoerg else if (newval > topn && topn == 0) 89224139Sjoerg { 89324139Sjoerg /* redraw the header */ 89424139Sjoerg display_header(Yes); 89524139Sjoerg d_header = i_header; 89624139Sjoerg } 89724139Sjoerg topn = newval; 89824139Sjoerg } 89924139Sjoerg break; 90024139Sjoerg 90124139Sjoerg case CMD_delay: /* new seconds delay */ 90224139Sjoerg new_message(MT_standout, "Seconds to delay: "); 90324139Sjoerg if ((i = readline(tempbuf1, 8, Yes)) > -1) 90424139Sjoerg { 90589757Sdwmalone if ((delay = i) == 0 && getuid() != 0) 90689757Sdwmalone { 90789757Sdwmalone delay = 1; 90889757Sdwmalone } 90924139Sjoerg } 91024139Sjoerg clear_message(); 91124139Sjoerg break; 91224139Sjoerg 91324139Sjoerg case CMD_displays: /* change display count */ 91424139Sjoerg new_message(MT_standout, 91524139Sjoerg "Displays to show (currently %s): ", 91624139Sjoerg displays == -1 ? "infinite" : 91724139Sjoerg itoa(displays)); 91824139Sjoerg if ((i = readline(tempbuf1, 10, Yes)) > 0) 91924139Sjoerg { 92024139Sjoerg displays = i; 92124139Sjoerg } 92224139Sjoerg else if (i == 0) 92324139Sjoerg { 92424139Sjoerg quit(0); 92524139Sjoerg } 92624139Sjoerg clear_message(); 92724139Sjoerg break; 92824139Sjoerg 92924139Sjoerg case CMD_kill: /* kill program */ 93024139Sjoerg new_message(0, "kill "); 93124139Sjoerg if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) 93224139Sjoerg { 93324139Sjoerg if ((errmsg = kill_procs(tempbuf2)) != NULL) 93424139Sjoerg { 93566641Simp new_message(MT_standout, "%s", errmsg); 93624139Sjoerg putchar('\r'); 93724139Sjoerg no_command = Yes; 93824139Sjoerg } 93924139Sjoerg } 94024139Sjoerg else 94124139Sjoerg { 94224139Sjoerg clear_message(); 94324139Sjoerg } 94424139Sjoerg break; 94524139Sjoerg 94624139Sjoerg case CMD_renice: /* renice program */ 94724139Sjoerg new_message(0, "renice "); 94824139Sjoerg if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) 94924139Sjoerg { 95024139Sjoerg if ((errmsg = renice_procs(tempbuf2)) != NULL) 95124139Sjoerg { 95268293Simp new_message(MT_standout, "%s", errmsg); 95324139Sjoerg putchar('\r'); 95424139Sjoerg no_command = Yes; 95524139Sjoerg } 95624139Sjoerg } 95724139Sjoerg else 95824139Sjoerg { 95924139Sjoerg clear_message(); 96024139Sjoerg } 96124139Sjoerg break; 96224139Sjoerg 96324139Sjoerg case CMD_idletog: 96424139Sjoerg case CMD_idletog2: 96524139Sjoerg ps.idle = !ps.idle; 96624139Sjoerg new_message(MT_standout | MT_delayed, 96724139Sjoerg " %sisplaying idle processes.", 96824139Sjoerg ps.idle ? "D" : "Not d"); 96924139Sjoerg putchar('\r'); 97024139Sjoerg break; 97124139Sjoerg 97238090Sdes case CMD_selftog: 97338090Sdes ps.self = (ps.self == -1) ? getpid() : -1; 97438090Sdes new_message(MT_standout | MT_delayed, 97538090Sdes " %sisplaying self.", 97638090Sdes (ps.self == -1) ? "D" : "Not d"); 97738090Sdes putchar('\r'); 97838090Sdes break; 97938090Sdes 98024139Sjoerg case CMD_user: 98124139Sjoerg new_message(MT_standout, 98224139Sjoerg "Username to show: "); 98324139Sjoerg if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) 98424139Sjoerg { 98524139Sjoerg if (tempbuf2[0] == '+' && 98624139Sjoerg tempbuf2[1] == '\0') 98724139Sjoerg { 98824139Sjoerg ps.uid = -1; 98924139Sjoerg } 99024139Sjoerg else if ((i = userid(tempbuf2)) == -1) 99124139Sjoerg { 99224139Sjoerg new_message(MT_standout, 99324139Sjoerg " %s: unknown user", tempbuf2); 99424139Sjoerg no_command = Yes; 99524139Sjoerg } 99624139Sjoerg else 99724139Sjoerg { 99824139Sjoerg ps.uid = i; 99924139Sjoerg } 100024139Sjoerg putchar('\r'); 100124139Sjoerg } 100224139Sjoerg else 100324139Sjoerg { 100424139Sjoerg clear_message(); 100524139Sjoerg } 100624139Sjoerg break; 100724139Sjoerg 1008117709Sjulian case CMD_thrtog: 1009117709Sjulian ps.thread = !ps.thread; 1010117709Sjulian new_message(MT_standout | MT_delayed, 1011145073Skeramida "Displaying threads %s", 1012145073Skeramida ps.thread ? "separately" : "as a count"); 1013145073Skeramida header_text = format_header(uname_field); 1014145073Skeramida reset_display(); 1015117709Sjulian putchar('\r'); 1016117709Sjulian break; 1017146342Skeramida case CMD_wcputog: 1018146342Skeramida ps.wcpu = !ps.wcpu; 1019146342Skeramida new_message(MT_standout | MT_delayed, 1020146342Skeramida "Displaying %sCPU", 1021146342Skeramida ps.wcpu ? "W" : ""); 1022146342Skeramida header_text = format_header(uname_field); 1023146342Skeramida reset_display(); 1024146342Skeramida putchar('\r'); 1025146342Skeramida break; 1026131402Salfred case CMD_viewtog: 1027131402Salfred if (++displaymode == DISP_MAX) 1028131402Salfred displaymode = 0; 1029131402Salfred header_text = format_header(uname_field); 1030131402Salfred display_header(Yes); 1031131402Salfred d_header = i_header; 1032131402Salfred reset_display(); 1033131402Salfred break; 1034132005Salfred case CMD_viewsys: 1035132005Salfred ps.system = !ps.system; 1036132005Salfred break; 1037168710Sstas case CMD_showargs: 1038168710Sstas fmt_flags ^= FMT_SHOWARGS; 1039168710Sstas break; 104024139Sjoerg#ifdef ORDER 104124139Sjoerg case CMD_order: 104224139Sjoerg new_message(MT_standout, 104324139Sjoerg "Order to sort: "); 104424139Sjoerg if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) 104524139Sjoerg { 104624139Sjoerg if ((i = string_index(tempbuf2, statics.order_names)) == -1) 104724139Sjoerg { 104824139Sjoerg new_message(MT_standout, 104924139Sjoerg " %s: unrecognized sorting order", tempbuf2); 105024139Sjoerg no_command = Yes; 105124139Sjoerg } 105224139Sjoerg else 105324139Sjoerg { 105424139Sjoerg order_index = i; 105524139Sjoerg } 105624139Sjoerg putchar('\r'); 105724139Sjoerg } 105824139Sjoerg else 105924139Sjoerg { 106024139Sjoerg clear_message(); 106124139Sjoerg } 106224139Sjoerg break; 106324139Sjoerg#endif 1064168799Srafan case CMD_jidtog: 1065168799Srafan ps.jail = !ps.jail; 1066168799Srafan new_message(MT_standout | MT_delayed, 1067168799Srafan " %sisplaying jail id.", 1068168799Srafan ps.jail ? "D" : "Not d"); 1069168799Srafan header_text = format_header(uname_field); 1070168799Srafan reset_display(); 1071168799Srafan putchar('\r'); 1072168799Srafan break; 107324139Sjoerg 107424139Sjoerg default: 107524139Sjoerg new_message(MT_standout, " BAD CASE IN SWITCH!"); 107624139Sjoerg putchar('\r'); 107724139Sjoerg } 107824139Sjoerg } 107924139Sjoerg 108024139Sjoerg /* flush out stuff that may have been written */ 108124139Sjoerg fflush(stdout); 108224139Sjoerg } 108324139Sjoerg } 108424139Sjoerg } 108524139Sjoerg } 108624139Sjoerg 108789757Sdwmalone#ifdef DEBUG 108889757Sdwmalone fclose(debug); 108989757Sdwmalone#endif 109024139Sjoerg quit(0); 109124139Sjoerg /*NOTREACHED*/ 109224139Sjoerg} 109324139Sjoerg 109424139Sjoerg/* 109524139Sjoerg * reset_display() - reset all the display routine pointers so that entire 109624139Sjoerg * screen will get redrawn. 109724139Sjoerg */ 109824139Sjoerg 109924139Sjoergreset_display() 110024139Sjoerg 110124139Sjoerg{ 110224139Sjoerg d_loadave = i_loadave; 110324139Sjoerg d_procstates = i_procstates; 110424139Sjoerg d_cpustates = i_cpustates; 110524139Sjoerg d_memory = i_memory; 110624142Sjoerg d_swap = i_swap; 110724139Sjoerg d_message = i_message; 110824139Sjoerg d_header = i_header; 110924139Sjoerg d_process = i_process; 111024139Sjoerg} 111124139Sjoerg 111224139Sjoerg/* 111324139Sjoerg * signal handlers 111424139Sjoerg */ 111524139Sjoerg 111624139Sjoergsigret_t leave() /* exit under normal conditions -- INT handler */ 111724139Sjoerg 111824139Sjoerg{ 111981187Skris leaveflag = 1; 112024139Sjoerg} 112124139Sjoerg 112224139Sjoergsigret_t tstop(i) /* SIGTSTP handler */ 112324139Sjoerg 112424139Sjoergint i; 112524139Sjoerg 112624139Sjoerg{ 112781187Skris tstopflag = 1; 112824139Sjoerg} 112924139Sjoerg 113024139Sjoerg#ifdef SIGWINCH 113124139Sjoergsigret_t winch(i) /* SIGWINCH handler */ 113224139Sjoerg 113324139Sjoergint i; 113424139Sjoerg 113524139Sjoerg{ 113681187Skris winchflag = 1; 113724139Sjoerg} 113824139Sjoerg#endif 113924139Sjoerg 114024139Sjoergvoid quit(status) /* exit under duress */ 114124139Sjoerg 114224139Sjoergint status; 114324139Sjoerg 114424139Sjoerg{ 114524139Sjoerg end_screen(); 114624139Sjoerg exit(status); 114724139Sjoerg /*NOTREACHED*/ 114824139Sjoerg} 114924139Sjoerg 115024139Sjoergsigret_t onalrm() /* SIGALRM handler */ 115124139Sjoerg 115224139Sjoerg{ 115324139Sjoerg /* this is only used in batch mode to break out of the pause() */ 115424139Sjoerg /* return; */ 115524139Sjoerg} 115624139Sjoerg 1157