diff options
-rw-r--r-- | Action.c | 19 | ||||
-rw-r--r-- | EnvScreen.c | 130 | ||||
-rw-r--r-- | EnvScreen.h | 16 | ||||
-rw-r--r-- | InfoScreen.c | 180 | ||||
-rw-r--r-- | InfoScreen.h | 53 | ||||
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | OpenFilesScreen.c | 133 | ||||
-rw-r--r-- | OpenFilesScreen.h | 14 | ||||
-rw-r--r-- | TraceScreen.c | 254 | ||||
-rw-r--r-- | TraceScreen.h | 24 |
10 files changed, 421 insertions, 407 deletions
@@ -346,9 +346,9 @@ static Htop_Reaction actionSetup(State* st) { static Htop_Reaction actionLsof(State* st) { Process* p = (Process*) Panel_getSelected(st->panel); if (!p) return HTOP_OK; - OpenFilesScreen* ts = OpenFilesScreen_new(p); - OpenFilesScreen_run(ts); - OpenFilesScreen_delete(ts); + OpenFilesScreen* ofs = OpenFilesScreen_new(p); + InfoScreen_run((InfoScreen*)ofs); + OpenFilesScreen_delete((Object*)ofs); clear(); CRT_enableDelay(); return HTOP_REFRESH | HTOP_REDRAW_BAR; @@ -358,8 +358,11 @@ static Htop_Reaction actionStrace(State* st) { Process* p = (Process*) Panel_getSelected(st->panel); if (!p) return HTOP_OK; TraceScreen* ts = TraceScreen_new(p); - TraceScreen_run(ts); - TraceScreen_delete(ts); + bool ok = TraceScreen_forkTracer(ts); + if (ok) { + InfoScreen_run((InfoScreen*)ts); + } + TraceScreen_delete((Object*)ts); clear(); CRT_enableDelay(); return HTOP_REFRESH | HTOP_REDRAW_BAR; @@ -504,9 +507,9 @@ static Htop_Reaction actionTagAllChildren(State* st) { static Htop_Reaction actionShowEnvScreen(State* st) { Process* p = (Process*) Panel_getSelected(st->panel); if (!p) return HTOP_OK; - EnvScreen* ts = EnvScreen_new(p); - EnvScreen_run(ts); - EnvScreen_delete(ts); + EnvScreen* es = EnvScreen_new(p); + InfoScreen_run((InfoScreen*)es); + EnvScreen_delete((Object*)es); clear(); CRT_enableDelay(); return HTOP_REFRESH | HTOP_REDRAW_BAR; diff --git a/EnvScreen.c b/EnvScreen.c index 1881b1ff..f8645ed5 100644 --- a/EnvScreen.c +++ b/EnvScreen.c @@ -12,52 +12,37 @@ #include <unistd.h> /*{ -#include "ProcessList.h" -#include "Panel.h" -#include "FunctionBar.h" +#include "InfoScreen.h" typedef struct EnvScreen_ { - Process* process; - Panel* display; - FunctionBar* bar; + InfoScreen super; } EnvScreen; }*/ -static const char* EnvScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL}; - -static const char* EnvScreenKeys[] = {"F3", "F4", "F5", "Esc"}; - -static int EnvScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; +InfoScreenClass EnvScreen_class = { + .super = { + .extends = Class(Object), + .delete = EnvScreen_delete + }, + .scan = EnvScreen_scan, + .draw = EnvScreen_draw +}; EnvScreen* EnvScreen_new(Process* process) { EnvScreen* this = malloc(sizeof(EnvScreen)); - this->process = process; - FunctionBar* bar = FunctionBar_new(EnvScreenFunctions, EnvScreenKeys, EnvScreenEvents); - this->display = Panel_new(0, 1, COLS, LINES-3, false, Class(ListItem), bar); - return this; + Object_setClass(this, Class(EnvScreen)); + return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES-3, " "); } -void EnvScreen_delete(EnvScreen* this) { - Panel_delete((Object*)this->display); - free(this); +void EnvScreen_delete(Object* this) { + free(InfoScreen_done((InfoScreen*)this)); } -static void EnvScreen_draw(EnvScreen* this, IncSet* inc) { - attrset(CRT_colors[METER_TEXT]); - mvhline(0, 0, ' ', COLS); - mvprintw(0, 0, "environment of process %d - %s", this->process->pid, this->process->comm); - attrset(CRT_colors[DEFAULT_COLOR]); - Panel_draw(this->display, true); - IncSet_drawBar(inc); +void EnvScreen_draw(InfoScreen* this) { + InfoScreen_drawTitled(this, "Environment of process %d - %s", this->process->pid, this->process->comm); } -static inline void addLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) { - Vector_add(lines, (Object*) ListItem_new(line, 0)); - if (!incFilter || String_contains_i(line, incFilter)) - Panel_add(panel, (Object*)Vector_get(lines, Vector_size(lines)-1)); -} - -static void EnvScreen_scan(EnvScreen* this, Vector* lines, IncSet* inc) { +void EnvScreen_scan(InfoScreen* this) { Panel* panel = this->display; int idx = MAX(Panel_getSelectedIndex(panel), 0); @@ -69,89 +54,14 @@ static void EnvScreen_scan(EnvScreen* this, Vector* lines, IncSet* inc) { seteuid(euid); if (env) { for (char *p = env; *p; p = strrchr(p, 0)+1) - addLine(p, lines, panel, IncSet_filter(inc)); + InfoScreen_addLine(this, p); free(env); } else { - addLine("Could not read process environment.", lines, panel, IncSet_filter(inc)); + InfoScreen_addLine(this, "Could not read process environment."); } - Vector_insertionSort(lines); + Vector_insertionSort(this->lines); Vector_insertionSort(panel->items); Panel_setSelected(panel, idx); } - -void EnvScreen_run(EnvScreen* this) { - Panel* panel = this->display; - Panel_setHeader(panel, " "); - - FunctionBar* bar = panel->defaultBar; - IncSet* inc = IncSet_new(bar); - - Vector* lines = Vector_new(panel->items->type, true, DEFAULT_SIZE); - - EnvScreen_scan(this, lines, inc); - EnvScreen_draw(this, inc); - - bool looping = true; - while (looping) { - - Panel_draw(panel, true); - - if (inc->active) - move(LINES-1, CRT_cursorX); - int ch = getch(); - - if (ch == KEY_MOUSE) { - MEVENT mevent; - int ok = getmouse(&mevent); - if (ok == OK) - if (mevent.y >= panel->y && mevent.y < LINES - 1) { - Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV); - ch = 0; - } if (mevent.y == LINES - 1) - ch = IncSet_synthesizeEvent(inc, mevent.x); - } - - if (inc->active) { - IncSet_handleKey(inc, ch, panel, IncSet_getListItemValue, lines); - continue; - } - - switch(ch) { - case ERR: - continue; - case KEY_F(3): - case '/': - IncSet_activate(inc, INC_SEARCH, panel); - break; - case KEY_F(4): - case '\\': - IncSet_activate(inc, INC_FILTER, panel); - break; - case KEY_F(5): - clear(); - EnvScreen_scan(this, lines, inc); - EnvScreen_draw(this, inc); - break; - case '\014': // Ctrl+L - clear(); - EnvScreen_draw(this, inc); - break; - case 'q': - case 27: - case KEY_F(10): - looping = false; - break; - case KEY_RESIZE: - Panel_resize(panel, COLS, LINES-2); - EnvScreen_draw(this, inc); - break; - default: - Panel_onKey(panel, ch); - } - } - - Vector_delete(lines); - IncSet_delete(inc); -} diff --git a/EnvScreen.h b/EnvScreen.h index f33f0591..7cdbb865 100644 --- a/EnvScreen.h +++ b/EnvScreen.h @@ -3,20 +3,20 @@ #ifndef HEADER_EnvScreen #define HEADER_EnvScreen -#include "ProcessList.h" -#include "Panel.h" -#include "FunctionBar.h" +#include "InfoScreen.h" typedef struct EnvScreen_ { - Process* process; - Panel* display; - FunctionBar* bar; + InfoScreen super; } EnvScreen; +extern InfoScreenClass EnvScreen_class; + EnvScreen* EnvScreen_new(Process* process); -void EnvScreen_delete(EnvScreen* this); +void EnvScreen_delete(Object* this); + +void EnvScreen_draw(InfoScreen* this); -void EnvScreen_run(EnvScreen* this); +void EnvScreen_scan(InfoScreen* this); #endif diff --git a/InfoScreen.c b/InfoScreen.c new file mode 100644 index 00000000..7ce9ca6a --- /dev/null +++ b/InfoScreen.c @@ -0,0 +1,180 @@ +#include "InfoScreen.h" + +#include "config.h" +#include "Object.h" +#include "CRT.h" +#include "IncSet.h" +#include "ListItem.h" +#include "Platform.h" +#include "StringUtils.h" + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> + +/*{ +#include "Process.h" +#include "Panel.h" +#include "FunctionBar.h" +#include "IncSet.h" + +typedef struct InfoScreen_ InfoScreen; + +typedef void(*InfoScreen_Scan)(InfoScreen*); +typedef void(*InfoScreen_Draw)(InfoScreen*); +typedef void(*InfoScreen_OnErr)(InfoScreen*); +typedef bool(*InfoScreen_OnKey)(InfoScreen*, int); + +typedef struct InfoScreenClass_ { + ObjectClass super; + const InfoScreen_Scan scan; + const InfoScreen_Draw draw; + const InfoScreen_OnErr onErr; + const InfoScreen_OnKey onKey; +} InfoScreenClass; + +#define As_InfoScreen(this_) ((InfoScreenClass*)(((InfoScreen*)(this_))->super.klass)) +#define InfoScreen_scan(this_) As_InfoScreen(this_)->scan((InfoScreen*)(this_)) +#define InfoScreen_draw(this_) As_InfoScreen(this_)->draw((InfoScreen*)(this_)) +#define InfoScreen_onErr(this_) As_InfoScreen(this_)->onErr((InfoScreen*)(this_)) +#define InfoScreen_onKey(this_, ch_) As_InfoScreen(this_)->onKey((InfoScreen*)(this_), ch_) + +struct InfoScreen_ { + Object super; + Process* process; + Panel* display; + FunctionBar* bar; + IncSet* inc; + Vector* lines; +}; +}*/ + +static const char* InfoScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL}; + +static const char* InfoScreenKeys[] = {"F3", "F4", "F5", "Esc"}; + +static int InfoScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; + +InfoScreen* InfoScreen_init(InfoScreen* this, Process* process, FunctionBar* bar, int height, char* panelHeader) { + this->process = process; + if (!bar) { + bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents); + } + this->display = Panel_new(0, 1, COLS, height, false, Class(ListItem), bar); + this->inc = IncSet_new(bar); + this->lines = Vector_new(this->display->items->type, true, DEFAULT_SIZE); + Panel_setHeader(this->display, panelHeader); + return this; +} + +InfoScreen* InfoScreen_done(InfoScreen* this) { + Panel_delete((Object*)this->display); + IncSet_delete(this->inc); + Vector_delete(this->lines); + return this; +} + +void InfoScreen_drawTitled(InfoScreen* this, char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + attrset(CRT_colors[METER_TEXT]); + mvhline(0, 0, ' ', COLS); + wmove(stdscr, 0, 0); + vw_printw(stdscr, fmt, ap); + attrset(CRT_colors[DEFAULT_COLOR]); + Panel_draw(this->display, true); + IncSet_drawBar(this->inc); + va_end(ap); +} + +void InfoScreen_addLine(InfoScreen* this, const char* line) { + Vector_add(this->lines, (Object*) ListItem_new(line, 0)); + const char* incFilter = IncSet_filter(this->inc); + if (!incFilter || String_contains_i(line, incFilter)) + Panel_add(this->display, (Object*)Vector_get(this->lines, Vector_size(this->lines)-1)); +} + +void InfoScreen_appendLine(InfoScreen* this, const char* line) { + ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines)-1); + ListItem_append(last, line); + const char* incFilter = IncSet_filter(this->inc); + if (incFilter && Panel_get(this->display, Panel_size(this->display)-1) != (Object*)last && String_contains_i(line, incFilter)) + Panel_add(this->display, (Object*)last); +} + +void InfoScreen_run(InfoScreen* this) { + Panel* panel = this->display; + + if (As_InfoScreen(this)->scan) InfoScreen_scan(this); + InfoScreen_draw(this); + + bool looping = true; + while (looping) { + + Panel_draw(panel, true); + + if (this->inc->active) + move(LINES-1, CRT_cursorX); + int ch = getch(); + + if (ch == ERR) { + if (As_InfoScreen(this)->onErr) { + InfoScreen_onErr(this); + continue; + } + } + + if (ch == KEY_MOUSE) { + MEVENT mevent; + int ok = getmouse(&mevent); + if (ok == OK) + if (mevent.y >= panel->y && mevent.y < LINES - 1) { + Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV); + ch = 0; + } if (mevent.y == LINES - 1) + ch = IncSet_synthesizeEvent(this->inc, mevent.x); + } + + if (this->inc->active) { + IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines); + continue; + } + + switch(ch) { + case ERR: + continue; + case KEY_F(3): + case '/': + IncSet_activate(this->inc, INC_SEARCH, panel); + break; + case KEY_F(4): + case '\\': + IncSet_activate(this->inc, INC_FILTER, panel); + break; + case KEY_F(5): + clear(); + if (As_InfoScreen(this)->scan) InfoScreen_scan(this); + InfoScreen_draw(this); + break; + case '\014': // Ctrl+L + clear(); + InfoScreen_draw(this); + break; + case 'q': + case 27: + case KEY_F(10): + looping = false; + break; + case KEY_RESIZE: + Panel_resize(panel, COLS, LINES-2); + InfoScreen_draw(this); + break; + default: + if (As_InfoScreen(this)->onKey && InfoScreen_onKey(this, ch)) { + continue; + } + Panel_onKey(panel, ch); + } + } +} diff --git a/InfoScreen.h b/InfoScreen.h new file mode 100644 index 00000000..2e1599f9 --- /dev/null +++ b/InfoScreen.h @@ -0,0 +1,53 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_InfoScreen +#define HEADER_InfoScreen + +#include "Process.h" +#include "Panel.h" +#include "FunctionBar.h" +#include "IncSet.h" + +typedef struct InfoScreen_ InfoScreen; + +typedef void(*InfoScreen_Scan)(InfoScreen*); +typedef void(*InfoScreen_Draw)(InfoScreen*); +typedef void(*InfoScreen_OnErr)(InfoScreen*); +typedef bool(*InfoScreen_OnKey)(InfoScreen*, int); + +typedef struct InfoScreenClass_ { + ObjectClass super; + const InfoScreen_Scan scan; + const InfoScreen_Draw draw; + const InfoScreen_OnErr onErr; + const InfoScreen_OnKey onKey; +} InfoScreenClass; + +#define As_InfoScreen(this_) ((InfoScreenClass*)(((InfoScreen*)(this_))->super.klass)) +#define InfoScreen_scan(this_) As_InfoScreen(this_)->scan((InfoScreen*)(this_)) +#define InfoScreen_draw(this_) As_InfoScreen(this_)->draw((InfoScreen*)(this_)) +#define InfoScreen_onErr(this_) As_InfoScreen(this_)->onErr((InfoScreen*)(this_)) +#define InfoScreen_onKey(this_, ch_) As_InfoScreen(this_)->onKey((InfoScreen*)(this_), ch_) + +struct InfoScreen_ { + Object super; + Process* process; + Panel* display; + FunctionBar* bar; + IncSet* inc; + Vector* lines; +}; + +InfoScreen* InfoScreen_init(InfoScreen* this, Process* process, FunctionBar* bar, int height, char* panelHeader); + +InfoScreen* InfoScreen_done(InfoScreen* this); + +void InfoScreen_drawTitled(InfoScreen* this, char* fmt, ...); + +void InfoScreen_addLine(InfoScreen* this, const char* line); + +void InfoScreen_appendLine(InfoScreen* this, const char* line); + +void InfoScreen_run(InfoScreen* this); + +#endif diff --git a/Makefile.am b/Makefile.am index 2861e10b..df122595 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,8 @@ LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \ 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 +HostnameMeter.c OpenFilesScreen.c Affinity.c IncSet.c Action.c EnvScreen.c \ +InfoScreen.c myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \ CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \ @@ -33,7 +34,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 +EnvScreen.h InfoScreen.h if HTOP_LINUX htop_CFLAGS += -rdynamic diff --git a/OpenFilesScreen.c b/OpenFilesScreen.c index 2a5e20af..096ed939 100644 --- a/OpenFilesScreen.c +++ b/OpenFilesScreen.c @@ -9,7 +9,6 @@ in the source distribution for its full text. #include "CRT.h" #include "ProcessList.h" -#include "ListItem.h" #include "IncSet.h" #include "StringUtils.h" #include "FunctionBar.h" @@ -25,8 +24,7 @@ in the source distribution for its full text. #include <sys/wait.h> /*{ -#include "Process.h" -#include "Panel.h" +#include "InfoScreen.h" typedef struct OpenFiles_Data_ { char* data[256]; @@ -44,43 +42,37 @@ typedef struct OpenFiles_FileData_ { } OpenFiles_FileData; typedef struct OpenFilesScreen_ { - Process* process; + InfoScreen super; pid_t pid; - Panel* display; } OpenFilesScreen; }*/ -static const char* OpenFilesScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL}; - -static const char* OpenFilesScreenKeys[] = {"F3", "F4", "F5", "Esc"}; - -static int OpenFilesScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; +InfoScreenClass OpenFilesScreen_class = { + .super = { + .extends = Class(Object), + .delete = OpenFilesScreen_delete + }, + .scan = OpenFilesScreen_scan, + .draw = OpenFilesScreen_draw +}; OpenFilesScreen* OpenFilesScreen_new(Process* process) { OpenFilesScreen* this = malloc(sizeof(OpenFilesScreen)); - this->process = process; - FunctionBar* bar = FunctionBar_new(OpenFilesScreenFunctions, OpenFilesScreenKeys, OpenFilesScreenEvents); - this->display = Panel_new(0, 1, COLS, LINES-3, false, Class(ListItem), bar); + Object_setClass(this, Class(OpenFilesScreen)); if (Process_isThread(process)) this->pid = process->tgid; else this->pid = process->pid; - return this; + return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES-3, " FD TYPE DEVICE SIZE NODE NAME"); } -void OpenFilesScreen_delete(OpenFilesScreen* this) { - Panel_delete((Object*)this->display); - free(this); +void OpenFilesScreen_delete(Object* this) { + free(InfoScreen_done((InfoScreen*)this)); } -static void OpenFilesScreen_draw(OpenFilesScreen* this, IncSet* inc) { - attrset(CRT_colors[METER_TEXT]); - mvhline(0, 0, ' ', COLS); - mvprintw(0, 0, "Snapshot of files open in process %d - %s", this->pid, this->process->comm); - attrset(CRT_colors[DEFAULT_COLOR]); - Panel_draw(this->display, true); - IncSet_drawBar(inc); +void OpenFilesScreen_draw(InfoScreen* this) { + InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, this->process->comm); } static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { @@ -122,27 +114,21 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { return pdata; } -static inline void addLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) { - Vector_add(lines, (Object*) ListItem_new(line, 0)); - if (!incFilter || String_contains_i(line, incFilter)) - Panel_add(panel, (Object*)Vector_get(lines, Vector_size(lines)-1)); -} - static inline void OpenFiles_Data_clear(OpenFiles_Data* data) { for (int i = 0; i < 255; i++) if (data->data[i]) free(data->data[i]); } -static void OpenFilesScreen_scan(OpenFilesScreen* this, Vector* lines, IncSet* inc) { +void OpenFilesScreen_scan(InfoScreen* this) { Panel* panel = this->display; int idx = Panel_getSelectedIndex(panel); Panel_prune(panel); - OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(this->pid); + OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(((OpenFilesScreen*)this)->pid); if (pdata->error == 127) { - addLine("Could not execute 'lsof'. Please make sure it is available in your $PATH.", lines, panel, IncSet_filter(inc)); + InfoScreen_addLine(this, "Could not execute 'lsof'. Please make sure it is available in your $PATH."); } else if (pdata->error == 1) { - addLine("Failed listing open files.", lines, panel, IncSet_filter(inc)); + InfoScreen_addLine(this, "Failed listing open files."); } else { OpenFiles_FileData* fdata = pdata->files; while (fdata) { @@ -155,7 +141,7 @@ static void OpenFilesScreen_scan(OpenFilesScreen* this, Vector* lines, IncSet* i data['s'] ? data['s'] : "", data['i'] ? data['i'] : "", data['n'] ? data['n'] : ""); - addLine(entry, lines, panel, IncSet_filter(inc)); + InfoScreen_addLine(this, entry); OpenFiles_Data_clear(&fdata->data); OpenFiles_FileData* old = fdata; fdata = fdata->next; @@ -164,82 +150,7 @@ static void OpenFilesScreen_scan(OpenFilesScreen* this, Vector* lines, IncSet* i OpenFiles_Data_clear(&pdata->data); } free(pdata); - Vector_insertionSort(lines); + Vector_insertionSort(this->lines); Vector_insertionSort(panel->items); Panel_setSelected(panel, idx); } - -void OpenFilesScreen_run(OpenFilesScreen* this) { - Panel* panel = this->display; - Panel_setHeader(panel, " FD TYPE DEVICE SIZE NODE NAME"); - - FunctionBar* bar = panel->defaultBar; - IncSet* inc = IncSet_new(bar); - - Vector* lines = Vector_new(panel->items->type, true, DEFAULT_SIZE); - - OpenFilesScreen_scan(this, lines, inc); - OpenFilesScreen_draw(this, inc); - - bool looping = true; - while (looping) { - - Panel_draw(panel, true); - - if (inc->active) - move(LINES-1, CRT_cursorX); - int ch = getch(); - - if (ch == KEY_MOUSE) { - MEVENT mevent; - int ok = getmouse(&mevent); - if (ok == OK) - if (mevent.y >= panel->y && mevent.y < LINES - 1) { - Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV); - ch = 0; - } if (mevent.y == LINES - 1) - ch = IncSet_synthesizeEvent(inc, mevent.x); - } - - if (inc->active) { - IncSet_handleKey(inc, ch, panel, IncSet_getListItemValue, lines); - continue; - } - - switch(ch) { - case ERR: - continue; - case KEY_F(3): - case '/': - IncSet_activate(inc, INC_SEARCH, panel); - break; - case KEY_F(4): - case '\\': - IncSet_activate(inc, INC_FILTER, panel); - break; - case KEY_F(5): - clear(); - OpenFilesScreen_scan(this, lines, inc); - OpenFilesScreen_draw(this, inc); - break; - case '\014': // Ctrl+L - clear(); - OpenFilesScreen_draw(this, inc); - break; - case 'q': - case 27: - case KEY_F(10): - looping = false; - break; - case KEY_RESIZE: - Panel_resize(panel, COLS, LINES-2); - OpenFilesScreen_draw(this, inc); - break; - default: - Panel_onKey(panel, ch); - } - } - - Vector_delete(lines); - IncSet_delete(inc); -} diff --git a/OpenFilesScreen.h b/OpenFilesScreen.h index 68e33363..8160cfe2 100644 --- a/OpenFilesScreen.h +++ b/OpenFilesScreen.h @@ -9,8 +9,7 @@ Released under the GNU GPL, see the COPYING file in the source distribution for its full text. */ -#include "Process.h" -#include "Panel.h" +#include "InfoScreen.h" typedef struct OpenFiles_Data_ { char* data[256]; @@ -28,16 +27,19 @@ typedef struct OpenFiles_FileData_ { } OpenFiles_FileData; typedef struct OpenFilesScreen_ { - Process* process; + InfoScreen super; pid_t pid; - Panel* display; } OpenFilesScreen; +extern InfoScreenClass OpenFilesScreen_class; + OpenFilesScreen* OpenFilesScreen_new(Process* process); -void OpenFilesScreen_delete(OpenFilesScreen* this); +void OpenFilesScreen_delete(Object* this); + +void OpenFilesScreen_draw(InfoScreen* this); -void OpenFilesScreen_run(OpenFilesScreen* this); +void OpenFilesScreen_scan(InfoScreen* this); #endif diff --git a/TraceScreen.c b/TraceScreen.c index 3a62eb63..0752a13c 100644 --- a/TraceScreen.c +++ b/TraceScreen.c @@ -8,6 +8,7 @@ in the source distribution for its full text. #include "TraceScreen.h" #include "CRT.h" +#include "InfoScreen.h" #include "ProcessList.h" #include "ListItem.h" #include "IncSet.h" @@ -26,13 +27,17 @@ in the source distribution for its full text. #include <signal.h> /*{ -#include "Process.h" -#include "Panel.h" +#include "InfoScreen.h" typedef struct TraceScreen_ { - Process* process; - Panel* display; + InfoScreen super; bool tracing; + int fdpair[2]; + int child; + FILE* strace; + int fd_strace; + bool contLine; + bool follow; } TraceScreen; }*/ @@ -43,188 +48,125 @@ static const char* TraceScreenKeys[] = {"F3", "F4", "F8", "F9", "Esc"}; static int TraceScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(8), KEY_F(9), 27}; +InfoScreenClass TraceScreen_class = { + .super = { + .extends = Class(Object), + .delete = TraceScreen_delete + }, + .draw = TraceScreen_draw, + .onErr = TraceScreen_updateTrace, + .onKey = TraceScreen_onKey, +}; + TraceScreen* TraceScreen_new(Process* process) { TraceScreen* this = malloc(sizeof(TraceScreen)); - this->process = process; - FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents); - this->display = Panel_new(0, 1, COLS, LINES-2, false, Class(ListItem), fuBar); + Object_setClass(this, Class(TraceScreen)); this->tracing = true; - return this; + this->contLine = false; + this->follow = false; + FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents); + CRT_disableDelay(); + return (TraceScreen*) InfoScreen_init(&this->super, process, fuBar, LINES-2, ""); } -void TraceScreen_delete(TraceScreen* this) { - Panel_delete((Object*)this->display); - free(this); +void TraceScreen_delete(Object* cast) { + TraceScreen* this = (TraceScreen*) cast; + if (this->child > 0) { + kill(this->child, SIGTERM); + waitpid(this->child, NULL, 0); + fclose(this->strace); + } + CRT_enableDelay(); + free(InfoScreen_done((InfoScreen*)cast)); } -static void TraceScreen_draw(TraceScreen* this, IncSet* inc) { +void TraceScreen_draw(InfoScreen* this) { attrset(CRT_colors[PANEL_HEADER_FOCUS]); mvhline(0, 0, ' ', COLS); mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm); attrset(CRT_colors[DEFAULT_COLOR]); - IncSet_drawBar(inc); -} - -static inline void addLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) { - Vector_add(lines, (Object*) ListItem_new(line, 0)); - if (!incFilter || String_contains_i(line, incFilter)) - Panel_add(panel, (Object*)Vector_get(lines, Vector_size(lines)-1)); + IncSet_drawBar(this->inc); } -static inline void appendLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) { - ListItem* last = (ListItem*)Vector_get(lines, Vector_size(lines)-1); - ListItem_append(last, line); - if (incFilter && Panel_get(panel, Panel_size(panel)-1) != (Object*)last && String_contains_i(line, incFilter)) - Panel_add(panel, (Object*)last); -} - -void TraceScreen_run(TraceScreen* this) { +bool TraceScreen_forkTracer(TraceScreen* this) { char buffer[1001]; - int fdpair[2]; - int err = pipe(fdpair); - if (err == -1) return; - int child = fork(); - if (child == -1) return; - if (child == 0) { + int err = pipe(this->fdpair); + if (err == -1) return false; + this->child = fork(); + if (this->child == -1) return false; + if (this->child == 0) { seteuid(getuid()); - dup2(fdpair[1], STDERR_FILENO); - int ok = fcntl(fdpair[1], F_SETFL, O_NONBLOCK); + dup2(this->fdpair[1], STDERR_FILENO); + int ok = fcntl(this->fdpair[1], F_SETFL, O_NONBLOCK); if (ok != -1) { - sprintf(buffer, "%d", this->process->pid); + sprintf(buffer, "%d", this->super.process->pid); execlp("strace", "strace", "-p", buffer, NULL); } const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH."; - ssize_t written = write(fdpair[1], message, strlen(message)); + ssize_t written = write(this->fdpair[1], message, strlen(message)); (void) written; exit(1); } - fcntl(fdpair[0], F_SETFL, O_NONBLOCK); - FILE* strace = fdopen(fdpair[0], "r"); - Panel* panel = this->display; - int fd_strace = fileno(strace); - CRT_disableDelay(); - bool contLine = false; - bool follow = false; - bool looping = true; - - FunctionBar* bar = panel->defaultBar; - IncSet* inc = IncSet_new(bar); - - Vector* lines = Vector_new(panel->items->type, true, DEFAULT_SIZE); - - TraceScreen_draw(this, inc); - - while (looping) { - - Panel_draw(panel, true); - const char* incFilter = IncSet_filter(inc); - - if (inc->active) - move(LINES-1, CRT_cursorX); - int ch = getch(); - - if (ch == ERR) { - fd_set fds; - FD_ZERO(&fds); -// FD_SET(STDIN_FILENO, &fds); - FD_SET(fd_strace, &fds); - struct timeval tv; - tv.tv_sec = 0; tv.tv_usec = 500; - int ready = select(fd_strace+1, &fds, NULL, NULL, &tv); - int nread = 0; - if (ready > 0 && FD_ISSET(fd_strace, &fds)) - nread = fread(buffer, 1, 1000, strace); - if (nread && this->tracing) { - char* line = buffer; - buffer[nread] = '\0'; - for (int i = 0; i < nread; i++) { - if (buffer[i] == '\n') { - buffer[i] = '\0'; - if (contLine) { - appendLine(line, lines, panel, incFilter); - contLine = false; - } else { - addLine(line, lines, panel, incFilter); - } - line = buffer+i+1; - } - } - if (line < buffer+nread) { - addLine(line, lines, panel, incFilter); - buffer[nread] = '\0'; - contLine = true; + fcntl(this->fdpair[0], F_SETFL, O_NONBLOCK); + this->strace = fdopen(this->fdpair[0], "r"); + this->fd_strace = fileno(this->strace); + return true; +} + +void TraceScreen_updateTrace(InfoScreen* super) { + TraceScreen* this = (TraceScreen*) super; + char buffer[1001]; + fd_set fds; + FD_ZERO(&fds); +// FD_SET(STDIN_FILENO, &fds); + FD_SET(this->fd_strace, &fds); + struct timeval tv; + tv.tv_sec = 0; tv.tv_usec = 500; + int ready = select(this->fd_strace+1, &fds, NULL, NULL, &tv); + int nread = 0; + if (ready > 0 && FD_ISSET(this->fd_strace, &fds)) + nread = fread(buffer, 1, 1000, this->strace); + if (nread && this->tracing) { + char* line = buffer; + buffer[nread] = '\0'; + for (int i = 0; i < nread; i++) { + if (buffer[i] == '\n') { + buffer[i] = '\0'; + if (this->contLine) { + InfoScreen_appendLine(&this->super, line); + this->contLine = false; + } else { + InfoScreen_addLine(&this->super, line); } - if (follow) - Panel_setSelected(panel, Panel_size(panel)-1); + line = buffer+i+1; } } - - if (ch == KEY_MOUSE) { - MEVENT mevent; - int ok = getmouse(&mevent); - if (ok == OK) - if (mevent.y >= panel->y && mevent.y < LINES - 1) { - Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV); - follow = false; - ch = 0; - } if (mevent.y == LINES - 1) - ch = IncSet_synthesizeEvent(inc, mevent.x); - } - - if (inc->active) { - IncSet_handleKey(inc, ch, panel, IncSet_getListItemValue, lines); - continue; + if (line < buffer+nread) { + InfoScreen_addLine(&this->super, line); + buffer[nread] = '\0'; + this->contLine = true; } - - switch(ch) { - case ERR: - continue; - case KEY_HOME: - Panel_setSelected(panel, 0); - break; - case KEY_END: - Panel_setSelected(panel, Panel_size(panel)-1); - break; - case KEY_F(3): - case '/': - IncSet_activate(inc, INC_SEARCH, panel); - break; - case KEY_F(4): - case '\\': - IncSet_activate(inc, INC_FILTER, panel); - break; + if (this->follow) + Panel_setSelected(this->super.display, Panel_size(this->super.display)-1); + } +} + +bool TraceScreen_onKey(InfoScreen* super, int ch) { + TraceScreen* this = (TraceScreen*) super; + switch(ch) { case 'f': case KEY_F(8): - follow = !follow; - if (follow) - Panel_setSelected(panel, Pan |