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
This commit is contained in:
Craig Small 2011-09-12 22:18:23 +10:00
parent 73ade5e2cb
commit e4c45d6984
9 changed files with 118 additions and 39 deletions

View File

@ -301,7 +301,7 @@ extern int prefer_bsd_defaults;
extern int running_only; extern int running_only;
extern int screen_cols; extern int screen_cols;
extern int screen_rows; extern int screen_rows;
extern unsigned long seconds_since_boot; extern time_t seconds_since_boot;
extern selection_node *selection_list; extern selection_node *selection_list;
extern unsigned simple_select; extern unsigned simple_select;
extern sort_node *sort_list; extern sort_node *sort_list;

View File

@ -489,10 +489,12 @@ not_root:
/* don't free the array because it takes time and ps will exit anyway */ /* 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){ static int want_this_proc_nop(proc_t *dummy){
(void)dummy; (void)dummy;
return 1; return 1;
} }
#endif
/***** sorted or forest */ /***** sorted or forest */
static void fancy_spew(void){ static void fancy_spew(void){

View File

@ -69,7 +69,7 @@ unsigned personality = 0xffffffff;
int prefer_bsd_defaults = -1; int prefer_bsd_defaults = -1;
int screen_cols = -1; int screen_cols = -1;
int screen_rows = -1; int screen_rows = -1;
unsigned long seconds_since_boot = -1; time_t seconds_since_boot = -1;
selection_node *selection_list = (selection_node *)0xdeadbeef; selection_node *selection_list = (selection_node *)0xdeadbeef;
unsigned simple_select = 0xffffffff; unsigned simple_select = 0xffffffff;
sort_node *sort_list = (sort_node *)0xdeadbeef; /* ready-to-use sort list */ sort_node *sort_list = (sort_node *)0xdeadbeef; /* ready-to-use sort list */

View File

@ -76,7 +76,8 @@ static unsigned max_leftward = 0x12345678; /* space for LEFT stuff */
static int wide_signals; /* true if we have room */ 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; 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? */ /* Source & destination are known. Return bytes or screen characters? */
//
// OldLinux FreeBSD HPUX
// ' ' ' ' ' ' ' '
// 'L' ' \_ ' '`-' ' '
// '+' ' \_ ' '|-' ' '
// '|' ' | ' '| ' ' '
//
static int forest_helper(char *restrict const outbuf){ static int forest_helper(char *restrict const outbuf){
char *p = forest_prefix; char *p = forest_prefix;
char *q = outbuf; 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); 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 */ /* "Processor utilisation for scheduling." --- we use %cpu w/o fraction */
static int pr_c(char *restrict const outbuf, const proc_t *restrict const pp){ static int pr_c(char *restrict const outbuf, const proc_t *restrict const pp){
unsigned long long total_time; /* jiffies used by this process */ 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); str = ctime(&t);
if(str[8]==' ') str[8]='0'; if(str[8]==' ') str[8]='0';
if(str[11]==' ') str[11]='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, "%8.8s", str+11);
return snprintf(outbuf, COLWID, " %6.6s", str+4); 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}, {"environ","ENVIRONMENT",pr_nop, sr_nop, 11, ENV, LNx, PO|UNLIMITED},
{"esp", "ESP", pr_esp, sr_kstk_esp, 8, 0, LNX, TO|RIGHT}, {"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 */ {"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}, {"euid", "EUID", pr_euid, sr_euid, 5, 0, LNX, ET|RIGHT},
{"euser", "EUSER", pr_euser, sr_euser, 8, USR, LNX, ET|USER}, {"euser", "EUSER", pr_euser, sr_euser, 8, USR, LNX, ET|USER},
{"f", "F", pr_flag, sr_flags, 1, 0, XXX, ET|RIGHT}, /*flags*/ {"f", "F", pr_flag, sr_flags, 1, 0, XXX, ET|RIGHT}, /*flags*/

View File

@ -617,6 +617,10 @@ static const char *parse_bsd_option(void){
trace("c true command name\n"); trace("c true command name\n");
bsd_c_option = 1; bsd_c_option = 1;
break; break;
// case 'd':
// trace("d FreeBSD-style tree\n");
// forest_type = 'f';
// break;
case 'e': case 'e':
trace("e environment\n"); trace("e environment\n");
bsd_e_option = 1; bsd_e_option = 1;

View File

@ -1008,6 +1008,11 @@ elapsed time since the process was started,
in\ the form\ [[DD\-]hh:]mm:ss. in\ the form\ [[DD\-]hh:]mm:ss.
T} T}
etimes ELAPSED T{
elapsed time since the process was started,
in\ seconds.
T}
euid EUID T{ euid EUID T{
effective user\ ID (alias\ \fBuid\fR). effective user\ ID (alias\ \fBuid\fR).
T} T}

2
top.1
View File

@ -1067,7 +1067,7 @@ Later, if you wish to monitor all tasks again in the \*(CW, re-issue this
command but just press <Enter> at the prompt. command but just press <Enter> at the prompt.
.TP 7 .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 In this mode, processes are reordered according to their parents and
the layout of the COMMAND column resembles that of a tree. the layout of the COMMAND column resembles that of a tree.
In forest view mode it is still possible to toggle between program In forest view mode it is still possible to toggle between program

119
top.c
View File

@ -155,8 +155,6 @@ static WIN_t *Curwin;
and/or that are simply more efficiently handled as globals and/or that are simply more efficiently handled as globals
[ 'Frames_...' (plural) stuff persists beyond 1 frame ] [ 'Frames_...' (plural) stuff persists beyond 1 frame ]
[ or are used in response to async signals received ! ] */ [ 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() // Frames_paused set by sig_paused(), unset by pause_pgm()
static volatile int Frames_paused; // become a paused background job static volatile int Frames_paused; // become a paused background job
// Frames_resize set by do_key() & sig_resize(), unset by calibrate_fields() // Frames_resize set by do_key() & sig_resize(), unset by calibrate_fields()
@ -512,12 +510,32 @@ static void pause_pgm (void) {
} // end: pause_pgm } // 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: * Catches:
* SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT and SIGTERM */ * SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT and SIGTERM */
static void sig_endpgm (int dont_care_sig) NORETURN;
static void sig_endpgm (int dont_care_sig) { 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; (void)dont_care_sig;
Frames_endpgm = 1;
} // end: sig_endpgm } // end: sig_endpgm
@ -525,7 +543,7 @@ static void sig_endpgm (int dont_care_sig) {
* Catches: * Catches:
* SIGTSTP, SIGTTIN and SIGTTOU */ * SIGTSTP, SIGTTIN and SIGTTOU */
static void sig_paused (int dont_care_sig) { static void sig_paused (int dont_care_sig) {
(void)dont_care_sig; (void)dont_care_sig;
Frames_paused = 1; Frames_paused = 1;
} // end: sig_paused } // end: sig_paused
@ -671,11 +689,21 @@ static int show_pmt (const char *str) {
* Show a special coordinate message, in support of scrolling */ * Show a special coordinate message, in support of scrolling */
static inline void show_scroll (void) { static inline void show_scroll (void) {
char tmp[SMLBUFSIZ]; 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) snprintf(tmp, sizeof(tmp)
, "scroll coordinates: y = %d/%d (tasks), x = %d/%d (fields)" , "scroll coordinates: y = %d/%d (tasks), x = %d/%d (fields)"
, Curwin->begtask + 1, Frame_maxtask , 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); PUTT("%s%s %.*s%s", tg2(0, Msg_row), Caps_off, Screen_cols - 2, tmp, Cap_clr_eol);
putp(tg2(0, Msg_row)); putp(tg2(0, Msg_row));
} // end: show_scroll } // end: show_scroll
@ -1392,6 +1420,9 @@ static void calibrate_fields (void) {
if (!Fieldstab[f].fmts) { ++varcolcnt; w->varcolsz += strlen(h) - 1; } if (!Fieldstab[f].fmts) { ++varcolcnt; w->varcolsz += strlen(h) - 1; }
s = scat(s, h); 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 /* 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 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--) { for (i = w->totpflgs - 1; -1 < i; i--) {
f = w->pflgsall[i]; f = w->pflgsall[i];
#ifndef USE_X_COLHDR #ifndef USE_X_COLHDR
if (P_MAXPFLGS < f) continue; if (P_MAXPFLGS < f) { w->endpflg = i; continue; }
#endif #endif
h = Fieldstab[f].head; h = Fieldstab[f].head;
if (Screen_cols <= ((int)(s - w->columnhdr) + (int)strlen(h))) break; if (Screen_cols <= ((int)(s - w->columnhdr) + (int)strlen(h))) break;
s = scat(s, h); s = scat(s, h);
w->endpflg = i; 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 /* finally, we can build the true run-time columns header, format any
variable column heading(s), if they're really being displayed, and 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; if (Screen_cols > (int)strlen(w->columnhdr)) w->eolcap = Caps_endline;
else w->eolcap = Caps_off; else w->eolcap = Caps_off;
#endif #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; if (!CHKw(w, Show_IDLEPS)) Frames_libflags |= L_stat;
// we must also accommodate an out of view sort field... // we must also accommodate an out of view sort field...
f = w->rc.sortindx; f = w->rc.sortindx;
Frames_libflags |= Fieldstab[f].lflg; Frames_libflags |= Fieldstab[f].lflg;
if (P_CMD == f && CHKw(w, Show_CMDLIN)) Frames_libflags |= L_CMDLINE; if (P_CMD == f && CHKw(w, Show_CMDLIN)) Frames_libflags |= L_CMDLINE;
} // end: VIZISw(w) } // end: VIZISw(w)
if (Rc.mode_altscr) w = w->next; if (Rc.mode_altscr) w = w->next;
} while (w != Curwin); } while (w != Curwin);
@ -1713,14 +1750,16 @@ always:
Fieldstab[P_CPN].fmts = fmts_cpu; Fieldstab[P_CPN].fmts = fmts_cpu;
} }
Cpu_pmax = 99.0; Cpu_pmax = 99.9;
Fieldstab[P_CPU].fmts = " %#4.1f "; Fieldstab[P_CPU].fmts = " %#4.1f ";
if (Rc.mode_irixps && Cpu_tot > 1 && !Thread_mode) { if (Rc.mode_irixps && Cpu_tot > 1 && !Thread_mode) {
Cpu_pmax = 999.0; Cpu_pmax = 100.0 * Cpu_tot;
Fieldstab[P_CPU].fmts = "%#5.1f ";
if (Cpu_tot > 10) { if (Cpu_tot > 10) {
Cpu_pmax = 99999.0; if (Cpu_pmax > 99999.0) Cpu_pmax = 99999.0;
Fieldstab[P_CPU].fmts = "%5.0f "; 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 * No matter what *they* say, we handle the really really BIG and
* IMPORTANT stuff upon which all those lessor functions depend! */ * IMPORTANT stuff upon which all those lessor functions depend! */
static void before (char *me) { static void before (char *me) {
struct sigaction sa;
int i; int i;
// setup our program name -- big! // setup our program name -- big!
@ -2051,6 +2091,28 @@ static void before (char *me) {
memcpy(HHash_one, HHash_nul, sizeof(HHash_nul)); memcpy(HHash_one, HHash_nul, sizeof(HHash_nul));
memcpy(HHash_two, HHash_nul, sizeof(HHash_nul)); memcpy(HHash_two, HHash_nul, sizeof(HHash_nul));
#endif #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 } // end: before
@ -2707,11 +2769,11 @@ static void keys_global (int ch) {
if (Secure_mode) { if (Secure_mode) {
show_msg(err_secure); show_msg(err_secure);
} else { } else {
int sig, pid; int pid, sig = SIGTERM;
char *str;
if (-1 < (pid = get_int("pid to signal/kill"))) { if (-1 < (pid = get_int("pid to signal/kill"))) {
sig = signal_name_to_number( str = linein(fmtmk("Send pid %d signal [%d/sigterm]", pid, SIGTERM));
linein(fmtmk("Send pid %d signal [%d/sigterm]", pid, SIGTERM))); if (*str) sig = signal_name_to_number(str);
if (-1 == sig) sig = SIGTERM;
if (0 < sig && kill(pid, sig)) if (0 < sig && kill(pid, sig))
show_msg(fmtmk("\aFailed signal pid '%d' with '%d': %s" show_msg(fmtmk("\aFailed signal pid '%d' with '%d': %s"
, pid, sig, strerror(errno))); , pid, sig, strerror(errno)));
@ -2872,6 +2934,13 @@ static void keys_task (int ch) {
if (VIZCHKw(w)) { if (VIZCHKw(w)) {
TOGw(w, Show_HICOLS); TOGw(w, Show_HICOLS);
capsmk(w); 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; break;
case 'y': case 'y':
@ -3579,7 +3648,6 @@ static void frame_make (void) {
int i, scrlins; int i, scrlins;
// deal with potential signals since the last time around... // deal with potential signals since the last time around...
if (Frames_endpgm) bye_bye(NULL);
if (Frames_paused) pause_pgm(); if (Frames_paused) pause_pgm();
if (Frames_resize) zap_fieldstab(); if (Frames_resize) zap_fieldstab();
@ -3635,7 +3703,6 @@ static void frame_make (void) {
/* /*
* duh... */ * duh... */
int main (int dont_care_argc, char **argv) { int main (int dont_care_argc, char **argv) {
struct sigaction sa;
(void)dont_care_argc; (void)dont_care_argc;
before(*argv); before(*argv);
// +-------------+ // +-------------+
@ -3645,22 +3712,6 @@ int main (int dont_care_argc, char **argv) {
whack_terminal(); // > onions etc. < whack_terminal(); // > onions etc. <
wins_stage_2(); // as bottom slice 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 (;;) { for (;;) {
struct timeval tv; 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 /* note: above select might have been interrupted by some signal
in which case the return code would have been -1 and an in which case the return code would have been -1 and an
integer (volatile) switch set. that in turn will cause 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
*/ */
} }
} }

2
top.h
View File

@ -335,6 +335,7 @@ typedef struct WIN_t {
/* else fieldscur char already has high bit on! */ \ /* else fieldscur char already has high bit on! */ \
} while (0) } while (0)
#define ENUviz(w,E) (NULL != memchr((w)->procflgs, E, (w)->maxpflgs)) #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 ------------------------------------------ */ /* Special Section: end ------------------------------------------ */
@ -621,6 +622,7 @@ typedef struct WIN_t {
//atic void bye_bye (const char *str); //atic void bye_bye (const char *str);
//atic void error_exit (const char *str); //atic void error_exit (const char *str);
//atic void pause_pgm (void); //atic void pause_pgm (void);
//atic void sig_abexit (int sig);
//atic void sig_endpgm (int dont_care_sig); //atic void sig_endpgm (int dont_care_sig);
//atic void sig_paused (int dont_care_sig); //atic void sig_paused (int dont_care_sig);
//atic void sig_resize (int dont_care_sig); //atic void sig_resize (int dont_care_sig);