📄 top.c
字号:
char *copyright = "Copyright (c) 1984 through 2004, William LeFebvre";/* * Top users/processes display for Unix * Version 3 * * This program may be freely redistributed, * but this entire comment MUST remain intact. * * Copyright (c) 1984, 1989, William LeFebvre, Rice University * Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University * Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory * Copyright (c) 1996, William LeFebvre, Group sys Consulting *//* * See the file "Changes" for information on version-to-version changes. *//* * This file contains "main" and other high-level routines. *//* * The following preprocessor variables, when defined, are used to * distinguish between different Unix implementations: * * SIGHOLD - use SVR4 sighold function when defined * SIGRELSE - use SVR4 sigrelse function when defined * FD_SET - macros FD_SET and FD_ZERO are used when defined */#include "os.h"#include <signal.h>#include <setjmp.h>#include <ctype.h>#include <sys/time.h>/* includes specific to top */#include "display.h" /* interface to display package */#include "screen.h" /* interface to screen package */#include "top.h"#include "top.local.h"#include "boolean.h"#include "machine.h"#include "utils.h"/* Size of the stdio buffer given to stdout */#define Buffersize 2048/* The buffer that stdio will use */char stdoutbuf[Buffersize];/* build Signal masks */#define Smask(s) (1 << ((s) - 1))/* for getopt: */extern int optind;extern char *optarg;/* imported from screen.c */extern int overstrike;/* signal handling routines */sigret_t leave();sigret_t onalrm();sigret_t tstop();#ifdef SIGWINCHsigret_t winch();#endif/* internal routines */void quit();/* values which need to be accessed by signal handlers */static int max_topn; /* maximum displayable processes *//* miscellaneous things */char *myname = "top";jmp_buf jmp_int;/* routines that don't return int */char *username();char *ctime();char *kill_procs();char *renice_procs();#ifdef ORDERextern int (*proc_compares[])();#elseextern int proc_compare();#endiftime_t time();caddr_t get_process_info();/* different routines for displaying the user's identification *//* (values assigned to get_userid) */char *username();char *itoa7();/* display routines that need to be predeclared */int i_loadave();int u_loadave();int i_procstates();int u_procstates();int i_cpustates();int u_cpustates();int i_memory();int u_memory();int i_message();int u_message();int i_header();int u_header();int i_process();int u_process();/* pointers to display routines */int (*d_loadave)() = i_loadave;int (*d_procstates)() = i_procstates;int (*d_cpustates)() = i_cpustates;int (*d_memory)() = i_memory;int (*d_message)() = i_message;int (*d_header)() = i_header;int (*d_process)() = i_process;main(argc, argv)int argc;char *argv[];{ register int i; register int active_procs; register int change; struct system_info system_info; struct statics statics; caddr_t processes; static char tempbuf1[50]; static char tempbuf2[50]; int old_sigmask; /* only used for BSD-style signals */ int topn = Default_TOPN; int delay = Default_DELAY; int displays = 0; /* indicates unspecified */ time_t curr_time; char *(*get_userid)() = username; char *uname_field = "USERNAME"; char *header_text; char *env_top; char **preset_argv; int preset_argc = 0; char **av; int ac; char dostates = No; char do_unames = Yes; char interactive = Maybe; char warnings = 0;#if Default_TOPN == Infinity char topn_specified = No;#endif char ch; char *iptr; char no_command = 1; struct timeval timeout; struct process_select ps;#ifdef ORDER char *order_name = NULL; int order_index = 0;#endif#ifndef FD_SET /* FD_SET and friends are not present: fake it */ typedef int fd_set;#define FD_ZERO(x) (*(x) = 0)#define FD_SET(f, x) (*(x) = 1<<f)#endif fd_set readfds;#ifdef ORDER static char command_chars[] = "\f qh?en#sdkriIuo";#else static char command_chars[] = "\f qh?en#sdkriIu";#endif/* these defines enumerate the "strchr"s of the commands in command_chars */#define CMD_redraw 0#define CMD_update 1#define CMD_quit 2#define CMD_help1 3#define CMD_help2 4#define CMD_OSLIMIT 4 /* terminals with OS can only handle commands */#define CMD_errors 5 /* less than or equal to CMD_OSLIMIT */#define CMD_number1 6#define CMD_number2 7#define CMD_delay 8#define CMD_displays 9#define CMD_kill 10#define CMD_renice 11#define CMD_idletog 12#define CMD_idletog2 13#define CMD_user 14#ifdef ORDER#define CMD_order 15#endif /* set the buffer for stdout */#ifdef DEBUG extern FILE *debug; debug = fopen("debug.run", "w"); setbuffer(stdout, NULL, 0);#else setbuffer(stdout, stdoutbuf, Buffersize);#endif /* get our name */ if (argc > 0) { if ((myname = strrchr(argv[0], '/')) == 0) { myname = argv[0]; } else { myname++; } } /* initialize some selection options */ ps.idle = Yes; ps.system = No; ps.uid = -1; ps.command = NULL; /* get preset options from the environment */ if ((env_top = getenv("TOP")) != NULL) { av = preset_argv = argparse(env_top, &preset_argc); ac = preset_argc; /* set the dummy argument to an explanatory message, in case getopt encounters a bad argument */ preset_argv[0] = "while processing environment"; } /* process options */ do { /* if we're done doing the presets, then process the real arguments */ if (preset_argc == 0) { ac = argc; av = argv; /* this should keep getopt happy... */ optind = 1; } while ((i = getopt(ac, av, "SIbinquvs:d:U:o:")) != EOF) { switch(i) { case 'v': /* show version number */ fprintf(stderr, "%s: version %s\n", myname, version_string()); exit(1); break; case 'u': /* toggle uid/username display */ do_unames = !do_unames; break; case 'U': /* display only username's processes */ if ((ps.uid = userid(optarg)) == -1) { fprintf(stderr, "%s: unknown user\n", optarg); exit(1); } break; case 'S': /* show system processes */ ps.system = !ps.system; break; case 'I': /* show idle processes */ ps.idle = !ps.idle; break; case 'i': /* go interactive regardless */ interactive = Yes; break; case 'n': /* batch, or non-interactive */ case 'b': interactive = No; break; case 'd': /* number of displays to show */ if ((i = atoiwi(optarg)) == Invalid || i == 0) { fprintf(stderr, "%s: warning: display count should be positive -- option ignored\n", myname); warnings++; } else { displays = i; } break; case 's': if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0)) { fprintf(stderr, "%s: warning: seconds delay should be positive -- using default\n", myname); delay = Default_DELAY; warnings++; } break; case 'q': /* be quick about it */ /* only allow this if user is really root */ if (getuid() == 0) { /* be very un-nice! */ (void) nice(-20); } else { fprintf(stderr, "%s: warning: `-q' option can only be used by root\n", myname); warnings++; } break; case 'o': /* select sort order */#ifdef ORDER order_name = optarg;#else fprintf(stderr, "%s: this platform does not support arbitrary ordering. Sorry.\n", myname); warnings++;#endif break; default: fprintf(stderr, "\Top version %s\n\Usage: %s [-ISbinqu] [-d x] [-s x] [-o field] [-U username] [number]\n", version_string(), myname); exit(1); } } /* get count of top processes to display (if any) */ if (optind < ac) { if ((topn = atoiwi(av[optind])) == Invalid) { fprintf(stderr, "%s: warning: process display count should be non-negative -- using default\n", myname); warnings++; }#if Default_TOPN == Infinity else { topn_specified = Yes; }#endif } /* tricky: remember old value of preset_argc & set preset_argc = 0 */ i = preset_argc; preset_argc = 0; /* repeat only if we really did the preset arguments */ } while (i != 0); /* set constants for username/uid display correctly */ if (!do_unames) { uname_field = " UID "; get_userid = itoa7; } /* initialize the kernel memory interface */ if (machine_init(&statics) == -1) { exit(1); }#ifdef ORDER /* determine sorting order index, if necessary */ if (order_name != NULL) { if ((order_index = string_index(order_name, statics.order_names)) == -1) { char **pp; fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n", myname, order_name); fprintf(stderr, "\tTry one of these:"); pp = statics.order_names; while (*pp != NULL) { fprintf(stderr, " %s", *pp++); } fputc('\n', stderr); exit(1); } }#endif#ifdef no_initialization_needed /* initialize the hashing stuff */ if (do_unames) { init_hash(); }#endif /* initialize termcap */ init_termcap(interactive); /* get the string to use for the process area header */ header_text = format_header(uname_field); /* initialize display interface */ if ((max_topn = display_init(&statics)) == -1) { fprintf(stderr, "%s: can't allocate sufficient memory\n", myname); exit(4); } /* print warning if user requested more processes than we can display */ if (topn > max_topn) { fprintf(stderr, "%s: warning: this terminal can only display %d processes.\n", myname, max_topn); warnings++; } /* adjust for topn == Infinity */ if (topn == Infinity) { /* * For smart terminals, infinity really means everything that can * be displayed, or Largest. * On dumb terminals, infinity means every process in the system! * We only really want to do that if it was explicitly specified. * This is always the case when "Default_TOPN != Infinity". But if * topn wasn't explicitly specified and we are on a dumb terminal * and the default is Infinity, then (and only then) we use * "Nominal_TOPN" instead. */#if Default_TOPN == Infinity topn = smart_terminal ? Largest : (topn_specified ? Largest : Nominal_TOPN);#else topn = Largest;#endif } /* set header display accordingly */ display_header(topn > 0); /* determine interactive state */ if (interactive == Maybe) { interactive = smart_terminal; } /* if # of displays not specified, fill it in */ if (displays == 0) { displays = smart_terminal ? Infinity : 1; } /* hold interrupt signals while setting up the screen and the handlers */#ifdef SIGHOLD sighold(SIGINT); sighold(SIGQUIT); sighold(SIGTSTP);#else old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));#endif init_screen(); (void) signal(SIGINT, leave); (void) signal(SIGQUIT, leave); (void) signal(SIGTSTP, tstop);#ifdef SIGWINCH (void) signal(SIGWINCH, winch);#endif#ifdef SIGRELSE sigrelse(SIGINT); sigrelse(SIGQUIT); sigrelse(SIGTSTP);#else (void) sigsetmask(old_sigmask);#endif if (warnings) { fputs("....", stderr); fflush(stderr); /* why must I do this? */ sleep((unsigned)(3 * warnings));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -