diff --git a/Action.c b/Action.c index eac7f1f6..f36e0bd2 100644 --- a/Action.c +++ b/Action.c @@ -13,6 +13,7 @@ in the source distribution for its full text. #include "CategoriesPanel.h" #include "CRT.h" #include "EnvScreen.h" +#include "CommandScreen.h" #include "MainPanel.h" #include "OpenFilesScreen.h" #include "Process.h" @@ -422,8 +423,8 @@ static const struct { const char* key; const char* info; } helpRight[] = { { .key = " e: ", .info = "show process environment" }, { .key = " i: ", .info = "set IO priority" }, { .key = " l: ", .info = "list open files with lsof" }, + { .key = " M: ", .info = "show process command in multiple lines" }, { .key = " s: ", .info = "trace syscalls with strace" }, - { .key = " ", .info = "" }, { .key = " F2 C S: ", .info = "setup" }, { .key = " F1 h: ", .info = "show this help screen" }, { .key = " F10 q: ", .info = "quit" }, @@ -530,6 +531,16 @@ static Htop_Reaction actionShowEnvScreen(State* st) { return HTOP_REFRESH | HTOP_REDRAW_BAR; } +static Htop_Reaction actionShowCommandScreen(State* st) { + Process* p = (Process*) Panel_getSelected(st->panel); + if (!p) return HTOP_OK; + CommandScreen* cmdScr = CommandScreen_new(p); + InfoScreen_run((InfoScreen*)cmdScr); + CommandScreen_delete((Object*)cmdScr); + clear(); + CRT_enableDelay(); + return HTOP_REFRESH | HTOP_REDRAW_BAR; +} void Action_setBindings(Htop_Action* keys) { keys[KEY_RESIZE] = actionResize; @@ -584,4 +595,5 @@ void Action_setBindings(Htop_Action* keys) { keys['U'] = actionUntagAll; keys['c'] = actionTagAllChildren; keys['e'] = actionShowEnvScreen; + keys['M'] = actionShowCommandScreen; } diff --git a/CommandScreen.c b/CommandScreen.c new file mode 100644 index 00000000..0e261175 --- /dev/null +++ b/CommandScreen.c @@ -0,0 +1,74 @@ +#include "CommandScreen.h" + +#include "config.h" +#include "CRT.h" +#include "IncSet.h" +#include "ListItem.h" +#include "Platform.h" +#include "StringUtils.h" + +#include +#include +#include + + +static void CommandScreen_addLine(InfoScreen* this, char* line, const char* p, int line_offset, int len) { + memcpy(line, p - line_offset, len); + line[len] = '\0'; + InfoScreen_addLine(this, line); +} + +static void CommandScreen_scan(InfoScreen* this) { + Panel* panel = this->display; + int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0); + + Panel_prune(panel); + + const char* p = this->process->comm; + char* line = xMalloc(COLS + 1); + int line_offset = 0, last_spc = -1, len; + for (; *p != '\0'; p++, line_offset++) { + if (*p == ' ') last_spc = line_offset; + + if (line_offset == COLS) { + len = (last_spc == -1) ? line_offset : last_spc; + CommandScreen_addLine(this, line, p, line_offset, len); + line_offset -= len; + last_spc = -1; + } + } + + if (line_offset > 0) CommandScreen_addLine(this, line, p, line_offset, line_offset); + + free(line); + Panel_setSelected(panel, idx); +} + +static void CommandScreen_draw(InfoScreen* this) { + char* title = xMalloc(COLS + 1); + int len = snprintf(title, COLS + 1, "Command of process %d - %s", this->process->pid, this->process->comm); + if (len > COLS) { + memset(&title[COLS - 3], '.', 3); + } + + InfoScreen_drawTitled(this, "%s", title); + free(title); +} + +InfoScreenClass CommandScreen_class = { + .super = { + .extends = Class(Object), + .delete = CommandScreen_delete + }, + .scan = CommandScreen_scan, + .draw = CommandScreen_draw +}; + +CommandScreen* CommandScreen_new(Process* process) { + CommandScreen* this = AllocThis(CommandScreen); + return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 3, " "); +} + +void CommandScreen_delete(Object* this) { + free(InfoScreen_done((InfoScreen*)this)); +} diff --git a/CommandScreen.h b/CommandScreen.h new file mode 100644 index 00000000..a1604a3e --- /dev/null +++ b/CommandScreen.h @@ -0,0 +1,16 @@ +#ifndef HEADER_CommandScreen +#define HEADER_CommandScreen + +#include "InfoScreen.h" + +typedef struct CommandScreen_ { + InfoScreen super; +} CommandScreen; + +extern InfoScreenClass CommandScreen_class; + +CommandScreen* CommandScreen_new(Process* process); + +void CommandScreen_delete(Object* this); + +#endif diff --git a/Makefile.am b/Makefile.am index c97ae938..441ea80e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \ SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c \ TraceScreen.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \ HostnameMeter.c OpenFilesScreen.c Affinity.c IncSet.c Action.c EnvScreen.c \ -InfoScreen.c XAlloc.c +InfoScreen.c CommandScreen.c XAlloc.c myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \ CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \ @@ -32,7 +32,7 @@ BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h ScreenManager.h Settings.h SignalsPanel.h StringUtils.h SwapMeter.h \ TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \ AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \ -EnvScreen.h InfoScreen.h XAlloc.h Macros.h +EnvScreen.h InfoScreen.h CommandScreen.h XAlloc.h Macros.h # Linux # ----- diff --git a/htop.1.in b/htop.1.in index 424cc157..215d92c5 100644 --- a/htop.1.in +++ b/htop.1.in @@ -116,6 +116,9 @@ update of system calls issued by the process. Display open files for a process: if lsof(1) is installed, pressing this key will display the list of file descriptors opened by the process. .TP +.B M +Display the command line of the highlighted process in multiple lines. +.TP .B F1, h, ? Go to the help screen .TP