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