Compare commits

...

140 commits
v1.3.0 ... main

Author SHA1 Message Date
Jakob P. Liljenberg 3d46dc6969
Merge pull request #838 from imwints/freebsd-static
Add missing linker flag for static links on FreeBSD
2024-05-13 23:05:12 +02:00
Steffen Winter b93206f038
Add missing linker flag for static links on FreeBSD
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=278551
2024-05-13 22:47:03 +02:00
Jakob P. Liljenberg ac62ba9de1
Merge pull request #840 from aristocratos/fix/zero_temp 2024-05-13 19:10:17 +02:00
Jakob P. Liljenberg 3f917c0412
Merge pull request #850 from acidghost/theme-comments 2024-05-13 19:08:45 +02:00
Andrea Jemmett 0127e8b3cd Fix comments in theme files 2024-05-12 16:09:09 +02:00
Jos Dehaes ebc86e9702 fix zero temp (#467) 2024-05-04 20:59:04 +02:00
aristocratos dd4ada7023 Fixed missing definition for ROCm static build 2024-05-01 20:43:46 +02:00
aristocratos b48bf6ae45 Add info text about regex filtering in help menu 2024-04-30 18:03:06 +02:00
Jakob P. Liljenberg 3b65b3a729
Merge pull request #806 from imwints/regex-search 2024-04-30 17:21:07 +02:00
Steffen 255b777563
Add regex filtering
Filters starting with '!' will try to match processes pid, name, cmd and
user with extended regex as defined by the C++ standard. A single '!'
will not filter.
2024-04-30 17:09:15 +02:00
Jakob P. Liljenberg 8c1a8ab4fa
Merge pull request #836 from vsey/Fix-Typo 2024-04-30 17:02:46 +02:00
Jakob P. Liljenberg f8cfa70dda
Merge branch 'main' into Fix-Typo 2024-04-30 17:02:16 +02:00
Jakob P. Liljenberg 3a6f816396
Merge pull request #835 from imwints/battery 2024-04-30 17:01:02 +02:00
vsey 14b388521d
Fix typo 2024-04-30 16:09:37 +02:00
Steffen Winter d200ce45ae
Show time in days when remaining battery exceeds an estimation of 24h 2024-04-30 15:32:41 +02:00
Jakob P. Liljenberg 924c3f3a72
Merge pull request #819 from kalkafox/rsmi-pwr-usage-fix
fix pwr_usage not being defined correctly during rsmi collection
2024-04-28 22:45:42 +02:00
Jakob P. Liljenberg 0e07debb7d
Merge pull request #831 from thecoder-001/main
macOS: fix crash if there exists a uid not associated with any user
2024-04-28 22:38:28 +02:00
Jakob P. Liljenberg b991e6898d
Merge pull request #832 from imwints/macos-ci
Fix brew not finding LLVM path after release of LLVM 18
2024-04-28 22:36:39 +02:00
Steffen Winter 5d7794019a
Fix brew not finding LLVM path after release of LLVM 18 2024-04-28 22:28:31 +02:00
thecoder-001 5ba45f7633
Remove logging for uid without username
Signed-off-by: thecoder-001 <ayush06feb@gmail.com>
2024-04-28 23:53:27 +05:30
thecoder-001 9a37395744
osx: show uid instead of 'unknown' if no user exists with the same
Signed-off-by: thecoder-001 <ayush06feb@gmail.com>
2024-04-28 02:53:50 +05:30
thecoder-001 08f90fb4f0
fix: crash on osx proc box
Signed-off-by: thecoder-001 <ayush06feb@gmail.com>
2024-04-28 02:41:20 +05:30
Kalka b06474136b fix pwr_usage not being defined correctly during rsmi collection 2024-04-11 22:50:58 -04:00
Jakob P. Liljenberg d1680735d9
Merge pull request #796 from davc0n/main 2024-03-23 01:42:17 +01:00
Jakob P. Liljenberg a535a6eb92
Merge pull request #797 from kz6fittycent/main 2024-03-23 01:37:59 +01:00
Jakob P. Liljenberg b1b8249d55
Merge pull request #807 from kk9uk/main 2024-03-23 01:35:52 +01:00
kk9uk 4a82105547 [FEATURE] Add gruvbox_light theme 2024-03-20 12:17:24 +08:00
kz6fittycent 8af8389bd0
Merge branch 'aristocratos:main' into main 2024-03-13 11:02:55 -05:00
kz6fittycent adaea59a2a
Update test-snap-can-build.yml 2024-03-13 10:50:29 -05:00
kz6fittycent 2aa2c90f41
Update snapcraft.yaml
core22 attempt
2024-03-13 10:49:38 -05:00
Davide Conti a60c969533 Fix rsmi device name buffer size
ref. issue #794
2024-03-13 10:12:28 +01:00
Jakob P. Liljenberg c767099d76
Merge pull request #724 from ottok/man-page 2024-03-04 18:03:27 +01:00
Otto Kekäläinen d8c054d92f Add 'lowdown' to build dependencies so GitHub actions actually runs it
Building the man page is optional and happens automatically if command
'lowdown' is present on the system. Add it to all possible GitHub CI files
so man page conversion will be tested and fully used.

Unfortunately 'lowdown' cannot be added to the musl jobs the program is
available only starting from Alpine v3.15, while the musl Docker images
run Alpine v3.14 (and haven't been updated in 2+ years).

Also, the Snap build used Ubuntu 20.04 "Focal" which equally is too old
to include Lowdown, which is available only from Ubuntu 22.04 "Jammy"
onward:
https://packages.ubuntu.com/search?suite=all&searchon=names&keywords=lowdown
2024-03-03 17:14:13 -08:00
Otto Kekäläinen ed68589af1 Create man page for btop in Markdown
Create a man page in Markdown format so that it can be read online on
GitHub etc and it can be edited much more easily than a raw troff/groff
file.

Compile it to proper man page format at build-time using 'lowdown' if
it is available on the system, otherwise just issue a warning in yellow.

Tested to work both with:

    export VERBOSE=1
    make
    make install
    make uninstall

    cmake -B build
    cmake --build build --verbose

While Lowdown is easy to manually install in all modern Linux distros
and also Homebrew for Mac, this commit does not add 'lowdown' in any
build dependencies or in the CI, that needs to be done separately.
2024-03-03 15:37:35 -08:00
Jakob P. Liljenberg c6fbfd1e27
Merge pull request #723 from ottok/fix-spelling 2024-03-01 07:58:12 +01:00
Otto Kekäläinen bfe8c20ebe Fix misc spelling 2024-02-29 22:11:39 -08:00
Jakob P. Liljenberg 6c66740290
Merge pull request #734 from imwints/build-info 2024-02-18 14:25:11 +01:00
Jakob P. Liljenberg 967ea1ab6f
Merge branch 'main' into build-info 2024-02-18 14:19:05 +01:00
Jakob P. Liljenberg cf609175fb
Merge pull request #763 from imwints/cmake-bump 2024-02-18 14:08:31 +01:00
Jakob P. Liljenberg e1575a1fca
Merge pull request #771 from Derppening/fix/linux-battery-wattage 2024-02-18 12:56:19 +01:00
David Mak e031cce6ba collect: Fix reading of battery power draw on Linux
This was erroneously set to read from the current battery charge.

Fixes #770.
2024-02-14 01:01:40 +08:00
Steffen Winter 83739f84e1
cmake: Remove version specifier 2024-02-12 23:56:43 +01:00
aristocratos fd2a2acdad v1.3.2 Hotfix GPU support AMD ROCm v6 2024-02-12 16:30:09 +01:00
Jakob P. Liljenberg 37d217eeb6
Merge pull request #762 from imwints/fix-rocm-github-link 2024-02-12 16:11:51 +01:00
Jakob P. Liljenberg f537715d8b
Merge branch 'main' into fix-rocm-github-link 2024-02-12 16:11:28 +01:00
Jakob P. Liljenberg 7a058e4f42
Merge pull request #761 from imwints/fix-rocm-5-6-supported 2024-02-12 16:09:50 +01:00
aristocratos bae006e94c Fixed variable names 2024-02-12 15:37:31 +01:00
aristocratos c625d512e1 Add check for possible librocm_smi64.so.6 and check for version 7 in the function logic 2024-02-12 15:31:43 +01:00
Steffen Winter 43af034317
fix: Can't detect librocm 6.0.x
librocm reports it's version as 7.0.0.0 in the 6.0.x release series.
2024-02-12 14:16:28 +01:00
Steffen Winter 5282acc149
fix: Change bad link to old rocm repository 2024-02-12 13:20:20 +01:00
aristocratos 9c34ac75dc v1.3.1 Bug fixes 2024-02-11 18:32:27 +01:00
Jakob P. Liljenberg 0f224bb0e2
Merge pull request #756 from imwints/unix-duplicates 2024-02-11 18:02:52 +01:00
Jakob P. Liljenberg 65f3ade9b6
Merge branch 'main' into unix-duplicates 2024-02-11 17:54:00 +01:00
Jakob P. Liljenberg e8137674b0
Merge pull request #755 from imwints/bsd 2024-02-11 17:53:39 +01:00
Jakob P. Liljenberg 1d62896c9b
Merge pull request #753 from lcheylus/utf8-ctype 2024-02-11 17:51:43 +01:00
Jakob P. Liljenberg 283ad3e76e
Merge branch 'main' into utf8-ctype 2024-02-11 17:49:35 +01:00
Jakob P. Liljenberg 97e78ebb12
Merge pull request #722 from MartinPit/hot-reload 2024-02-11 17:49:11 +01:00
aristocratos 1670e1db79 Reuse code from init, properly log warnings and move execution in to main loop 2024-02-11 17:42:51 +01:00
Jakob P. Liljenberg 67561d1994
Merge branch 'main' into hot-reload 2024-02-11 17:07:06 +01:00
Jakob P. Liljenberg 46f6b4fe90
Merge pull request #747 from aristocratos/fix/zombie 2024-02-11 17:06:23 +01:00
Jakob P. Liljenberg 459cbbeb52
Merge branch 'main' into fix/zombie 2024-02-11 16:49:49 +01:00
Jakob P. Liljenberg d460fc63dc
Merge pull request #746 from M-Sviridov/main 2024-02-11 16:49:25 +01:00
Jakob P. Liljenberg c587c9f1e3
Merge pull request #743 from planet36/config-trailing-newline 2024-02-11 16:46:44 +01:00
Jakob P. Liljenberg c7fdd8adfe
Merge branch 'main' into config-trailing-newline 2024-02-11 16:45:56 +01:00
Jakob P. Liljenberg 77c758c349
Merge pull request #689 from vsey/battery-power-2 2024-02-11 16:45:40 +01:00
Jakob P. Liljenberg f1f37ad6af
Merge branch 'main' into battery-power-2 2024-02-11 16:39:59 +01:00
Jakob P. Liljenberg 338aa72f6f
Merge pull request #735 from rkmcode/main 2024-02-11 16:33:46 +01:00
Jakob P. Liljenberg 842b9f83b2
Merge branch 'main' into main 2024-02-11 16:33:01 +01:00
Jakob P. Liljenberg cae6c86ecd
Merge pull request #720 from imwints/fmt-header-only 2024-02-11 16:21:17 +01:00
Jakob P. Liljenberg 7f5b060b0c
Merge branch 'main' into fmt-header-only 2024-02-11 16:11:52 +01:00
Jakob P. Liljenberg bf5618536b
Merge pull request #721 from imwints/debug 2024-02-11 16:11:32 +01:00
Jakob P. Liljenberg e0884917e6
Merge branch 'main' into debug 2024-02-11 16:11:05 +01:00
Jakob P. Liljenberg 1584ce6468
Merge pull request #717 from imwints/fix-716 2024-02-11 16:10:25 +01:00
Jakob P. Liljenberg 7057d7653d
Merge branch 'main' into fix-716 2024-02-11 15:58:38 +01:00
Jakob P. Liljenberg 91e137a411
Merge pull request #718 from imwints/cmake-openbsd 2024-02-11 15:58:08 +01:00
Jakob P. Liljenberg bb8c7bc35c
Merge branch 'main' into cmake-openbsd 2024-02-11 15:53:44 +01:00
Jakob P. Liljenberg 70dec20b23
Merge pull request #714 from tessus/fix/if-name-len 2024-02-11 15:51:49 +01:00
Jakob P. Liljenberg 8bf88c1918
Merge branch 'main' into fix/if-name-len 2024-02-11 15:50:14 +01:00
Steffen Winter ab0bef204a
collect: Share ifaddrs wrapper and use uniq_ptr-like syntax 2024-02-09 14:03:06 +01:00
Steffen Winter ee46dba838
bsd: Wrap kvm_t* in a uniq_ptr and share code between BSD's 2024-02-09 13:16:09 +01:00
Steffen Winter a0e2a5c1d2
cmake: Fix undefined reference to `kvm_openfiles' on BSD's 2024-02-09 12:06:16 +01:00
Laurent Cheylus f2ead3d3a9
Check LC_CTYPE to set UTF-8 locale
Fix aristocratos/btop#752

Signed-off-by: Laurent Cheylus <foxy@free.fr>
2024-02-08 14:35:21 +01:00
MartinPit 57703d3087
Merge branch 'main' into hot-reload 2024-02-05 16:08:57 +01:00
Jos Dehaes 2b09f29a1e fix: don't mangle memory for zombie processes
for a zombie process, `proc_pidpath` returns 0, and nothing is written in fullname, so it's uninitialized garbage
2024-02-02 09:28:07 +01:00
Mathieu Sviridov bc0eb4291f Add theme based on Everforest Dark Medium palette 2024-02-02 12:49:30 +11:00
Steven Ward 69363487bc Write newline at end of config file 2024-01-30 20:12:58 -05:00
vsey 0bb1d4bf97
Merge branch 'main' into battery-power-2 2024-01-30 22:05:00 +01:00
Jakob P. Liljenberg edcb68cbb9
Merge pull request #737 from fxzjshm/fix-rocm-v6
Fix dynamic loading of ROCm v6
2024-01-27 09:00:31 +01:00
fxzjshm 7d3617a274
Fix dynamic loading of ROCm v6
Corrected definition of `rsmi_frequencies_t` of ROCm v5 and v6.
Also added the missing `LOAD_SYM(rsmi_version_get);` as it is used later.

Fixes: 5511131 ("Support for dynamic loading of ROCm v6")
Signed-off-by: fxzjshm <fxzjshm@163.com>
2024-01-27 15:31:02 +08:00
aristocratos 4461a431ae Fixed incorrect used and available memory for OSX 2024-01-26 23:29:31 +01:00
aristocratos eab6c58137 Fix dependencies for Continuous Build Gpu 2024-01-26 22:48:04 +01:00
aristocratos 8019e117c7 Added continuous build for testing Gpu support 2024-01-26 22:45:11 +01:00
aristocratos 5511131572 Support for dynamic loading of ROCm v6 2024-01-26 22:11:23 +01:00
rliang 81d09860f7
Fix basic_string::_M_create exception
when 1000>hz>999.5, round(hz)=1000
btop_draw.cpp: 793: Symbols::h_line * (7 - cpuHz.size())  exception
2024-01-25 03:36:15 +08:00
Steffen Winter bdc8d0151d Ask for 'btop --version' in issue template 2024-01-24 15:02:14 +01:00
Steffen Winter 7717020197
Include build info in binary 2024-01-24 15:02:11 +01:00
jkre c750543950 Fix missing value in battery status tuple for openbsd 2024-01-22 22:32:16 +01:00
jkre 61105e46b7 Add battery power draw to battery inforamtion tuple for openbsd and set it to a constant 2024-01-22 22:20:33 +01:00
vsey 40cdb92b8e
Merge branch 'aristocratos:main' into battery-power-2 2024-01-22 22:01:14 +01:00
Martin Oliver Pitoňák fb994b69eb
added ctrl+r shortcut to reload config from disk 2024-01-17 17:27:18 +01:00
Martin Oliver Pitoňák e047f88bd5
SIGUSR2 signal now reloads the config 2024-01-17 16:41:58 +01:00
Steffen Winter 3174c83b43
-DFMT_HEADER_ONLY as a compiler flag
This just defines FMT_HEADER_ONLY everywhere instead of just in all
files that include `btop_tools.hpp`, in case the statement gets removed
there.
2024-01-17 09:56:18 +01:00
Martin Oliver Pitoňák 67a674e850
btop now reacts to SIGUSR1 by reloading config 2024-01-16 19:02:20 +01:00
Steffen Winter a44ce1c3a1
Make BTOP_DEBUG also work for CMake 2024-01-15 19:23:47 +01:00
Steffen Winter 57752df6fc
CMake: Enable OpenBSD 2024-01-15 16:07:24 +01:00
Steffen Winter cec251bf05
Allow the Findkvm module on all BSDs 2024-01-15 16:00:34 +01:00
Steffen Winter 05da55c549
Fix abort in locale detection on OpenBSD
For whatever reason catch doesn't work for exceptions thrown in
a dynamically linked library and the program aborts.
2024-01-15 15:55:04 +01:00
Helmut K. C. Tessarek 6a6f514f80 fix: increase interface name length to 15 2024-01-12 11:28:42 -05:00
Jakob P. Liljenberg b2df50396b
Update README.md -> Fixed bad links 2024-01-11 19:27:29 +01:00
aristocratos e936339038 Undefine FORTIFY_SOURCE before setting new value when enabled 2024-01-11 10:39:39 +01:00
Jakob P. Liljenberg c649369efb
Merge pull request #648 from imwints/fortification
Increase fortification level
2024-01-11 09:42:59 +01:00
Jakob P. Liljenberg 21fe2cc07b
Merge branch 'main' into fortification 2024-01-11 09:42:09 +01:00
Jakob P. Liljenberg d063cd300e
Merge pull request #711 from v4u6h4n/patch-1
Update README.md
2024-01-11 09:36:47 +01:00
aristocratos ca368c5b89 Added link to compile section 2024-01-11 09:35:20 +01:00
v4u6h4n 3cbb0484a4
Update README.md
Added optional dependencies to 'Prerequisites' section.
2024-01-11 12:19:09 +11:00
Jakob P. Liljenberg 60bd10d44c
Merge pull request #706 from imwints/cmake
Bump cmake to v1.3.0
2024-01-09 08:12:51 +01:00
Steffen Winter 19c6099c7c
Use _FORTIFY_SOURCE=3 and put it behind a build flag 2024-01-08 13:19:16 +01:00
Steffen Winter 4ab43fd159
Bump cmake to v1.3.0 2024-01-07 18:59:21 +01:00
vsey b28c5ffc40
Merge branch 'main' into battery-power-2 2024-01-03 20:52:30 +01:00
vsey fb6af5ddb4
Merge branch 'aristocratos:main' into battery-power-2 2023-12-29 01:14:34 +01:00
vsey 63ce0abc64
Merge branch 'aristocratos:main' into battery-power-2 2023-12-26 23:43:14 +01:00
vsey 9dd43796fd
Merge branch 'main' into battery-power-2 2023-12-25 12:32:01 +01:00
vsey 5792216eb9
Merge branch 'aristocratos:main' into battery-power-2 2023-12-17 21:19:39 +01:00
vsey 46743abab8
Merge branch 'main' into battery-power-2 2023-12-17 15:36:27 +01:00
jkre 0c706cd20a make os compatible 2023-12-15 01:28:57 +01:00
jkre a81b514d6d add freebsd support for battery power 2023-12-15 01:14:47 +01:00
jkre cd6c1b7294 make discribtion in menu and settings clearer 2023-12-14 23:27:19 +01:00
jkre 2934138a66 Only redraw battery indicator on power change if power change option is set to true 2023-12-14 22:56:31 +01:00
jkre 578b01e06b add show_battery_power option to menu 2023-12-14 22:19:22 +01:00
jkre 7a188bfaaf round wattage to second decimal 2023-12-14 01:39:00 +01:00
jkre 1ad1418771 remove redundant space 2023-12-14 00:58:17 +01:00
jkre ddd4bec1c3 Show wattage next to battery remaining time when wattage could be calculated 2023-12-14 00:54:29 +01:00
jkre 6e575116fe add power to get_battery function output 2023-12-14 00:53:01 +01:00
jkre 419a7d4ca3 add power draw calculation for battery 2023-12-14 00:32:06 +01:00
jkre b09f352c09 clean up if statement for battery percent calculation 2023-12-14 00:16:15 +01:00
jkre f6d8c4a044 use capacity as default for battery percentage, less complicated and matches desktop percent exactly 2023-12-13 23:58:40 +01:00
jkre ab294bfc10 add battery percentage calculation in charge case 2023-12-13 23:51:18 +01:00
jkre ee61700a44 add case of calculating the remaining battery time for current/charge 2023-12-13 23:39:45 +01:00
jkre b99008f626 Introduce charge in addition to energy for laptops that use charge instead of energy, this is done so that the units make more sense in this case 2023-12-13 23:17:07 +01:00
jkre 4c74a7c51d Add current_now and voltage_now to battery struct and fix naming of
current_now
2023-12-13 22:51:40 +01:00
56 changed files with 1004 additions and 327 deletions

View file

@ -28,10 +28,9 @@ Any bug that can be solved by just reading the [prerequisites](https://github.co
[If applicable, add screenshots to help explain your problem.] [If applicable, add screenshots to help explain your problem.]
**Info (please complete the following information):** **Info (please complete the following information):**
- btop++ version: `btop -v` - btop++ version: `btop --version`
- If using snap: `snap info btop` - If using snap: `snap info btop`
- Binary: [self compiled or static binary from release] - Binary: [self compiled or static binary from release]
- (If compiled) Compiler and version:
- Architecture: [x86_64, aarch64, etc.] `uname -m` - Architecture: [x86_64, aarch64, etc.] `uname -m`
- Platform: [Linux, FreeBSD, OsX] - Platform: [Linux, FreeBSD, OsX]
- (Linux) Kernel: `uname -r` - (Linux) Kernel: `uname -r`

View file

@ -33,8 +33,7 @@ jobs:
with: with:
release: '14.0' release: '14.0'
usesh: true usesh: true
prepare: pkg install -y cmake ninja prepare: pkg install -y cmake ninja lowdown
run: | run: |
CXX=clang++ cmake -B build -G Ninja -DBTOP_STATIC=ON CXX=clang++ cmake -B build -G Ninja -DBTOP_STATIC=ON
cmake --build build --verbose cmake --build build --verbose

View file

@ -30,11 +30,10 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install build tools - name: Install build tools
run: apk add --no-cache --update clang cmake lld ninja run: apk add --no-cache --update clang cmake lld ninja lowdown
- name: Configure - name: Configure
run: CXX=clang++ LDFLAGS=-fuse-ld=lld cmake -B build -G Ninja -DBTOP_STATIC=ON run: CXX=clang++ LDFLAGS=-fuse-ld=lld cmake -B build -G Ninja -DBTOP_STATIC=ON
- name: Compile - name: Compile
run: cmake --build build --verbose run: cmake --build build --verbose

View file

@ -32,7 +32,7 @@ jobs:
run: | run: |
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
brew update --quiet brew update --quiet
brew install --force --overwrite cmake llvm@17 ninja brew install --force --overwrite cmake llvm ninja lowdown
- name: Configure - name: Configure
run: | run: |
@ -44,4 +44,3 @@ jobs:
- name: Compile - name: Compile
run: cmake --build build --verbose run: cmake --build build --verbose

View file

@ -45,7 +45,7 @@ jobs:
release: '14.0' release: '14.0'
usesh: true usesh: true
prepare: | prepare: |
pkg install -y gmake gcc coreutils git pkg install -y gmake gcc coreutils git lowdown
git config --global --add safe.directory /home/runner/work/btop/btop git config --global --add safe.directory /home/runner/work/btop/btop
run: | run: |
CXX=${{ matrix.compiler }} gmake STATIC=true STRIP=true CXX=${{ matrix.compiler }} gmake STATIC=true STRIP=true
@ -59,4 +59,3 @@ jobs:
name: btop-x86_64-freebsd-14 name: btop-x86_64-freebsd-14
path: 'bin/*' path: 'bin/*'
if-no-files-found: error if-no-files-found: error

View file

@ -0,0 +1,45 @@
name: Continuous Build Gpu
on:
workflow_dispatch:
push:
branches:
- main
tags-ignore:
- '*.*'
paths:
- 'src/**'
- '!src/osx/**'
- '!src/freebsd/**'
- '!src/openbsd/**'
- 'include/**'
- 'Makefile'
- '.github/workflows/continuous-build-gpu.yml'
pull_request:
branches:
- main
paths:
- 'src/**'
- '!src/osx/**'
- '!src/freebsd/**'
- '!src/openbsd/**'
- 'include/**'
- 'Makefile'
- '.github/workflows/continuous-build-gpu.yml'
jobs:
gpu_build_linux:
runs-on: ubuntu-latest
container: alpine:edge
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
- name: Install build tools
run: apk add --no-cache --update gcc g++ make
- name: Compile
run: make CXX=g++ GPU_SUPPORT=true

View file

@ -42,7 +42,7 @@ jobs:
release: '7.4' release: '7.4'
usesh: true usesh: true
prepare: | prepare: |
pkg_add gmake gcc%11 g++%11 coreutils git pkg_add gmake gcc%11 g++%11 coreutils git lowdown
git config --global --add safe.directory /home/runner/work/btop/btop git config --global --add safe.directory /home/runner/work/btop/btop
run: | run: |
gmake CXX=eg++ STATIC=true STRIP=true gmake CXX=eg++ STATIC=true STRIP=true
@ -55,4 +55,3 @@ jobs:
name: btop-x86_64-openbsd-7.4 name: btop-x86_64-openbsd-7.4
path: 'bin/*' path: 'bin/*'
if-no-files-found: error if-no-files-found: error

View file

@ -1,5 +1,4 @@
name: 🧪 Test snap can be built on x86_64 name: 🧪 Test snap can be built on x86_64
on: on:
workflow_dispatch: workflow_dispatch:
push: push:
@ -28,7 +27,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node-version: [16.x] node-version: [20.x]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2

5
.gitignore vendored
View file

@ -46,9 +46,14 @@ stage/
*.out *.out
*.app *.app
# Compiled man page
btop.1
build build
bin bin
btop btop
/obj/
config.h
.*/ .*/
# Optional libraries # Optional libraries

View file

@ -1,3 +1,25 @@
## v1.3.2
Description | Author(s) | References
--- | --- | ---
fix: Can't detect librocm 6.0.x | @imwints, @aristocratos | #761
## v1.3.1
Description | Author(s) | References
--- | --- | ---
GPU: Added support for dynamic loading of ROCm v6 libraries | @aristocratos, @fxzjshm | 5511131, #737
Increase max network interface name to 15 | @tessus | #714
Fix OpenBSD UTF-8 locale detection | @lcheylus, @imwints | #753, #717
Add hot-reloading of config file with CTRL+R or SIGUSR2 signal | @MartinPit | #722
Add battery power draw for linux and freebsd | @vsey | #689
Fix crash caused by string exception when cpu clock is exactly between 999.5 and 999.9 Mhz | @rkmcode | #735
Write newline at end of config file | @planet36 | #743
Add theme based on Everforest Dark Medium palette | @M-Sviridov | #746
fix: don't mangle memory for zombie processes | @joske | #747
Share common code from collect | @imwints | #756
Fixed incorrect used and available memory for OSX | | 4461a43
## v1.3.0 ## v1.3.0
* Added Gpu Support Linux | @romner-set | PR #529 * Added Gpu Support Linux | @romner-set | PR #529
@ -158,7 +180,7 @@
* Fixed: Wrong memory unit when shorten and size is less than 10, by @mohi001 * Fixed: Wrong memory unit when shorten and size is less than 10, by @mohi001
* Fixed: Use cpu cores avarage temp if missing cpu package temp for FreeBSD * Fixed: Use cpu cores average temp if missing cpu package temp for FreeBSD
* Changed: Enter symbol to a more common variant * Changed: Enter symbol to a more common variant
@ -454,7 +476,7 @@
* Fixed: Sizing constraints bug on start and boxes can be toggled from size error screen * Fixed: Sizing constraints bug on start and boxes can be toggled from size error screen
* Fixed: UTF-8 check crashing if LANG was set to non existant locale * Fixed: UTF-8 check crashing if LANG was set to non existent locale
## v1.0.4 ## v1.0.4

View file

@ -11,7 +11,6 @@ if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
endif() endif()
project("btop" project("btop"
VERSION 1.2.13
DESCRIPTION "A monitor of resources" DESCRIPTION "A monitor of resources"
HOMEPAGE_URL "https://github.com/aristocratos/btop" HOMEPAGE_URL "https://github.com/aristocratos/btop"
LANGUAGES CXX LANGUAGES CXX
@ -41,6 +40,7 @@ option(BTOP_LTO "Enable LTO" ON)
option(BTOP_USE_MOLD "Use mold to link btop" OFF) option(BTOP_USE_MOLD "Use mold to link btop" OFF)
option(BTOP_PEDANTIC "Enable a bunch of additional warnings" OFF) option(BTOP_PEDANTIC "Enable a bunch of additional warnings" OFF)
option(BTOP_WERROR "Compile with warnings as errors" OFF) option(BTOP_WERROR "Compile with warnings as errors" OFF)
option(BTOP_FORTIFY "Detect buffer overflows with _FORTIFY_SOURCE=3" ON)
option(BTOP_GPU "Enable GPU support" ON) option(BTOP_GPU "Enable GPU support" ON)
cmake_dependent_option(BTOP_RSMI_STATIC "Link statically to ROCm SMI" OFF "BTOP_GPU" OFF) cmake_dependent_option(BTOP_RSMI_STATIC "Link statically to ROCm SMI" OFF "BTOP_GPU" OFF)
@ -64,6 +64,8 @@ if(APPLE)
target_sources(btop PRIVATE src/osx/btop_collect.cpp src/osx/sensors.cpp src/osx/smc.cpp) target_sources(btop PRIVATE src/osx/btop_collect.cpp src/osx/sensors.cpp src/osx/smc.cpp)
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
target_sources(btop PRIVATE src/freebsd/btop_collect.cpp) target_sources(btop PRIVATE src/freebsd/btop_collect.cpp)
elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
target_sources(btop PRIVATE src/openbsd/btop_collect.cpp src/openbsd/sysctlbyname.cpp)
elseif(LINUX) elseif(LINUX)
target_sources(btop PRIVATE src/linux/btop_collect.cpp) target_sources(btop PRIVATE src/linux/btop_collect.cpp)
else() else()
@ -75,6 +77,21 @@ if(NOT CXX_HAVE_RANGES)
message(FATAL_ERROR "The compiler doesn't support <ranges>") message(FATAL_ERROR "The compiler doesn't support <ranges>")
endif() endif()
# Generate build info
execute_process(
COMMAND "git" "rev-parse" "--short" "HEAD"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
set(CONFIGURE_COMMAND
"cmake -DBTOP_STATIC=${BTOP_STATIC} -DBTOP_USE_MOLD=${BTOP_USE_MOLD} -DBTOP_FORTIFY=${BTOP_FORTIFY} -DBTOP_GPU=${BTOP_GPU}"
)
get_filename_component(CXX_COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME)
set(COMPILER "${CXX_COMPILER_BASENAME}")
set(COMPILER_VERSION "${CMAKE_CXX_COMPILER_VERSION}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY IMMEDIATE)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Check for and enable LTO # Check for and enable LTO
check_ipo_supported(RESULT ipo_supported) check_ipo_supported(RESULT ipo_supported)
if(ipo_supported AND BTOP_LTO) if(ipo_supported AND BTOP_LTO)
@ -97,7 +114,7 @@ if(BTOP_WERROR)
endif() endif()
if(NOT APPLE) if(NOT APPLE)
target_compile_options(btop PRIVATE -fstack-clash-protection) target_compile_options(btop PRIVATE -fstack-clash-protection)
endif() endif()
check_cxx_compiler_flag(-fstack-protector HAS_FSTACK_PROTECTOR) check_cxx_compiler_flag(-fstack-protector HAS_FSTACK_PROTECTOR)
if(HAS_FSTACK_PROTECTOR) if(HAS_FSTACK_PROTECTOR)
@ -109,10 +126,11 @@ if(HAS_FCF_PROTECTION)
endif() endif()
target_compile_definitions(btop PRIVATE target_compile_definitions(btop PRIVATE
FMT_HEADER_ONLY
_FILE_OFFSET_BITS=64 _FILE_OFFSET_BITS=64
$<$<CONFIG:Debug>:_GLIBCXX_ASSERTIONS _LIBCPP_ENABLE_ASSERTIONS=1> $<$<CONFIG:Debug>:_GLIBCXX_ASSERTIONS _LIBCPP_ENABLE_ASSERTIONS=1>
# Only has an effect with optimizations enabled # Only has an effect with optimizations enabled
$<$<NOT:$<CONFIG:Debug>>:_FORTIFY_SOURCE=2> $<$<AND:$<NOT:$<CONFIG:Debug>>,$<BOOL:${BTOP_FORTIFY}>>:_FORTIFY_SOURCE=3>
) )
target_include_directories(btop SYSTEM PRIVATE include) target_include_directories(btop SYSTEM PRIVATE include)
@ -129,7 +147,7 @@ if(LINUX AND BTOP_GPU)
if(BTOP_RSMI_STATIC) if(BTOP_RSMI_STATIC)
# ROCm doesn't properly add it's folders to the module path if `CMAKE_MODULE_PATH` is already # ROCm doesn't properly add it's folders to the module path if `CMAKE_MODULE_PATH` is already
# set # set
# We could also manully append ROCm's path here # We could also manually append ROCm's path here
set(_CMAKE_MODULE_PATH CMAKE_MODULE_PATH) set(_CMAKE_MODULE_PATH CMAKE_MODULE_PATH)
unset(CMAKE_MODULE_PATH) unset(CMAKE_MODULE_PATH)
@ -175,15 +193,43 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
INSTALL_RPATH "/usr/local/lib/gcc${GCC_VERSION_MAJOR}" INSTALL_RPATH "/usr/local/lib/gcc${GCC_VERSION_MAJOR}"
BUILD_WITH_INSTALL_RPATH TRUE BUILD_WITH_INSTALL_RPATH TRUE
) )
# The gcc compiler wrapper doesn't add '--eh-frame-hdr' on FreeBSD with static builds
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=278551
if(BTOP_STATIC)
target_link_options(btop PRIVATE LINKER:--eh-frame-hdr)
endif()
endif() endif()
find_package(devstat REQUIRED) find_package(devstat REQUIRED)
target_link_libraries(btop devstat::devstat) find_package(kvm REQUIRED)
target_link_libraries(btop devstat::devstat kvm::kvm)
if(BTOP_STATIC) if(BTOP_STATIC)
find_package(elf REQUIRED) find_package(elf REQUIRED)
find_package(kvm REQUIRED) target_link_libraries(btop elf::elf)
target_link_libraries(btop elf::elf kvm::kvm)
endif() endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(btop PRIVATE -static-libstdc++)
endif()
find_package(kvm REQUIRED)
target_link_libraries(btop kvm::kvm)
endif()
# Check if lowdown is installed
find_program(LOWDOWN_EXECUTABLE lowdown)
if(LOWDOWN_EXECUTABLE)
# Custom target to compile Markdown to man page using lowdown
add_custom_target(btop.1 ALL
COMMAND lowdown -s -Tman -o btop.1 manpage.md
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
# Install the man page
install(FILES btop.1 DESTINATION "share/man/man1")
else()
message(WARNING "Command 'lowdown' not found: skipping generating man page btop.1")
endif() endif()
install(TARGETS btop RUNTIME) install(TARGETS btop RUNTIME)
@ -191,4 +237,3 @@ install(FILES "btop.desktop" DESTINATION "share/applications")
install(FILES "Img/icon.png" DESTINATION "share/icons/hicolor/48x48/apps" RENAME "btop.png") install(FILES "Img/icon.png" DESTINATION "share/icons/hicolor/48x48/apps" RENAME "btop.png")
install(FILES "Img/icon.svg" DESTINATION "share/icons/hicolor/scalable/apps" RENAME "btop.svg") install(FILES "Img/icon.svg" DESTINATION "share/icons/hicolor/scalable/apps" RENAME "btop.svg")
install(DIRECTORY "themes" DESTINATION "share/btop") install(DIRECTORY "themes" DESTINATION "share/btop")

View file

@ -50,6 +50,11 @@ ifeq ($(GPU_SUPPORT),true)
override ADDFLAGS += -DGPU_SUPPORT override ADDFLAGS += -DGPU_SUPPORT
endif endif
FORTIFY_SOURCE ?= true
ifeq ($(FORTIFY_SOURCE),true)
override ADDFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3
endif
#? Compiler and Linker #? Compiler and Linker
ifeq ($(shell $(CXX) --version | grep clang >/dev/null 2>&1; echo $$?),0) ifeq ($(shell $(CXX) --version | grep clang >/dev/null 2>&1; echo $$?),0)
override CXX_IS_CLANG := true override CXX_IS_CLANG := true
@ -92,17 +97,18 @@ ifneq ($(PLATFORM) $(ARCH),macos arm64)
endif endif
ifeq ($(STATIC),true) ifeq ($(STATIC),true)
ifeq ($(CXX_IS_CLANG) $(CLANG_WORKS),true true) ifeq ($(CXX_IS_CLANG),true)
ifeq ($(shell $(CXX) -print-target-triple | grep gnu >/dev/null; echo $$?),0) ifeq ($(shell $(CXX) -print-target-triple | grep gnu >/dev/null; echo $$?),0)
$(error $(shell printf "\033[1;91mERROR: \033[97m$(CXX) can't statically link glibc\033[0m")) $(error $(shell printf "\033[1;91mERROR: \033[97m$(CXX) can't statically link glibc\033[0m"))
endif endif
else
override ADDFLAGS += -static-libgcc -static-libstdc++
endif endif
ifeq ($(PLATFORM_LC),linux)
override ADDFLAGS += -DSTATIC_BUILD -static -Wl,--fatal-warnings ifeq ($(PLATFORM_LC),$(filter $(PLATFORM_LC),freebsd linux))
else ifeq ($(PLATFORM_LC),freebsd) override ADDFLAGS += -DSTATIC_BUILD -static
override ADDFLAGS += -DSTATIC_BUILD else
ifeq ($(CXX_IS_CLANG),false)
override ADDFLAGS += -static-libgcc -static-libstdc++
endif
endif endif
endif endif
@ -125,9 +131,13 @@ else ifeq ($(PLATFORM_LC),freebsd)
PLATFORM_DIR := freebsd PLATFORM_DIR := freebsd
THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1) THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1)
SU_GROUP := wheel SU_GROUP := wheel
override ADDFLAGS += -lm -lkvm -ldevstat -Wl,-rpath=/usr/local/lib/gcc$(CXX_VERSION_MAJOR) override ADDFLAGS += -lm -lkvm -ldevstat
ifneq ($(STATIC),true) ifeq ($(STATIC),true)
override ADDFLAGS += -lstdc++ override ADDFLAGS += -lelf -Wl,--eh-frame-hdr
endif
ifeq ($(CXX_IS_CLANG),false)
override ADDFLAGS += -lstdc++ -Wl,rpath=/usr/local/lib/gcc$(CXX_VERSION_MAJOR)
endif endif
export MAKE = gmake export MAKE = gmake
else ifeq ($(PLATFORM_LC),macos) else ifeq ($(PLATFORM_LC),macos)
@ -138,7 +148,7 @@ else ifeq ($(PLATFORM_LC),macos)
else ifeq ($(PLATFORM_LC),openbsd) else ifeq ($(PLATFORM_LC),openbsd)
PLATFORM_DIR := openbsd PLATFORM_DIR := openbsd
THREADS := $(shell sysctl -n hw.ncpu || echo 1) THREADS := $(shell sysctl -n hw.ncpu || echo 1)
override ADDFLAGS += -lkvm override ADDFLAGS += -lkvm -static-libstdc++
export MAKE = gmake export MAKE = gmake
SU_GROUP := wheel SU_GROUP := wheel
else else
@ -158,6 +168,12 @@ else
LTO := $(THREADS) LTO := $(THREADS)
endif endif
GIT_COMMIT := $(shell git rev-parse --short HEAD 2> /dev/null || true)
CONFIGURE_COMMAND := $(MAKE) STATIC=$(STATIC) FORTIFY_SOURCE=$(FORTIFY_SOURCE)
ifeq ($(PLATFORM_LC),linux)
CONFIGURE_COMMAND += GPU_SUPPORT=$(GPU_SUPPORT) RSMI_STATIC=$(RSMI_STATIC)
endif
#? The Directories, Source, Includes, Objects and Binary #? The Directories, Source, Includes, Objects and Binary
SRCDIR := src SRCDIR := src
INCDIRS := include $(wildcard lib/**/include) INCDIRS := include $(wildcard lib/**/include)
@ -174,10 +190,10 @@ override GOODFLAGS := $(foreach flag,$(TESTFLAGS),$(strip $(shell echo "int main
override REQFLAGS := -std=c++20 override REQFLAGS := -std=c++20
WARNFLAGS := -Wall -Wextra -pedantic WARNFLAGS := -Wall -Wextra -pedantic
OPTFLAGS := -O2 -ftree-vectorize -flto=$(LTO) OPTFLAGS := -O2 -ftree-vectorize -flto=$(LTO)
LDCXXFLAGS := -pthread -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -D_FILE_OFFSET_BITS=64 $(GOODFLAGS) $(ADDFLAGS) LDCXXFLAGS := -pthread -DFMT_HEADER_ONLY -D_GLIBCXX_ASSERTIONS -D_FILE_OFFSET_BITS=64 $(GOODFLAGS) $(ADDFLAGS)
override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS)
override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS) override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS)
INC := $(foreach incdir,$(INCDIRS),-isystem $(incdir)) -I$(SRCDIR) INC := $(foreach incdir,$(INCDIRS),-isystem $(incdir)) -I$(SRCDIR) -I$(BUILDDIR)
SU_USER := root SU_USER := root
ifdef DEBUG ifdef DEBUG
@ -217,7 +233,7 @@ endif
#? Default Make #? Default Make
.ONESHELL: .ONESHELL:
all: | info rocm_smi info-quiet directories btop all: | info rocm_smi info-quiet directories btop.1 config.h btop
ifneq ($(QUIET),true) ifneq ($(QUIET),true)
info: info:
@ -238,7 +254,6 @@ info:
@true @true
endif endif
info-quiet: | info rocm_smi info-quiet: | info rocm_smi
@printf "\n\033[1;92mBuilding btop++ \033[91m(\033[97mv$(BTOP_VERSION)\033[91m) \033[93m$(PLATFORM) \033[96m$(ARCH)\033[0m\n" @printf "\n\033[1;92mBuilding btop++ \033[91m(\033[97mv$(BTOP_VERSION)\033[91m) \033[93m$(PLATFORM) \033[96m$(ARCH)\033[0m\n"
@ -262,6 +277,22 @@ directories:
@$(VERBOSE) || printf "mkdir -p $(BUILDDIR)/$(PLATFORM_DIR)\n" @$(VERBOSE) || printf "mkdir -p $(BUILDDIR)/$(PLATFORM_DIR)\n"
@mkdir -p $(BUILDDIR)/$(PLATFORM_DIR) @mkdir -p $(BUILDDIR)/$(PLATFORM_DIR)
config.h: $(BUILDDIR)/config.h
$(BUILDDIR)/config.h: $(SRCDIR)/config.h.in | directories
@$(QUIET) || printf "\033[1mConfiguring $(BUILDDIR)/config.h\033[0m\n"
@$(VERBOSE) || printf 'sed -e "s|@GIT_COMMIT@|$(GIT_COMMIT)|" -e "s|@CONFIGURE_COMMAND@|$(CONFIGURE_COMMAND)|" -e "s|@COMPILER@|$(CXX)|" -e "s|@COMPILER_VERSION@|$(CXX_VERSION)|" $< | tee $@ > /dev/null\n'
@sed -e "s|@GIT_COMMIT@|$(GIT_COMMIT)|" -e "s|@CONFIGURE_COMMAND@|$(CONFIGURE_COMMAND)|" -e "s|@COMPILER@|$(CXX)|" -e "s|@COMPILER_VERSION@|$(CXX_VERSION)|" $< | tee $@ > /dev/null
#? Man page
btop.1: manpage.md | directories
ifeq ($(shell command -v lowdown >/dev/null; echo $$?),0)
@printf "\n\033[1;92mGenerating man page $@\033[37m...\033[0m\n"
lowdown -s -Tman -o $@ $<
else
@printf "\n\033[1;93mCommand 'lowdown' not found: skipping generating man page $@\033[0m\n"
endif
#? Clean only Objects #? Clean only Objects
clean: clean:
@printf "\033[1;91mRemoving: \033[1;97mbuilt objects...\033[0m\n" @printf "\033[1;91mRemoving: \033[1;97mbuilt objects...\033[0m\n"
@ -293,7 +324,11 @@ install:
@printf "\033[1;92mInstalling SVG icon to: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg\n" @printf "\033[1;92mInstalling SVG icon to: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg\n"
@mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps @mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps
@cp -p Img/icon.svg $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg @cp -p Img/icon.svg $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg
ifneq ($(wildcard btop.1),)
@printf "\033[1;92mInstalling man page to: \033[1;97m$(DESTDIR)$(PREFIX)/share/man/man1/btop.1\n"
@mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1
@cp -p btop.1 $(DESTDIR)$(PREFIX)/share/man/man1/btop.1
endif
#? Set SUID bit for btop as $SU_USER in $SU_GROUP #? Set SUID bit for btop as $SU_USER in $SU_GROUP
setuid: setuid:
@ -303,17 +338,20 @@ setuid:
@printf "\033[1;92mSetting SUID bit\033[0m\n" @printf "\033[1;92mSetting SUID bit\033[0m\n"
@chmod u+s $(DESTDIR)$(PREFIX)/bin/btop @chmod u+s $(DESTDIR)$(PREFIX)/bin/btop
# With 'rm -v' user will see what files (if any) got removed
uninstall: uninstall:
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/bin/btop\033[0m\n" @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/bin/btop\033[0m\n"
@rm -rf $(DESTDIR)$(PREFIX)/bin/btop @rm -rfv $(DESTDIR)$(PREFIX)/bin/btop
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop\033[0m\n" @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop\033[0m\n"
@rm -rf $(DESTDIR)$(PREFIX)/share/btop @rm -rfv $(DESTDIR)$(PREFIX)/share/btop
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/applications/btop.desktop\033[0m\n" @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/applications/btop.desktop\033[0m\n"
@rm -rf $(DESTDIR)$(PREFIX)/share/applications/btop.desktop @rm -rfv $(DESTDIR)$(PREFIX)/share/applications/btop.desktop
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png\033[0m\n" @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png\033[0m\n"
@rm -rf $(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png @rm -rfv $(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg\033[0m\n" @printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg\033[0m\n"
@rm -rf $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg @rm -rfv $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/man/man1/btop.1\033[0m\n"
@rm -rfv $(DESTDIR)$(PREFIX)/share/man/man1/btop.1
#? Pull in dependency info for *existing* .o files #? Pull in dependency info for *existing* .o files
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) -include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
@ -357,7 +395,7 @@ btop: $(OBJECTS) | rocm_smi directories
#? Compile #? Compile
.ONESHELL: .ONESHELL:
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) | rocm_smi directories $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) | rocm_smi directories config.h
@sleep 0.3 2>/dev/null || true @sleep 0.3 2>/dev/null || true
@TSTAMP=$$(date +%s 2>/dev/null || echo "0") @TSTAMP=$$(date +%s 2>/dev/null || echo "0")
@$(QUIET) || printf "\033[1;97mCompiling $<\033[0m\n" @$(QUIET) || printf "\033[1;97mCompiling $<\033[0m\n"
@ -366,4 +404,4 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) | rocm_smi directories
@printf "\033[1;92m$$($(PROGRESS))$(P)\033[10D\033[5C-> \033[1;37m$@ \033[100D\033[38C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$($(DATE_CMD) +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n" @printf "\033[1;92m$$($(PROGRESS))$(P)\033[10D\033[5C-> \033[1;37m$@ \033[100D\033[38C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$($(DATE_CMD) +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n"
#? Non-File Targets #? Non-File Targets
.PHONY: all msg help pre .PHONY: all config.h msg help pre

133
README.md
View file

@ -47,8 +47,8 @@
Btop release v1.3.0 Btop release v1.3.0
Big release with GPU support added for Linux and platform support for OpenBSD. Big thanks to @romner-set (GPU support) and @joske (OpenBSD support) for contributions. Big release with GPU support added for Linux and platform support for OpenBSD. Big thanks to [@romner-set](https://github.com/romner-set) (GPU support) and [@joske](https://github.com/joske) (OpenBSD support) for contributions.
And a multitude of bugfixes and small changes, see [CHANGES.md](CHANGES.md) and latest [release](https://github.com/aristocratos/btop/releases/latest) for detailed list and attributions. And a multitude of bugfixes and small changes, see [CHANGELOG.md](CHANGELOG.md) and latest [release](https://github.com/aristocratos/btop/releases/latest) for detailed list and attributions.
See news entry below for more information regarding GPU support. See news entry below for more information regarding GPU support.
@ -106,7 +106,7 @@ If you want to help out, test for bugs/fix bugs or just try out the branches:
**macOS / OSX** **macOS / OSX**
```bash ```bash
# Install and use Homebrew or MacPorts package managers for easy dependency installation # Install and use Homebrew or MacPorts package managers for easy dependency installation
brew install coreutils make gcc@11 brew install coreutils make gcc@11 lowdown
git clone https://github.com/aristocratos/btop.git git clone https://github.com/aristocratos/btop.git
cd btop cd btop
git checkout OSX git checkout OSX
@ -115,7 +115,7 @@ gmake
**FreeBSD** **FreeBSD**
```bash ```bash
sudo pkg install gmake gcc11 coreutils git sudo pkg install gmake gcc11 coreutils git lowdown
git clone https://github.com/aristocratos/btop.git git clone https://github.com/aristocratos/btop.git
cd btop cd btop
git checkout freebsd git checkout freebsd
@ -222,6 +222,22 @@ Also needs a UTF8 locale and a font that covers:
* Unicode Block “Geometric Shapes” U+25A0 - U+25FF * Unicode Block “Geometric Shapes” U+25A0 - U+25FF
* Unicode Block "Box Drawing" and "Block Elements" U+2500 - U+259F * Unicode Block "Box Drawing" and "Block Elements" U+2500 - U+259F
### **Optional Dependencies (Needed for GPU monitoring)**
GPU monitoring also requires a btop binary built with GPU support (`GPU_SUPPORT=true` flag).
See [GPU compatibility](#gpu-compatibility) section for more about compiling with GPU support.
* **NVIDIA**
If you have an NVIDIA GPU you must use an official NVIDIA driver, both the closed-source and open-source ones have been verified to work.
In addition to that you must also have the nvidia-ml dynamic library installed, which should be included with the driver package of your distribution.
* **AMD**
If you have an AMD GPU `rocm_smi_lib` is required, which may or may not be packaged for your distribution.
### **Notice (Text rendering issues)** ### **Notice (Text rendering issues)**
* If you are having problems with the characters in the graphs not looking like they do in the screenshots, it's likely a problem with your systems configured fallback font not having support for braille characters. * If you are having problems with the characters in the graphs not looking like they do in the screenshots, it's likely a problem with your systems configured fallback font not having support for braille characters.
@ -362,12 +378,12 @@ Also needs a UTF8 locale and a font that covers:
* **AMD** * **AMD**
AMDGPU data is queried using the [ROCm SMI](https://github.com/RadeonOpenCompute/rocm_smi_lib) library, which may or may not be packaged for your distribution. If your distribution doesn't provide a package, btop++ is statically linked to ROCm SMI with the `RSMI_STATIC=true` make flag. AMDGPU data is queried using the [ROCm SMI](https://github.com/rocm/rocm_smi_lib) library, which may or may not be packaged for your distribution. If your distribution doesn't provide a package, btop++ is statically linked to ROCm SMI with the `RSMI_STATIC=true` make flag.
This flag expects the ROCm SMI source code in `lib/rocm_smi_lib`, and compilation will fail if it's not there. The latest tested version is 5.6.x, which can be obtained with the following command: This flag expects the ROCm SMI source code in `lib/rocm_smi_lib`, and compilation will fail if it's not there. The latest tested version is 5.6.x, which can be obtained with the following command:
```bash ```bash
git clone https://github.com/RadeonOpenCompute/rocm_smi_lib.git --depth 1 -b rocm-5.6.x lib/rocm_smi_lib git clone https://github.com/rocm/rocm_smi_lib.git --depth 1 -b rocm-5.6.x lib/rocm_smi_lib
``` ```
<details> <details>
@ -379,7 +395,7 @@ Also needs a UTF8 locale and a font that covers:
1. **Install dependencies (example for Ubuntu 21.04 Hirsute)** 1. **Install dependencies (example for Ubuntu 21.04 Hirsute)**
```bash ```bash
sudo apt install coreutils sed git build-essential gcc-11 g++-11 sudo apt install coreutils sed git build-essential gcc-11 g++-11 lowdown
``` ```
2. **Clone repository** 2. **Clone repository**
@ -405,10 +421,11 @@ Also needs a UTF8 locale and a font that covers:
| `STRIP=true` | To force stripping of debug symbols (adds `-s` linker flag) | | `STRIP=true` | To force stripping of debug symbols (adds `-s` linker flag) |
| `DEBUG=true` | Sets OPTFLAGS to `-O0 -g` and enables more verbose debug logging | | `DEBUG=true` | Sets OPTFLAGS to `-O0 -g` and enables more verbose debug logging |
| `ARCH=<architecture>` | To manually set the target architecture | | `ARCH=<architecture>` | To manually set the target architecture |
| `FORTIFY_SOURCE=false` | Disable fortification with `_FORTIFY_SOURCE=3` |
| `GPU_SUPPORT=<true\|false>` | Enable/disable GPU support (Enabled by default on X86_64 Linux) | | `GPU_SUPPORT=<true\|false>` | Enable/disable GPU support (Enabled by default on X86_64 Linux) |
| `RSMI_STATIC=true` | To statically link the ROCm SMI library used for querying AMDGPU | | `RSMI_STATIC=true` | To statically link the ROCm SMI library used for querying AMDGPU |
| `ADDFLAGS=<flags>` | For appending flags to both compiler and linker | | `ADDFLAGS=<flags>` | For appending flags to both compiler and linker |
| `CXX=<compiler>` | Manualy set which compiler to use | | `CXX=<compiler>` | Manually set which compiler to use |
Example: `make ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. Example: `make ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
@ -469,12 +486,12 @@ Also needs a UTF8 locale and a font that covers:
1. **Install build dependencies** 1. **Install build dependencies**
Requires Clang / GCC, CMake, Ninja and Git Requires Clang / GCC, CMake, Ninja, Lowdown and Git
For example, with Debian Bookworm: For example, with Debian Bookworm:
```bash ```bash
sudo apt install cmake git g++ ninja-build sudo apt install cmake git g++ ninja-build lowdown
``` ```
2. **Clone the repository** 2. **Clone the repository**
@ -503,6 +520,7 @@ Also needs a UTF8 locale and a font that covers:
| `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) | | `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) |
| `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) | | `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) |
| `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) | | `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) |
| `-DBTOP_FORTIFY=<ON\|OFF>` | Detect buffer overflows with `_FORTIFY_SOURCE=3` (ON by default) |
| `-DBTOP_GPU=<ON\|OFF>` | Enable GPU support (ON by default) | | `-DBTOP_GPU=<ON\|OFF>` | Enable GPU support (ON by default) |
| `-DBTOP_RSMI_STATIC=<ON\|OFF>` | Build and link the ROCm SMI library statically (OFF by default) | | `-DBTOP_RSMI_STATIC=<ON\|OFF>` | Build and link the ROCm SMI library statically (OFF by default) |
| `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) | | `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) |
@ -551,7 +569,7 @@ Also needs a UTF8 locale and a font that covers:
1. **Install dependencies (example for Homebrew)** 1. **Install dependencies (example for Homebrew)**
```bash ```bash
brew install coreutils make gcc@12 brew install coreutils make gcc@12 lowdown
``` ```
2. **Clone repository** 2. **Clone repository**
@ -576,8 +594,9 @@ Also needs a UTF8 locale and a font that covers:
| `STRIP=true` | To force stripping of debug symbols (adds `-s` linker flag) | | `STRIP=true` | To force stripping of debug symbols (adds `-s` linker flag) |
| `DEBUG=true` | Sets OPTFLAGS to `-O0 -g` and enables more verbose debug logging | | `DEBUG=true` | Sets OPTFLAGS to `-O0 -g` and enables more verbose debug logging |
| `ARCH=<architecture>` | To manually set the target architecture | | `ARCH=<architecture>` | To manually set the target architecture |
| `FORTIFY_SOURCE=false` | Disable fortification with `_FORTIFY_SOURCE=3` |
| `ADDFLAGS=<flags>` | For appending flags to both compiler and linker | | `ADDFLAGS=<flags>` | For appending flags to both compiler and linker |
| `CXX=<compiler>` | Manualy set which compiler to use | | `CXX=<compiler>` | Manually set which compiler to use |
Example: `gmake ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. Example: `gmake ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
@ -636,11 +655,11 @@ Also needs a UTF8 locale and a font that covers:
1. **Install build dependencies** 1. **Install build dependencies**
Requires Clang, CMake, Ninja and Git Requires Clang, CMake, Ninja, Lowdown and Git
```bash ```bash
brew update --quiet brew update --quiet
brew install cmake git llvm ninja brew install cmake git llvm ninja lowdown
``` ```
2. **Clone the repository** 2. **Clone the repository**
@ -674,6 +693,7 @@ Also needs a UTF8 locale and a font that covers:
| `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) | | `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) |
| `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) | | `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) |
| `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) | | `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) |
| `-DBTOP_FORTIFY=<ON\|OFF>` | Detect buffer overflows with `_FORTIFY_SOURCE=3` (ON by default) |
| `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) | | `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) |
To force any specific compiler, run `CXX=<compiler> cmake -B build -G Ninja` To force any specific compiler, run `CXX=<compiler> cmake -B build -G Ninja`
@ -716,7 +736,7 @@ Also needs a UTF8 locale and a font that covers:
1. **Install dependencies** 1. **Install dependencies**
```bash ```bash
sudo pkg install gmake gcc11 coreutils git sudo pkg install gmake gcc11 coreutils git lowdown
``` ```
2. **Clone repository** 2. **Clone repository**
@ -742,8 +762,9 @@ Also needs a UTF8 locale and a font that covers:
| `STRIP=true` | To force stripping of debug symbols (adds `-s` linker flag) | | `STRIP=true` | To force stripping of debug symbols (adds `-s` linker flag) |
| `DEBUG=true` | Sets OPTFLAGS to `-O0 -g` and enables more verbose debug logging | | `DEBUG=true` | Sets OPTFLAGS to `-O0 -g` and enables more verbose debug logging |
| `ARCH=<architecture>` | To manually set the target architecture | | `ARCH=<architecture>` | To manually set the target architecture |
| `FORTIFY_SOURCE=false` | Disable fortification with `_FORTIFY_SOURCE=3` |
| `ADDFLAGS=<flags>` | For appending flags to both compiler and linker | | `ADDFLAGS=<flags>` | For appending flags to both compiler and linker |
| `CXX=<compiler>` | Manualy set which compiler to use | | `CXX=<compiler>` | Manually set which compiler to use |
Example: `gmake ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. Example: `gmake ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
@ -802,18 +823,18 @@ Also needs a UTF8 locale and a font that covers:
1. **Install build dependencies** 1. **Install build dependencies**
Requires Clang / GCC, CMake, Ninja and Git Requires Clang / GCC, CMake, Ninja, Lowdown and Git
_**Note:** LLVM's libc++ shipped with FreeBSD 13 is too old and cannot compile btop._ _**Note:** LLVM's libc++ shipped with FreeBSD 13 is too old and cannot compile btop._
FreeBSD 14 and later: FreeBSD 14 and later:
```bash ```bash
pkg install cmake ninja pkg install cmake ninja lowdown
``` ```
FreeBSD 13: FreeBSD 13:
```bash ```bash
pkg install cmake gcc13 ninja pkg install cmake gcc13 ninja lowdown
``` ```
2. **Clone the repository** 2. **Clone the repository**
@ -851,6 +872,7 @@ Also needs a UTF8 locale and a font that covers:
| `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) | | `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) |
| `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) | | `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) |
| `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) | | `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) |
| `-DBTOP_FORTIFY=<ON\|OFF>` | Detect buffer overflows with `_FORTIFY_SOURCE=3` (ON by default) |
| `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) | | `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) |
_**Note:** Static linking does not work with GCC._ _**Note:** Static linking does not work with GCC._
@ -895,7 +917,7 @@ Also needs a UTF8 locale and a font that covers:
1. **Install dependencies** 1. **Install dependencies**
```bash ```bash
pkg_add gmake gcc%11 g++%11 coreutils git pkg_add gmake gcc%11 g++%11 coreutils git lowdown
``` ```
2. **Clone repository** 2. **Clone repository**
@ -921,8 +943,9 @@ Also needs a UTF8 locale and a font that covers:
| `STRIP=true` | To force stripping of debug symbols (adds `-s` linker flag) | | `STRIP=true` | To force stripping of debug symbols (adds `-s` linker flag) |
| `DEBUG=true` | Sets OPTFLAGS to `-O0 -g` and enables more verbose debug logging | | `DEBUG=true` | Sets OPTFLAGS to `-O0 -g` and enables more verbose debug logging |
| `ARCH=<architecture>` | To manually set the target architecture | | `ARCH=<architecture>` | To manually set the target architecture |
| `FORTIFY_SOURCE=false` | Disable fortification with `_FORTIFY_SOURCE=3` |
| `ADDFLAGS=<flags>` | For appending flags to both compiler and linker | | `ADDFLAGS=<flags>` | For appending flags to both compiler and linker |
| `CXX=<compiler>` | Manualy set which compiler to use | | `CXX=<compiler>` | Manually set which compiler to use |
Example: `gmake ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. Example: `gmake ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
@ -972,6 +995,74 @@ Also needs a UTF8 locale and a font that covers:
gmake help gmake help
``` ```
</details>
<details>
<summary>
### With CMake (Community maintained)
</summary>
1. **Install build dependencies**
Requires GCC, CMake, Ninja, Lowdown and Git
_**Note:** LLVM's libc++ shipped with OpenBSD 7.4 is too old and cannot compile btop._
```bash
pkg_add cmake g++%11 git ninja lowdown
```
2. **Clone the repository**
```bash
git clone https://github.com/aristocratos/btop.git && cd btop
```
3. **Compile**
```bash
# Configure
CXX=eg++ cmake -B build -G Ninja
# Build
cmake --build build
```
This will automatically build a release version of btop.
Some useful options to pass to the configure step:
| Configure flag | Description |
|---------------------------------|-------------------------------------------------------------------------|
| `-DBTOP_LTO=<ON\|OFF>` | Enables link time optimization (ON by default) |
| `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) |
| `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) |
| `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) |
| `-DBTOP_FORTIFY=<ON\|OFF>` | Detect buffer overflows with `_FORTIFY_SOURCE=3` (ON by default) |
| `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) |
To force any other compiler, run `CXX=<compiler> cmake -B build -G Ninja`
4. **Install**
```bash
cmake --install build
```
May require root privileges
5. **Uninstall**
CMake doesn't generate an uninstall target by default. To remove installed files, run
```
cat build/install_manifest.txt | xargs rm -irv
```
6. **Cleanup build directory**
```bash
cmake --build build -t clean
```
</details> </details>
## Installing the snap ## Installing the snap

View file

@ -3,7 +3,7 @@
# Find libkvm, the Kernel Data Access Library # Find libkvm, the Kernel Data Access Library
# #
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") if(BSD)
find_path(kvm_INCLUDE_DIR NAMES kvm.h) find_path(kvm_INCLUDE_DIR NAMES kvm.h)
find_library(kvm_LIBRARY NAMES kvm) find_library(kvm_LIBRARY NAMES kvm)

57
manpage.md Normal file
View file

@ -0,0 +1,57 @@
% btop(1) | User Commands
%
% "January 4 2024"
# NAME
btop - Resource monitor that shows usage and stats for processor, memory, disks, network, and processes.
# SYNOPSIS
**btop** [**-lc**] [**-t** | **+t**] [**-p** _id_] [**\-\-utf-force**]
[**\-\-debug**] [{**-h** | **\-\-help**} | {**-v** | **\-\-version**}]
# DESCRIPTION
**btop** is a program that shows usage and stats for processor, memory, disks, network, and processes.
# OPTIONS
The program follows the usual GNU command line syntax, with long options
starting with two dashes ('-'). A summary of options is included below.
**-lc**, **\-\-low-color**
: Disable truecolor, converts 24-bit colors to 256-color.
**-t**, **\-\-tty_on**
: Force (ON) tty mode, max 16 colors and tty-friendly graph symbols.
**+t**, **\-\-tty_off**
: Force (OFF) tty mode.
**-p**, **\-\-preset _id_**
: Start with preset, integer value between 0-9.
**\-\-utf-force**
: Force start even if no UTF-8 locale was detected.
**\-\-debug**
: Start in DEBUG mode: shows microsecond timer for information collect and screen draw functions and sets loglevel to DEBUG.
**-h**, **\-\-help**
: Show summary of options.
**-v**, **\-\-version**
: Show version of program.
# BUGS
The upstream bug tracker can be found at https://github.com/aristocratos/btop/issues.
# SEE ALSO
**top**(1), **htop**(1)
# AUTHOR
**btop** was written by Jakob P. Liljenberg a.k.a. "Aristocratos".

View file

@ -6,7 +6,7 @@ description: |
C++ version and continuation of bashtop and bpytop. C++ version and continuation of bashtop and bpytop.
license: Apache-2.0 license: Apache-2.0
base: core20 base: core22
grade: stable grade: stable
confinement: strict confinement: strict
compression: lzo compression: lzo
@ -49,6 +49,8 @@ parts:
- PREFIX=/usr/local - PREFIX=/usr/local
- STATIC=true - STATIC=true
- ADDFLAGS="-D SNAPPED" - ADDFLAGS="-D SNAPPED"
# Add 'lowdown' to build dependencies as soon at Snap builder updates from
# Ubuntu 20.04 "Focal" to something newer that has Lowdown included
build-packages: build-packages:
- coreutils - coreutils
- sed - sed
@ -56,7 +58,7 @@ parts:
- build-essential - build-essential
- gcc-11 - gcc-11
- g++-11 - g++-11
override-pull: | override-pull: |
snapcraftctl pull snapcraftctl pull
snapcraftctl set-version "$(git describe --tags | sed 's/^v//' | cut -d "-" -f1)" snapcraftctl set-version "$(git describe --tags | sed 's/^v//' | cut -d "-" -f1)"

View file

@ -52,7 +52,9 @@ tab-size = 4
#include "btop_theme.hpp" #include "btop_theme.hpp"
#include "btop_draw.hpp" #include "btop_draw.hpp"
#include "btop_menu.hpp" #include "btop_menu.hpp"
#include "config.h"
#include "fmt/core.h" #include "fmt/core.h"
#include "fmt/ostream.h"
using std::atomic; using std::atomic;
using std::cout; using std::cout;
@ -78,7 +80,7 @@ namespace Global {
{"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"},
{"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"},
}; };
const string Version = "1.3.0"; const string Version = "1.3.2";
int coreCount; int coreCount;
string overlay; string overlay;
@ -108,6 +110,7 @@ namespace Global {
atomic<bool> should_sleep (false); atomic<bool> should_sleep (false);
atomic<bool> _runner_started (false); atomic<bool> _runner_started (false);
atomic<bool> init_conf (false); atomic<bool> init_conf (false);
atomic<bool> reload_conf (false);
bool arg_tty{}; bool arg_tty{};
bool arg_low_color{}; bool arg_low_color{};
@ -115,6 +118,19 @@ namespace Global {
int arg_update = 0; int arg_update = 0;
} }
static void print_version() {
if constexpr (GIT_COMMIT.empty()) {
fmt::print("btop version: {}\n", Global::Version);
} else {
fmt::print("btop version: {}+{}\n", Global::Version, GIT_COMMIT);
}
}
static void print_version_with_build_info() {
print_version();
fmt::print("Compiled with: {} ({})\nConfigured with: {}\n", COMPILER, COMPILER_VERSION, CONFIGURE_COMMAND);
}
//* A simple argument parser //* A simple argument parser
void argumentParser(const int argc, char **argv) { void argumentParser(const int argc, char **argv) {
for(int i = 1; i < argc; i++) { for(int i = 1; i < argc; i++) {
@ -136,8 +152,12 @@ void argumentParser(const int argc, char **argv) {
); );
exit(0); exit(0);
} }
else if (is_in(argument, "-v", "--version")) { else if (is_in(argument, "-v")) {
fmt::println("btop version: {}", Global::Version); print_version();
exit(0);
}
else if (is_in(argument, "--version")) {
print_version_with_build_info();
exit(0); exit(0);
} }
else if (is_in(argument, "-lc", "--low-color")) { else if (is_in(argument, "-lc", "--low-color")) {
@ -364,9 +384,38 @@ void _signal_handler(const int sig) {
case SIGUSR1: case SIGUSR1:
// Input::poll interrupt // Input::poll interrupt
break; break;
case SIGUSR2:
Global::reload_conf = true;
Input::interrupt();
break;
} }
} }
//* Config init
void init_config(){
atomic_lock lck(Global::init_conf);
vector<string> load_warnings;
Config::load(Config::conf_file, load_warnings);
Config::set("lowcolor", (Global::arg_low_color ? true : not Config::getB("truecolor")));
static bool first_init = true;
if (Global::debug and first_init) {
Logger::set("DEBUG");
Logger::debug("Running in DEBUG mode!");
}
else Logger::set(Config::getS("log_level"));
static string log_level;
if (const string current_level = Config::getS("log_level"); log_level != current_level) {
log_level = current_level;
Logger::info("Logger set to " + (Global::debug ? "DEBUG" : log_level));
}
for (const auto& err_str : load_warnings) Logger::warning(err_str);
first_init = false;
}
//* Manages secondary thread for collection and drawing of boxes //* Manages secondary thread for collection and drawing of boxes
namespace Runner { namespace Runner {
atomic<bool> active (false); atomic<bool> active (false);
@ -403,7 +452,7 @@ namespace Runner {
} }
}; };
//* Wrapper for raising priviliges when using SUID bit //* Wrapper for raising privileges when using SUID bit
class gain_priv { class gain_priv {
int status = -1; int status = -1;
public: public:
@ -836,7 +885,7 @@ int main(int argc, char **argv) {
Global::start_time = time_s(); Global::start_time = time_s();
//? Save real and effective userid's and drop priviliges until needed if running with SUID bit set //? Save real and effective userid's and drop privileges until needed if running with SUID bit set
Global::real_uid = getuid(); Global::real_uid = getuid();
Global::set_uid = geteuid(); Global::set_uid = geteuid();
if (Global::real_uid != Global::set_uid) { if (Global::real_uid != Global::set_uid) {
@ -895,22 +944,7 @@ int main(int argc, char **argv) {
} }
//? Config init //? Config init
{ init_config();
atomic_lock lck(Global::init_conf);
vector<string> load_warnings;
Config::load(Config::conf_file, load_warnings);
Config::set("lowcolor", (Global::arg_low_color ? true : not Config::getB("truecolor")));
if (Global::debug) {
Logger::set("DEBUG");
Logger::debug("Starting in DEBUG mode!");
}
else Logger::set(Config::getS("log_level"));
Logger::info("Logger set to " + (Global::debug ? "DEBUG" : Config::getS("log_level")));
for (const auto& err_str : load_warnings) Logger::warning(err_str);
}
//? Try to find and set a UTF-8 locale //? Try to find and set a UTF-8 locale
if (std::setlocale(LC_ALL, "") != nullptr and not s_contains((string)std::setlocale(LC_ALL, ""), ";") if (std::setlocale(LC_ALL, "") != nullptr and not s_contains((string)std::setlocale(LC_ALL, ""), ";")
@ -920,7 +954,7 @@ int main(int argc, char **argv) {
else { else {
string found; string found;
bool set_failure{}; bool set_failure{};
for (const auto loc_env : array{"LANG", "LC_ALL"}) { for (const auto loc_env : array{"LANG", "LC_ALL", "LC_CTYPE"}) {
if (std::getenv(loc_env) != nullptr and str_to_upper(s_replace((string)std::getenv(loc_env), "-", "")).ends_with("UTF8")) { if (std::getenv(loc_env) != nullptr and str_to_upper(s_replace((string)std::getenv(loc_env), "-", "")).ends_with("UTF8")) {
found = std::getenv(loc_env); found = std::getenv(loc_env);
if (std::setlocale(LC_ALL, found.c_str()) == nullptr) { if (std::setlocale(LC_ALL, found.c_str()) == nullptr) {
@ -1035,6 +1069,7 @@ int main(int argc, char **argv) {
std::signal(SIGCONT, _signal_handler); std::signal(SIGCONT, _signal_handler);
std::signal(SIGWINCH, _signal_handler); std::signal(SIGWINCH, _signal_handler);
std::signal(SIGUSR1, _signal_handler); std::signal(SIGUSR1, _signal_handler);
std::signal(SIGUSR2, _signal_handler);
sigset_t mask; sigset_t mask;
sigemptyset(&mask); sigemptyset(&mask);
@ -1086,9 +1121,27 @@ int main(int argc, char **argv) {
try { try {
while (not true not_eq not false) { while (not true not_eq not false) {
//? Check for exceptions in secondary thread and exit with fail signal if true //? Check for exceptions in secondary thread and exit with fail signal if true
if (Global::thread_exception) clean_quit(1); if (Global::thread_exception) {
else if (Global::should_quit) clean_quit(0); clean_quit(1);
else if (Global::should_sleep) { Global::should_sleep = false; _sleep(); } }
else if (Global::should_quit) {
clean_quit(0);
}
else if (Global::should_sleep) {
Global::should_sleep = false;
_sleep();
}
//? Hot reload config from CTRL + R or SIGUSR2
else if (Global::reload_conf) {
Global::reload_conf = false;
if (Runner::active) Runner::stop();
Config::unlock();
init_config();
Theme::updateThemes();
Theme::setTheme();
Draw::banner_gen(0, 0, false, true);
Global::resized = true;
}
//? Make sure terminal size hasn't changed (in case of SIGWINCH not working properly) //? Make sure terminal size hasn't changed (in case of SIGWINCH not working properly)
term_resize(Global::resized); term_resize(Global::resized);
@ -1123,9 +1176,9 @@ int main(int argc, char **argv) {
update_ms = Config::getI("update_ms"); update_ms = Config::getI("update_ms");
future_time = time_ms() + update_ms; future_time = time_ms() + update_ms;
} }
else if (future_time - current_time > update_ms) else if (future_time - current_time > update_ms) {
future_time = current_time; future_time = current_time;
}
//? Poll for input and process any input detected //? Poll for input and process any input detected
else if (Input::poll(min((uint64_t)1000, future_time - current_time))) { else if (Input::poll(min((uint64_t)1000, future_time - current_time))) {
if (not Runner::active) Config::unlock(); if (not Runner::active) Config::unlock();

View file

@ -199,6 +199,8 @@ namespace Config {
{"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."}, {"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."},
{"show_battery_watts", "#* Show power stats of battery next to charge indicator."},
{"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n" {"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n"
"#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."}, "#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."},
#ifdef GPU_SUPPORT #ifdef GPU_SUPPORT
@ -293,6 +295,7 @@ namespace Config {
{"net_auto", true}, {"net_auto", true},
{"net_sync", true}, {"net_sync", true},
{"show_battery", true}, {"show_battery", true},
{"show_battery_watts", true},
{"vim_keys", false}, {"vim_keys", false},
{"tty_mode", false}, {"tty_mode", false},
{"disk_free_priv", false}, {"disk_free_priv", false},
@ -729,9 +732,9 @@ namespace Config {
if (geteuid() != Global::real_uid and seteuid(Global::real_uid) != 0) return; if (geteuid() != Global::real_uid and seteuid(Global::real_uid) != 0) return;
std::ofstream cwrite(conf_file, std::ios::trunc); std::ofstream cwrite(conf_file, std::ios::trunc);
if (cwrite.good()) { if (cwrite.good()) {
cwrite << "#? Config file for btop v. " << Global::Version; cwrite << "#? Config file for btop v. " << Global::Version << "\n";
for (auto [name, description] : descriptions) { for (auto [name, description] : descriptions) {
cwrite << "\n\n" << (description.empty() ? "" : description + "\n") cwrite << "\n" << (description.empty() ? "" : description + "\n")
<< name << " = "; << name << " = ";
if (strings.contains(name)) if (strings.contains(name))
cwrite << "\"" << strings.at(name) << "\""; cwrite << "\"" << strings.at(name) << "\"";
@ -739,6 +742,7 @@ namespace Config {
cwrite << ints.at(name); cwrite << ints.at(name);
else if (bools.contains(name)) else if (bools.contains(name))
cwrite << (bools.at(name) ? "True" : "False"); cwrite << (bools.at(name) ? "True" : "False");
cwrite << "\n";
} }
} }
} }

View file

@ -706,6 +706,7 @@ namespace Cpu {
if (Config::getB("show_battery") and has_battery) { if (Config::getB("show_battery") and has_battery) {
static int old_percent{}; // defaults to = 0 static int old_percent{}; // defaults to = 0
static long old_seconds{}; // defaults to = 0 static long old_seconds{}; // defaults to = 0
static float old_watts{}; // defaults to = 0
static string old_status; static string old_status;
static Draw::Meter bat_meter {10, "cpu", true}; static Draw::Meter bat_meter {10, "cpu", true};
static const std::unordered_map<string, string> bat_symbols = { static const std::unordered_map<string, string> bat_symbols = {
@ -715,16 +716,18 @@ namespace Cpu {
{"unknown", ""} {"unknown", ""}
}; };
const auto& [percent, seconds, status] = current_bat; const auto& [percent, watts, seconds, status] = current_bat;
if (redraw or percent != old_percent or seconds != old_seconds or status != old_status) { if (redraw or percent != old_percent or (watts != old_watts and Config::getB("show_battery_watts")) or seconds != old_seconds or status != old_status) {
old_percent = percent; old_percent = percent;
old_watts = watts;
old_seconds = seconds; old_seconds = seconds;
old_status = status; old_status = status;
const string str_time = (seconds > 0 ? sec_to_dhms(seconds, true, true) : ""); const string str_time = (seconds > 0 ? sec_to_dhms(seconds, false, true) : "");
const string str_percent = to_string(percent) + '%'; const string str_percent = to_string(percent) + '%';
const string str_watts = (watts != -1 and Config::getB("show_battery_watts") ? fmt::format("{:.2f}", watts) + 'W' : "");
const auto& bat_symbol = bat_symbols.at((bat_symbols.contains(status) ? status : "unknown")); const auto& bat_symbol = bat_symbols.at((bat_symbols.contains(status) ? status : "unknown"));
const int current_len = (Term::width >= 100 ? 11 : 0) + str_time.size() + str_percent.size() + to_string(Config::getI("update_ms")).size(); const int current_len = (Term::width >= 100 ? 11 : 0) + str_time.size() + str_percent.size() + str_watts.size() + to_string(Config::getI("update_ms")).size();
const int current_pos = Term::width - current_len - 17; const int current_pos = Term::width - current_len - 17;
if ((bat_pos != current_pos or bat_len != current_len) and bat_pos > 0 and not redraw) if ((bat_pos != current_pos or bat_len != current_len) and bat_pos > 0 and not redraw)
@ -734,7 +737,7 @@ namespace Cpu {
out += Mv::to(y, bat_pos) + title_left + Theme::c("title") + Fx::b + "BAT" + bat_symbol + ' ' + str_percent out += Mv::to(y, bat_pos) + title_left + Theme::c("title") + Fx::b + "BAT" + bat_symbol + ' ' + str_percent
+ (Term::width >= 100 ? Fx::ub + ' ' + bat_meter(percent) + Fx::b : "") + (Term::width >= 100 ? Fx::ub + ' ' + bat_meter(percent) + Fx::b : "")
+ (not str_time.empty() ? ' ' + Theme::c("title") + str_time : " ") + Fx::ub + title_right; + (not str_time.empty() ? ' ' + Theme::c("title") + str_time : "") + (not str_watts.empty() ? " " + Theme::c("title") + Fx::b + str_watts : "") + Fx::ub + title_right;
} }
} }
else if (bat_pos > 0) { else if (bat_pos > 0) {
@ -1361,6 +1364,7 @@ namespace Net {
int x = 1, y, width = 20, height; int x = 1, y, width = 20, height;
int b_x, b_y, b_width, b_height, d_graph_height, u_graph_height; int b_x, b_y, b_width, b_height, d_graph_height, u_graph_height;
bool shown = true, redraw = true; bool shown = true, redraw = true;
const int MAX_IFNAMSIZ = 15;
string old_ip; string old_ip;
std::unordered_map<string, Draw::Graph> graphs; std::unordered_map<string, Draw::Graph> graphs;
string box; string box;
@ -1381,7 +1385,7 @@ namespace Net {
out.reserve(width * height); out.reserve(width * height);
const string title_left = Theme::c("net_box") + Fx::ub + Symbols::title_left; const string title_left = Theme::c("net_box") + Fx::ub + Symbols::title_left;
const string title_right = Theme::c("net_box") + Fx::ub + Symbols::title_right; const string title_right = Theme::c("net_box") + Fx::ub + Symbols::title_right;
const int i_size = min((int)selected_iface.size(), 10); const int i_size = min((int)selected_iface.size(), MAX_IFNAMSIZ);
const long long down_max = (net_auto ? safeVal(graph_max, "download"s) : ((long long)(Config::getI("net_download")) << 20) / 8); const long long down_max = (net_auto ? safeVal(graph_max, "download"s) : ((long long)(Config::getI("net_download")) << 20) / 8);
const long long up_max = (net_auto ? safeVal(graph_max, "upload"s) : ((long long)(Config::getI("net_upload")) << 20) / 8); const long long up_max = (net_auto ? safeVal(graph_max, "upload"s) : ((long long)(Config::getI("net_upload")) << 20) / 8);
@ -1403,7 +1407,7 @@ namespace Net {
//? Interface selector and buttons //? Interface selector and buttons
out += Mv::to(y, x+width - i_size - 9) + title_left + Fx::b + Theme::c("hi_fg") + "<b " + Theme::c("title") out += Mv::to(y, x+width - i_size - 9) + title_left + Fx::b + Theme::c("hi_fg") + "<b " + Theme::c("title")
+ uresize(selected_iface, 10) + Theme::c("hi_fg") + " n>" + title_right + uresize(selected_iface, MAX_IFNAMSIZ) + Theme::c("hi_fg") + " n>" + title_right
+ Mv::to(y, x+width - i_size - 15) + title_left + Theme::c("hi_fg") + (safeVal(net.stat, "download"s).offset + safeVal(net.stat, "upload"s).offset > 0 ? Fx::b : "") + 'z' + Mv::to(y, x+width - i_size - 15) + title_left + Theme::c("hi_fg") + (safeVal(net.stat, "download"s).offset + safeVal(net.stat, "upload"s).offset > 0 ? Fx::b : "") + 'z'
+ Theme::c("title") + "ero" + title_right; + Theme::c("title") + "ero" + title_right;
Input::mouse_mappings["b"] = {y, x+width - i_size - 8, 1, 3}; Input::mouse_mappings["b"] = {y, x+width - i_size - 8, 1, 3};
@ -2238,3 +2242,4 @@ namespace Draw {
} }
} }
} }

View file

@ -41,6 +41,7 @@ namespace Input {
//* Map for translating key codes to readable values //* Map for translating key codes to readable values
const std::unordered_map<string, string> Key_escapes = { const std::unordered_map<string, string> Key_escapes = {
{"\033", "escape"}, {"\033", "escape"},
{"\x12", "ctrl_r"},
{"\n", "enter"}, {"\n", "enter"},
{" ", "space"}, {" ", "space"},
{"\x7f", "backspace"}, {"\x7f", "backspace"},
@ -258,8 +259,10 @@ namespace Input {
Draw::calcSizes(); Draw::calcSizes();
Runner::run("all", false, true); Runner::run("all", false, true);
return; return;
} } else if (is_in(key, "ctrl_r")) {
else kill(getpid(), SIGUSR2);
return;
} else
keep_going = true; keep_going = true;
if (not keep_going) return; if (not keep_going) return;

View file

@ -56,7 +56,7 @@ namespace Input {
//* Last entered key //* Last entered key
extern deque<string> history; extern deque<string> history;
//* Poll keyboard & mouse input for <timeout> ms and return input availabilty as a bool //* Poll keyboard & mouse input for <timeout> ms and return input availability as a bool
bool poll(const uint64_t timeout=0); bool poll(const uint64_t timeout=0);
//* Get a key or mouse action from input //* Get a key or mouse action from input

View file

@ -177,6 +177,7 @@ namespace Menu {
{"F2, o", "Shows options."}, {"F2, o", "Shows options."},
{"F1, ?, h", "Shows this window."}, {"F1, ?, h", "Shows this window."},
{"ctrl + z", "Sleep program and put in background."}, {"ctrl + z", "Sleep program and put in background."},
{"ctrl + r", "Reloads config file from disk."},
{"q, ctrl + c", "Quits program."}, {"q, ctrl + c", "Quits program."},
{"+, -", "Add/Subtract 100ms to/from update timer."}, {"+, -", "Add/Subtract 100ms to/from update timer."},
{"Up, Down", "Select in process list."}, {"Up, Down", "Select in process list."},
@ -190,7 +191,7 @@ namespace Menu {
{"z", "Toggle totals reset for current network device"}, {"z", "Toggle totals reset for current network device"},
{"a", "Toggle auto scaling for the network graphs."}, {"a", "Toggle auto scaling for the network graphs."},
{"y", "Toggle synced scaling mode for network graphs."}, {"y", "Toggle synced scaling mode for network graphs."},
{"f, /", "To enter a process filter."}, {"f, /", "To enter a process filter. Start with ! for regex."},
{"delete", "Clear any entered filter."}, {"delete", "Clear any entered filter."},
{"c", "Toggle per-core cpu usage of processes."}, {"c", "Toggle per-core cpu usage of processes."},
{"r", "Reverse sorting order in processes box."}, {"r", "Reverse sorting order in processes box."},
@ -353,6 +354,11 @@ namespace Menu {
"Can be both batteries and UPS.", "Can be both batteries and UPS.",
"", "",
"\"Auto\" for auto detection."}, "\"Auto\" for auto detection."},
{"show_battery_watts",
"Show battery power.",
"",
"Show discharge power when discharging.",
"Show charging power when charging."},
{"log_level", {"log_level",
"Set loglevel for error.log", "Set loglevel for error.log",
"", "",
@ -484,7 +490,7 @@ namespace Menu {
"Kelvin, 0 = absolute zero, 1 degree change", "Kelvin, 0 = absolute zero, 1 degree change",
"equals 1 degree change in Celsius.", "equals 1 degree change in Celsius.",
"", "",
"Rankine, 0 = abosulte zero, 1 degree change", "Rankine, 0 = absolute zero, 1 degree change",
"equals 1 degree change in Fahrenheit."}, "equals 1 degree change in Fahrenheit."},
{"show_cpu_freq", {"show_cpu_freq",
"Show CPU frequency.", "Show CPU frequency.",
@ -645,7 +651,7 @@ namespace Menu {
"", "",
"Begin line with \"exclude=\" to change to", "Begin line with \"exclude=\" to change to",
"exclude filter.", "exclude filter.",
"Oterwise defaults to \"most include\" filter.", "Otherwise defaults to \"most include\" filter.",
"", "",
"Example:", "Example:",
"\"exclude=/boot /home/user\""}, "\"exclude=/boot /home/user\""},

View file

@ -17,6 +17,8 @@ tab-size = 4
*/ */
#include <ranges> #include <ranges>
#include <regex>
#include <string>
#include "btop_config.hpp" #include "btop_config.hpp"
#include "btop_shared.hpp" #include "btop_shared.hpp"
@ -111,6 +113,22 @@ namespace Proc {
} }
} }
bool matches_filter(const proc_info& proc, const std::string& filter) {
if (filter.starts_with("!")) {
if (filter.size() == 1) {
return true;
}
std::regex regex{filter.substr(1), std::regex::extended};
return std::regex_search(std::to_string(proc.pid), regex) ||
std::regex_search(proc.name, regex) || std::regex_match(proc.cmd, regex) ||
std::regex_search(proc.user, regex);
} else {
return s_contains(std::to_string(proc.pid), filter) ||
s_contains_ic(proc.name, filter) || s_contains_ic(proc.cmd, filter) ||
s_contains_ic(proc.user, filter);
}
}
void _tree_gen(proc_info& cur_proc, vector<proc_info>& in_procs, vector<tree_proc>& out_procs, void _tree_gen(proc_info& cur_proc, vector<proc_info>& in_procs, vector<tree_proc>& out_procs,
int cur_depth, bool collapsed, const string& filter, bool found, bool no_update, bool should_filter) { int cur_depth, bool collapsed, const string& filter, bool found, bool no_update, bool should_filter) {
auto cur_pos = out_procs.size(); auto cur_pos = out_procs.size();
@ -118,10 +136,7 @@ namespace Proc {
//? If filtering, include children of matching processes //? If filtering, include children of matching processes
if (not found and (should_filter or not filter.empty())) { if (not found and (should_filter or not filter.empty())) {
if (not s_contains(std::to_string(cur_proc.pid), filter) if (!matches_filter(cur_proc, filter)) {
and not s_contains_ic(cur_proc.name, filter)
and not s_contains_ic(cur_proc.cmd, filter)
and not s_contains_ic(cur_proc.user, filter)) {
filtering = true; filtering = true;
cur_proc.filtered = true; cur_proc.filtered = true;
filter_found++; filter_found++;

View file

@ -25,10 +25,19 @@ tab-size = 4
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#include <ifaddrs.h>
#include <unordered_map> #include <unordered_map>
#include <unistd.h> #include <unistd.h>
// From `man 3 getifaddrs`: <net/if.h> must be included before <ifaddrs.h>
// clang-format off
#include <net/if.h>
#include <ifaddrs.h>
// clang-format on
#if defined(__FreeBSD__) || defined(__OpenBSD__)
# include <kvm.h>
#endif
using std::array; using std::array;
using std::atomic; using std::atomic;
using std::deque; using std::deque;
@ -83,6 +92,15 @@ namespace Shared {
void init(); void init();
extern long coreCount, page_size, clk_tck; extern long coreCount, page_size, clk_tck;
#if defined(__FreeBSD__) || defined(__OpenBSD__)
struct KvmDeleter {
void operator()(kvm_t* handle) {
kvm_close(handle);
}
};
using KvmPtr = std::unique_ptr<kvm_t, KvmDeleter>;
#endif
} }
@ -178,7 +196,7 @@ namespace Cpu {
extern string cpuName, cpuHz; extern string cpuName, cpuHz;
extern vector<string> available_fields; extern vector<string> available_fields;
extern vector<string> available_sensors; extern vector<string> available_sensors;
extern tuple<int, long, string> current_bat; extern tuple<int, float, long, string> current_bat;
struct cpu_info { struct cpu_info {
std::unordered_map<string, deque<long long>> cpu_percent = { std::unordered_map<string, deque<long long>> cpu_percent = {
@ -213,7 +231,7 @@ namespace Cpu {
auto get_cpuHz() -> string; auto get_cpuHz() -> string;
//* Get battery info from /sys //* Get battery info from /sys
auto get_battery() -> tuple<int, long, string>; auto get_battery() -> tuple<int, float, long, string>;
} }
namespace Mem { namespace Mem {
@ -289,6 +307,17 @@ namespace Net {
bool connected{}; bool connected{};
}; };
class IfAddrsPtr {
struct ifaddrs* ifaddr;
int status;
public:
IfAddrsPtr() { status = getifaddrs(&ifaddr); }
~IfAddrsPtr() { freeifaddrs(ifaddr); }
[[nodiscard]] constexpr auto operator()() -> struct ifaddrs* { return ifaddr; }
[[nodiscard]] constexpr auto get() -> struct ifaddrs* { return ifaddr; }
[[nodiscard]] constexpr auto get_status() const noexcept -> int { return status; };
};
extern std::unordered_map<string, net_info> current_net; extern std::unordered_map<string, net_info> current_net;
//* Collect net upload/download stats //* Collect net upload/download stats
@ -395,6 +424,8 @@ namespace Proc {
void tree_sort(vector<tree_proc>& proc_vec, const string& sorting, void tree_sort(vector<tree_proc>& proc_vec, const string& sorting,
bool reverse, int& c_index, const int index_max, bool collapsed = false); bool reverse, int& c_index, const int index_max, bool collapsed = false);
bool matches_filter(const proc_info& proc, const std::string& filter);
//* Generate process tree list //* Generate process tree list
void _tree_gen(proc_info& cur_proc, vector<proc_info>& in_procs, vector<tree_proc>& out_procs, void _tree_gen(proc_info& cur_proc, vector<proc_info>& in_procs, vector<tree_proc>& out_procs,
int cur_depth, bool collapsed, const string& filter, int cur_depth, bool collapsed, const string& filter,

View file

@ -381,11 +381,16 @@ namespace Theme {
if (themefile.good()) { if (themefile.good()) {
Logger::debug("Loading theme file: " + filename); Logger::debug("Loading theme file: " + filename);
while (not themefile.bad()) { while (not themefile.bad()) {
if (themefile.peek() == '#') {
themefile.ignore(SSmax, '\n');
continue;
}
themefile.ignore(SSmax, '['); themefile.ignore(SSmax, '[');
if (themefile.eof()) break; if (themefile.eof()) break;
string name, value; string name, value;
getline(themefile, name, ']'); getline(themefile, name, ']');
if (not Default_theme.contains(name)) { if (not Default_theme.contains(name)) {
themefile.ignore(SSmax, '\n');
continue; continue;
} }
themefile.ignore(SSmax, '='); themefile.ignore(SSmax, '=');
@ -394,6 +399,7 @@ namespace Theme {
if (themefile.peek() == '"') { if (themefile.peek() == '"') {
themefile.ignore(1); themefile.ignore(1);
getline(themefile, value, '"'); getline(themefile, value, '"');
themefile.ignore(SSmax, '\n');
} }
else getline(themefile, value, '\n'); else getline(themefile, value, '\n');

View file

@ -32,7 +32,7 @@ namespace Theme {
extern std::filesystem::path theme_dir; extern std::filesystem::path theme_dir;
extern std::filesystem::path user_theme_dir; extern std::filesystem::path user_theme_dir;
//* Contains "Default" and "TTY" at indeces 0 and 1, otherwise full paths to theme files //* Contains "Default" and "TTY" at indices 0 and 1, otherwise full paths to theme files
extern vector<string> themes; extern vector<string> themes;
//* Generate escape sequence for 24-bit or 256 color and return as a string //* Generate escape sequence for 24-bit or 256 color and return as a string

View file

@ -89,7 +89,7 @@ namespace Term {
} }
bool refresh(bool only_check) { bool refresh(bool only_check) {
// Query dimensions of '/dev/tty' of the 'STDOUT_FILENO' isn't avaiable. // Query dimensions of '/dev/tty' of the 'STDOUT_FILENO' isn't available.
// This variable is set in those cases to avoid calls to ioctl // This variable is set in those cases to avoid calls to ioctl
constinit static bool uses_dev_tty = false; constinit static bool uses_dev_tty = false;
struct winsize wsize {}; struct winsize wsize {};
@ -644,7 +644,7 @@ namespace Logger {
size_t loglevel; size_t loglevel;
fs::path logfile; fs::path logfile;
//* Wrapper for lowering priviliges if using SUID bit and currently isn't using real userid //* Wrapper for lowering privileges if using SUID bit and currently isn't using real userid
class lose_priv { class lose_priv {
int status = -1; int status = -1;
public: public:

View file

@ -18,6 +18,10 @@ tab-size = 4
#pragma once #pragma once
#if !defined(NDEBUG)
# define BTOP_DEBUG
#endif
#include <algorithm> // for std::ranges::count_if #include <algorithm> // for std::ranges::count_if
#include <array> #include <array>
#include <atomic> #include <atomic>
@ -42,11 +46,9 @@ tab-size = 4
#define HOST_NAME_MAX 64 #define HOST_NAME_MAX 64
#endif #endif
#endif #endif
#define FMT_HEADER_ONLY
#include "fmt/core.h" #include "fmt/core.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "fmt/ostream.h"
#include "fmt/ranges.h"
using std::array; using std::array;
using std::atomic; using std::atomic;
@ -112,7 +114,7 @@ namespace Mv {
//* Save cursor position //* Save cursor position
const string save = Fx::e + "s"; const string save = Fx::e + "s";
//* Restore saved cursor postion //* Restore saved cursor position
const string restore = Fx::e + "u"; const string restore = Fx::e + "u";
} }
@ -284,7 +286,7 @@ namespace Tools {
return is_in(str, "true", "True"); return is_in(str, "true", "True");
} }
//* Check if a string is a valid integer value (only postive) //* Check if a string is a valid integer value (only positive)
inline bool isint(const string& str) { inline bool isint(const string& str) {
return all_of(str.begin(), str.end(), ::isdigit); return all_of(str.begin(), str.end(), ::isdigit);
} }

10
src/config.h.in Normal file
View file

@ -0,0 +1,10 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <string_view>
constexpr std::string_view GIT_COMMIT = "@GIT_COMMIT@";
constexpr std::string_view COMPILER = "@COMPILER@";
constexpr std::string_view COMPILER_VERSION = "@COMPILER_VERSION@";
constexpr std::string_view CONFIGURE_COMMAND = "@CONFIGURE_COMMAND@";

View file

@ -189,25 +189,13 @@ namespace Shared {
Logger::debug("Init -> Mem::get_zpools()"); Logger::debug("Init -> Mem::get_zpools()");
Mem::get_zpools(); Mem::get_zpools();
} }
//* RAII wrapper for kvm_openfiles
class kvm_openfiles_wrapper {
kvm_t* kd = nullptr;
public:
kvm_openfiles_wrapper(const char* execf, const char* coref, const char* swapf, int flags, char* err) {
this->kd = kvm_openfiles(execf, coref, swapf, flags, err);
}
~kvm_openfiles_wrapper() { kvm_close(kd); }
auto operator()() -> kvm_t* { return kd; }
};
} // namespace Shared } // namespace Shared
namespace Cpu { namespace Cpu {
string cpuName; string cpuName;
string cpuHz; string cpuHz;
bool has_battery = true; bool has_battery = true;
tuple<int, long, string> current_bat; tuple<int, float, long, string> current_bat;
const array<string, 10> time_names = {"user", "nice", "system", "idle"}; const array<string, 10> time_names = {"user", "nice", "system", "idle"};
@ -277,7 +265,7 @@ namespace Cpu {
got_sensors = true; got_sensors = true;
int temp; int temp;
size_t size = sizeof(temp); size_t size = sizeof(temp);
sysctlbyname("dev.cpu.0.coretemp.tjmax", &temp, &size, nullptr, 0); //asuming the max temp is same for all cores sysctlbyname("dev.cpu.0.coretemp.tjmax", &temp, &size, nullptr, 0); //assuming the max temp is same for all cores
temp = (temp - 2732) / 10; // since it's an int, it's multiplied by 10, and offset to absolute zero... temp = (temp - 2732) / 10; // since it's an int, it's multiplied by 10, and offset to absolute zero...
current_cpu.temp_max = temp; current_cpu.temp_max = temp;
} }
@ -373,10 +361,11 @@ namespace Cpu {
return core_map; return core_map;
} }
auto get_battery() -> tuple<int, long, string> { auto get_battery() -> tuple<int, float, long, string> {
if (not has_battery) return {0, 0, ""}; if (not has_battery) return {0, 0, 0, ""};
long seconds = -1; long seconds = -1;
float watts = -1;
uint32_t percent = -1; uint32_t percent = -1;
size_t size = sizeof(percent); size_t size = sizeof(percent);
string status = "discharging"; string status = "discharging";
@ -388,6 +377,10 @@ namespace Cpu {
if (sysctlbyname("hw.acpi.battery.time", &seconds, &size, nullptr, 0) < 0) { if (sysctlbyname("hw.acpi.battery.time", &seconds, &size, nullptr, 0) < 0) {
seconds = 0; seconds = 0;
} }
size = sizeof(watts);
if (sysctlbyname("hw.acpi.battery.rate", &watts, &size, nullptr, 0) < 0) {
watts = -1;
}
int state; int state;
size = sizeof(state); size = sizeof(state);
if (sysctlbyname("hw.acpi.battery.state", &state, &size, nullptr, 0) < 0) { if (sysctlbyname("hw.acpi.battery.state", &state, &size, nullptr, 0) < 0) {
@ -402,7 +395,7 @@ namespace Cpu {
} }
} }
return {percent, seconds, status}; return {percent, watts, seconds, status};
} }
auto collect(bool no_update) -> cpu_info & { auto collect(bool no_update) -> cpu_info & {
@ -668,9 +661,9 @@ namespace Mem {
if (show_swap) { if (show_swap) {
char buf[_POSIX2_LINE_MAX]; char buf[_POSIX2_LINE_MAX];
Shared::kvm_openfiles_wrapper kd(nullptr, _PATH_DEVNULL, nullptr, O_RDONLY, buf); Shared::KvmPtr kd {kvm_openfiles(nullptr, _PATH_DEVNULL, nullptr, O_RDONLY, buf)};
struct kvm_swap swap[16]; struct kvm_swap swap[16];
int nswap = kvm_getswapinfo(kd(), swap, 16, 0); int nswap = kvm_getswapinfo(kd.get(), swap, 16, 0);
int totalSwap = 0, usedSwap = 0; int totalSwap = 0, usedSwap = 0;
for (int i = 0; i < nswap; i++) { for (int i = 0; i < nswap; i++) {
totalSwap += swap[i].ksw_total; totalSwap += swap[i].ksw_total;
@ -823,17 +816,6 @@ namespace Net {
bool rescale = true; bool rescale = true;
uint64_t timestamp = 0; uint64_t timestamp = 0;
//* RAII wrapper for getifaddrs
class getifaddr_wrapper {
struct ifaddrs *ifaddr;
public:
int status;
getifaddr_wrapper() { status = getifaddrs(&ifaddr); }
~getifaddr_wrapper() { freeifaddrs(ifaddr); }
auto operator()() -> struct ifaddrs * { return ifaddr; }
};
auto collect(bool no_update) -> net_info & { auto collect(bool no_update) -> net_info & {
auto &net = current_net; auto &net = current_net;
auto &config_iface = Config::getS("net_iface"); auto &config_iface = Config::getS("net_iface");
@ -843,10 +825,10 @@ namespace Net {
if (not no_update and errors < 3) { if (not no_update and errors < 3) {
//? Get interface list using getifaddrs() wrapper //? Get interface list using getifaddrs() wrapper
getifaddr_wrapper if_wrap{}; IfAddrsPtr if_addrs {};
if (if_wrap.status != 0) { if (if_addrs.get_status() != 0) {
errors++; errors++;
Logger::error("Net::collect() -> getifaddrs() failed with id " + to_string(if_wrap.status)); Logger::error("Net::collect() -> getifaddrs() failed with id " + to_string(if_addrs.get_status()));
redraw = true; redraw = true;
return empty_net; return empty_net;
} }
@ -858,7 +840,7 @@ namespace Net {
string ipv4, ipv6; string ipv4, ipv6;
//? Iteration over all items in getifaddrs() list //? Iteration over all items in getifaddrs() list
for (auto *ifa = if_wrap(); ifa != nullptr; ifa = ifa->ifa_next) { for (auto *ifa = if_addrs.get(); ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) continue; if (ifa->ifa_addr == nullptr) continue;
family = ifa->ifa_addr->sa_family; family = ifa->ifa_addr->sa_family;
const auto &iface = ifa->ifa_name; const auto &iface = ifa->ifa_name;
@ -925,7 +907,7 @@ namespace Net {
} }
} }
//? Get total recieved and transmitted bytes + device address if no ip was found //? Get total received and transmitted bytes + device address if no ip was found
for (const auto &iface : interfaces) { for (const auto &iface : interfaces) {
for (const string dir : {"download", "upload"}) { for (const string dir : {"download", "upload"}) {
auto &saved_stat = net.at(iface).stat.at(dir); auto &saved_stat = net.at(iface).stat.at(dir);
@ -1164,8 +1146,8 @@ namespace Proc {
int count = 0; int count = 0;
char buf[_POSIX2_LINE_MAX]; char buf[_POSIX2_LINE_MAX];
Shared::kvm_openfiles_wrapper kd(nullptr, _PATH_DEVNULL, nullptr, O_RDONLY, buf); Shared::KvmPtr kd {kvm_openfiles(nullptr, _PATH_DEVNULL, nullptr, O_RDONLY, buf)};
const struct kinfo_proc* kprocs = kvm_getprocs(kd(), KERN_PROC_PROC, 0, &count); const struct kinfo_proc* kprocs = kvm_getprocs(kd.get(), KERN_PROC_PROC, 0, &count);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
const struct kinfo_proc* kproc = &kprocs[i]; const struct kinfo_proc* kproc = &kprocs[i];
@ -1192,7 +1174,7 @@ namespace Proc {
continue; continue;
} }
new_proc.name = kproc->ki_comm; new_proc.name = kproc->ki_comm;
char** argv = kvm_getargv(kd(), kproc, 0); char** argv = kvm_getargv(kd.get(), kproc, 0);
if (argv) { if (argv) {
for (int i = 0; argv[i] and cmp_less(new_proc.cmd.size(), 1000); i++) { for (int i = 0; argv[i] and cmp_less(new_proc.cmd.size(), 1000); i++) {
new_proc.cmd += argv[i] + " "s; new_proc.cmd += argv[i] + " "s;
@ -1257,18 +1239,13 @@ namespace Proc {
filter_found = 0; filter_found = 0;
for (auto& p : current_procs) { for (auto& p : current_procs) {
if (not tree and not filter.empty()) { if (not tree and not filter.empty()) {
if (not s_contains_ic(to_string(p.pid), filter) if (!matches_filter(p, filter)) {
and not s_contains_ic(p.name, filter) p.filtered = true;
and not s_contains_ic(p.cmd, filter) filter_found++;
and not s_contains_ic(p.user, filter)) { } else {
p.filtered = true; p.filtered = false;
filter_found++;
}
else {
p.filtered = false;
}
} }
else { } else {
p.filtered = false; p.filtered = false;
} }
} }

View file

@ -158,39 +158,49 @@ namespace Gpu {
//? AMD data collection //? AMD data collection
namespace Rsmi { namespace Rsmi {
//? RSMI defines, structs & typedefs
#define RSMI_DEVICE_NAME_BUFFER_SIZE 128
#if !defined(RSMI_STATIC) #if !defined(RSMI_STATIC)
//? RSMI defines, structs & typedefs #define RSMI_MAX_NUM_FREQUENCIES_V5 32
#define RSMI_MAX_NUM_FREQUENCIES 32 #define RSMI_MAX_NUM_FREQUENCIES_V6 33
#define RSMI_STATUS_SUCCESS 0 #define RSMI_STATUS_SUCCESS 0
#define RSMI_MEM_TYPE_VRAM 0 #define RSMI_MEM_TYPE_VRAM 0
#define RSMI_TEMP_CURRENT 0 #define RSMI_TEMP_CURRENT 0
#define RSMI_TEMP_TYPE_EDGE 0 #define RSMI_TEMP_TYPE_EDGE 0
#define RSMI_CLK_TYPE_MEM 4 #define RSMI_CLK_TYPE_MEM 4
#define RSMI_CLK_TYPE_SYS 0 #define RSMI_CLK_TYPE_SYS 0
#define RSMI_TEMP_MAX 1 #define RSMI_TEMP_MAX 1
typedef int rsmi_status_t, typedef int rsmi_status_t,
rsmi_temperature_metric_t, rsmi_temperature_metric_t,
rsmi_clk_type_t, rsmi_clk_type_t,
rsmi_memory_type_t; rsmi_memory_type_t;
struct rsmi_frequencies_t {uint32_t num_supported, current, frequency[RSMI_MAX_NUM_FREQUENCIES];}; struct rsmi_version_t {uint32_t major, minor, patch; const char* build;};
struct rsmi_frequencies_t_v5 {uint32_t num_supported, current; uint64_t frequency[RSMI_MAX_NUM_FREQUENCIES_V5];};
struct rsmi_frequencies_t_v6 {bool has_deep_sleep; uint32_t num_supported, current; uint64_t frequency[RSMI_MAX_NUM_FREQUENCIES_V6];};
//? Function pointers //? Function pointers
rsmi_status_t (*rsmi_init)(uint64_t); rsmi_status_t (*rsmi_init)(uint64_t);
rsmi_status_t (*rsmi_shut_down)(); rsmi_status_t (*rsmi_shut_down)();
rsmi_status_t (*rsmi_version_get)(rsmi_version_t*);
rsmi_status_t (*rsmi_num_monitor_devices)(uint32_t*); rsmi_status_t (*rsmi_num_monitor_devices)(uint32_t*);
rsmi_status_t (*rsmi_dev_name_get)(uint32_t, char*, size_t); rsmi_status_t (*rsmi_dev_name_get)(uint32_t, char*, size_t);
rsmi_status_t (*rsmi_dev_power_cap_get)(uint32_t, uint32_t, uint64_t*); rsmi_status_t (*rsmi_dev_power_cap_get)(uint32_t, uint32_t, uint64_t*);
rsmi_status_t (*rsmi_dev_temp_metric_get)(uint32_t, uint32_t, rsmi_temperature_metric_t, int64_t*); rsmi_status_t (*rsmi_dev_temp_metric_get)(uint32_t, uint32_t, rsmi_temperature_metric_t, int64_t*);
rsmi_status_t (*rsmi_dev_busy_percent_get)(uint32_t, uint32_t*); rsmi_status_t (*rsmi_dev_busy_percent_get)(uint32_t, uint32_t*);
rsmi_status_t (*rsmi_dev_memory_busy_percent_get)(uint32_t, uint32_t*); rsmi_status_t (*rsmi_dev_memory_busy_percent_get)(uint32_t, uint32_t*);
rsmi_status_t (*rsmi_dev_gpu_clk_freq_get)(uint32_t, rsmi_clk_type_t, rsmi_frequencies_t*); rsmi_status_t (*rsmi_dev_gpu_clk_freq_get_v5)(uint32_t, rsmi_clk_type_t, rsmi_frequencies_t_v5*);
rsmi_status_t (*rsmi_dev_gpu_clk_freq_get_v6)(uint32_t, rsmi_clk_type_t, rsmi_frequencies_t_v6*);
rsmi_status_t (*rsmi_dev_power_ave_get)(uint32_t, uint32_t, uint64_t*); rsmi_status_t (*rsmi_dev_power_ave_get)(uint32_t, uint32_t, uint64_t*);
rsmi_status_t (*rsmi_dev_memory_total_get)(uint32_t, rsmi_memory_type_t, uint64_t*); rsmi_status_t (*rsmi_dev_memory_total_get)(uint32_t, rsmi_memory_type_t, uint64_t*);
rsmi_status_t (*rsmi_dev_memory_usage_get)(uint32_t, rsmi_memory_type_t, uint64_t*); rsmi_status_t (*rsmi_dev_memory_usage_get)(uint32_t, rsmi_memory_type_t, uint64_t*);
rsmi_status_t (*rsmi_dev_pci_throughput_get)(uint32_t, uint64_t*, uint64_t*, uint64_t*); rsmi_status_t (*rsmi_dev_pci_throughput_get)(uint32_t, uint64_t*, uint64_t*, uint64_t*);
uint32_t version_major = 0;
//? Data //? Data
void* rsmi_dl_handle; void* rsmi_dl_handle;
#endif #endif
@ -294,7 +304,7 @@ namespace Cpu {
string cpuName; string cpuName;
string cpuHz; string cpuHz;
bool has_battery = true; bool has_battery = true;
tuple<int, long, string> current_bat; tuple<int, float, long, string> current_bat;
const array time_names { const array time_names {
"user"s, "nice"s, "system"s, "idle"s, "iowait"s, "user"s, "nice"s, "system"s, "idle"s, "iowait"s,
@ -438,7 +448,7 @@ namespace Cpu {
const int file_id = atoi(file.path().filename().c_str() + 4); // skip "temp" prefix const int file_id = atoi(file.path().filename().c_str() + 4); // skip "temp" prefix
string file_path = file.path(); string file_path = file.path();
if (!s_contains(file_path, file_suffix)) { if (!s_contains(file_path, file_suffix) or s_contains(file_path, "nvme")) {
continue; continue;
} }
@ -583,7 +593,7 @@ namespace Cpu {
cpuhz += " GHz"; cpuhz += " GHz";
} }
else if (hz > 0) else if (hz > 0)
cpuhz = to_string((int)round(hz)) + " MHz"; cpuhz = to_string((int)hz) + " MHz";
} }
catch (const std::exception& e) { catch (const std::exception& e) {
@ -664,13 +674,14 @@ namespace Cpu {
} }
struct battery { struct battery {
fs::path base_dir, energy_now, energy_full, power_now, status, online; fs::path base_dir, energy_now, charge_now, energy_full, charge_full, power_now, current_now, voltage_now, status, online;
string device_type; string device_type;
bool use_energy = true; bool use_energy_or_charge = true;
bool use_power = true;
}; };
auto get_battery() -> tuple<int, long, string> { auto get_battery() -> tuple<int, float, long, string> {
if (not has_battery) return {0, 0, ""}; if (not has_battery) return {0, 0, 0, ""};
static string auto_sel; static string auto_sel;
static std::unordered_map<string, battery> batteries; static std::unordered_map<string, battery> batteries;
@ -702,19 +713,27 @@ namespace Cpu {
} }
if (fs::exists(bat_dir / "energy_now")) new_bat.energy_now = bat_dir / "energy_now"; if (fs::exists(bat_dir / "energy_now")) new_bat.energy_now = bat_dir / "energy_now";
else if (fs::exists(bat_dir / "charge_now")) new_bat.energy_now = bat_dir / "charge_now"; else if (fs::exists(bat_dir / "charge_now")) new_bat.charge_now = bat_dir / "charge_now";
else new_bat.use_energy = false; else new_bat.use_energy_or_charge = false;
if (fs::exists(bat_dir / "energy_full")) new_bat.energy_full = bat_dir / "energy_full"; if (fs::exists(bat_dir / "energy_full")) new_bat.energy_full = bat_dir / "energy_full";
else if (fs::exists(bat_dir / "charge_full")) new_bat.energy_full = bat_dir / "charge_full"; else if (fs::exists(bat_dir / "charge_full")) new_bat.charge_full = bat_dir / "charge_full";
else new_bat.use_energy = false; else new_bat.use_energy_or_charge = false;
if (not new_bat.use_energy and not fs::exists(bat_dir / "capacity")) { if (not new_bat.use_energy_or_charge and not fs::exists(bat_dir / "capacity")) {
continue; continue;
} }
if (fs::exists(bat_dir / "power_now")) new_bat.power_now = bat_dir / "power_now"; if (fs::exists(bat_dir / "power_now")) {
else if (fs::exists(bat_dir / "current_now")) new_bat.power_now = bat_dir / "current_now"; new_bat.power_now = bat_dir / "power_now";
}
else if ((fs::exists(bat_dir / "current_now")) and (fs::exists(bat_dir / "voltage_now"))) {
new_bat.current_now = bat_dir / "current_now";
new_bat.voltage_now = bat_dir / "voltage_now";
}
else {
new_bat.use_power = false;
}
if (fs::exists(bat_dir / "AC0/online")) new_bat.online = bat_dir / "AC0/online"; if (fs::exists(bat_dir / "AC0/online")) new_bat.online = bat_dir / "AC0/online";
else if (fs::exists(bat_dir / "AC/online")) new_bat.online = bat_dir / "AC/online"; else if (fs::exists(bat_dir / "AC/online")) new_bat.online = bat_dir / "AC/online";
@ -729,7 +748,7 @@ namespace Cpu {
} }
if (batteries.empty()) { if (batteries.empty()) {
has_battery = false; has_battery = false;
return {0, 0, ""}; return {0, 0, 0, ""};
} }
} }
@ -749,15 +768,9 @@ namespace Cpu {
int percent = -1; int percent = -1;
long seconds = -1; long seconds = -1;
float watts = -1;
//? Try to get battery percentage //? Try to get battery percentage
if (b.use_energy) {
try {
percent = round(100.0 * stoll(readfile(b.energy_now, "-1")) / stoll(readfile(b.energy_full, "1")));
}
catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { }
}
if (percent < 0) { if (percent < 0) {
try { try {
percent = stoll(readfile(b.base_dir / "capacity", "-1")); percent = stoll(readfile(b.base_dir / "capacity", "-1"));
@ -765,9 +778,23 @@ namespace Cpu {
catch (const std::invalid_argument&) { } catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { } catch (const std::out_of_range&) { }
} }
if (b.use_energy_or_charge and percent < 0) {
try {
percent = round(100.0 * stoll(readfile(b.energy_now, "-1")) / stoll(readfile(b.energy_full, "1")));
}
catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { }
}
if (b.use_energy_or_charge and percent < 0) {
try {
percent = round(100.0 * stoll(readfile(b.charge_now, "-1")) / stoll(readfile(b.charge_full, "1")));
}
catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { }
}
if (percent < 0) { if (percent < 0) {
has_battery = false; has_battery = false;
return {0, 0, ""}; return {0, 0, 0, ""};
} }
//? Get charging/discharging status //? Get charging/discharging status
@ -781,13 +808,23 @@ namespace Cpu {
//? Get seconds to empty //? Get seconds to empty
if (not is_in(status, "charging", "full")) { if (not is_in(status, "charging", "full")) {
if (b.use_energy and not b.power_now.empty()) { if (b.use_energy_or_charge ) {
try { if (not b.power_now.empty()) {
seconds = round((double)stoll(readfile(b.energy_now, "0")) / stoll(readfile(b.power_now, "1")) * 3600); try {
seconds = round((double)stoll(readfile(b.energy_now, "0")) / stoll(readfile(b.power_now, "1")) * 3600);
}
catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { }
}
else if (not b.current_now.empty()) {
try {
seconds = round((double)stoll(readfile(b.charge_now, "0")) / (double)stoll(readfile(b.current_now, "1")) * 3600);
}
catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { }
} }
catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { }
} }
if (seconds < 0 and fs::exists(b.base_dir / "time_to_empty")) { if (seconds < 0 and fs::exists(b.base_dir / "time_to_empty")) {
try { try {
seconds = stoll(readfile(b.base_dir / "time_to_empty", "0")) * 60; seconds = stoll(readfile(b.base_dir / "time_to_empty", "0")) * 60;
@ -797,7 +834,26 @@ namespace Cpu {
} }
} }
return {percent, seconds, status}; //? Get power draw
if (b.use_power) {
if (not b.power_now.empty()) {
try {
watts = (float)stoll(readfile(b.power_now, "-1")) / 1000000.0;
}
catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { }
}
else if (not b.voltage_now.empty() and not b.current_now.empty()) {
try {
watts = (float)stoll(readfile(b.current_now, "-1")) / 1000000.0 * stoll(readfile(b.voltage_now, "1")) / 1000000.0;
}
catch (const std::invalid_argument&) { }
catch (const std::out_of_range&) { }
}
}
return {percent, watts, seconds, status};
} }
auto collect(bool no_update) -> cpu_info& { auto collect(bool no_update) -> cpu_info& {
@ -1232,6 +1288,7 @@ namespace Gpu {
"librocm_smi64.so", "librocm_smi64.so",
"librocm_smi64.so.5", // fedora "librocm_smi64.so.5", // fedora
"librocm_smi64.so.1.0", // debian "librocm_smi64.so.1.0", // debian
"librocm_smi64.so.6"
}; };
for (const auto& l : libRocAlts) { for (const auto& l : libRocAlts) {
@ -1259,13 +1316,13 @@ namespace Gpu {
LOAD_SYM(rsmi_init); LOAD_SYM(rsmi_init);
LOAD_SYM(rsmi_shut_down); LOAD_SYM(rsmi_shut_down);
LOAD_SYM(rsmi_version_get);
LOAD_SYM(rsmi_num_monitor_devices); LOAD_SYM(rsmi_num_monitor_devices);
LOAD_SYM(rsmi_dev_name_get); LOAD_SYM(rsmi_dev_name_get);
LOAD_SYM(rsmi_dev_power_cap_get); LOAD_SYM(rsmi_dev_power_cap_get);
LOAD_SYM(rsmi_dev_temp_metric_get); LOAD_SYM(rsmi_dev_temp_metric_get);
LOAD_SYM(rsmi_dev_busy_percent_get); LOAD_SYM(rsmi_dev_busy_percent_get);
LOAD_SYM(rsmi_dev_memory_busy_percent_get); LOAD_SYM(rsmi_dev_memory_busy_percent_get);
LOAD_SYM(rsmi_dev_gpu_clk_freq_get);
LOAD_SYM(rsmi_dev_power_ave_get); LOAD_SYM(rsmi_dev_power_ave_get);
LOAD_SYM(rsmi_dev_memory_total_get); LOAD_SYM(rsmi_dev_memory_total_get);
LOAD_SYM(rsmi_dev_memory_usage_get); LOAD_SYM(rsmi_dev_memory_usage_get);
@ -1281,6 +1338,27 @@ namespace Gpu {
return false; return false;
} }
#if !defined(RSMI_STATIC)
//? Check version
rsmi_version_t version;
result = rsmi_version_get(&version);
if (result != RSMI_STATUS_SUCCESS) {
Logger::warning("ROCm SMI: Failed to get version");
return false;
} else if (version.major == 5) {
if ((rsmi_dev_gpu_clk_freq_get_v5 = (decltype(rsmi_dev_gpu_clk_freq_get_v5))load_rsmi_sym("rsmi_dev_gpu_clk_freq_get")) == nullptr)
return false;
// In the release tarballs of rocm 6.0.0 and 6.0.2 the version queried with rsmi_version_get is 7.0.0.0
} else if (version.major == 6 || version.major == 7) {
if ((rsmi_dev_gpu_clk_freq_get_v6 = (decltype(rsmi_dev_gpu_clk_freq_get_v6))load_rsmi_sym("rsmi_dev_gpu_clk_freq_get")) == nullptr)
return false;
} else {
Logger::warning("ROCm SMI: Dynamic loading only supported for version 5 and 6");
return false;
}
version_major = version.major;
#endif
//? Device count //? Device count
result = rsmi_num_monitor_devices(&device_count); result = rsmi_num_monitor_devices(&device_count);
if (result != RSMI_STATUS_SUCCESS) { if (result != RSMI_STATUS_SUCCESS) {
@ -1321,8 +1399,8 @@ namespace Gpu {
for (uint32_t i = 0; i < device_count; ++i) { for (uint32_t i = 0; i < device_count; ++i) {
if constexpr(is_init) { if constexpr(is_init) {
//? Device name //? Device name
char name[NVML_DEVICE_NAME_BUFFER_SIZE]; // ROCm SMI does not provide a constant for this as far as I can tell, this should be good enough char name[RSMI_DEVICE_NAME_BUFFER_SIZE];
result = rsmi_dev_name_get(i, name, NVML_DEVICE_NAME_BUFFER_SIZE); result = rsmi_dev_name_get(i, name, RSMI_DEVICE_NAME_BUFFER_SIZE);
if (result != RSMI_STATUS_SUCCESS) if (result != RSMI_STATUS_SUCCESS)
Logger::warning("ROCm SMI: Failed to get device name"); Logger::warning("ROCm SMI: Failed to get device name");
else gpu_names[Nvml::device_count + i] = string(name); else gpu_names[Nvml::device_count + i] = string(name);
@ -1364,7 +1442,46 @@ namespace Gpu {
if constexpr(is_init) gpus_slice[i].supported_functions.mem_utilization = false; if constexpr(is_init) gpus_slice[i].supported_functions.mem_utilization = false;
} else gpus_slice[i].mem_utilization_percent.push_back((long long)utilization); } else gpus_slice[i].mem_utilization_percent.push_back((long long)utilization);
} }
#if !defined(RSMI_STATIC)
//? Clock speeds
if (gpus_slice[i].supported_functions.gpu_clock) {
if (version_major == 5) {
rsmi_frequencies_t_v5 frequencies;
result = rsmi_dev_gpu_clk_freq_get_v5(i, RSMI_CLK_TYPE_SYS, &frequencies);
if (result != RSMI_STATUS_SUCCESS) {
Logger::warning("ROCm SMI: Failed to get GPU clock speed: ");
if constexpr(is_init) gpus_slice[i].supported_functions.gpu_clock = false;
} else gpus_slice[i].gpu_clock_speed = (long long)frequencies.frequency[frequencies.current]/1000000; // Hz to MHz
}
else if (version_major == 6 || version_major == 7) {
rsmi_frequencies_t_v6 frequencies;
result = rsmi_dev_gpu_clk_freq_get_v6(i, RSMI_CLK_TYPE_SYS, &frequencies);
if (result != RSMI_STATUS_SUCCESS) {
Logger::warning("ROCm SMI: Failed to get GPU clock speed: ");
if constexpr(is_init) gpus_slice[i].supported_functions.gpu_clock = false;
} else gpus_slice[i].gpu_clock_speed = (long long)frequencies.frequency[frequencies.current]/1000000; // Hz to MHz
}
}
if (gpus_slice[i].supported_functions.mem_clock) {
if (version_major == 5) {
rsmi_frequencies_t_v5 frequencies;
result = rsmi_dev_gpu_clk_freq_get_v5(i, RSMI_CLK_TYPE_MEM, &frequencies);
if (result != RSMI_STATUS_SUCCESS) {
Logger::warning("ROCm SMI: Failed to get VRAM clock speed: ");
if constexpr(is_init) gpus_slice[i].supported_functions.mem_clock = false;
} else gpus_slice[i].mem_clock_speed = (long long)frequencies.frequency[frequencies.current]/1000000; // Hz to MHz
}
else if (version_major == 6 || version_major == 7) {
rsmi_frequencies_t_v6 frequencies;
result = rsmi_dev_gpu_clk_freq_get_v6(i, RSMI_CLK_TYPE_MEM, &frequencies);
if (result != RSMI_STATUS_SUCCESS) {
Logger::warning("ROCm SMI: Failed to get VRAM clock speed: ");
if constexpr(is_init) gpus_slice[i].supported_functions.mem_clock = false;
} else gpus_slice[i].mem_clock_speed = (long long)frequencies.frequency[frequencies.current]/1000000; // Hz to MHz
}
}
#else
//? Clock speeds //? Clock speeds
if (gpus_slice[i].supported_functions.gpu_clock) { if (gpus_slice[i].supported_functions.gpu_clock) {
rsmi_frequencies_t frequencies; rsmi_frequencies_t frequencies;
@ -1383,6 +1500,7 @@ namespace Gpu {
if constexpr(is_init) gpus_slice[i].supported_functions.mem_clock = false; if constexpr(is_init) gpus_slice[i].supported_functions.mem_clock = false;
} else gpus_slice[i].mem_clock_speed = (long long)frequencies.frequency[frequencies.current]/1000000; // Hz to MHz } else gpus_slice[i].mem_clock_speed = (long long)frequencies.frequency[frequencies.current]/1000000; // Hz to MHz
} }
#endif
//? Power usage & state //? Power usage & state
if (gpus_slice[i].supported_functions.pwr_usage) { if (gpus_slice[i].supported_functions.pwr_usage) {
@ -1391,7 +1509,10 @@ namespace Gpu {
if (result != RSMI_STATUS_SUCCESS) { if (result != RSMI_STATUS_SUCCESS) {
Logger::warning("ROCm SMI: Failed to get GPU power usage"); Logger::warning("ROCm SMI: Failed to get GPU power usage");
if constexpr(is_init) gpus_slice[i].supported_functions.pwr_usage = false; if constexpr(is_init) gpus_slice[i].supported_functions.pwr_usage = false;
} else gpus_slice[i].gpu_percent.at("gpu-pwr-totals").push_back(clamp((long long)round((double)gpus_slice[i].pwr_usage * 100.0 / (double)gpus_slice[i].pwr_max_usage), 0ll, 100ll)); } else {
gpus_slice[i].pwr_usage = (long long)power / 1000;
gpus_slice[i].gpu_percent.at("gpu-pwr-totals").push_back(clamp((long long)round((double)gpus_slice[i].pwr_usage * 100.0 / (double)gpus_slice[i].pwr_max_usage), 0ll, 100ll));
}
if constexpr(is_init) gpus_slice[i].supported_functions.pwr_state = false; if constexpr(is_init) gpus_slice[i].supported_functions.pwr_state = false;
} }
@ -1946,7 +2067,7 @@ namespace Mem {
if (access(zfs_pool_stat_path.c_str(), R_OK) == 0) { if (access(zfs_pool_stat_path.c_str(), R_OK) == 0) {
return zfs_pool_stat_path; return zfs_pool_stat_path;
} else { } else {
Logger::debug("Cant access folder: " + zfs_pool_stat_path.string()); Logger::debug("Can't access folder: " + zfs_pool_stat_path.string());
return ""; return "";
} }
} }
@ -2084,16 +2205,6 @@ namespace Net {
bool rescale{true}; bool rescale{true};
uint64_t timestamp{}; uint64_t timestamp{};
//* RAII wrapper for getifaddrs
class getifaddr_wrapper {
struct ifaddrs* ifaddr;
public:
int status;
getifaddr_wrapper() { status = getifaddrs(&ifaddr); }
~getifaddr_wrapper() { freeifaddrs(ifaddr); }
auto operator()() -> struct ifaddrs* { return ifaddr; }
};
auto collect(bool no_update) -> net_info& { auto collect(bool no_update) -> net_info& {
if (Runner::stopping) return empty_net; if (Runner::stopping) return empty_net;
auto& net = current_net; auto& net = current_net;
@ -2104,10 +2215,10 @@ namespace Net {
if (not no_update and errors < 3) { if (not no_update and errors < 3) {
//? Get interface list using getifaddrs() wrapper //? Get interface list using getifaddrs() wrapper
getifaddr_wrapper if_wrap {}; IfAddrsPtr if_addrs {};
if (if_wrap.status != 0) { if (if_addrs.get_status() != 0) {
errors++; errors++;
Logger::error("Net::collect() -> getifaddrs() failed with id " + to_string(if_wrap.status)); Logger::error("Net::collect() -> getifaddrs() failed with id " + to_string(if_addrs.get_status()));
redraw = true; redraw = true;
return empty_net; return empty_net;
} }
@ -2119,7 +2230,7 @@ namespace Net {
string ipv4, ipv6; string ipv4, ipv6;
//? Iteration over all items in getifaddrs() list //? Iteration over all items in getifaddrs() list
for (auto* ifa = if_wrap(); ifa != nullptr; ifa = ifa->ifa_next) { for (auto* ifa = if_addrs.get(); ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) continue; if (ifa->ifa_addr == nullptr) continue;
family = ifa->ifa_addr->sa_family; family = ifa->ifa_addr->sa_family;
const auto& iface = ifa->ifa_name; const auto& iface = ifa->ifa_name;
@ -2161,7 +2272,7 @@ namespace Net {
} //else, ignoring family==AF_PACKET (see man 3 getifaddrs) which is the first one in the `for` loop. } //else, ignoring family==AF_PACKET (see man 3 getifaddrs) which is the first one in the `for` loop.
} }
//? Get total recieved and transmitted bytes + device address if no ip was found //? Get total received and transmitted bytes + device address if no ip was found
for (const auto& iface : interfaces) { for (const auto& iface : interfaces) {
if (net.at(iface).ipv4.empty() and net.at(iface).ipv6.empty()) if (net.at(iface).ipv4.empty() and net.at(iface).ipv6.empty())
net.at(iface).ipv4 = readfile("/sys/class/net/" + iface + "/address"); net.at(iface).ipv4 = readfile("/sys/class/net/" + iface + "/address");
@ -2688,18 +2799,13 @@ namespace Proc {
filter_found = 0; filter_found = 0;
for (auto& p : current_procs) { for (auto& p : current_procs) {
if (not tree and not filter.empty()) { if (not tree and not filter.empty()) {
if (not s_contains_ic(to_string(p.pid), filter) if (!matches_filter(p, filter)) {
and not s_contains_ic(p.name, filter) p.filtered = true;
and not s_contains_ic(p.cmd, filter) filter_found++;
and not s_contains_ic(p.user, filter)) { } else {
p.filtered = true; p.filtered = false;
filter_found++;
}
else {
p.filtered = false;
}
} }
else { } else {
p.filtered = false; p.filtered = false;
} }
} }

View file

@ -184,25 +184,13 @@ namespace Shared {
Mem::old_uptime = system_uptime(); Mem::old_uptime = system_uptime();
Mem::collect(); Mem::collect();
} }
//* RAII wrapper for kvm_openfiles
class kvm_openfiles_wrapper {
kvm_t* kd = nullptr;
public:
kvm_openfiles_wrapper(const char* execf, const char* coref, const char* swapf, int flags, char* err) {
this->kd = kvm_openfiles(execf, coref, swapf, flags, err);
}
~kvm_openfiles_wrapper() { kvm_close(kd); }
auto operator()() -> kvm_t* { return kd; }
};
} // namespace Shared } // namespace Shared
namespace Cpu { namespace Cpu {
string cpuName; string cpuName;
string cpuHz; string cpuHz;
bool has_battery = true; bool has_battery = true;
tuple<int, long, string> current_bat; tuple<int, float, long, string> current_bat;
const array<string, 10> time_names = {"user", "nice", "system", "idle"}; const array<string, 10> time_names = {"user", "nice", "system", "idle"};
@ -385,8 +373,8 @@ namespace Cpu {
return core_map; return core_map;
} }
auto get_battery() -> tuple<int, long, string> { auto get_battery() -> tuple<int, float, long, string> {
if (not has_battery) return {0, 0, ""}; if (not has_battery) return {0, 0, 0, ""};
long seconds = -1; long seconds = -1;
uint32_t percent = -1; uint32_t percent = -1;
@ -417,7 +405,7 @@ namespace Cpu {
} }
} }
return {percent, seconds, status}; return {percent, -1, seconds, status};
} }
auto collect(bool no_update) -> cpu_info & { auto collect(bool no_update) -> cpu_info & {
@ -780,17 +768,6 @@ namespace Net {
bool rescale = true; bool rescale = true;
uint64_t timestamp = 0; uint64_t timestamp = 0;
//* RAII wrapper for getifaddrs
class getifaddr_wrapper {
struct ifaddrs *ifaddr;
public:
int status;
getifaddr_wrapper() { status = getifaddrs(&ifaddr); }
~getifaddr_wrapper() { freeifaddrs(ifaddr); }
auto operator()() -> struct ifaddrs * { return ifaddr; }
};
auto collect(bool no_update) -> net_info & { auto collect(bool no_update) -> net_info & {
auto &net = current_net; auto &net = current_net;
auto &config_iface = Config::getS("net_iface"); auto &config_iface = Config::getS("net_iface");
@ -800,10 +777,10 @@ namespace Net {
if (not no_update and errors < 3) { if (not no_update and errors < 3) {
//? Get interface list using getifaddrs() wrapper //? Get interface list using getifaddrs() wrapper
getifaddr_wrapper if_wrap{}; IfAddrsPtr if_addrs {};
if (if_wrap.status != 0) { if (if_addrs.get_status() != 0) {
errors++; errors++;
Logger::error("Net::collect() -> getifaddrs() failed with id " + to_string(if_wrap.status)); Logger::error("Net::collect() -> getifaddrs() failed with id " + to_string(if_addrs.get_status()));
redraw = true; redraw = true;
return empty_net; return empty_net;
} }
@ -815,7 +792,7 @@ namespace Net {
string ipv4, ipv6; string ipv4, ipv6;
//? Iteration over all items in getifaddrs() list //? Iteration over all items in getifaddrs() list
for (auto *ifa = if_wrap(); ifa != nullptr; ifa = ifa->ifa_next) { for (auto *ifa = if_addrs.get(); ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) continue; if (ifa->ifa_addr == nullptr) continue;
family = ifa->ifa_addr->sa_family; family = ifa->ifa_addr->sa_family;
const auto &iface = ifa->ifa_name; const auto &iface = ifa->ifa_name;
@ -882,7 +859,7 @@ namespace Net {
} }
} }
//? Get total recieved and transmitted bytes + device address if no ip was found //? Get total received and transmitted bytes + device address if no ip was found
for (const auto &iface : interfaces) { for (const auto &iface : interfaces) {
for (const string dir : {"download", "upload"}) { for (const string dir : {"download", "upload"}) {
auto &saved_stat = net.at(iface).stat.at(dir); auto &saved_stat = net.at(iface).stat.at(dir);
@ -1102,8 +1079,8 @@ namespace Proc {
int count = 0; int count = 0;
char buf[_POSIX2_LINE_MAX]; char buf[_POSIX2_LINE_MAX];
Shared::kvm_openfiles_wrapper kd(nullptr, nullptr, nullptr, KVM_NO_FILES, buf); Shared::KvmPtr kd {kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, buf)};
const struct kinfo_proc* kprocs = kvm_getprocs(kd(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count); const struct kinfo_proc* kprocs = kvm_getprocs(kd.get() , KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
const struct kinfo_proc* kproc = &kprocs[i]; const struct kinfo_proc* kproc = &kprocs[i];
@ -1130,7 +1107,7 @@ namespace Proc {
continue; continue;
} }
new_proc.name = kproc->p_comm; new_proc.name = kproc->p_comm;
char** argv = kvm_getargv(kd(), kproc, 0); char** argv = kvm_getargv(kd.get(), kproc, 0);
if (argv) { if (argv) {
for (int i = 0; argv[i] and cmp_less(new_proc.cmd.size(), 1000); i++) { for (int i = 0; argv[i] and cmp_less(new_proc.cmd.size(), 1000); i++) {
new_proc.cmd += argv[i] + " "s; new_proc.cmd += argv[i] + " "s;
@ -1194,18 +1171,13 @@ namespace Proc {
filter_found = 0; filter_found = 0;
for (auto& p : current_procs) { for (auto& p : current_procs) {
if (not tree and not filter.empty()) { if (not tree and not filter.empty()) {
if (not s_contains_ic(to_string(p.pid), filter) if (!matches_filter(p, filter)) {
and not s_contains_ic(p.name, filter) p.filtered = true;
and not s_contains_ic(p.cmd, filter) filter_found++;
and not s_contains_ic(p.user, filter)) { } else {
p.filtered = true; p.filtered = false;
filter_found++;
}
else {
p.filtered = false;
}
} }
else { } else {
p.filtered = false; p.filtered = false;
} }
} }

View file

@ -191,7 +191,7 @@ namespace Cpu {
string cpuHz; string cpuHz;
bool has_battery = true; bool has_battery = true;
bool macM1 = false; bool macM1 = false;
tuple<int, long, string> current_bat; tuple<int, float, long, string> current_bat;
const array<string, 10> time_names = {"user", "nice", "system", "idle"}; const array<string, 10> time_names = {"user", "nice", "system", "idle"};
@ -407,8 +407,8 @@ namespace Cpu {
~IOPSList_Wrap() { CFRelease(data); } ~IOPSList_Wrap() { CFRelease(data); }
}; };
auto get_battery() -> tuple<int, long, string> { auto get_battery() -> tuple<int, float, long, string> {
if (not has_battery) return {0, 0, ""}; if (not has_battery) return {0, 0, 0, ""};
uint32_t percent = -1; uint32_t percent = -1;
long seconds = -1; long seconds = -1;
@ -447,7 +447,7 @@ namespace Cpu {
has_battery = false; has_battery = false;
} }
} }
return {percent, seconds, status}; return {percent, -1, seconds, status};
} }
auto collect(bool no_update) -> cpu_info & { auto collect(bool no_update) -> cpu_info & {
@ -686,7 +686,7 @@ namespace Mem {
if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&p, &info_size) == 0) { if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&p, &info_size) == 0) {
mem.stats.at("free") = p.free_count * Shared::pageSize; mem.stats.at("free") = p.free_count * Shared::pageSize;
mem.stats.at("cached") = p.external_page_count * Shared::pageSize; mem.stats.at("cached") = p.external_page_count * Shared::pageSize;
mem.stats.at("used") = (p.active_count + p.inactive_count + p.wire_count) * Shared::pageSize; mem.stats.at("used") = (p.active_count + p.wire_count) * Shared::pageSize;
mem.stats.at("available") = Shared::totalMem - mem.stats.at("used"); mem.stats.at("available") = Shared::totalMem - mem.stats.at("used");
} }
@ -940,7 +940,7 @@ namespace Net {
} }
} }
//? Get total recieved and transmitted bytes + device address if no ip was found //? Get total received and transmitted bytes + device address if no ip was found
for (const auto &iface : interfaces) { for (const auto &iface : interfaces) {
for (const string dir : {"download", "upload"}) { for (const string dir : {"download", "upload"}) {
auto &saved_stat = net.at(iface).stat.at(dir); auto &saved_stat = net.at(iface).stat.at(dir);
@ -1212,10 +1212,14 @@ namespace Proc {
//? Get program name, command, username, parent pid, nice and status //? Get program name, command, username, parent pid, nice and status
if (no_cache) { if (no_cache) {
char fullname[PROC_PIDPATHINFO_MAXSIZE]; char fullname[PROC_PIDPATHINFO_MAXSIZE];
proc_pidpath(pid, fullname, sizeof(fullname)); int rc = proc_pidpath(pid, fullname, sizeof(fullname));
const string f_name = std::string(fullname); string f_name = "<defunct>";
size_t lastSlash = f_name.find_last_of('/'); if (rc != 0) {
new_proc.name = f_name.substr(lastSlash + 1); f_name = std::string(fullname);
size_t lastSlash = f_name.find_last_of('/');
f_name = f_name.substr(lastSlash + 1);
}
new_proc.name = f_name;
//? Get process arguments if possible, fallback to process path in case of failure //? Get process arguments if possible, fallback to process path in case of failure
if (Shared::arg_max > 0) { if (Shared::arg_max > 0) {
std::unique_ptr<char[]> proc_chars(new char[Shared::arg_max]); std::unique_ptr<char[]> proc_chars(new char[Shared::arg_max]);
@ -1245,7 +1249,11 @@ namespace Proc {
new_proc.ppid = kproc.kp_eproc.e_ppid; new_proc.ppid = kproc.kp_eproc.e_ppid;
new_proc.cpu_s = kproc.kp_proc.p_starttime.tv_sec * 1'000'000 + kproc.kp_proc.p_starttime.tv_usec; new_proc.cpu_s = kproc.kp_proc.p_starttime.tv_sec * 1'000'000 + kproc.kp_proc.p_starttime.tv_usec;
struct passwd *pwd = getpwuid(kproc.kp_eproc.e_ucred.cr_uid); struct passwd *pwd = getpwuid(kproc.kp_eproc.e_ucred.cr_uid);
new_proc.user = pwd->pw_name; if (pwd != nullptr) {
new_proc.user = pwd->pw_name;
} else {
new_proc.user = std::to_string(kproc.kp_eproc.e_ucred.cr_uid);
}
} }
new_proc.p_nice = kproc.kp_proc.p_nice; new_proc.p_nice = kproc.kp_proc.p_nice;
new_proc.state = kproc.kp_proc.p_stat; new_proc.state = kproc.kp_proc.p_stat;
@ -1297,7 +1305,7 @@ namespace Proc {
filter_found = 0; filter_found = 0;
for (auto &p : current_procs) { for (auto &p : current_procs) {
if (not tree and not filter.empty()) { if (not tree and not filter.empty()) {
if (not s_contains_ic(to_string(p.pid), filter) and not s_contains_ic(p.name, filter) and not s_contains_ic(p.cmd, filter) and not s_contains_ic(p.user, filter)) { if (!matches_filter(p, filter)) {
p.filtered = true; p.filtered = true;
filter_found++; filter_found++;
} else { } else {

View file

@ -18,7 +18,7 @@ theme[main_fg]="#cfd8dc"
# Title color for boxes # Title color for boxes
theme[title]="#ff" theme[title]="#ff"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#90" theme[hi_fg]="#90"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#2e3436"
# Title color for boxes # Title color for boxes
theme[title]="#2e3436" theme[title]="#2e3436"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#1a5fb4" theme[hi_fg]="#1a5fb4"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#99DFFF"
# Title color for boxes # Title color for boxes
theme[title]="#99FFFF" theme[title]="#99FFFF"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#FF7F00" theme[hi_fg]="#FF7F00"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -11,7 +11,7 @@ theme[main_fg]="#eee8d5"
# Title color for boxes # Title color for boxes
theme[title]="#eee8d5" theme[title]="#eee8d5"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#d1302c" theme[hi_fg]="#d1302c"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -0,0 +1,92 @@
# All graphs and meters can be gradients
# For single color graphs leave "mid" and "end" variable empty.
# Use "start" and "end" variables for two color gradient
# Use "start", "mid" and "end" for three color gradient
# Main background, empty for terminal default, need to be empty if you want transparent background
theme[main_bg]="#2d353b"
# Main text color
theme[main_fg]="#d3c6aa"
# Title color for boxes
theme[title]="#d3c6aa"
# Highlight color for keyboard shortcuts
theme[hi_fg]="#e67e80"
# Background color of selected items
theme[selected_bg]="#3d484d"
# Foreground color of selected items
theme[selected_fg]="#dbbc7f"
# Color of inactive/disabled text
theme[inactive_fg]="#2d353b"
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
theme[graph_text]="#d3c6aa"
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
theme[proc_misc]="#a7c080"
# Cpu box outline color
theme[cpu_box]="#3d484d"
# Memory/disks box outline color
theme[mem_box]="#3d484d"
# Net up/down box outline color
theme[net_box]="#3d484d"
# Processes box outline color
theme[proc_box]="#3d484d"
# Box divider line and small boxes line color
theme[div_line]="#3d484d"
# Temperature graph colors
theme[temp_start]="#a7c080"
theme[temp_mid]="#dbbc7f"
theme[temp_end]="#f85552"
# CPU graph colors
theme[cpu_start]="#a7c080"
theme[cpu_mid]="#dbbc7f"
theme[cpu_end]="#f85552"
# Mem/Disk free meter
theme[free_start]="#f85552"
theme[free_mid]="#dbbc7f"
theme[free_end]="#a7c080"
# Mem/Disk cached meter
theme[cached_start]="#7fbbb3"
theme[cached_mid]="#83c092"
theme[cached_end]="#a7c080"
# Mem/Disk available meter
theme[available_start]="#f85552"
theme[available_mid]="#dbbc7f"
theme[available_end]="#a7c080"
# Mem/Disk used meter
theme[used_start]="#a7c080"
theme[used_mid]="#dbbc7f"
theme[used_end]="#f85552"
# Download graph colors
theme[download_start]="#a7c080"
theme[download_mid]="#83c092"
theme[download_end]="#7fbbb3"
# Upload graph colors
theme[upload_start]="#dbbc7f"
theme[upload_mid]="#e69875"
theme[upload_end]="#e67e80"
# Process box color gradient for threads, mem and cpu usage
theme[process_start]="#a7c080"
theme[process_mid]="#e67e80"
theme[process_end]="#f85552"

View file

@ -18,7 +18,7 @@ theme[main_fg]="#737680"
# Title color for boxes # Title color for boxes
theme[title]="#272a34" theme[title]="#272a34"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#90" theme[hi_fg]="#90"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#E6E6E6"
# Title color for boxes # Title color for boxes
theme[title]="#ff" theme[title]="#ff"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#90" theme[hi_fg]="#90"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#bb"
# Title color for boxes # Title color for boxes
theme[title]="#cc" theme[title]="#cc"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#90" theme[hi_fg]="#90"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#a89984"
# Title color for boxes # Title color for boxes
theme[title]="#ebdbb2" theme[title]="#ebdbb2"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#d79921" theme[hi_fg]="#d79921"
# Background color of selected items # Background color of selected items

View file

@ -0,0 +1,89 @@
# Btop gruvbox_light theme
# by kk9uk
# Main background, empty for terminal default, need to be empty if you want transparent background
theme[main_bg]="#fbf1c7"
# Main text color
theme[main_fg]="#3c3836"
# Title color for boxes
theme[title]="#3c3836"
# Highlight color for keyboard shortcuts
theme[hi_fg]="#cc241d"
# Background color of selected items
theme[selected_bg]="#f2e5bc"
# Foreground color of selected items
theme[selected_fg]="#8f3f71"
# Color of inactive/disabled text
theme[inactive_fg]="#ebdbb2"
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
theme[graph_text]="#a89984"
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
theme[proc_misc]="#98971a"
# Cpu box outline color
theme[cpu_box]="#a89984"
# Memory/disks box outline color
theme[mem_box]="#a89984"
# Net up/down box outline color
theme[net_box]="#a89984"
# Processes box outline color
theme[proc_box]="#a89984"
# Box divider line and small boxes line color
theme[div_line]="#a89984"
# Temperature graph colors
theme[temp_start]="#98971a"
theme[temp_mid]=""
theme[temp_end]="#cc241d"
# CPU graph colors
theme[cpu_start]="#427b58"
theme[cpu_mid]="#d79921"
theme[cpu_end]="#cc241d"
# Mem/Disk free meter
theme[free_start]="#cc241d"
theme[free_mid]="#d79921"
theme[free_end]="#427b58"
# Mem/Disk cached meter
theme[cached_start]="#458588"
theme[cached_mid]="#076678"
theme[cached_end]="#427b58"
# Mem/Disk available meter
theme[available_start]="#cc241d"
theme[available_mid]="#d65d0e"
theme[available_end]="#b57614"
# Mem/Disk used meter
theme[used_start]="#427b58"
theme[used_mid]="#d65d0e"
theme[used_end]="#cc241d"
# Download graph colors
theme[download_start]="#98971a"
theme[download_mid]="#689d6a"
theme[download_end]="#79740e"
# Upload graph colors
theme[upload_start]="#cc241d"
theme[upload_mid]="#d65d0e"
theme[upload_end]="#b57614"
# Process box color gradient for threads, mem and cpu usage
theme[process_start]="#427b58"
theme[process_mid]="#af3a03"
theme[process_end]="#cc241d"

View file

@ -18,7 +18,7 @@ theme[main_fg]="#d4be98"
# Title color for boxes # Title color for boxes
theme[title]="#d4be98" theme[title]="#d4be98"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#ea6962" theme[hi_fg]="#ea6962"
# Background color of selected items # Background color of selected items

View file

@ -18,7 +18,7 @@ theme[main_fg]="#F8F8F2"
# Title color for boxes # Title color for boxes
theme[title]="#F8F8F2" theme[title]="#F8F8F2"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#2eb398" theme[hi_fg]="#2eb398"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#F8F8F2"
# Title color for boxes # Title color for boxes
theme[title]="#F8F8F2" theme[title]="#F8F8F2"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#F92672" theme[hi_fg]="#F92672"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#d6deeb"
# Title color for boxes # Title color for boxes
theme[title]="#ffffff" theme[title]="#ffffff"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#addb67" theme[hi_fg]="#addb67"
# Background color of selected items # Background color of selected items

View file

@ -18,7 +18,7 @@ theme[main_fg]="#D8DEE9"
# Title color for boxes # Title color for boxes
theme[title]="#8FBCBB" theme[title]="#8FBCBB"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#5E81AC" theme[hi_fg]="#5E81AC"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -10,7 +10,7 @@ theme[main_fg]="#abb2bf"
# Title color for boxes # Title color for boxes
theme[title]="#abb2bf" theme[title]="#abb2bf"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#61afef" theme[hi_fg]="#61afef"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -12,7 +12,7 @@ theme[main_fg]="#00"
# Title color for boxes # Title color for boxes
theme[title]="#00" theme[title]="#00"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#CC3E28" theme[hi_fg]="#CC3E28"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#eee8d5"
# Title color for boxes # Title color for boxes
theme[title]="#fdf6e3" theme[title]="#fdf6e3"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#b58900" theme[hi_fg]="#b58900"
# Background color of selected items # Background color of selected items

View file

@ -18,7 +18,7 @@ theme[main_fg]="#586e75"
# Title color for boxes # Title color for boxes
theme[title]="#002b36" theme[title]="#002b36"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#b58900" theme[hi_fg]="#b58900"
# Background color of selected items # Background color of selected items

View file

@ -10,7 +10,7 @@ theme[main_fg]="#cfc9c2"
# Title color for boxes # Title color for boxes
theme[title]="#cfc9c2" theme[title]="#cfc9c2"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#7dcfff" theme[hi_fg]="#7dcfff"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -10,7 +10,7 @@ theme[main_fg]="#cfc9c2"
# Title color for boxes # Title color for boxes
theme[title]="#cfc9c2" theme[title]="#cfc9c2"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#7dcfff" theme[hi_fg]="#7dcfff"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#c5c8c6"
# Title color for boxes # Title color for boxes
theme[title]="#c5c8c6" theme[title]="#c5c8c6"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#81beb7" theme[hi_fg]="#81beb7"
# Background color of selected item in processes box # Background color of selected item in processes box

View file

@ -18,7 +18,7 @@ theme[main_fg]="#30"
# Title color for boxes # Title color for boxes
theme[title]="#10" theme[title]="#10"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#284d75" theme[hi_fg]="#284d75"
# Background color of selected item in processes box # Background color of selected item in processes box