mirror of
https://github.com/xzeldon/htop.git
synced 2025-07-15 13:34:35 +03:00
Compare commits
62 Commits
Author | SHA1 | Date | |
---|---|---|---|
ce6d60e7de | |||
5d92a9f20d | |||
b3500ac3b7 | |||
2ba8a81d47 | |||
f2f1c99ad9 | |||
1ffe5d79bd | |||
8502f4e64f | |||
a5db139a0a | |||
8a67d7f086 | |||
0b89c66f58 | |||
3bb731c645 | |||
fbaa0cd146 | |||
a076488809 | |||
6301d5c1da | |||
4979245aa5 | |||
0155980fd6 | |||
2af90b711f | |||
d55f394541 | |||
c7d93a8f30 | |||
2d2a2df6f2 | |||
de645ea16c | |||
6ae56f2578 | |||
bfcb8ca019 | |||
d800d7a3ce | |||
27db9297b7 | |||
330d4fe22f | |||
8e10cde800 | |||
ca2c01bd16 | |||
7043a93eba | |||
8fe04b7494 | |||
43d5c61884 | |||
e103ec0317 | |||
7ff654f2df | |||
7386c6fed0 | |||
ce9e7fd14f | |||
badeaf9e82 | |||
a3cced9fb6 | |||
24c5ca9ddf | |||
eb6f8d569d | |||
8c8149d146 | |||
a150a81669 | |||
90ea3ac3c9 | |||
293c16e22d | |||
f6aa5d29bb | |||
2c06566405 | |||
d609c04fe4 | |||
ca9d7cd708 | |||
debeac49cd | |||
a0b899f29d | |||
8b83a9f055 | |||
495f2292dc | |||
1cc3f8074f | |||
aa08279964 | |||
5359eae28b | |||
f1463fdd64 | |||
3edb6e1ea3 | |||
71ddc6a6a1 | |||
b9336af76f | |||
f46ddd3230 | |||
94d7f0b585 | |||
86d2931255 | |||
0672be7db1 |
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@ -2,6 +2,11 @@ name: CI
|
|||||||
|
|
||||||
on: [ push, pull_request ]
|
on: [ push, pull_request ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Enable format attributes in ncurses headers
|
||||||
|
# Enable fortified memory/string handling
|
||||||
|
CPPFLAGS: -DGCC_PRINTF -DGCC_SCANF -D_FORTIFY_SOURCE=2
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-ubuntu-latest-minimal-gcc:
|
build-ubuntu-latest-minimal-gcc:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -47,6 +52,10 @@ jobs:
|
|||||||
|
|
||||||
build-ubuntu-latest-full-featured-gcc:
|
build-ubuntu-latest-full-featured-gcc:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# Enable LTO, might trigger additional warnings on advanced inlining
|
||||||
|
env:
|
||||||
|
CFLAGS: -O3 -g -flto
|
||||||
|
LDFLAGS: -O3 -g -flto
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
|
52
Action.c
52
Action.c
@ -104,7 +104,7 @@ static bool changePriority(MainPanel* panel, int delta) {
|
|||||||
return anyTagged;
|
return anyTagged;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addUserToVector(hkey_t key, void* userCast, void* panelCast) {
|
static void addUserToVector(ht_key_t key, void* userCast, void* panelCast) {
|
||||||
const char* user = userCast;
|
const char* user = userCast;
|
||||||
Panel* panel = panelCast;
|
Panel* panel = panelCast;
|
||||||
Panel_add(panel, (Object*) ListItem_new(user, key));
|
Panel_add(panel, (Object*) ListItem_new(user, key));
|
||||||
@ -162,9 +162,11 @@ Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) {
|
|||||||
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING;
|
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Htop_Reaction sortBy(State* st) {
|
// ----------------------------------------
|
||||||
|
|
||||||
|
static Htop_Reaction actionSetSortColumn(State* st) {
|
||||||
Htop_Reaction reaction = HTOP_OK;
|
Htop_Reaction reaction = HTOP_OK;
|
||||||
Panel* sortPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem), FunctionBar_newEnterEsc("Sort ", "Cancel "));
|
Panel* sortPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Sort ", "Cancel "));
|
||||||
Panel_setHeader(sortPanel, "Sort by");
|
Panel_setHeader(sortPanel, "Sort by");
|
||||||
ProcessField* fields = st->settings->fields;
|
ProcessField* fields = st->settings->fields;
|
||||||
for (int i = 0; fields[i]; i++) {
|
for (int i = 0; fields[i]; i++) {
|
||||||
@ -187,12 +189,8 @@ static Htop_Reaction sortBy(State* st) {
|
|||||||
return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------
|
static Htop_Reaction actionSortByPID(State* st) {
|
||||||
|
return Action_setSortKey(st->settings, PID);
|
||||||
static Htop_Reaction actionResize(State* st) {
|
|
||||||
clear();
|
|
||||||
Panel_resize(st->panel, COLS, LINES - (st->panel->y) - 1);
|
|
||||||
return HTOP_REDRAW_BAR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Htop_Reaction actionSortByMemory(State* st) {
|
static Htop_Reaction actionSortByMemory(State* st) {
|
||||||
@ -250,16 +248,6 @@ static Htop_Reaction actionIncSearch(State* st) {
|
|||||||
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Htop_Reaction actionIncNext(State* st) {
|
|
||||||
IncSet_next(((MainPanel*)st->panel)->inc, INC_SEARCH, st->panel, (IncMode_GetPanelValue) MainPanel_getValue);
|
|
||||||
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Htop_Reaction actionIncPrev(State* st) {
|
|
||||||
IncSet_prev(((MainPanel*)st->panel)->inc, INC_SEARCH, st->panel, (IncMode_GetPanelValue) MainPanel_getValue);
|
|
||||||
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Htop_Reaction actionHigherPriority(State* st) {
|
static Htop_Reaction actionHigherPriority(State* st) {
|
||||||
bool changed = changePriority((MainPanel*)st->panel, -1);
|
bool changed = changePriority((MainPanel*)st->panel, -1);
|
||||||
return changed ? HTOP_REFRESH : HTOP_OK;
|
return changed ? HTOP_REFRESH : HTOP_OK;
|
||||||
@ -277,10 +265,6 @@ static Htop_Reaction actionInvertSortOrder(State* st) {
|
|||||||
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
|
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Htop_Reaction actionSetSortColumn(State* st) {
|
|
||||||
return sortBy(st);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Htop_Reaction actionExpandOrCollapse(State* st) {
|
static Htop_Reaction actionExpandOrCollapse(State* st) {
|
||||||
bool changed = expandCollapse(st->panel);
|
bool changed = expandCollapse(st->panel);
|
||||||
return changed ? HTOP_RECALCULATE : HTOP_OK;
|
return changed ? HTOP_RECALCULATE : HTOP_OK;
|
||||||
@ -341,7 +325,7 @@ static Htop_Reaction actionKill(State* st) {
|
|||||||
if (sgn) {
|
if (sgn) {
|
||||||
if (sgn->key != 0) {
|
if (sgn->key != 0) {
|
||||||
Panel_setHeader(st->panel, "Sending...");
|
Panel_setHeader(st->panel, "Sending...");
|
||||||
Panel_draw(st->panel, false, true, true);
|
Panel_draw(st->panel, false, true, true, State_hideFunctionBar(st));
|
||||||
refresh();
|
refresh();
|
||||||
MainPanel_foreachProcess((MainPanel*)st->panel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL);
|
MainPanel_foreachProcess((MainPanel*)st->panel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL);
|
||||||
napms(500);
|
napms(500);
|
||||||
@ -352,7 +336,7 @@ static Htop_Reaction actionKill(State* st) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Htop_Reaction actionFilterByUser(State* st) {
|
static Htop_Reaction actionFilterByUser(State* st) {
|
||||||
Panel* usersPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem), FunctionBar_newEnterEsc("Show ", "Cancel "));
|
Panel* usersPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Show ", "Cancel "));
|
||||||
Panel_setHeader(usersPanel, "Show processes of:");
|
Panel_setHeader(usersPanel, "Show processes of:");
|
||||||
UsersTable_foreach(st->ut, addUserToVector, usersPanel);
|
UsersTable_foreach(st->ut, addUserToVector, usersPanel);
|
||||||
Vector_insertionSort(usersPanel->items);
|
Vector_insertionSort(usersPanel->items);
|
||||||
@ -462,7 +446,7 @@ static const struct {
|
|||||||
{ .key = " K: ", .info = "hide/show kernel threads" },
|
{ .key = " K: ", .info = "hide/show kernel threads" },
|
||||||
{ .key = " F: ", .info = "cursor follows process" },
|
{ .key = " F: ", .info = "cursor follows process" },
|
||||||
{ .key = " + -: ", .info = "expand/collapse tree" },
|
{ .key = " + -: ", .info = "expand/collapse tree" },
|
||||||
{ .key = " P M T: ", .info = "sort by CPU%, MEM% or TIME" },
|
{ .key = "N P M T: ", .info = "sort by PID, CPU%, MEM% or TIME" },
|
||||||
{ .key = " I: ", .info = "invert sort order" },
|
{ .key = " I: ", .info = "invert sort order" },
|
||||||
{ .key = " F6 > .: ", .info = "select sort column" },
|
{ .key = " F6 > .: ", .info = "select sort column" },
|
||||||
{ .key = NULL, .info = NULL }
|
{ .key = NULL, .info = NULL }
|
||||||
@ -563,24 +547,24 @@ static Htop_Reaction actionHelp(State* st) {
|
|||||||
int item;
|
int item;
|
||||||
for (item = 0; helpLeft[item].key; item++) {
|
for (item = 0; helpLeft[item].key; item++) {
|
||||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||||
mvaddstr(line + item, 9, helpLeft[item].info);
|
mvaddstr(line + item, 10, helpLeft[item].info);
|
||||||
attrset(CRT_colors[HELP_BOLD]);
|
attrset(CRT_colors[HELP_BOLD]);
|
||||||
mvaddstr(line + item, 0, helpLeft[item].key);
|
mvaddstr(line + item, 1, helpLeft[item].key);
|
||||||
if (String_eq(helpLeft[item].key, " H: ")) {
|
if (String_eq(helpLeft[item].key, " H: ")) {
|
||||||
attrset(CRT_colors[PROCESS_THREAD]);
|
attrset(CRT_colors[PROCESS_THREAD]);
|
||||||
mvaddstr(line + item, 32, "threads");
|
mvaddstr(line + item, 33, "threads");
|
||||||
} else if (String_eq(helpLeft[item].key, " K: ")) {
|
} else if (String_eq(helpLeft[item].key, " K: ")) {
|
||||||
attrset(CRT_colors[PROCESS_THREAD]);
|
attrset(CRT_colors[PROCESS_THREAD]);
|
||||||
mvaddstr(line + item, 26, "threads");
|
mvaddstr(line + item, 27, "threads");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int leftHelpItems = item;
|
int leftHelpItems = item;
|
||||||
|
|
||||||
for (item = 0; helpRight[item].key; item++) {
|
for (item = 0; helpRight[item].key; item++) {
|
||||||
attrset(CRT_colors[HELP_BOLD]);
|
attrset(CRT_colors[HELP_BOLD]);
|
||||||
mvaddstr(line + item, 40, helpRight[item].key);
|
mvaddstr(line + item, 41, helpRight[item].key);
|
||||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||||
mvaddstr(line + item, 49, helpRight[item].info);
|
mvaddstr(line + item, 50, helpRight[item].info);
|
||||||
}
|
}
|
||||||
line += MAXIMUM(leftHelpItems, item);
|
line += MAXIMUM(leftHelpItems, item);
|
||||||
line++;
|
line++;
|
||||||
@ -655,7 +639,7 @@ void Action_setBindings(Htop_Action* keys) {
|
|||||||
keys['I'] = actionInvertSortOrder;
|
keys['I'] = actionInvertSortOrder;
|
||||||
keys['K'] = actionToggleKernelThreads;
|
keys['K'] = actionToggleKernelThreads;
|
||||||
keys['M'] = actionSortByMemory;
|
keys['M'] = actionSortByMemory;
|
||||||
keys['N'] = actionIncPrev;
|
keys['N'] = actionSortByPID;
|
||||||
keys['P'] = actionSortByCPU;
|
keys['P'] = actionSortByCPU;
|
||||||
keys['S'] = actionSetup;
|
keys['S'] = actionSetup;
|
||||||
keys['T'] = actionSortByTime;
|
keys['T'] = actionSortByTime;
|
||||||
@ -673,7 +657,6 @@ void Action_setBindings(Htop_Action* keys) {
|
|||||||
keys['k'] = actionKill;
|
keys['k'] = actionKill;
|
||||||
keys['l'] = actionLsof;
|
keys['l'] = actionLsof;
|
||||||
keys['m'] = actionToggleMergedCommand;
|
keys['m'] = actionToggleMergedCommand;
|
||||||
keys['n'] = actionIncNext;
|
|
||||||
keys['p'] = actionToggleProgramPath;
|
keys['p'] = actionToggleProgramPath;
|
||||||
keys['q'] = actionQuit;
|
keys['q'] = actionQuit;
|
||||||
keys['s'] = actionStrace;
|
keys['s'] = actionStrace;
|
||||||
@ -693,5 +676,4 @@ void Action_setBindings(Htop_Action* keys) {
|
|||||||
keys[KEY_F(10)] = actionQuit;
|
keys[KEY_F(10)] = actionQuit;
|
||||||
keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
|
keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
|
||||||
keys[KEY_RECLICK] = actionExpandOrCollapse;
|
keys[KEY_RECLICK] = actionExpandOrCollapse;
|
||||||
keys[KEY_RESIZE] = actionResize;
|
|
||||||
}
|
}
|
||||||
|
4
Action.h
4
Action.h
@ -41,6 +41,10 @@ typedef struct State_ {
|
|||||||
bool hideProcessSelection;
|
bool hideProcessSelection;
|
||||||
} State;
|
} State;
|
||||||
|
|
||||||
|
static inline bool State_hideFunctionBar(const State* st) {
|
||||||
|
return st->settings->hideFunctionBar == 2 || (st->settings->hideFunctionBar == 1 && st->hideProcessSelection);
|
||||||
|
}
|
||||||
|
|
||||||
typedef Htop_Reaction (*Htop_Action)(State* st);
|
typedef Htop_Reaction (*Htop_Action)(State* st);
|
||||||
|
|
||||||
Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess);
|
Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess);
|
||||||
|
82
CRT.c
82
CRT.c
@ -41,6 +41,9 @@ in the source distribution for its full text.
|
|||||||
#define ColorPairGrayBlack ColorPair(Magenta,Magenta)
|
#define ColorPairGrayBlack ColorPair(Magenta,Magenta)
|
||||||
#define ColorIndexGrayBlack ColorIndex(Magenta,Magenta)
|
#define ColorIndexGrayBlack ColorIndex(Magenta,Magenta)
|
||||||
|
|
||||||
|
#define ColorPairWhiteDefault ColorPair(Red, Red)
|
||||||
|
#define ColorIndexWhiteDefault ColorIndex(Red, Red)
|
||||||
|
|
||||||
static const char* const CRT_treeStrAscii[LAST_TREE_STR] = {
|
static const char* const CRT_treeStrAscii[LAST_TREE_STR] = {
|
||||||
[TREE_STR_VERT] = "|",
|
[TREE_STR_VERT] = "|",
|
||||||
[TREE_STR_RTEE] = "`",
|
[TREE_STR_RTEE] = "`",
|
||||||
@ -48,6 +51,8 @@ static const char* const CRT_treeStrAscii[LAST_TREE_STR] = {
|
|||||||
[TREE_STR_TEND] = ",",
|
[TREE_STR_TEND] = ",",
|
||||||
[TREE_STR_OPEN] = "+",
|
[TREE_STR_OPEN] = "+",
|
||||||
[TREE_STR_SHUT] = "-",
|
[TREE_STR_SHUT] = "-",
|
||||||
|
[TREE_STR_ASC] = "+",
|
||||||
|
[TREE_STR_DESC] = "-",
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_LIBNCURSESW
|
#ifdef HAVE_LIBNCURSESW
|
||||||
@ -61,6 +66,8 @@ static const char* const CRT_treeStrUtf8[LAST_TREE_STR] = {
|
|||||||
// WITH VERTICAL STROKE' (U+1FBAF, "\xf0\x9f\xae\xaf") when
|
// WITH VERTICAL STROKE' (U+1FBAF, "\xf0\x9f\xae\xaf") when
|
||||||
// Unicode 13 is common
|
// Unicode 13 is common
|
||||||
[TREE_STR_SHUT] = "\xe2\x94\x80", // ─
|
[TREE_STR_SHUT] = "\xe2\x94\x80", // ─
|
||||||
|
[TREE_STR_ASC] = "\xe2\x96\xb3", // △
|
||||||
|
[TREE_STR_DESC] = "\xe2\x96\xbd", // ▽
|
||||||
};
|
};
|
||||||
|
|
||||||
bool CRT_utf8 = false;
|
bool CRT_utf8 = false;
|
||||||
@ -114,6 +121,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
|
[METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
|
||||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black),
|
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black),
|
||||||
[METER_VALUE_OK] = ColorPair(Green, Black),
|
[METER_VALUE_OK] = ColorPair(Green, Black),
|
||||||
|
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
|
||||||
[LED_COLOR] = ColorPair(Green, Black),
|
[LED_COLOR] = ColorPair(Green, Black),
|
||||||
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black),
|
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black),
|
||||||
[PROCESS] = A_NORMAL,
|
[PROCESS] = A_NORMAL,
|
||||||
@ -198,6 +206,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[METER_VALUE_IOWRITE] = A_NORMAL,
|
[METER_VALUE_IOWRITE] = A_NORMAL,
|
||||||
[METER_VALUE_NOTICE] = A_BOLD,
|
[METER_VALUE_NOTICE] = A_BOLD,
|
||||||
[METER_VALUE_OK] = A_NORMAL,
|
[METER_VALUE_OK] = A_NORMAL,
|
||||||
|
[METER_VALUE_WARN] = A_BOLD,
|
||||||
[LED_COLOR] = A_NORMAL,
|
[LED_COLOR] = A_NORMAL,
|
||||||
[TASKS_RUNNING] = A_BOLD,
|
[TASKS_RUNNING] = A_BOLD,
|
||||||
[PROCESS] = A_NORMAL,
|
[PROCESS] = A_NORMAL,
|
||||||
@ -282,6 +291,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[METER_VALUE_IOWRITE] = ColorPair(Yellow, White),
|
[METER_VALUE_IOWRITE] = ColorPair(Yellow, White),
|
||||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, White),
|
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, White),
|
||||||
[METER_VALUE_OK] = ColorPair(Green, White),
|
[METER_VALUE_OK] = ColorPair(Green, White),
|
||||||
|
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, White),
|
||||||
[LED_COLOR] = ColorPair(Green, White),
|
[LED_COLOR] = ColorPair(Green, White),
|
||||||
[TASKS_RUNNING] = ColorPair(Green, White),
|
[TASKS_RUNNING] = ColorPair(Green, White),
|
||||||
[PROCESS] = ColorPair(Black, White),
|
[PROCESS] = ColorPair(Black, White),
|
||||||
@ -344,10 +354,10 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[ZRAM] = ColorPair(Yellow, White)
|
[ZRAM] = ColorPair(Yellow, White)
|
||||||
},
|
},
|
||||||
[COLORSCHEME_LIGHTTERMINAL] = {
|
[COLORSCHEME_LIGHTTERMINAL] = {
|
||||||
[RESET_COLOR] = ColorPair(Blue, Black),
|
[RESET_COLOR] = ColorPair(Black, Black),
|
||||||
[DEFAULT_COLOR] = ColorPair(Blue, Black),
|
[DEFAULT_COLOR] = ColorPair(Black, Black),
|
||||||
[FUNCTION_BAR] = ColorPair(Black, Cyan),
|
[FUNCTION_BAR] = ColorPair(Black, Cyan),
|
||||||
[FUNCTION_KEY] = ColorPair(Blue, Black),
|
[FUNCTION_KEY] = ColorPair(Black, Black),
|
||||||
[PANEL_HEADER_FOCUS] = ColorPair(Black, Green),
|
[PANEL_HEADER_FOCUS] = ColorPair(Black, Green),
|
||||||
[PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green),
|
[PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green),
|
||||||
[PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan),
|
[PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan),
|
||||||
@ -360,17 +370,18 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[BATTERY] = ColorPair(Yellow, Black),
|
[BATTERY] = ColorPair(Yellow, Black),
|
||||||
[LARGE_NUMBER] = ColorPair(Red, Black),
|
[LARGE_NUMBER] = ColorPair(Red, Black),
|
||||||
[METER_TEXT] = ColorPair(Blue, Black),
|
[METER_TEXT] = ColorPair(Blue, Black),
|
||||||
[METER_VALUE] = ColorPair(Blue, Black),
|
[METER_VALUE] = ColorPair(Black, Black),
|
||||||
[METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
|
[METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
|
||||||
[METER_VALUE_IOREAD] = ColorPair(Green, Black),
|
[METER_VALUE_IOREAD] = ColorPair(Green, Black),
|
||||||
[METER_VALUE_IOWRITE] = ColorPair(Yellow, Black),
|
[METER_VALUE_IOWRITE] = ColorPair(Yellow, Black),
|
||||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, Black),
|
[METER_VALUE_NOTICE] = A_BOLD | ColorPairWhiteDefault,
|
||||||
[METER_VALUE_OK] = ColorPair(Green, Black),
|
[METER_VALUE_OK] = ColorPair(Green, Black),
|
||||||
|
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
|
||||||
[LED_COLOR] = ColorPair(Green, Black),
|
[LED_COLOR] = ColorPair(Green, Black),
|
||||||
[TASKS_RUNNING] = ColorPair(Green, Black),
|
[TASKS_RUNNING] = ColorPair(Green, Black),
|
||||||
[PROCESS] = ColorPair(Blue, Black),
|
[PROCESS] = ColorPair(Black, Black),
|
||||||
[PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack,
|
[PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack,
|
||||||
[PROCESS_TAG] = ColorPair(Yellow, Blue),
|
[PROCESS_TAG] = ColorPair(White, Blue),
|
||||||
[PROCESS_MEGABYTES] = ColorPair(Blue, Black),
|
[PROCESS_MEGABYTES] = ColorPair(Blue, Black),
|
||||||
[PROCESS_GIGABYTES] = ColorPair(Green, Black),
|
[PROCESS_GIGABYTES] = ColorPair(Green, Black),
|
||||||
[PROCESS_BASENAME] = ColorPair(Green, Black),
|
[PROCESS_BASENAME] = ColorPair(Green, Black),
|
||||||
@ -394,34 +405,34 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[MEMORY_BUFFERS] = ColorPair(Cyan, Black),
|
[MEMORY_BUFFERS] = ColorPair(Cyan, Black),
|
||||||
[MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, Black),
|
[MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, Black),
|
||||||
[MEMORY_CACHE] = ColorPair(Yellow, Black),
|
[MEMORY_CACHE] = ColorPair(Yellow, Black),
|
||||||
[LOAD_AVERAGE_FIFTEEN] = ColorPair(Blue, Black),
|
[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black, Black),
|
||||||
[LOAD_AVERAGE_FIVE] = ColorPair(Blue, Black),
|
[LOAD_AVERAGE_FIVE] = ColorPair(Black, Black),
|
||||||
[LOAD_AVERAGE_ONE] = ColorPair(Yellow, Black),
|
[LOAD_AVERAGE_ONE] = ColorPair(Black, Black),
|
||||||
[LOAD] = ColorPair(Yellow, Black),
|
[LOAD] = ColorPairWhiteDefault,
|
||||||
[HELP_BOLD] = ColorPair(Blue, Black),
|
[HELP_BOLD] = ColorPair(Blue, Black),
|
||||||
[CLOCK] = ColorPair(Yellow, Black),
|
[CLOCK] = ColorPairWhiteDefault,
|
||||||
[DATE] = ColorPair(White, Black),
|
[DATE] = ColorPairWhiteDefault,
|
||||||
[DATETIME] = ColorPair(White, Black),
|
[DATETIME] = ColorPairWhiteDefault,
|
||||||
[CHECK_BOX] = ColorPair(Blue, Black),
|
[CHECK_BOX] = ColorPair(Blue, Black),
|
||||||
[CHECK_MARK] = ColorPair(Blue, Black),
|
[CHECK_MARK] = ColorPair(Black, Black),
|
||||||
[CHECK_TEXT] = ColorPair(Blue, Black),
|
[CHECK_TEXT] = ColorPair(Black, Black),
|
||||||
[HOSTNAME] = ColorPair(Yellow, Black),
|
[HOSTNAME] = ColorPairWhiteDefault,
|
||||||
[CPU_NICE] = ColorPair(Cyan, Black),
|
[CPU_NICE] = ColorPair(Cyan, Black),
|
||||||
[CPU_NICE_TEXT] = ColorPair(Cyan, Black),
|
[CPU_NICE_TEXT] = ColorPair(Cyan, Black),
|
||||||
[CPU_NORMAL] = ColorPair(Green, Black),
|
[CPU_NORMAL] = ColorPair(Green, Black),
|
||||||
[CPU_SYSTEM] = ColorPair(Red, Black),
|
[CPU_SYSTEM] = ColorPair(Red, Black),
|
||||||
[CPU_IOWAIT] = A_BOLD | ColorPair(Blue, Black),
|
[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black),
|
||||||
[CPU_IRQ] = A_BOLD | ColorPair(Blue, Black),
|
[CPU_IRQ] = A_BOLD | ColorPair(Blue, Black),
|
||||||
[CPU_SOFTIRQ] = ColorPair(Blue, Black),
|
[CPU_SOFTIRQ] = ColorPair(Blue, Black),
|
||||||
[CPU_STEAL] = ColorPair(Blue, Black),
|
[CPU_STEAL] = ColorPair(Black, Black),
|
||||||
[CPU_GUEST] = ColorPair(Blue, Black),
|
[CPU_GUEST] = ColorPair(Black, Black),
|
||||||
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Blue, Black),
|
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, Black),
|
||||||
[PRESSURE_STALL_SIXTY] = ColorPair(Blue, Black),
|
[PRESSURE_STALL_SIXTY] = ColorPair(Black, Black),
|
||||||
[PRESSURE_STALL_TEN] = ColorPair(Blue, Black),
|
[PRESSURE_STALL_TEN] = ColorPair(Black, Black),
|
||||||
[ZFS_MFU] = ColorPair(Cyan, Black),
|
[ZFS_MFU] = ColorPair(Cyan, Black),
|
||||||
[ZFS_MRU] = ColorPair(Yellow, Black),
|
[ZFS_MRU] = ColorPair(Yellow, Black),
|
||||||
[ZFS_ANON] = A_BOLD | ColorPair(Magenta, Black),
|
[ZFS_ANON] = A_BOLD | ColorPair(Magenta, Black),
|
||||||
[ZFS_HEADER] = ColorPair(Blue, Black),
|
[ZFS_HEADER] = ColorPair(Black, Black),
|
||||||
[ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Black),
|
[ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Black),
|
||||||
[ZFS_COMPRESSED] = ColorPair(Cyan, Black),
|
[ZFS_COMPRESSED] = ColorPair(Cyan, Black),
|
||||||
[ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Black),
|
[ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Black),
|
||||||
@ -450,6 +461,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[METER_VALUE_IOWRITE] = ColorPair(Black, Blue),
|
[METER_VALUE_IOWRITE] = ColorPair(Black, Blue),
|
||||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Blue),
|
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Blue),
|
||||||
[METER_VALUE_OK] = ColorPair(Green, Blue),
|
[METER_VALUE_OK] = ColorPair(Green, Blue),
|
||||||
|
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
|
||||||
[LED_COLOR] = ColorPair(Green, Blue),
|
[LED_COLOR] = ColorPair(Green, Blue),
|
||||||
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Blue),
|
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Blue),
|
||||||
[PROCESS] = ColorPair(White, Blue),
|
[PROCESS] = ColorPair(White, Blue),
|
||||||
@ -532,8 +544,9 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
|
[METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
|
||||||
[METER_VALUE_IOREAD] = ColorPair(Green, Black),
|
[METER_VALUE_IOREAD] = ColorPair(Green, Black),
|
||||||
[METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
|
[METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
|
||||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, Black),
|
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black),
|
||||||
[METER_VALUE_OK] = ColorPair(Green, Black),
|
[METER_VALUE_OK] = ColorPair(Green, Black),
|
||||||
|
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
|
||||||
[LED_COLOR] = ColorPair(Green, Black),
|
[LED_COLOR] = ColorPair(Green, Black),
|
||||||
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black),
|
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black),
|
||||||
[PROCESS] = ColorPair(Cyan, Black),
|
[PROCESS] = ColorPair(Cyan, Black),
|
||||||
@ -689,6 +702,7 @@ void CRT_init(const int* delay, int colorScheme, bool allowUnicode) {
|
|||||||
define_key("\033[12~", KEY_F(2));
|
define_key("\033[12~", KEY_F(2));
|
||||||
define_key("\033[13~", KEY_F(3));
|
define_key("\033[13~", KEY_F(3));
|
||||||
define_key("\033[14~", KEY_F(4));
|
define_key("\033[14~", KEY_F(4));
|
||||||
|
define_key("\033[14;2~", KEY_F(15));
|
||||||
define_key("\033[17;2~", KEY_F(18));
|
define_key("\033[17;2~", KEY_F(18));
|
||||||
char sequence[3] = "\033a";
|
char sequence[3] = "\033a";
|
||||||
for (char c = 'a'; c <= 'z'; c++) {
|
for (char c = 'a'; c <= 'z'; c++) {
|
||||||
@ -778,7 +792,7 @@ void CRT_setColors(int colorScheme) {
|
|||||||
|
|
||||||
for (short int i = 0; i < 8; i++) {
|
for (short int i = 0; i < 8; i++) {
|
||||||
for (short int j = 0; j < 8; j++) {
|
for (short int j = 0; j < 8; j++) {
|
||||||
if (ColorIndex(i, j) != ColorIndexGrayBlack) {
|
if (ColorIndex(i, j) != ColorIndexGrayBlack && ColorIndex(i, j) != ColorIndexWhiteDefault) {
|
||||||
short int bg = (colorScheme != COLORSCHEME_BLACKNIGHT)
|
short int bg = (colorScheme != COLORSCHEME_BLACKNIGHT)
|
||||||
? (j == 0 ? -1 : j)
|
? (j == 0 ? -1 : j)
|
||||||
: j;
|
: j;
|
||||||
@ -791,6 +805,8 @@ void CRT_setColors(int colorScheme) {
|
|||||||
short int grayBlackBg = (colorScheme != COLORSCHEME_BLACKNIGHT) ? -1 : 0;
|
short int grayBlackBg = (colorScheme != COLORSCHEME_BLACKNIGHT) ? -1 : 0;
|
||||||
init_pair(ColorIndexGrayBlack, grayBlackFg, grayBlackBg);
|
init_pair(ColorIndexGrayBlack, grayBlackFg, grayBlackBg);
|
||||||
|
|
||||||
|
init_pair(ColorIndexWhiteDefault, White, -1);
|
||||||
|
|
||||||
CRT_colors = CRT_colorSchemes[colorScheme];
|
CRT_colors = CRT_colorSchemes[colorScheme];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,9 +823,13 @@ void CRT_handleSIGSEGV(int signal) {
|
|||||||
"- Your OS and kernel version (uname -a)\n"
|
"- Your OS and kernel version (uname -a)\n"
|
||||||
"- Your distribution and release (lsb_release -a)\n"
|
"- Your distribution and release (lsb_release -a)\n"
|
||||||
"- Likely steps to reproduce (How did it happened?)\n"
|
"- Likely steps to reproduce (How did it happened?)\n"
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef HAVE_EXECINFO_H
|
#ifdef HAVE_EXECINFO_H
|
||||||
"- Backtrace of the issue (see below)\n"
|
fprintf(stderr, "- Backtrace of the issue (see below)\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
"\n"
|
"\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -844,11 +864,15 @@ void CRT_handleSIGSEGV(int signal) {
|
|||||||
"you should provide a disassembly of your binary.\n"
|
"you should provide a disassembly of your binary.\n"
|
||||||
"This can usually be done by running the following command:\n"
|
"This can usually be done by running the following command:\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef HTOP_DARWIN
|
#ifdef HTOP_DARWIN
|
||||||
" otool -tvV `which htop` > ~/htop.otool\n"
|
fprintf(stderr, " otool -tvV `which htop` > ~/htop.otool\n");
|
||||||
#else
|
#else
|
||||||
" objdump -d -S -w `which htop` > ~/htop.objdump\n"
|
fprintf(stderr, " objdump -d -S -w `which htop` > ~/htop.objdump\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
"\n"
|
"\n"
|
||||||
"Please include the generated file in your report.\n"
|
"Please include the generated file in your report.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
3
CRT.h
3
CRT.h
@ -22,6 +22,8 @@ typedef enum TreeStr_ {
|
|||||||
TREE_STR_TEND,
|
TREE_STR_TEND,
|
||||||
TREE_STR_OPEN,
|
TREE_STR_OPEN,
|
||||||
TREE_STR_SHUT,
|
TREE_STR_SHUT,
|
||||||
|
TREE_STR_ASC,
|
||||||
|
TREE_STR_DESC,
|
||||||
LAST_TREE_STR
|
LAST_TREE_STR
|
||||||
} TreeStr;
|
} TreeStr;
|
||||||
|
|
||||||
@ -57,6 +59,7 @@ typedef enum ColorElements_ {
|
|||||||
METER_VALUE_IOWRITE,
|
METER_VALUE_IOWRITE,
|
||||||
METER_VALUE_NOTICE,
|
METER_VALUE_NOTICE,
|
||||||
METER_VALUE_OK,
|
METER_VALUE_OK,
|
||||||
|
METER_VALUE_WARN,
|
||||||
LED_COLOR,
|
LED_COLOR,
|
||||||
UPTIME,
|
UPTIME,
|
||||||
BATTERY,
|
BATTERY,
|
||||||
|
33
ChangeLog
33
ChangeLog
@ -1,15 +1,40 @@
|
|||||||
|
What's new in version 3.0.5
|
||||||
|
|
||||||
|
* BUGFIX / SECURITY: InfoScreen: fix uncontrolled format string
|
||||||
|
* BUGFIX: Improve white text in the Light Terminal colour scheme
|
||||||
|
(both of the above thanks to V)
|
||||||
|
* Enable the function bar on the main screen to be hidden (see Setup -> Display options)
|
||||||
|
* BUGFIX: Reduce layout issues esp. around printing wide characters (not complete yet)
|
||||||
|
* BUGFIX: Make the follow function exit cleanly after followed process died
|
||||||
|
* Solaris: make Process callbacks static
|
||||||
|
* Update help and man page for improved -t / -s options
|
||||||
|
* Drop usage of formatted error messages from <err.h>
|
||||||
|
* Show arrow indicating order of sorted process column
|
||||||
|
* Lots of plumbing around the internal Hashtable, hardening and code cleanups
|
||||||
|
* LibSensors: add support for Ryzen CPUs (vor 5 Tagen)
|
||||||
|
(thanks to Matej Dian)
|
||||||
|
* BUGFIX: Fix CPU percentage on M1 silicon Macs
|
||||||
|
(thanks to Luke Groeninger)
|
||||||
|
* LoadMeter: dynamically adjust color and total of bar
|
||||||
|
* Find libsensors.so.4 for Fedora and friends
|
||||||
|
* Add support to display CPU frequencies on Solarish platforms
|
||||||
|
(thanks to Dominik Hassler)
|
||||||
|
* Enable going back to previous search matches (Shift-F3)
|
||||||
|
* Added keybind 'N' for sorting by PID (drops 'n'/'N' as not used before much)
|
||||||
|
(thanks to Jake Mannens)
|
||||||
|
|
||||||
What's new in version 3.0.4
|
What's new in version 3.0.4
|
||||||
|
|
||||||
* Separate tree and list sort orders
|
* Separate tree and list sort orders
|
||||||
* Invert Process_compare so that superclass matches run first
|
* Invert Process_compare so that superclass matches run first
|
||||||
(thanks to Hisham Muhammad)
|
(thanks to Hisham Muhammad)
|
||||||
* Unhardcode Mac OS tick-to-milliseconds conversion
|
* Unhardcode Mac OS tick-to-milliseconds conversion
|
||||||
(thanks to Alexander Momchilov)
|
(thanks to Alexander Momchilov)
|
||||||
* Check if clock_gettime needs linking of librt
|
* Check if clock_gettime needs linking of librt
|
||||||
* Define O_PATH if not already defined
|
* Define O_PATH if not already defined
|
||||||
(thanks to Chris Burr)
|
(thanks to Chris Burr)
|
||||||
* Add column on Mac for processes running under translation
|
* Add column on Mac for processes running under translation
|
||||||
(thanks to Dániel Bakai)
|
(thanks to Dániel Bakai)
|
||||||
* Configure check for additional linker flags for keypad(3)
|
* Configure check for additional linker flags for keypad(3)
|
||||||
* PSI Meter: constant width and only print ten-duration as bar
|
* PSI Meter: constant width and only print ten-duration as bar
|
||||||
* Sort in paused mode after inverting sort order
|
* Sort in paused mode after inverting sort order
|
||||||
|
@ -60,7 +60,7 @@ const InfoScreenClass CommandScreen_class = {
|
|||||||
|
|
||||||
CommandScreen* CommandScreen_new(Process* process) {
|
CommandScreen* CommandScreen_new(Process* process) {
|
||||||
CommandScreen* this = AllocThis(CommandScreen);
|
CommandScreen* this = AllocThis(CommandScreen);
|
||||||
return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 3, " ");
|
return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandScreen_delete(Object* this) {
|
void CommandScreen_delete(Object* this) {
|
||||||
|
@ -124,6 +124,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
|
|||||||
Panel_add(super, (Object*) NumberItem_newByRef("Update interval (in seconds)", &(settings->delay), -1, 1, 255));
|
Panel_add(super, (Object*) NumberItem_newByRef("Update interval (in seconds)", &(settings->delay), -1, 1, 255));
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef("Highlight new and old processes", &(settings->highlightChanges)));
|
Panel_add(super, (Object*) CheckItem_newByRef("Highlight new and old processes", &(settings->highlightChanges)));
|
||||||
Panel_add(super, (Object*) NumberItem_newByRef("- Highlight time (in seconds)", &(settings->highlightDelaySecs), 0, 1, 24*60*60));
|
Panel_add(super, (Object*) NumberItem_newByRef("- Highlight time (in seconds)", &(settings->highlightDelaySecs), 0, 1, 24*60*60));
|
||||||
|
Panel_add(super, (Object*) NumberItem_newByRef("Hide main function bar (0 - off, 1 - on ESC until next input, 2 - permanently)", &(settings->hideFunctionBar), 0, 0, 2));
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef("Show topology when selecting affinity by default", &(settings->topologyAffinity)));
|
Panel_add(super, (Object*) CheckItem_newByRef("Show topology when selecting affinity by default", &(settings->topologyAffinity)));
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
EnvScreen* EnvScreen_new(Process* process) {
|
EnvScreen* EnvScreen_new(Process* process) {
|
||||||
EnvScreen* this = xMalloc(sizeof(EnvScreen));
|
EnvScreen* this = xMalloc(sizeof(EnvScreen));
|
||||||
Object_setClass(this, Class(EnvScreen));
|
Object_setClass(this, Class(EnvScreen));
|
||||||
return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 3, " ");
|
return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnvScreen_delete(Object* this) {
|
void EnvScreen_delete(Object* this) {
|
||||||
|
90
Hashtable.c
90
Hashtable.c
@ -15,22 +15,37 @@ in the source distribution for its full text.
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "CRT.h"
|
||||||
#include "Macros.h"
|
#include "Macros.h"
|
||||||
#include "XUtils.h"
|
#include "XUtils.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct HashtableItem_ {
|
||||||
|
ht_key_t key;
|
||||||
|
size_t probe;
|
||||||
|
void* value;
|
||||||
|
} HashtableItem;
|
||||||
|
|
||||||
|
struct Hashtable_ {
|
||||||
|
size_t size;
|
||||||
|
HashtableItem* buckets;
|
||||||
|
size_t items;
|
||||||
|
bool owner;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
static void Hashtable_dump(const Hashtable* this) {
|
static void Hashtable_dump(const Hashtable* this) {
|
||||||
fprintf(stderr, "Hashtable %p: size=%u items=%u owner=%s\n",
|
fprintf(stderr, "Hashtable %p: size=%zu items=%zu owner=%s\n",
|
||||||
(const void*)this,
|
(const void*)this,
|
||||||
this->size,
|
this->size,
|
||||||
this->items,
|
this->items,
|
||||||
this->owner ? "yes" : "no");
|
this->owner ? "yes" : "no");
|
||||||
|
|
||||||
unsigned int items = 0;
|
size_t items = 0;
|
||||||
for (unsigned int i = 0; i < this->size; i++) {
|
for (size_t i = 0; i < this->size; i++) {
|
||||||
fprintf(stderr, " item %5u: key = %5u probe = %2u value = %p\n",
|
fprintf(stderr, " item %5zu: key = %5u probe = %2zu value = %p\n",
|
||||||
i,
|
i,
|
||||||
this->buckets[i].key,
|
this->buckets[i].key,
|
||||||
this->buckets[i].probe,
|
this->buckets[i].probe,
|
||||||
@ -40,15 +55,15 @@ static void Hashtable_dump(const Hashtable* this) {
|
|||||||
items++;
|
items++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Hashtable %p: items=%u counted=%u\n",
|
fprintf(stderr, "Hashtable %p: items=%zu counted=%zu\n",
|
||||||
(const void*)this,
|
(const void*)this,
|
||||||
this->items,
|
this->items,
|
||||||
items);
|
items);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Hashtable_isConsistent(const Hashtable* this) {
|
static bool Hashtable_isConsistent(const Hashtable* this) {
|
||||||
unsigned int items = 0;
|
size_t items = 0;
|
||||||
for (unsigned int i = 0; i < this->size; i++) {
|
for (size_t i = 0; i < this->size; i++) {
|
||||||
if (this->buckets[i].value)
|
if (this->buckets[i].value)
|
||||||
items++;
|
items++;
|
||||||
}
|
}
|
||||||
@ -58,9 +73,9 @@ static bool Hashtable_isConsistent(const Hashtable* this) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Hashtable_count(const Hashtable* this) {
|
size_t Hashtable_count(const Hashtable* this) {
|
||||||
unsigned int items = 0;
|
size_t items = 0;
|
||||||
for (unsigned int i = 0; i < this->size; i++) {
|
for (size_t i = 0; i < this->size; i++) {
|
||||||
if (this->buckets[i].value)
|
if (this->buckets[i].value)
|
||||||
items++;
|
items++;
|
||||||
}
|
}
|
||||||
@ -80,18 +95,17 @@ static const uint64_t OEISprimes[] = {
|
|||||||
34359738337, 68719476731, 137438953447
|
34359738337, 68719476731, 137438953447
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint64_t nextPrime(unsigned int n) {
|
static uint64_t nextPrime(size_t n) {
|
||||||
assert(n <= OEISprimes[ARRAYSIZE(OEISprimes) - 1]);
|
/* on 32-bit make sure we do not return primes not fitting in size_t */
|
||||||
|
for (size_t i = 0; i < ARRAYSIZE(OEISprimes) && OEISprimes[i] < SIZE_MAX; i++) {
|
||||||
for (unsigned int i = 0; i < ARRAYSIZE(OEISprimes); i++) {
|
|
||||||
if (n <= OEISprimes[i])
|
if (n <= OEISprimes[i])
|
||||||
return OEISprimes[i];
|
return OEISprimes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return OEISprimes[ARRAYSIZE(OEISprimes) - 1];
|
CRT_fatalError("Hashtable: no prime found");
|
||||||
}
|
}
|
||||||
|
|
||||||
Hashtable* Hashtable_new(unsigned int size, bool owner) {
|
Hashtable* Hashtable_new(size_t size, bool owner) {
|
||||||
Hashtable* this;
|
Hashtable* this;
|
||||||
|
|
||||||
this = xMalloc(sizeof(Hashtable));
|
this = xMalloc(sizeof(Hashtable));
|
||||||
@ -115,7 +129,7 @@ void Hashtable_clear(Hashtable* this) {
|
|||||||
assert(Hashtable_isConsistent(this));
|
assert(Hashtable_isConsistent(this));
|
||||||
|
|
||||||
if (this->owner)
|
if (this->owner)
|
||||||
for (unsigned int i = 0; i < this->size; i++)
|
for (size_t i = 0; i < this->size; i++)
|
||||||
free(this->buckets[i].value);
|
free(this->buckets[i].value);
|
||||||
|
|
||||||
memset(this->buckets, 0, this->size * sizeof(HashtableItem));
|
memset(this->buckets, 0, this->size * sizeof(HashtableItem));
|
||||||
@ -124,11 +138,11 @@ void Hashtable_clear(Hashtable* this) {
|
|||||||
assert(Hashtable_isConsistent(this));
|
assert(Hashtable_isConsistent(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void insert(Hashtable* this, hkey_t key, void* value) {
|
static void insert(Hashtable* this, ht_key_t key, void* value) {
|
||||||
unsigned int index = key % this->size;
|
size_t index = key % this->size;
|
||||||
unsigned int probe = 0;
|
size_t probe = 0;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
unsigned int origIndex = index;
|
size_t origIndex = index;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -167,7 +181,7 @@ static void insert(Hashtable* this, hkey_t key, void* value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hashtable_setSize(Hashtable* this, unsigned int size) {
|
void Hashtable_setSize(Hashtable* this, size_t size) {
|
||||||
|
|
||||||
assert(Hashtable_isConsistent(this));
|
assert(Hashtable_isConsistent(this));
|
||||||
|
|
||||||
@ -175,14 +189,14 @@ void Hashtable_setSize(Hashtable* this, unsigned int size) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
HashtableItem* oldBuckets = this->buckets;
|
HashtableItem* oldBuckets = this->buckets;
|
||||||
unsigned int oldSize = this->size;
|
size_t oldSize = this->size;
|
||||||
|
|
||||||
this->size = nextPrime(size);
|
this->size = nextPrime(size);
|
||||||
this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem));
|
this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem));
|
||||||
this->items = 0;
|
this->items = 0;
|
||||||
|
|
||||||
/* rehash */
|
/* rehash */
|
||||||
for (unsigned int i = 0; i < oldSize; i++) {
|
for (size_t i = 0; i < oldSize; i++) {
|
||||||
if (!oldBuckets[i].value)
|
if (!oldBuckets[i].value)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -194,15 +208,19 @@ void Hashtable_setSize(Hashtable* this, unsigned int size) {
|
|||||||
assert(Hashtable_isConsistent(this));
|
assert(Hashtable_isConsistent(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hashtable_put(Hashtable* this, hkey_t key, void* value) {
|
void Hashtable_put(Hashtable* this, ht_key_t key, void* value) {
|
||||||
|
|
||||||
assert(Hashtable_isConsistent(this));
|
assert(Hashtable_isConsistent(this));
|
||||||
assert(this->size > 0);
|
assert(this->size > 0);
|
||||||
assert(value);
|
assert(value);
|
||||||
|
|
||||||
/* grow on load-factor > 0.7 */
|
/* grow on load-factor > 0.7 */
|
||||||
if (10 * this->items > 7 * this->size)
|
if (10 * this->items > 7 * this->size) {
|
||||||
|
if (SIZE_MAX / 2 < this->size)
|
||||||
|
CRT_fatalError("Hashtable: size overflow");
|
||||||
|
|
||||||
Hashtable_setSize(this, 2 * this->size);
|
Hashtable_setSize(this, 2 * this->size);
|
||||||
|
}
|
||||||
|
|
||||||
insert(this, key, value);
|
insert(this, key, value);
|
||||||
|
|
||||||
@ -211,11 +229,11 @@ void Hashtable_put(Hashtable* this, hkey_t key, void* value) {
|
|||||||
assert(this->size > this->items);
|
assert(this->size > this->items);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Hashtable_remove(Hashtable* this, hkey_t key) {
|
void* Hashtable_remove(Hashtable* this, ht_key_t key) {
|
||||||
unsigned int index = key % this->size;
|
size_t index = key % this->size;
|
||||||
unsigned int probe = 0;
|
size_t probe = 0;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
unsigned int origIndex = index;
|
size_t origIndex = index;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(Hashtable_isConsistent(this));
|
assert(Hashtable_isConsistent(this));
|
||||||
@ -230,7 +248,7 @@ void* Hashtable_remove(Hashtable* this, hkey_t key) {
|
|||||||
res = this->buckets[index].value;
|
res = this->buckets[index].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int next = (index + 1) % this->size;
|
size_t next = (index + 1) % this->size;
|
||||||
|
|
||||||
while (this->buckets[next].value && this->buckets[next].probe > 0) {
|
while (this->buckets[next].value && this->buckets[next].probe > 0) {
|
||||||
this->buckets[index] = this->buckets[next];
|
this->buckets[index] = this->buckets[next];
|
||||||
@ -266,12 +284,12 @@ void* Hashtable_remove(Hashtable* this, hkey_t key) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Hashtable_get(Hashtable* this, hkey_t key) {
|
void* Hashtable_get(Hashtable* this, ht_key_t key) {
|
||||||
unsigned int index = key % this->size;
|
size_t index = key % this->size;
|
||||||
unsigned int probe = 0;
|
size_t probe = 0;
|
||||||
void* res = NULL;
|
void* res = NULL;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
unsigned int origIndex = index;
|
size_t origIndex = index;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(Hashtable_isConsistent(this));
|
assert(Hashtable_isConsistent(this));
|
||||||
@ -296,7 +314,7 @@ void* Hashtable_get(Hashtable* this, hkey_t key) {
|
|||||||
|
|
||||||
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) {
|
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) {
|
||||||
assert(Hashtable_isConsistent(this));
|
assert(Hashtable_isConsistent(this));
|
||||||
for (unsigned int i = 0; i < this->size; i++) {
|
for (size_t i = 0; i < this->size; i++) {
|
||||||
HashtableItem* walk = &this->buckets[i];
|
HashtableItem* walk = &this->buckets[i];
|
||||||
if (walk->value)
|
if (walk->value)
|
||||||
f(walk->key, walk->value, userData);
|
f(walk->key, walk->value, userData);
|
||||||
|
30
Hashtable.h
30
Hashtable.h
@ -8,44 +8,34 @@ in the source distribution for its full text.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned int hkey_t;
|
typedef unsigned int ht_key_t;
|
||||||
|
|
||||||
typedef void(*Hashtable_PairFunction)(hkey_t key, void* value, void* userdata);
|
typedef void(*Hashtable_PairFunction)(ht_key_t key, void* value, void* userdata);
|
||||||
|
|
||||||
typedef struct HashtableItem_ {
|
typedef struct Hashtable_ Hashtable;
|
||||||
hkey_t key;
|
|
||||||
unsigned int probe;
|
|
||||||
void* value;
|
|
||||||
} HashtableItem;
|
|
||||||
|
|
||||||
typedef struct Hashtable_ {
|
|
||||||
unsigned int size;
|
|
||||||
HashtableItem* buckets;
|
|
||||||
unsigned int items;
|
|
||||||
bool owner;
|
|
||||||
} Hashtable;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
unsigned int Hashtable_count(const Hashtable* this);
|
size_t Hashtable_count(const Hashtable* this);
|
||||||
|
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
Hashtable* Hashtable_new(unsigned int size, bool owner);
|
Hashtable* Hashtable_new(size_t size, bool owner);
|
||||||
|
|
||||||
void Hashtable_delete(Hashtable* this);
|
void Hashtable_delete(Hashtable* this);
|
||||||
|
|
||||||
void Hashtable_clear(Hashtable* this);
|
void Hashtable_clear(Hashtable* this);
|
||||||
|
|
||||||
void Hashtable_setSize(Hashtable* this, unsigned int size);
|
void Hashtable_setSize(Hashtable* this, size_t size);
|
||||||
|
|
||||||
void Hashtable_put(Hashtable* this, hkey_t key, void* value);
|
void Hashtable_put(Hashtable* this, ht_key_t key, void* value);
|
||||||
|
|
||||||
void* Hashtable_remove(Hashtable* this, hkey_t key);
|
void* Hashtable_remove(Hashtable* this, ht_key_t key);
|
||||||
|
|
||||||
void* Hashtable_get(Hashtable* this, hkey_t key);
|
void* Hashtable_get(Hashtable* this, ht_key_t key);
|
||||||
|
|
||||||
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);
|
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);
|
||||||
|
|
||||||
|
22
IncSet.c
22
IncSet.c
@ -29,9 +29,9 @@ void IncSet_reset(IncSet* this, IncType type) {
|
|||||||
IncMode_reset(&this->modes[type]);
|
IncMode_reset(&this->modes[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* const searchFunctions[] = {"Next ", "Cancel ", " Search: ", NULL};
|
static const char* const searchFunctions[] = {"Next ", "Prev ", "Cancel ", " Search: ", NULL};
|
||||||
static const char* const searchKeys[] = {"F3", "Esc", " "};
|
static const char* const searchKeys[] = {"F3", "S-F3", "Esc", " "};
|
||||||
static const int searchEvents[] = {KEY_F(3), 27, ERR};
|
static const int searchEvents[] = {KEY_F(3), KEY_F(15), 27, ERR};
|
||||||
|
|
||||||
static inline void IncMode_initSearch(IncMode* search) {
|
static inline void IncMode_initSearch(IncMode* search) {
|
||||||
memset(search, 0, sizeof(IncMode));
|
memset(search, 0, sizeof(IncMode));
|
||||||
@ -133,14 +133,6 @@ static bool IncMode_find(IncMode* mode, Panel* panel, IncMode_GetPanelValue getP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IncSet_next(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue) {
|
|
||||||
return IncMode_find(&this->modes[type], panel, getPanelValue, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IncSet_prev(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue) {
|
|
||||||
return IncMode_find(&this->modes[type], panel, getPanelValue, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) {
|
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) {
|
||||||
if (ch == ERR)
|
if (ch == ERR)
|
||||||
return true;
|
return true;
|
||||||
@ -149,11 +141,11 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue
|
|||||||
int size = Panel_size(panel);
|
int size = Panel_size(panel);
|
||||||
bool filterChanged = false;
|
bool filterChanged = false;
|
||||||
bool doSearch = true;
|
bool doSearch = true;
|
||||||
if (ch == KEY_F(3)) {
|
if (ch == KEY_F(3) || ch == KEY_F(15)) {
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
IncMode_find(mode, panel, getPanelValue, 1);
|
IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1);
|
||||||
doSearch = false;
|
doSearch = false;
|
||||||
} else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) {
|
} else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) {
|
||||||
if (mode->index < INCMODE_MAX) {
|
if (mode->index < INCMODE_MAX) {
|
||||||
@ -167,7 +159,7 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((ch == KEY_BACKSPACE || ch == 127)) {
|
} else if (ch == KEY_BACKSPACE || ch == 127) {
|
||||||
if (mode->index > 0) {
|
if (mode->index > 0) {
|
||||||
mode->index--;
|
mode->index--;
|
||||||
mode->buffer[mode->index] = 0;
|
mode->buffer[mode->index] = 0;
|
||||||
@ -182,7 +174,7 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue
|
|||||||
doSearch = false;
|
doSearch = false;
|
||||||
}
|
}
|
||||||
} else if (ch == KEY_RESIZE) {
|
} else if (ch == KEY_RESIZE) {
|
||||||
Panel_resize(panel, COLS, LINES - panel->y - 1);
|
doSearch = (mode->index > 0);
|
||||||
} else {
|
} else {
|
||||||
if (mode->isFilter) {
|
if (mode->isFilter) {
|
||||||
filterChanged = true;
|
filterChanged = true;
|
||||||
|
4
IncSet.h
4
IncSet.h
@ -48,10 +48,6 @@ IncSet* IncSet_new(FunctionBar* bar);
|
|||||||
|
|
||||||
void IncSet_delete(IncSet* this);
|
void IncSet_delete(IncSet* this);
|
||||||
|
|
||||||
bool IncSet_next(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue);
|
|
||||||
|
|
||||||
bool IncSet_prev(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue);
|
|
||||||
|
|
||||||
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines);
|
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines);
|
||||||
|
|
||||||
const char* IncSet_getListItemValue(Panel* panel, int i);
|
const char* IncSet_getListItemValue(Panel* panel, int i);
|
||||||
|
@ -26,7 +26,7 @@ InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBa
|
|||||||
if (!bar) {
|
if (!bar) {
|
||||||
bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents);
|
bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents);
|
||||||
}
|
}
|
||||||
this->display = Panel_new(0, 1, COLS, height, false, Class(ListItem), bar);
|
this->display = Panel_new(0, 1, COLS, height, Class(ListItem), false, bar);
|
||||||
this->inc = IncSet_new(bar);
|
this->inc = IncSet_new(bar);
|
||||||
this->lines = Vector_new(this->display->items->type, true, DEFAULT_SIZE);
|
this->lines = Vector_new(this->display->items->type, true, DEFAULT_SIZE);
|
||||||
Panel_setHeader(this->display, panelHeader);
|
Panel_setHeader(this->display, panelHeader);
|
||||||
@ -54,9 +54,9 @@ void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) {
|
|||||||
|
|
||||||
attrset(CRT_colors[METER_TEXT]);
|
attrset(CRT_colors[METER_TEXT]);
|
||||||
mvhline(0, 0, ' ', COLS);
|
mvhline(0, 0, ' ', COLS);
|
||||||
mvwprintw(stdscr, 0, 0, title);
|
mvaddstr(0, 0, title);
|
||||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||||
Panel_draw(this->display, true, true, true);
|
Panel_draw(this->display, true, true, true, false);
|
||||||
|
|
||||||
IncSet_drawBar(this->inc);
|
IncSet_drawBar(this->inc);
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ void InfoScreen_run(InfoScreen* this) {
|
|||||||
bool looping = true;
|
bool looping = true;
|
||||||
while (looping) {
|
while (looping) {
|
||||||
|
|
||||||
Panel_draw(panel, false, true, true);
|
Panel_draw(panel, false, true, true, false);
|
||||||
IncSet_drawBar(this->inc);
|
IncSet_drawBar(this->inc);
|
||||||
|
|
||||||
if (this->inc->active) {
|
if (this->inc->active) {
|
||||||
|
@ -57,7 +57,7 @@ void ListItem_append(ListItem* this, const char* text) {
|
|||||||
this->value[newLen] = '\0';
|
this->value[newLen] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static long ListItem_compare(const void* cast1, const void* cast2) {
|
static int ListItem_compare(const void* cast1, const void* cast2) {
|
||||||
const ListItem* obj1 = (const ListItem*) cast1;
|
const ListItem* obj1 = (const ListItem*) cast1;
|
||||||
const ListItem* obj2 = (const ListItem*) cast2;
|
const ListItem* obj2 = (const ListItem*) cast2;
|
||||||
return strcmp(obj1->value, obj2->value);
|
return strcmp(obj1->value, obj2->value);
|
||||||
|
@ -24,8 +24,36 @@ static const int LoadMeter_attributes[] = {
|
|||||||
LOAD
|
LOAD
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const int OK_attributes[] = {
|
||||||
|
METER_VALUE_OK
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int Medium_attributes[] = {
|
||||||
|
METER_VALUE_WARN
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int High_attributes[] = {
|
||||||
|
METER_VALUE_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
static void LoadAverageMeter_updateValues(Meter* this, char* buffer, size_t size) {
|
static void LoadAverageMeter_updateValues(Meter* this, char* buffer, size_t size) {
|
||||||
Platform_getLoadAverage(&this->values[0], &this->values[1], &this->values[2]);
|
Platform_getLoadAverage(&this->values[0], &this->values[1], &this->values[2]);
|
||||||
|
|
||||||
|
// only show bar for 1min value
|
||||||
|
this->curItems = 1;
|
||||||
|
|
||||||
|
// change bar color and total based on value
|
||||||
|
if (this->values[0] < 1.0) {
|
||||||
|
this->curAttributes = OK_attributes;
|
||||||
|
this->total = 1.0;
|
||||||
|
} else if (this->values[0] < this->pl->cpuCount) {
|
||||||
|
this->curAttributes = Medium_attributes;
|
||||||
|
this->total = this->pl->cpuCount;
|
||||||
|
} else {
|
||||||
|
this->curAttributes = High_attributes;
|
||||||
|
this->total = 2 * this->pl->cpuCount;
|
||||||
|
}
|
||||||
|
|
||||||
xSnprintf(buffer, size, "%.2f/%.2f/%.2f", this->values[0], this->values[1], this->values[2]);
|
xSnprintf(buffer, size, "%.2f/%.2f/%.2f", this->values[0], this->values[1], this->values[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,9 +71,19 @@ static void LoadAverageMeter_display(const Object* cast, RichString* out) {
|
|||||||
static void LoadMeter_updateValues(Meter* this, char* buffer, size_t size) {
|
static void LoadMeter_updateValues(Meter* this, char* buffer, size_t size) {
|
||||||
double five, fifteen;
|
double five, fifteen;
|
||||||
Platform_getLoadAverage(&this->values[0], &five, &fifteen);
|
Platform_getLoadAverage(&this->values[0], &five, &fifteen);
|
||||||
if (this->values[0] > this->total) {
|
|
||||||
this->total = this->values[0];
|
// change bar color and total based on value
|
||||||
|
if (this->values[0] < 1.0) {
|
||||||
|
this->curAttributes = OK_attributes;
|
||||||
|
this->total = 1.0;
|
||||||
|
} else if (this->values[0] < this->pl->cpuCount) {
|
||||||
|
this->curAttributes = Medium_attributes;
|
||||||
|
this->total = this->pl->cpuCount;
|
||||||
|
} else {
|
||||||
|
this->curAttributes = High_attributes;
|
||||||
|
this->total = 2 * this->pl->cpuCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
xSnprintf(buffer, size, "%.2f", this->values[0]);
|
xSnprintf(buffer, size, "%.2f", this->values[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
36
MainPanel.c
36
MainPanel.c
@ -44,6 +44,11 @@ void MainPanel_pidSearch(MainPanel* this, int ch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* MainPanel_getValue(Panel* this, int i) {
|
||||||
|
const Process* p = (const Process*) Panel_get(this, i);
|
||||||
|
return Process_getCommand(p);
|
||||||
|
}
|
||||||
|
|
||||||
static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
||||||
MainPanel* this = (MainPanel*) super;
|
MainPanel* this = (MainPanel*) super;
|
||||||
|
|
||||||
@ -51,7 +56,12 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
|||||||
|
|
||||||
Htop_Reaction reaction = HTOP_OK;
|
Htop_Reaction reaction = HTOP_OK;
|
||||||
|
|
||||||
if (ch != ERR && ch != KEY_RESIZE)
|
/* Let supervising ScreenManager handle resize */
|
||||||
|
if (ch == KEY_RESIZE)
|
||||||
|
return IGNORED;
|
||||||
|
|
||||||
|
/* reset on every normal key */
|
||||||
|
if (ch != ERR)
|
||||||
this->state->hideProcessSelection = false;
|
this->state->hideProcessSelection = false;
|
||||||
|
|
||||||
if (EVENT_IS_HEADER_CLICK(ch)) {
|
if (EVENT_IS_HEADER_CLICK(ch)) {
|
||||||
@ -72,7 +82,7 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
|||||||
reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS;
|
reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS;
|
||||||
result = HANDLED;
|
result = HANDLED;
|
||||||
} else if (ch != ERR && this->inc->active) {
|
} else if (ch != ERR && this->inc->active) {
|
||||||
bool filterChanged = IncSet_handleKey(this->inc, ch, super, (IncMode_GetPanelValue) MainPanel_getValue, NULL);
|
bool filterChanged = IncSet_handleKey(this->inc, ch, super, MainPanel_getValue, NULL);
|
||||||
if (filterChanged) {
|
if (filterChanged) {
|
||||||
this->state->pl->incFilter = IncSet_filter(this->inc);
|
this->state->pl->incFilter = IncSet_filter(this->inc);
|
||||||
reaction = HTOP_REFRESH | HTOP_REDRAW_BAR;
|
reaction = HTOP_REFRESH | HTOP_REDRAW_BAR;
|
||||||
@ -102,7 +112,7 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
|||||||
MainPanel_updateTreeFunctions(this, this->state->settings->treeView);
|
MainPanel_updateTreeFunctions(this, this->state->settings->treeView);
|
||||||
}
|
}
|
||||||
if (reaction & HTOP_UPDATE_PANELHDR) {
|
if (reaction & HTOP_UPDATE_PANELHDR) {
|
||||||
ProcessList_printHeader(this->state->pl, Panel_getHeader(super));
|
result |= REDRAW;
|
||||||
}
|
}
|
||||||
if (reaction & HTOP_REFRESH) {
|
if (reaction & HTOP_REFRESH) {
|
||||||
result |= REFRESH;
|
result |= REFRESH;
|
||||||
@ -131,11 +141,6 @@ int MainPanel_selectedPid(MainPanel* this) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* MainPanel_getValue(MainPanel* this, int i) {
|
|
||||||
Process* p = (Process*) Panel_get((Panel*)this, i);
|
|
||||||
return Process_getCommand(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged) {
|
bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged) {
|
||||||
Panel* super = (Panel*) this;
|
Panel* super = (Panel*) this;
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
@ -160,21 +165,32 @@ bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Ar
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MainPanel_drawFunctionBar(Panel* super) {
|
static void MainPanel_drawFunctionBar(Panel* super, bool hideFunctionBar) {
|
||||||
MainPanel* this = (MainPanel*) super;
|
MainPanel* this = (MainPanel*) super;
|
||||||
|
|
||||||
|
// Do not hide active search and filter bar.
|
||||||
|
if (hideFunctionBar && !this->inc->active)
|
||||||
|
return;
|
||||||
|
|
||||||
IncSet_drawBar(this->inc);
|
IncSet_drawBar(this->inc);
|
||||||
if (this->state->pauseProcessUpdate) {
|
if (this->state->pauseProcessUpdate) {
|
||||||
FunctionBar_append("PAUSED", CRT_colors[PAUSED]);
|
FunctionBar_append("PAUSED", CRT_colors[PAUSED]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void MainPanel_printHeader(Panel* super) {
|
||||||
|
MainPanel* this = (MainPanel*) super;
|
||||||
|
ProcessList_printHeader(this->state->pl, &super->header);
|
||||||
|
}
|
||||||
|
|
||||||
const PanelClass MainPanel_class = {
|
const PanelClass MainPanel_class = {
|
||||||
.super = {
|
.super = {
|
||||||
.extends = Class(Panel),
|
.extends = Class(Panel),
|
||||||
.delete = MainPanel_delete
|
.delete = MainPanel_delete
|
||||||
},
|
},
|
||||||
.eventHandler = MainPanel_eventHandler,
|
.eventHandler = MainPanel_eventHandler,
|
||||||
.drawFunctionBar = MainPanel_drawFunctionBar
|
.drawFunctionBar = MainPanel_drawFunctionBar,
|
||||||
|
.printHeader = MainPanel_printHeader
|
||||||
};
|
};
|
||||||
|
|
||||||
MainPanel* MainPanel_new() {
|
MainPanel* MainPanel_new() {
|
||||||
|
@ -38,8 +38,6 @@ void MainPanel_pidSearch(MainPanel* this, int ch);
|
|||||||
|
|
||||||
int MainPanel_selectedPid(MainPanel* this);
|
int MainPanel_selectedPid(MainPanel* this);
|
||||||
|
|
||||||
const char* MainPanel_getValue(MainPanel* this, int i);
|
|
||||||
|
|
||||||
bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged);
|
bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged);
|
||||||
|
|
||||||
extern const PanelClass MainPanel_class;
|
extern const PanelClass MainPanel_class;
|
||||||
|
11
Meter.c
11
Meter.c
@ -39,6 +39,7 @@ Meter* Meter_new(const struct ProcessList_* pl, int param, const MeterClass* typ
|
|||||||
this->param = param;
|
this->param = param;
|
||||||
this->pl = pl;
|
this->pl = pl;
|
||||||
this->curItems = type->maxItems;
|
this->curItems = type->maxItems;
|
||||||
|
this->curAttributes = NULL;
|
||||||
this->values = type->maxItems ? xCalloc(type->maxItems, sizeof(double)) : NULL;
|
this->values = type->maxItems ? xCalloc(type->maxItems, sizeof(double)) : NULL;
|
||||||
this->total = type->total;
|
this->total = type->total;
|
||||||
this->caption = xStrdup(type->caption);
|
this->caption = xStrdup(type->caption);
|
||||||
@ -252,13 +253,14 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
|
|||||||
// ...then print the buffer.
|
// ...then print the buffer.
|
||||||
offset = 0;
|
offset = 0;
|
||||||
for (uint8_t i = 0; i < this->curItems; i++) {
|
for (uint8_t i = 0; i < this->curItems; i++) {
|
||||||
RichString_setAttrn(&bar, CRT_colors[Meter_attributes(this)[i]], startPos + offset, startPos + offset + blockSizes[i] - 1);
|
int attr = this->curAttributes ? this->curAttributes[i] : Meter_attributes(this)[i];
|
||||||
|
RichString_setAttrn(&bar, CRT_colors[attr], startPos + offset, blockSizes[i]);
|
||||||
RichString_printoffnVal(bar, y, x + offset, startPos + offset, MINIMUM(blockSizes[i], w - offset));
|
RichString_printoffnVal(bar, y, x + offset, startPos + offset, MINIMUM(blockSizes[i], w - offset));
|
||||||
offset += blockSizes[i];
|
offset += blockSizes[i];
|
||||||
offset = CLAMP(offset, 0, w);
|
offset = CLAMP(offset, 0, w);
|
||||||
}
|
}
|
||||||
if (offset < w) {
|
if (offset < w) {
|
||||||
RichString_setAttrn(&bar, CRT_colors[BAR_SHADOW], startPos + offset, startPos + w - 1);
|
RichString_setAttrn(&bar, CRT_colors[BAR_SHADOW], startPos + offset, w - offset);
|
||||||
RichString_printoffnVal(bar, y, x + offset, startPos + offset, w - offset);
|
RichString_printoffnVal(bar, y, x + offset, startPos + offset, w - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,9 +292,6 @@ static const char* const GraphMeterMode_dotsAscii[] = {
|
|||||||
/*20*/":", /*21*/":", /*22*/":"
|
/*20*/":", /*21*/":", /*22*/":"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* const* GraphMeterMode_dots;
|
|
||||||
static int GraphMeterMode_pixPerRow;
|
|
||||||
|
|
||||||
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||||
|
|
||||||
if (!this->drawData) {
|
if (!this->drawData) {
|
||||||
@ -301,6 +300,8 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
|||||||
GraphData* data = this->drawData;
|
GraphData* data = this->drawData;
|
||||||
const int nValues = METER_BUFFER_LEN;
|
const int nValues = METER_BUFFER_LEN;
|
||||||
|
|
||||||
|
const char* const* GraphMeterMode_dots;
|
||||||
|
int GraphMeterMode_pixPerRow;
|
||||||
#ifdef HAVE_LIBNCURSESW
|
#ifdef HAVE_LIBNCURSESW
|
||||||
if (CRT_utf8) {
|
if (CRT_utf8) {
|
||||||
GraphMeterMode_dots = GraphMeterMode_dotsUtf8;
|
GraphMeterMode_dots = GraphMeterMode_dotsUtf8;
|
||||||
|
1
Meter.h
1
Meter.h
@ -100,6 +100,7 @@ struct Meter_ {
|
|||||||
int h;
|
int h;
|
||||||
const ProcessList* pl;
|
const ProcessList* pl;
|
||||||
uint8_t curItems;
|
uint8_t curItems;
|
||||||
|
const int* curAttributes;
|
||||||
double* values;
|
double* values;
|
||||||
double total;
|
double total;
|
||||||
void* meterData;
|
void* meterData;
|
||||||
|
2
Object.h
2
Object.h
@ -24,7 +24,7 @@ struct Object_;
|
|||||||
typedef struct Object_ Object;
|
typedef struct Object_ Object;
|
||||||
|
|
||||||
typedef void(*Object_Display)(const Object*, RichString*);
|
typedef void(*Object_Display)(const Object*, RichString*);
|
||||||
typedef long(*Object_Compare)(const void*, const void*);
|
typedef int(*Object_Compare)(const void*, const void*);
|
||||||
typedef void(*Object_Delete)(Object*);
|
typedef void(*Object_Delete)(Object*);
|
||||||
|
|
||||||
#define Object_getClass(obj_) ((const Object*)(obj_))->klass
|
#define Object_getClass(obj_) ((const Object*)(obj_))->klass
|
||||||
|
@ -74,7 +74,7 @@ OpenFilesScreen* OpenFilesScreen_new(const Process* process) {
|
|||||||
} else {
|
} else {
|
||||||
this->pid = process->pid;
|
this->pid = process->pid;
|
||||||
}
|
}
|
||||||
return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 3, " FD TYPE MODE DEVICE SIZE NODE NAME");
|
return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " FD TYPE MODE DEVICE SIZE NODE NAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenFilesScreen_delete(Object* this) {
|
void OpenFilesScreen_delete(Object* this) {
|
||||||
|
70
Panel.c
70
Panel.c
@ -30,7 +30,7 @@ const PanelClass Panel_class = {
|
|||||||
.eventHandler = Panel_selectByTyping,
|
.eventHandler = Panel_selectByTyping,
|
||||||
};
|
};
|
||||||
|
|
||||||
Panel* Panel_new(int x, int y, int w, int h, bool owner, const ObjectClass* type, FunctionBar* fuBar) {
|
Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) {
|
||||||
Panel* this;
|
Panel* this;
|
||||||
this = xMalloc(sizeof(Panel));
|
this = xMalloc(sizeof(Panel));
|
||||||
Object_setClass(this, Class(Panel));
|
Object_setClass(this, Class(Panel));
|
||||||
@ -76,13 +76,6 @@ void Panel_setSelectionColor(Panel* this, ColorElements colorId) {
|
|||||||
this->selectionColorId = colorId;
|
this->selectionColorId = colorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
RichString* Panel_getHeader(Panel* this) {
|
|
||||||
assert (this != NULL);
|
|
||||||
|
|
||||||
this->needsRedraw = true;
|
|
||||||
return &(this->header);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Panel_setHeader(Panel* this, const char* header) {
|
inline void Panel_setHeader(Panel* this, const char* header) {
|
||||||
RichString_writeWide(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
|
RichString_writeWide(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
|
||||||
this->needsRedraw = true;
|
this->needsRedraw = true;
|
||||||
@ -99,10 +92,6 @@ void Panel_move(Panel* this, int x, int y) {
|
|||||||
void Panel_resize(Panel* this, int w, int h) {
|
void Panel_resize(Panel* this, int w, int h) {
|
||||||
assert (this != NULL);
|
assert (this != NULL);
|
||||||
|
|
||||||
if (RichString_sizeVal(this->header) > 0) {
|
|
||||||
h--;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->w = w;
|
this->w = w;
|
||||||
this->h = h;
|
this->h = h;
|
||||||
this->needsRedraw = true;
|
this->needsRedraw = true;
|
||||||
@ -219,7 +208,7 @@ void Panel_splice(Panel* this, Vector* from) {
|
|||||||
this->needsRedraw = true;
|
this->needsRedraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected) {
|
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar) {
|
||||||
assert (this != NULL);
|
assert (this != NULL);
|
||||||
|
|
||||||
int size = Vector_size(this->items);
|
int size = Vector_size(this->items);
|
||||||
@ -228,20 +217,29 @@ void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelect
|
|||||||
int x = this->x;
|
int x = this->x;
|
||||||
int h = this->h;
|
int h = this->h;
|
||||||
|
|
||||||
|
if (hideFunctionBar)
|
||||||
|
h++;
|
||||||
|
|
||||||
|
const int header_attr = focus
|
||||||
|
? CRT_colors[PANEL_HEADER_FOCUS]
|
||||||
|
: CRT_colors[PANEL_HEADER_UNFOCUS];
|
||||||
|
if (force_redraw) {
|
||||||
|
if (Panel_printHeaderFn(this))
|
||||||
|
Panel_printHeader(this);
|
||||||
|
else
|
||||||
|
RichString_setAttr(&this->header, header_attr);
|
||||||
|
}
|
||||||
int headerLen = RichString_sizeVal(this->header);
|
int headerLen = RichString_sizeVal(this->header);
|
||||||
if (headerLen > 0) {
|
if (headerLen > 0) {
|
||||||
int attr = focus
|
attrset(header_attr);
|
||||||
? CRT_colors[PANEL_HEADER_FOCUS]
|
|
||||||
: CRT_colors[PANEL_HEADER_UNFOCUS];
|
|
||||||
attrset(attr);
|
|
||||||
mvhline(y, x, ' ', this->w);
|
mvhline(y, x, ' ', this->w);
|
||||||
if (scrollH < headerLen) {
|
if (scrollH < headerLen) {
|
||||||
RichString_setAttr(&this->header, attr);
|
|
||||||
RichString_printoffnVal(this->header, y, x, scrollH,
|
RichString_printoffnVal(this->header, y, x, scrollH,
|
||||||
MINIMUM(headerLen - scrollH, this->w));
|
MINIMUM(headerLen - scrollH, this->w));
|
||||||
}
|
}
|
||||||
attrset(CRT_colors[RESET_COLOR]);
|
attrset(CRT_colors[RESET_COLOR]);
|
||||||
y++;
|
y++;
|
||||||
|
h--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure scroll area is on screen
|
// ensure scroll area is on screen
|
||||||
@ -324,8 +322,8 @@ void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelect
|
|||||||
|
|
||||||
if (focus && (this->needsRedraw || force_redraw || !this->wasFocus)) {
|
if (focus && (this->needsRedraw || force_redraw || !this->wasFocus)) {
|
||||||
if (Panel_drawFunctionBarFn(this))
|
if (Panel_drawFunctionBarFn(this))
|
||||||
Panel_drawFunctionBar(this);
|
Panel_drawFunctionBar(this, hideFunctionBar);
|
||||||
else
|
else if (!hideFunctionBar)
|
||||||
FunctionBar_draw(this->currentBar);
|
FunctionBar_draw(this->currentBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,13 +333,21 @@ void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelect
|
|||||||
move(0, 0);
|
move(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int Panel_headerHeight(const Panel* this) {
|
||||||
|
return RichString_sizeVal(this->header) > 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool Panel_onKey(Panel* this, int key) {
|
bool Panel_onKey(Panel* this, int key) {
|
||||||
assert (this != NULL);
|
assert (this != NULL);
|
||||||
|
|
||||||
int size = Vector_size(this->items);
|
const int size = Vector_size(this->items);
|
||||||
|
|
||||||
#define CLAMP_INDEX(var, delta, min, max) \
|
#define PANEL_SCROLL(amount) \
|
||||||
CLAMP((var) + (delta), (min), MAXIMUM(0, (max)))
|
do { \
|
||||||
|
this->selected += (amount); \
|
||||||
|
this->scrollV = CLAMP(this->scrollV + (amount), 0, MAXIMUM(0, (size - this->h - Panel_headerHeight(this)))); \
|
||||||
|
this->needsRedraw = true; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
@ -375,27 +381,19 @@ bool Panel_onKey(Panel* this, int key) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_PPAGE:
|
case KEY_PPAGE:
|
||||||
this->selected -= (this->h - 1);
|
PANEL_SCROLL(-(this->h - Panel_headerHeight(this)));
|
||||||
this->scrollV = CLAMP_INDEX(this->scrollV, -(this->h - 1), 0, size - this->h);
|
|
||||||
this->needsRedraw = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_NPAGE:
|
case KEY_NPAGE:
|
||||||
this->selected += (this->h - 1);
|
PANEL_SCROLL(+(this->h - Panel_headerHeight(this)));
|
||||||
this->scrollV = CLAMP_INDEX(this->scrollV, +(this->h - 1), 0, size - this->h);
|
|
||||||
this->needsRedraw = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_WHEELUP:
|
case KEY_WHEELUP:
|
||||||
this->selected -= CRT_scrollWheelVAmount;
|
PANEL_SCROLL(-CRT_scrollWheelVAmount);
|
||||||
this->scrollV = CLAMP_INDEX(this->scrollV, -CRT_scrollWheelVAmount, 0, size - this->h);
|
|
||||||
this->needsRedraw = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_WHEELDOWN:
|
case KEY_WHEELDOWN:
|
||||||
this->selected += CRT_scrollWheelVAmount;
|
PANEL_SCROLL(+CRT_scrollWheelVAmount);
|
||||||
this->scrollV = CLAMP_INDEX(this->scrollV, +CRT_scrollWheelVAmount, 0, size - this->h);
|
|
||||||
this->needsRedraw = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_HOME:
|
case KEY_HOME:
|
||||||
@ -420,7 +418,7 @@ bool Panel_onKey(Panel* this, int key) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CLAMP_INDEX
|
#undef PANEL_SCROLL
|
||||||
|
|
||||||
// ensure selection within bounds
|
// ensure selection within bounds
|
||||||
if (this->selected < 0 || size == 0) {
|
if (this->selected < 0 || size == 0) {
|
||||||
|
22
Panel.h
22
Panel.h
@ -36,19 +36,23 @@ typedef enum HandlerResult_ {
|
|||||||
#define EVENT_HEADER_CLICK_GET_X(ev_) ((ev_) + 10000)
|
#define EVENT_HEADER_CLICK_GET_X(ev_) ((ev_) + 10000)
|
||||||
|
|
||||||
typedef HandlerResult (*Panel_EventHandler)(Panel*, int);
|
typedef HandlerResult (*Panel_EventHandler)(Panel*, int);
|
||||||
typedef void (*Panel_DrawFunctionBar)(Panel*);
|
typedef void (*Panel_DrawFunctionBar)(Panel*, bool);
|
||||||
|
typedef void (*Panel_PrintHeader)(Panel*);
|
||||||
|
|
||||||
typedef struct PanelClass_ {
|
typedef struct PanelClass_ {
|
||||||
const ObjectClass super;
|
const ObjectClass super;
|
||||||
const Panel_EventHandler eventHandler;
|
const Panel_EventHandler eventHandler;
|
||||||
const Panel_DrawFunctionBar drawFunctionBar;
|
const Panel_DrawFunctionBar drawFunctionBar;
|
||||||
|
const Panel_PrintHeader printHeader;
|
||||||
} PanelClass;
|
} PanelClass;
|
||||||
|
|
||||||
#define As_Panel(this_) ((const PanelClass*)((this_)->super.klass))
|
#define As_Panel(this_) ((const PanelClass*)((this_)->super.klass))
|
||||||
#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler
|
#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler
|
||||||
#define Panel_eventHandler(this_, ev_) (assert(As_Panel(this_)->eventHandler), As_Panel(this_)->eventHandler((Panel*)(this_), ev_))
|
#define Panel_eventHandler(this_, ev_) (assert(As_Panel(this_)->eventHandler), As_Panel(this_)->eventHandler((Panel*)(this_), ev_))
|
||||||
#define Panel_drawFunctionBarFn(this_) As_Panel(this_)->drawFunctionBar
|
#define Panel_drawFunctionBarFn(this_) As_Panel(this_)->drawFunctionBar
|
||||||
#define Panel_drawFunctionBar(this_) (assert(As_Panel(this_)->drawFunctionBar), As_Panel(this_)->drawFunctionBar((Panel*)(this_)))
|
#define Panel_drawFunctionBar(this_, hideFB_) (assert(As_Panel(this_)->drawFunctionBar), As_Panel(this_)->drawFunctionBar((Panel*)(this_), hideFB_))
|
||||||
|
#define Panel_printHeaderFn(this_) As_Panel(this_)->printHeader
|
||||||
|
#define Panel_printHeader(this_) (assert(As_Panel(this_)->printHeader), As_Panel(this_)->printHeader((Panel*)(this_)))
|
||||||
|
|
||||||
struct Panel_ {
|
struct Panel_ {
|
||||||
Object super;
|
Object super;
|
||||||
@ -74,7 +78,7 @@ struct Panel_ {
|
|||||||
|
|
||||||
extern const PanelClass Panel_class;
|
extern const PanelClass Panel_class;
|
||||||
|
|
||||||
Panel* Panel_new(int x, int y, int w, int h, bool owner, const ObjectClass* type, FunctionBar* fuBar);
|
Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar);
|
||||||
|
|
||||||
void Panel_delete(Object* cast);
|
void Panel_delete(Object* cast);
|
||||||
|
|
||||||
@ -84,8 +88,6 @@ void Panel_done(Panel* this);
|
|||||||
|
|
||||||
void Panel_setSelectionColor(Panel* this, ColorElements colorId);
|
void Panel_setSelectionColor(Panel* this, ColorElements colorId);
|
||||||
|
|
||||||
RichString* Panel_getHeader(Panel* this);
|
|
||||||
|
|
||||||
void Panel_setHeader(Panel* this, const char* header);
|
void Panel_setHeader(Panel* this, const char* header);
|
||||||
|
|
||||||
void Panel_move(Panel* this, int x, int y);
|
void Panel_move(Panel* this, int x, int y);
|
||||||
@ -116,7 +118,7 @@ int Panel_size(Panel* this);
|
|||||||
|
|
||||||
void Panel_setSelected(Panel* this, int selected);
|
void Panel_setSelected(Panel* this, int selected);
|
||||||
|
|
||||||
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected);
|
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar);
|
||||||
|
|
||||||
void Panel_splice(Panel* this, Vector* from);
|
void Panel_splice(Panel* this, Vector* from);
|
||||||
|
|
||||||
|
41
Process.c
41
Process.c
@ -183,34 +183,34 @@ void Process_fillStarttimeBuffer(Process* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void Process_writeCommand(const Process* this, int attr, int baseattr, RichString* str) {
|
static inline void Process_writeCommand(const Process* this, int attr, int baseattr, RichString* str) {
|
||||||
int start = RichString_size(str), finish = 0;
|
int start = RichString_size(str);
|
||||||
|
int len = 0;
|
||||||
const char* comm = this->comm;
|
const char* comm = this->comm;
|
||||||
|
|
||||||
if (this->settings->highlightBaseName || !this->settings->showProgramPath) {
|
if (this->settings->highlightBaseName || !this->settings->showProgramPath) {
|
||||||
int i, basename = 0;
|
int basename = 0;
|
||||||
for (i = 0; i < this->basenameOffset; i++) {
|
for (int i = 0; i < this->basenameOffset; i++) {
|
||||||
if (comm[i] == '/') {
|
if (comm[i] == '/') {
|
||||||
basename = i + 1;
|
basename = i + 1;
|
||||||
} else if (comm[i] == ':') {
|
} else if (comm[i] == ':') {
|
||||||
finish = i + 1;
|
len = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!finish) {
|
if (len == 0) {
|
||||||
if (this->settings->showProgramPath) {
|
if (this->settings->showProgramPath) {
|
||||||
start += basename;
|
start += basename;
|
||||||
} else {
|
} else {
|
||||||
comm += basename;
|
comm += basename;
|
||||||
}
|
}
|
||||||
finish = this->basenameOffset - basename;
|
len = this->basenameOffset - basename;
|
||||||
}
|
}
|
||||||
finish += start - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RichString_appendWide(str, attr, comm);
|
RichString_appendWide(str, attr, comm);
|
||||||
|
|
||||||
if (this->settings->highlightBaseName) {
|
if (this->settings->highlightBaseName) {
|
||||||
RichString_setAttrn(str, baseattr, start, finish);
|
RichString_setAttrn(str, baseattr, start, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +244,11 @@ void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width) {
|
||||||
|
int c = RichString_appendnWide(str, attr, content, MINIMUM(width, strlen(content)));
|
||||||
|
RichString_appendChr(str, ' ', width + 1 - c);
|
||||||
|
}
|
||||||
|
|
||||||
void Process_writeField(const Process* this, RichString* str, ProcessField field) {
|
void Process_writeField(const Process* this, RichString* str, ProcessField field) {
|
||||||
char buffer[256]; buffer[255] = '\0';
|
char buffer[256]; buffer[255] = '\0';
|
||||||
int attr = CRT_colors[DEFAULT_COLOR];
|
int attr = CRT_colors[DEFAULT_COLOR];
|
||||||
@ -363,15 +368,13 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
|
|||||||
case USER: {
|
case USER: {
|
||||||
if (Process_getuid != this->st_uid)
|
if (Process_getuid != this->st_uid)
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
attr = CRT_colors[PROCESS_SHADOW];
|
||||||
|
|
||||||
if (this->user) {
|
if (this->user) {
|
||||||
xSnprintf(buffer, n, "%-9s ", this->user);
|
Process_printLeftAlignedField(str, attr, this->user, 9);
|
||||||
} else {
|
return;
|
||||||
xSnprintf(buffer, n, "%-9d ", this->st_uid);
|
|
||||||
}
|
|
||||||
if (buffer[9] != '\0') {
|
|
||||||
buffer[9] = ' ';
|
|
||||||
buffer[10] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xSnprintf(buffer, n, "%-9d ", this->st_uid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -477,14 +480,14 @@ bool Process_sendSignal(Process* this, Arg sgn) {
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
long Process_pidCompare(const void* v1, const void* v2) {
|
int Process_pidCompare(const void* v1, const void* v2) {
|
||||||
const Process* p1 = (const Process*)v1;
|
const Process* p1 = (const Process*)v1;
|
||||||
const Process* p2 = (const Process*)v2;
|
const Process* p2 = (const Process*)v2;
|
||||||
|
|
||||||
return SPACESHIP_NUMBER(p1->pid, p2->pid);
|
return SPACESHIP_NUMBER(p1->pid, p2->pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
long Process_compare(const void* v1, const void* v2) {
|
int Process_compare(const void* v1, const void* v2) {
|
||||||
const Process *p1, *p2;
|
const Process *p1, *p2;
|
||||||
const Settings *settings = ((const Process*)v1)->settings;
|
const Settings *settings = ((const Process*)v1)->settings;
|
||||||
|
|
||||||
@ -498,7 +501,7 @@ long Process_compare(const void* v1, const void* v2) {
|
|||||||
|
|
||||||
ProcessField key = Settings_getActiveSortKey(settings);
|
ProcessField key = Settings_getActiveSortKey(settings);
|
||||||
|
|
||||||
long result = Process_compareByKey(p1, p2, key);
|
int result = Process_compareByKey(p1, p2, key);
|
||||||
|
|
||||||
// Implement tie-breaker (needed to make tree mode more stable)
|
// Implement tie-breaker (needed to make tree mode more stable)
|
||||||
if (!result)
|
if (!result)
|
||||||
@ -507,7 +510,7 @@ long Process_compare(const void* v1, const void* v2) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
long Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key) {
|
int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
10
Process.h
10
Process.h
@ -122,7 +122,7 @@ typedef struct ProcessFieldData_ {
|
|||||||
|
|
||||||
// Implemented in platform-specific code:
|
// Implemented in platform-specific code:
|
||||||
void Process_writeField(const Process* this, RichString* str, ProcessField field);
|
void Process_writeField(const Process* this, RichString* str, ProcessField field);
|
||||||
long Process_compare(const void* v1, const void* v2);
|
int Process_compare(const void* v1, const void* v2);
|
||||||
void Process_delete(Object* cast);
|
void Process_delete(Object* cast);
|
||||||
bool Process_isThread(const Process* this);
|
bool Process_isThread(const Process* this);
|
||||||
extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD];
|
extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD];
|
||||||
@ -131,7 +131,7 @@ extern int Process_pidDigits;
|
|||||||
|
|
||||||
typedef Process*(*Process_New)(const struct Settings_*);
|
typedef Process*(*Process_New)(const struct Settings_*);
|
||||||
typedef void (*Process_WriteField)(const Process*, RichString*, ProcessField);
|
typedef void (*Process_WriteField)(const Process*, RichString*, ProcessField);
|
||||||
typedef long (*Process_CompareByKey)(const Process*, const Process*, ProcessField);
|
typedef int (*Process_CompareByKey)(const Process*, const Process*, ProcessField);
|
||||||
typedef const char* (*Process_GetCommandStr)(const Process*);
|
typedef const char* (*Process_GetCommandStr)(const Process*);
|
||||||
|
|
||||||
typedef struct ProcessClass_ {
|
typedef struct ProcessClass_ {
|
||||||
@ -179,6 +179,8 @@ void Process_fillStarttimeBuffer(Process* this);
|
|||||||
|
|
||||||
void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, int coloring);
|
void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, int coloring);
|
||||||
|
|
||||||
|
void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width);
|
||||||
|
|
||||||
void Process_display(const Object* cast, RichString* out);
|
void Process_display(const Object* cast, RichString* out);
|
||||||
|
|
||||||
void Process_done(Process* this);
|
void Process_done(Process* this);
|
||||||
@ -199,8 +201,8 @@ bool Process_changePriorityBy(Process* this, Arg delta);
|
|||||||
|
|
||||||
bool Process_sendSignal(Process* this, Arg sgn);
|
bool Process_sendSignal(Process* this, Arg sgn);
|
||||||
|
|
||||||
long Process_pidCompare(const void* v1, const void* v2);
|
int Process_pidCompare(const void* v1, const void* v2);
|
||||||
|
|
||||||
long Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key);
|
int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -112,6 +112,13 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RichString_appendWide(header, color, alignedProcessFieldTitle(fields[i]));
|
RichString_appendWide(header, color, alignedProcessFieldTitle(fields[i]));
|
||||||
|
if (key == fields[i] && RichString_getCharVal(*header, RichString_size(header) - 1) == ' ') {
|
||||||
|
header->chlen--; // rewind to override space
|
||||||
|
RichString_appendnWide(header,
|
||||||
|
CRT_colors[PANEL_SELECTION_FOCUS],
|
||||||
|
CRT_treeStr[Settings_getActiveDirection(this->settings) == 1 ? TREE_STR_DESC : TREE_STR_ASC],
|
||||||
|
1);
|
||||||
|
}
|
||||||
if (COMM == fields[i] && settings->showMergedCommand) {
|
if (COMM == fields[i] && settings->showMergedCommand) {
|
||||||
RichString_appendAscii(header, color, "(merged)");
|
RichString_appendAscii(header, color, "(merged)");
|
||||||
}
|
}
|
||||||
@ -141,7 +148,7 @@ void ProcessList_remove(ProcessList* this, Process* p) {
|
|||||||
Process* pp = Hashtable_remove(this->processTable, p->pid);
|
Process* pp = Hashtable_remove(this->processTable, p->pid);
|
||||||
assert(pp == p); (void)pp;
|
assert(pp == p); (void)pp;
|
||||||
|
|
||||||
unsigned int pid = p->pid;
|
pid_t pid = p->pid;
|
||||||
int idx = Vector_indexOf(this->processes, p, Process_pidCompare);
|
int idx = Vector_indexOf(this->processes, p, Process_pidCompare);
|
||||||
assert(idx != -1);
|
assert(idx != -1);
|
||||||
|
|
||||||
@ -149,7 +156,12 @@ void ProcessList_remove(ProcessList* this, Process* p) {
|
|||||||
Vector_remove(this->processes, idx);
|
Vector_remove(this->processes, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Hashtable_get(this->processTable, pid) == NULL); (void)pid;
|
if (this->following != -1 && this->following == pid) {
|
||||||
|
this->following = -1;
|
||||||
|
Panel_setSelectionColor(this->panel, PANEL_SELECTION_FOCUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(Hashtable_get(this->processTable, pid) == NULL);
|
||||||
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
|
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,14 +360,14 @@ static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level,
|
|||||||
Vector_delete(children);
|
Vector_delete(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long ProcessList_treeProcessCompare(const void* v1, const void* v2) {
|
static int ProcessList_treeProcessCompare(const void* v1, const void* v2) {
|
||||||
const Process *p1 = (const Process*)v1;
|
const Process *p1 = (const Process*)v1;
|
||||||
const Process *p2 = (const Process*)v2;
|
const Process *p2 = (const Process*)v2;
|
||||||
|
|
||||||
return SPACESHIP_NUMBER(p1->tree_left, p2->tree_left);
|
return SPACESHIP_NUMBER(p1->tree_left, p2->tree_left);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long ProcessList_treeProcessCompareByPID(const void* v1, const void* v2) {
|
static int ProcessList_treeProcessCompareByPID(const void* v1, const void* v2) {
|
||||||
const Process *p1 = (const Process*)v1;
|
const Process *p1 = (const Process*)v1;
|
||||||
const Process *p2 = (const Process*)v2;
|
const Process *p2 = (const Process*)v2;
|
||||||
|
|
||||||
@ -486,7 +498,6 @@ void ProcessList_rebuildPanel(ProcessList* this) {
|
|||||||
const char* incFilter = this->incFilter;
|
const char* incFilter = this->incFilter;
|
||||||
|
|
||||||
int currPos = Panel_getSelectedIndex(this->panel);
|
int currPos = Panel_getSelectedIndex(this->panel);
|
||||||
pid_t currPid = this->following != -1 ? this->following : 0;
|
|
||||||
int currScrollV = this->panel->scrollV;
|
int currScrollV = this->panel->scrollV;
|
||||||
|
|
||||||
Panel_prune(this->panel);
|
Panel_prune(this->panel);
|
||||||
@ -502,7 +513,7 @@ void ProcessList_rebuildPanel(ProcessList* this) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Panel_set(this->panel, idx, (Object*)p);
|
Panel_set(this->panel, idx, (Object*)p);
|
||||||
if ((this->following == -1 && idx == currPos) || (this->following != -1 && p->pid == currPid)) {
|
if ((this->following == -1 && idx == currPos) || (this->following != -1 && p->pid == this->following)) {
|
||||||
Panel_setSelected(this->panel, idx);
|
Panel_setSelected(this->panel, idx);
|
||||||
this->panel->scrollV = currScrollV;
|
this->panel->scrollV = currScrollV;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ ProcessLocksScreen* ProcessLocksScreen_new(const Process* process) {
|
|||||||
this->pid = process->tgid;
|
this->pid = process->tgid;
|
||||||
else
|
else
|
||||||
this->pid = process->pid;
|
this->pid = process->pid;
|
||||||
return (ProcessLocksScreen*) InfoScreen_init(&this->super, process, NULL, LINES-3, " ID TYPE EXCLUSION READ/WRITE DEVICE:INODE START END FILENAME");
|
return (ProcessLocksScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ID TYPE EXCLUSION READ/WRITE DEVICE:INODE START END FILENAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessLocksScreen_delete(Object* this) {
|
void ProcessLocksScreen_delete(Object* this) {
|
||||||
|
66
RichString.c
66
RichString.c
@ -48,33 +48,35 @@ static void RichString_setLen(RichString* this, int len) {
|
|||||||
|
|
||||||
#ifdef HAVE_LIBNCURSESW
|
#ifdef HAVE_LIBNCURSESW
|
||||||
|
|
||||||
static inline void RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) {
|
static inline int RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||||
wchar_t data[len + 1];
|
wchar_t data[len + 1];
|
||||||
len = mbstowcs(data, data_c, len);
|
len = mbstowcs(data, data_c, len);
|
||||||
if (len < 0)
|
if (len <= 0)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
int newLen = from + len;
|
int newLen = from + len;
|
||||||
RichString_setLen(this, newLen);
|
RichString_setLen(this, newLen);
|
||||||
for (int i = from, j = 0; i < newLen; i++, j++) {
|
for (int i = from, j = 0; i < newLen; i++, j++) {
|
||||||
this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (iswprint(data[j]) ? data[j] : '?') } };
|
this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (iswprint(data[j]) ? data[j] : '?') } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return wcswidth(data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void RichString_writeFromAscii(RichString* this, int attrs, const char* data, int from, int len) {
|
static inline int RichString_writeFromAscii(RichString* this, int attrs, const char* data, int from, int len) {
|
||||||
int newLen = from + len;
|
int newLen = from + len;
|
||||||
RichString_setLen(this, newLen);
|
RichString_setLen(this, newLen);
|
||||||
for (int i = from, j = 0; i < newLen; i++, j++) {
|
for (int i = from, j = 0; i < newLen; i++, j++) {
|
||||||
this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (isprint(data[j]) ? data[j] : '?') } };
|
this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (isprint(data[j]) ? data[j] : '?') } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
|
inline void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) {
|
||||||
cchar_t* ch = this->chptr + start;
|
int end = CLAMP(start + charcount, 0, this->chlen);
|
||||||
finish = CLAMP(finish, 0, this->chlen - 1);
|
for (int i = start; i < end; i++) {
|
||||||
for (int i = start; i <= finish; i++) {
|
this->chptr[i].attr = attrs;
|
||||||
ch->attr = attrs;
|
|
||||||
ch++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,25 +93,25 @@ int RichString_findChar(RichString* this, char c, int start) {
|
|||||||
|
|
||||||
#else /* HAVE_LIBNCURSESW */
|
#else /* HAVE_LIBNCURSESW */
|
||||||
|
|
||||||
static inline void RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) {
|
static inline int RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||||
int newLen = from + len;
|
int newLen = from + len;
|
||||||
RichString_setLen(this, newLen);
|
RichString_setLen(this, newLen);
|
||||||
for (int i = from, j = 0; i < newLen; i++, j++) {
|
for (int i = from, j = 0; i < newLen; i++, j++) {
|
||||||
this->chptr[i] = (((unsigned char)data_c[j]) >= 32 ? ((unsigned char)data_c[j]) : '?') | attrs;
|
this->chptr[i] = (((unsigned char)data_c[j]) >= 32 ? ((unsigned char)data_c[j]) : '?') | attrs;
|
||||||
}
|
}
|
||||||
this->chptr[newLen] = 0;
|
this->chptr[newLen] = 0;
|
||||||
|
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void RichString_writeFromAscii(RichString* this, int attrs, const char* data_c, int from, int len) {
|
static inline int RichString_writeFromAscii(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||||
RichString_writeFromWide(this, attrs, data_c, from, len);
|
return RichString_writeFromWide(this, attrs, data_c, from, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
|
void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) {
|
||||||
chtype* ch = this->chptr + start;
|
int end = CLAMP(start + charcount, 0, this->chlen);
|
||||||
finish = CLAMP(finish, 0, this->chlen - 1);
|
for (int i = start; i < end; i++) {
|
||||||
for (int i = start; i <= finish; i++) {
|
this->chptr[i] = (this->chptr[i] & 0xff) | attrs;
|
||||||
*ch = (*ch & 0xff) | attrs;
|
|
||||||
ch++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,29 +144,29 @@ void RichString_appendChr(RichString* this, char c, int count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RichString_setAttr(RichString* this, int attrs) {
|
void RichString_setAttr(RichString* this, int attrs) {
|
||||||
RichString_setAttrn(this, attrs, 0, this->chlen - 1);
|
RichString_setAttrn(this, attrs, 0, this->chlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichString_appendWide(RichString* this, int attrs, const char* data) {
|
int RichString_appendWide(RichString* this, int attrs, const char* data) {
|
||||||
RichString_writeFromWide(this, attrs, data, this->chlen, strlen(data));
|
return RichString_writeFromWide(this, attrs, data, this->chlen, strlen(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichString_appendnWide(RichString* this, int attrs, const char* data, int len) {
|
int RichString_appendnWide(RichString* this, int attrs, const char* data, int len) {
|
||||||
RichString_writeFromWide(this, attrs, data, this->chlen, len);
|
return RichString_writeFromWide(this, attrs, data, this->chlen, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichString_writeWide(RichString* this, int attrs, const char* data) {
|
int RichString_writeWide(RichString* this, int attrs, const char* data) {
|
||||||
RichString_writeFromWide(this, attrs, data, 0, strlen(data));
|
return RichString_writeFromWide(this, attrs, data, 0, strlen(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichString_appendAscii(RichString* this, int attrs, const char* data) {
|
int RichString_appendAscii(RichString* this, int attrs, const char* data) {
|
||||||
RichString_writeFromAscii(this, attrs, data, this->chlen, strlen(data));
|
return RichString_writeFromAscii(this, attrs, data, this->chlen, strlen(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichString_appendnAscii(RichString* this, int attrs, const char* data, int len) {
|
int RichString_appendnAscii(RichString* this, int attrs, const char* data, int len) {
|
||||||
RichString_writeFromAscii(this, attrs, data, this->chlen, len);
|
return RichString_writeFromAscii(this, attrs, data, this->chlen, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichString_writeAscii(RichString* this, int attrs, const char* data) {
|
int RichString_writeAscii(RichString* this, int attrs, const char* data) {
|
||||||
RichString_writeFromAscii(this, attrs, data, 0, strlen(data));
|
return RichString_writeFromAscii(this, attrs, data, 0, strlen(data));
|
||||||
}
|
}
|
||||||
|
14
RichString.h
14
RichString.h
@ -42,7 +42,7 @@ typedef struct RichString_ {
|
|||||||
int highlightAttr;
|
int highlightAttr;
|
||||||
} RichString;
|
} RichString;
|
||||||
|
|
||||||
void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
|
void RichString_setAttrn(RichString* this, int attrs, int start, int charcount);
|
||||||
|
|
||||||
int RichString_findChar(RichString* this, char c, int start);
|
int RichString_findChar(RichString* this, char c, int start);
|
||||||
|
|
||||||
@ -52,16 +52,16 @@ void RichString_setAttr(RichString* this, int attrs);
|
|||||||
|
|
||||||
void RichString_appendChr(RichString* this, char c, int count);
|
void RichString_appendChr(RichString* this, char c, int count);
|
||||||
|
|
||||||
void RichString_appendWide(RichString* this, int attrs, const char* data);
|
int RichString_appendWide(RichString* this, int attrs, const char* data);
|
||||||
|
|
||||||
void RichString_appendnWide(RichString* this, int attrs, const char* data, int len);
|
int RichString_appendnWide(RichString* this, int attrs, const char* data, int len);
|
||||||
|
|
||||||
void RichString_writeWide(RichString* this, int attrs, const char* data);
|
int RichString_writeWide(RichString* this, int attrs, const char* data);
|
||||||
|
|
||||||
void RichString_appendAscii(RichString* this, int attrs, const char* data);
|
int RichString_appendAscii(RichString* this, int attrs, const char* data);
|
||||||
|
|
||||||
void RichString_appendnAscii(RichString* this, int attrs, const char* data, int len);
|
int RichString_appendnAscii(RichString* this, int attrs, const char* data, int len);
|
||||||
|
|
||||||
void RichString_writeAscii(RichString* this, int attrs, const char* data);
|
int RichString_writeAscii(RichString* this, int attrs, const char* data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -123,8 +123,8 @@ static void ScreenManager_drawPanels(ScreenManager* this, int focus, bool force_
|
|||||||
const int nPanels = this->panelCount;
|
const int nPanels = this->panelCount;
|
||||||
for (int i = 0; i < nPanels; i++) {
|
for (int i = 0; i < nPanels; i++) {
|
||||||
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
||||||
Panel_draw(panel, force_redraw, i == focus, !((panel == this->state->panel) && this->state->hideProcessSelection));
|
Panel_draw(panel, force_redraw, i == focus, !((panel == this->state->panel) && this->state->hideProcessSelection), State_hideFunctionBar(this->state));
|
||||||
mvvline(panel->y, panel->x + panel->w, ' ', panel->h + 1);
|
mvvline(panel->y, panel->x + panel->w, ' ', panel->h + (State_hideFunctionBar(this->state) ? 1 : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
|||||||
|
|
||||||
bool timedOut = true;
|
bool timedOut = true;
|
||||||
bool redraw = true;
|
bool redraw = true;
|
||||||
bool force_redraw = false;
|
bool force_redraw = true;
|
||||||
bool rescan = false;
|
bool rescan = false;
|
||||||
int sortTimeout = 0;
|
int sortTimeout = 0;
|
||||||
int resetSortTimeout = 5;
|
int resetSortTimeout = 5;
|
||||||
|
@ -221,6 +221,8 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo
|
|||||||
} else if (String_eq(option[0], "right_meter_modes")) {
|
} else if (String_eq(option[0], "right_meter_modes")) {
|
||||||
Settings_readMeterModes(this, option[1], 1);
|
Settings_readMeterModes(this, option[1], 1);
|
||||||
didReadMeters = true;
|
didReadMeters = true;
|
||||||
|
} else if (String_eq(option[0], "hide_function_bar")) {
|
||||||
|
this->hideFunctionBar = atoi(option[1]);
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
} else if (String_eq(option[0], "topology_affinity")) {
|
} else if (String_eq(option[0], "topology_affinity")) {
|
||||||
this->topologyAffinity = !!atoi(option[1]);
|
this->topologyAffinity = !!atoi(option[1]);
|
||||||
@ -315,6 +317,7 @@ bool Settings_write(Settings* this) {
|
|||||||
fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0);
|
fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0);
|
||||||
fprintf(fd, "right_meters="); writeMeters(this, fd, 1);
|
fprintf(fd, "right_meters="); writeMeters(this, fd, 1);
|
||||||
fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1);
|
fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1);
|
||||||
|
fprintf(fd, "hide_function_bar=%d\n", (int) this->hideFunctionBar);
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
fprintf(fd, "topology_affinity=%d\n", (int) this->topologyAffinity);
|
fprintf(fd, "topology_affinity=%d\n", (int) this->topologyAffinity);
|
||||||
#endif
|
#endif
|
||||||
@ -352,6 +355,7 @@ Settings* Settings_new(int initialCpuCount) {
|
|||||||
this->findCommInCmdline = true;
|
this->findCommInCmdline = true;
|
||||||
this->stripExeFromCmdline = true;
|
this->stripExeFromCmdline = true;
|
||||||
this->showMergedCommand = false;
|
this->showMergedCommand = false;
|
||||||
|
this->hideFunctionBar = 0;
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
this->topologyAffinity = false;
|
this->topologyAffinity = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,6 +64,7 @@ typedef struct Settings_ {
|
|||||||
bool accountGuestInCPUMeter;
|
bool accountGuestInCPUMeter;
|
||||||
bool headerMargin;
|
bool headerMargin;
|
||||||
bool enableMouse;
|
bool enableMouse;
|
||||||
|
int hideFunctionBar; // 0 - off, 1 - on ESC until next input, 2 - permanently
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
bool topologyAffinity;
|
bool topologyAffinity;
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,7 +19,7 @@ in the source distribution for its full text.
|
|||||||
|
|
||||||
|
|
||||||
Panel* SignalsPanel_new() {
|
Panel* SignalsPanel_new() {
|
||||||
Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem), FunctionBar_newEnterEsc("Send ", "Cancel "));
|
Panel* this = Panel_new(1, 1, 1, 1, Class(ListItem), true, FunctionBar_newEnterEsc("Send ", "Cancel "));
|
||||||
const int defaultSignal = SIGTERM;
|
const int defaultSignal = SIGTERM;
|
||||||
int defaultPosition = 15;
|
int defaultPosition = 15;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
2
Vector.h
2
Vector.h
@ -58,7 +58,7 @@ unsigned int Vector_count(const Vector* this);
|
|||||||
|
|
||||||
#else /* NDEBUG */
|
#else /* NDEBUG */
|
||||||
|
|
||||||
static inline Object* Vector_get(Vector* this, int idx) {
|
static inline Object* Vector_get(const Vector* this, int idx) {
|
||||||
return this->array[idx];
|
return this->array[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
XUtils.c
22
XUtils.c
@ -13,6 +13,7 @@ in the source distribution for its full text.
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -36,9 +37,21 @@ void* xMalloc(size_t size) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* xMallocArray(size_t nmemb, size_t size) {
|
||||||
|
assert(nmemb > 0);
|
||||||
|
assert(size > 0);
|
||||||
|
if (SIZE_MAX / nmemb < size) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
return xMalloc(nmemb * size);
|
||||||
|
}
|
||||||
|
|
||||||
void* xCalloc(size_t nmemb, size_t size) {
|
void* xCalloc(size_t nmemb, size_t size) {
|
||||||
assert(nmemb > 0);
|
assert(nmemb > 0);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
if (SIZE_MAX / nmemb < size) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
void* data = calloc(nmemb, size);
|
void* data = calloc(nmemb, size);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
fail();
|
fail();
|
||||||
@ -56,6 +69,15 @@ void* xRealloc(void* ptr, size_t size) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* xReallocArray(void* ptr, size_t nmemb, size_t size) {
|
||||||
|
assert(nmemb > 0);
|
||||||
|
assert(size > 0);
|
||||||
|
if (SIZE_MAX / nmemb < size) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
return xRealloc(ptr, nmemb * size);
|
||||||
|
}
|
||||||
|
|
||||||
char* String_cat(const char* s1, const char* s2) {
|
char* String_cat(const char* s1, const char* s2) {
|
||||||
const size_t l1 = strlen(s1);
|
const size_t l1 = strlen(s1);
|
||||||
const size_t l2 = strlen(s2);
|
const size_t l2 = strlen(s2);
|
||||||
|
4
XUtils.h
4
XUtils.h
@ -23,10 +23,14 @@ void fail(void) ATTR_NORETURN;
|
|||||||
|
|
||||||
void* xMalloc(size_t size);
|
void* xMalloc(size_t size);
|
||||||
|
|
||||||
|
void* xMallocArray(size_t nmemb, size_t size);
|
||||||
|
|
||||||
void* xCalloc(size_t nmemb, size_t size);
|
void* xCalloc(size_t nmemb, size_t size);
|
||||||
|
|
||||||
void* xRealloc(void* ptr, size_t size);
|
void* xRealloc(void* ptr, size_t size);
|
||||||
|
|
||||||
|
void* xReallocArray(void* ptr, size_t nmemb, size_t size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* String_startsWith gives better performance if strlen(match) can be computed
|
* String_startsWith gives better performance if strlen(match) can be computed
|
||||||
* at compile time (e.g. when they are immutable string literals). :)
|
* at compile time (e.g. when they are immutable string literals). :)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.65)
|
AC_PREREQ(2.65)
|
||||||
AC_INIT([htop],[3.0.4],[htop@groups.io])
|
AC_INIT([htop],[3.0.5],[htop@groups.io])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([htop.c])
|
AC_CONFIG_SRCDIR([htop.c])
|
||||||
AC_CONFIG_AUX_DIR([.])
|
AC_CONFIG_AUX_DIR([.])
|
||||||
|
@ -82,7 +82,7 @@ static void DarwinProcess_writeField(const Process* this, RichString* str, Proce
|
|||||||
RichString_appendWide(str, attr, buffer);
|
RichString_appendWide(str, attr, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long DarwinProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
static int DarwinProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||||
const DarwinProcess* p1 = (const DarwinProcess*)v1;
|
const DarwinProcess* p1 = (const DarwinProcess*)v1;
|
||||||
const DarwinProcess* p2 = (const DarwinProcess*)v2;
|
const DarwinProcess* p2 = (const DarwinProcess*)v2;
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ in the source distribution for its full text.
|
|||||||
|
|
||||||
#include "DarwinProcessList.h"
|
#include "DarwinProcessList.h"
|
||||||
|
|
||||||
#include <err.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <libproc.h>
|
#include <libproc.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -161,7 +160,7 @@ void ProcessList_delete(ProcessList* this) {
|
|||||||
|
|
||||||
static double ticksToNanoseconds(const double ticks) {
|
static double ticksToNanoseconds(const double ticks) {
|
||||||
const double nanos_per_sec = 1e9;
|
const double nanos_per_sec = 1e9;
|
||||||
return ticks / (double) Platform_clockTicksPerSec * Platform_timebaseToNS * nanos_per_sec;
|
return (ticks / Platform_timebaseToNS) * (nanos_per_sec / (double) Platform_clockTicksPerSec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
|
@ -71,14 +71,7 @@ static void DragonFlyBSDProcess_writeField(const Process* this, RichString* str,
|
|||||||
// add Platform-specific fields here
|
// add Platform-specific fields here
|
||||||
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, (fp->kernel ? -1 : this->pid)); break;
|
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, (fp->kernel ? -1 : this->pid)); break;
|
||||||
case JID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, fp->jid); break;
|
case JID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, fp->jid); break;
|
||||||
case JAIL: {
|
case JAIL: Process_printLeftAlignedField(str, attr, fp->jname, 11); return;
|
||||||
xSnprintf(buffer, n, "%-11s ", fp->jname);
|
|
||||||
if (buffer[11] != '\0') {
|
|
||||||
buffer[11] = ' ';
|
|
||||||
buffer[12] = '\0';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
Process_writeField(this, str, field);
|
Process_writeField(this, str, field);
|
||||||
return;
|
return;
|
||||||
@ -86,7 +79,7 @@ static void DragonFlyBSDProcess_writeField(const Process* this, RichString* str,
|
|||||||
RichString_appendWide(str, attr, buffer);
|
RichString_appendWide(str, attr, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long DragonFlyBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
static int DragonFlyBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||||
const DragonFlyBSDProcess* p1 = (const DragonFlyBSDProcess*)v1;
|
const DragonFlyBSDProcess* p1 = (const DragonFlyBSDProcess*)v1;
|
||||||
const DragonFlyBSDProcess* p2 = (const DragonFlyBSDProcess*)v2;
|
const DragonFlyBSDProcess* p2 = (const DragonFlyBSDProcess*)v2;
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ in the source distribution for its full text.
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
#include <err.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -112,7 +111,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
|||||||
|
|
||||||
dfpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
|
dfpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
|
||||||
if (dfpl->kd == NULL) {
|
if (dfpl->kd == NULL) {
|
||||||
errx(1, "kvm_open: %s", errbuf);
|
CRT_fatalError("kvm_openfiles() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
return pl;
|
return pl;
|
||||||
@ -294,25 +293,20 @@ static inline void DragonFlyBSDProcessList_scanJails(DragonFlyBSDProcessList* df
|
|||||||
char* nextpos;
|
char* nextpos;
|
||||||
|
|
||||||
if (sysctlbyname("jail.list", NULL, &len, NULL, 0) == -1) {
|
if (sysctlbyname("jail.list", NULL, &len, NULL, 0) == -1) {
|
||||||
fprintf(stderr, "initial sysctlbyname / jail.list failed\n");
|
CRT_fatalError("initial sysctlbyname / jail.list failed");
|
||||||
exit(3);
|
|
||||||
}
|
}
|
||||||
retry:
|
retry:
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
jls = xMalloc(len);
|
jls = xMalloc(len);
|
||||||
if (jls == NULL) {
|
|
||||||
fprintf(stderr, "xMalloc failed\n");
|
|
||||||
exit(4);
|
|
||||||
}
|
|
||||||
if (sysctlbyname("jail.list", jls, &len, NULL, 0) == -1) {
|
if (sysctlbyname("jail.list", jls, &len, NULL, 0) == -1) {
|
||||||
if (errno == ENOMEM) {
|
if (errno == ENOMEM) {
|
||||||
free(jls);
|
free(jls);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "sysctlbyname / jail.list failed\n");
|
CRT_fatalError("sysctlbyname / jail.list failed");
|
||||||
exit(5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dfpl->jails) {
|
if (dfpl->jails) {
|
||||||
|
@ -71,14 +71,9 @@ static void FreeBSDProcess_writeField(const Process* this, RichString* str, Proc
|
|||||||
switch (field) {
|
switch (field) {
|
||||||
// add FreeBSD-specific fields here
|
// add FreeBSD-specific fields here
|
||||||
case JID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, fp->jid); break;
|
case JID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, fp->jid); break;
|
||||||
case JAIL: {
|
case JAIL:
|
||||||
xSnprintf(buffer, n, "%-11s ", fp->jname);
|
Process_printLeftAlignedField(str, attr, fp->jname ? fp->jname : "N/A", 11);
|
||||||
if (buffer[11] != '\0') {
|
return;
|
||||||
buffer[11] = ' ';
|
|
||||||
buffer[12] = '\0';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TTY_NR:
|
case TTY_NR:
|
||||||
if (fp->ttyPath) {
|
if (fp->ttyPath) {
|
||||||
if (fp->ttyPath == nodevStr)
|
if (fp->ttyPath == nodevStr)
|
||||||
@ -96,7 +91,7 @@ static void FreeBSDProcess_writeField(const Process* this, RichString* str, Proc
|
|||||||
RichString_appendWide(str, attr, buffer);
|
RichString_appendWide(str, attr, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long FreeBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
static int FreeBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||||
const FreeBSDProcess* p1 = (const FreeBSDProcess*)v1;
|
const FreeBSDProcess* p1 = (const FreeBSDProcess*)v1;
|
||||||
const FreeBSDProcess* p2 = (const FreeBSDProcess*)v2;
|
const FreeBSDProcess* p2 = (const FreeBSDProcess*)v2;
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ in the source distribution for its full text.
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <err.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -145,7 +144,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
|||||||
|
|
||||||
fpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
|
fpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
|
||||||
if (fpl->kd == NULL) {
|
if (fpl->kd == NULL) {
|
||||||
errx(1, "kvm_open: %s", errbuf);
|
CRT_fatalError("kvm_openfiles() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
fpl->ttys = Hashtable_new(20, true);
|
fpl->ttys = Hashtable_new(20, true);
|
||||||
@ -415,7 +414,7 @@ static char* FreeBSDProcessList_readJailName(const struct kinfo_proc* kproc) {
|
|||||||
char* jname = NULL;
|
char* jname = NULL;
|
||||||
char jnamebuf[MAXHOSTNAMELEN];
|
char jnamebuf[MAXHOSTNAMELEN];
|
||||||
|
|
||||||
if (kproc->ki_jid != 0 ) {
|
if (kproc->ki_jid != 0) {
|
||||||
struct iovec jiov[6];
|
struct iovec jiov[6];
|
||||||
|
|
||||||
memset(jnamebuf, 0, sizeof(jnamebuf));
|
memset(jnamebuf, 0, sizeof(jnamebuf));
|
||||||
|
10
htop.1.in
10
htop.1.in
@ -42,7 +42,8 @@ Display a help message and exit
|
|||||||
Show only the given PIDs
|
Show only the given PIDs
|
||||||
.TP
|
.TP
|
||||||
\fB\-s \-\-sort\-key COLUMN\fR
|
\fB\-s \-\-sort\-key COLUMN\fR
|
||||||
Sort by this column (use \-\-sort\-key help for a column list)
|
Sort by this column (use \-\-sort\-key help for a column list).
|
||||||
|
This will force a list view unless you specify -t at the same time.
|
||||||
.TP
|
.TP
|
||||||
\fB\-u \-\-user=USERNAME\fR
|
\fB\-u \-\-user=USERNAME\fR
|
||||||
Show only the processes of a given user
|
Show only the processes of a given user
|
||||||
@ -57,7 +58,8 @@ Disable support of mouse control
|
|||||||
Output version information and exit
|
Output version information and exit
|
||||||
.TP
|
.TP
|
||||||
\fB\-t \-\-tree
|
\fB\-t \-\-tree
|
||||||
Show processes in tree view
|
Show processes in tree view. This can be used to force a tree view when
|
||||||
|
requesting a sort order with -s.
|
||||||
.TP
|
.TP
|
||||||
\fB\-H \-\-highlight-changes=DELAY\fR
|
\fB\-H \-\-highlight-changes=DELAY\fR
|
||||||
Highlight new and old processes
|
Highlight new and old processes
|
||||||
@ -135,6 +137,7 @@ select which columns are displayed, in which order.
|
|||||||
Incrementally search the command lines of all the displayed processes. The
|
Incrementally search the command lines of all the displayed processes. The
|
||||||
currently selected (highlighted) command will update as you type. While in
|
currently selected (highlighted) command will update as you type. While in
|
||||||
search mode, pressing F3 will cycle through matching occurrences.
|
search mode, pressing F3 will cycle through matching occurrences.
|
||||||
|
Pressing Shift-F3 will cycle backwards.
|
||||||
|
|
||||||
Alternatively the search can be started by simply typing the command
|
Alternatively the search can be started by simply typing the command
|
||||||
you are looking for, although for the first character normal key
|
you are looking for, although for the first character normal key
|
||||||
@ -184,6 +187,9 @@ Set CPU affinity: mark which CPUs a process is allowed to use.
|
|||||||
.B u
|
.B u
|
||||||
Show only processes owned by a specified user.
|
Show only processes owned by a specified user.
|
||||||
.TP
|
.TP
|
||||||
|
.B N
|
||||||
|
Sort by PID.
|
||||||
|
.TP
|
||||||
.B M
|
.B M
|
||||||
Sort by memory usage (top compatibility key).
|
Sort by memory usage (top compatibility key).
|
||||||
.TP
|
.TP
|
||||||
|
9
htop.c
9
htop.c
@ -49,8 +49,8 @@ static void printHelpFlag(void) {
|
|||||||
"-H --highlight-changes[=DELAY] Highlight new and old processes\n"
|
"-H --highlight-changes[=DELAY] Highlight new and old processes\n"
|
||||||
"-M --no-mouse Disable the mouse\n"
|
"-M --no-mouse Disable the mouse\n"
|
||||||
"-p --pid=PID[,PID,PID...] Show only the given PIDs\n"
|
"-p --pid=PID[,PID,PID...] Show only the given PIDs\n"
|
||||||
"-s --sort-key=COLUMN Sort by COLUMN (try --sort-key=help for a list)\n"
|
"-s --sort-key=COLUMN Sort by COLUMN in list view (try --sort-key=help for a list)\n"
|
||||||
"-t --tree Show the tree view by default\n"
|
"-t --tree Show the tree view (can be combined with -s)\n"
|
||||||
"-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
|
"-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
|
||||||
"-U --no-unicode Do not use unicode but plain ASCII\n"
|
"-U --no-unicode Do not use unicode but plain ASCII\n"
|
||||||
"-V --version Print version info\n"
|
"-V --version Print version info\n"
|
||||||
@ -93,7 +93,7 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
|||||||
.highlightDelaySecs = -1,
|
.highlightDelaySecs = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct option long_opts[] =
|
const struct option long_opts[] =
|
||||||
{
|
{
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"version", no_argument, 0, 'V'},
|
{"version", no_argument, 0, 'V'},
|
||||||
@ -204,6 +204,7 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
case 'F': {
|
case 'F': {
|
||||||
assert(optarg);
|
assert(optarg);
|
||||||
|
free(flags.commFilter);
|
||||||
flags.commFilter = xStrdup(optarg);
|
flags.commFilter = xStrdup(optarg);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -313,8 +314,6 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
MainPanel_updateTreeFunctions(panel, settings->treeView);
|
MainPanel_updateTreeFunctions(panel, settings->treeView);
|
||||||
|
|
||||||
ProcessList_printHeader(pl, Panel_getHeader((Panel*)panel));
|
|
||||||
|
|
||||||
State state = {
|
State state = {
|
||||||
.settings = settings,
|
.settings = settings,
|
||||||
.ut = ut,
|
.ut = ut,
|
||||||
|
@ -17,7 +17,7 @@ in the source distribution for its full text.
|
|||||||
|
|
||||||
|
|
||||||
Panel* IOPriorityPanel_new(IOPriority currPrio) {
|
Panel* IOPriorityPanel_new(IOPriority currPrio) {
|
||||||
Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem), FunctionBar_newEnterEsc("Set ", "Cancel "));
|
Panel* this = Panel_new(1, 1, 1, 1, Class(ListItem), true, FunctionBar_newEnterEsc("Set ", "Cancel "));
|
||||||
|
|
||||||
Panel_setHeader(this, "IO Priority:");
|
Panel_setHeader(this, "IO Priority:");
|
||||||
Panel_add(this, (Object*) ListItem_new("None (based on nice)", IOPriority_None));
|
Panel_add(this, (Object*) ListItem_new("None (based on nice)", IOPriority_None));
|
||||||
|
@ -23,13 +23,15 @@ static void* dlopenHandle = NULL;
|
|||||||
|
|
||||||
int LibSensors_init(FILE* input) {
|
int LibSensors_init(FILE* input) {
|
||||||
if (!dlopenHandle) {
|
if (!dlopenHandle) {
|
||||||
|
/* Find the unversioned libsensors.so (symlink) and prefer that, but Debian has .so.5 and Fedora .so.4 without
|
||||||
|
matching symlinks (unless people install the -dev packages) */
|
||||||
dlopenHandle = dlopen("libsensors.so", RTLD_LAZY);
|
dlopenHandle = dlopen("libsensors.so", RTLD_LAZY);
|
||||||
if (!dlopenHandle) {
|
if (!dlopenHandle)
|
||||||
/* Debian contains no unversioned .so in libsensors5, only in the -dev package, so work around that: */
|
|
||||||
dlopenHandle = dlopen("libsensors.so.5", RTLD_LAZY);
|
dlopenHandle = dlopen("libsensors.so.5", RTLD_LAZY);
|
||||||
if (!dlopenHandle)
|
if (!dlopenHandle)
|
||||||
goto dlfailure;
|
dlopenHandle = dlopen("libsensors.so.4", RTLD_LAZY);
|
||||||
}
|
if (!dlopenHandle)
|
||||||
|
goto dlfailure;
|
||||||
|
|
||||||
/* Clear any errors */
|
/* Clear any errors */
|
||||||
dlerror();
|
dlerror();
|
||||||
@ -84,7 +86,10 @@ void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) {
|
|||||||
for (const sensors_chip_name *chip = sym_sensors_get_detected_chips(NULL, &n); chip; chip = sym_sensors_get_detected_chips(NULL, &n)) {
|
for (const sensors_chip_name *chip = sym_sensors_get_detected_chips(NULL, &n); chip; chip = sym_sensors_get_detected_chips(NULL, &n)) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sym_sensors_snprintf_chip_name(buffer, sizeof(buffer), chip);
|
sym_sensors_snprintf_chip_name(buffer, sizeof(buffer), chip);
|
||||||
if (!String_startsWith(buffer, "coretemp") && !String_startsWith(buffer, "cpu_thermal"))
|
if (!String_startsWith(buffer, "coretemp") &&
|
||||||
|
!String_startsWith(buffer, "cpu_thermal") &&
|
||||||
|
!String_startsWith(buffer, "k10temp") &&
|
||||||
|
!String_startsWith(buffer, "zenpower"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int m = 0;
|
int m = 0;
|
||||||
@ -102,6 +107,8 @@ void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) {
|
|||||||
} else if (String_startsWith(label, "temp")) {
|
} else if (String_startsWith(label, "temp")) {
|
||||||
/* Raspberry Pi has only temp1 */
|
/* Raspberry Pi has only temp1 */
|
||||||
tempId = 0;
|
tempId = 0;
|
||||||
|
} else if (String_startsWith(label, "Tdie")) {
|
||||||
|
tempId = 0;
|
||||||
} else if (String_startsWith(label, "Core ")) {
|
} else if (String_startsWith(label, "Core ")) {
|
||||||
tempId = 1 + atoi(label + strlen("Core "));
|
tempId = 1 + atoi(label + strlen("Core "));
|
||||||
} else {
|
} else {
|
||||||
|
@ -88,9 +88,9 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
|||||||
[OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, },
|
[OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, },
|
||||||
[IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, },
|
[IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, },
|
||||||
#ifdef HAVE_DELAYACCT
|
#ifdef HAVE_DELAYACCT
|
||||||
[PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = 0, },
|
[PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, },
|
||||||
[PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = 0, },
|
[PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, },
|
||||||
[PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = 0, },
|
[PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, },
|
||||||
#endif
|
#endif
|
||||||
[M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it.", .flags = PROCESS_FLAG_LINUX_SMAPS, },
|
[M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it.", .flags = PROCESS_FLAG_LINUX_SMAPS, },
|
||||||
[M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, },
|
[M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, },
|
||||||
@ -198,12 +198,11 @@ static bool findCommInCmdline(const char *comm, const char *cmdline, int cmdline
|
|||||||
/* Try to find procComm in tokenized cmdline - this might in rare cases
|
/* Try to find procComm in tokenized cmdline - this might in rare cases
|
||||||
* mis-identify a string or fail, if comm or cmdline had been unsuitably
|
* mis-identify a string or fail, if comm or cmdline had been unsuitably
|
||||||
* modified by the process */
|
* modified by the process */
|
||||||
const char *token;
|
|
||||||
const char *tokenBase;
|
const char *tokenBase;
|
||||||
size_t tokenLen;
|
size_t tokenLen;
|
||||||
const size_t commLen = strlen(comm);
|
const size_t commLen = strlen(comm);
|
||||||
|
|
||||||
for (token = cmdline + cmdlineBasenameOffset; *token; ) {
|
for (const char *token = cmdline + cmdlineBasenameOffset; *token; ) {
|
||||||
for (tokenBase = token; *token && *token != '\n'; ++token) {
|
for (tokenBase = token; *token && *token != '\n'; ++token) {
|
||||||
if (*token == '/') {
|
if (*token == '/') {
|
||||||
tokenBase = token + 1;
|
tokenBase = token + 1;
|
||||||
@ -529,30 +528,30 @@ static void LinuxProcess_writeCommand(const Process* this, int attr, int baseAtt
|
|||||||
if (!lp->mergedCommand.separateComm && commStart == baseStart && highlightBaseName) {
|
if (!lp->mergedCommand.separateComm && commStart == baseStart && highlightBaseName) {
|
||||||
/* If it was matched with procExe's basename, make it bold if needed */
|
/* If it was matched with procExe's basename, make it bold if needed */
|
||||||
if (commEnd > baseEnd) {
|
if (commEnd > baseEnd) {
|
||||||
RichString_setAttrn(str, A_BOLD | baseAttr, baseStart, baseEnd - 1);
|
RichString_setAttrn(str, A_BOLD | baseAttr, baseStart, baseEnd - baseStart);
|
||||||
RichString_setAttrn(str, A_BOLD | commAttr, baseEnd, commEnd - 1);
|
RichString_setAttrn(str, A_BOLD | commAttr, baseEnd, commEnd - baseEnd);
|
||||||
} else if (commEnd < baseEnd) {
|
} else if (commEnd < baseEnd) {
|
||||||
RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - 1);
|
RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - commStart);
|
||||||
RichString_setAttrn(str, A_BOLD | baseAttr, commEnd, baseEnd - 1);
|
RichString_setAttrn(str, A_BOLD | baseAttr, commEnd, baseEnd - commEnd);
|
||||||
} else {
|
} else {
|
||||||
// Actually should be highlighted commAttr, but marked baseAttr to reduce visual noise
|
// Actually should be highlighted commAttr, but marked baseAttr to reduce visual noise
|
||||||
RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - 1);
|
RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - commStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
baseStart = baseEnd;
|
baseStart = baseEnd;
|
||||||
} else {
|
} else {
|
||||||
RichString_setAttrn(str, commAttr, commStart, commEnd - 1);
|
RichString_setAttrn(str, commAttr, commStart, commEnd - commStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baseStart < baseEnd && highlightBaseName) {
|
if (baseStart < baseEnd && highlightBaseName) {
|
||||||
RichString_setAttrn(str, baseAttr, baseStart, baseEnd - 1);
|
RichString_setAttrn(str, baseAttr, baseStart, baseEnd - baseStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc->sep1)
|
if (mc->sep1)
|
||||||
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep1, strStart + mc->sep1);
|
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep1, 1);
|
||||||
if (mc->sep2)
|
if (mc->sep2)
|
||||||
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep2, strStart + mc->sep2);
|
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LinuxProcess_writeCommandField(const Process *this, RichString *str, char *buffer, int n, int attr) {
|
static void LinuxProcess_writeCommandField(const Process *this, RichString *str, char *buffer, int n, int attr) {
|
||||||
@ -708,39 +707,46 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case PROC_COMM: {
|
case PROC_COMM: {
|
||||||
|
const char* procComm;
|
||||||
if (lp->procComm) {
|
if (lp->procComm) {
|
||||||
attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM];
|
attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM];
|
||||||
/* 15 being (TASK_COMM_LEN - 1) */
|
procComm = lp->procComm;
|
||||||
xSnprintf(buffer, n, "%-15.15s ", lp->procComm);
|
|
||||||
} else {
|
} else {
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
attr = CRT_colors[PROCESS_SHADOW];
|
||||||
xSnprintf(buffer, n, "%-15.15s ", Process_isKernelThread(lp) ? kthreadID : "N/A");
|
procComm = Process_isKernelThread(lp) ? kthreadID : "N/A";
|
||||||
}
|
}
|
||||||
break;
|
/* 15 being (TASK_COMM_LEN - 1) */
|
||||||
|
Process_printLeftAlignedField(str, attr, procComm, 15);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case PROC_EXE: {
|
case PROC_EXE: {
|
||||||
|
const char* procExe;
|
||||||
if (lp->procExe) {
|
if (lp->procExe) {
|
||||||
attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_BASENAME : PROCESS_BASENAME];
|
attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_BASENAME : PROCESS_BASENAME];
|
||||||
if (lp->procExeDeleted)
|
if (lp->procExeDeleted)
|
||||||
attr = CRT_colors[FAILED_READ];
|
attr = CRT_colors[FAILED_READ];
|
||||||
xSnprintf(buffer, n, "%-15.15s ", lp->procExe + lp->procExeBasenameOffset);
|
procExe = lp->procExe + lp->procExeBasenameOffset;
|
||||||
} else {
|
} else {
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
attr = CRT_colors[PROCESS_SHADOW];
|
||||||
xSnprintf(buffer, n, "%-15.15s ", Process_isKernelThread(lp) ? kthreadID : "N/A");
|
procExe = Process_isKernelThread(lp) ? kthreadID : "N/A";
|
||||||
}
|
}
|
||||||
break;
|
Process_printLeftAlignedField(str, attr, procExe, 15);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case CWD:
|
case CWD: {
|
||||||
|
const char* cwd;
|
||||||
if (!lp->cwd) {
|
if (!lp->cwd) {
|
||||||
xSnprintf(buffer, n, "%-25s ", "N/A");
|
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
attr = CRT_colors[PROCESS_SHADOW];
|
||||||
|
cwd = "N/A";
|
||||||
} else if (String_startsWith(lp->cwd, "/proc/") && strstr(lp->cwd, " (deleted)") != NULL) {
|
} else if (String_startsWith(lp->cwd, "/proc/") && strstr(lp->cwd, " (deleted)") != NULL) {
|
||||||
xSnprintf(buffer, n, "%-25s ", "main thread terminated");
|
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
attr = CRT_colors[PROCESS_SHADOW];
|
||||||
|
cwd = "main thread terminated";
|
||||||
} else {
|
} else {
|
||||||
xSnprintf(buffer, n, "%-25.25s ", lp->cwd);
|
cwd = lp->cwd;
|
||||||
}
|
}
|
||||||
break;
|
Process_printLeftAlignedField(str, attr, cwd, 25);
|
||||||
|
return;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Process_writeField(this, str, field);
|
Process_writeField(this, str, field);
|
||||||
return;
|
return;
|
||||||
@ -748,7 +754,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
|
|||||||
RichString_appendWide(str, attr, buffer);
|
RichString_appendWide(str, attr, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long LinuxProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||||
const LinuxProcess* p1 = (const LinuxProcess*)v1;
|
const LinuxProcess* p1 = (const LinuxProcess*)v1;
|
||||||
const LinuxProcess* p2 = (const LinuxProcess*)v2;
|
const LinuxProcess* p2 = (const LinuxProcess*)v2;
|
||||||
|
|
||||||
|
@ -18,16 +18,17 @@ in the source distribution for its full text.
|
|||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
|
|
||||||
#define PROCESS_FLAG_LINUX_IOPRIO 0x00000100
|
#define PROCESS_FLAG_LINUX_IOPRIO 0x00000100
|
||||||
#define PROCESS_FLAG_LINUX_OPENVZ 0x00000200
|
#define PROCESS_FLAG_LINUX_OPENVZ 0x00000200
|
||||||
#define PROCESS_FLAG_LINUX_VSERVER 0x00000400
|
#define PROCESS_FLAG_LINUX_VSERVER 0x00000400
|
||||||
#define PROCESS_FLAG_LINUX_CGROUP 0x00000800
|
#define PROCESS_FLAG_LINUX_CGROUP 0x00000800
|
||||||
#define PROCESS_FLAG_LINUX_OOM 0x00001000
|
#define PROCESS_FLAG_LINUX_OOM 0x00001000
|
||||||
#define PROCESS_FLAG_LINUX_SMAPS 0x00002000
|
#define PROCESS_FLAG_LINUX_SMAPS 0x00002000
|
||||||
#define PROCESS_FLAG_LINUX_CTXT 0x00004000
|
#define PROCESS_FLAG_LINUX_CTXT 0x00004000
|
||||||
#define PROCESS_FLAG_LINUX_SECATTR 0x00008000
|
#define PROCESS_FLAG_LINUX_SECATTR 0x00008000
|
||||||
#define PROCESS_FLAG_LINUX_LRS_FIX 0x00010000
|
#define PROCESS_FLAG_LINUX_LRS_FIX 0x00010000
|
||||||
#define PROCESS_FLAG_LINUX_CWD 0x00020000
|
#define PROCESS_FLAG_LINUX_CWD 0x00020000
|
||||||
|
#define PROCESS_FLAG_LINUX_DELAYACCT 0x00040000
|
||||||
|
|
||||||
|
|
||||||
/* LinuxProcessMergedCommand is populated by LinuxProcess_makeCommandStr: It
|
/* LinuxProcessMergedCommand is populated by LinuxProcess_makeCommandStr: It
|
||||||
|
@ -102,7 +102,7 @@ static void LinuxProcessList_initTtyDrivers(LinuxProcessList* this) {
|
|||||||
|
|
||||||
int numDrivers = 0;
|
int numDrivers = 0;
|
||||||
int allocd = 10;
|
int allocd = 10;
|
||||||
ttyDrivers = xMalloc(sizeof(TtyDriver) * allocd);
|
ttyDrivers = xMallocArray(allocd, sizeof(TtyDriver));
|
||||||
char* at = buf;
|
char* at = buf;
|
||||||
while (*at != '\0') {
|
while (*at != '\0') {
|
||||||
at = strchr(at, ' '); // skip first token
|
at = strchr(at, ' '); // skip first token
|
||||||
@ -136,7 +136,7 @@ static void LinuxProcessList_initTtyDrivers(LinuxProcessList* this) {
|
|||||||
numDrivers++;
|
numDrivers++;
|
||||||
if (numDrivers == allocd) {
|
if (numDrivers == allocd) {
|
||||||
allocd += 10;
|
allocd += 10;
|
||||||
ttyDrivers = xRealloc(ttyDrivers, sizeof(TtyDriver) * allocd);
|
ttyDrivers = xReallocArray(ttyDrivers, allocd, sizeof(TtyDriver));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
numDrivers++;
|
numDrivers++;
|
||||||
@ -208,10 +208,6 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
|||||||
ProcessList_init(pl, Class(LinuxProcess), usersTable, pidMatchList, userId);
|
ProcessList_init(pl, Class(LinuxProcess), usersTable, pidMatchList, userId);
|
||||||
LinuxProcessList_initTtyDrivers(this);
|
LinuxProcessList_initTtyDrivers(this);
|
||||||
|
|
||||||
#ifdef HAVE_DELAYACCT
|
|
||||||
LinuxProcessList_initNetlinkSocket(this);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Initialize page size
|
// Initialize page size
|
||||||
pageSize = sysconf(_SC_PAGESIZE);
|
pageSize = sysconf(_SC_PAGESIZE);
|
||||||
if (pageSize == -1)
|
if (pageSize == -1)
|
||||||
@ -488,7 +484,7 @@ static inline uint64_t fast_strtoull_hex(char **str, int maxlen) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED hkey_t key, void* value, void* data) {
|
static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED ht_key_t key, void* value, void* data) {
|
||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -955,12 +951,19 @@ static int handleNetlinkMsg(struct nl_msg* nlmsg, void* linuxProcess) {
|
|||||||
static void LinuxProcessList_readDelayAcctData(LinuxProcessList* this, LinuxProcess* process) {
|
static void LinuxProcessList_readDelayAcctData(LinuxProcessList* this, LinuxProcess* process) {
|
||||||
struct nl_msg* msg;
|
struct nl_msg* msg;
|
||||||
|
|
||||||
|
if (!this->netlink_socket) {
|
||||||
|
LinuxProcessList_initNetlinkSocket(this);
|
||||||
|
if (!this->netlink_socket) {
|
||||||
|
goto delayacct_failure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (nl_socket_modify_cb(this->netlink_socket, NL_CB_VALID, NL_CB_CUSTOM, handleNetlinkMsg, process) < 0) {
|
if (nl_socket_modify_cb(this->netlink_socket, NL_CB_VALID, NL_CB_CUSTOM, handleNetlinkMsg, process) < 0) {
|
||||||
return;
|
goto delayacct_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (msg = nlmsg_alloc())) {
|
if (! (msg = nlmsg_alloc())) {
|
||||||
return;
|
goto delayacct_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, this->netlink_family, 0, NLM_F_REQUEST, TASKSTATS_CMD_GET, TASKSTATS_VERSION)) {
|
if (! genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, this->netlink_family, 0, NLM_F_REQUEST, TASKSTATS_CMD_GET, TASKSTATS_VERSION)) {
|
||||||
@ -972,15 +975,19 @@ static void LinuxProcessList_readDelayAcctData(LinuxProcessList* this, LinuxProc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nl_send_sync(this->netlink_socket, msg) < 0) {
|
if (nl_send_sync(this->netlink_socket, msg) < 0) {
|
||||||
process->swapin_delay_percent = NAN;
|
goto delayacct_failure;
|
||||||
process->blkio_delay_percent = NAN;
|
|
||||||
process->cpu_delay_percent = NAN;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nl_recvmsgs_default(this->netlink_socket) < 0) {
|
if (nl_recvmsgs_default(this->netlink_socket) < 0) {
|
||||||
return;
|
goto delayacct_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
delayacct_failure:
|
||||||
|
process->swapin_delay_percent = NAN;
|
||||||
|
process->blkio_delay_percent = NAN;
|
||||||
|
process->cpu_delay_percent = NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1419,7 +1426,9 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DELAYACCT
|
#ifdef HAVE_DELAYACCT
|
||||||
LinuxProcessList_readDelayAcctData(this, lp);
|
if (settings->flags & PROCESS_FLAG_LINUX_DELAYACCT) {
|
||||||
|
LinuxProcessList_readDelayAcctData(this, lp);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (settings->flags & PROCESS_FLAG_LINUX_CGROUP) {
|
if (settings->flags & PROCESS_FLAG_LINUX_CGROUP) {
|
||||||
@ -1793,7 +1802,9 @@ static void scanCPUFreqencyFromCPUinfo(LinuxProcessList* this) {
|
|||||||
continue;
|
continue;
|
||||||
} else if (
|
} else if (
|
||||||
(sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
|
(sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
|
||||||
(sscanf(buffer, "cpu MHz: %lf", &frequency) == 1)
|
(sscanf(buffer, "cpu MHz: %lf", &frequency) == 1) ||
|
||||||
|
(sscanf(buffer, "clock : %lfMHz", &frequency) == 1) ||
|
||||||
|
(sscanf(buffer, "clock: %lfMHz", &frequency) == 1)
|
||||||
) {
|
) {
|
||||||
if (cpuid < 0 || cpuid > (cpus - 1)) {
|
if (cpuid < 0 || cpuid > (cpus - 1)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -202,7 +202,7 @@ static void OpenBSDProcess_writeField(const Process* this, RichString* str, Proc
|
|||||||
RichString_appendWide(str, attr, buffer);
|
RichString_appendWide(str, attr, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long OpenBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
static int OpenBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||||
const OpenBSDProcess* p1 = (const OpenBSDProcess*)v1;
|
const OpenBSDProcess* p1 = (const OpenBSDProcess*)v1;
|
||||||
const OpenBSDProcess* p2 = (const OpenBSDProcess*)v2;
|
const OpenBSDProcess* p2 = (const OpenBSDProcess*)v2;
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ in the source distribution for its full text.
|
|||||||
|
|
||||||
#include "OpenBSDProcessList.h"
|
#include "OpenBSDProcessList.h"
|
||||||
|
|
||||||
#include <err.h>
|
|
||||||
#include <kvm.h>
|
#include <kvm.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -57,11 +56,11 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
|||||||
|
|
||||||
size = sizeof(fscale);
|
size = sizeof(fscale);
|
||||||
if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) {
|
if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) {
|
||||||
err(1, "fscale sysctl call failed");
|
CRT_fatalError("fscale sysctl call failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pageSize = sysconf(_SC_PAGESIZE)) == -1)
|
if ((pageSize = sysconf(_SC_PAGESIZE)) == -1)
|
||||||
err(1, "pagesize sysconf call failed");
|
CRT_fatalError("pagesize sysconf call failed");
|
||||||
pageSizeKB = pageSize / ONE_K;
|
pageSizeKB = pageSize / ONE_K;
|
||||||
|
|
||||||
for (int i = 0; i <= pl->cpuCount; i++) {
|
for (int i = 0; i <= pl->cpuCount; i++) {
|
||||||
@ -72,7 +71,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
|||||||
|
|
||||||
opl->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
|
opl->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
|
||||||
if (opl->kd == NULL) {
|
if (opl->kd == NULL) {
|
||||||
errx(1, "kvm_open: %s", errbuf);
|
CRT_fatalError("kvm_openfiles() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
return pl;
|
return pl;
|
||||||
@ -97,7 +96,7 @@ static void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
|||||||
size_t size_uvmexp = sizeof(uvmexp);
|
size_t size_uvmexp = sizeof(uvmexp);
|
||||||
|
|
||||||
if (sysctl(uvmexp_mib, 2, &uvmexp, &size_uvmexp, NULL, 0) < 0) {
|
if (sysctl(uvmexp_mib, 2, &uvmexp, &size_uvmexp, NULL, 0) < 0) {
|
||||||
err(1, "uvmexp sysctl call failed");
|
CRT_fatalError("uvmexp sysctl call failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
pl->totalMem = uvmexp.npages * pageSizeKB;
|
pl->totalMem = uvmexp.npages * pageSizeKB;
|
||||||
@ -109,7 +108,7 @@ static void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
|||||||
size_t size_bcstats = sizeof(bcstats);
|
size_t size_bcstats = sizeof(bcstats);
|
||||||
|
|
||||||
if (sysctl(bcache_mib, 3, &bcstats, &size_bcstats, NULL, 0) < 0) {
|
if (sysctl(bcache_mib, 3, &bcstats, &size_bcstats, NULL, 0) < 0) {
|
||||||
err(1, "cannot get vfs.bcachestat");
|
CRT_fatalError("cannot get vfs.bcachestat");
|
||||||
}
|
}
|
||||||
|
|
||||||
pl->cachedMem = bcstats.numbufpages * pageSizeKB;
|
pl->cachedMem = bcstats.numbufpages * pageSizeKB;
|
||||||
|
@ -205,7 +205,7 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
|||||||
|
|
||||||
percent = isnan(percent) ? 0.0 : CLAMP(percent, 0.0, 100.0);
|
percent = isnan(percent) ? 0.0 : CLAMP(percent, 0.0, 100.0);
|
||||||
|
|
||||||
v[CPU_METER_FREQUENCY] = NAN;
|
v[CPU_METER_FREQUENCY] = cpuData->frequency;
|
||||||
v[CPU_METER_TEMPERATURE] = NAN;
|
v[CPU_METER_TEMPERATURE] = NAN;
|
||||||
|
|
||||||
return percent;
|
return percent;
|
||||||
|
@ -18,17 +18,6 @@ in the source distribution for its full text.
|
|||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
|
||||||
const ProcessClass SolarisProcess_class = {
|
|
||||||
.super = {
|
|
||||||
.extends = Class(Process),
|
|
||||||
.display = Process_display,
|
|
||||||
.delete = Process_delete,
|
|
||||||
.compare = Process_compare
|
|
||||||
},
|
|
||||||
.writeField = SolarisProcess_writeField,
|
|
||||||
.compareByKey = SolarisProcess_compareByKey
|
|
||||||
};
|
|
||||||
|
|
||||||
const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||||
[0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, },
|
[0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, },
|
||||||
[PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, },
|
[PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, },
|
||||||
@ -78,7 +67,7 @@ void Process_delete(Object* cast) {
|
|||||||
free(sp);
|
free(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolarisProcess_writeField(const Process* this, RichString* str, ProcessField field) {
|
static void SolarisProcess_writeField(const Process* this, RichString* str, ProcessField field) {
|
||||||
const SolarisProcess* sp = (const SolarisProcess*) this;
|
const SolarisProcess* sp = (const SolarisProcess*) this;
|
||||||
char buffer[256]; buffer[255] = '\0';
|
char buffer[256]; buffer[255] = '\0';
|
||||||
int attr = CRT_colors[DEFAULT_COLOR];
|
int attr = CRT_colors[DEFAULT_COLOR];
|
||||||
@ -90,7 +79,7 @@ void SolarisProcess_writeField(const Process* this, RichString* str, ProcessFiel
|
|||||||
case TASKID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->taskid); break;
|
case TASKID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->taskid); break;
|
||||||
case POOLID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->poolid); break;
|
case POOLID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->poolid); break;
|
||||||
case CONTID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->contid); break;
|
case CONTID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->contid); break;
|
||||||
case ZONE: xSnprintf(buffer, n, "%-*s ", ZONENAME_MAX/4, sp->zname); break;
|
case ZONE: Process_printLeftAlignedField(str, attr, sp->zname ? sp->zname : "global", ZONENAME_MAX/4); return;
|
||||||
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realpid); break;
|
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realpid); break;
|
||||||
case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realppid); break;
|
case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realppid); break;
|
||||||
case LWPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->lwpid); break;
|
case LWPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->lwpid); break;
|
||||||
@ -101,7 +90,7 @@ void SolarisProcess_writeField(const Process* this, RichString* str, ProcessFiel
|
|||||||
RichString_appendWide(str, attr, buffer);
|
RichString_appendWide(str, attr, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
long SolarisProcess_compareByKey(const void* v1, const void* v2, ProcessField key) {
|
static int SolarisProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||||
const SolarisProcess* p1 = (const SolarisProcess*)v1;
|
const SolarisProcess* p1 = (const SolarisProcess*)v1;
|
||||||
const SolarisProcess* p2 = (const SolarisProcess*)v2;
|
const SolarisProcess* p2 = (const SolarisProcess*)v2;
|
||||||
|
|
||||||
@ -140,3 +129,14 @@ bool Process_isThread(const Process* this) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ProcessClass SolarisProcess_class = {
|
||||||
|
.super = {
|
||||||
|
.extends = Class(Process),
|
||||||
|
.display = Process_display,
|
||||||
|
.delete = Process_delete,
|
||||||
|
.compare = Process_compare
|
||||||
|
},
|
||||||
|
.writeField = SolarisProcess_writeField,
|
||||||
|
.compareByKey = SolarisProcess_compareByKey
|
||||||
|
};
|
||||||
|
@ -40,10 +40,6 @@ Process* SolarisProcess_new(const Settings* settings);
|
|||||||
|
|
||||||
void Process_delete(Object* cast);
|
void Process_delete(Object* cast);
|
||||||
|
|
||||||
void SolarisProcess_writeField(const Process* this, RichString* str, ProcessField field);
|
|
||||||
|
|
||||||
long SolarisProcess_compareByKey(const Process* v1, const Process* v2, ProcessField field);
|
|
||||||
|
|
||||||
bool Process_isThread(const Process* this);
|
bool Process_isThread(const Process* this);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,7 +14,6 @@ in the source distribution for its full text.
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
#include <err.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <procfs.h>
|
#include <procfs.h>
|
||||||
@ -72,11 +71,11 @@ static inline void SolarisProcessList_scanCPUTime(ProcessList* pl) {
|
|||||||
const SolarisProcessList* spl = (SolarisProcessList*) pl;
|
const SolarisProcessList* spl = (SolarisProcessList*) pl;
|
||||||
int cpus = pl->cpuCount;
|
int cpus = pl->cpuCount;
|
||||||
kstat_t* cpuinfo = NULL;
|
kstat_t* cpuinfo = NULL;
|
||||||
int kchain = 0;
|
|
||||||
kstat_named_t* idletime = NULL;
|
kstat_named_t* idletime = NULL;
|
||||||
kstat_named_t* intrtime = NULL;
|
kstat_named_t* intrtime = NULL;
|
||||||
kstat_named_t* krnltime = NULL;
|
kstat_named_t* krnltime = NULL;
|
||||||
kstat_named_t* usertime = NULL;
|
kstat_named_t* usertime = NULL;
|
||||||
|
kstat_named_t* cpu_freq = NULL;
|
||||||
double idlebuf = 0;
|
double idlebuf = 0;
|
||||||
double intrbuf = 0;
|
double intrbuf = 0;
|
||||||
double krnlbuf = 0;
|
double krnlbuf = 0;
|
||||||
@ -94,21 +93,31 @@ static inline void SolarisProcessList_scanCPUTime(ProcessList* pl) {
|
|||||||
// Calculate per-CPU statistics first
|
// Calculate per-CPU statistics first
|
||||||
for (int i = 0; i < cpus; i++) {
|
for (int i = 0; i < cpus; i++) {
|
||||||
if (spl->kd != NULL) {
|
if (spl->kd != NULL) {
|
||||||
cpuinfo = kstat_lookup(spl->kd, "cpu", i, "sys");
|
if ((cpuinfo = kstat_lookup(spl->kd, "cpu", i, "sys")) != NULL) {
|
||||||
}
|
if (kstat_read(spl->kd, cpuinfo, NULL) != -1) {
|
||||||
if (cpuinfo != NULL) {
|
idletime = kstat_data_lookup(cpuinfo, "cpu_nsec_idle");
|
||||||
kchain = kstat_read(spl->kd, cpuinfo, NULL);
|
intrtime = kstat_data_lookup(cpuinfo, "cpu_nsec_intr");
|
||||||
}
|
krnltime = kstat_data_lookup(cpuinfo, "cpu_nsec_kernel");
|
||||||
if (kchain != -1 ) {
|
usertime = kstat_data_lookup(cpuinfo, "cpu_nsec_user");
|
||||||
idletime = kstat_data_lookup(cpuinfo, "cpu_nsec_idle");
|
}
|
||||||
intrtime = kstat_data_lookup(cpuinfo, "cpu_nsec_intr");
|
}
|
||||||
krnltime = kstat_data_lookup(cpuinfo, "cpu_nsec_kernel");
|
|
||||||
usertime = kstat_data_lookup(cpuinfo, "cpu_nsec_user");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( (idletime != NULL) && (intrtime != NULL)
|
assert( (idletime != NULL) && (intrtime != NULL)
|
||||||
&& (krnltime != NULL) && (usertime != NULL) );
|
&& (krnltime != NULL) && (usertime != NULL) );
|
||||||
|
|
||||||
|
if (pl->settings->showCPUFrequency) {
|
||||||
|
if (spl->kd != NULL) {
|
||||||
|
if ((cpuinfo = kstat_lookup(spl->kd, "cpu_info", i, NULL)) != NULL) {
|
||||||
|
if (kstat_read(spl->kd, cpuinfo, NULL) != -1) {
|
||||||
|
cpu_freq = kstat_data_lookup(cpuinfo, "current_clock_Hz");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( cpu_freq != NULL );
|
||||||
|
}
|
||||||
|
|
||||||
CPUData* cpuData = &(spl->cpus[i + arrskip]);
|
CPUData* cpuData = &(spl->cpus[i + arrskip]);
|
||||||
|
|
||||||
uint64_t totaltime = (idletime->value.ui64 - cpuData->lidle)
|
uint64_t totaltime = (idletime->value.ui64 - cpuData->lidle)
|
||||||
@ -128,6 +137,8 @@ static inline void SolarisProcessList_scanCPUTime(ProcessList* pl) {
|
|||||||
cpuData->lkrnl = krnltime->value.ui64;
|
cpuData->lkrnl = krnltime->value.ui64;
|
||||||
cpuData->lintr = intrtime->value.ui64;
|
cpuData->lintr = intrtime->value.ui64;
|
||||||
cpuData->lidle = idletime->value.ui64;
|
cpuData->lidle = idletime->value.ui64;
|
||||||
|
// Add frequency in MHz
|
||||||
|
cpuData->frequency = pl->settings->showCPUFrequency ? (double)cpu_freq->value.ui64 / 1E6 : NAN;
|
||||||
// Accumulate the current percentages into buffers for later average calculation
|
// Accumulate the current percentages into buffers for later average calculation
|
||||||
if (cpus > 1) {
|
if (cpus > 1) {
|
||||||
userbuf += cpuData->userPercent;
|
userbuf += cpuData->userPercent;
|
||||||
@ -165,8 +176,8 @@ static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) {
|
|||||||
|
|
||||||
// Part 1 - physical memory
|
// Part 1 - physical memory
|
||||||
if (spl->kd != NULL && meminfo == NULL) {
|
if (spl->kd != NULL && meminfo == NULL) {
|
||||||
// Look up the kstat chain just one, it never changes
|
// Look up the kstat chain just once, it never changes
|
||||||
meminfo = kstat_lookup(spl->kd, "unix", 0, "system_pages");
|
meminfo = kstat_lookup(spl->kd, "unix", 0, "system_pages");
|
||||||
}
|
}
|
||||||
if (meminfo != NULL) {
|
if (meminfo != NULL) {
|
||||||
ksrphyserr = kstat_read(spl->kd, meminfo, NULL);
|
ksrphyserr = kstat_read(spl->kd, meminfo, NULL);
|
||||||
|
@ -33,6 +33,7 @@ typedef struct CPUData_ {
|
|||||||
double irqPercent;
|
double irqPercent;
|
||||||
double idlePercent;
|
double idlePercent;
|
||||||
double systemAllPercent;
|
double systemAllPercent;
|
||||||
|
double frequency;
|
||||||
uint64_t luser;
|
uint64_t luser;
|
||||||
uint64_t lkrnl;
|
uint64_t lkrnl;
|
||||||
uint64_t lintr;
|
uint64_t lintr;
|
||||||
|
Reference in New Issue
Block a user