Deleted Added
sdiff udiff text old ( 168863 ) new ( 169257 )
full compact
1char *copyright =
2 "Copyright (c) 1984 through 1996, William LeFebvre";
3
4/*
5 * Top users/processes display for Unix
6 * Version 3
7 *
8 * This program may be freely redistributed,
9 * but this entire comment MUST remain intact.
10 *
11 * Copyright (c) 1984, 1989, William LeFebvre, Rice University
12 * Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University
13 * Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory
14 * Copyright (c) 1996, William LeFebvre, Group sys Consulting
15 *
16 * $FreeBSD: head/contrib/top/top.c 168863 2007-04-19 14:24:54Z rafan $
17 */
18
19/*
20 * See the file "Changes" for information on version-to-version changes.
21 */
22
23/*
24 * This file contains "main" and other high-level routines.
25 */
26
27/*
28 * The following preprocessor variables, when defined, are used to
29 * distinguish between different Unix implementations:
30 *
31 * SIGHOLD - use SVR4 sighold function when defined
32 * SIGRELSE - use SVR4 sigrelse function when defined
33 * FD_SET - macros FD_SET and FD_ZERO are used when defined
34 */
35
36#include "os.h"
37#include <errno.h>
38#include <signal.h>
39#include <setjmp.h>
40#include <ctype.h>
41#include <sys/time.h>
42
43/* includes specific to top */
44#include "display.h" /* interface to display package */
45#include "screen.h" /* interface to screen package */
46#include "top.h"
47#include "top.local.h"
48#include "boolean.h"
49#include "machine.h"
50#include "utils.h"
51
52/* Size of the stdio buffer given to stdout */
53#define Buffersize 2048
54
55/* The buffer that stdio will use */
56char stdoutbuf[Buffersize];
57
58/* build Signal masks */
59#define Smask(s) (1 << ((s) - 1))
60
61/* for getopt: */
62extern int optind;
63extern char *optarg;
64
65/* imported from screen.c */
66extern int overstrike;
67
68static int fmt_flags = 0;
69
70/* signal handling routines */
71sigret_t leave();
72sigret_t onalrm();
73sigret_t tstop();
74#ifdef SIGWINCH
75sigret_t winch();
76#endif
77
78volatile sig_atomic_t leaveflag;
79volatile sig_atomic_t tstopflag;
80volatile sig_atomic_t winchflag;
81
82/* internal routines */
83void quit();
84
85/* values which need to be accessed by signal handlers */
86static int max_topn; /* maximum displayable processes */
87
88/* miscellaneous things */
89struct process_select ps;
90char *myname = "top";
91jmp_buf jmp_int;
92
93/* routines that don't return int */
94
95char *username();
96char *ctime();
97char *kill_procs();
98char *renice_procs();
99
100#ifdef ORDER
101extern int (*compares[])();
102#else
103extern int proc_compare();
104extern int io_compare();
105#endif
106time_t time();
107
108caddr_t get_process_info();
109
110/* different routines for displaying the user's identification */
111/* (values assigned to get_userid) */
112char *username();
113char *itoa7();
114
115/* display routines that need to be predeclared */
116int i_loadave();
117int u_loadave();
118int i_procstates();
119int u_procstates();
120int i_cpustates();
121int u_cpustates();
122int i_memory();
123int u_memory();
124int i_swap();
125int u_swap();
126int i_message();
127int u_message();
128int i_header();
129int u_header();
130int i_process();
131int u_process();
132
133/* pointers to display routines */
134int (*d_loadave)() = i_loadave;
135int (*d_procstates)() = i_procstates;
136int (*d_cpustates)() = i_cpustates;
137int (*d_memory)() = i_memory;
138int (*d_swap)() = i_swap;
139int (*d_message)() = i_message;
140int (*d_header)() = i_header;
141int (*d_process)() = i_process;
142
143
144main(argc, argv)
145
146int argc;
147char *argv[];
148
149{
150 register int i;
151 register int active_procs;
152 register int change;
153
154 struct system_info system_info;
155 struct statics statics;
156 caddr_t processes;
157
158 static char tempbuf1[50];
159 static char tempbuf2[50];
160 int old_sigmask; /* only used for BSD-style signals */
161 int topn = Default_TOPN;
162 int delay = Default_DELAY;
163 int displays = 0; /* indicates unspecified */
164 int sel_ret = 0;
165 time_t curr_time;
166 char *(*get_userid)() = username;
167 char *uname_field = "USERNAME";
168 char *header_text;
169 char *env_top;
170 char **preset_argv;
171 int preset_argc = 0;
172 char **av;
173 int ac;
174 char dostates = No;
175 char do_unames = Yes;
176 char interactive = Maybe;
177 char warnings = 0;
178#if Default_TOPN == Infinity
179 char topn_specified = No;
180#endif
181 char ch;
182 char *iptr;
183 char no_command = 1;
184 struct timeval timeout;
185#ifdef ORDER
186 char *order_name = NULL;
187 int order_index = 0;
188#endif
189#ifndef FD_SET
190 /* FD_SET and friends are not present: fake it */
191 typedef int fd_set;
192#define FD_ZERO(x) (*(x) = 0)
193#define FD_SET(f, x) (*(x) = 1<<f)
194#endif
195 fd_set readfds;
196
197#ifdef ORDER
198 static char command_chars[] = "\f qh?en#sdkriIutHmSCajo";
199#else
200 static char command_chars[] = "\f qh?en#sdkriIutHmSCaj";
201#endif
202/* these defines enumerate the "strchr"s of the commands in command_chars */
203#define CMD_redraw 0
204#define CMD_update 1
205#define CMD_quit 2
206#define CMD_help1 3
207#define CMD_help2 4
208#define CMD_OSLIMIT 4 /* terminals with OS can only handle commands */
209#define CMD_errors 5 /* less than or equal to CMD_OSLIMIT */
210#define CMD_number1 6
211#define CMD_number2 7
212#define CMD_delay 8
213#define CMD_displays 9
214#define CMD_kill 10
215#define CMD_renice 11
216#define CMD_idletog 12
217#define CMD_idletog2 13
218#define CMD_user 14
219#define CMD_selftog 15
220#define CMD_thrtog 16
221#define CMD_viewtog 17
222#define CMD_viewsys 18
223#define CMD_wcputog 19
224#define CMD_showargs 20
225#define CMD_jidtog 21
226#ifdef ORDER
227#define CMD_order 22
228#endif
229
230 /* set the buffer for stdout */
231#ifdef DEBUG
232 extern FILE *debug;
233 debug = fopen("debug.run", "w");
234 setbuffer(stdout, NULL, 0);
235#else
236 setbuffer(stdout, stdoutbuf, Buffersize);
237#endif
238
239 /* get our name */
240 if (argc > 0)
241 {
242 if ((myname = strrchr(argv[0], '/')) == 0)
243 {
244 myname = argv[0];
245 }
246 else
247 {
248 myname++;
249 }
250 }
251
252 /* initialize some selection options */
253 ps.idle = Yes;
254 ps.self = -1;
255 ps.system = No;
256 ps.uid = -1;
257 ps.thread = No;
258 ps.wcpu = 1;
259 ps.jail = No;
260 ps.command = NULL;
261
262 /* get preset options from the environment */
263 if ((env_top = getenv("TOP")) != NULL)
264 {
265 av = preset_argv = argparse(env_top, &preset_argc);
266 ac = preset_argc;
267
268 /* set the dummy argument to an explanatory message, in case
269 getopt encounters a bad argument */
270 preset_argv[0] = "while processing environment";
271 }
272
273 /* process options */
274 do {
275 /* if we're done doing the presets, then process the real arguments */
276 if (preset_argc == 0)
277 {
278 ac = argc;
279 av = argv;
280
281 /* this should keep getopt happy... */
282 optind = 1;
283 }
284
285 while ((i = getopt(ac, av, "CSIHabijnquvs:d:U:m:o:t")) != EOF)
286 {
287 switch(i)
288 {
289 case 'v': /* show version number */
290 fprintf(stderr, "%s: version %s\n",
291 myname, version_string());
292 exit(1);
293 break;
294
295 case 'u': /* toggle uid/username display */
296 do_unames = !do_unames;
297 break;
298
299 case 'U': /* display only username's processes */
300 if ((ps.uid = userid(optarg)) == -1)
301 {
302 fprintf(stderr, "%s: unknown user\n", optarg);
303 exit(1);
304 }
305 break;
306
307 case 'S': /* show system processes */
308 ps.system = !ps.system;
309 break;
310
311 case 'I': /* show idle processes */
312 ps.idle = !ps.idle;
313 break;
314
315 case 'i': /* go interactive regardless */
316 interactive = Yes;
317 break;
318
319 case 'n': /* batch, or non-interactive */
320 case 'b':
321 interactive = No;
322 break;
323
324 case 'a':
325 fmt_flags ^= FMT_SHOWARGS;
326 break;
327
328 case 'd': /* number of displays to show */
329 if ((i = atoiwi(optarg)) == Invalid || i == 0)
330 {
331 fprintf(stderr,
332 "%s: warning: display count should be positive -- option ignored\n",
333 myname);
334 warnings++;
335 }
336 else
337 {
338 displays = i;
339 }
340 break;
341
342 case 's':
343 if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
344 {
345 fprintf(stderr,
346 "%s: warning: seconds delay should be positive -- using default\n",
347 myname);
348 delay = Default_DELAY;
349 warnings++;
350 }
351 break;
352
353 case 'q': /* be quick about it */
354 /* only allow this if user is really root */
355 if (getuid() == 0)
356 {
357 /* be very un-nice! */
358 (void) nice(-20);
359 }
360 else
361 {
362 fprintf(stderr,
363 "%s: warning: `-q' option can only be used by root\n",
364 myname);
365 warnings++;
366 }
367 break;
368
369 case 'm': /* select display mode */
370 if (strcmp(optarg, "io") == 0) {
371 displaymode = DISP_IO;
372 } else if (strcmp(optarg, "cpu") == 0) {
373 displaymode = DISP_CPU;
374 } else {
375 fprintf(stderr,
376 "%s: warning: `-m' option can only take args "
377 "'io' or 'cpu'\n",
378 myname);
379 exit(1);
380 }
381 break;
382
383 case 'o': /* select sort order */
384#ifdef ORDER
385 order_name = optarg;
386#else
387 fprintf(stderr,
388 "%s: this platform does not support arbitrary ordering. Sorry.\n",
389 myname);
390 warnings++;
391#endif
392 break;
393
394 case 't':
395 ps.self = (ps.self == -1) ? getpid() : -1;
396 break;
397
398 case 'C':
399 ps.wcpu = !ps.wcpu;
400 break;
401
402 case 'H':
403 ps.thread = !ps.thread;
404 break;
405
406 case 'j':
407 ps.jail = !ps.jail;
408 break;
409
410 default:
411 fprintf(stderr,
412"Top version %s\n"
413"Usage: %s [-abCHIijnqStuv] [-d count] [-m io | cpu] [-o field] [-s time]\n"
414" [-U username] [number]\n",
415 version_string(), myname);
416 exit(1);
417 }
418 }
419
420 /* get count of top processes to display (if any) */
421 if (optind < ac)
422 {
423 if ((topn = atoiwi(av[optind])) == Invalid)
424 {
425 fprintf(stderr,
426 "%s: warning: process display count should be non-negative -- using default\n",
427 myname);
428 warnings++;
429 }
430#if Default_TOPN == Infinity
431 else
432 {
433 topn_specified = Yes;
434 }
435#endif
436 }
437
438 /* tricky: remember old value of preset_argc & set preset_argc = 0 */
439 i = preset_argc;
440 preset_argc = 0;
441
442 /* repeat only if we really did the preset arguments */
443 } while (i != 0);
444
445 /* set constants for username/uid display correctly */
446 if (!do_unames)
447 {
448 uname_field = " UID ";
449 get_userid = itoa7;
450 }
451
452 /* initialize the kernel memory interface */
453 if (machine_init(&statics) == -1)
454 {
455 exit(1);
456 }
457
458#ifdef ORDER
459 /* determine sorting order index, if necessary */
460 if (order_name != NULL)
461 {
462 if ((order_index = string_index(order_name, statics.order_names)) == -1)
463 {
464 char **pp;
465
466 fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
467 myname, order_name);
468 fprintf(stderr, "\tTry one of these:");
469 pp = statics.order_names;
470 while (*pp != NULL)
471 {
472 fprintf(stderr, " %s", *pp++);
473 }
474 fputc('\n', stderr);
475 exit(1);
476 }
477 }
478#endif
479
480#ifdef no_initialization_needed
481 /* initialize the hashing stuff */
482 if (do_unames)
483 {
484 init_hash();
485 }
486#endif
487
488 /* initialize termcap */
489 init_termcap(interactive);
490
491 /* get the string to use for the process area header */
492 header_text = format_header(uname_field);
493
494 /* initialize display interface */
495 if ((max_topn = display_init(&statics)) == -1)
496 {
497 fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);
498 exit(4);
499 }
500
501 /* print warning if user requested more processes than we can display */
502 if (topn > max_topn)
503 {
504 fprintf(stderr,
505 "%s: warning: this terminal can only display %d processes.\n",
506 myname, max_topn);
507 warnings++;
508 }
509
510 /* adjust for topn == Infinity */
511 if (topn == Infinity)
512 {
513 /*
514 * For smart terminals, infinity really means everything that can
515 * be displayed, or Largest.
516 * On dumb terminals, infinity means every process in the system!
517 * We only really want to do that if it was explicitly specified.
518 * This is always the case when "Default_TOPN != Infinity". But if
519 * topn wasn't explicitly specified and we are on a dumb terminal
520 * and the default is Infinity, then (and only then) we use
521 * "Nominal_TOPN" instead.
522 */
523#if Default_TOPN == Infinity
524 topn = smart_terminal ? Largest :
525 (topn_specified ? Largest : Nominal_TOPN);
526#else
527 topn = Largest;
528#endif
529 }
530
531 /* set header display accordingly */
532 display_header(topn > 0);
533
534 /* determine interactive state */
535 if (interactive == Maybe)
536 {
537 interactive = smart_terminal;
538 }
539
540 /* if # of displays not specified, fill it in */
541 if (displays == 0)
542 {
543 displays = smart_terminal ? Infinity : 1;
544 }
545
546 /* hold interrupt signals while setting up the screen and the handlers */
547#ifdef SIGHOLD
548 sighold(SIGINT);
549 sighold(SIGQUIT);
550 sighold(SIGTSTP);
551#else
552 old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));
553#endif
554 init_screen();
555 (void) signal(SIGINT, leave);
556 (void) signal(SIGQUIT, leave);
557 (void) signal(SIGTSTP, tstop);
558#ifdef SIGWINCH
559 (void) signal(SIGWINCH, winch);
560#endif
561#ifdef SIGRELSE
562 sigrelse(SIGINT);
563 sigrelse(SIGQUIT);
564 sigrelse(SIGTSTP);
565#else
566 (void) sigsetmask(old_sigmask);
567#endif
568 if (warnings)
569 {
570 fputs("....", stderr);
571 fflush(stderr); /* why must I do this? */
572 sleep((unsigned)(3 * warnings));
573 fputc('\n', stderr);
574 }
575
576restart:
577
578 /*
579 * main loop -- repeat while display count is positive or while it
580 * indicates infinity (by being -1)
581 */
582
583 while ((displays == -1) || (displays-- > 0))
584 {
585 int (*compare)();
586
587
588 /* get the current stats */
589 get_system_info(&system_info);
590
591#ifdef ORDER
592 compare = compares[order_index];
593#else
594 if (displaymode == DISP_CPU)
595 compare = proc_compare;
596 else
597 compare = io_compare;
598#endif
599
600 /* get the current set of processes */
601 processes =
602 get_process_info(&system_info, &ps, compare);
603
604 /* display the load averages */
605 (*d_loadave)(system_info.last_pid,
606 system_info.load_avg);
607
608 /* display the current time */
609 /* this method of getting the time SHOULD be fairly portable */
610 time(&curr_time);
611 i_uptime(&system_info.boottime, &curr_time);
612 i_timeofday(&curr_time);
613
614 /* display process state breakdown */
615 (*d_procstates)(system_info.p_total,
616 system_info.procstates);
617
618 /* display the cpu state percentage breakdown */
619 if (dostates) /* but not the first time */
620 {
621 (*d_cpustates)(system_info.cpustates);
622 }
623 else
624 {
625 /* we'll do it next time */
626 if (smart_terminal)
627 {
628 z_cpustates();
629 }
630 else
631 {
632 putchar('\n');
633 }
634 dostates = Yes;
635 }
636
637 /* display memory stats */
638 (*d_memory)(system_info.memory);
639
640 /* display swap stats */
641 (*d_swap)(system_info.swap);
642
643 /* handle message area */
644 (*d_message)();
645
646 /* update the header area */
647 (*d_header)(header_text);
648
649 if (topn > 0)
650 {
651 /* determine number of processes to actually display */
652 /* this number will be the smallest of: active processes,
653 number user requested, number current screen accomodates */
654 active_procs = system_info.P_ACTIVE;
655 if (active_procs > topn)
656 {
657 active_procs = topn;
658 }
659 if (active_procs > max_topn)
660 {
661 active_procs = max_topn;
662 }
663
664 /* now show the top "n" processes. */
665 for (i = 0; i < active_procs; i++)
666 {
667 (*d_process)(i, format_next_process(processes, get_userid,
668 fmt_flags));
669 }
670 }
671 else
672 {
673 i = 0;
674 }
675
676 /* do end-screen processing */
677 u_endscreen(i);
678
679 /* now, flush the output buffer */
680 if (fflush(stdout) != 0)
681 {
682 new_message(MT_standout, " Write error on stdout");
683 putchar('\r');
684 quit(1);
685 /*NOTREACHED*/
686 }
687
688 /* only do the rest if we have more displays to show */
689 if (displays)
690 {
691 /* switch out for new display on smart terminals */
692 if (smart_terminal)
693 {
694 if (overstrike)
695 {
696 reset_display();
697 }
698 else
699 {
700 d_loadave = u_loadave;
701 d_procstates = u_procstates;
702 d_cpustates = u_cpustates;
703 d_memory = u_memory;
704 d_swap = u_swap;
705 d_message = u_message;
706 d_header = u_header;
707 d_process = u_process;
708 }
709 }
710
711 no_command = Yes;
712 if (!interactive)
713 {
714 /* set up alarm */
715 (void) signal(SIGALRM, onalrm);
716 (void) alarm((unsigned)delay);
717
718 /* wait for the rest of it .... */
719 pause();
720 }
721 else while (no_command)
722 {
723 /* assume valid command unless told otherwise */
724 no_command = No;
725
726 /* set up arguments for select with timeout */
727 FD_ZERO(&readfds);
728 FD_SET(0, &readfds); /* for standard input */
729 timeout.tv_sec = delay;
730 timeout.tv_usec = 0;
731
732 if (leaveflag) {
733 end_screen();
734 exit(0);
735 }
736
737 if (tstopflag) {
738 /* move to the lower left */
739 end_screen();
740 fflush(stdout);
741
742 /* default the signal handler action */
743 (void) signal(SIGTSTP, SIG_DFL);
744
745 /* unblock the signal and send ourselves one */
746#ifdef SIGRELSE
747 sigrelse(SIGTSTP);
748#else
749 (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
750#endif
751 (void) kill(0, SIGTSTP);
752
753 /* reset the signal handler */
754 (void) signal(SIGTSTP, tstop);
755
756 /* reinit screen */
757 reinit_screen();
758 reset_display();
759 tstopflag = 0;
760 goto restart;
761 }
762
763 if (winchflag) {
764 /* reascertain the screen dimensions */
765 get_screensize();
766
767 /* tell display to resize */
768 max_topn = display_resize();
769
770 /* reset the signal handler */
771 (void) signal(SIGWINCH, winch);
772
773 reset_display();
774 winchflag = 0;
775 goto restart;
776 }
777
778 /* wait for either input or the end of the delay period */
779 sel_ret = select(2, &readfds, NULL, NULL, &timeout);
780 if (sel_ret < 0 && errno != EINTR)
781 quit(0);
782 if (sel_ret > 0)
783 {
784 int newval;
785 char *errmsg;
786
787 /* something to read -- clear the message area first */
788 clear_message();
789
790 /* now read it and convert to command strchr */
791 /* (use "change" as a temporary to hold strchr) */
792 if (read(0, &ch, 1) != 1)
793 {
794 /* read error: either 0 or -1 */
795 new_message(MT_standout, " Read error on stdin");
796 putchar('\r');
797 quit(1);
798 /*NOTREACHED*/
799 }
800 if ((iptr = strchr(command_chars, ch)) == NULL)
801 {
802 if (ch != '\r' && ch != '\n')
803 {
804 /* illegal command */
805 new_message(MT_standout, " Command not understood");
806 }
807 putchar('\r');
808 no_command = Yes;
809 }
810 else
811 {
812 change = iptr - command_chars;
813 if (overstrike && change > CMD_OSLIMIT)
814 {
815 /* error */
816 new_message(MT_standout,
817 " Command cannot be handled by this terminal");
818 putchar('\r');
819 no_command = Yes;
820 }
821 else switch(change)
822 {
823 case CMD_redraw: /* redraw screen */
824 reset_display();
825 break;
826
827 case CMD_update: /* merely update display */
828 /* is the load average high? */
829 if (system_info.load_avg[0] > LoadMax)
830 {
831 /* yes, go home for visual feedback */
832 go_home();
833 fflush(stdout);
834 }
835 break;
836
837 case CMD_quit: /* quit */
838 quit(0);
839 /*NOTREACHED*/
840 break;
841
842 case CMD_help1: /* help */
843 case CMD_help2:
844 reset_display();
845 clear();
846 show_help();
847 standout("Hit any key to continue: ");
848 fflush(stdout);
849 (void) read(0, &ch, 1);
850 break;
851
852 case CMD_errors: /* show errors */
853 if (error_count() == 0)
854 {
855 new_message(MT_standout,
856 " Currently no errors to report.");
857 putchar('\r');
858 no_command = Yes;
859 }
860 else
861 {
862 reset_display();
863 clear();
864 show_errors();
865 standout("Hit any key to continue: ");
866 fflush(stdout);
867 (void) read(0, &ch, 1);
868 }
869 break;
870
871 case CMD_number1: /* new number */
872 case CMD_number2:
873 new_message(MT_standout,
874 "Number of processes to show: ");
875 newval = readline(tempbuf1, 8, Yes);
876 if (newval > -1)
877 {
878 if (newval > max_topn)
879 {
880 new_message(MT_standout | MT_delayed,
881 " This terminal can only display %d processes.",
882 max_topn);
883 putchar('\r');
884 }
885
886 if (newval == 0)
887 {
888 /* inhibit the header */
889 display_header(No);
890 }
891 else if (newval > topn && topn == 0)
892 {
893 /* redraw the header */
894 display_header(Yes);
895 d_header = i_header;
896 }
897 topn = newval;
898 }
899 break;
900
901 case CMD_delay: /* new seconds delay */
902 new_message(MT_standout, "Seconds to delay: ");
903 if ((i = readline(tempbuf1, 8, Yes)) > -1)
904 {
905 if ((delay = i) == 0 && getuid() != 0)
906 {
907 delay = 1;
908 }
909 }
910 clear_message();
911 break;
912
913 case CMD_displays: /* change display count */
914 new_message(MT_standout,
915 "Displays to show (currently %s): ",
916 displays == -1 ? "infinite" :
917 itoa(displays));
918 if ((i = readline(tempbuf1, 10, Yes)) > 0)
919 {
920 displays = i;
921 }
922 else if (i == 0)
923 {
924 quit(0);
925 }
926 clear_message();
927 break;
928
929 case CMD_kill: /* kill program */
930 new_message(0, "kill ");
931 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
932 {
933 if ((errmsg = kill_procs(tempbuf2)) != NULL)
934 {
935 new_message(MT_standout, "%s", errmsg);
936 putchar('\r');
937 no_command = Yes;
938 }
939 }
940 else
941 {
942 clear_message();
943 }
944 break;
945
946 case CMD_renice: /* renice program */
947 new_message(0, "renice ");
948 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
949 {
950 if ((errmsg = renice_procs(tempbuf2)) != NULL)
951 {
952 new_message(MT_standout, "%s", errmsg);
953 putchar('\r');
954 no_command = Yes;
955 }
956 }
957 else
958 {
959 clear_message();
960 }
961 break;
962
963 case CMD_idletog:
964 case CMD_idletog2:
965 ps.idle = !ps.idle;
966 new_message(MT_standout | MT_delayed,
967 " %sisplaying idle processes.",
968 ps.idle ? "D" : "Not d");
969 putchar('\r');
970 break;
971
972 case CMD_selftog:
973 ps.self = (ps.self == -1) ? getpid() : -1;
974 new_message(MT_standout | MT_delayed,
975 " %sisplaying self.",
976 (ps.self == -1) ? "D" : "Not d");
977 putchar('\r');
978 break;
979
980 case CMD_user:
981 new_message(MT_standout,
982 "Username to show: ");
983 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
984 {
985 if (tempbuf2[0] == '+' &&
986 tempbuf2[1] == '\0')
987 {
988 ps.uid = -1;
989 }
990 else if ((i = userid(tempbuf2)) == -1)
991 {
992 new_message(MT_standout,
993 " %s: unknown user", tempbuf2);
994 no_command = Yes;
995 }
996 else
997 {
998 ps.uid = i;
999 }
1000 putchar('\r');
1001 }
1002 else
1003 {
1004 clear_message();
1005 }
1006 break;
1007
1008 case CMD_thrtog:
1009 ps.thread = !ps.thread;
1010 new_message(MT_standout | MT_delayed,
1011 "Displaying threads %s",
1012 ps.thread ? "separately" : "as a count");
1013 header_text = format_header(uname_field);
1014 reset_display();
1015 putchar('\r');
1016 break;
1017 case CMD_wcputog:
1018 ps.wcpu = !ps.wcpu;
1019 new_message(MT_standout | MT_delayed,
1020 "Displaying %sCPU",
1021 ps.wcpu ? "W" : "");
1022 header_text = format_header(uname_field);
1023 reset_display();
1024 putchar('\r');
1025 break;
1026 case CMD_viewtog:
1027 if (++displaymode == DISP_MAX)
1028 displaymode = 0;
1029 header_text = format_header(uname_field);
1030 display_header(Yes);
1031 d_header = i_header;
1032 reset_display();
1033 break;
1034 case CMD_viewsys:
1035 ps.system = !ps.system;
1036 break;
1037 case CMD_showargs:
1038 fmt_flags ^= FMT_SHOWARGS;
1039 break;
1040#ifdef ORDER
1041 case CMD_order:
1042 new_message(MT_standout,
1043 "Order to sort: ");
1044 if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
1045 {
1046 if ((i = string_index(tempbuf2, statics.order_names)) == -1)
1047 {
1048 new_message(MT_standout,
1049 " %s: unrecognized sorting order", tempbuf2);
1050 no_command = Yes;
1051 }
1052 else
1053 {
1054 order_index = i;
1055 }
1056 putchar('\r');
1057 }
1058 else
1059 {
1060 clear_message();
1061 }
1062 break;
1063#endif
1064 case CMD_jidtog:
1065 ps.jail = !ps.jail;
1066 new_message(MT_standout | MT_delayed,
1067 " %sisplaying jail id.",
1068 ps.jail ? "D" : "Not d");
1069 header_text = format_header(uname_field);
1070 reset_display();
1071 putchar('\r');
1072 break;
1073
1074 default:
1075 new_message(MT_standout, " BAD CASE IN SWITCH!");
1076 putchar('\r');
1077 }
1078 }
1079
1080 /* flush out stuff that may have been written */
1081 fflush(stdout);
1082 }
1083 }
1084 }
1085 }
1086
1087#ifdef DEBUG
1088 fclose(debug);
1089#endif
1090 quit(0);
1091 /*NOTREACHED*/
1092}
1093
1094/*
1095 * reset_display() - reset all the display routine pointers so that entire
1096 * screen will get redrawn.
1097 */
1098
1099reset_display()
1100
1101{
1102 d_loadave = i_loadave;
1103 d_procstates = i_procstates;
1104 d_cpustates = i_cpustates;
1105 d_memory = i_memory;
1106 d_swap = i_swap;
1107 d_message = i_message;
1108 d_header = i_header;
1109 d_process = i_process;
1110}
1111
1112/*
1113 * signal handlers
1114 */
1115
1116sigret_t leave() /* exit under normal conditions -- INT handler */
1117
1118{
1119 leaveflag = 1;
1120}
1121
1122sigret_t tstop(i) /* SIGTSTP handler */
1123
1124int i;
1125
1126{
1127 tstopflag = 1;
1128}
1129
1130#ifdef SIGWINCH
1131sigret_t winch(i) /* SIGWINCH handler */
1132
1133int i;
1134
1135{
1136 winchflag = 1;
1137}
1138#endif
1139
1140void quit(status) /* exit under duress */
1141
1142int status;
1143
1144{
1145 end_screen();
1146 exit(status);
1147 /*NOTREACHED*/
1148}
1149
1150sigret_t onalrm() /* SIGALRM handler */
1151
1152{
1153 /* this is only used in batch mode to break out of the pause() */
1154 /* return; */
1155}
1156