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