refactor *Screen classes, add InfoScreen superclass

This commit is contained in:
Hisham Muhammad 2016-01-12 06:00:58 -02:00
parent faf2860669
commit 466d4da0c6
10 changed files with 420 additions and 406 deletions

View File

@ -346,9 +346,9 @@ static Htop_Reaction actionSetup(State* st) {
static Htop_Reaction actionLsof(State* st) { static Htop_Reaction actionLsof(State* st) {
Process* p = (Process*) Panel_getSelected(st->panel); Process* p = (Process*) Panel_getSelected(st->panel);
if (!p) return HTOP_OK; if (!p) return HTOP_OK;
OpenFilesScreen* ts = OpenFilesScreen_new(p); OpenFilesScreen* ofs = OpenFilesScreen_new(p);
OpenFilesScreen_run(ts); InfoScreen_run((InfoScreen*)ofs);
OpenFilesScreen_delete(ts); OpenFilesScreen_delete((Object*)ofs);
clear(); clear();
CRT_enableDelay(); CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR; return HTOP_REFRESH | HTOP_REDRAW_BAR;
@ -358,8 +358,11 @@ static Htop_Reaction actionStrace(State* st) {
Process* p = (Process*) Panel_getSelected(st->panel); Process* p = (Process*) Panel_getSelected(st->panel);
if (!p) return HTOP_OK; if (!p) return HTOP_OK;
TraceScreen* ts = TraceScreen_new(p); TraceScreen* ts = TraceScreen_new(p);
TraceScreen_run(ts); bool ok = TraceScreen_forkTracer(ts);
TraceScreen_delete(ts); if (ok) {
InfoScreen_run((InfoScreen*)ts);
}
TraceScreen_delete((Object*)ts);
clear(); clear();
CRT_enableDelay(); CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR; return HTOP_REFRESH | HTOP_REDRAW_BAR;
@ -504,9 +507,9 @@ static Htop_Reaction actionTagAllChildren(State* st) {
static Htop_Reaction actionShowEnvScreen(State* st) { static Htop_Reaction actionShowEnvScreen(State* st) {
Process* p = (Process*) Panel_getSelected(st->panel); Process* p = (Process*) Panel_getSelected(st->panel);
if (!p) return HTOP_OK; if (!p) return HTOP_OK;
EnvScreen* ts = EnvScreen_new(p); EnvScreen* es = EnvScreen_new(p);
EnvScreen_run(ts); InfoScreen_run((InfoScreen*)es);
EnvScreen_delete(ts); EnvScreen_delete((Object*)es);
clear(); clear();
CRT_enableDelay(); CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR; return HTOP_REFRESH | HTOP_REDRAW_BAR;

View File

@ -12,52 +12,37 @@
#include <unistd.h> #include <unistd.h>
/*{ /*{
#include "ProcessList.h" #include "InfoScreen.h"
#include "Panel.h"
#include "FunctionBar.h"
typedef struct EnvScreen_ { typedef struct EnvScreen_ {
Process* process; InfoScreen super;
Panel* display;
FunctionBar* bar;
} EnvScreen; } EnvScreen;
}*/ }*/
static const char* EnvScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL}; InfoScreenClass EnvScreen_class = {
.super = {
static const char* EnvScreenKeys[] = {"F3", "F4", "F5", "Esc"}; .extends = Class(Object),
.delete = EnvScreen_delete
static int EnvScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; },
.scan = EnvScreen_scan,
.draw = EnvScreen_draw
};
EnvScreen* EnvScreen_new(Process* process) { EnvScreen* EnvScreen_new(Process* process) {
EnvScreen* this = malloc(sizeof(EnvScreen)); EnvScreen* this = malloc(sizeof(EnvScreen));
this->process = process; Object_setClass(this, Class(EnvScreen));
FunctionBar* bar = FunctionBar_new(EnvScreenFunctions, EnvScreenKeys, EnvScreenEvents); return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES-3, " ");
this->display = Panel_new(0, 1, COLS, LINES-3, false, Class(ListItem), bar);
return this;
} }
void EnvScreen_delete(EnvScreen* this) { void EnvScreen_delete(Object* this) {
Panel_delete((Object*)this->display); free(InfoScreen_done((InfoScreen*)this));
free(this);
} }
static void EnvScreen_draw(EnvScreen* this, IncSet* inc) { void EnvScreen_draw(InfoScreen* this) {
attrset(CRT_colors[METER_TEXT]); InfoScreen_drawTitled(this, "Environment of process %d - %s", this->process->pid, this->process->comm);
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);
} }
static inline void addLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) { void EnvScreen_scan(InfoScreen* this) {
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) {
Panel* panel = this->display; Panel* panel = this->display;
int idx = MAX(Panel_getSelectedIndex(panel), 0); int idx = MAX(Panel_getSelectedIndex(panel), 0);
@ -69,89 +54,14 @@ static void EnvScreen_scan(EnvScreen* this, Vector* lines, IncSet* inc) {
seteuid(euid); seteuid(euid);
if (env) { if (env) {
for (char *p = env; *p; p = strrchr(p, 0)+1) for (char *p = env; *p; p = strrchr(p, 0)+1)
addLine(p, lines, panel, IncSet_filter(inc)); InfoScreen_addLine(this, p);
free(env); free(env);
} }
else { 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); Vector_insertionSort(panel->items);
Panel_setSelected(panel, idx); 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);
}

View File

@ -3,20 +3,20 @@
#ifndef HEADER_EnvScreen #ifndef HEADER_EnvScreen
#define HEADER_EnvScreen #define HEADER_EnvScreen
#include "ProcessList.h" #include "InfoScreen.h"
#include "Panel.h"
#include "FunctionBar.h"
typedef struct EnvScreen_ { typedef struct EnvScreen_ {
Process* process; InfoScreen super;
Panel* display;
FunctionBar* bar;
} EnvScreen; } EnvScreen;
extern InfoScreenClass EnvScreen_class;
EnvScreen* EnvScreen_new(Process* process); EnvScreen* EnvScreen_new(Process* process);
void EnvScreen_delete(EnvScreen* this); void EnvScreen_delete(Object* this);
void EnvScreen_run(EnvScreen* this); void EnvScreen_draw(InfoScreen* this);
void EnvScreen_scan(InfoScreen* this);
#endif #endif

180
InfoScreen.c Normal file
View File

@ -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);
}
}
}

