2014-11-24 20:55:03 +00:00
|
|
|
/*
|
|
|
|
htop - Action.c
|
2015-03-21 19:52:54 +00:00
|
|
|
(C) 2015 Hisham H. Muhammad
|
2020-10-05 07:51:32 +00:00
|
|
|
Released under the GNU GPLv2, see the COPYING file
|
2014-11-24 20:55:03 +00:00
|
|
|
in the source distribution for its full text.
|
|
|
|
*/
|
|
|
|
|
2020-11-18 13:26:30 +00:00
|
|
|
#include "config.h" // IWYU pragma: keep
|
2015-01-22 01:27:31 +00:00
|
|
|
|
2014-11-24 20:55:03 +00:00
|
|
|
#include "Action.h"
|
2020-09-19 11:55:23 +00:00
|
|
|
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
#include "CRT.h"
|
2015-01-22 01:27:31 +00:00
|
|
|
#include "CategoriesPanel.h"
|
2020-09-19 11:55:23 +00:00
|
|
|
#include "CommandScreen.h"
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
#include "DynamicColumn.h"
|
2015-12-02 21:58:22 +00:00
|
|
|
#include "EnvScreen.h"
|
2020-09-19 11:55:23 +00:00
|
|
|
#include "FunctionBar.h"
|
2020-11-18 13:26:30 +00:00
|
|
|
#include "Hashtable.h"
|
2020-09-19 11:55:23 +00:00
|
|
|
#include "IncSet.h"
|
|
|
|
#include "InfoScreen.h"
|
|
|
|
#include "ListItem.h"
|
|
|
|
#include "Macros.h"
|
2015-01-23 05:08:21 +00:00
|
|
|
#include "MainPanel.h"
|
2015-01-22 01:27:31 +00:00
|
|
|
#include "OpenFilesScreen.h"
|
|
|
|
#include "Process.h"
|
2020-11-11 21:15:35 +00:00
|
|
|
#include "ProcessLocksScreen.h"
|
2020-09-19 11:55:23 +00:00
|
|
|
#include "ProvideCurses.h"
|
2014-11-24 21:22:50 +00:00
|
|
|
#include "ScreenManager.h"
|
2015-01-22 01:27:31 +00:00
|
|
|
#include "SignalsPanel.h"
|
|
|
|
#include "TraceScreen.h"
|
2020-09-19 11:55:23 +00:00
|
|
|
#include "Vector.h"
|
2020-10-14 18:21:09 +00:00
|
|
|
#include "XUtils.h"
|
2015-01-22 01:27:31 +00:00
|
|
|
|
2021-06-13 09:29:39 +00:00
|
|
|
#if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
|
2020-11-18 14:12:18 +00:00
|
|
|
#include "Affinity.h"
|
|
|
|
#include "AffinityPanel.h"
|
|
|
|
#endif
|
|
|
|
|
2014-11-24 20:55:03 +00:00
|
|
|
|
2018-11-11 05:48:08 +00:00
|
|
|
Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess) {
|
2021-02-05 13:12:49 +00:00
|
|
|
MainPanel* mainPanel = st->mainPanel;
|
2015-01-22 01:27:31 +00:00
|
|
|
Header* header = st->header;
|
2019-10-31 16:39:12 +00:00
|
|
|
|
2021-02-05 13:12:49 +00:00
|
|
|
int y = ((Panel*)mainPanel)->y;
|
2021-01-05 22:42:55 +00:00
|
|
|
ScreenManager* scr = ScreenManager_new(header, st->settings, st, false);
|
2014-11-24 21:22:50 +00:00
|
|
|
scr->allowFocusChange = false;
|
2015-03-23 18:26:56 +00:00
|
|
|
ScreenManager_add(scr, list, x - 1);
|
2021-02-05 13:12:49 +00:00
|
|
|
ScreenManager_add(scr, (Panel*)mainPanel, -1);
|
2014-11-24 21:22:50 +00:00
|
|
|
Panel* panelFocus;
|
|
|
|
int ch;
|
|
|
|
bool unfollow = false;
|
2021-02-05 13:12:49 +00:00
|
|
|
int pid = followProcess ? MainPanel_selectedPid(mainPanel) : -1;
|
2018-11-11 05:48:08 +00:00
|
|
|
if (followProcess && header->pl->following == -1) {
|
2014-11-24 21:22:50 +00:00
|
|
|
header->pl->following = pid;
|
|
|
|
unfollow = true;
|
|
|
|
}
|
|
|
|
ScreenManager_run(scr, &panelFocus, &ch);
|
|
|
|
if (unfollow) {
|
|
|
|
header->pl->following = -1;
|
|
|
|
}
|
|
|
|
ScreenManager_delete(scr);
|
2021-02-05 13:12:49 +00:00
|
|
|
Panel_move((Panel*)mainPanel, 0, y);
|
|
|
|
Panel_resize((Panel*)mainPanel, COLS, LINES - y - 1);
|
2014-11-24 21:22:50 +00:00
|
|
|
if (panelFocus == list && ch == 13) {
|
2018-11-11 05:48:08 +00:00
|
|
|
if (followProcess) {
|
2021-02-05 13:12:49 +00:00
|
|
|
const Process* selected = (const Process*)Panel_getSelected((Panel*)mainPanel);
|
2018-11-11 05:48:08 +00:00
|
|
|
if (selected && selected->pid == pid)
|
|
|
|
return Panel_getSelected(list);
|
2020-11-01 00:09:51 +00:00
|
|
|
|
|
|
|
beep();
|
2018-11-11 05:48:08 +00:00
|
|
|
} else {
|
2014-11-24 21:22:50 +00:00
|
|
|
return Panel_getSelected(list);
|
2018-11-11 05:48:08 +00:00
|
|
|
}
|
2014-11-24 21:22:50 +00:00
|
|
|
}
|
2020-11-01 00:09:51 +00:00
|
|
|
|
2014-11-24 21:22:50 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2015-01-22 01:27:31 +00:00
|
|
|
|
|
|
|
// ----------------------------------------
|
|
|
|
|
2020-10-05 13:14:54 +00:00
|
|
|
static void Action_runSetup(State* st) {
|
2020-11-26 05:15:09 +00:00
|
|
|
ScreenManager* scr = ScreenManager_new(st->header, st->settings, st, true);
|
2020-10-05 13:14:54 +00:00
|
|
|
CategoriesPanel* panelCategories = CategoriesPanel_new(scr, st->settings, st->header, st->pl);
|
2015-03-23 18:26:56 +00:00
|
|
|
ScreenManager_add(scr, (Panel*) panelCategories, 16);
|
2015-01-22 01:27:31 +00:00
|
|
|
CategoriesPanel_makeMetersPage(panelCategories);
|
|
|
|
Panel* panelFocus;
|
|
|
|
int ch;
|
|
|
|
ScreenManager_run(scr, &panelFocus, &ch);
|
|
|
|
ScreenManager_delete(scr);
|
2020-10-05 13:14:54 +00:00
|
|
|
if (st->settings->changed) {
|
|
|
|
Header_writeBackToSettings(st->header);
|
2015-03-17 02:01:21 +00:00
|
|
|
}
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
2015-01-23 05:08:21 +00:00
|
|
|
static bool changePriority(MainPanel* panel, int delta) {
|
2015-01-22 01:27:31 +00:00
|
|
|
bool anyTagged;
|
2020-11-01 00:09:51 +00:00
|
|
|
bool ok = MainPanel_foreachProcess(panel, Process_changePriorityBy, (Arg) { .i = delta }, &anyTagged);
|
2015-01-22 01:27:31 +00:00
|
|
|
if (!ok)
|
|
|
|
beep();
|
|
|
|
return anyTagged;
|
|
|
|
}
|
|
|
|
|
2021-01-04 22:20:36 +00:00
|
|
|
static void addUserToVector(ht_key_t key, void* userCast, void* panelCast) {
|
2020-10-27 10:46:29 +00:00
|
|
|
const char* user = userCast;
|
|
|
|
Panel* panel = panelCast;
|
2015-01-22 01:27:31 +00:00
|
|
|
Panel_add(panel, (Object*) ListItem_new(user, key));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Action_setUserOnly(const char* userName, uid_t* userId) {
|
2020-10-27 10:46:29 +00:00
|
|
|
const struct passwd* user = getpwnam(userName);
|
2015-01-22 01:27:31 +00:00
|
|
|
if (user) {
|
|
|
|
*userId = user->pw_uid;
|
|
|
|
return true;
|
|
|
|
}
|
2020-10-15 20:35:44 +00:00
|
|
|
*userId = (uid_t)-1;
|
2015-01-22 01:27:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tagAllChildren(Panel* panel, Process* parent) {
|
|
|
|
parent->tag = true;
|
|
|
|
pid_t ppid = parent->pid;
|
|
|
|
for (int i = 0; i < Panel_size(panel); i++) {
|
|
|
|
Process* p = (Process*) Panel_get(panel, i);
|
2017-09-14 20:10:39 +00:00
|
|
|
if (!p->tag && Process_isChildOf(p, ppid)) {
|
2015-01-22 01:27:31 +00:00
|
|
|
tagAllChildren(panel, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool expandCollapse(Panel* panel) {
|
|
|
|
Process* p = (Process*) Panel_getSelected(panel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return false;
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
p->showChildren = !p->showChildren;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-04-05 22:31:18 +00:00
|
|
|
static bool collapseIntoParent(Panel* panel) {
|
2021-01-05 22:42:55 +00:00
|
|
|
const Process* p = (Process*) Panel_getSelected(panel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return false;
|
|
|
|
|
2018-04-05 22:31:18 +00:00
|
|
|
pid_t ppid = Process_getParentPid(p);
|
|
|
|
for (int i = 0; i < Panel_size(panel); i++) {
|
|
|
|
Process* q = (Process*) Panel_get(panel, i);
|
|
|
|
if (q->pid == ppid) {
|
|
|
|
q->showChildren = false;
|
|
|
|
Panel_setSelected(panel, i);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-03-25 02:12:43 +00:00
|
|
|
Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) {
|
2020-12-18 14:03:31 +00:00
|
|
|
Settings_setSortKey(settings, sortKey);
|
2015-04-09 18:17:20 +00:00
|
|
|
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING;
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
2021-01-01 20:31:30 +00:00
|
|
|
// ----------------------------------------
|
|
|
|
|
|
|
|
static Htop_Reaction actionSetSortColumn(State* st) {
|
2015-01-22 01:27:31 +00:00
|
|
|
Htop_Reaction reaction = HTOP_OK;
|
2021-01-02 22:51:53 +00:00
|
|
|
Panel* sortPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Sort ", "Cancel "));
|
2015-01-22 01:27:31 +00:00
|
|
|
Panel_setHeader(sortPanel, "Sort by");
|
2021-01-05 22:42:55 +00:00
|
|
|
const ProcessField* fields = st->settings->fields;
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
Hashtable* dynamicColumns = st->settings->dynamicColumns;
|
2015-01-22 01:27:31 +00:00
|
|
|
for (int i = 0; fields[i]; i++) {
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
char* name = NULL;
|
|
|
|
if (fields[i] >= LAST_PROCESSFIELD) {
|
|
|
|
DynamicColumn* column = Hashtable_get(dynamicColumns, fields[i]);
|
|
|
|
if (column)
|
|
|
|
name = xStrdup(column->caption ? column->caption : column->name);
|
|
|
|
} else {
|
|
|
|
name = String_trim(Process_fields[fields[i]].name);
|
|
|
|
}
|
2015-01-22 01:27:31 +00:00
|
|
|
Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i]));
|
2020-12-18 14:03:31 +00:00
|
|
|
if (fields[i] == Settings_getActiveSortKey(st->settings))
|
2015-01-22 01:27:31 +00:00
|
|
|
Panel_setSelected(sortPanel, i);
|
2020-11-01 00:09:51 +00:00
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
free(name);
|
|
|
|
}
|
2021-01-05 22:42:55 +00:00
|
|
|
const ListItem* field = (const ListItem*) Action_pickFromVector(st, sortPanel, 15, false);
|
2015-01-22 01:27:31 +00:00
|
|
|
if (field) {
|
2015-03-25 02:12:43 +00:00
|
|
|
reaction |= Action_setSortKey(st->settings, field->key);
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
Object_delete(sortPanel);
|
2020-11-01 00:09:51 +00:00
|
|
|
|
2020-10-05 13:14:54 +00:00
|
|
|
if (st->pauseProcessUpdate)
|
|
|
|
ProcessList_sort(st->pl);
|
2020-11-01 00:09:51 +00:00
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
|
|
|
}
|
|
|
|
|
2020-12-19 14:48:07 +00:00
|
|
|
static Htop_Reaction actionSortByPID(State* st) {
|
|
|
|
return Action_setSortKey(st->settings, PID);
|
|
|
|
}
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
static Htop_Reaction actionSortByMemory(State* st) {
|
2015-03-25 02:12:43 +00:00
|
|
|
return Action_setSortKey(st->settings, PERCENT_MEM);
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionSortByCPU(State* st) {
|
2015-03-25 02:12:43 +00:00
|
|
|
return Action_setSortKey(st->settings, PERCENT_CPU);
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionSortByTime(State* st) {
|
2015-03-25 02:12:43 +00:00
|
|
|
return Action_setSortKey(st->settings, TIME);
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionToggleKernelThreads(State* st) {
|
|
|
|
st->settings->hideKernelThreads = !st->settings->hideKernelThreads;
|
2021-03-03 18:56:39 +00:00
|
|
|
return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionToggleUserlandThreads(State* st) {
|
|
|
|
st->settings->hideUserlandThreads = !st->settings->hideUserlandThreads;
|
2021-03-03 18:56:39 +00:00
|
|
|
return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
2015-07-29 19:32:36 +00:00
|
|
|
static Htop_Reaction actionToggleProgramPath(State* st) {
|
|
|
|
st->settings->showProgramPath = !st->settings->showProgramPath;
|
|
|
|
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
|
|
|
|
}
|
|
|
|
|
2020-10-17 10:54:45 +00:00
|
|
|
static Htop_Reaction actionToggleMergedCommand(State* st) {
|
|
|
|
st->settings->showMergedCommand = !st->settings->showMergedCommand;
|
|
|
|
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
|
|
|
|
}
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
static Htop_Reaction actionToggleTreeView(State* st) {
|
|
|
|
st->settings->treeView = !st->settings->treeView;
|
2020-11-01 00:09:51 +00:00
|
|
|
|
2021-07-14 17:11:18 +00:00
|
|
|
if (!st->settings->allBranchesCollapsed)
|
|
|
|
ProcessList_expandTree(st->pl);
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
|
|
|
}
|
|
|
|
|
2021-02-12 17:48:09 +00:00
|
|
|
static Htop_Reaction actionExpandOrCollapseAllBranches(State* st) {
|
|
|
|
st->settings->allBranchesCollapsed = !st->settings->allBranchesCollapsed;
|
|
|
|
if (st->settings->allBranchesCollapsed)
|
|
|
|
ProcessList_collapseAllBranches(st->pl);
|
|
|
|
else
|
|
|
|
ProcessList_expandTree(st->pl);
|
|
|
|
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
|
|
|
|
}
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
static Htop_Reaction actionIncFilter(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
IncSet* inc = (st->mainPanel)->inc;
|
|
|
|
IncSet_activate(inc, INC_FILTER, (Panel*)st->mainPanel);
|
2015-03-23 01:39:33 +00:00
|
|
|
st->pl->incFilter = IncSet_filter(inc);
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionIncSearch(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
IncSet_reset(st->mainPanel->inc, INC_SEARCH);
|
|
|
|
IncSet_activate(st->mainPanel->inc, INC_SEARCH, (Panel*)st->mainPanel);
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionHigherPriority(State* st) {
|
2021-01-21 19:27:37 +00:00
|
|
|
if (Settings_isReadonly())
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2021-02-05 13:12:49 +00:00
|
|
|
bool changed = changePriority(st->mainPanel, -1);
|
2015-01-22 01:27:31 +00:00
|
|
|
return changed ? HTOP_REFRESH : HTOP_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionLowerPriority(State* st) {
|
2021-01-21 19:27:37 +00:00
|
|
|
if (Settings_isReadonly())
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2021-02-05 13:12:49 +00:00
|
|
|
bool changed = changePriority(st->mainPanel, 1);
|
2015-01-22 01:27:31 +00:00
|
|
|
return changed ? HTOP_REFRESH : HTOP_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionInvertSortOrder(State* st) {
|
|
|
|
Settings_invertSortOrder(st->settings);
|
2020-12-09 12:43:07 +00:00
|
|
|
if (st->pauseProcessUpdate)
|
|
|
|
ProcessList_sort(st->pl);
|
2021-03-12 17:02:39 +00:00
|
|
|
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionExpandOrCollapse(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
bool changed = expandCollapse((Panel*)st->mainPanel);
|
2015-01-22 01:27:31 +00:00
|
|
|
return changed ? HTOP_RECALCULATE : HTOP_OK;
|
|
|
|
}
|
|
|
|
|
2018-04-05 22:31:18 +00:00
|
|
|
static Htop_Reaction actionCollapseIntoParent(State* st) {
|
|
|
|
if (!st->settings->treeView) {
|
|
|
|
return HTOP_OK;
|
|
|
|
}
|
2021-02-05 13:12:49 +00:00
|
|
|
bool changed = collapseIntoParent((Panel*)st->mainPanel);
|
2018-04-05 22:31:18 +00:00
|
|
|
return changed ? HTOP_RECALCULATE : HTOP_OK;
|
|
|
|
}
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
static Htop_Reaction actionExpandCollapseOrSortColumn(State* st) {
|
|
|
|
return st->settings->treeView ? actionExpandOrCollapse(st) : actionSetSortColumn(st);
|
|
|
|
}
|
|
|
|
|
2020-09-08 12:28:34 +00:00
|
|
|
static Htop_Reaction actionQuit(ATTR_UNUSED State* st) {
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_QUIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionSetAffinity(State* st) {
|
2021-01-21 19:27:37 +00:00
|
|
|
if (Settings_isReadonly())
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2021-06-12 16:17:28 +00:00
|
|
|
if (st->pl->activeCPUs == 1)
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_OK;
|
2020-11-01 00:09:51 +00:00
|
|
|
|
2021-06-13 09:29:39 +00:00
|
|
|
#if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
|
2021-02-05 13:12:49 +00:00
|
|
|
const Process* p = (const Process*) Panel_getSelected((Panel*)st->mainPanel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2020-08-25 10:01:54 +00:00
|
|
|
Affinity* affinity1 = Affinity_get(p, st->pl);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!affinity1)
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2020-08-26 00:15:00 +00:00
|
|
|
int width;
|
|
|
|
Panel* affinityPanel = AffinityPanel_new(st->pl, affinity1, &width);
|
2020-08-26 20:03:04 +00:00
|
|
|
width += 1; /* we add a gap between the panels */
|
2020-08-25 10:01:54 +00:00
|
|
|
Affinity_delete(affinity1);
|
2015-01-22 01:27:31 +00:00
|
|
|
|
2021-01-05 22:42:55 +00:00
|
|
|
const void* set = Action_pickFromVector(st, affinityPanel, width, true);
|
2015-01-22 01:27:31 +00:00
|
|
|
if (set) {
|
2020-08-25 10:01:54 +00:00
|
|
|
Affinity* affinity2 = AffinityPanel_getAffinity(affinityPanel, st->pl);
|
2021-02-05 13:12:49 +00:00
|
|
|
bool ok = MainPanel_foreachProcess(st->mainPanel, Affinity_set, (Arg) { .v = affinity2 }, NULL);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!ok)
|
|
|
|
beep();
|
2020-08-25 10:01:54 +00:00
|
|
|
Affinity_delete(affinity2);
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
2020-09-11 18:36:02 +00:00
|
|
|
Object_delete(affinityPanel);
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
2021-06-13 09:29:39 +00:00
|
|
|
#else
|
|
|
|
return HTOP_OK;
|
|
|
|
#endif
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionKill(State* st) {
|
2021-01-21 19:27:37 +00:00
|
|
|
if (Settings_isReadonly())
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2020-09-28 10:17:52 +00:00
|
|
|
Panel* signalsPanel = SignalsPanel_new();
|
2021-01-05 22:42:55 +00:00
|
|
|
const ListItem* sgn = (ListItem*) Action_pickFromVector(st, signalsPanel, 15, true);
|
2021-03-17 16:53:23 +00:00
|
|
|
if (sgn && sgn->key != 0) {
|
|
|
|
Panel_setHeader((Panel*)st->mainPanel, "Sending...");
|
|
|
|
Panel_draw((Panel*)st->mainPanel, false, true, true, State_hideFunctionBar(st));
|
|
|
|
refresh();
|
|
|
|
MainPanel_foreachProcess(st->mainPanel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL);
|
|
|
|
napms(500);
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
Panel_delete((Object*)signalsPanel);
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionFilterByUser(State* st) {
|
2021-01-02 22:51:53 +00:00
|
|
|
Panel* usersPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Show ", "Cancel "));
|
2015-01-22 01:27:31 +00:00
|
|
|
Panel_setHeader(usersPanel, "Show processes of:");
|
|
|
|
UsersTable_foreach(st->ut, addUserToVector, usersPanel);
|
|
|
|
Vector_insertionSort(usersPanel->items);
|
|
|
|
ListItem* allUsers = ListItem_new("All users", -1);
|
|
|
|
Panel_insert(usersPanel, 0, (Object*) allUsers);
|
2021-01-05 22:42:55 +00:00
|
|
|
const ListItem* picked = (ListItem*) Action_pickFromVector(st, usersPanel, 20, false);
|
2015-01-22 01:27:31 +00:00
|
|
|
if (picked) {
|
|
|
|
if (picked == allUsers) {
|
2020-09-24 10:01:59 +00:00
|
|
|
st->pl->userId = (uid_t)-1;
|
2015-01-22 01:27:31 +00:00
|
|
|
} else {
|
|
|
|
Action_setUserOnly(ListItem_getRef(picked), &(st->pl->userId));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Panel_delete((Object*)usersPanel);
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
|
|
|
}
|
|
|
|
|
2016-05-05 13:30:06 +00:00
|
|
|
Htop_Reaction Action_follow(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
st->pl->following = MainPanel_selectedPid(st->mainPanel);
|
|
|
|
Panel_setSelectionColor((Panel*)st->mainPanel, PANEL_SELECTION_FOLLOW);
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_KEEP_FOLLOWING;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionSetup(State* st) {
|
2020-10-05 13:14:54 +00:00
|
|
|
Action_runSetup(st);
|
2015-01-22 01:27:31 +00:00
|
|
|
int headerHeight = Header_calculateHeight(st->header);
|
2021-02-05 13:12:49 +00:00
|
|
|
Panel_move((Panel*)st->mainPanel, 0, headerHeight);
|
2021-07-14 17:18:27 +00:00
|
|
|
Panel_resize((Panel*)st->mainPanel, COLS, LINES - headerHeight - 1);
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionLsof(State* st) {
|
2021-01-21 19:27:37 +00:00
|
|
|
if (Settings_isReadonly())
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2021-02-05 13:12:49 +00:00
|
|
|
const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2016-01-12 08:00:58 +00:00
|
|
|
OpenFilesScreen* ofs = OpenFilesScreen_new(p);
|
|
|
|
InfoScreen_run((InfoScreen*)ofs);
|
|
|
|
OpenFilesScreen_delete((Object*)ofs);
|
2015-01-22 01:27:31 +00:00
|
|
|
clear();
|
|
|
|
CRT_enableDelay();
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR;
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:02:27 +00:00
|
|
|
static Htop_Reaction actionShowLocks(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
|
2021-07-14 17:11:18 +00:00
|
|
|
if (!p)
|
|
|
|
return HTOP_OK;
|
2020-10-09 19:02:27 +00:00
|
|
|
ProcessLocksScreen* pls = ProcessLocksScreen_new(p);
|
|
|
|
InfoScreen_run((InfoScreen*)pls);
|
|
|
|
ProcessLocksScreen_delete((Object*)pls);
|
|
|
|
clear();
|
|
|
|
CRT_enableDelay();
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR;
|
|
|
|
}
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
static Htop_Reaction actionStrace(State* st) {
|
2021-01-21 19:27:37 +00:00
|
|
|
if (Settings_isReadonly())
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2021-02-05 13:12:49 +00:00
|
|
|
const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
TraceScreen* ts = TraceScreen_new(p);
|
2016-01-12 08:00:58 +00:00
|
|
|
bool ok = TraceScreen_forkTracer(ts);
|
|
|
|
if (ok) {
|
|
|
|
InfoScreen_run((InfoScreen*)ts);
|
|
|
|
}
|
|
|
|
TraceScreen_delete((Object*)ts);
|
2015-01-22 01:27:31 +00:00
|
|
|
clear();
|
|
|
|
CRT_enableDelay();
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionTag(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
Process_toggleTag(p);
|
2021-02-05 13:12:49 +00:00
|
|
|
Panel_onKey((Panel*)st->mainPanel, KEY_DOWN);
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_OK;
|
|
|
|
}
|
|
|
|
|
2020-10-31 22:28:02 +00:00
|
|
|
static Htop_Reaction actionRedraw(ATTR_UNUSED State* st) {
|
2015-01-22 01:27:31 +00:00
|
|
|
clear();
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR;
|
|
|
|
}
|
|
|
|
|
2020-10-31 22:28:02 +00:00
|
|
|
static Htop_Reaction actionTogglePauseProcessUpdate(State* st) {
|
2020-10-05 13:14:54 +00:00
|
|
|
st->pauseProcessUpdate = !st->pauseProcessUpdate;
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR;
|
|
|
|
}
|
|
|
|
|
2020-11-01 00:49:54 +00:00
|
|
|
static const struct {
|
|
|
|
const char* key;
|
2021-01-21 19:27:37 +00:00
|
|
|
bool roInactive;
|
2020-11-01 00:49:54 +00:00
|
|
|
const char* info;
|
|
|
|
} helpLeft[] = {
|
2021-01-21 19:27:37 +00:00
|
|
|
{ .key = " Arrows: ", .roInactive = false, .info = "scroll process list" },
|
|
|
|
{ .key = " Digits: ", .roInactive = false, .info = "incremental PID search" },
|
|
|
|
{ .key = " F3 /: ", .roInactive = false, .info = "incremental name search" },
|
|
|
|
{ .key = " F4 \\: ", .roInactive = false, .info = "incremental name filtering" },
|
|
|
|
{ .key = " F5 t: ", .roInactive = false, .info = "tree view" },
|
|
|
|
{ .key = " p: ", .roInactive = false, .info = "toggle program path" },
|
|
|
|
{ .key = " m: ", .roInactive = false, .info = "toggle merged command" },
|
|
|
|
{ .key = " Z: ", .roInactive = false, .info = "pause/resume process updates" },
|
|
|
|
{ .key = " u: ", .roInactive = false, .info = "show processes of a single user" },
|
|
|
|
{ .key = " H: ", .roInactive = false, .info = "hide/show user process threads" },
|
|
|
|
{ .key = " K: ", .roInactive = false, .info = "hide/show kernel threads" },
|
|
|
|
{ .key = " F: ", .roInactive = false, .info = "cursor follows process" },
|
|
|
|
{ .key = " + - *: ", .roInactive = false, .info = "expand/collapse tree/toggle all" },
|
|
|
|
{ .key = "N P M T: ", .roInactive = false, .info = "sort by PID, CPU%, MEM% or TIME" },
|
|
|
|
{ .key = " I: ", .roInactive = false, .info = "invert sort order" },
|
|
|
|
{ .key = " F6 > .: ", .roInactive = false, .info = "select sort column" },
|
2015-01-22 01:27:31 +00:00
|
|
|
{ .key = NULL, .info = NULL }
|
|
|
|
};
|
|
|
|
|
2020-11-01 00:49:54 +00:00
|
|
|
static const struct {
|
|
|
|
const char* key;
|
2021-01-21 19:27:37 +00:00
|
|
|
bool roInactive;
|
2020-11-01 00:49:54 +00:00
|
|
|
const char* info;
|
|
|
|
} helpRight[] = {
|
2021-01-21 19:27:37 +00:00
|
|
|
{ .key = " Space: ", .roInactive = false, .info = "tag process" },
|
|
|
|
{ .key = " c: ", .roInactive = false, .info = "tag process and its children" },
|
|
|
|
{ .key = " U: ", .roInactive = false, .info = "untag all processes" },
|
|
|
|
{ .key = " F9 k: ", .roInactive = true, .info = "kill process/tagged processes" },
|
|
|
|
{ .key = " F7 ]: ", .roInactive = true, .info = "higher priority (root only)" },
|
|
|
|
{ .key = " F8 [: ", .roInactive = false, .info = "lower priority (+ nice)" },
|
2021-06-13 09:29:39 +00:00
|
|
|
#if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
|
2021-01-21 19:27:37 +00:00
|
|
|
{ .key = " a: ", .roInactive = true, .info = "set CPU affinity" },
|
2015-01-22 01:27:31 +00:00
|
|
|
#endif
|
2021-01-21 19:27:37 +00:00
|
|
|
{ .key = " e: ", .roInactive = false, .info = "show process environment" },
|
|
|
|
{ .key = " i: ", .roInactive = true, .info = "set IO priority" },
|
|
|
|
{ .key = " l: ", .roInactive = true, .info = "list open files with lsof" },
|
|
|
|
{ .key = " x: ", .roInactive = false, .info = "list file locks of process" },
|
|
|
|
{ .key = " s: ", .roInactive = true, .info = "trace syscalls with strace" },
|
|
|
|
{ .key = " w: ", .roInactive = false, .info = "wrap process command in multiple lines" },
|
|
|
|
{ .key = " F2 C S: ", .roInactive = false, .info = "setup" },
|
2021-04-21 19:49:03 +00:00
|
|
|
{ .key = " F1 h ?: ", .roInactive = false, .info = "show this help screen" },
|
2021-01-21 19:27:37 +00:00
|
|
|
{ .key = " F10 q: ", .roInactive = false, .info = "quit" },
|
2015-01-22 01:27:31 +00:00
|
|
|
{ .key = NULL, .info = NULL }
|
|
|
|
};
|
|
|
|
|
2020-10-31 19:26:53 +00:00
|
|
|
static inline void addattrstr( int attr, const char* str) {
|
|
|
|
attrset(attr);
|
|
|
|
addstr(str);
|
|
|
|
}
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
static Htop_Reaction actionHelp(State* st) {
|
|
|
|
clear();
|
|
|
|
attrset(CRT_colors[HELP_BOLD]);
|
|
|
|
|
2020-10-31 22:28:02 +00:00
|
|
|
for (int i = 0; i < LINES - 1; i++)
|
2015-01-22 01:27:31 +00:00
|
|
|
mvhline(i, 0, ' ', COLS);
|
|
|
|
|
2020-10-12 11:30:23 +00:00
|
|
|
int line = 0;
|
|
|
|
|
|
|
|
mvaddstr(line++, 0, "htop " VERSION " - " COPYRIGHT);
|
|
|
|
mvaddstr(line++, 0, "Released under the GNU GPLv2. See 'man' page for more info.");
|
2015-01-22 01:27:31 +00:00
|
|
|
|
|
|
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
2020-10-12 11:30:23 +00:00
|
|
|
line++;
|
|
|
|
mvaddstr(line++, 0, "CPU usage bar: ");
|
2020-10-31 19:26:53 +00:00
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[BAR_BORDER], "[");
|
2021-01-05 22:42:55 +00:00
|
|
|
if (st->settings->detailedCPUTime) {
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[CPU_NICE_TEXT], "low"); addstr("/");
|
|
|
|
addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/");
|
2020-08-20 04:09:27 +00:00
|
|
|
addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/");
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[CPU_IRQ], "irq"); addstr("/");
|
|
|
|
addattrstr(CRT_colors[CPU_SOFTIRQ], "soft-irq"); addstr("/");
|
|
|
|
addattrstr(CRT_colors[CPU_STEAL], "steal"); addstr("/");
|
|
|
|
addattrstr(CRT_colors[CPU_GUEST], "guest"); addstr("/");
|
|
|
|
addattrstr(CRT_colors[CPU_IOWAIT], "io-wait");
|
|
|
|
addattrstr(CRT_colors[BAR_SHADOW], " used%");
|
|
|
|
} else {
|
|
|
|
addattrstr(CRT_colors[CPU_NICE_TEXT], "low-priority"); addstr("/");
|
|
|
|
addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/");
|
2020-08-20 04:09:27 +00:00
|
|
|
addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/");
|
2018-06-13 03:47:08 +00:00
|
|
|
addattrstr(CRT_colors[CPU_GUEST], "virtualiz");
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[BAR_SHADOW], " used%");
|
|
|
|
}
|
|
|
|
addattrstr(CRT_colors[BAR_BORDER], "]");
|
|
|
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
2020-10-12 11:30:23 +00:00
|
|
|
mvaddstr(line++, 0, "Memory bar: ");
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[BAR_BORDER], "[");
|
|
|
|
addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/");
|
|
|
|
addattrstr(CRT_colors[MEMORY_BUFFERS_TEXT], "buffers"); addstr("/");
|
2021-03-24 11:58:46 +00:00
|
|
|
addattrstr(CRT_colors[MEMORY_SHARED], "shared"); addstr("/");
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[MEMORY_CACHE], "cache");
|
2021-03-24 11:58:46 +00:00
|
|
|
addattrstr(CRT_colors[BAR_SHADOW], " used/total");
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[BAR_BORDER], "]");
|
|
|
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
2020-10-12 11:30:23 +00:00
|
|
|
mvaddstr(line++, 0, "Swap bar: ");
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[BAR_BORDER], "[");
|
|
|
|
addattrstr(CRT_colors[SWAP], "used");
|
2021-01-07 13:38:18 +00:00
|
|
|
#ifdef HTOP_LINUX
|
|
|
|
addattrstr(CRT_colors[BAR_SHADOW], "/");
|
|
|
|
addattrstr(CRT_colors[SWAP_CACHE], "cache");
|
|
|
|
addattrstr(CRT_colors[BAR_SHADOW], " used/total");
|
|
|
|
#else
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[BAR_SHADOW], " used/total");
|
2021-01-07 13:38:18 +00:00
|
|
|
#endif
|
2015-01-22 01:27:31 +00:00
|
|
|
addattrstr(CRT_colors[BAR_BORDER], "]");
|
|
|
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
2020-10-31 22:28:02 +00:00
|
|
|
mvaddstr(line++, 0, "Type and layout of header meters are configurable in the setup screen.");
|
2015-01-22 01:27:31 +00:00
|
|
|
if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
|
2020-10-12 11:30:23 +00:00
|
|
|
mvaddstr(line, 0, "In monochrome, meters display as different chars, in order: |#*@$%&.");
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
2020-10-12 11:30:23 +00:00
|
|
|
line++;
|
|
|
|
|
|
|
|
mvaddstr(line++, 0, "Process state: R: running; S: sleeping; T: traced/stopped; Z: zombie; D: disk sleep");
|
|
|
|
|
|
|
|
line++;
|
|
|
|
|
2021-01-21 19:27:37 +00:00
|
|
|
const bool readonly = Settings_isReadonly();
|
|
|
|
|
2020-10-12 11:30:23 +00:00
|
|
|
int item;
|
|
|
|
for (item = 0; helpLeft[item].key; item++) {
|
2021-01-21 19:27:37 +00:00
|
|
|
attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[DEFAULT_COLOR]);
|
2020-12-19 14:48:07 +00:00
|
|
|
mvaddstr(line + item, 10, helpLeft[item].info);
|
2021-01-21 19:27:37 +00:00
|
|
|
attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[HELP_BOLD]);
|
2020-12-19 14:48:07 +00:00
|
|
|
mvaddstr(line + item, 1, helpLeft[item].key);
|
2020-10-19 10:05:06 +00:00
|
|
|
if (String_eq(helpLeft[item].key, " H: ")) {
|
2021-01-21 19:27:37 +00:00
|
|
|
attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[PROCESS_THREAD]);
|
2020-12-19 14:48:07 +00:00
|
|
|
mvaddstr(line + item, 33, "threads");
|
2020-10-19 10:05:06 +00:00
|
|
|
} else if (String_eq(helpLeft[item].key, " K: ")) {
|
2021-01-21 19:27:37 +00:00
|
|
|
attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[PROCESS_THREAD]);
|
2020-12-19 14:48:07 +00:00
|
|
|
mvaddstr(line + item, 27, "threads");
|
2020-10-12 11:30:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
int leftHelpItems = item;
|
|
|
|
|
|
|
|
for (item = 0; helpRight[item].key; item++) {
|
2021-01-21 19:27:37 +00:00
|
|
|
attrset((helpRight[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[HELP_BOLD]);
|
2020-12-19 14:48:07 +00:00
|
|
|
mvaddstr(line + item, 41, helpRight[item].key);
|
2021-01-21 19:27:37 +00:00
|
|
|
attrset((helpRight[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[DEFAULT_COLOR]);
|
2020-12-19 14:48:07 +00:00
|
|
|
mvaddstr(line + item, 50, helpRight[item].info);
|
2020-10-12 11:30:23 +00:00
|
|
|
}
|
|
|
|
line += MAXIMUM(leftHelpItems, item);
|
|
|
|
line++;
|
2015-01-22 01:27:31 +00:00
|
|
|
|
|
|
|
attrset(CRT_colors[HELP_BOLD]);
|
2020-10-12 11:30:23 +00:00
|
|
|
mvaddstr(line++, 0, "Press any key to return.");
|
2015-01-22 01:27:31 +00:00
|
|
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
|
|
|
refresh();
|
|
|
|
CRT_readKey();
|
|
|
|
clear();
|
|
|
|
|
2021-03-12 17:02:39 +00:00
|
|
|
return HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_KEEP_FOLLOWING;
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionUntagAll(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
for (int i = 0; i < Panel_size((Panel*)st->mainPanel); i++) {
|
|
|
|
Process* p = (Process*) Panel_get((Panel*)st->mainPanel, i);
|
2015-01-22 01:27:31 +00:00
|
|
|
p->tag = false;
|
|
|
|
}
|
|
|
|
return HTOP_REFRESH;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Htop_Reaction actionTagAllChildren(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2021-02-05 13:12:49 +00:00
|
|
|
tagAllChildren((Panel*)st->mainPanel, p);
|
2015-01-22 01:27:31 +00:00
|
|
|
return HTOP_OK;
|
|
|
|
}
|
|
|
|
|
2015-12-02 21:58:22 +00:00
|
|
|
static Htop_Reaction actionShowEnvScreen(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2016-01-12 08:00:58 +00:00
|
|
|
EnvScreen* es = EnvScreen_new(p);
|
|
|
|
InfoScreen_run((InfoScreen*)es);
|
|
|
|
EnvScreen_delete((Object*)es);
|
2015-12-02 21:58:22 +00:00
|
|
|
clear();
|
|
|
|
CRT_enableDelay();
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR;
|
|
|
|
}
|
|
|
|
|
2017-08-03 09:43:28 +00:00
|
|
|
static Htop_Reaction actionShowCommandScreen(State* st) {
|
2021-02-05 13:12:49 +00:00
|
|
|
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
|
2020-11-01 00:09:51 +00:00
|
|
|
if (!p)
|
|
|
|
return HTOP_OK;
|
|
|
|
|
2017-08-03 09:43:28 +00:00
|
|
|
CommandScreen* cmdScr = CommandScreen_new(p);
|
|
|
|
InfoScreen_run((InfoScreen*)cmdScr);
|
|
|
|
CommandScreen_delete((Object*)cmdScr);
|
|
|
|
clear();
|
|
|
|
CRT_enableDelay();
|
|
|
|
return HTOP_REFRESH | HTOP_REDRAW_BAR;
|
|
|
|
}
|
2015-12-02 21:58:22 +00:00
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
void Action_setBindings(Htop_Action* keys) {
|
2020-12-21 14:53:42 +00:00
|
|
|
keys[' '] = actionTag;
|
2021-02-12 17:48:09 +00:00
|
|
|
keys['*'] = actionExpandOrCollapseAllBranches;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['+'] = actionExpandOrCollapse;
|
2015-01-22 01:27:31 +00:00
|
|
|
keys[','] = actionSetSortColumn;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['-'] = actionExpandOrCollapse;
|
2015-01-22 01:27:31 +00:00
|
|
|
keys['.'] = actionSetSortColumn;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['/'] = actionIncSearch;
|
|
|
|
keys['<'] = actionSetSortColumn;
|
2015-01-22 01:27:31 +00:00
|
|
|
keys['='] = actionExpandOrCollapse;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['>'] = actionSetSortColumn;
|
|
|
|
keys['?'] = actionHelp;
|
|
|
|
keys['C'] = actionSetup;
|
2016-05-05 13:30:06 +00:00
|
|
|
keys['F'] = Action_follow;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['H'] = actionToggleUserlandThreads;
|
|
|
|
keys['I'] = actionInvertSortOrder;
|
|
|
|
keys['K'] = actionToggleKernelThreads;
|
|
|
|
keys['M'] = actionSortByMemory;
|
2020-12-19 14:48:07 +00:00
|
|
|
keys['N'] = actionSortByPID;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['P'] = actionSortByCPU;
|
2015-01-22 01:27:31 +00:00
|
|
|
keys['S'] = actionSetup;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['T'] = actionSortByTime;
|
2015-01-22 01:27:31 +00:00
|
|
|
keys['U'] = actionUntagAll;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['Z'] = actionTogglePauseProcessUpdate;
|
|
|
|
keys['['] = actionLowerPriority;
|
|
|
|
keys['\014'] = actionRedraw; // Ctrl+L
|
|
|
|
keys['\177'] = actionCollapseIntoParent;
|
|
|
|
keys['\\'] = actionIncFilter;
|
|
|
|
keys[']'] = actionHigherPriority;
|
|
|
|
keys['a'] = actionSetAffinity;
|
2015-01-22 01:27:31 +00:00
|
|
|
keys['c'] = actionTagAllChildren;
|
2015-12-02 21:58:22 +00:00
|
|
|
keys['e'] = actionShowEnvScreen;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['h'] = actionHelp;
|
|
|
|
keys['k'] = actionKill;
|
|
|
|
keys['l'] = actionLsof;
|
|
|
|
keys['m'] = actionToggleMergedCommand;
|
|
|
|
keys['p'] = actionToggleProgramPath;
|
|
|
|
keys['q'] = actionQuit;
|
|
|
|
keys['s'] = actionStrace;
|
|
|
|
keys['t'] = actionToggleTreeView;
|
|
|
|
keys['u'] = actionFilterByUser;
|
2020-10-07 16:36:20 +00:00
|
|
|
keys['w'] = actionShowCommandScreen;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys['x'] = actionShowLocks;
|
|
|
|
keys[KEY_F(1)] = actionHelp;
|
|
|
|
keys[KEY_F(2)] = actionSetup;
|
|
|
|
keys[KEY_F(3)] = actionIncSearch;
|
|
|
|
keys[KEY_F(4)] = actionIncFilter;
|
|
|
|
keys[KEY_F(5)] = actionToggleTreeView;
|
|
|
|
keys[KEY_F(6)] = actionSetSortColumn;
|
|
|
|
keys[KEY_F(7)] = actionHigherPriority;
|
|
|
|
keys[KEY_F(8)] = actionLowerPriority;
|
|
|
|
keys[KEY_F(9)] = actionKill;
|
2020-12-21 19:40:00 +00:00
|
|
|
keys[KEY_F(10)] = actionQuit;
|
|
|
|
keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
|
2020-12-21 14:53:42 +00:00
|
|
|
keys[KEY_RECLICK] = actionExpandOrCollapse;
|
2015-01-22 01:27:31 +00:00
|
|
|
}
|