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