diff --git a/top/top.c b/top/top.c index a7406bc2..607084cd 100644 --- a/top/top.c +++ b/top/top.c @@ -110,7 +110,18 @@ static int Monpidsidx = 0; basis (see the WIN_t). Max_lines is the total number of screen rows after deducting summary information overhead. */ /* Current terminal screen size. */ -static int Screen_cols, Screen_rows, Max_lines; +static int Screen_cols, Screen_rows, Max_lines; + + // these are used to potentially set aside a bottom 'window' +#define SCREEN_ROWS ( Screen_rows - Tagged_rsvd ) + // 1 for horizontal separator +#define TAGGED_RSVD ( 1 ) +#define TAGGED_UNDO do { Tagged_task = Tagged_rsvd = Tagged_lflg = 0; } while (0) +static int Tagged_task, + Tagged_rsvd, + Tagged_lflg; +static char *Tagged_name; +static void(*Tagged_func)(void); /* This is really the number of lines needed to display the summary information (0 - nn), but is used as the relative row where we @@ -2128,6 +2139,9 @@ static void build_headers (void) { if (EU_CMD == f && CHKw(w, Show_CMDLIN)) Frames_libflags |= L_CMDLINE; // for 'U' filtering we need the other user ids too if (w->usrseltyp == 'U') Frames_libflags |= L_status; + + // lastly, accommodate any special non-display 'tagged' needs... + if (Tagged_lflg) Frames_libflags |= Tagged_lflg; } // end: VIZISw(w) if (Rc.mode_altscr) w = w->next; @@ -4540,13 +4554,14 @@ static void win_reset (WIN_t *q) { #else q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = q->focus_pid = 0; #endif - // these next two are global, not really windows based - Monpidsidx = 0; - Rc.tics_scaled = 0; - osel_clear(q); q->findstr[0] = '\0'; q->rc.combine_cpus = 0; + + // these next guys are global, not really windows based + Monpidsidx = 0; + Rc.tics_scaled = 0; + TAGGED_UNDO; } // end: win_reset @@ -4829,6 +4844,70 @@ static void wins_stage_2 (void) { } // end: wins_stage_2 + /* + * This guy manages the bottom margin window | + * & the tagged process command line display | */ +static void wins_tag_cmdline (void) { + char buf[SMLBUFSIZ]; + const char *p; + int i; + + for (i = 0; i < Frame_maxtask; i++) { + if (Tagged_task == Curwin->ppt[i]->tid) + break; + } + if (i < Frame_maxtask) { + snprintf(buf, sizeof(buf), "command line for pid %d:", Tagged_task); + p = *Curwin->ppt[i]->cmdline; + if (!p || !*p) p = "n/a"; + Tagged_rsvd = 1 + TAGGED_RSVD + (strlen(p) / Screen_cols); + putp(fmtmk("%s%s%-*s", tg2(0, SCREEN_ROWS), Curwin->capclr_hdr, Screen_cols, buf)); + putp(fmtmk("%s%s", tg2(0, SCREEN_ROWS + 1), Cap_clr_eos)); + putp(fmtmk("%s%s", tg2(0, SCREEN_ROWS + 1), Cap_norm)); + fputs(p, stdout); + } else { + TAGGED_UNDO; + } +} // end: wins_tag_cmdline + + + /* + * This guy manages the bottom margin window | + * showing miscellaneous variable width data | */ +static void wins_tag_generic (void) { + char buf[SMLBUFSIZ]; + const char *p; + int i; + + for (i = 0; i < Frame_maxtask; i++) { + if (Tagged_task == Curwin->ppt[i]->tid) + break; + } + if (i < Frame_maxtask) { + snprintf(buf, sizeof(buf), "%s for pid %d:", Tagged_name, Tagged_task); + switch (Tagged_lflg) { + case (L_CGROUP): // Ctrl-G + p = *Curwin->ppt[i]->cgroup; + break; + case (L_SUPGRP): // Ctrl-U + p = Curwin->ppt[i]->supgrp; + break; + case (L_ENVIRON): // Ctrl-V + p = *Curwin->ppt[i]->environ; + break; + } + if (!p || !*p || !strcmp(p, "-")) p = "n/a"; + Tagged_rsvd = 1 + TAGGED_RSVD + (strlen(p) / Screen_cols); + putp(fmtmk("%s%s%-*s", tg2(0, SCREEN_ROWS), Curwin->capclr_hdr, Screen_cols, buf)); + putp(fmtmk("%s%s", tg2(0, SCREEN_ROWS + 1), Cap_clr_eos)); + putp(fmtmk("%s%s", tg2(0, SCREEN_ROWS + 1), Cap_norm)); + fputs(p, stdout); + } else { + TAGGED_UNDO; + } +} // end: wins_tag_generic + + /* * Determine if this task matches the 'u/U' selection * criteria for a given window */ @@ -5053,7 +5132,7 @@ static void forest_excluded (WIN_t *q) { // if some task 'above' us ended, try to maintain focus // ( but allow scrolling when there are many children ) if (q->begtask > q->focus_beg - && (Screen_rows > (q->focus_end - q->focus_beg))) { + && (SCREEN_ROWS > (q->focus_end - q->focus_beg))) { q->begtask = q->focus_beg; q->begnext = 0; // as 'mkVIZoff' but in any window } @@ -5417,6 +5496,53 @@ static void keys_global (int ch) { Rc.tics_scaled = 0; #endif break; + case kbd_CtrlG: + def = w->ppt[w->begtask]->tid; + // if already targeted, assume user wants to turn it off ... + if (Tagged_task && Tagged_lflg == (L_CGROUP)) { + TAGGED_UNDO; + } else { + Tagged_task = def; + Tagged_lflg = L_CGROUP; + Tagged_name = "control groups"; + Tagged_func = wins_tag_generic; + } + break; + case kbd_CtrlK: + def = w->ppt[w->begtask]->tid; + // if already targeted, assume user wants to turn it off ... + if (Tagged_task && Tagged_lflg == (L_CMDLINE)) { + TAGGED_UNDO; + } else { + Tagged_task = def; + Tagged_lflg = L_CMDLINE; + Tagged_func = wins_tag_cmdline; + } + break; + case kbd_CtrlU: + def = w->ppt[w->begtask]->tid; + // if already targeted, assume user wants to turn it off ... + if (Tagged_task && Tagged_lflg == (L_SUPGRP)) { + TAGGED_UNDO; + } else { + Tagged_task = def; + Tagged_lflg = L_SUPGRP; + Tagged_name = "supplementary groups"; + Tagged_func = wins_tag_generic; + } + break; + case kbd_CtrlV: + def = w->ppt[w->begtask]->tid; + // if already targeted, assume user wants to turn it off ... + if (Tagged_task && Tagged_lflg == (L_ENVIRON)) { + TAGGED_UNDO; + } else { + Tagged_task = def; + Tagged_lflg = L_ENVIRON; + Tagged_name = "environment"; + Tagged_func = wins_tag_generic; + } + break; case kbd_ENTER: // these two have the effect of waking us case kbd_SPACE: // from 'pselect', refreshing the display break; // and updating any hot-plugged resources @@ -6040,7 +6166,7 @@ static int sum_unify (CPU_t *cpu, int nobuf) { * A helper function that displays cpu and/or numa node stuff | * ( so as to keep the 'summary_show' guy a reasonable size ) | */ static void do_cpus (void) { - #define noMAS (Msg_row + 1 >= Screen_rows - 1) + #define noMAS (Msg_row + 1 >= SCREEN_ROWS - 1) char tmp[MEDBUFSIZ]; int i; @@ -6230,7 +6356,8 @@ static void do_key (int ch) { { keys_global, { '?', 'B', 'd', 'E', 'e', 'f', 'g', 'H', 'h' , 'I', 'k', 'r', 's', 'X', 'Y', 'Z', '0' - , kbd_CtrlE, kbd_ENTER, kbd_SPACE, '\0' } }, + , kbd_CtrlE, kbd_CtrlG, kbd_CtrlK, kbd_CtrlU, kbd_CtrlV + , kbd_ENTER, kbd_SPACE, '\0' } }, { keys_summary, { '!', '1', '2', '3', '4', 'C', 'l', 'm', 't', '\0' } }, { keys_task, @@ -6300,7 +6427,7 @@ all_done: * 2) Display task/cpu states (maybe) * 3) Display memory & swap usage (maybe) */ static void summary_show (void) { - #define isROOM(f,n) (CHKw(Curwin, f) && Msg_row + (n) < Screen_rows - 1) + #define isROOM(f,n) (CHKw(Curwin, f) && Msg_row + (n) < SCREEN_ROWS - 1) // Display Uptime and Loadavg if (isROOM(View_LOADAV, 1)) { @@ -6815,7 +6942,7 @@ static void frame_make (void) { Tree_idx = Pseudo_row = Msg_row = scrlins = 0; summary_show(); - Max_lines = (Screen_rows - Msg_row) - 1; + Max_lines = (SCREEN_ROWS - Msg_row) - 1; // we're now on Msg_row so clear out any residual messages ... putp(Cap_clr_eol); @@ -6842,8 +6969,8 @@ static void frame_make (void) { PSU_CLREOS(Pseudo_row); } - if (CHKw(w, View_SCROLL) && VIZISw(Curwin)) - show_scroll(); + if (CHKw(w, View_SCROLL) && VIZISw(Curwin)) show_scroll(); + if (Tagged_task) Tagged_func(); fflush(stdout); /* we'll deem any terminal not supporting tgoto as dumb and disable diff --git a/top/top.h b/top/top.h index d7a8a1c9..0362c6a5 100644 --- a/top/top.h +++ b/top/top.h @@ -61,6 +61,7 @@ //#define SCROLLVAR_NO /* disable intra-column horizontal scrolls */ //#define SCROLLV_BY_1 /* when scrolling left/right do not move 8 */ //#define STRINGCASENO /* case insenstive compare/locate versions */ +//#define TAG_CMD_MUST /* CtrlK (cmdline) needs proper 'c' toggle */ //#define TERMIOS_ONLY /* use native input only (just limp along) */ //#define TOG4_NOFORCE /* no force 2 abreast mode with '4' toggle */ //#define TOG4_NOTRUNC /* ensure no truncation for 2 abreast mode */ @@ -182,8 +183,12 @@ char *strcasestr(const char *haystack, const char *needle); #define kbd_BKSP 137 #define kbd_INS 138 #define kbd_DEL 139 -#define kbd_CtrlO '\017' #define kbd_CtrlE '\005' +#define kbd_CtrlG '\007' +#define kbd_CtrlK '\013' +#define kbd_CtrlO '\017' +#define kbd_CtrlU '\025' +#define kbd_CtrlV '\026' /* Special value in Pseudo_row to force an additional procs refresh -- used at startup and for task/thread mode transitions */ @@ -805,6 +810,8 @@ typedef struct WIN_t { //atic void wins_reflag (int what, int flg); //atic void wins_stage_1 (void); //atic void wins_stage_2 (void); +//atic void wins_tag_cmdline (void); +//atic void wins_tag_generic (void); //atic inline int wins_usrselect (const WIN_t *q, const int idx); /*------ Forest View support -------------------------------------------*/ //atic void forest_adds (const int self, int level); diff --git a/top/top_nls.c b/top/top_nls.c index dbeda3a9..2d07b70a 100644 --- a/top/top_nls.c +++ b/top/top_nls.c @@ -590,7 +590,8 @@ static void build_uniq_nlstab (void) { " V,v,F . Toggle: '~1V~2' forest view; '~1v~2' hide/show children; '~1F~2' keep focused\n" "\n" "%s" - " W,Y,!,^E Write cfg '~1W~2'; Inspect '~1Y~2'; Combine Cpus '~1!~2'; Scale time ~1Ctrl~2+'~1E~2'\n" + " ^G,K,U,V View: ctl groups ~1^g~2; cmdline ~1^k~2; supp groups ~1^u~2; environment ~1^v~2\n" + " W,Y,!,^E Write cfg '~1W~2'; Inspect '~1Y~2'; Combine Cpus '~1!~2'; Scale time ~1^e~2'\n" " q Quit\n" " ( commands shown with '.' require a ~1visible~2 task display ~1window~2 ) \n" "Press '~1h~2' or '~1?~2' for help with ~1Windows~2,\n" @@ -661,8 +662,7 @@ static void build_uniq_nlstab (void) { . also imbedded in the translatable text (along with escape seqs) . should never themselves be translated. */ Uniq_nlstab[KEYS_helpext_fmt] = _("" - " k,r Manipulate tasks: '~1k~2' kill; '~1r~2' renice\n" - " d or s Set update interval\n"); + " d,k,r,^R, '~1d~2' set delay; '~1k~2' kill; '~1r~2' renice; ~1Ctrl~2+'~1R~2' renice autogroup\n"); /* Translation Hint: . This Fields Management header should be 3 lines long so as