aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lange <DLange@git.local>2023-02-05 04:25:56 +0100
committerDaniel Lange <DLange@git.local>2023-02-05 04:25:56 +0100
commitf288666edc9180a2e81e6655951878124f321df6 (patch)
treeda70bf44b2423f6f8e9a070c063fed79d190b489
parent937052b231259a47d881d539ad5748245ef55b99 (diff)
downloaddebian_htop-f288666edc9180a2e81e6655951878124f321df6.tar.gz
debian_htop-f288666edc9180a2e81e6655951878124f321df6.tar.bz2
debian_htop-f288666edc9180a2e81e6655951878124f321df6.zip
New upstream version 3.2.2upstream/3.2.2
-rw-r--r--.github/dependabot.yml9
-rw-r--r--.github/workflows/build_release.yml2
-rw-r--r--.github/workflows/ci.yml48
-rw-r--r--.github/workflows/codeql-analysis.yml49
-rw-r--r--.gitignore3
-rw-r--r--Action.c38
-rw-r--r--Action.h1
-rw-r--r--AffinityPanel.c2
-rw-r--r--AvailableColumnsPanel.c2
-rw-r--r--AvailableMetersPanel.c2
-rw-r--r--AvailableMetersPanel.h2
-rw-r--r--CPUMeter.c18
-rw-r--r--CRT.c81
-rw-r--r--CRT.h4
-rw-r--r--ChangeLog40
-rw-r--r--ColumnsPanel.c2
-rw-r--r--CommandLine.c56
-rw-r--r--Compat.c37
-rw-r--r--Compat.h5
-rw-r--r--DiskIOMeter.c10
-rw-r--r--DisplayOptionsPanel.c2
-rw-r--r--Header.c11
-rw-r--r--MainPanel.c18
-rw-r--r--MemoryMeter.c20
-rw-r--r--MemoryMeter.h8
-rw-r--r--MetersPanel.c7
-rw-r--r--NetworkIOMeter.c15
-rw-r--r--OpenFilesScreen.c2
-rw-r--r--Panel.c6
-rw-r--r--Process.c90
-rw-r--r--Process.h6
-rw-r--r--ProcessList.c4
-rw-r--r--ProcessLocksScreen.c15
-rw-r--r--ProcessLocksScreen.h4
-rw-r--r--README3
-rw-r--r--RichString.c6
-rw-r--r--ScreenManager.c28
-rw-r--r--ScreenManager.h4
-rw-r--r--ScreensPanel.c36
-rw-r--r--ScreensPanel.h2
-rw-r--r--Settings.c33
-rw-r--r--Settings.h2
-rw-r--r--SwapMeter.c6
-rw-r--r--SwapMeter.h5
-rw-r--r--TraceScreen.c6
-rw-r--r--UsersTable.c2
-rw-r--r--XUtils.c31
-rw-r--r--XUtils.h2
-rw-r--r--configure.ac10
-rw-r--r--darwin/DarwinProcess.c2
-rw-r--r--darwin/DarwinProcessList.c3
-rw-r--r--darwin/Platform.c22
-rw-r--r--darwin/Platform.h18
-rw-r--r--darwin/PlatformHelpers.c9
-rw-r--r--darwin/PlatformHelpers.h2
-rw-r--r--docs/images/screenshot.pngbin80937 -> 46142 bytes
-rw-r--r--dragonflybsd/DragonFlyBSDProcessList.c4
-rw-r--r--dragonflybsd/Platform.c24
-rw-r--r--dragonflybsd/Platform.h18
-rw-r--r--freebsd/FreeBSDProcessList.c12
-rw-r--r--freebsd/Platform.c30
-rw-r--r--freebsd/Platform.h18
-rw-r--r--htop.1.in7
-rw-r--r--htop.pngbin3537 -> 2616 bytes
-rw-r--r--linux/CGroupUtils.c10
-rw-r--r--linux/CGroupUtils.h2
-rw-r--r--linux/LinuxProcess.c4
-rw-r--r--linux/LinuxProcessList.c95
-rw-r--r--linux/Platform.c167
-rw-r--r--linux/Platform.h18
-rw-r--r--linux/SystemdMeter.c6
-rw-r--r--netbsd/Platform.c26
-rw-r--r--netbsd/Platform.h18
-rw-r--r--openbsd/Platform.c24
-rw-r--r--openbsd/Platform.h18
-rw-r--r--pcp-htop.5.in2
-rw-r--r--pcp/PCPDynamicColumn.c7
-rw-r--r--pcp/PCPDynamicMeter.c10
-rw-r--r--pcp/PCPProcessList.c2
-rw-r--r--pcp/Platform.c84
-rw-r--r--pcp/Platform.h2
-rw-r--r--solaris/Platform.c24
-rw-r--r--solaris/Platform.h18
-rw-r--r--unsupported/Platform.c10
-rw-r--r--unsupported/Platform.h18
85 files changed, 992 insertions, 537 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..5516fd6
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,9 @@
+---
+
+version: 2
+
+updates:
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: weekly
diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml
index 8c87915..655853c 100644
--- a/.github/workflows/build_release.yml
+++ b/.github/workflows/build_release.yml
@@ -11,7 +11,7 @@ jobs:
name: build
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v3
with:
submodules: true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index af8ed88..2e75ec0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,7 +11,7 @@ jobs:
build-ubuntu-latest-minimal-gcc:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends libncursesw5-dev
- name: Bootstrap
@@ -31,16 +31,16 @@ jobs:
build-ubuntu-latest-minimal-clang:
runs-on: ubuntu-latest
env:
- CC: clang-12
+ CC: clang-15
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: install clang repo
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
- sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y
+ sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main' -y
sudo apt-get update -q
- name: Install Dependencies
- run: sudo apt-get install --no-install-recommends clang-12 libncursesw5-dev
+ run: sudo apt-get install --no-install-recommends clang-15 libncursesw5-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
@@ -57,7 +57,7 @@ jobs:
CFLAGS: -O3 -g -flto
LDFLAGS: -O3 -g -flto -Wl,--as-needed
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
- name: Bootstrap
@@ -72,16 +72,16 @@ jobs:
build-ubuntu-latest-full-featured-clang:
runs-on: ubuntu-latest
env:
- CC: clang-12
+ CC: clang-15
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: install clang repo
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
- sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y
+ sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main' -y
sudo apt-get update -q
- name: Install Dependencies
- run: sudo apt-get install --no-install-recommends clang-12 libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
+ run: sudo apt-get install --no-install-recommends clang-15 libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
@@ -98,7 +98,7 @@ jobs:
CFLAGS: -O3 -g -flto
LDFLAGS: -O3 -g -flto
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends libncursesw5-dev libtinfo-dev libgpm-dev libsensors4-dev libcap-dev
- name: Bootstrap
@@ -111,14 +111,10 @@ jobs:
run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-static --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --disable-hwloc --disable-delayacct --enable-sensors --enable-capabilities'
build-ubuntu-latest-pcp:
- # Turns out 'ubuntu-latest' can be older than 20.04, we want PCP v5+
- runs-on: ubuntu-20.04
- env:
- # Until Ubuntu catches up with pcp-5.2.3+:
- # pcp/Platform.c:309:45: warning: passing argument 2 of ‘pmLookupName’ from incompatible pointer type [-Wincompatible-pointer-types]
- CFLAGS: -Wno-error=incompatible-pointer-types
+ # we want PCP v5.2.3+
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends libpcp3-dev libncursesw5-dev libtinfo-dev libgpm-dev
- name: Bootstrap
@@ -131,29 +127,29 @@ jobs:
build-ubuntu-latest-clang-analyzer:
runs-on: ubuntu-latest
env:
- CC: clang-12
+ CC: clang-15
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: install clang repo
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
- sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y
+ sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main' -y
sudo apt-get update -q
- name: Install Dependencies
- run: sudo apt-get install --no-install-recommends clang-12 clang-tools-12 libncursesw5-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
+ run: sudo apt-get install --no-install-recommends clang-15 clang-tools-15 libncursesw5-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
- run: scan-build-12 -analyze-headers --status-bugs ./configure --enable-debug --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-delayacct --enable-sensors --enable-capabilities
+ run: scan-build-15 -analyze-headers --status-bugs ./configure --enable-debug --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-delayacct --enable-sensors --enable-capabilities
- name: Build
- run: scan-build-12 -analyze-headers --status-bugs make -j"$(nproc)"
+ run: scan-build-15 -analyze-headers --status-bugs make -j"$(nproc)"
build-macos-latest-clang:
runs-on: macOS-latest
env:
CC: clang
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Install Dependencies
run: brew install automake
- name: Bootstrap
@@ -168,6 +164,6 @@ jobs:
whitespace_check:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: check-whitespaces
run: git diff-tree --check $(git hash-object -t tree /dev/null) HEAD
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000..17356b6
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,49 @@
+name: "CodeQL"
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+ schedule:
+ - cron: '0 1 * * 0'
+
+permissions:
+ contents: read
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ security-events: write
+
+ env:
+ # Enable format attributes in ncurses headers
+ # Enable fortified memory/string handling
+ CPPFLAGS: -DGCC_PRINTF -DGCC_SCANF -D_FORTIFY_SOURCE=2
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: cpp
+
+ - name: Install Dependencies
+ run: sudo apt-get install --no-install-recommends libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
+
+ - name: Bootstrap
+ run: ./autogen.sh
+
+ - name: Configure
+ run: ./configure --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities
+
+ - name: Build
+ run: make
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
diff --git a/.gitignore b/.gitignore
index 8262449..50f3bd1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,3 +51,6 @@ callgrind.out.*
# IDE workspace configurations
/.idea/
/.vscode/
+
+# Language Servers
+/.cache/clangd/
diff --git a/Action.c b/Action.c
index b765248..81432f5 100644
--- a/Action.c
+++ b/Action.c
@@ -213,22 +213,37 @@ static Htop_Reaction actionSortByTime(State* st) {
static Htop_Reaction actionToggleKernelThreads(State* st) {
st->settings->hideKernelThreads = !st->settings->hideKernelThreads;
+ st->settings->lastUpdate++;
+
return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionToggleUserlandThreads(State* st) {
st->settings->hideUserlandThreads = !st->settings->hideUserlandThreads;
+ st->settings->lastUpdate++;
+
+ return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
+}
+
+static Htop_Reaction actionToggleRunningInContainer(State* st) {
+ st->settings->hideRunningInContainer = !st->settings->hideRunningInContainer;
+ st->settings->lastUpdate++;
+
return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionToggleProgramPath(State* st) {
st->settings->showProgramPath = !st->settings->showProgramPath;
- return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
+ st->settings->lastUpdate++;
+
+ return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionToggleMergedCommand(State* st) {
st->settings->showMergedCommand = !st->settings->showMergedCommand;
- return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
+ st->settings->lastUpdate++;
+
+ return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_UPDATE_PANELHDR;
}
static Htop_Reaction actionToggleTreeView(State* st) {
@@ -240,6 +255,11 @@ static Htop_Reaction actionToggleTreeView(State* st) {
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
+static Htop_Reaction actionToggleHideMeters(State* st) {
+ st->hideMeters = !st->hideMeters;
+ return HTOP_RESIZE | HTOP_KEEP_FOLLOWING;
+}
+
static Htop_Reaction actionExpandOrCollapseAllBranches(State* st) {
ScreenSettings* ss = st->settings->ss;
if (!ss->treeView) {
@@ -285,10 +305,13 @@ static Htop_Reaction actionLowerPriority(State* st) {
static Htop_Reaction actionInvertSortOrder(State* st) {
ScreenSettings_invertSortOrder(st->settings->ss);
st->pl->needsSort = true;
- return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
+ return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_UPDATE_PANELHDR;
}
static Htop_Reaction actionExpandOrCollapse(State* st) {
+ if (!st->settings->ss->treeView)
+ return HTOP_OK;
+
bool changed = expandCollapse((Panel*)st->mainPanel);
return changed ? HTOP_RECALCULATE : HTOP_OK;
}
@@ -312,7 +335,7 @@ static Htop_Reaction actionNextScreen(State* st) {
settings->ssIndex = 0;
}
settings->ss = settings->screens[settings->ssIndex];
- return HTOP_REFRESH;
+ return HTOP_UPDATE_PANELHDR | HTOP_REFRESH;
}
static Htop_Reaction actionPrevScreen(State* st) {
@@ -323,7 +346,7 @@ static Htop_Reaction actionPrevScreen(State* st) {
settings->ssIndex--;
}
settings->ss = settings->screens[settings->ssIndex];
- return HTOP_REFRESH;
+ return HTOP_UPDATE_PANELHDR | HTOP_REFRESH;
}
Htop_Reaction Action_setScreenTab(Settings* settings, int x) {
@@ -337,7 +360,7 @@ Htop_Reaction Action_setScreenTab(Settings* settings, int x) {
if (x <= s + len + 1) {
settings->ssIndex = i;
settings->ss = settings->screens[i];
- return HTOP_REFRESH;
+ return HTOP_UPDATE_PANELHDR | HTOP_REFRESH;
}
s += len + 3;
}
@@ -506,6 +529,7 @@ static const struct {
bool roInactive;
const char* info;
} helpLeft[] = {
+ { .key = " #: ", .roInactive = false, .info = "hide/show header meters" },
{ .key = " Tab: ", .roInactive = false, .info = "switch to next screen tab" },
{ .key = " Arrows: ", .roInactive = false, .info = "scroll process list" },
{ .key = " Digits: ", .roInactive = false, .info = "incremental PID search" },
@@ -732,6 +756,7 @@ static Htop_Reaction actionShowCommandScreen(State* st) {
void Action_setBindings(Htop_Action* keys) {
keys[' '] = actionTag;
+ keys['#'] = actionToggleHideMeters;
keys['*'] = actionExpandOrCollapseAllBranches;
keys['+'] = actionExpandOrCollapse;
keys[','] = actionSetSortColumn;
@@ -749,6 +774,7 @@ void Action_setBindings(Htop_Action* keys) {
keys['K'] = actionToggleKernelThreads;
keys['M'] = actionSortByMemory;
keys['N'] = actionSortByPID;
+ keys['O'] = actionToggleRunningInContainer;
keys['P'] = actionSortByCPU;
keys['S'] = actionSetup;
keys['T'] = actionSortByTime;
diff --git a/Action.h b/Action.h
index 06af188..09b68bd 100644
--- a/Action.h
+++ b/Action.h
@@ -43,6 +43,7 @@ typedef struct State_ {
Header* header;
bool pauseProcessUpdate;
bool hideProcessSelection;
+ bool hideMeters;
} State;
static inline bool State_hideFunctionBar(const State* st) {
diff --git a/AffinityPanel.c b/AffinityPanel.c
index 9875a5c..b724397 100644
--- a/AffinityPanel.c
+++ b/AffinityPanel.c
@@ -201,7 +201,7 @@ static HandlerResult AffinityPanel_eventHandler(Panel* super, int ch) {
MaskItem* selected = (MaskItem*) Panel_getSelected(super);
bool keepSelected = true;
- switch(ch) {
+ switch (ch) {
case KEY_MOUSE:
case KEY_RECLICK:
case ' ':
diff --git a/AvailableColumnsPanel.c b/AvailableColumnsPanel.c
index 7720bef..b8c09c7 100644
--- a/AvailableColumnsPanel.c
+++ b/AvailableColumnsPanel.c
@@ -45,7 +45,7 @@ static HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
AvailableColumnsPanel* this = (AvailableColumnsPanel*) super;
HandlerResult result = IGNORED;
- switch(ch) {
+ switch (ch) {
case 13:
case KEY_ENTER:
case KEY_F(5):
diff --git a/AvailableMetersPanel.c b/AvailableMetersPanel.c
index 368f494..c7ab89b 100644
--- a/AvailableMetersPanel.c
+++ b/AvailableMetersPanel.c
@@ -54,7 +54,7 @@ static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) {
HandlerResult result = IGNORED;
bool update = false;
- switch(ch) {
+ switch (ch) {
case KEY_F(5):
case 'l':
case 'L':
diff --git a/AvailableMetersPanel.h b/AvailableMetersPanel.h
index f5f7a2d..1c0555a 100644
--- a/AvailableMetersPanel.h
+++ b/AvailableMetersPanel.h
@@ -29,6 +29,6 @@ typedef struct AvailableMetersPanel_ {
extern const PanelClass AvailableMetersPanel_class;
-AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, size_t columns, MetersPanel **meterPanels, ScreenManager* scr, const ProcessList* pl);
+AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, size_t columns, MetersPanel** meterPanels, ScreenManager* scr, const ProcessList* pl);
#endif
diff --git a/CPUMeter.c b/CPUMeter.c
index 9974db9..ba00595 100644
--- a/CPUMeter.c
+++ b/CPUMeter.c
@@ -167,6 +167,18 @@ static void CPUMeter_display(const Object* cast, RichString* out) {
}
}
+ if (this->pl->settings->showCPUFrequency) {
+ char cpuFrequencyBuffer[10];
+ double cpuFrequency = this->values[CPU_METER_FREQUENCY];
+ if (isnan(cpuFrequency)) {
+ len = xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A ");
+ } else {
+ len = xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz ", (unsigned)cpuFrequency);
+ }
+ RichString_appendAscii(out, CRT_colors[METER_TEXT], "freq: ");
+ RichString_appendnWide(out, CRT_colors[METER_VALUE], cpuFrequencyBuffer, len);
+ }
+
#ifdef BUILD_WITH_CPU_TEMP
if (this->pl->settings->showCPUTemperature) {
char cpuTemperatureBuffer[10];
@@ -187,7 +199,7 @@ static void CPUMeter_display(const Object* cast, RichString* out) {
static void AllCPUsMeter_getRange(const Meter* this, int* start, int* count) {
const CPUMeterData* data = this->meterData;
unsigned int cpus = data->cpus;
- switch(Meter_name(this)[0]) {
+ switch (Meter_name(this)[0]) {
default:
case 'A': // All
*start = 0;
@@ -195,10 +207,10 @@ static void AllCPUsMeter_getRange(const Meter* this, int* start, int* count) {
break;
case 'L': // First Half
*start = 0;
- *count = (cpus+1) / 2;
+ *count = (cpus + 1) / 2;
break;
case 'R': // Second Half
- *start = (cpus+1) / 2;
+ *start = (cpus + 1) / 2;
*count = cpus / 2;
break;
}
diff --git a/CRT.c b/CRT.c
index 868f237..64c259f 100644
--- a/CRT.c
+++ b/CRT.c
@@ -134,7 +134,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[METER_VALUE] = A_BOLD | ColorPair(Cyan, Black),
[METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
[METER_VALUE_IOREAD] = ColorPair(Green, Black),
- [METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
+ [METER_VALUE_IOWRITE] = A_BOLD | ColorPair(Blue, Black),
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black),
[METER_VALUE_OK] = ColorPair(Green, Black),
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
@@ -156,7 +156,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[PROCESS_THREAD] = ColorPair(Green, Black),
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Black),
[PROCESS_COMM] = ColorPair(Magenta, Black),
- [PROCESS_THREAD_COMM] = ColorPair(Blue, Black),
+ [PROCESS_THREAD_COMM] = A_BOLD | ColorPair(Blue, Black),
[BAR_BORDER] = A_BOLD,
[BAR_SHADOW] = A_BOLD | ColorPairGrayBlack,
[SWAP] = ColorPair(Red, Black),
@@ -164,14 +164,14 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[GRAPH_1] = A_BOLD | ColorPair(Cyan, Black),
[GRAPH_2] = ColorPair(Cyan, Black),
[MEMORY_USED] = ColorPair(Green, Black),
- [MEMORY_BUFFERS] = ColorPair(Blue, Black),
+ [MEMORY_BUFFERS] = A_BOLD | ColorPair(Blue, Black),
[MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue, Black),
[MEMORY_CACHE] = ColorPair(Yellow, Black),
[MEMORY_SHARED] = ColorPair(Magenta, Black),
[HUGEPAGE_1] = ColorPair(Green, Black),
[HUGEPAGE_2] = ColorPair(Yellow, Black),
[HUGEPAGE_3] = ColorPair(Red, Black),
- [HUGEPAGE_4] = ColorPair(Blue, Black),
+ [HUGEPAGE_4] = A_BOLD | ColorPair(Blue, Black),
[LOAD_AVERAGE_FIFTEEN] = ColorPair(Cyan, Black),
[LOAD_AVERAGE_FIVE] = A_BOLD | ColorPair(Cyan, Black),
[LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White, Black),
@@ -185,7 +185,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CHECK_MARK] = A_BOLD,
[CHECK_TEXT] = A_NORMAL,
[HOSTNAME] = A_BOLD,
- [CPU_NICE] = ColorPair(Blue, Black),
+ [CPU_NICE] = A_BOLD | ColorPair(Blue, Black),
[CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue, Black),
[CPU_NORMAL] = ColorPair(Green, Black),
[CPU_SYSTEM] = ColorPair(Red, Black),
@@ -202,19 +202,19 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Cyan, Black),
[PRESSURE_STALL_SIXTY] = A_BOLD | ColorPair(Cyan, Black),
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Black),
- [ZFS_MFU] = ColorPair(Blue, Black),
+ [ZFS_MFU] = A_BOLD | ColorPair(Blue, Black),
[ZFS_MRU] = ColorPair(Yellow, Black),
[ZFS_ANON] = ColorPair(Magenta, Black),
[ZFS_HEADER] = ColorPair(Cyan, Black),
[ZFS_OTHER] = ColorPair(Magenta, Black),
- [ZFS_COMPRESSED] = ColorPair(Blue, Black),
+ [ZFS_COMPRESSED] = A_BOLD | ColorPair(Blue, Black),
[ZFS_RATIO] = ColorPair(Magenta, Black),
[ZRAM] = ColorPair(Yellow, Black),
[DYNAMIC_GRAY] = ColorPairGrayBlack,
[DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack,
[DYNAMIC_RED] = ColorPair(Red, Black),
[DYNAMIC_GREEN] = ColorPair(Green, Black),
- [DYNAMIC_BLUE] = ColorPair(Blue, Black),
+ [DYNAMIC_BLUE] = A_BOLD | ColorPair(Blue, Black),
[DYNAMIC_CYAN] = ColorPair(Cyan, Black),
[DYNAMIC_MAGENTA] = ColorPair(Magenta, Black),
[DYNAMIC_YELLOW] = ColorPair(Yellow, Black),
@@ -408,11 +408,11 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue, White),
[CPU_STEAL] = ColorPair(Cyan, White),
[CPU_GUEST] = ColorPair(Cyan, White),
- [PANEL_EDIT] = ColorPair(White,Blue),
- [SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Black,White),
- [SCREENS_OTH_TEXT] = A_BOLD | ColorPair(Black,White),
- [SCREENS_CUR_BORDER] = ColorPair(Green,Green),
- [SCREENS_CUR_TEXT] = ColorPair(Black,Green),
+ [PANEL_EDIT] = ColorPair(White, Blue),
+ [SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Black, White),
+ [SCREENS_OTH_TEXT] = A_BOLD | ColorPair(Black, White),
+ [SCREENS_CUR_BORDER] = ColorPair(Green, Green),
+ [SCREENS_CUR_TEXT] = ColorPair(Black, Green),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, White),
[PRESSURE_STALL_SIXTY] = ColorPair(Black, White),
[PRESSURE_STALL_TEN] = ColorPair(Black, White),
@@ -515,11 +515,11 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue, Black),
[CPU_STEAL] = ColorPair(Black, Black),
[CPU_GUEST] = ColorPair(Black, Black),
- [PANEL_EDIT] = ColorPair(White,Blue),
- [SCREENS_OTH_BORDER] = ColorPair(Blue,Black),
- [SCREENS_OTH_TEXT] = ColorPair(Blue,Black),
- [SCREENS_CUR_BORDER] = ColorPair(Green,Green),
- [SCREENS_CUR_TEXT] = ColorPair(Black,Green),
+ [PANEL_EDIT] = ColorPair(White, Blue),
+ [SCREENS_OTH_BORDER] = ColorPair(Blue, Black),
+ [SCREENS_OTH_TEXT] = ColorPair(Blue, Black),
+ [SCREENS_CUR_BORDER] = ColorPair(Green, Green),
+ [SCREENS_CUR_TEXT] = ColorPair(Black, Green),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, Black),
[PRESSURE_STALL_SIXTY] = ColorPair(Black, Black),
[PRESSURE_STALL_TEN] = ColorPair(Black, Black),
@@ -622,11 +622,11 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Black, Blue),
[CPU_STEAL] = ColorPair(White, Blue),
[CPU_GUEST] = ColorPair(White, Blue),
- [PANEL_EDIT] = ColorPair(White,Blue),
- [SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Yellow,Blue),
- [SCREENS_OTH_TEXT] = ColorPair(Cyan,Blue),
- [SCREENS_CUR_BORDER] = ColorPair(Cyan,Cyan),
- [SCREENS_CUR_TEXT] = ColorPair(Black,Cyan),
+ [PANEL_EDIT] = ColorPair(White, Blue),
+ [SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Yellow, Blue),
+ [SCREENS_OTH_TEXT] = ColorPair(Cyan, Blue),
+ [SCREENS_CUR_BORDER] = ColorPair(Cyan, Cyan),
+ [SCREENS_CUR_TEXT] = ColorPair(Black, Cyan),
[PRESSURE_STALL_THREEHUNDRED] = A_BOLD | ColorPair(Black, Blue),
[PRESSURE_STALL_SIXTY] = A_NORMAL | ColorPair(White, Blue),
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Blue),
@@ -727,11 +727,11 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue, Black),
[CPU_STEAL] = ColorPair(Cyan, Black),
[CPU_GUEST] = ColorPair(Cyan, Black),
- [PANEL_EDIT] = ColorPair(White,Cyan),
- [SCREENS_OTH_BORDER] = ColorPair(White,Black),
- [SCREENS_OTH_TEXT] = ColorPair(Cyan,Black),
- [SCREENS_CUR_BORDER] = A_BOLD | ColorPair(White,Black),
- [SCREENS_CUR_TEXT] = A_BOLD | ColorPair(Green,Black),
+ [PANEL_EDIT] = ColorPair(White, Cyan),
+ [SCREENS_OTH_BORDER] = ColorPair(White, Black),
+ [SCREENS_OTH_TEXT] = ColorPair(Cyan, Black),
+ [SCREENS_CUR_BORDER] = A_BOLD | ColorPair(White, Black),
+ [SCREENS_CUR_TEXT] = A_BOLD | ColorPair(Green, Black),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Green, Black),
[PRESSURE_STALL_SIXTY] = ColorPair(Green, Black),
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(Green, Black),
@@ -834,7 +834,7 @@ static void dumpStderr(void) {
fprintf(stderr, ">>>>>>>>>> stderr output >>>>>>>>>>\n");
header = true;
}
- (void)! write(STDERR_FILENO, buffer, res);
+ full_write(STDERR_FILENO, buffer, res);
}
}
@@ -900,8 +900,8 @@ void CRT_resetSignalHandlers(void) {
signal(SIGQUIT, SIG_DFL);
}
-void CRT_setMouse(bool enabled) {
#ifdef HAVE_GETMOUSE
+void CRT_setMouse(bool enabled) {
if (enabled) {
#if NCURSES_MOUSE_VERSION > 1
mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL);
@@ -911,13 +911,12 @@ void CRT_setMouse(bool enabled) {
} else {
mousemask(0, NULL);
}
-#endif
}
+#endif
void CRT_init(const Settings* settings, bool allowUnicode) {
- redirectStderr();
-
initscr();
+ redirectStderr();
noecho();
CRT_crashSettings = settings;
CRT_delay = &(settings->delay);
@@ -1012,10 +1011,12 @@ IGNORE_WCASTQUAL_END
CRT_degreeSign = initDegreeSign();
}
-void CRT_done() {
- attron(CRT_colors[RESET_COLOR]);
+void CRT_done(void) {
+ int resetColor = CRT_colors ? CRT_colors[RESET_COLOR] : CRT_colorSchemes[COLORSCHEME_DEFAULT][RESET_COLOR];
+
+ attron(resetColor);
mvhline(LINES - 1, 0, ' ', COLS);
- attroff(CRT_colors[RESET_COLOR]);
+ attroff(resetColor);
refresh();
curs_set(1);
@@ -1031,7 +1032,7 @@ void CRT_fatalError(const char* note) {
exit(2);
}
-int CRT_readKey() {
+int CRT_readKey(void) {
nocbreak();
cbreak();
nodelay(stdscr, FALSE);
@@ -1040,13 +1041,13 @@ int CRT_readKey() {
return ret;
}
-void CRT_disableDelay() {
+void CRT_disableDelay(void) {
nocbreak();
cbreak();
nodelay(stdscr, TRUE);
}
-void CRT_enableDelay() {
+void CRT_enableDelay(void) {
halfdelay(*CRT_delay);
}
@@ -1095,7 +1096,7 @@ static void print_backtrace(void) {
unw_get_proc_name(&cursor, symbolName, sizeof(symbolName), &offset);
unw_proc_info_t pip;
- pip.unwind_info = NULL;
+ pip.unwind_info = 0;
const char* fname = "?";
const void* ptr = 0;
diff --git a/CRT.h b/CRT.h
index 297e896..c06d3ae 100644
--- a/CRT.h
+++ b/CRT.h
@@ -185,7 +185,11 @@ extern int CRT_scrollWheelVAmount;
extern ColorScheme CRT_colorScheme;
+#ifdef HAVE_GETMOUSE
void CRT_setMouse(bool enabled);
+#else
+#define CRT_setMouse(enabled)
+#endif
void CRT_init(const Settings* settings, bool allowUnicode);
diff --git a/ChangeLog b/ChangeLog
index 8f5266c..5717a52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+What's new in version 3.2.2
+
+* CPUMeter now can show frequency in text mode
+* Add option to render distribution path prefixes shadowed
+* DiskIOMeter converts to bytes per second (not per interval)
+* DiskIOMeter uses complete units, including missing "iB/s"
+* DiskIOMeter indicates read and write in meter mode
+* NetworkIOMeter converts to packets per second, shows packet rate
+* Allow continued process following when changing display settings
+* Update the panel header when changing to another tab
+* Drop margin around the header if there are no meters
+* Use Unicode replacement character for non-printable characters
+* Default color preset uses bold blue for better visibility
+* Update the Panel header on sort order inversions ('I')
+* Toggle the header meters with pound key
+* Fix ScreenPanel to handle quitting the panel while renaming
+* Add fallback for HOME environment variable using passwd database
+* Replace meaningless ID column with FD column in lock screen
+* Use device format in the lock screen matching the files screen
+* On Linux, improvements to file-descriptor lock detection
+* On Linux, further distinguish systemd states in the SystemdMeter
+* On Linux, improvements to cgroup and container identification
+* On Linux, support openat(2) without readlinkat(2) platforms
+* On Darwin, fix current process buffer handling for busy systems
+* On DragonFly BSD, fix incorrect processor time of processes
+* On FreeBSD, fix an issue with the memory graph not showing correctly
+* On FreeBSD, add support for displaying shared memory usage
+* On PCP, use pmLookupDescs(3) if available for efficiency
+* On PCP, normalize generic columns values for consistent display
+* On PCP, changes preparing for configurable, dynamic screens
+* Handle invalid process columns from the configuration file
+* Avoid undefined behaviour with deeply nested processes
+* Fix crash when removing the currently active screen
+* Prevent possible crash on a very early error path
+* Include automake for Debian/Ubuntu
+* Restore non-mouse support
+* Reject unsupported command line arguments
+* Document idle process state
+* Clarify M_TRS/M_DRS columns
+
What's new in version 3.2.1
* Fix setting to show all branches collapsed by default
diff --git a/ColumnsPanel.c b/ColumnsPanel.c
index 2482693..d53fff2 100644
--- a/ColumnsPanel.c
+++ b/ColumnsPanel.c
@@ -38,7 +38,7 @@ static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
HandlerResult result = IGNORED;
int size = Panel_size(super);
- switch(ch) {
+ switch (ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
diff --git a/CommandLine.c b/CommandLine.c
index d21f482..682e054 100644
--- a/CommandLine.c
+++ b/CommandLine.c
@@ -66,7 +66,6 @@ static void printHelpFlag(const char* name) {
"-V --version Print version info\n");
Platform_longOptionsUsage(name);
printf("\n"
- "Long options may be passed with a single dash.\n\n"
"Press F1 inside %s for online help.\n"
"See 'man %s' for more information.\n", name, name);
}
@@ -80,7 +79,9 @@ typedef struct CommandLineSettings_ {
int sortKey;
int delay;
bool useColors;
+#ifdef HAVE_GETMOUSE
bool enableMouse;
+#endif
bool treeView;
bool allowUnicode;
bool highlightChanges;
@@ -97,7 +98,9 @@ static CommandLineStatus parseArguments(const char* program, int argc, char** ar
.sortKey = 0,
.delay = -1,
.useColors = true,
+#ifdef HAVE_GETMOUSE
.enableMouse = true,
+#endif
.treeView = false,
.allowUnicode = true,
.highlightChanges = false,
@@ -143,7 +146,8 @@ static CommandLineStatus parseArguments(const char* program, int argc, char** ar
for (int j = 1; j < LAST_PROCESSFIELD; j++) {
const char* name = Process_fields[j].name;
const char* description = Process_fields[j].description;
- if (name) printf("%19s %s\n", name, description);
+ if (name)
+ printf("%19s %s\n", name, description);
}
return STATUS_OK_EXIT;
}
@@ -163,8 +167,10 @@ static CommandLineStatus parseArguments(const char* program, int argc, char** ar
break;
case 'd':
if (sscanf(optarg, "%16d", &(flags->delay)) == 1) {
- if (flags->delay < 1) flags->delay = 1;
- if (flags->delay > 100) flags->delay = 100;
+ if (flags->delay < 1)
+ flags->delay = 1;
+ if (flags->delay > 100)
+ flags->delay = 100;
} else {
fprintf(stderr, "Error: invalid delay value \"%s\".\n", optarg);
return STATUS_ERROR_EXIT;
@@ -172,7 +178,7 @@ static CommandLineStatus parseArguments(const char* program, int argc, char** ar
break;
case 'u':
{
- const char *username = optarg;
+ const char* username = optarg;
if (!username && optind < argc && argv[optind] != NULL &&
(argv[optind][0] != '\0' && argv[optind][0] != '-')) {
username = argv[optind++];
@@ -181,7 +187,7 @@ static CommandLineStatus parseArguments(const char* program, int argc, char** ar
if (!username) {
flags->userId = geteuid();
} else if (!Action_setUserOnly(username, &(flags->userId))) {
- for (const char *itr = username; *itr; ++itr)
+ for (const char* itr = username; *itr; ++itr)
if (!isdigit((unsigned char)*itr)) {
fprintf(stderr, "Error: invalid user \"%s\".\n", username);
return STATUS_ERROR_EXIT;
@@ -214,11 +220,11 @@ static CommandLineStatus parseArguments(const char* program, int argc, char** ar
flags->pidMatchList = Hashtable_new(8, false);
}
- while(pid) {
- unsigned int num_pid = atoi(pid);
- // deepcode ignore CastIntegerToAddress: we just want a non-NULL pointer here
- Hashtable_put(flags->pidMatchList, num_pid, (void *) 1);
- pid = strtok_r(NULL, ",", &saveptr);
+ while (pid) {
+ unsigned int num_pid = atoi(pid);
+ // deepcode ignore CastIntegerToAddress: we just want a non-NULL pointer here
+ Hashtable_put(flags->pidMatchList, num_pid, (void*) 1);
+ pid = strtok_r(NULL, ",", &saveptr);
}
free(argCopy);
@@ -230,19 +236,19 @@ static CommandLineStatus parseArguments(const char* program, int argc, char** ar
break;
}
case 'H': {
- const char *delay = optarg;
+ const char* delay = optarg;
if (!delay && optind < argc && argv[optind] != NULL &&
(argv[optind][0] != '\0' && argv[optind][0] != '-')) {
- delay = argv[optind++];
+ delay = argv[optind++];
}
if (delay) {
- if (sscanf(delay, "%16d", &(flags->highlightDelaySecs)) == 1) {
- if (flags->highlightDelaySecs < 1)
- flags->highlightDelaySecs = 1;
- } else {
- fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay);
- return STATUS_ERROR_EXIT;
- }
+ if (sscanf(delay, "%16d", &(flags->highlightDelaySecs)) == 1) {
+ if (flags->highlightDelaySecs < 1)
+ flags->highlightDelaySecs = 1;
+ } else {
+ fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay);
+ return STATUS_ERROR_EXIT;
+ }
}
flags->highlightChanges = true;
break;
@@ -259,6 +265,15 @@ static CommandLineStatus parseArguments(const char* program, int argc, char** ar
}
}
}
+
+ if (optind < argc) {
+ fprintf(stderr, "Error: unsupported non-option ARGV-elements:");
+ while (optind < argc)
+ fprintf(stderr, " %s", argv[optind++]);
+ fprintf(stderr, "\n");
+ return STATUS_ERROR_EXIT;
+ }
+
return STATUS_OK;
}
@@ -359,6 +374,7 @@ int CommandLine_run(const char* name, int argc, char** argv) {
.header = header,
.pauseProcessUpdate = false,
.hideProcessSelection = false,
+ .hideMeters = false,
};
MainPanel_setState(panel, &state);
diff --git a/Compat.c b/Compat.c
index 8c88138..d0ad2cc 100644
--- a/Compat.c
+++ b/Compat.c
@@ -11,6 +11,7 @@ in the source distribution for its full text.
#include <errno.h>
#include <fcntl.h> // IWYU pragma: keep
+#include <limits.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h> // IWYU pragma: keep
@@ -18,6 +19,12 @@ in the source distribution for its full text.
#include "XUtils.h" // IWYU pragma: keep
+/* GNU/Hurd does not have PATH_MAX in limits.h */
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+
+
int Compat_faccessat(int dirfd,
const char* pathname,
int mode,
@@ -117,3 +124,33 @@ ssize_t Compat_readlinkat(int dirfd,
#endif
}
+
+ssize_t Compat_readlink(openat_arg_t dirfd,
+ const char* pathname,
+ char* buf,
+ size_t bufsize) {
+
+#ifdef HAVE_OPENAT
+
+ char fdPath[32];
+ xSnprintf(fdPath, sizeof(fdPath), "/proc/self/fd/%d", dirfd);
+
+ char dirPath[PATH_MAX + 1];
+ ssize_t r = readlink(fdPath, dirPath, sizeof(dirPath) - 1);
+ if (r < 0)
+ return r;
+
+ dirPath[r] = '\0';
+
+ char linkPath[PATH_MAX + 1];
+ xSnprintf(linkPath, sizeof(linkPath), "%s/%s", dirPath, pathname);
+
+#else
+
+ char linkPath[PATH_MAX + 1];
+ xSnprintf(linkPath, sizeof(linkPath), "%s/%s", dirfd, pathname);
+
+#endif /* HAVE_OPENAT */
+
+ return readlink(linkPath, buf, bufsize);
+}
diff --git a/Compat.h b/Compat.h
index 2b5e205..1c4794e 100644
--- a/Compat.h
+++ b/Compat.h
@@ -56,4 +56,9 @@ ssize_t Compat_readlinkat(int dirfd,
char* buf,
size_t bufsize);
+ssize_t Compat_readlink(openat_arg_t dirfd,
+ const char* pathname,
+ char* buf,
+ size_t bufsize);
+
#endif /* HEADER_Compat */
diff --git a/DiskIOMeter.c b/DiskIOMeter.c
index 12c87de..adab8f7 100644
--- a/DiskIOMeter.c
+++ b/DiskIOMeter.c
@@ -64,7 +64,8 @@ static void DiskIOMeter_updateValues(Meter* this) {
if (data.totalBytesRead > cached_read_total) {
diff = data.totalBytesRead - cached_read_total;
- diff /= 1024; /* Meter_humanUnit() expects unit in kilo */
+ diff = (1000 * diff) / passedTimeInMs; /* convert to B/s */
+ diff /= ONE_K; /* convert to KiB/s */
cached_read_diff = (uint32_t)diff;
} else {
cached_read_diff = 0;
@@ -73,7 +74,8 @@ static void DiskIOMeter_updateValues(Meter* this) {
if (data.totalBytesWritten > cached_write_total) {
diff = data.totalBytesWritten - cached_write_total;
- diff /= 1024; /* Meter_humanUnit() expects unit in kilo */
+ diff = (1000 * diff) / passedTimeInMs; /* convert to B/s */
+ diff /= ONE_K; /* convert to KiB/s */
cached_write_diff = (uint32_t)diff;
} else {
cached_write_diff = 0;
@@ -104,7 +106,7 @@ static void DiskIOMeter_updateValues(Meter* this) {
char bufferRead[12], bufferWrite[12];
Meter_humanUnit(bufferRead, cached_read_diff, sizeof(bufferRead));
Meter_humanUnit(bufferWrite, cached_write_diff, sizeof(bufferWrite));
- snprintf(this->txtBuffer, sizeof(this->txtBuffer), "%sB %sB %.1f%%", bufferRead, bufferWrite, cached_utilisation_diff);
+ snprintf(this->txtBuffer, sizeof(this->txtBuffer), "r:%siB/s w:%siB/s %.1f%%", bufferRead, bufferWrite, cached_utilisation_diff);
}
static void DiskIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out) {
@@ -132,10 +134,12 @@ static void DiskIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out)
RichString_appendAscii(out, CRT_colors[METER_TEXT], " read: ");
Meter_humanUnit(buffer, cached_read_diff, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], buffer);
+ RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], "iB/s");
RichString_appendAscii(out, CRT_colors[METER_TEXT], " write: ");
Meter_humanUnit(buffer, cached_write_diff, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], buffer);
+ RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], "iB/s");
}
const MeterClass DiskIOMeter_class = {
diff --git a/DisplayOptionsPanel.c b/DisplayOptionsPanel.c
index fc23cb6..f9fa9b1 100644
--- a/DisplayOptionsPanel.c
+++ b/DisplayOptionsPanel.c
@@ -116,11 +116,13 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
Panel_add(super, (Object*) CheckItem_newByRef("Shadow other users' processes", &(settings->shadowOtherUsers)));
Panel_add(super, (Object*) CheckItem_newByRef("Hide kernel threads", &(settings->hideKernelThreads)));
Panel_add(super, (Object*) CheckItem_newByRef("Hide userland process threads", &(settings->hideUserlandThreads)));
+ Panel_add(super, (Object*) CheckItem_newByRef("Hide processes running in containers", &(settings->hideRunningInContainer)));
Panel_add(super, (Object*) CheckItem_newByRef("Display threads in a different color", &(settings->highlightThreads)));
Panel_add(super, (Object*) CheckItem_newByRef("Show custom thread names", &(settings->showThreadNames)));
Panel_add(super, (Object*) CheckItem_newByRef("Show program path", &(settings->showProgramPath)));
Panel_add(super, (Object*) CheckItem_newByRef("Highlight program \"basename\"", &(settings->highlightBaseName)));
Panel_add(super, (Object*) CheckItem_newByRef("Highlight out-dated/removed programs (red) / libraries (yellow)", &(settings->highlightDeletedExe)));
+ Panel_add(super, (Object*) CheckItem_newByRef("Shadow distribution path prefixes", &(settings->shadowDistPathPrefix)));
Panel_add(super, (Object*) CheckItem_newByRef("Merge exe, comm and cmdline in Command", &(settings->showMergedCommand)));
Panel_add(super, (Object*) CheckItem_newByRef("- Try to find comm in cmdline (when Command is merged)", &(settings->findCommInCmdline)));
Panel_add(super, (Object*) CheckItem_newByRef("- Try to strip exe from cmdline (when Command is merged)", &(settings->stripExeFromCmdline)));
diff --git a/Header.c b/Header.c
index 8dff89b..1953c02 100644
--- a/Header.c
+++ b/Header.c
@@ -286,10 +286,19 @@ int Header_calculateHeight(Header* this) {
}
maxHeight = MAXIMUM(maxHeight, height);
}
+
+ if (maxHeight == pad) {
+ maxHeight = 0;
+ this->pad = 0;
+ } else {
+ this->pad = pad;
+ }
+
if (this->settings->screenTabs) {
maxHeight++;
}
+
this->height = maxHeight;
- this->pad = pad;
+
return maxHeight;
}
diff --git a/MainPanel.c b/MainPanel.c
index 44915df..89b4e7d 100644
--- a/MainPanel.c
+++ b/MainPanel.c
@@ -122,28 +122,28 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
}
}
- if (reaction & HTOP_REDRAW_BAR) {
+ if ((reaction & HTOP_REDRAW_BAR) == HTOP_REDRAW_BAR) {
MainPanel_updateLabels(this, settings->ss->treeView, this->state->pl->incFilter);
}
- if (reaction & HTOP_RESIZE) {
+ if ((reaction & HTOP_RESIZE) == HTOP_RESIZE) {
result |= RESIZE;
}
- if (reaction & HTOP_UPDATE_PANELHDR) {
+ if ((reaction & HTOP_UPDATE_PANELHDR) == HTOP_UPDATE_PANELHDR) {
result |= REDRAW;
}
- if (reaction & HTOP_REFRESH) {
+ if ((reaction & HTOP_REFRESH) == HTOP_REFRESH) {
result |= REFRESH;
}
- if (reaction & HTOP_RECALCULATE) {
+ if ((reaction & HTOP_RECALCULATE) == HTOP_RECALCULATE) {
result |= RESCAN;
}
- if (reaction & HTOP_SAVE_SETTINGS) {
+ if ((reaction & HTOP_SAVE_SETTINGS) == HTOP_SAVE_SETTINGS) {
this->state->settings->changed = true;
}
- if (reaction & HTOP_QUIT) {
+ if ((reaction & HTOP_QUIT) == HTOP_QUIT) {
return BREAK_LOOP;
}
- if (!(reaction & HTOP_KEEP_FOLLOWING)) {
+ if ((reaction & HTOP_KEEP_FOLLOWING) != HTOP_KEEP_FOLLOWING) {
this->state->pl->following = -1;
Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS);
}
@@ -210,7 +210,7 @@ const PanelClass MainPanel_class = {
.printHeader = MainPanel_printHeader
};
-MainPanel* MainPanel_new() {
+MainPanel* MainPanel_new(void) {
MainPanel* this = AllocThis(MainPanel);
Panel_init((Panel*) this, 1, 1, 1, 1, Class(Process), false, FunctionBar_new(Settings_isReadonly() ? MainFunctions_ro : MainFunctions, NULL, NULL));
this->keys = xCalloc(KEY_MAX, sizeof(Htop_Action));
diff --git a/MemoryMeter.c b/MemoryMeter.c
index 89e242c..ac01dfe 100644
--- a/MemoryMeter.c
+++ b/MemoryMeter.c
@@ -29,14 +29,14 @@ static void MemoryMeter_updateValues(Meter* this) {
int written;
/* shared and available memory are not supported on all platforms */
- this->values[2] = NAN;
- this->values[4] = NAN;
+ this->values[MEMORY_METER_SHARED] = NAN;
+ this->values[MEMORY_METER_AVAILABLE] = NAN;
Platform_setMemoryValues(this);
/* Do not print available memory in bar mode */
this->curItems = 4;
- written = Meter_humanUnit(buffer, this->values[0], size);
+ written = Meter_humanUnit(buffer, this->values[MEMORY_METER_USED], size);
METER_BUFFER_CHECK(buffer, size, written);
METER_BUFFER_APPEND_CHR(buffer, size, '/');
@@ -52,28 +52,28 @@ static void MemoryMeter_display(const Object* cast, RichString* out) {
Meter_humanUnit(buffer, this->total, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer);
- Meter_humanUnit(buffer, this->values[0], sizeof(buffer));
+ Meter_humanUnit(buffer, this->values[MEMORY_METER_USED], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:");
RichString_appendAscii(out, CRT_colors[MEMORY_USED], buffer);
- Meter_humanUnit(buffer, this->values[1], sizeof(buffer));
+ Meter_humanUnit(buffer, this->values[MEMORY_METER_BUFFERS], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " buffers:");
RichString_appendAscii(out, CRT_colors[MEMORY_BUFFERS_TEXT], buffer);
/* shared memory is not supported on all platforms */
- if (!isnan(this->values[2])) {
- Meter_humanUnit(buffer, this->values[2], sizeof(buffer));
+ if (!isnan(this->values[MEMORY_METER_SHARED])) {
+ Meter_humanUnit(buffer, this->values[MEMORY_METER_SHARED], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " shared:");
RichString_appendAscii(out, CRT_colors[MEMORY_SHARED], buffer);
}
- Meter_humanUnit(buffer, this->values[3], sizeof(buffer));
+ Meter_humanUnit(buffer, this->values[MEMORY_METER_CACHE], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " cache:");
RichString_appendAscii(out, CRT_colors[MEMORY_CACHE], buffer);
/* available memory is not supported on all platforms */
- if (!isnan(this->values[4])) {
- Meter_humanUnit(buffer, this->values[4], sizeof(buffer));
+ if (!isnan(this->values[MEMORY_METER_AVAILABLE])) {
+ Meter_humanUnit(buffer, this->values[MEMORY_METER_AVAILABLE], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " available:");
RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer);
}
diff --git a/MemoryMeter.h b/MemoryMeter.h
index d23021e..cc2a160 100644
--- a/MemoryMeter.h
+++ b/MemoryMeter.h
@@ -9,6 +9,14 @@ in the source distribution for its full text.
#include "Meter.h"
+typedef enum {
+ MEMORY_METER_USED = 0,
+ MEMORY_METER_BUFFERS = 1,
+ MEMORY_METER_SHARED = 2,
+ MEMORY_METER_CACHE = 3,
+ MEMORY_METER_AVAILABLE = 4,
+ MEMORY_METER_ITEMCOUNT = 5, // number of entries in this enum
+} MemoryMeterValues;
extern const MeterClass MemoryMeter_class;
diff --git a/MetersPanel.c b/MetersPanel.c
index 97da630..580e41b 100644
--- a/MetersPanel.c
+++ b/MetersPanel.c
@@ -33,7 +33,7 @@ static const char* const MetersMovingKeys[] = {"Space", "Enter", "Up", "Dn", "<-
static const int MetersMovingEvents[] = {' ', 13, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, ERR, KEY_DC, KEY_F(10)};
static FunctionBar* Meters_movingBar = NULL;
-void MetersPanel_cleanup() {
+void MetersPanel_cleanup(void) {
if (Meters_movingBar) {
FunctionBar_delete(Meters_movingBar);
Meters_movingBar = NULL;
@@ -91,7 +91,7 @@ static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) {
HandlerResult result = IGNORED;
bool sideMove = false;
- switch(ch) {
+ switch (ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
@@ -110,7 +110,8 @@ static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) {
break;
Meter* meter = (Meter*) Vector_get(this->meters, selected);
int mode = meter->mode + 1;
- if (mode == LAST_METERMODE) mode = 1;
+ if (mode == LAST_METERMODE)
+ mode = 1;
Meter_setMode(meter, mode);
Panel_set(super, selected, (Object*) Meter_toListItem(meter, this->moving));
result = HANDLED;
diff --git a/NetworkIOMeter.c b/NetworkIOMeter.c
index dd91b75..d41eafa 100644
--- a/NetworkIOMeter.c
+++ b/NetworkIOMeter.c
@@ -59,8 +59,8 @@ static void NetworkIOMeter_updateValues(Meter* this) {
if (data.bytesReceived > cached_rxb_total) {
diff = data.bytesReceived - cached_rxb_total;
- diff /= ONE_K; /* Meter_humanUnit() expects unit in kilo */
- diff = (1000 * diff) / passedTimeInMs; /* convert to per second */
+ diff = (1000 * diff) / passedTimeInMs; /* convert to B/s */
+ diff /= ONE_K; /* convert to KiB/s */
cached_rxb_diff = (uint32_t)diff;
} else {
cached_rxb_diff = 0;
@@ -69,6 +69,7 @@ static void NetworkIOMeter_updateValues(Meter* this) {
if (data.packetsReceived > cached_rxp_total) {
diff = data.packetsReceived - cached_rxp_total;
+ diff = (1000 * diff) / passedTimeInMs; /* convert to B/s */
cached_rxp_diff = (uint32_t)diff;
} else {
cached_rxp_diff = 0;
@@ -77,8 +78,8 @@ static void NetworkIOMeter_updateValues(Meter* this) {
if (data.bytesTransmitted > cached_txb_total) {
diff = data.bytesTransmitted - cached_txb_total;
- diff /= ONE_K; /* Meter_humanUnit() expects unit in kilo */
- diff = (1000 * diff) / passedTimeInMs; /* convert to per second */
+ diff = (1000 * diff) / passedTimeInMs; /* convert to B/s */
+ diff /= ONE_K; /* convert to KiB/s */
cached_txb_diff = (uint32_t)diff;
} else {
cached_txb_diff = 0;
@@ -87,6 +88,7 @@ static void NetworkIOMeter_updateValues(Meter* this) {
if (data.packetsTransmitted > cached_txp_total) {
diff = data.packetsTransmitted - cached_txp_total;
+ diff = (1000 * diff) / passedTimeInMs; /* convert to B/s */
cached_txp_diff = (uint32_t)diff;
} else {
cached_txp_diff = 0;
@@ -112,7 +114,8 @@ static void NetworkIOMeter_updateValues(Meter* this) {
char bufferBytesReceived[12], bufferBytesTransmitted[12];
Meter_humanUnit(bufferBytesReceived, cached_rxb_diff, sizeof(bufferBytesReceived));
Meter_humanUnit(bufferBytesTransmitted, cached_txb_diff, sizeof(bufferBytesTransmitted));
- xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "rx:%siB/s tx:%siB/s", bufferBytesReceived, bufferBytesTransmitted);
+ xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "rx:%siB/s tx:%siB/s %d/%dpkts/s",
+ bufferBytesReceived, bufferBytesTransmitted, cached_rxp_diff, cached_txp_diff);
}
static void NetworkIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out) {
@@ -143,7 +146,7 @@ static void NetworkIOMeter_display(ATTR_UNUSED const Object* cast, RichString* o
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], buffer);
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], "iB/s");
- len = xSnprintf(buffer, sizeof(buffer), " (%u/%u packets) ", cached_rxp_diff, cached_txp_diff);
+ len = xSnprintf(buffer, sizeof(buffer), " (%u/%u pkts/s) ", cached_rxp_diff, cached_txp_diff);
RichString_appendnAscii(out, CRT_colors[METER_TEXT], buffer, len);
}
diff --git a/OpenFilesScreen.c b/OpenFilesScreen.c
index 787e17b..4256575 100644
--- a/OpenFilesScreen.c
+++ b/OpenFilesScreen.c
@@ -226,7 +226,7 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
struct stat st;
if (stat(filename, &st) == 0) {
char fileSizeBuf[21]; /* 20 (long long) + 1 (NULL) */
- xSnprintf(fileSizeBuf, sizeof(fileSizeBuf), "%"PRIu64, st.st_size); /* st.st_size is long long on macOS, long on linux */
+ xSnprintf(fileSizeBuf, sizeof(fileSizeBuf), "%"PRIu64, (uint64_t)st.st_size); /* st.st_size is long long on macOS, long on linux */
free_and_xStrdup(&item->data[fileSizeIndex], fileSizeBuf);
}
}
diff --git a/Panel.c b/Panel.c
index 4ea03f6..d1bc6a7 100644
--- a/Panel.c
+++ b/Panel.c
@@ -443,6 +443,9 @@ bool Panel_onKey(Panel* this, int key) {
HandlerResult Panel_selectByTyping(Panel* this, int ch) {
int size = Panel_size(this);
+ if (ch == '#')
+ return IGNORED;
+
if (!this->eventHandlerState)
this->eventHandlerState = xCalloc(100, sizeof(char));
char* buffer = this->eventHandlerState;
@@ -468,7 +471,8 @@ HandlerResult Panel_selectByTyping(Panel* this, int ch) {
len = strlen(buffer);
for (int i = 0; i < size; i++) {
const char* cur = ((ListItem*) Panel_get(this, i))->value;
- while (*cur == ' ') cur++;
+ while (*cur == ' ')
+ cur++;
if (strncasecmp(cur, buffer, len) == 0) {
Panel_setSelected(this, i);
return HANDLED;
diff --git a/Process.c b/Process.c
index 2a4c809..fcaa3d5 100644
--- a/Process.c
+++ b/Process.c
@@ -44,7 +44,7 @@ static uid_t Process_getuid = (uid_t)-1;
int Process_pidDigits = PROCESS_MIN_PID_DIGITS;
int Process_uidDigits = PROCESS_MIN_UID_DIGITS;
-void Process_setupColumnWidths() {
+void Process_setupColumnWidths(void) {
int maxPid = Platform_getMaxPid();
if (maxPid == -1)
return;
@@ -413,6 +413,7 @@ void Process_makeCommandStr(Process* this) {
bool searchCommInCmdline = settings->findCommInCmdline;
bool stripExeFromCmdline = settings->stripExeFromCmdline;
bool showThreadNames = settings->showThreadNames;
+ bool shadowDistPathPrefix = settings->shadowDistPathPrefix;
uint64_t settingsStamp = settings->lastUpdate;
@@ -472,6 +473,56 @@ void Process_makeCommandStr(Process* this) {
str = stpcpy(str, SEPARATOR); \
} while (0)
+ #define CHECK_AND_MARK(str_, prefix_) \
+ if (String_startsWith(str_, prefix_)) { \
+ WRITE_HIGHLIGHT(0, strlen(prefix_), CRT_colors[PROCESS_SHADOW], CMDLINE_HIGHLIGHT_FLAG_PREFIXDIR); \
+ break; \
+ } else (void)0
+
+ #define CHECK_AND_MARK_DIST_PATH_PREFIXES(str_) \
+ do { \
+ if ((str_)[0] != '/') { \
+ break; \
+ } \
+ switch ((str_)[1]) { \
+ case 'b': \
+ CHECK_AND_MARK(str_, "/bin/"); \
+ break; \
+ case 'l': \
+ CHECK_AND_MARK(str_, "/lib/"); \
+ CHECK_AND_MARK(str_, "/lib32/"); \
+ CHECK_AND_MARK(str_, "/lib64/"); \
+ CHECK_AND_MARK(str_, "/libx32/"); \
+ break; \
+ case 's': \
+ CHECK_AND_MARK(str_, "/sbin/"); \
+ break; \
+ case 'u': \
+ if (String_startsWith(str_, "/usr/")) { \
+ switch ((str_)[5]) { \
+ case 'b': \
+ CHECK_AND_MARK(str_, "/usr/bin/"); \
+ break; \
+ case 'l': \
+ CHECK_AND_MARK(str_, "/usr/libexec/"); \
+ CHECK_AND_MARK(str_, "/usr/lib/"); \
+ CHECK_AND_MARK(str_, "/usr/lib32/"); \
+ CHECK_AND_MARK(str_, "/usr/lib64/"); \
+ CHECK_AND_MARK(str_, "/usr/libx32/"); \
+ \
+ CHECK_AND_MARK(str_, "/usr/local/bin/"); \
+ CHECK_AND_MARK(str_, "/usr/local/lib/"); \
+ CHECK_AND_MARK(str_, "/usr/local/sbin/"); \
+ break; \
+ case 's': \
+ CHECK_AND_MARK(str_, "/usr/sbin/"); \
+ break; \
+ } \
+ } \
+ break; \
+ } \
+ } while (0)
+
const int baseAttr = Process_isThread(this) ? CRT_colors[PROCESS_THREAD_BASENAME] : CRT_colors[PROCESS_BASENAME];
const int commAttr = Process_isThread(this) ? CRT_colors[PROCESS_THREAD_COMM] : CRT_colors[PROCESS_COMM];
const int delExeAttr = CRT_colors[FAILED_READ];
@@ -503,13 +554,16 @@ void Process_makeCommandStr(Process* this) {
WRITE_HIGHLIGHT(0, strlen(procComm), commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM);
str = stpcpy(str, procComm);
- if(!showMergedCommand)
+ if (!showMergedCommand)
return;
WRITE_SEPARATOR;
}
}
+ if (shadowDistPathPrefix && showProgramPath)
+ CHECK_AND_MARK_DIST_PATH_PREFIXES(cmdline);
+
if (cmdlineBasenameEnd > cmdlineBasenameStart)
WRITE_HIGHLIGHT(showProgramPath ? cmdlineBasenameStart : 0, cmdlineBasenameEnd - cmdlineBasenameStart, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME);
@@ -537,6 +591,8 @@ void Process_makeCommandStr(Process* this) {
/* Start with copying exe */
if (showProgramPath) {
+ if (shadowDistPathPrefix)
+ CHECK_AND_MARK_DIST_PATH_PREFIXES(procExe);
if (haveCommInExe)
WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM);
WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME);
@@ -594,6 +650,9 @@ void Process_makeCommandStr(Process* this) {
WRITE_SEPARATOR;
}
+ if (shadowDistPathPrefix)
+ CHECK_AND_MARK_DIST_PATH_PREFIXES(cmdline);
+
if (!haveCommInExe && haveCommInCmdline && !haveCommField && (!Process_isUserlandThread(this) || showThreadNames))
WRITE_HIGHLIGHT(commStart, commEnd - commStart, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM);
@@ -601,6 +660,8 @@ void Process_makeCommandStr(Process* this) {
if (*cmdline)
(void)stpcpyWithNewlineConversion(str, cmdline);
+ #undef CHECK_AND_MARK_DIST_PATH_PREFIXES
+ #undef CHECK_AND_MARK
#undef WRITE_SEPARATOR
#undef WRITE_HIGHLIGHT
}
@@ -609,6 +670,7 @@ void Process_writeCommand(const Process* this, int attr, int baseAttr, RichStrin
(void)baseAttr;
const ProcessMergedCommand* mc = &this->mergedCommand;
+ const char* mergedCommand = mc->str;
int strStart = RichString_size(str);
@@ -616,7 +678,7 @@ void Process_writeCommand(const Process* this, int attr, int baseAttr, RichStrin
const bool highlightSeparator = true;
const bool highlightDeleted = this->settings->highlightDeletedExe;
- if (!this->mergedCommand.str) {
+ if (!mergedCommand) {
int len = 0;
const char* cmdline = this->cmdline;
@@ -649,7 +711,7 @@ void Process_writeCommand(const Process* this, int attr, int baseAttr, RichStrin
return;
}
- RichString_appendWide(str, attr, this->mergedCommand.str);
+ RichString_appendWide(str, attr, mergedCommand);
for (size_t i = 0, hlCount = CLAMP(mc->highlightCount, 0, ARRAYSIZE(mc->highlights)); i < hlCount; i++) {
const ProcessCmdlineHighlight* hl = &mc->highlights[i];
@@ -669,6 +731,10 @@ void Process_writeCommand(const Process* this, int attr, int baseAttr, RichStrin
if (!highlightDeleted)
continue;
+ if (hl->flags & CMDLINE_HIGHLIGHT_FLAG_PREFIXDIR)
+ if (!highlightDeleted)
+ continue;
+
RichString_setAttrn(str, hl->attr, strStart + hl->offset, hl->length);
}
}
@@ -782,19 +848,11 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
}
char* buf = buffer;
- int maxIndent = 0;
- bool lastItem = (this->indent < 0);
- int indent = (this->indent < 0 ? -this->indent : this->indent);
-
- for (int i = 0; i < 32; i++) {
- if (indent & (1U << i)) {
- maxIndent = i + 1;
- }
- }
+ const bool lastItem = (this->indent < 0);
- for (int i = 0; i < maxIndent - 1; i++) {
+ for (uint32_t indent = (this->indent < 0 ? -this->indent : this->indent); indent > 1; indent >>= 1) {
int written, ret;
- if (indent & (1 << i)) {
+ if (indent & 1U) {
ret = xSnprintf(buf, n, "%s ", CRT_treeStr[TREE_STR_VERT]);
} else {
ret = xSnprintf(buf, n, " ");
@@ -1248,7 +1306,7 @@ void Process_updateExe(Process* this, const char* exe) {
uint8_t Process_fieldWidths[LAST_PROCESSFIELD] = { 0 };
-void Process_resetFieldWidths() {
+void Process_resetFieldWidths(void) {
for (size_t i = 0; i < LAST_PROCESSFIELD; i++) {
if (!Process_fields[i].autoWidth)
continue;
diff --git a/Process.h b/Process.h
index a1ca50f..eb79470 100644
--- a/Process.h
+++ b/Process.h
@@ -134,6 +134,9 @@ typedef struct Process_ {
/* This is a userland thread / LWP */
bool isUserlandThread;
+ /* This process is running inside a container */
+ bool isRunningInContainer;
+
/* Controlling terminal identifier of the process */
unsigned long int tty_nr;
@@ -242,7 +245,7 @@ typedef struct Process_ {
/*
* Internal state for tree-mode.
*/
- int indent;
+ int32_t indent;
unsigned int tree_depth;
/* Has no known parent process */
@@ -328,6 +331,7 @@ static inline bool Process_isThread(const Process* this) {
#define CMDLINE_HIGHLIGHT_FLAG_BASENAME 0x00000002
#define CMDLINE_HIGHLIGHT_FLAG_COMM 0x00000004
#define CMDLINE_HIGHLIGHT_FLAG_DELETED 0x00000008
+#define CMDLINE_HIGHLIGHT_FLAG_PREFIXDIR 0x00000010
#define ONE_K 1024UL
#define ONE_M (ONE_K * ONE_K)
diff --git a/ProcessList.c b/ProcessList.c
index bbaddd8..d115678 100644
--- a/ProcessList.c
+++ b/ProcessList.c
@@ -199,7 +199,7 @@ static void ProcessList_removeIndex(ProcessList* this, const Process* p, int idx
assert(Vector_countEquals(this->processes, Hashtable_count(this->processTable)));
}
-static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level, int indent, bool show) {
+static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, unsigned int level, int32_t indent, bool show) {
// On OpenBSD the kernel thread 'swapper' has pid 0.
// Do not treat it as root of any tree.
if (pid == 0)
@@ -239,7 +239,7 @@ static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level,
Vector_add(this->displayList, process);
- int nextIndent = indent | (1 << level);
+ int32_t nextIndent = indent | ((int32_t)1 << MINIMUM(level, sizeof(process->indent) * 8 - 2));
ProcessList_buildTreeBranch(this, process->pid, level + 1, (i < lastShown) ? nextIndent : indent, process->show && process->showChildren);
if (i == lastShown) {
process->indent = -nextIndent;
diff --git a/ProcessLocksScreen.c b/ProcessLocksScreen.c
index b842d2b..57c9ce7 100644
--- a/ProcessLocksScreen.c
+++ b/ProcessLocksScreen.c
@@ -27,7 +27,8 @@ ProcessLocksScreen* ProcessLocksScreen_new(const Process* process) {
this->pid = process->tgid;
else
this->pid = process->pid;
- return (ProcessLocksScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ID TYPE EXCLUSION READ/WRITE DEVICE:INODE START END FILENAME");
+
+ return (ProcessLocksScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " FD TYPE EXCLUSION READ/WRITE DEVICE NODE START END FILENAME");
}
void ProcessLocksScreen_delete(Object* this) {
@@ -64,18 +65,18 @@ static void ProcessLocksScreen_scan(InfoScreen* this) {
char entry[512];
if (ULLONG_MAX == data->end) {
- xSnprintf(entry, sizeof(entry), "%10d %-10s %-10s %-10s %02x:%02x:%020"PRIu64" %20"PRIu64" %20s %s",
- data->id,
+ xSnprintf(entry, sizeof(entry), "%5d %-10s %-10s %-10s %#6"PRIx64" %10"PRIu64" %19"PRIu64" %19s %s",
+ data->fd,
data->locktype, data->exclusive, data->readwrite,
- data->dev[0], data->dev[1], data->inode,
+ (uint64_t) data->dev, data->inode,
data->start, "<END OF FILE>",
data->filename ? data->filename : "<N/A>"
);
} else {
- xSnprintf(entry, sizeof(entry), "%10d %-10s %-10s %-10s %02x:%02x:%020"PRIu64" %20"PRIu64" %20"PRIu64" %s",
- data->id,
+ xSnprintf(entry, sizeof(entry), "%5d %-10s %-10s %-10s %#6"PRIx64" %10"PRIu64" %19"PRIu64" %19"PRIu64" %s",
+ data->fd,
data->locktype, data->exclusive, data->readwrite,
- data->dev[0], data->dev[1], data->inode,
+ (uint64_t) data->dev, data->inode,
data->start, data->end,
data->filename ? data->filename : "<N/A>"
);
diff --git a/ProcessLocksScreen.h b/ProcessLocksScreen.h
index cf34de4..417df7b 100644
--- a/ProcessLocksScreen.h
+++ b/ProcessLocksScreen.h
@@ -26,8 +26,8 @@ typedef struct FileLocks_Data_ {
char* exclusive;
char* readwrite;
char* filename;
- int id;
- unsigned int dev[2];
+ int fd;
+ dev_t dev;
uint64_t inode;
uint64_t start;
uint64_t end;
diff --git a/README b/README
index 55372b4..7ace7cd 100644
--- a/README
+++ b/README
@@ -34,6 +34,7 @@ List of build-time dependencies:
* standard GNU autotools-based C toolchain
- C99 compliant compiler
- `autoconf`
+ - `automake`
- `autotools`
* `ncurses`
@@ -54,7 +55,7 @@ Install these and other required packages for C development from your package ma
**Debian/Ubuntu**
~~~ shell
-sudo apt install libncursesw5-dev autotools-dev autoconf build-essential
+sudo apt install libncursesw5-dev autotools-dev autoconf automake build-essential
~~~
**Fedora/RHEL**
diff --git a/RichString.c b/RichString.c
index 3dac083..daa0c91 100644
--- a/RichString.c
+++ b/RichString.c
@@ -61,7 +61,7 @@ static inline int RichString_writeFromWide(RichString* this, int attrs, const ch
int newLen = from + len;
RichString_setLen(this, newLen);
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] : L'\xFFFD') } };
}
return len;
@@ -79,7 +79,7 @@ int RichString_appendnWideColumns(RichString* this, int attrs, const char* data_
int columnsWritten = 0;
int pos = from;
for (int j = 0; j < len; j++) {
- wchar_t c = iswprint(data[j]) ? data[j] : '?';
+ wchar_t c = iswprint(data[j]) ? data[j] : L'\xFFFD';
int cwidth = wcwidth(c);
if (cwidth > *columns)
break;
@@ -101,7 +101,7 @@ static inline int RichString_writeFromAscii(RichString* this, int attrs, const c
int newLen = from + len;
RichString_setLen(this, newLen);
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] : L'\xFFFD') } };
}
return len;
diff --git a/ScreenManager.c b/ScreenManager.c
index e4b04bd..55cacd2 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -24,7 +24,7 @@ in the source distribution for its full text.
#include "XUtils.h"
-ScreenManager* ScreenManager_new(Header* header, const Settings* settings, const State* state, bool owner) {
+ScreenManager* ScreenManager_new(Header* header, const Settings* settings, State* state, bool owner) {
ScreenManager* this;
this = xMalloc(sizeof(ScreenManager));
this->x1 = 0;
@@ -53,18 +53,28 @@ void ScreenManager_add(ScreenManager* this, Panel* item, int size) {
ScreenManager_insert(this, item, size, Vector_size(this->panels));
}
+static int header_height(const ScreenManager* this) {
+ if (this->state->hideMeters)
+ return 0;
+
+ if (this->header)
+ return this->header->height;
+
+ return 0;
+}
+
void ScreenManager_insert(ScreenManager* this, Panel* item, int size, int idx) {
int lastX = 0;
if (idx > 0) {
const Panel* last = (const Panel*) Vector_get(this->panels, idx - 1);
lastX = last->x + last->w + 1;
}
- int height = LINES - this->y1 - (this->header ? this->header->height : 0) + this->y2;
+ int height = LINES - this->y1 - header_height(this) + this->y2;
if (size <= 0) {
size = COLS - this->x1 + this->x2 - lastX;
}
Panel_resize(item, size, height);
- Panel_move(item, lastX, this->y1 + (this->header ? this->header->height : 0));
+ Panel_move(item, lastX, this->y1 + header_height(this));
if (idx < this->panelCount) {
for (int i = idx + 1; i <= this->panelCount; i++) {
Panel* p = (Panel*) Vector_get(this->panels, i);
@@ -91,7 +101,7 @@ Panel* ScreenManager_remove(ScreenManager* this, int idx) {
}
void ScreenManager_resize(ScreenManager* this) {
- int y1_header = this->y1 + (this->header ? this->header->height : 0);
+ int y1_header = this->y1 + header_height(this);
int panels = this->panelCount;
int lastX = 0;
for (int i = 0; i < panels - 1; i++) {
@@ -105,7 +115,7 @@ void ScreenManager_resize(ScreenManager* this) {
Panel_move(panel, lastX, y1_header);
}
-static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTimeout, bool* redraw, bool* rescan, bool* timedOut, bool *force_redraw) {
+static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTimeout, bool* redraw, bool* rescan, bool* timedOut, bool* force_redraw) {
ProcessList* pl = this->header->pl;
Platform_gettime_realtime(&pl->realtime, &pl->realtimeMs);
@@ -137,7 +147,8 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi
}
if (*redraw) {
ProcessList_rebuildPanel(pl);
- Header_draw(this->header);
+ if (!this->state->hideMeters)
+ Header_draw(this->header);
}
*rescan = false;
}
@@ -376,6 +387,11 @@ tryRight:
}
break;
+ case '#':
+ this->state->hideMeters = !this->state->hideMeters;
+ ScreenManager_resize(this);
+ force_redraw = true;
+ break;
case 27:
case 'q':
case KEY_F(10):
diff --git a/ScreenManager.h b/ScreenManager.h
index 978b524..d08a941 100644
--- a/ScreenManager.h
+++ b/ScreenManager.h
@@ -26,11 +26,11 @@ typedef struct ScreenManager_ {
int panelCount;
Header* header;
const Settings* settings;
- const State* state;
+ State* state;
bool allowFocusChange;
} ScreenManager;
-ScreenManager* ScreenManager_new(Header* header, const Settings* settings, const State* state, bool owner);
+ScreenManager* ScreenManager_new(Header* header, const Settings* settings, State* state, bool owner);
void ScreenManager_delete(ScreenManager* this);
diff --git a/ScreensPanel.c b/ScreensPanel.c
index 785c387..cb664ac 100644
--- a/ScreensPanel.c
+++ b/ScreensPanel.c
@@ -55,6 +55,10 @@ static void ScreensPanel_delete(Object* object) {
item->ss = NULL;
}
+ /* during renaming the ListItem's value points to our static buffer */
+ if (this->renamingItem)
+ this->renamingItem->value = this->saved;
+
Panel_done(super);
free(this);
}
@@ -70,7 +74,7 @@ static HandlerResult ScreensPanel_eventHandlerRenaming(Panel* super, int ch) {
Panel_setCursorToSelection(super);
}
} else {
- switch(ch) {
+ switch (ch) {
case 127:
case KEY_BACKSPACE:
{
@@ -89,9 +93,10 @@ static HandlerResult ScreensPanel_eventHandlerRenaming(Panel* super, int ch) {
ListItem* item = (ListItem*) Panel_getSelected(super);
if (!item)
break;
+ assert(item == this->renamingItem);
free(this->saved);
item->value = xStrdup(this->buffer);
- this->renaming = false;
+ this->renamingItem = NULL;
super->cursorOn = false;
Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS);
ScreensPanel_update(super);
@@ -102,8 +107,9 @@ static HandlerResult ScreensPanel_eventHandlerRenaming(Panel* super, int ch) {
ListItem* item = (ListItem*) Panel_getSelected(super);
if (!item)
break;
+ assert(item == this->renamingItem);
item->value = this->saved;
- this->renaming = false;
+ this->renamingItem = NULL;
super->cursorOn = false;
Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS);
break;
@@ -119,7 +125,7 @@ static void startRenaming(Panel* super) {
ListItem* item = (ListItem*) Panel_getSelected(super);
if (item == NULL)
return;
- this->renaming = true;
+ this->renamingItem = item;
super->cursorOn = true;
char* name = item->value;
this->saved = name;
@@ -132,7 +138,7 @@ static void startRenaming(Panel* super) {
Panel_setCursorToSelection(super);
}
-static void rebuildSettingsArray(Panel* super) {
+static void rebuildSettingsArray(Panel* super, int selected) {
ScreensPanel* const this = (ScreensPanel*) super;
int n = Panel_size(super);
@@ -144,13 +150,20 @@ static void rebuildSettingsArray(Panel* super) {
this->settings->screens[i] = item->ss;
}
this->settings->nScreens = n;
+ /* ensure selection is in valid range */
+ if (selected > n - 1)
+ selected = n - 1;
+ else if (selected < 0)
+ selected = 0;
+ this->settings->ssIndex = selected;
+ this->settings->ss = this->settings->screens[selected];
}
static void addNewScreen(Panel* super) {
ScreensPanel* const this = (ScreensPanel*) super;
const char* name = "New";
- ScreenSettings* ss = Settings_newScreen(this->settings, &(const ScreenDefaults){ .name = name, .columns = "PID Command", .sortKey = "PID" });
+ ScreenSettings* ss = Settings_newScreen(this->settings, &(const ScreenDefaults) { .name = name, .columns = "PID Command", .sortKey = "PID" });
ScreenListItem* item = ScreenListItem_new(name, ss);
int idx = Panel_getSelectedIndex(super);
Panel_insert(super, idx + 1, (Object*) item);
@@ -164,7 +177,7 @@ static HandlerResult ScreensPanel_eventHandlerNormal(Panel* super, int ch) {
ScreenListItem* oldFocus = (ScreenListItem*) Panel_getSelected(super);
bool shouldRebuildArray = false;
HandlerResult result = IGNORED;
- switch(ch) {
+ switch (ch) {
case '\n':
case '\r':
case KEY_ENTER:
@@ -242,9 +255,8 @@ static HandlerResult ScreensPanel_eventHandlerNormal(Panel* super, int ch) {
case KEY_F(9):
//case KEY_DC:
{
- if (Panel_size(super) > 1) {
+ if (Panel_size(super) > 1)
Panel_remove(super, selected);
- }
shouldRebuildArray = true;
result = HANDLED;
break;
@@ -264,7 +276,7 @@ static HandlerResult ScreensPanel_eventHandlerNormal(Panel* super, int ch) {
result = HANDLED;
}
if (shouldRebuildArray)
- rebuildSettingsArray(super);
+ rebuildSettingsArray(super, selected);
if (result == HANDLED)
ScreensPanel_update(super);
return result;
@@ -273,7 +285,7 @@ static HandlerResult ScreensPanel_eventHandlerNormal(Panel* super, int ch) {
static HandlerResult ScreensPanel_eventHandler(Panel* super, int ch) {
ScreensPanel* const this = (ScreensPanel*) super;
- if (this->renaming) {
+ if (this->renamingItem) {
return ScreensPanel_eventHandlerRenaming(super, ch);
} else {
return ScreensPanel_eventHandlerNormal(super, ch);
@@ -298,7 +310,7 @@ ScreensPanel* ScreensPanel_new(Settings* settings) {
this->settings = settings;
this->columns = ColumnsPanel_new(settings->screens[0], columns, &(settings->changed));
this->moving = false;
- this->renaming = false;
+ this->renamingItem = NULL;
super->cursorOn = false;
this->cursor = 0;
Panel_setHeader(super, "Screens");
diff --git a/ScreensPanel.h b/ScreensPanel.h
index 1f82395..88d85b5 100644
--- a/ScreensPanel.h
+++ b/ScreensPanel.h
@@ -31,7 +31,7 @@ typedef struct ScreensPanel_ {
char* saved;
int cursor;
bool moving;
- bool renaming;
+ ListItem *renamingItem;
} ScreensPanel;
typedef struct ScreenListItem_ {
diff --git a/Settings.c b/Settings.c
index 7d6fca4..8543b9e 100644
--- a/Settings.c
+++ b/Settings.c
@@ -10,6 +10,7 @@ in the source distribution for its full text.
#include <ctype.h>
#include <errno.h>
#include <limits.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -261,10 +262,9 @@ static void ScreenSettings_readFields(ScreenSettings* ss, Hashtable* columns, co
}
int id = toFieldIndex(columns, ids[i]);
if (id >= 0)
- ss->fields[j] = id;
+ ss->fields[j++] = id;
if (id > 0 && id < LAST_PROCESSFIELD)
ss->flags |= Process_fields[id].flags;
- j++;
}
String_freeArray(ids);
}
@@ -381,6 +381,8 @@ static bool Settings_read(Settings* this, const char* fileName, unsigned int ini
this->hideKernelThreads = atoi(option[1]);
} else if (String_eq(option[0], "hide_userland_threads")) {
this->hideUserlandThreads = atoi(option[1]);
+ } else if (String_eq(option[0], "hide_running_in_container")) {
+ this->hideRunningInContainer = atoi(option[1]);
} else if (String_eq(option[0], "shadow_other_users")) {
this->shadowOtherUsers = atoi(option[1]);
} else if (String_eq(option[0], "show_thread_names")) {
@@ -391,6 +393,8 @@ static bool Settings_read(Settings* this, const char* fileName, unsigned int ini
this->highlightBaseName = atoi(option[1]);
} else if (String_eq(option[0], "highlight_deleted_exe")) {
this->highlightDeletedExe = atoi(option[1]);
+ } else if (String_eq(option[0], "shadow_distribution_path_prefix")) {
+ this->shadowDistPathPrefix = atoi(option[1]);
} else if (String_eq(option[0], "highlight_megabytes")) {
this->highlightMegabytes = atoi(option[1]);
} else if (String_eq(option[0], "highlight_threads")) {
@@ -475,13 +479,17 @@ static bool Settings_read(Settings* this, const char* fileName, unsigned int ini
this->topologyAffinity = !!atoi(option[1]);
#endif
} else if (strncmp(option[0], "screen:", 7) == 0) {
- screen = Settings_newScreen(this, &(const ScreenDefaults){ .name = option[0] + 7, .columns = option[1] });
+ screen = Settings_newScreen(this, &(const ScreenDefaults) { .name = option[0] + 7, .columns = option[1] });
} else if (String_eq(option[0], ".sort_key")) {
- if (screen)
- screen->sortKey = toFieldIndex(this->dynamicColumns, option[1]);
+ if (screen) {
+ int key = toFieldIndex(this->dynamicColumns, option[1]);
+ screen->sortKey = key > 0 ? key : PID;
+ }
} else if (String_eq(option[0], ".tree_sort_key")) {
- if (screen)
- screen->treeSortKey = toFieldIndex(this->dynamicColumns, option[1]);
+ if (screen) {
+ int key = toFieldIndex(this->dynamicColumns, option[1]);
+ screen->treeSortKey = key > 0 ? key : PID;
+ }
} else if (String_eq(option[0], ".sort_direction")) {
if (screen)
screen->direction = atoi(option[1]);
@@ -575,11 +583,13 @@ int Settings_write(const Settings* this, bool onCrash) {
fprintf(fd, "fields="); writeFields(fd, this->screens[0]->fields, this->dynamicColumns, false, separator);
printSettingInteger("hide_kernel_threads", this->hideKernelThreads);
printSettingInteger("hide_userland_threads", this->hideUserlandThreads);
+ printSettingInteger("hide_running_in_container", this->hideRunningInContainer);
printSettingInteger("shadow_other_users", this->shadowOtherUsers);
printSettingInteger("show_thread_names", this->showThreadNames);
printSettingInteger("show_program_path", this->showProgramPath);
printSettingInteger("highlight_base_name", this->highlightBaseName);
printSettingInteger("highlight_deleted_exe", this->highlightDeletedExe);
+ printSettingInteger("shadow_distribution_path_prefix", this->shadowDistPathPrefix);
printSettingInteger("highlight_megabytes", this->highlightMegabytes);
printSettingInteger("highlight_threads", this->highlightThreads);
printSettingInteger("highlight_changes", this->highlightChanges);
@@ -668,8 +678,10 @@ Settings* Settings_new(unsigned int initialCpuCount, Hashtable* dynamicColumns)
this->showThreadNames = false;
this->hideKernelThreads = true;
this->hideUserlandThreads = false;
+ this->hideRunningInContainer = false;
this->highlightBaseName = false;
this->highlightDeletedExe = true;
+ this->shadowDistPathPrefix = false;
this->highlightMegabytes = true;
this->detailedCPUTime = false;
this->countCPUsFromOne = false;
@@ -702,9 +714,10 @@ Settings* Settings_new(unsigned int initialCpuCount, Hashtable* dynamicColumns)
this->filename = xStrdup(rcfile);
} else {
const char* home = getenv("HOME");
- if (!home)
- home = "";
-
+ if (!home) {
+ const struct passwd* pw = getpwuid(getuid());
+ home = pw ? pw->pw_dir : "";
+ }
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
char* configDir = NULL;
char* htopDir = NULL;
diff --git a/Settings.h b/Settings.h
index facd3f2..baf05da 100644
--- a/Settings.h
+++ b/Settings.h
@@ -73,9 +73,11 @@ typedef struct Settings_ {
bool shadowOtherUsers;
bool showThreadNames;
bool hideKernelThreads;
+ bool hideRunningInContainer;
bool hideUserlandThreads;
bool highlightBaseName;
bool highlightDeletedExe;
+ bool shadowDistPathPrefix;
bool highlightMegabytes;
bool highlightThreads;
bool highlightChanges;
diff --git a/SwapMeter.c b/SwapMeter.c
index 081967f..c0f4820 100644
--- a/SwapMeter.c
+++ b/SwapMeter.c
@@ -45,12 +45,12 @@ static void SwapMeter_display(const Object* cast, RichString* out) {
RichString_writeAscii(out, CRT_colors[METER_TEXT], ":");
Meter_humanUnit(buffer, this->total, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer);
- Meter_humanUnit(buffer, this->values[0], sizeof(buffer));
+ Meter_humanUnit(buffer, this->values[SWAP_METER_USED], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:");
RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer);
- if (!isnan(this->values[1])) {
- Meter_humanUnit(buffer, this->values[1], sizeof(buffer));
+ if (!isnan(this->values[SWAP_METER_CACHE])) {
+ Meter_humanUnit(buffer, this->values[SWAP_METER_CACHE], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " cache:");
RichString_appendAscii(out, CRT_colors[SWAP_CACHE], buffer);
}
diff --git a/SwapMeter.h b/SwapMeter.h
index 485485a..b71e83f 100644
--- a/SwapMeter.h
+++ b/SwapMeter.h
@@ -9,6 +9,11 @@ in the source distribution for its full text.
#include "Meter.h"
+typedef enum {
+ SWAP_METER_USED = 0,
+ SWAP_METER_CACHE = 1,
+ SWAP_METER_ITEMCOUNT = 2, // number of entries in this enum
+} SwapMeterValues;
extern const MeterClass SwapMeter_class;
diff --git a/TraceScreen.c b/TraceScreen.c
index 90400b4..2aa0781 100644
--- a/TraceScreen.c
+++ b/TraceScreen.c
@@ -164,17 +164,17 @@ static void TraceScreen_updateTrace(InfoScreen* super) {
static bool TraceScreen_onKey(InfoScreen* super, int ch) {
TraceScreen* this = (TraceScreen*) super;
- switch(ch) {
+ switch (ch) {
case 'f':
case KEY_F(8):
this->follow = !(this->follow);
if (this->follow)
- Panel_setSelected(super->display, Panel_size(super->display)-1);
+ Panel_setSelected(super->display, Panel_size(super->display) - 1);
return true;
case 't':
case KEY_F(9):
this->tracing = !this->tracing;
- FunctionBar_setLabel(super->display->defaultBar, KEY_F(9), this->tracing?"Stop Tracing ":"Resume Tracing ");
+ FunctionBar_setLabel(super->display->defaultBar, KEY_F(9), this->tracing ? "Stop Tracing " : "Resume Tracing ");
InfoScreen_draw(this);
return true;
}
diff --git a/UsersTable.c b/UsersTable.c
index 8c4a0ed..6586a4b 100644
--- a/UsersTable.c
+++ b/UsersTable.c
@@ -17,7 +17,7 @@ in the source distribution for its full text.
#include "XUtils.h"
-UsersTable* UsersTable_new() {
+UsersTable* UsersTable_new(void) {
UsersTable* this;
this = xMalloc(sizeof(UsersTable));
this->users = Hashtable_new(10, true);
diff --git a/XUtils.c b/XUtils.c
index 2012b6c..6a021f3 100644
--- a/XUtils.c
+++ b/XUtils.c
@@ -21,7 +21,7 @@ in the source distribution for its full text.
#include "CRT.h"
-void fail() {
+void fail(void) {
CRT_done();
abort();
@@ -104,9 +104,9 @@ inline bool String_contains_i(const char* s1, const char* s2, bool multi) {
String_freeArray(needles);
return true;
}
- }
- String_freeArray(needles);
- return false;
+ }
+ String_freeArray(needles);
+ return false;
} else {
return strcasestr(s1, s2) != NULL;
}
@@ -313,3 +313,26 @@ ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size
return readfd_internal(fd, buffer, count);
}
+
+ssize_t full_write(int fd, const void* buf, size_t count) {
+ ssize_t written = 0;
+
+ while (count > 0) {
+ ssize_t r = write(fd, buf, count);
+ if (r < 0) {
+ if (errno == EINTR)
+ continue;
+
+ return r;
+ }
+
+ if (r == 0)
+ break;
+
+ written += r;
+ buf = (const unsigned char*)buf + r;
+ count -= (size_t)r;
+ }
+
+ return written;
+}
diff --git a/XUtils.h b/XUtils.h
index 2522a71..e1c50be 100644
--- a/XUtils.h
+++ b/XUtils.h
@@ -73,4 +73,6 @@ char* xStrndup(const char* str, size_t len) ATTR_NONNULL ATTR_MALLOC;
ssize_t xReadfile(const char* pathname, void* buffer, size_t count);
ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count);
+ssize_t full_write(int fd, const void* buf, size_t count);
+
#endif
diff --git a/configure.ac b/configure.ac
index 7a52ab5..bbb042a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@
# ----------------------------------------------------------------------
AC_PREREQ([2.69])
-AC_INIT([htop], [3.2.1], [htop@groups.io], [], [https://htop.dev/])
+AC_INIT([htop], [3.2.2], [htop@groups.io], [], [https://htop.dev/])
AC_CONFIG_SRCDIR([htop.c])
AC_CONFIG_AUX_DIR([build-aux])
@@ -212,7 +212,7 @@ AC_RUN_IFELSE([
# Checks for generic library functions.
# ----------------------------------------------------------------------
-AC_CHECK_LIB([m], [ceil], [], [AC_MSG_ERROR([can not find required function ceil()])])
+AC_SEARCH_LIBS([ceil], [m], [], [AC_MSG_ERROR([can not find required function ceil()])])
if test "$my_htop_platform" = dragonflybsd; then
AC_SEARCH_LIBS([kvm_open], [kvm], [], [AC_MSG_ERROR([can not find required function kvm_open()])])
@@ -266,6 +266,10 @@ if test "$my_htop_platform" = darwin; then
AC_CHECK_FUNCS([mach_timebase_info])
fi
+if test "$my_htop_platform" = pcp; then
+ AC_CHECK_FUNCS([pmLookupDescs])
+fi
+
if test "$my_htop_platform" = linux && test "x$enable_static" = xyes; then
AC_CHECK_LIB([systemd], [sd_bus_open_system])
fi
@@ -723,7 +727,7 @@ AC_SUBST([AM_CPPFLAGS])
# We're done, let's go!
# ----------------------------------------------------------------------
-AC_DEFINE_UNQUOTED([COPYRIGHT], ["(C) 2004-2019 Hisham Muhammad. (C) 2020-2022 htop dev team."], [Copyright message.])
+AC_DEFINE_UNQUOTED([COPYRIGHT], ["(C) 2004-2019 Hisham Muhammad. (C) 2020-2023 htop dev team."], [Copyright message.])
AM_CONDITIONAL([HTOP_LINUX], [test "$my_htop_platform" = linux])
AM_CONDITIONAL([HTOP_FREEBSD], [test "$my_htop_platform" = freebsd])
diff --git a/darwin/DarwinProcess.c b/darwin/DarwinProcess.c
index d0204dd..6027c25 100644
--- a/darwin/DarwinProcess.c
+++ b/darwin/DarwinProcess.c
@@ -282,7 +282,7 @@ static char* DarwinProcess_getDevname(dev_t dev) {
return NULL;
}
char buf[sizeof("/dev/") + MAXNAMLEN];
- char *name = devname_r(dev, S_IFCHR, buf, MAXNAMLEN);
+ char* name = devname_r(dev, S_IFCHR, buf, MAXNAMLEN);
if (name) {
return xStrdup(name);
}
diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c
index bd7821b..dae588b 100644
--- a/darwin/DarwinProcessList.c
+++ b/darwin/DarwinProcessList.c
@@ -68,12 +68,13 @@ static struct kinfo_proc* ProcessList_getKInfoProcs(size_t* count) {
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
struct kinfo_proc* processes = NULL;
- for (int retry = 3; retry > 0; retry--) {
+ for (unsigned int retry = 0; retry < 4; retry++) {
size_t size = 0;
if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0 || size == 0) {
CRT_fatalError("Unable to get size of kproc_infos");
}
+ size += 16 * retry * retry * sizeof(struct kinfo_proc);
processes = xRealloc(processes, size);
if (sysctl(mib, 4, processes, &size, NULL, 0) == 0) {
diff --git a/darwin/Platform.c b/darwin/Platform.c
index 4b34d88..332752b 100644
--- a/darwin/Platform.c
+++ b/darwin/Platform.c
@@ -172,7 +172,7 @@ void Platform_setBindings(Htop_Action* keys) {
(void) keys;
}
-int Platform_getUptime() {
+int Platform_getUptime(void) {
struct timeval bootTime, currTime;
int mib[2] = { CTL_KERN, KERN_BOOTTIME };
size_t size = sizeof(bootTime);
@@ -200,7 +200,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
}
}
-int Platform_getMaxPid() {
+int Platform_getMaxPid(void) {
/* http://opensource.apple.com/source/xnu/xnu-2782.1.97/bsd/sys/proc_internal.hh */
return 99999;
}
@@ -264,11 +264,11 @@ void Platform_setMemoryValues(Meter* mtr) {
double page_K = (double)vm_page_size / (double)1024;
mtr->total = dpl->host_info.max_mem / 1024;
- mtr->values[0] = (double)(vm->active_count + vm->wire_count) * page_K;
- mtr->values[1] = (double)vm->purgeable_count * page_K;
- // mtr->values[2] = "shared memory, like tmpfs and shm"
- mtr->values[3] = (double)vm->inactive_count * page_K;
- // mtr->values[4] = "available memory"
+ mtr->values[MEMORY_METER_USED] = (double)(vm->active_count + vm->wire_count) * page_K;
+ mtr->values[MEMORY_METER_BUFFERS] = (double)vm->purgeable_count * page_K;
+ // mtr->values[MEMORY_METER_SHARED] = "shared memory, like tmpfs and shm"
+ mtr->values[MEMORY_METER_CACHE] = (double)vm->inactive_count * page_K;
+ // mtr->values[MEMORY_METER_AVAILABLE] = "available memory"
}
void Platform_setSwapValues(Meter* mtr) {
@@ -278,7 +278,7 @@ void Platform_setSwapValues(Meter* mtr) {
sysctl(mib, 2, &swapused, &swlen, NULL, 0);
mtr->total = swapused.xsu_total / 1024;
- mtr->values[0] = swapused.xsu_used / 1024;
+ mtr->values[SWAP_METER_USED] = swapused.xsu_used / 1024;
}
void Platform_setZfsArcValues(Meter* this) {
@@ -344,12 +344,6 @@ char* Platform_getProcessEnv(pid_t pid) {
return env;
}
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
-}
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
diff --git a/darwin/Platform.h b/darwin/Platform.h
index 4f8e7c9..6636207 100644
--- a/darwin/Platform.h
+++ b/darwin/Platform.h
@@ -68,8 +68,6 @@ void Platform_setZfsCompressedArcValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
bool Platform_getDiskIO(DiskIOData* data);
@@ -100,7 +98,9 @@ static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec)
void Platform_gettime_monotonic(uint64_t* msec);
-static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+static inline Hashtable* Platform_dynamicMeters(void) {
+ return NULL;
+}
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
@@ -110,12 +110,18 @@ static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) {
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
-static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+static inline Hashtable* Platform_dynamicColumns(void) {
+ return NULL;
+}
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
-static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) {
+ return NULL;
+}
-static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) {
+ return false;
+}
#endif
diff --git a/darwin/PlatformHelpers.c b/darwin/PlatformHelpers.c
index bde9068..97f0741 100644
--- a/darwin/PlatformHelpers.c
+++ b/darwin/PlatformHelpers.c
@@ -58,7 +58,7 @@ bool Platform_KernelVersionIsBetween(KernelVersion lowerBound, KernelVersion upp
&& Platform_CompareKernelVersion(upperBound) < 0;
}
-void Platform_getCPUBrandString(char *cpuBrandString, size_t cpuBrandStringSize) {
+void Platform_getCPUBrandString(char* cpuBrandString, size_t cpuBrandStringSize) {
if (sysctlbyname("machdep.cpu.brand_string", cpuBrandString, &cpuBrandStringSize, NULL, 0) == -1) {
fprintf(stderr,
"WARN: Unable to determine the CPU brand string.\n"
@@ -69,12 +69,13 @@ void Platform_getCPUBrandString(char *cpuBrandString, size_t cpuBrandStringSize)
}
// Adapted from https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment
-bool Platform_isRunningTranslated() {
+bool Platform_isRunningTranslated(void) {
int ret = 0;
size_t size = sizeof(ret);
errno = 0;
if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) {
- if (errno == ENOENT) return false;
+ if (errno == ENOENT)
+ return false;
fprintf(stderr,
"WARN: Could not determine if this process was running in a translation environment like Rosetta 2.\n"
@@ -86,7 +87,7 @@ bool Platform_isRunningTranslated() {
return ret;
}
-double Platform_calculateNanosecondsPerMachTick() {
+double Platform_calculateNanosecondsPerMachTick(void) {
// Check if we can determine the timebase used on this system.
// If the API is unavailable assume we get our timebase in nanoseconds.
#ifndef HAVE_MACH_TIMEBASE_INFO
diff --git a/darwin/PlatformHelpers.h b/darwin/PlatformHelpers.h
index 07f3fe2..45aea1a 100644
--- a/darwin/PlatformHelpers.h
+++ b/darwin/PlatformHelpers.h
@@ -31,7 +31,7 @@ bool Platform_KernelVersionIsBetween(KernelVersion lowerBound, KernelVersion upp
double Platform_calculateNanosecondsPerMachTick(void);
-void Platform_getCPUBrandString(char *cpuBrandString, size_t cpuBrandStringSize);
+void Platform_getCPUBrandString(char* cpuBrandString, size_t cpuBrandStringSize);
bool Platform_isRunningTranslated(void);
diff --git a/docs/images/screenshot.png b/docs/images/screenshot.png
index 0ff3cfe..85cb9dd 100644
--- a/docs/images/screenshot.png
+++ b/docs/images/screenshot.png
Binary files differ
diff --git a/dragonflybsd/DragonFlyBSDProcessList.c b/dragonflybsd/DragonFlyBSDProcessList.c
index 0d0e1a4..f46d6ce 100644
--- a/dragonflybsd/DragonFlyBSDProcessList.c
+++ b/dragonflybsd/DragonFlyBSDProcessList.c
@@ -509,7 +509,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
proc->m_virt = kproc->kp_vm_map_size / ONE_K;
proc->m_resident = kproc->kp_vm_rssize * pageSizeKb;
proc->nlwp = kproc->kp_nthreads; // number of lwp thread
- proc->time = (kproc->kp_swtime + 5000) / 10000;
+ proc->time = (kproc->kp_lwp.kl_uticks + kproc->kp_lwp.kl_sticks + kproc->kp_lwp.kl_iticks) / 10000;
proc->percent_cpu = 100.0 * ((double)kproc->kp_lwp.kl_pctcpu / (double)kernelFScale);
proc->percent_mem = 100.0 * proc->m_resident / (double)(super->totalMem);
@@ -527,7 +527,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
else
proc->priority = -kproc->kp_lwp.kl_tdprio;
- switch(kproc->kp_lwp.kl_rtprio.type) {
+ switch (kproc->kp_lwp.kl_rtprio.type) {
case RTP_PRIO_REALTIME:
proc->nice = PRIO_MIN - 1 - RTP_PRIO_MAX + kproc->kp_lwp.kl_rtprio.prio;
break;
diff --git a/dragonflybsd/Platform.c b/dragonflybsd/Platform.c
index ea5f4fa..8a684d8 100644
--- a/dragonflybsd/Platform.c
+++ b/dragonflybsd/Platform.c
@@ -126,7 +126,7 @@ void Platform_setBindings(Htop_Action* keys) {
(void) keys;
}
-int Platform_getUptime() {
+int Platform_getUptime(void) {
struct timeval bootTime, currTime;
int mib[2] = { CTL_KERN, KERN_BOOTTIME };
size_t size = sizeof(bootTime);
@@ -157,7 +157,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
*fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale;
}
-int Platform_getMaxPid() {
+int Platform_getMaxPid(void) {
int maxPid;
size_t size = sizeof(maxPid);
int err = sysctlbyname("kern.pid_max", &maxPid, &size, NULL, 0);
@@ -208,18 +208,18 @@ void Platform_setMemoryValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalMem;
- this->values[0] = pl->usedMem;
- this->values[1] = pl->buffersMem;
- // this->values[2] = "shared memory, like tmpfs and shm"
- this->values[3] = pl->cachedMem;
- // this->values[4] = "available memory"
+ this->values[MEMORY_METER_USED] = pl->usedMem;
+ this->values[MEMORY_METER_BUFFERS] = pl->buffersMem;
+ // this->values[MEMORY_METER_SHARED] = "shared memory, like tmpfs and shm"
+ this->values[MEMORY_METER_CACHE] = pl->cachedMem;
+ // this->values[MEMORY_METER_AVAILABLE] = "available memory"
}
void Platform_setSwapValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalSwap;
- this->values[0] = pl->usedSwap;
- this->values[1] = NAN;
+ this->values[SWAP_METER_USED] = pl->usedSwap;
+ this->values[SWAP_METER_CACHE] = NAN;
}
char* Platform_getProcessEnv(pid_t pid) {
@@ -228,12 +228,6 @@ char* Platform_getProcessEnv(pid_t pid) {
return NULL;
}
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
-}
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
diff --git a/dragonflybsd/Platform.h b/dragonflybsd/Platform.h
index ec140ad..cf69356 100644
--- a/dragonflybsd/Platform.h
+++ b/dragonflybsd/Platform.h
@@ -59,8 +59,6 @@ void Platform_setSwapValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
bool Platform_getDiskIO(DiskIOData* data);
@@ -93,7 +91,9 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
Generic_gettime_monotonic(msec);
}
-static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+static inline Hashtable* Platform_dynamicMeters(void) {
+ return NULL;
+}
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
@@ -103,12 +103,18 @@ static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) {
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
-static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+static inline Hashtable* Platform_dynamicColumns(void) {
+ return NULL;
+}
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
-static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) {
+ return NULL;
+}
-static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) {
+ return false;
+}
#endif
diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c
index f58f338..2c7e20b 100644
--- a/freebsd/FreeBSDProcessList.c
+++ b/freebsd/FreeBSDProcessList.c
@@ -25,6 +25,7 @@ in the source distribution for its full text.
#include <sys/time.h>
#include <sys/types.h>
#include <sys/user.h>
+#include <sys/vmmeter.h>
#include "CRT.h"
#include "Compat.h"
@@ -49,6 +50,7 @@ static int MIB_vm_stats_vm_v_active_count[4];
static int MIB_vm_stats_vm_v_cache_count[4];
static int MIB_vm_stats_vm_v_inactive_count[4];
static int MIB_vm_stats_vm_v_free_count[4];
+static int MIB_vm_vmtotal[2];
static int MIB_vfs_bufspace[2];
@@ -82,6 +84,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, H
len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len);
len = 4; sysctlnametomib("vm.stats.vm.v_inactive_count", MIB_vm_stats_vm_v_inactive_count, &len);
len = 4; sysctlnametomib("vm.stats.vm.v_free_count", MIB_vm_stats_vm_v_free_count, &len);
+ len = 2; sysctlnametomib("vm.vmtotal", MIB_vm_vmtotal, &len);
len = 2; sysctlnametomib("vfs.bufspace", MIB_vfs_bufspace, &len);
@@ -330,6 +333,7 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
u_int memActive, memWire, cachedMem;
long buffersMem;
size_t len;
+ struct vmtotal vmtotal;
//disabled for now, as it is always smaller than phycal amount of memory...
//...to avoid "where is my memory?" questions
@@ -360,6 +364,10 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
cachedMem *= pageSizeKb;
pl->cachedMem = cachedMem;
+ len = sizeof(vmtotal);
+ sysctl(MIB_vm_vmtotal, 2, &(vmtotal), &len, NULL, 0);
+ pl->sharedMem = vmtotal.t_vmshr * pageSizeKb;
+
if (fpl->zfs.enabled) {
fpl->memWire -= fpl->zfs.size;
pl->cachedMem += fpl->zfs.size;
@@ -397,6 +405,7 @@ static void FreeBSDProcessList_updateExe(const struct kinfo_proc* kproc, Process
}
static void FreeBSDProcessList_updateCwd(const struct kinfo_proc* kproc, Process* proc) {
+#ifdef KERN_PROC_CWD
const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_CWD, kproc->ki_pid };
char buffer[2048];
size_t size = sizeof(buffer);
@@ -414,6 +423,9 @@ static void FreeBSDProcessList_updateCwd(const struct kinfo_proc* kproc, Process
}
free_and_xStrdup(&proc->procCwd, buffer);
+#else
+ proc->procCwd = NULL;
+#endif
}
static void FreeBSDProcessList_updateProcessName(kvm_t* kd, const struct kinfo_proc* kproc, Process* proc) {
diff --git a/freebsd/Platform.c b/freebsd/Platform.c
index 1a731b7..646163a 100644
--- a/freebsd/Platform.c
+++ b/freebsd/Platform.c
@@ -148,7 +148,7 @@ void Platform_setBindings(Htop_Action* keys) {
(void) keys;
}
-int Platform_getUptime() {
+int Platform_getUptime(void) {
struct timeval bootTime, currTime;
const int mib[2] = { CTL_KERN, KERN_BOOTTIME };
size_t size = sizeof(bootTime);
@@ -179,7 +179,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
*fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale;
}
-int Platform_getMaxPid() {
+int Platform_getMaxPid(void) {
int maxPid;
size_t size = sizeof(maxPid);
int err = sysctlbyname("kern.pid_max", &maxPid, &size, NULL, 0);
@@ -230,28 +230,28 @@ void Platform_setMemoryValues(Meter* this) {
const FreeBSDProcessList* fpl = (const FreeBSDProcessList*) pl;
this->total = pl->totalMem;
- this->values[0] = pl->usedMem;
- this->values[1] = pl->buffersMem;
- // this->values[2] = "shared memory, like tmpfs and shm"
- this->values[3] = pl->cachedMem;
- // this->values[4] = "available memory"
+ this->values[MEMORY_METER_USED] = pl->usedMem;
+ this->values[MEMORY_METER_BUFFERS] = pl->buffersMem;
+ this->values[MEMORY_METER_SHARED] = pl->sharedMem;
+ this->values[MEMORY_METER_CACHE] = pl->cachedMem;
+ // this->values[MEMORY_METER_AVAILABLE] = "available memory"
if (fpl->zfs.enabled) {
// ZFS does not shrink below the value of zfs_arc_min.
unsigned long long int shrinkableSize = 0;
if (fpl->zfs.size > fpl->zfs.min)
shrinkableSize = fpl->zfs.size - fpl->zfs.min;
- this->values[0] -= shrinkableSize;
- this->values[3] += shrinkableSize;
- // this->values[4] += shrinkableSize;
+ this->values[MEMORY_METER_USED] -= shrinkableSize;
+ this->values[MEMORY_METER_CACHE] += shrinkableSize;
+ // this->values[MEMORY_METER_AVAILABLE] += shrinkableSize;
}
}
void Platform_setSwapValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalSwap;
- this->values[0] = pl->usedSwap;
- this->values[1] = NAN;
+ this->values[SWAP_METER_USED] = pl->usedSwap;
+ this->values[SWAP_METER_CACHE] = NAN;
}
void Platform_setZfsArcValues(Meter* this) {
@@ -287,12 +287,6 @@ char* Platform_getProcessEnv(pid_t pid) {
return env;
}
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
-}
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
diff --git a/freebsd/Platform.h b/freebsd/Platform.h
index c0292d9..51269c0 100644
--- a/freebsd/Platform.h
+++ b/freebsd/Platform.h
@@ -59,8 +59,6 @@ void Platform_setZfsCompressedArcValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
bool Platform_getDiskIO(DiskIOData* data);
@@ -93,7 +91,9 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
Generic_gettime_monotonic(msec);
}
-static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+static inline Hashtable* Platform_dynamicMeters(void) {
+ return NULL;
+}
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
@@ -103,12 +103,18 @@ static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) {
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
-static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+static inline Hashtable* Platform_dynamicColumns(void) {
+ return NULL;
+}
-static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) {
+ return NULL;
+}
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
-static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) {
+ return false;
+}
#endif
diff --git a/htop.1.in b/htop.1.in
index c81c819..eefc37f 100644
--- a/htop.1.in
+++ b/htop.1.in
@@ -1,4 +1,4 @@
-.TH "HTOP" "1" "2022" "@PACKAGE_STRING@" "User Commands"
+.TH "HTOP" "1" "2023" "@PACKAGE_STRING@" "User Commands"
.SH "NAME"
htop, pcp-htop \- interactive process viewer
.SH "SYNOPSIS"
@@ -327,7 +327,8 @@ The process ID.
.TP
.B STATE (S)
The state of the process:
- \fBS\fR for sleeping (idle)
+ \fBS\fR for sleeping
+ \fBI\fR for idle (longer inactivity than sleeping on platforms that distinguish)
\fBR\fR for running
\fBD\fR for disk sleep (uninterruptible)
\fBZ\fR for zombie (waiting for parent to read its exit status)
@@ -668,7 +669,7 @@ communities, and forms part of the Performance Co-Pilot suite of tools.
.SH "COPYRIGHT"
Copyright \(co 2004-2019 Hisham Muhammad.
.br
-Copyright \(co 2020-2022 htop dev team.
+Copyright \(co 2020-2023 htop dev team.
.LP
License GPLv2+: GNU General Public License version 2 or, at your option, any later version.
.LP
diff --git a/htop.png b/htop.png
index 90020ad..7809d22 100644
--- a/htop.png
+++ b/htop.png
Binary files differ
diff --git a/linux/CGroupUtils.c b/linux/CGroupUtils.c
index 22cce91..c11c460 100644
--- a/linux/CGroupUtils.c
+++ b/linux/CGroupUtils.c
@@ -11,7 +11,7 @@ in the source distribution for its full text.
typedef struct StrBuf_state {
- char *buf;
+ char* buf;
size_t size;
size_t pos;
} StrBuf_state;
@@ -60,7 +60,7 @@ static bool Label_checkSuffix(const char* labelStart, size_t labelLen, const cha
return labelLen > strlen(expected) && String_startsWith(labelStart + labelLen - strlen(expected), expected);
}
-static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrBuf_putc_t w) {
+static bool CGroup_filterName_internal(const char* cgroup, StrBuf_state* s, StrBuf_putc_t w) {
const char* str_slice_suffix = ".slice";
const char* str_system_slice = "system.slice";
const char* str_user_slice = "user.slice";
@@ -237,7 +237,7 @@ static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrB
if (String_startsWith(cgroup, "user@")) {
cgroup = nextSlash;
- while(*cgroup == '/')
+ while (*cgroup == '/')
cgroup++;
continue;
@@ -275,7 +275,7 @@ static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrB
cgroup += strlen(str_nspawn_payload_label);
continue;
- } else if(Label_checkPrefix(labelStart, scopeNameLen, str_snap_scope_prefix)) {
+ } else if (Label_checkPrefix(labelStart, scopeNameLen, str_snap_scope_prefix)) {
const char* nextDot = strchrnul(labelStart + strlen(str_snap_scope_prefix), '.');
if (!StrBuf_putsz(s, w, "!snap:"))
@@ -316,7 +316,7 @@ static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrB
return true;
}
-char* CGroup_filterName(const char *cgroup) {
+char* CGroup_filterName(const char* cgroup) {
StrBuf_state s = {
.buf = NULL,
.size = 0,
diff --git a/linux/CGroupUtils.h b/linux/CGroupUtils.h
index db2df7f..ff13437 100644
--- a/linux/CGroupUtils.h
+++ b/linux/CGroupUtils.h
@@ -11,6 +11,6 @@ in the source distribution for its full text.
#include <stddef.h>
-char* CGroup_filterName(const char *cgroup);
+char* CGroup_filterName(const char* cgroup);
#endif /* HEADER_CGroupUtils */
diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c
index 92be326..381b7cf 100644
--- a/linux/LinuxProcess.c
+++ b/linux/LinuxProcess.c
@@ -53,8 +53,8 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
[M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, },
[M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, },
[M_SHARE] = { .name = "M_SHARE", .title = " SHR ", .description = "Size of the process's shared pages", .flags = 0, .defaultSortDesc = true, },
- [M_TRS] = { .name = "M_TRS", .title = " CODE ", .description = "Size of the text segment of the process", .flags = 0, .defaultSortDesc = true, },
- [M_DRS] = { .name = "M_DRS", .title = " DATA ", .description = "Size of the data segment plus stack usage of the process", .flags = 0, .defaultSortDesc = true, },
+ [M_TRS] = { .name = "M_TRS", .title = " CODE ", .description = "Size of the .text segment of the process (CODE)", .flags = 0, .defaultSortDesc = true, },
+ [M_DRS] = { .name = "M_DRS", .title = " DATA ", .description = "Size of the .data segment plus stack usage of the process (DATA)", .flags = 0, .defaultSortDesc = true, },
[M_LRS] = { .name = "M_LRS", .title = " LIB ", .description = "The library size of the process (calculated from memory maps)", .flags = PROCESS_FLAG_LINUX_LRS_FIX, .defaultSortDesc = true, },
[ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, },
[PERCENT_CPU] = { .name = "PERCENT_CPU", .title = " CPU%", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, },
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
index 45b045c..eca9459 100644
--- a/linux/LinuxProcessList.c
+++ b/linux/LinuxProcessList.c
@@ -10,6 +10,7 @@ in the source distribution for its full text.
#include "linux/LinuxProcessList.h"
#include <assert.h>
+#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -181,7 +182,7 @@ static unsigned int scanAvailableCPUsFromCPUinfo(LinuxProcessList* this) {
if (String_startsWith(buffer, "processor"))
availableCPUs++;
- }
+ }
fclose(file);
@@ -219,7 +220,7 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super) {
if (!String_startsWith(entry->d_name, "cpu"))
continue;
- char *endp;
+ char* endp;
unsigned long int id = strtoul(entry->d_name + 3, &endp, 10);
if (id == ULONG_MAX || endp == entry->d_name + 3 || *endp != '\0')
continue;
@@ -263,9 +264,9 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super) {
return;
if (Running_containerized) {
- /* LXC munges /proc/cpuinfo but not the /sys/devices/system/cpu/ files,
- * so limit the visible CPUs to what the guest has been configured to see: */
- currExisting = active = scanAvailableCPUsFromCPUinfo(this);
+ /* LXC munges /proc/cpuinfo but not the /sys/devices/system/cpu/ files,
+ * so limit the visible CPUs to what the guest has been configured to see: */
+ currExisting = active = scanAvailableCPUsFromCPUinfo(this);
}
#ifdef HAVE_SENSORS_SENSORS_H
@@ -671,7 +672,7 @@ static void LinuxProcessList_readMaps(LinuxProcess* process, openat_arg_t procFd
if (' ' != *readptr++)
continue;
- while(*readptr > ' ')
+ while (*readptr > ' ')
readptr++; // Skip parsing this hex value
if (' ' != *readptr++)
continue;
@@ -763,6 +764,43 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t p
return r == 7;
}
+static bool LinuxProcessList_checkPidNamespace(Process* process, openat_arg_t procFd) {
+ FILE* statusfile = fopenat(procFd, "status", "r");
+ if (!statusfile)
+ return false;
+
+ while (true) {
+ char buffer[PROC_LINE_LENGTH + 1];
+ if (fgets(buffer, sizeof(buffer), statusfile) == NULL)
+ break;
+
+ if (!String_startsWith(buffer, "NSpid:"))
+ continue;
+
+ char* ptr = buffer;
+ int pid_ns_count = 0;
+ while (*ptr && *ptr != '\n' && !isdigit(*ptr))
+ ++ptr;
+
+ while (*ptr && *ptr != '\n') {
+ if (isdigit(*ptr))
+ pid_ns_count++;
+ while (isdigit(*ptr))
+ ++ptr;
+ while (*ptr && *ptr != '\n' && !isdigit(*ptr))
+ ++ptr;
+ }
+
+ if (pid_ns_count > 1)
+ process->isRunningInContainer = true;
+
+ break;
+ }
+
+ fclose(statusfile);
+ return true;
+}
+
static bool LinuxProcessList_readSmapsFile(LinuxProcess* process, openat_arg_t procFd, bool haveSmapsRollup) {
//http://elixir.free-electrons.com/linux/v4.10/source/fs/proc/task_mmu.c#L719
//kernel will return data in chunks of size PAGE_SIZE or less.
@@ -851,7 +889,7 @@ static void LinuxProcessList_readOpenVZData(LinuxProcess* process, openat_arg_t
char* value_end = name_value_sep;
- while(*value_end > 32) {
+ while (*value_end > 32) {
value_end++;
}
@@ -861,7 +899,7 @@ static void LinuxProcessList_readOpenVZData(LinuxProcess* process, openat_arg_t
*value_end = '\0';
- switch(field) {
+ switch (field) {
case 1:
foundEnvID = true;
if (!String_eq(name_value_sep, process->ctid ? process->ctid : ""))
@@ -891,6 +929,13 @@ static void LinuxProcessList_readOpenVZData(LinuxProcess* process, openat_arg_t
#endif
+static bool isContainerOrVMSlice(char* cgroup) {
+ if (String_startsWith(cgroup, "/user") || String_startsWith(cgroup, "/system"))
+ return false;
+
+ return true;
+}
+
static void LinuxProcessList_readCGroupFile(LinuxProcess* process, openat_arg_t procFd) {
FILE* file = fopenat(procFd, "cgroup", "r");
if (!file) {
@@ -941,7 +986,7 @@ static void LinuxProcessList_readCGroupFile(LinuxProcess* process, openat_arg_t
free_and_xStrdup(&process->cgroup, output);
if (!changed) {
- if(process->cgroup_short) {
+ if (process->cgroup_short) {
Process_updateFieldWidth(CCGROUP, strlen(process->cgroup_short));
} else {
//CCGROUP is alias to normal CGROUP if shortening fails
@@ -1090,9 +1135,7 @@ static void LinuxProcessList_readCwd(LinuxProcess* process, openat_arg_t procFd)
#if defined(HAVE_READLINKAT) && defined(HAVE_OPENAT)
ssize_t r = readlinkat(procFd, "cwd", pathBuffer, sizeof(pathBuffer) - 1);
#else
- char filename[MAX_NAME + 1];
- xSnprintf(filename, sizeof(filename), "%s/cwd", procFd);
- ssize_t r = readlink(filename, pathBuffer, sizeof(pathBuffer) - 1);
+ ssize_t r = Compat_readlink(procFd, "cwd", pathBuffer, sizeof(pathBuffer) - 1);
#endif
if (r < 0) {
@@ -1329,9 +1372,7 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t proc
#if defined(HAVE_READLINKAT) && defined(HAVE_OPENAT)
amtRead = readlinkat(procFd, "exe", filename, sizeof(filename) - 1);
#else
- char path[4096];
- xSnprintf(path, sizeof(path), "%s/exe", procFd);
- amtRead = readlink(path, filename, sizeof(filename) - 1);
+ amtRead = Compat_readlink(procFd, "exe", filename, sizeof(filename) - 1);
#endif
if (amtRead > 0) {
filename[amtRead] = 0;
@@ -1423,7 +1464,7 @@ static bool isOlderThan(const ProcessList* pl, const Process* proc, unsigned int
/* Starttime might not yet be parsed */
if (proc->starttime_ctime <= 0)
- return false;
+ return false;
uint64_t realtime = pl->realtimeMs / 1000;
@@ -1457,6 +1498,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
const unsigned int activeCPUs = pl->activeCPUs;
const bool hideKernelThreads = settings->hideKernelThreads;
const bool hideUserlandThreads = settings->hideUserlandThreads;
+ const bool hideRunningInContainer = settings->hideRunningInContainer;
while ((entry = readdir(dir)) != NULL) {
const char* name = entry->d_name;
@@ -1508,6 +1550,15 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
LinuxProcessList_recurseProcTree(this, procFd, "task", proc, period);
+ if (ss->flags & PROCESS_FLAG_LINUX_CGROUP || hideRunningInContainer) {
+ LinuxProcessList_readCGroupFile(lp, procFd);
+ if (hideRunningInContainer && lp->cgroup && isContainerOrVMSlice(lp->cgroup)) {
+ if (!LinuxProcessList_checkPidNamespace(proc, procFd)) {
+ goto errorReadingProcess;
+ }
+ }
+ }
+
/*
* These conditions will not trigger on first occurrence, cause we need to
* add the process to the ProcessList and do all one time scans
@@ -1530,6 +1581,12 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
Compat_openatArgClose(procFd);
continue;
}
+ if (preExisting && hideRunningInContainer && proc->isRunningInContainer) {
+ proc->updated = true;
+ proc->show = false;
+ Compat_openatArgClose(procFd);
+ continue;
+ }
if (ss->flags & PROCESS_FLAG_IO)
LinuxProcessList_readIoFile(lp, procFd, pl->realtimeMs);
@@ -1580,7 +1637,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
char statCommand[MAX_NAME + 1];
unsigned long long int lasttimes = (lp->utime + lp->stime);
unsigned long int tty_nr = proc->tty_nr;
- if (! LinuxProcessList_readStatFile(proc, procFd, statCommand, sizeof(statCommand)))
+ if (!LinuxProcessList_readStatFile(proc, procFd, statCommand, sizeof(statCommand)))
goto errorReadingProcess;
if (lp->flags & PF_KTHREAD) {
@@ -1644,10 +1701,6 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
}
#endif
- if (ss->flags & PROCESS_FLAG_LINUX_CGROUP) {
- LinuxProcessList_readCGroupFile(lp, procFd);
- }
-
if (ss->flags & PROCESS_FLAG_LINUX_OOM) {
LinuxProcessList_readOomData(lp, procFd);
}
diff --git a/linux/Platform.c b/linux/Platform.c
index 38b66e8..64f25c4 100644
--- a/linux/Platform.c
+++ b/linux/Platform.c
@@ -12,6 +12,7 @@ in the source distribution for its full text.
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <math.h>
@@ -21,6 +22,7 @@ in the source distribution for its full text.
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <sys/sysmacros.h>
#include "BatteryMeter.h"
#include "ClockMeter.h"
@@ -250,7 +252,7 @@ const MeterClass* const Platform_meterTypes[] = {
NULL
};
-int Platform_getUptime() {
+int Platform_getUptime(void) {
double uptime = 0;
FILE* fd = fopen(PROCDIR "/uptime", "r");
if (fd) {
@@ -285,7 +287,7 @@ err:
*fifteen = NAN;
}
-int Platform_getMaxPid() {
+int Platform_getMaxPid(void) {
FILE* file = fopen(PROCDIR "/sys/kernel/pid_max", "r");
if (!file)
return -1;
@@ -351,20 +353,20 @@ void Platform_setMemoryValues(Meter* this) {
const LinuxProcessList* lpl = (const LinuxProcessList*) pl;
this->total = pl->totalMem;
- this->values[0] = pl->usedMem;
- this->values[1] = pl->buffersMem;
- this->values[2] = pl->sharedMem;
- this->values[3] = pl->cachedMem;
- this->values[4] = pl->availableMem;
+ this->values[MEMORY_METER_USED] = pl->usedMem;
+ this->values[MEMORY_METER_BUFFERS] = pl->buffersMem;
+ this->values[MEMORY_METER_SHARED] = pl->sharedMem;
+ this->values[MEMORY_METER_CACHE] = pl->cachedMem;
+ this->values[MEMORY_METER_AVAILABLE] = pl->availableMem;
if (lpl->zfs.enabled != 0 && !Running_containerized) {
// ZFS does not shrink below the value of zfs_arc_min.
unsigned long long int shrinkableSize = 0;
if (lpl->zfs.size > lpl->zfs.min)
shrinkableSize = lpl->zfs.size - lpl->zfs.min;
- this->values[0] -= shrinkableSize;
- this->values[3] += shrinkableSize;
- this->values[4] += shrinkableSize;
+ this->values[MEMORY_METER_USED] -= shrinkableSize;
+ this->values[MEMORY_METER_CACHE] += shrinkableSize;
+ this->values[MEMORY_METER_AVAILABLE] += shrinkableSize;
}
}
@@ -430,117 +432,90 @@ char* Platform_getProcessEnv(pid_t pid) {
return env;
}
-/*
- * Return the absolute path of a file given its pid&inode number
- *
- * Based on implementation of lslocks from util-linux:
- * https://sources.debian.org/src/util-linux/2.36-3/misc-utils/lslocks.c/#L162
- */
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- struct stat sb;
- const struct dirent* de;
+FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
+ FileLocks_ProcessData* pdata = xCalloc(1, sizeof(FileLocks_ProcessData));
DIR* dirp;
- ssize_t len;
- int fd;
+ int dfd;
char path[PATH_MAX];
- char sym[PATH_MAX];
- char* ret = NULL;
-
- memset(path, 0, sizeof(path));
- memset(sym, 0, sizeof(sym));
-
- xSnprintf(path, sizeof(path), "%s/%d/fd/", PROCDIR, pid);
+ xSnprintf(path, sizeof(path), PROCDIR "/%d/fdinfo/", pid);
if (strlen(path) >= (sizeof(path) - 2))
- return NULL;
+ goto err;
if (!(dirp = opendir(path)))
- return NULL;
+ goto err;
- if ((fd = dirfd(dirp)) < 0 )
- goto out;
+ if ((dfd = dirfd(dirp)) == -1) {
+ closedir(dirp);
+ goto err;
+ }
- while ((de = readdir(dirp))) {
+ FileLocks_LockData** data_ref = &pdata->locks;
+ for (struct dirent* de; (de = readdir(dirp)); ) {
if (String_eq(de->d_name, ".") || String_eq(de->d_name, ".."))
continue;
- /* care only for numerical descriptors */
- if (!strtoull(de->d_name, (char **) NULL, 10))
+ errno = 0;
+ char *end = de->d_name;
+ int file = strtoull(de->d_name, &end, 10);
+ if (errno || *end)
continue;
- if (!Compat_fstatat(fd, path, de->d_name, &sb, 0) && inode != sb.st_ino)
+ int fd = openat(dfd, de->d_name, O_RDONLY | O_CLOEXEC);
+ if(fd == -1)
continue;
+ FILE *f = fdopen(fd, "r");
+ if(!f) {
+ close(fd);
+ continue;
+ }
- if ((len = Compat_readlinkat(fd, path, de->d_name, sym, sizeof(sym) - 1)) < 1)
- goto out;
-
- sym[len] = '\0';
-
- ret = xStrdup(sym);
- break;
- }
-
-out:
- closedir(dirp);
- return ret;
-}
+ for (char buffer[1024]; fgets(buffer, sizeof(buffer), f); ) {
+ if (!strchr(buffer, '\n'))
+ continue;
-FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
- FileLocks_ProcessData* pdata = xCalloc(1, sizeof(FileLocks_ProcessData));
+ if (strncmp(buffer, "lock:\t", strlen("lock:\t")))
+ continue;
- FILE* f = fopen(PROCDIR "/locks", "r");
- if (!f) {
- pdata->error = true;
- return pdata;
- }
+ FileLocks_Data data = {.fd = file};
+ int _;
+ unsigned int maj, min;
+ char lock_end[25], locktype[32], exclusive[32], readwrite[32];
+ if (10 != sscanf(buffer + strlen("lock:\t"), "%d: %31s %31s %31s %d %x:%x:%"PRIu64" %"PRIu64" %24s",
+ &_, locktype, exclusive, readwrite, &_,
+ &maj, &min, &data.inode,
+ &data.start, lock_end))
+ continue;
- char buffer[1024];
- FileLocks_LockData** data_ref = &pdata->locks;
- while(fgets(buffer, sizeof(buffer), f)) {
- if (!strchr(buffer, '\n'))
- continue;
+ data.locktype = xStrdup(locktype);
+ data.exclusive = xStrdup(exclusive);
+ data.readwrite = xStrdup(readwrite);
+ data.dev = makedev(maj, min);
- int lock_id;
- char lock_type[16];
- char lock_excl[16];
- char lock_rw[16];
- pid_t lock_pid;
- unsigned int lock_dev[2];
- uint64_t lock_inode;
- char lock_start[25];
- char lock_end[25];
-
- if (10 != sscanf(buffer, "%d: %15s %15s %15s %d %x:%x:%"PRIu64" %24s %24s",
- &lock_id, lock_type, lock_excl, lock_rw, &lock_pid,
- &lock_dev[0], &lock_dev[1], &lock_inode,
- lock_start, lock_end))
- continue;
+ if (String_eq(lock_end, "EOF"))
+ data.end = ULLONG_MAX;
+ else
+ data.end = strtoull(lock_end, NULL, 10);
- if (pid != lock_pid)
- continue;
+ xSnprintf(path, sizeof(path), PROCDIR "/%d/fd/%s", pid, de->d_name);
+ char link[PATH_MAX];
+ ssize_t link_len;
+ if (strlen(path) < (sizeof(path) - 2) && (link_len = readlink(path, link, sizeof(link))) != -1)
+ data.filename = xStrndup(link, link_len);
- FileLocks_LockData* ldata = xCalloc(1, sizeof(FileLocks_LockData));
- FileLocks_Data* data = &ldata->data;
- data->id = lock_id;
- data->locktype = xStrdup(lock_type);
- data->exclusive = xStrdup(lock_excl);
- data->readwrite = xStrdup(lock_rw);
- data->filename = Platform_getInodeFilename(lock_pid, lock_inode);
- data->dev[0] = lock_dev[0];
- data->dev[1] = lock_dev[1];
- data->inode = lock_inode;
- data->start = strtoull(lock_start, NULL, 10);
- if (!String_eq(lock_end, "EOF")) {
- data->end = strtoull(lock_end, NULL, 10);
- } else {
- data->end = ULLONG_MAX;
+ *data_ref = xCalloc(1, sizeof(FileLocks_LockData));
+ (*data_ref)->data = data;
+ data_ref = &(*data_ref)->next;
}
- *data_ref = ldata;
- data_ref = &ldata->next;
+ fclose(f);
}
- fclose(f);
+ closedir(dirp);
+ return pdata;
+
+err:
+ pdata->error = true;
return pdata;
}
diff --git a/linux/Platform.h b/linux/Platform.h
index e6fa161..f6ac188 100644
--- a/linux/Platform.h
+++ b/linux/Platform.h
@@ -75,8 +75,6 @@ void Platform_setZfsCompressedArcValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred);
@@ -114,7 +112,9 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
Generic_gettime_monotonic(msec);
}
-static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+static inline Hashtable* Platform_dynamicMeters(void) {
+ return NULL;
+}
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
@@ -124,12 +124,18 @@ static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) {
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
-static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+static inline Hashtable* Platform_dynamicColumns(void) {
+ return NULL;
+}
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
-static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) {
+ return NULL;
+}
-static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) {
+ return false;
+}
#endif
diff --git a/linux/SystemdMeter.c b/linux/SystemdMeter.c
index 53ae2d2..cee3231 100644
--- a/linux/SystemdMeter.c
+++ b/linux/SystemdMeter.c
@@ -310,8 +310,12 @@ static int valueDigitColor(unsigned int value) {
static void SystemdMeter_display(ATTR_UNUSED const Object* cast, RichString* out) {
char buffer[16];
int len;
+ int color = METER_VALUE_ERROR;
- int color = (systemState && String_eq(systemState, "running")) ? METER_VALUE_OK : METER_VALUE_ERROR;
+ if (systemState) {
+ color = String_eq(systemState, "running") ? METER_VALUE_OK :
+ String_eq(systemState, "degraded") ? METER_VALUE_ERROR : METER_VALUE_WARN;
+ }
RichString_writeAscii(out, CRT_colors[color], systemState ? systemState : "N/A");
RichString_appendAscii(out, CRT_colors[METER_TEXT], " (");
diff --git a/netbsd/Platform.c b/netbsd/Platform.c
index cf6079d..ad6050c 100644
--- a/netbsd/Platform.c
+++ b/netbsd/Platform.c
@@ -196,7 +196,7 @@ void Platform_setBindings(Htop_Action* keys) {
(void) keys;
}
-int Platform_getUptime() {
+int Platform_getUptime(void) {
struct timeval bootTime, currTime;
const int mib[2] = { CTL_KERN, KERN_BOOTTIME };
size_t size = sizeof(bootTime);
@@ -227,7 +227,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
*fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale;
}
-int Platform_getMaxPid() {
+int Platform_getMaxPid(void) {
// https://nxr.netbsd.org/xref/src/sys/sys/ansi.h#__pid_t
// pid is assigned as a 32bit Integer.
return INT32_MAX;
@@ -270,18 +270,18 @@ double Platform_setCPUValues(Meter* this, int cpu) {
void Platform_setMemoryValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalMem;
- this->values[0] = pl->usedMem;
- this->values[1] = pl->buffersMem;
- // this->values[2] = "shared memory, like tmpfs and shm"
- this->values[3] = pl->cachedMem;
- // this->values[4] = "available memory"
+ this->values[MEMORY_METER_USED] = pl->usedMem;
+ this->values[MEMORY_METER_BUFFERS] = pl->buffersMem;
+ // this->values[MEMORY_METER_SHARED] = "shared memory, like tmpfs and shm"
+ this->values[MEMORY_METER_CACHE] = pl->cachedMem;
+ // this->values[MEMORY_METER_AVAILABLE] = "available memory"
}
void Platform_setSwapValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalSwap;
- this->values[0] = pl->usedSwap;
- this->values[1] = NAN;
+ this->values[SWAP_METER_USED] = pl->usedSwap;
+ this->values[SWAP_METER_CACHE] = NAN;
}
char* Platform_getProcessEnv(pid_t pid) {
@@ -338,12 +338,6 @@ end:
return env;
}
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
-}
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
@@ -351,7 +345,7 @@ FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
bool Platform_getDiskIO(DiskIOData* data) {
const int mib[] = { CTL_HW, HW_IOSTATS, sizeof(struct io_sysctl) };
- struct io_sysctl *iostats = NULL;
+ struct io_sysctl* iostats = NULL;
size_t size = 0;
for (int retry = 3; retry > 0; retry--) {
diff --git a/netbsd/Platform.h b/netbsd/Platform.h
index 3ad51e2..0e53b45 100644
--- a/netbsd/Platform.h
+++ b/netbsd/Platform.h
@@ -65,8 +65,6 @@ void Platform_setSwapValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
bool Platform_getDiskIO(DiskIOData* data);
@@ -97,7 +95,9 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
Generic_gettime_monotonic(msec);
}
-static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+static inline Hashtable* Platform_dynamicMeters(void) {
+ return NULL;
+}
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
@@ -107,12 +107,18 @@ static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) {
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
-static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+static inline Hashtable* Platform_dynamicColumns(void) {
+ return NULL;
+}
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
-static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) {
+ return NULL;
+}
-static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) {
+ return false;
+}
#endif
diff --git a/openbsd/Platform.c b/openbsd/Platform.c
index b222bee..1ce5ba1 100644
--- a/openbsd/Platform.c
+++ b/openbsd/Platform.c
@@ -143,7 +143,7 @@ void Platform_setBindings(Htop_Action* keys) {
(void) keys;
}
-int Platform_getUptime() {
+int Platform_getUptime(void) {
struct timeval bootTime, currTime;
const int mib[2] = { CTL_KERN, KERN_BOOTTIME };
size_t size = sizeof(bootTime);
@@ -174,7 +174,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
*fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale;
}
-int Platform_getMaxPid() {
+int Platform_getMaxPid(void) {
return 2 * THREAD_PID_OFFSET;
}
@@ -227,18 +227,18 @@ void Platform_setMemoryValues(Meter* this) {
long int cachedMem = pl->cachedMem;
usedMem -= buffersMem + cachedMem;
this->total = pl->totalMem;
- this->values[0] = usedMem;
- this->values[1] = buffersMem;
- // this->values[2] = "shared memory, like tmpfs and shm"
- this->values[3] = cachedMem;
- // this->values[4] = "available memory"
+ this->values[MEMORY_METER_USED] = usedMem;
+ this->values[MEMORY_METER_BUFFERS] = buffersMem;
+ // this->values[MEMORY_METER_SHARED] = "shared memory, like tmpfs and shm"
+ this->values[MEMORY_METER_CACHE] = cachedMem;
+ // this->values[MEMORY_METER_AVAILABLE] = "available memory"
}
void Platform_setSwapValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalSwap;
- this->values[0] = pl->usedSwap;
- this->values[1] = NAN;
+ this->values[SWAP_METER_USED] = pl->usedSwap;
+ this->values[SWAP_METER_CACHE] = NAN;
}
char* Platform_getProcessEnv(pid_t pid) {
@@ -296,12 +296,6 @@ end:
return env;
}
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
-}
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
diff --git a/openbsd/Platform.h b/openbsd/Platform.h
index e3d6116..27d792e 100644
--- a/openbsd/Platform.h
+++ b/openbsd/Platform.h
@@ -57,8 +57,6 @@ void Platform_setSwapValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
bool Platform_getDiskIO(DiskIOData* data);
@@ -91,7 +89,9 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
Generic_gettime_monotonic(msec);
}
-static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+static inline Hashtable* Platform_dynamicMeters(void) {
+ return NULL;
+}
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
@@ -101,12 +101,18 @@ static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) {
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
-static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+static inline Hashtable* Platform_dynamicColumns(void) {
+ return NULL;
+}
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
-static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) {
+ return NULL;
+}
-static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) {
+ return false;
+}
#endif
diff --git a/pcp-htop.5.in b/pcp-htop.5.in
index 0f5cb14..dbc0dfb 100644
--- a/pcp-htop.5.in
+++ b/pcp-htop.5.in
@@ -1,4 +1,4 @@
-.TH "PCP-HTOP" "5" "2022" "@PACKAGE_STRING@" "File Formats"
+.TH "PCP-HTOP" "5" "2023" "@PACKAGE_STRING@" "File Formats"
.SH "NAME"
\f3pcp-htop\f1 \- pcp-htop configuration file
.SH "DESCRIPTION"
diff --git a/pcp/PCPDynamicColumn.c b/pcp/PCPDynamicColumn.c
index aab2525..33c6d72 100644
--- a/pcp/PCPDynamicColumn.c
+++ b/pcp/PCPDynamicColumn.c
@@ -14,6 +14,7 @@ in the source distribution for its full text.
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
+#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -194,6 +195,12 @@ void PCPDynamicColumns_init(PCPDynamicColumns* columns) {
const char* home = getenv("HOME");
char* path;
+ if (!xdgConfigHome && !home) {
+ const struct passwd* pw = getpwuid(getuid());
+ if (pw)
+ home = pw->pw_dir;
+ }
+
columns->table = Hashtable_new(0, true);
/* developer paths - PCP_HTOP_DIR=./pcp ./pcp-htop */
diff --git a/pcp/PCPDynamicMeter.c b/pcp/PCPDynamicMeter.c
index 7c55e4b..e899988 100644
--- a/pcp/PCPDynamicMeter.c
+++ b/pcp/PCPDynamicMeter.c
@@ -12,12 +12,14 @@ in the source distribution for its full text.
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
-#include <pcp/pmapi.h>
+#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <pcp/pmapi.h>
+
#include "Macros.h"
#include "Platform.h"
#include "RichString.h"
@@ -251,6 +253,12 @@ void PCPDynamicMeters_init(PCPDynamicMeters* meters) {
const char* home = getenv("HOME");
char* path;
+ if (!xdgConfigHome && !home) {
+ const struct passwd* pw = getpwuid(getuid());
+ if (pw)
+ home = pw->pw_dir;
+ }
+
meters->table = Hashtable_new(0, true);
/* developer paths - PCP_HTOP_DIR=./pcp ./pcp-htop */
diff --git a/pcp/PCPProcessList.c b/pcp/PCPProcessList.c
index 045f7ae..f893689 100644
--- a/pcp/PCPProcessList.c
+++ b/pcp/PCPProcessList.c
@@ -571,7 +571,7 @@ static void PCPProcessList_updateAllCPUTime(PCPProcessList* this, PCPMetric metr
{
pmAtomValue* value = &this->cpu[cpumetric];
if (PCPMetric_values(metric, value, 1, PM_TYPE_U64) == NULL)
- memset(&value, 0, sizeof(pmAtomValue));
+ memset(value, 0, sizeof(pmAtomValue));
}
static void PCPProcessList_updatePerCPUTime(PCPProcessList* this, PCPMetric metric, CPUMetric cpumetric)
diff --git a/pcp/Platform.c b/pcp/Platform.c
index 342bf43..994cef3 100644
--- a/pcp/Platform.c
+++ b/pcp/Platform.c
@@ -1,8 +1,8 @@
/*
htop - linux/Platform.c
(C) 2014 Hisham H. Muhammad
-(C) 2020-2021 htop dev team
-(C) 2020-2021 Red Hat, Inc.
+(C) 2020-2022 htop dev team
+(C) 2020-2022 Red Hat, Inc.
Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/
@@ -248,6 +248,37 @@ static const char* Platform_metricNames[] = {
[PCP_METRIC_COUNT] = NULL
};
+#ifndef HAVE_PMLOOKUPDESCS
+/*
+ * pmLookupDescs(3) exists in latest versions of libpcp (5.3.6+),
+ * but for older versions we provide an implementation here. This
+ * involves multiple round trips to pmcd though, which the latest
+ * libpcp version avoids by using a protocol extension. In time,
+ * perhaps in a few years, we could remove this back-compat code.
+ */
+int pmLookupDescs(int numpmid, pmID* pmids, pmDesc* descs) {
+ int count = 0;
+
+ for (int i = 0; i < numpmid; i++) {
+ /* expect some metrics to be missing - e.g. PMDA not available */
+ if (pmids[i] == PM_ID_NULL)
+ continue;
+
+ int sts = pmLookupDesc(pmids[i], &descs[i]);
+ if (sts < 0) {
+ if (pmDebugOptions.appl0)
+ fprintf(stderr, "Error: cannot lookup metric %s(%s): %s\n",
+ pcp->names[i], pmIDStr(pcp->pmids[i]), pmErrStr(sts));
+ pmids[i] = PM_ID_NULL;
+ continue;
+ }
+
+ count++;
+ }
+ return count;
+}
+#endif
+
size_t Platform_addMetric(PCPMetric id, const char* name) {
unsigned int i = (unsigned int)id;
@@ -325,21 +356,14 @@ bool Platform_init(void) {
return false;
}
- for (size_t i = 0; i < pcp->totalMetrics; i++) {
- pcp->fetch[i] = PM_ID_NULL; /* default is to not sample */
-
- /* expect some metrics to be missing - e.g. PMDA not available */
- if (pcp->pmids[i] == PM_ID_NULL)
- continue;
-
- sts = pmLookupDesc(pcp->pmids[i], &pcp->descs[i]);
- if (sts < 0) {
- if (pmDebugOptions.appl0)
- fprintf(stderr, "Error: cannot lookup metric %s(%s): %s\n",
- pcp->names[i], pmIDStr(pcp->pmids[i]), pmErrStr(sts));
- pcp->pmids[i] = PM_ID_NULL;
- continue;
- }
+ sts = pmLookupDescs(pcp->totalMetrics, pcp->pmids, pcp->descs);
+ if (sts < 1) {
+ if (sts < 0)
+ fprintf(stderr, "Error: cannot lookup descriptors: %s\n", pmErrStr(sts));
+ else /* ensure we have at least one valid metric to work with */
+ fprintf(stderr, "Error: cannot find a single valid metric, exiting\n");
+ Platform_done();
+ return false;
}
/* set proc.control.perclient.threads to 1 for live contexts */
@@ -504,28 +528,28 @@ void Platform_setMemoryValues(Meter* this) {
const PCPProcessList* ppl = (const PCPProcessList*) pl;
this->total = pl->totalMem;
- this->values[0] = pl->usedMem;
- this->values[1] = pl->buffersMem;
- this->values[2] = pl->sharedMem;
- this->values[3] = pl->cachedMem;
- this->values[4] = pl->availableMem;
+ this->values[MEMORY_METER_USED] = pl->usedMem;
+ this->values[MEMORY_METER_BUFFERS] = pl->buffersMem;
+ this->values[MEMORY_METER_SHARED] = pl->sharedMem;
+ this->values[MEMORY_METER_CACHE] = pl->cachedMem;
+ this->values[MEMORY_METER_AVAILABLE] = pl->availableMem;
if (ppl->zfs.enabled != 0) {
// ZFS does not shrink below the value of zfs_arc_min.
unsigned long long int shrinkableSize = 0;
if (ppl->zfs.size > ppl->zfs.min)
shrinkableSize = ppl->zfs.size - ppl->zfs.min;
- this->values[0] -= shrinkableSize;
- this->values[3] += shrinkableSize;
- this->values[4] += shrinkableSize;
+ this->values[MEMORY_METER_USED] -= shrinkableSize;
+ this->values[MEMORY_METER_CACHE] += shrinkableSize;
+ this->values[MEMORY_METER_AVAILABLE] += shrinkableSize;
}
}
void Platform_setSwapValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalSwap;
- this->values[0] = pl->usedSwap;
- this->values[1] = pl->cachedSwap;
+ this->values[SWAP_METER_USED] = pl->usedSwap;
+ this->values[SWAP_METER_CACHE] = pl->cachedSwap;
}
void Platform_setZramValues(Meter* this) {
@@ -645,12 +669,6 @@ char* Platform_getProcessEnv(pid_t pid) {
return value.cp;
}
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
-}
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
diff --git a/pcp/Platform.h b/pcp/Platform.h
index dc51c73..f06f226 100644
--- a/pcp/Platform.h
+++ b/pcp/Platform.h
@@ -98,8 +98,6 @@ void Platform_setZfsCompressedArcValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred);
diff --git a/solaris/Platform.c b/solaris/Platform.c
index 9c5acb5..96f3526 100644
--- a/solaris/Platform.c
+++ b/solaris/Platform.c
@@ -144,7 +144,7 @@ void Platform_setBindings(Htop_Action* keys) {
(void) keys;
}
-int Platform_getUptime() {
+int Platform_getUptime(void) {
int boot_time = 0;
int curr_time = time(NULL);
struct utmpx* ent;
@@ -173,7 +173,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
*fifteen = plat_loadavg[LOADAVG_15MIN];
}
-int Platform_getMaxPid() {
+int Platform_getMaxPid(void) {
int vproc = 32778; // Reasonable Solaris default
kstat_ctl_t* kc = kstat_open();
@@ -237,18 +237,18 @@ double Platform_setCPUValues(Meter* this, unsigned int cpu) {
void Platform_setMemoryValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalMem;
- this->values[0] = pl->usedMem;
- this->values[1] = pl->buffersMem;
- // this->values[2] = "shared memory, like tmpfs and shm"
- this->values[3] = pl->cachedMem;
- // this->values[4] = "available memory"
+ this->values[MEMORY_METER_USED] = pl->usedMem;
+ this->values[MEMORY_METER_BUFFERS] = pl->buffersMem;
+ // this->values[MEMORY_METER_SHARED] = "shared memory, like tmpfs and shm"
+ this->values[MEMORY_METER_CACHE] = pl->cachedMem;
+ // this->values[MEMORY_METER_AVAILABLE] = "available memory"
}
void Platform_setSwapValues(Meter* this) {
const ProcessList* pl = this->pl;
this->total = pl->totalSwap;
- this->values[0] = pl->usedSwap;
- this->values[1] = NAN;
+ this->values[SWAP_METER_USED] = pl->usedSwap;
+ this->values[SWAP_METER_CACHE] = NAN;
}
void Platform_setZfsArcValues(Meter* this) {
@@ -308,12 +308,6 @@ char* Platform_getProcessEnv(pid_t pid) {
return xRealloc(envBuilder.env, envBuilder.size + 1);
}
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
-}
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
diff --git a/solaris/Platform.h b/solaris/Platform.h
index 1b3dc9f..14431e3 100644
--- a/solaris/Platform.h
+++ b/solaris/Platform.h
@@ -86,8 +86,6 @@ void Platform_setZfsCompressedArcValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
bool Platform_getDiskIO(DiskIOData* data);
@@ -132,7 +130,9 @@ IGNORE_WCASTQUAL_BEGIN
IGNORE_WCASTQUAL_END
}
-static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+static inline Hashtable* Platform_dynamicMeters(void) {
+ return NULL;
+}
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
@@ -142,12 +142,18 @@ static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) {
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
-static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+static inline Hashtable* Platform_dynamicColumns(void) {
+ return NULL;
+}
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
-static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) {
+ return NULL;
+}
-static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) {
+ return false;
+}
#endif
diff --git a/unsupported/Platform.c b/unsupported/Platform.c
index 33d7c41..27bc560 100644
--- a/unsupported/Platform.c
+++ b/unsupported/Platform.c
@@ -90,7 +90,7 @@ void Platform_setBindings(Htop_Action* keys) {
(void) keys;
}
-int Platform_getUptime() {
+int Platform_getUptime(void) {
return 0;
}
@@ -100,7 +100,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
*fifteen = 0;
}
-int Platform_getMaxPid() {
+int Platform_getMaxPid(void) {
return 1;
}
@@ -129,12 +129,6 @@ char* Platform_getProcessEnv(pid_t pid) {
return NULL;
}
-char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
-}
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
diff --git a/unsupported/Platform.h b/unsupported/Platform.h
index 5c874d4..f475dda 100644
--- a/unsupported/Platform.h
+++ b/unsupported/Platform.h
@@ -50,8 +50,6 @@ void Platform_setSwapValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
-char* Platform_getInodeFilename(pid_t pid, ino_t inode);
-
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
bool Platform_getDiskIO(DiskIOData* data);
@@ -80,7 +78,9 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
Generic_gettime_monotonic(msec);
}
-static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+static inline Hashtable* Platform_dynamicMeters(void) {
+ return NULL;
+}
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
@@ -90,12 +90,18 @@ static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) {
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
-static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+static inline Hashtable* Platform_dynamicColumns(void) {
+ return NULL;
+}
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
-static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) {
+ return NULL;
+}
-static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) {
+ return false;
+}
#endif

© 2014-2024 Faster IT GmbH | imprint | privacy policy