From e4c45d6984955fc69ce5bc0629a0d42bcfb1a6ba Mon Sep 17 00:00:00 2001 From: Craig Small Date: Mon, 12 Sep 2011 22:18:23 +1000 Subject: [PATCH] added ps etimes, miscellaneous top enhancements ps program . etimes added for ELAPSED expressed in seconds . time_t used in place of former unsigned long top program . corrected scroll message bug when 'x' toggle on . fixed forest view potential missing libflags bug . improved 'k' default signal invocation logic . enhanced logic for %CPU maximums displayed . made signal handling more robust and efficient --- ps/common.h | 2 +- ps/display.c | 2 + ps/global.c | 2 +- ps/output.c | 19 +++++++- ps/parser.c | 4 ++ ps/ps.1 | 5 +++ top.1 | 2 +- top.c | 119 ++++++++++++++++++++++++++++++++++++--------------- top.h | 2 + 9 files changed, 118 insertions(+), 39 deletions(-) diff --git a/ps/common.h b/ps/common.h index 0b47d906..d7208a7c 100644 --- a/ps/common.h +++ b/ps/common.h @@ -301,7 +301,7 @@ extern int prefer_bsd_defaults; extern int running_only; extern int screen_cols; extern int screen_rows; -extern unsigned long seconds_since_boot; +extern time_t seconds_since_boot; extern selection_node *selection_list; extern unsigned simple_select; extern sort_node *sort_list; diff --git a/ps/display.c b/ps/display.c index 8c22deaa..78685c40 100644 --- a/ps/display.c +++ b/ps/display.c @@ -489,10 +489,12 @@ not_root: /* don't free the array because it takes time and ps will exit anyway */ } +#if 0 static int want_this_proc_nop(proc_t *dummy){ (void)dummy; return 1; } +#endif /***** sorted or forest */ static void fancy_spew(void){ diff --git a/ps/global.c b/ps/global.c index 0b3bc5b4..f795e018 100644 --- a/ps/global.c +++ b/ps/global.c @@ -69,7 +69,7 @@ unsigned personality = 0xffffffff; int prefer_bsd_defaults = -1; int screen_cols = -1; int screen_rows = -1; -unsigned long seconds_since_boot = -1; +time_t seconds_since_boot = -1; selection_node *selection_list = (selection_node *)0xdeadbeef; unsigned simple_select = 0xffffffff; sort_node *sort_list = (sort_node *)0xdeadbeef; /* ready-to-use sort list */ diff --git a/ps/output.c b/ps/output.c index 44a9aaa4..54b0585f 100644 --- a/ps/output.c +++ b/ps/output.c @@ -76,7 +76,8 @@ static unsigned max_leftward = 0x12345678; /* space for LEFT stuff */ static int wide_signals; /* true if we have room */ -static unsigned long seconds_since_1970; +static time_t seconds_since_1970; +static time_t time_of_boot; static unsigned long page_shift; @@ -277,6 +278,13 @@ STIME stime hms or md time format ***/ /* Source & destination are known. Return bytes or screen characters? */ +// +// OldLinux FreeBSD HPUX +// ' ' ' ' ' ' ' ' +// 'L' ' \_ ' '`-' ' ' +// '+' ' \_ ' '|-' ' ' +// '|' ' | ' '| ' ' ' +// static int forest_helper(char *restrict const outbuf){ char *p = forest_prefix; char *q = outbuf; @@ -430,6 +438,12 @@ static int pr_etime(char *restrict const outbuf, const proc_t *restrict const pp return (int)(cp-outbuf); } +/* elapsed wall clock time in seconds */ +static int pr_etimes(char *restrict const outbuf, const proc_t *restrict const pp){ + unsigned t = seconds_since_boot - (unsigned long)(pp->start_time / Hertz); + return snprintf(outbuf, COLWID, "%u", t); +} + /* "Processor utilisation for scheduling." --- we use %cpu w/o fraction */ static int pr_c(char *restrict const outbuf, const proc_t *restrict const pp){ unsigned long long total_time; /* jiffies used by this process */ @@ -950,7 +964,7 @@ static int pr_start(char *restrict const outbuf, const proc_t *restrict const pp str = ctime(&t); if(str[8]==' ') str[8]='0'; if(str[11]==' ') str[11]='0'; - if((unsigned long)t+60*60*24 > seconds_since_1970) + if((unsigned long)t+60*60*24 > (unsigned long)seconds_since_1970) return snprintf(outbuf, COLWID, "%8.8s", str+11); return snprintf(outbuf, COLWID, " %6.6s", str+4); } @@ -1345,6 +1359,7 @@ static const format_struct format_array[] = { {"environ","ENVIRONMENT",pr_nop, sr_nop, 11, ENV, LNx, PO|UNLIMITED}, {"esp", "ESP", pr_esp, sr_kstk_esp, 8, 0, LNX, TO|RIGHT}, {"etime", "ELAPSED", pr_etime, sr_nop, 11, 0, U98, ET|RIGHT}, /* was 7 wide */ +{"etimes", "ELAPSED", pr_etimes, sr_nop, 7, 0, BSD, ET|RIGHT}, /* FreeBSD */ {"euid", "EUID", pr_euid, sr_euid, 5, 0, LNX, ET|RIGHT}, {"euser", "EUSER", pr_euser, sr_euser, 8, USR, LNX, ET|USER}, {"f", "F", pr_flag, sr_flags, 1, 0, XXX, ET|RIGHT}, /*flags*/ diff --git a/ps/parser.c b/ps/parser.c index 5ad9035c..dfdf6dbc 100644 --- a/ps/parser.c +++ b/ps/parser.c @@ -617,6 +617,10 @@ static const char *parse_bsd_option(void){ trace("c true command name\n"); bsd_c_option = 1; break; +// case 'd': +// trace("d FreeBSD-style tree\n"); +// forest_type = 'f'; +// break; case 'e': trace("e environment\n"); bsd_e_option = 1; diff --git a/ps/ps.1 b/ps/ps.1 index 58d3d083..ad29415e 100644 --- a/ps/ps.1 +++ b/ps/ps.1 @@ -1008,6 +1008,11 @@ elapsed time since the process was started, in\ the form\ [[DD\-]hh:]mm:ss. T} +etimes ELAPSED T{ +elapsed time since the process was started, +in\ seconds. +T} + euid EUID T{ effective user\ ID (alias\ \fBuid\fR). T} diff --git a/top.1 b/top.1 index dee1d6aa..3f61a36d 100644 --- a/top.1 +++ b/top.1 @@ -1067,7 +1067,7 @@ Later, if you wish to monitor all tasks again in the \*(CW, re-issue this command but just press at the prompt. .TP 7 -\ \ \'\fBV\fR' :\fIForest-View-Mode \fR toggle \fR +\ \ \'\fBV\fR' :\fIForest-View-Mode\fR toggle \fR In this mode, processes are reordered according to their parents and the layout of the COMMAND column resembles that of a tree. In forest view mode it is still possible to toggle between program diff --git a/top.c b/top.c index 183135ac..88cf3297 100644 --- a/top.c +++ b/top.c @@ -155,8 +155,6 @@ static WIN_t *Curwin; and/or that are simply more efficiently handled as globals [ 'Frames_...' (plural) stuff persists beyond 1 frame ] [ or are used in response to async signals received ! ] */ - // Frames_endpgm set by sig_endpgm(), no need to unset -static volatile int Frames_endpgm; // time to quit this shit // Frames_paused set by sig_paused(), unset by pause_pgm() static volatile int Frames_paused; // become a paused background job // Frames_resize set by do_key() & sig_resize(), unset by calibrate_fields() @@ -512,12 +510,32 @@ static void pause_pgm (void) { } // end: pause_pgm + /* + * Catches all remaining signals not otherwise handled */ +static void sig_abexit (int sig) NORETURN; +static void sig_abexit (int sig) { + static const char *ab_msg = + "\n\tsignal %d (%s) was caught by %s, please" + "\n\tsee http://www.debian.org/Bugs/Reporting\n"; + sigset_t ss; + + sigfillset(&ss); + sigprocmask(SIG_BLOCK, &ss, NULL); + bye_bye(fmtmk(ab_msg, sig, signal_number_to_name(sig), Myname)); +} // end: sig_abexit + + /* * Catches: * SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT and SIGTERM */ +static void sig_endpgm (int dont_care_sig) NORETURN; static void sig_endpgm (int dont_care_sig) { + sigset_t ss; + + sigfillset(&ss); + sigprocmask(SIG_BLOCK, &ss, NULL); + bye_bye(NULL); (void)dont_care_sig; - Frames_endpgm = 1; } // end: sig_endpgm @@ -525,7 +543,7 @@ static void sig_endpgm (int dont_care_sig) { * Catches: * SIGTSTP, SIGTTIN and SIGTTOU */ static void sig_paused (int dont_care_sig) { - (void)dont_care_sig; + (void)dont_care_sig; Frames_paused = 1; } // end: sig_paused @@ -671,11 +689,21 @@ static int show_pmt (const char *str) { * Show a special coordinate message, in support of scrolling */ static inline void show_scroll (void) { char tmp[SMLBUFSIZ]; + int totpflgs = Curwin->totpflgs; + int begpflgs = Curwin->begpflg + 1; +#ifndef USE_X_COLHDR + if (CHKw(Curwin, Show_HICOLS)) { + totpflgs -= 2; + if (ENUpos(Curwin, Curwin->rc.sortindx) < Curwin->begpflg) begpflgs -= 2; + } +#endif + if (1 > totpflgs) totpflgs = 1; + if (1 > begpflgs) begpflgs = 1; snprintf(tmp, sizeof(tmp) , "scroll coordinates: y = %d/%d (tasks), x = %d/%d (fields)" , Curwin->begtask + 1, Frame_maxtask - , Curwin->begpflg + 1, Curwin->totpflgs); + , begpflgs, totpflgs); PUTT("%s%s %.*s%s", tg2(0, Msg_row), Caps_off, Screen_cols - 2, tmp, Cap_clr_eol); putp(tg2(0, Msg_row)); } // end: show_scroll @@ -1392,6 +1420,9 @@ static void calibrate_fields (void) { if (!Fieldstab[f].fmts) { ++varcolcnt; w->varcolsz += strlen(h) - 1; } s = scat(s, h); } +#ifndef USE_X_COLHDR + if (X_XON == w->procflgs[i - 1]) --i; +#endif /* establish the final maxpflgs and prepare to grow the variable column heading(s) via varcolsz - it may be a fib if their pflags weren't @@ -1407,13 +1438,16 @@ static void calibrate_fields (void) { for (i = w->totpflgs - 1; -1 < i; i--) { f = w->pflgsall[i]; #ifndef USE_X_COLHDR - if (P_MAXPFLGS < f) continue; + if (P_MAXPFLGS < f) { w->endpflg = i; continue; } #endif h = Fieldstab[f].head; if (Screen_cols <= ((int)(s - w->columnhdr) + (int)strlen(h))) break; s = scat(s, h); w->endpflg = i; } +#ifndef USE_X_COLHDR + if (X_XOF == w->pflgsall[w->endpflg]) ++w->endpflg; +#endif /* finally, we can build the true run-time columns header, format any variable column heading(s), if they're really being displayed, and @@ -1453,13 +1487,16 @@ static void calibrate_fields (void) { if (Screen_cols > (int)strlen(w->columnhdr)) w->eolcap = Caps_endline; else w->eolcap = Caps_off; #endif - // to show only 'busy' processes requires L_stat... + // with forest view mode, we'll need tgid & ppid... + if (CHKw(w, Show_FOREST)) Frames_libflags |= L_status; + // for 'busy' only processes, we'll need pcpu (utime & stime)... if (!CHKw(w, Show_IDLEPS)) Frames_libflags |= L_stat; // we must also accommodate an out of view sort field... f = w->rc.sortindx; Frames_libflags |= Fieldstab[f].lflg; if (P_CMD == f && CHKw(w, Show_CMDLIN)) Frames_libflags |= L_CMDLINE; } // end: VIZISw(w) + if (Rc.mode_altscr) w = w->next; } while (w != Curwin); @@ -1713,14 +1750,16 @@ always: Fieldstab[P_CPN].fmts = fmts_cpu; } - Cpu_pmax = 99.0; + Cpu_pmax = 99.9; Fieldstab[P_CPU].fmts = " %#4.1f "; if (Rc.mode_irixps && Cpu_tot > 1 && !Thread_mode) { - Cpu_pmax = 999.0; - Fieldstab[P_CPU].fmts = "%#5.1f "; + Cpu_pmax = 100.0 * Cpu_tot; if (Cpu_tot > 10) { - Cpu_pmax = 99999.0; + if (Cpu_pmax > 99999.0) Cpu_pmax = 99999.0; Fieldstab[P_CPU].fmts = "%5.0f "; + } else { + if (Cpu_pmax > 999.9) Cpu_pmax = 999.9; + Fieldstab[P_CPU].fmts = "%#5.1f "; } } @@ -2022,6 +2061,7 @@ static void sysinfo_refresh (int forced) { * No matter what *they* say, we handle the really really BIG and * IMPORTANT stuff upon which all those lessor functions depend! */ static void before (char *me) { + struct sigaction sa; int i; // setup our program name -- big! @@ -2051,6 +2091,28 @@ static void before (char *me) { memcpy(HHash_one, HHash_nul, sizeof(HHash_nul)); memcpy(HHash_two, HHash_nul, sizeof(HHash_nul)); #endif + + // lastly, establish a robust signals environment + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + for (i = SIGRTMAX + 1; i; i--) { + switch (i) { + case SIGALRM: case SIGHUP: case SIGINT: + case SIGPIPE: case SIGQUIT: case SIGTERM: + sa.sa_handler = sig_endpgm; + break; + case SIGTSTP: case SIGTTIN: case SIGTTOU: + sa.sa_handler = sig_paused; + break; + case SIGCONT: case SIGWINCH: + sa.sa_handler = sig_resize; + break; + default: + sa.sa_handler = sig_abexit; + break; + } + sigaction(i, &sa, NULL); + } } // end: before @@ -2707,11 +2769,11 @@ static void keys_global (int ch) { if (Secure_mode) { show_msg(err_secure); } else { - int sig, pid; + int pid, sig = SIGTERM; + char *str; if (-1 < (pid = get_int("pid to signal/kill"))) { - sig = signal_name_to_number( - linein(fmtmk("Send pid %d signal [%d/sigterm]", pid, SIGTERM))); - if (-1 == sig) sig = SIGTERM; + str = linein(fmtmk("Send pid %d signal [%d/sigterm]", pid, SIGTERM)); + if (*str) sig = signal_name_to_number(str); if (0 < sig && kill(pid, sig)) show_msg(fmtmk("\aFailed signal pid '%d' with '%d': %s" , pid, sig, strerror(errno))); @@ -2872,6 +2934,13 @@ static void keys_task (int ch) { if (VIZCHKw(w)) { TOGw(w, Show_HICOLS); capsmk(w); +#ifndef USE_X_COLHDR + if (ENUpos(w, w->rc.sortindx) < w->begpflg) { + if (CHKw(w, Show_HICOLS)) w->begpflg += 2; + else w->begpflg -= 2; + if (0 > w->begpflg) w->begpflg = 0; + } +#endif } break; case 'y': @@ -3579,7 +3648,6 @@ static void frame_make (void) { int i, scrlins; // deal with potential signals since the last time around... - if (Frames_endpgm) bye_bye(NULL); if (Frames_paused) pause_pgm(); if (Frames_resize) zap_fieldstab(); @@ -3635,7 +3703,6 @@ static void frame_make (void) { /* * duh... */ int main (int dont_care_argc, char **argv) { - struct sigaction sa; (void)dont_care_argc; before(*argv); // +-------------+ @@ -3645,22 +3712,6 @@ int main (int dont_care_argc, char **argv) { whack_terminal(); // > onions etc. < wins_stage_2(); // as bottom slice // +-------------+ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sa.sa_handler = sig_endpgm; - sigaction(SIGALRM, &sa, NULL); - if (!Batch) sigaction(SIGHUP, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGPIPE, &sa, NULL); - sigaction(SIGQUIT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - sa.sa_handler = sig_paused; - sigaction(SIGTSTP, &sa, NULL); - sigaction(SIGTTIN, &sa, NULL); - sigaction(SIGTTOU, &sa, NULL); - sa.sa_handler = sig_resize; - sigaction(SIGCONT, &sa, NULL); - sigaction(SIGWINCH, &sa, NULL); for (;;) { struct timeval tv; @@ -3686,7 +3737,7 @@ int main (int dont_care_argc, char **argv) { /* note: above select might have been interrupted by some signal in which case the return code would have been -1 and an integer (volatile) switch set. that in turn will cause - frame_make() to deal with it as its first responsiblity + frame_make() to deal with it if we survived the handler */ } } diff --git a/top.h b/top.h index 65625358..5dd0733b 100644 --- a/top.h +++ b/top.h @@ -335,6 +335,7 @@ typedef struct WIN_t { /* else fieldscur char already has high bit on! */ \ } while (0) #define ENUviz(w,E) (NULL != memchr((w)->procflgs, E, (w)->maxpflgs)) +#define ENUpos(w,E) ((int)((FLG_t*)memchr((w)->pflgsall, E, (w)->totpflgs) - (w)->pflgsall)) /* Special Section: end ------------------------------------------ */ @@ -621,6 +622,7 @@ typedef struct WIN_t { //atic void bye_bye (const char *str); //atic void error_exit (const char *str); //atic void pause_pgm (void); +//atic void sig_abexit (int sig); //atic void sig_endpgm (int dont_care_sig); //atic void sig_paused (int dont_care_sig); //atic void sig_resize (int dont_care_sig);