53
InfoScreen.h Normal file
View File

@ -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

View File

@ -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 \ BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c \ SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c \
TraceScreen.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.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 \ myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \
CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.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 \ ScreenManager.h Settings.h SignalsPanel.h StringUtils.h SwapMeter.h \
TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.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 \ AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \
EnvScreen.h EnvScreen.h InfoScreen.h
if HTOP_LINUX if HTOP_LINUX
htop_CFLAGS += -rdynamic htop_CFLAGS += -rdynamic

View File

@ -9,7 +9,6 @@ in the source distribution for its full text.
#include "CRT.h" #include "CRT.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "ListItem.h"
#include "IncSet.h" #include "IncSet.h"
#include "StringUtils.h" #include "StringUtils.h"
#include "FunctionBar.h" #include "FunctionBar.h"
@ -25,8 +24,7 @@ in the source distribution for its full text.
#include <sys/wait.h> #include <sys/wait.h>
/*{ /*{
#include "Process.h" #include "InfoScreen.h"
#include "Panel.h"
typedef struct OpenFiles_Data_ { typedef struct OpenFiles_Data_ {
char* data[256]; char* data[256];
@ -44,43 +42,37 @@ typedef struct OpenFiles_FileData_ {
} OpenFiles_FileData; } OpenFiles_FileData;
typedef struct OpenFilesScreen_ { typedef struct OpenFilesScreen_ {
Process* process; InfoScreen super;
pid_t pid; pid_t pid;
Panel* display;
} OpenFilesScreen; } OpenFilesScreen;
}*/ }*/
static const char* OpenFilesScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL}; InfoScreenClass OpenFilesScreen_class = {
.super = {
static const char* OpenFilesScreenKeys[] = {"F3", "F4", "F5", "Esc"}; .extends = Class(Object),
.delete = OpenFilesScreen_delete
static int OpenFilesScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; },
.scan = OpenFilesScreen_scan,
.draw = OpenFilesScreen_draw
};
OpenFilesScreen* OpenFilesScreen_new(Process* process) { OpenFilesScreen* OpenFilesScreen_new(Process* process) {
OpenFilesScreen* this = malloc(sizeof(OpenFilesScreen)); OpenFilesScreen* this = malloc(sizeof(OpenFilesScreen));
this->process = process; Object_setClass(this, Class(OpenFilesScreen));
FunctionBar* bar = FunctionBar_new(OpenFilesScreenFunctions, OpenFilesScreenKeys, OpenFilesScreenEvents);
this->display = Panel_new(0, 1, COLS, LINES-3, false, Class(ListItem), bar);
if (Process_isThread(process)) if (Process_isThread(process))
this->pid = process->tgid; this->pid = process->tgid;
else else
this->pid = process->pid; 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) { void OpenFilesScreen_delete(Object* this) {
Panel_delete((Object*)this->display); free(InfoScreen_done((InfoScreen*)this));
free(this);
} }
static void OpenFilesScreen_draw(OpenFilesScreen* this, IncSet* inc) { void OpenFilesScreen_draw(InfoScreen* this) {
attrset(CRT_colors[METER_TEXT]); InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, this->process->comm);
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);
} }
static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
@ -122,27 +114,21 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
return pdata; 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) { static inline void OpenFiles_Data_clear(OpenFiles_Data* data) {
for (int i = 0; i < 255; i++) for (int i = 0; i < 255; i++)
if (data->data[i]) if (data->data[i])
free(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; Panel* panel = this->display;
int idx = Panel_getSelectedIndex(panel); int idx = Panel_getSelectedIndex(panel);
Panel_prune(panel); Panel_prune(panel);
OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(this->pid); OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(((OpenFilesScreen*)this)->pid);
if (pdata->error == 127) { 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) { } else if (pdata->error == 1) {
addLine("Failed listing open files.", lines, panel, IncSet_filter(inc)); InfoScreen_addLine(this, "Failed listing open files.");
} else { } else {
OpenFiles_FileData* fdata = pdata->files; OpenFiles_FileData* fdata = pdata->files;
while (fdata) { while (fdata) {
@ -155,7 +141,7 @@ static void OpenFilesScreen_scan(OpenFilesScreen* this, Vector* lines, IncSet* i
data['s'] ? data['s'] : "", data['s'] ? data['s'] : "",
data['i'] ? data['i'] : "", data['i'] ? data['i'] : "",
data['n'] ? data['n'] : ""); data['n'] ? data['n'] : "");
addLine(entry, lines, panel, IncSet_filter(inc)); InfoScreen_addLine(this, entry);
OpenFiles_Data_clear(&fdata->data); OpenFiles_Data_clear(&fdata->data);
OpenFiles_FileData* old = fdata; OpenFiles_FileData* old = fdata;
fdata = fdata->next; fdata = fdata->next;
@ -164,82 +150,7 @@ static void OpenFilesScreen_scan(OpenFilesScreen* this, Vector* lines, IncSet* i
OpenFiles_Data_clear(&pdata->data); OpenFiles_Data_clear(&pdata->data);
} }
free(pdata); free(pdata);
Vector_insertionSort(lines); Vector_insertionSort(this->lines);
Vector_insertionSort(panel->items); Vector_insertionSort(panel->items);
Panel_setSelected(panel, idx); 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);
}

View File

@ -9,8 +9,7 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Process.h" #include "InfoScreen.h"
#include "Panel.h"
typedef struct OpenFiles_Data_ { typedef struct OpenFiles_Data_ {
char* data[256]; char* data[256];
@ -28,16 +27,19 @@ typedef struct OpenFiles_FileData_ {
} OpenFiles_FileData; } OpenFiles_FileData;
typedef struct OpenFilesScreen_ { typedef struct OpenFilesScreen_ {
Process* process; InfoScreen super;
pid_t pid; pid_t pid;
Panel* display;
} OpenFilesScreen; } OpenFilesScreen;
extern InfoScreenClass OpenFilesScreen_class;
OpenFilesScreen* OpenFilesScreen_new(Process* process); OpenFilesScreen* OpenFilesScreen_new(Process* process);
void OpenFilesScreen_delete(OpenFilesScreen* this); void OpenFilesScreen_delete(Object* this);
void OpenFilesScreen_run(OpenFilesScreen* this); void OpenFilesScreen_draw(InfoScreen* this);
void OpenFilesScreen_scan(InfoScreen* this);
#endif #endif

View File

@ -8,6 +8,7 @@ in the source distribution for its full text.
#include "TraceScreen.h" #include "TraceScreen.h"
#include "CRT.h" #include "CRT.h"
#include "InfoScreen.h"
#include "ProcessList.h" #include "ProcessList.h"
#include "ListItem.h" #include "ListItem.h"
#include "IncSet.h" #include "IncSet.h"
@ -26,13 +27,17 @@ in the source distribution for its full text.
#include <signal.h> #include <signal.h>
/*{ /*{
#include "Process.h" #include "InfoScreen.h"
#include "Panel.h"
typedef struct TraceScreen_ { typedef struct TraceScreen_ {
Process* process; InfoScreen super;
Panel* display;
bool tracing; bool tracing;
int fdpair[2];
int child;
FILE* strace;
int fd_strace;
bool contLine;
bool follow;
} TraceScreen; } 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}; 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* TraceScreen_new(Process* process) {
TraceScreen* this = malloc(sizeof(TraceScreen)); TraceScreen* this = malloc(sizeof(TraceScreen));
this->process = process; Object_setClass(this, Class(TraceScreen));
FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents);
this->display = Panel_new(0, 1, COLS, LINES-2, false, Class(ListItem), fuBar);
this->tracing = true; 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) { void TraceScreen_delete(Object* cast) {
Panel_delete((Object*)this->display); TraceScreen* this = (TraceScreen*) cast;
free(this); 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]); attrset(CRT_colors[PANEL_HEADER_FOCUS]);
mvhline(0, 0, ' ', COLS); mvhline(0, 0, ' ', COLS);
mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm); mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm);
attrset(CRT_colors[DEFAULT_COLOR]); attrset(CRT_colors[DEFAULT_COLOR]);
IncSet_drawBar(inc); IncSet_drawBar(this->inc);
} }
static inline void addLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) { bool TraceScreen_forkTracer(TraceScreen* this) {
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 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) {
char buffer[1001]; char buffer[1001];
int fdpair[2]; int err = pipe(this->fdpair);
int err = pipe(fdpair); if (err == -1) return false;
if (err == -1) return; this->child = fork();
int child = fork(); if (this->child == -1) return false;
if (child == -1) return; if (this->child == 0) {
if (child == 0) {
seteuid(getuid()); seteuid(getuid());
dup2(fdpair[1], STDERR_FILENO); dup2(this->fdpair[1], STDERR_FILENO);
int ok = fcntl(fdpair[1], F_SETFL, O_NONBLOCK); int ok = fcntl(this->fdpair[1], F_SETFL, O_NONBLOCK);
if (ok != -1) { if (ok != -1) {
sprintf(buffer, "%d", this->process->pid); sprintf(buffer, "%d", this->super.process->pid);
execlp("strace", "strace", "-p", buffer, NULL); execlp("strace", "strace", "-p", buffer, NULL);
} }
const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH."; 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; (void) written;
exit(1); exit(1);
} }
fcntl(fdpair[0], F_SETFL, O_NONBLOCK); fcntl(this->fdpair[0], F_SETFL, O_NONBLOCK);
FILE* strace = fdopen(fdpair[0], "r"); this->strace = fdopen(this->fdpair[0], "r");
Panel* panel = this->display; this->fd_strace = fileno(this->strace);
int fd_strace = fileno(strace); return true;
CRT_disableDelay(); }
bool contLine = false;
bool follow = false;
bool looping = true;
FunctionBar* bar = panel->defaultBar; void TraceScreen_updateTrace(InfoScreen* super) {
IncSet* inc = IncSet_new(bar); TraceScreen* this = (TraceScreen*) super;
char buffer[1001];
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_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
// FD_SET(STDIN_FILENO, &fds); // FD_SET(STDIN_FILENO, &fds);
FD_SET(fd_strace, &fds); FD_SET(this->fd_strace, &fds);
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; tv.tv_usec = 500; tv.tv_sec = 0; tv.tv_usec = 500;
int ready = select(fd_strace+1, &fds, NULL, NULL, &tv); int ready = select(this->fd_strace+1, &fds, NULL, NULL, &tv);
int nread = 0; int nread = 0;
if (ready > 0 && FD_ISSET(fd_strace, &fds)) if (ready > 0 && FD_ISSET(this->fd_strace, &fds))
nread = fread(buffer, 1, 1000, strace); nread = fread(buffer, 1, 1000, this->strace);
if (nread && this->tracing) { if (nread && this->tracing) {
char* line = buffer; char* line = buffer;
buffer[nread] = '\0'; buffer[nread] = '\0';
for (int i = 0; i < nread; i++) { for (int i = 0; i < nread; i++) {
if (buffer[i] == '\n') { if (buffer[i] == '\n') {
buffer[i] = '\0'; buffer[i] = '\0';
if (contLine) { if (this->contLine) {
appendLine(line, lines, panel, incFilter); InfoScreen_appendLine(&this->super, line);
contLine = false; this->contLine = false;
} else { } else {
addLine(line, lines, panel, incFilter); InfoScreen_addLine(&this->super, line);
} }
line = buffer+i+1; line = buffer+i+1;
} }
} }
if (line < buffer+nread) { if (line < buffer+nread) {
addLine(line, lines, panel, incFilter); InfoScreen_addLine(&this->super, line);
buffer[nread] = '\0'; buffer[nread] = '\0';
contLine = true; this->contLine = true;
}
if (follow)
Panel_setSelected(panel, Panel_size(panel)-1);
} }
if (this->follow)
Panel_setSelected(this->super.display, Panel_size(this->super.display)-1);
} }
}
if (ch == KEY_MOUSE) { bool TraceScreen_onKey(InfoScreen* super, int ch) {
MEVENT mevent; TraceScreen* this = (TraceScreen*) super;
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;
}
switch(ch) { 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;
case 'f': case 'f':
case KEY_F(8): case KEY_F(8):
follow = !follow; this->follow = !(this->follow);
if (follow) if (this->follow)
Panel_setSelected(panel, Panel_size(panel)-1); Panel_setSelected(super->display, Panel_size(super->display)-1);
break; return true;
case 't': case 't':
case KEY_F(9): case KEY_F(9):
this->tracing = !this->tracing; this->tracing = !this->tracing;
FunctionBar_setLabel(bar, KEY_F(9), this->tracing?"Stop Tracing ":"Resume Tracing "); FunctionBar_setLabel(super->display->defaultBar, KEY_F(9), this->tracing?"Stop Tracing ":"Resume Tracing ");
TraceScreen_draw(this, inc); InfoScreen_draw(this);
break; return true;
case 'q':
case 27:
case KEY_F(10):
looping = false;
break;
case KEY_RESIZE:
Panel_resize(panel, COLS, LINES-2);
TraceScreen_draw(this, inc);
break;
default:
follow = false;
Panel_onKey(panel, ch);
} }
} this->follow = false;
return false;
IncSet_delete(inc);
Vector_delete(lines);
kill(child, SIGTERM);
waitpid(child, NULL, 0);
fclose(strace);
CRT_enableDelay();
} }

View File

@ -9,20 +9,32 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "Process.h" #include "InfoScreen.h"
#include "Panel.h"
typedef struct TraceScreen_ { typedef struct TraceScreen_ {
Process* process; InfoScreen super;
Panel* display;
bool tracing; bool tracing;
int fdpair[2];
int child;
FILE* strace;
int fd_strace;
bool contLine;
bool follow;
} TraceScreen; } TraceScreen;
extern InfoScreenClass TraceScreen_class;
TraceScreen* TraceScreen_new(Process* process); TraceScreen* TraceScreen_new(Process* process);
void TraceScreen_delete(TraceScreen* this); void TraceScreen_delete(Object* cast);
void TraceScreen_run(TraceScreen* this); void TraceScreen_draw(InfoScreen* this);
bool TraceScreen_forkTracer(TraceScreen* this);
void TraceScreen_updateTrace(InfoScreen* super);
bool TraceScreen_onKey(InfoScreen* super, int ch);
#endif #endif