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