2284 Commits

Author SHA1 Message Date
6876a4b136 Update ChangeLog 2021-08-27 12:11:22 +10:00
da7a369fa8 Merge branch 'shorten_crash_report' of cgzones/htop, rebased by BenBE 2021-08-26 19:31:50 +02:00
4ed3ab5c2c Shorten crash output to fit on screen 2021-08-26 14:09:39 +02:00
088dc5b9a7 Remove license excemption for PLPA and update GPL-2 license text
The Portable Linux Processor Affinity (PLPA) project has been depreciated in
favour of the Portable Hardware Locality (hwloc) project. So the license
exception present in previous versions of htop is obsolete and thus removed.

The text of COPYING has been updated to the latest upstream license text
of GPL-2 from the Free Software Foundation, Inc. (FSF).
There are only editorial changes like line wrapping, removing page breaks,
updating the "19yy" to "<year>" and changing the FSF address.
2021-08-26 11:37:36 +02:00
16faf82739 Clarify naming of Platform_nanosecondsPerSchedulerTick 2021-08-25 20:45:00 +02:00
df17374a92 Merge branch 'refactor-Darwin-platform-unit-conversion-helpers' of amomchilov/htop 2021-08-25 19:15:17 +02:00
59d0c5b26a Refactor Darwin platform unit conversion helpers 2021-08-25 11:55:05 -04:00
fa48c484cc Merge branch 'fix-macOS-time-calculations' of amomchilov/htop 2021-08-25 17:07:06 +02:00
a5e2eff5e9 configure: resolve autotools 2.70 deprecation warnings
configure.ac:72: warning: The macro `AC_PROG_CC_C99' is obsolete.
    configure.ac:72: You should run autoupdate.
    ./lib/autoconf/c.m4:1659: AC_PROG_CC_C99 is expanded from...
    configure.ac:72: the top level
    configure.ac:134: warning: The macro `AC_HEADER_STDC' is obsolete.
    configure.ac:134: You should run autoupdate.
    ./lib/autoconf/headers.m4:704: AC_HEADER_STDC is expanded from...
    configure.ac:134: the top level
2021-08-25 13:16:40 +02:00
2bf626c4e4 IWYU update 2021-08-25 09:54:30 +02:00
fecf093367 IWYU: add two header rules 2021-08-25 09:54:30 +02:00
c243db0b2c XUtils: move implementation of String_contains_i out of header file
The function strcasestr(3) is only available if _GNU_SOURCE is defined.
If any file includes <string.h> before declaring _GNU_SOURCE, e.g by
including "config.h", compilation fails with the following error:

    In file included from ColumnsPanel.c:8:
    In file included from ./ColumnsPanel.h:12:
    In file included from ./Panel.h:13:
    In file included from ./CRT.h:16:
    In file included from ./Settings.h:17:
    In file included from ./Process.h:15:
    In file included from ./Object.h:17:
    ./XUtils.h:42:11: error: implicit declaration of function 'strcasestr' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
       return strcasestr(s1, s2) != NULL;
              ^
    ./XUtils.h:42:11: note: did you mean 'strcasecmp'?
    /usr/include/strings.h:116:12: note: 'strcasecmp' declared here
    extern int strcasecmp (const char *__s1, const char *__s2)
               ^

Move the implementation to avoid unnecessary includes.
Since LTO is quite common and stable performance should not be impacted
if used.
2021-08-25 09:54:30 +02:00
a18018ed48 Merge branch 'hlayout_id' of cgzones/htop 2021-08-24 20:43:18 +02:00
db076b9c8e HeaderLayout: save name in configuration
Use a name in the user configuration file instead of the compile
time enum value, so that future reorderings or insertions do not change
the user selected layout.
2021-08-24 20:27:59 +02:00
0679e9f45e Unsupported: update platform 2021-08-24 20:23:03 +02:00
7a4d6fa409 Style touch-ups 2021-08-23 10:37:49 -04:00
5b4d63d1be Fix macOS CPU time calculations 2021-08-23 10:37:49 -04:00
ec2307688e Merge branch 'header_fmt' of cgzones/htop 2021-08-23 14:56:05 +02:00
6d10736a64 Merge branch 'config_versions' of fasterit/htop 2021-08-23 14:53:24 +02:00
711a7aacb0 Tiny cleanup from review comments 2021-08-23 14:50:46 +02:00
a912512ac9 Simplify delay.tv_usec calculation from BenBE
Closes #761
2021-08-23 10:42:08 +02:00
35d94a5ae5 Apply approved warning message suggested by nathans 2021-08-23 08:58:14 +02:00
ccb756d3c7 Widen integer type before multiplication
Meter.c:320:71: warning: performing an implicit widening conversion to type '__suseconds_t' (aka 'long') of a multiplication performed in type 'int' [bugprone-implicit-    widening-of-multiplication-result]
          struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay - ((globalDelay / 10) * 10)) * 100000 };
                                                                          ^
2021-08-22 17:53:21 +02:00
5dec9475bb Use break inside loop with false condition
Found by clang-tidy.

    home/christian/Coding/workspaces/htop/Process.c:505:13: warning: 'continue' in loop with false condition is equivalent to 'break' [bugprone-terminating-continue]
               WRITE_HIGHLIGHT(0, strlen(procComm), commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM);
               ^
    /home/christian/Coding/workspaces/htop/Process.c:461:13: note: expanded from macro 'WRITE_HIGHLIGHT'
                continue;                                                                         \
                ^
2021-08-22 17:53:21 +02:00
c3746dc901 Align parameters names between function declaration and definition
Found by clang-tidy.
2021-08-22 17:53:21 +02:00
6e6334e603 Simplify adding pages in one place 2021-08-22 16:15:59 +02:00
9060a4179d Add option to change Header layout 2021-08-22 16:15:59 +02:00
7269faf651 Only request selection index in ColorsPanel when needed 2021-08-22 15:22:27 +02:00
7146059645 Removed unused field in ColorsPanel 2021-08-22 15:21:52 +02:00
cf45a5d02b MemorySwapMeter: use full width on odd total width 2021-08-22 14:51:13 +02:00
a905c45195 Meter: update documentation to match Doxygen style 2021-08-22 14:50:52 +02:00
9df0f62859 Linux: do not scan frequency for inactive CPUs 2021-08-22 14:50:38 +02:00
68f2bfea61 Abstract resize handling by adding a new Htop reaction 2021-08-22 10:40:59 +02:00
b9e69223d0 ScreenManager: reduce ScreenManager_resize
The main change is the header hight being not included in y1.
This is important if a sub-manager gets resized, e.g. a resize while
editing the Settings or in a pickFromVector selection, and afterwards,
then the sub-manager is closed, the super-ScreenManager gets resized, it
uses the correct header hight.
The header hight might have been changed since the last resize of the
super-manager in the Settings by adding/removing some meters.

This fixes new meters being hidden after added at runtime after a resize
in the main window.
2021-08-22 10:40:59 +02:00
edc3de7cb5 Action: specify implication in code not in comments 2021-08-22 10:40:59 +02:00
a9ddaccc63 Merge branch 'read-settings-defaults' of bjpbakker/htop 2021-08-18 14:47:16 +02:00
a0c244a163 Spell out virtualized 2021-08-18 14:01:25 +02:00
f886759022 Meter: limit LED mode by width
Stop displaying LED-mode if maximum width is reached.
2021-08-17 10:36:10 +02:00
b965417bf7 Add combined memory and swap meter
Closes: #699
2021-08-17 10:36:10 +02:00
3f727d4720 Merge pull request #747 from natoscott/coverity
Coverity scan updates (minor)
2021-08-17 15:42:33 +10:00
d5ff5c48a8 Apply suggestions from code review
Co-authored-by: BenBE <BenBE@geshi.org>
2021-08-17 15:42:10 +10:00
c7f634ec21 PCP: ensure unsigned types used throughout CPU count detection
This cannot be negative in these code locations, but for the
purposes of static checking like Coverity scan make it clear
and used the same unsigned type as ProcessList.h for the CPU
count variable (matching PL activeCPUs and existingCPUs).
2021-08-17 14:41:55 +10:00
c401ac3a98 Ensure DynamicColumn hash lookups never see NULL pointers
This cannot happen in these code locations, but for the purposes
of static checkers like Coverity scan (and for future proofing),
add two more guards on NULL hash table entry pointers.
2021-08-17 14:41:40 +10:00
fefff80631 PCP: PCPMetric.[ch] Mdoule
Split the PCP Metric API (functions `Metric_*`) into their own module.
as @BenBE suggested.
2021-08-16 17:23:07 +02:00
edafa26f9e Simplify Action_pickFromVector() width parameter usage
Pass one less instead of subtracting one inside the function.
2021-08-16 08:05:46 +02:00
68460b25e3 Reset the signal handlers at program exit
The signal handler will access the Settings struct, which gets freed at
normal program finalization.

When using leak sanitizers with ASAN_OPTIONS=abort_on_error=1, which
runs after program termination, any leak causes SIGABRT to be raised,
calling the crash handler, which will derefernce the freed Settings.

    ==44741==ERROR: AddressSanitizer: heap-use-after-free on address 0x60d000000080 at pc 0x0000005680df bp 0x7fffe335e960 sp 0x7fffe335e958
    READ of size 8 at 0x60d000000080 thread T0
        #0 0x5680de in Settings_write /home/christian/Coding/workspaces/htop/Settings.c:329:26
        #1 0x4f77b7 in CRT_handleSIGSEGV /home/christian/Coding/workspaces/htop/CRT.c:1020:4
        #2 0x7f8a1120c13f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1413f)
        #3 0x7f8a11042ce0 in __libc_signal_restore_set signal/../sysdeps/unix/sysv/linux/internal-signals.h:86:3
        #4 0x7f8a11042ce0 in raise signal/../sysdeps/unix/sysv/linux/raise.c:48:3
        #5 0x7f8a1102c536 in abort stdlib/abort.c:79:7
        #6 0x4c3db6 in __sanitizer::Abort() (/home/christian/Coding/workspaces/htop/htop+0x4c3db6)
        #7 0x4c2090 in __sanitizer::Die() (/home/christian/Coding/workspaces/htop/htop+0x4c2090)
        #8 0x4d0a17 in __lsan::HandleLeaks() (/home/christian/Coding/workspaces/htop/htop+0x4d0a17)
        #9 0x4cd950 in __lsan::DoLeakCheck() (/home/christian/Coding/workspaces/htop/htop+0x4cd950)
        #10 0x7f8a110454d6 in __run_exit_handlers stdlib/exit.c:108:8
        #11 0x7f8a11045679 in exit stdlib/exit.c:139:3
        #12 0x7f8a1102dd10 in __libc_start_main csu/../csu/libc-start.c:342:3
        #13 0x428a19 in _start (/home/christian/Coding/workspaces/htop/htop+0x428a19)

    0x60d000000080 is located 64 bytes inside of 144-byte region [0x60d000000040,0x60d0000000d0)
    freed by thread T0 here:
        #0 0x4a4f72 in free (/home/christian/Coding/workspaces/htop/htop+0x4a4f72)
        #1 0x566693 in Settings_delete /home/christian/Coding/workspaces/htop/Settings.c:32:4
        #2 0x4ede10 in CommandLine_run /home/christian/Coding/workspaces/htop/CommandLine.c:393:4
        #3 0x4d6f32 in main /home/christian/Coding/workspaces/htop/htop.c:15:11
        #4 0x7f8a1102dd09 in __libc_start_main csu/../csu/libc-start.c:308:16

    previously allocated by thread T0 here:
        #0 0x4a5372 in __interceptor_calloc (/home/christian/Coding/workspaces/htop/htop+0x4a5372)
        #1 0x57f61a in xCalloc /home/christian/Coding/workspaces/htop/XUtils.c:55:17
        #2 0x5688a6 in Settings_new /home/christian/Coding/workspaces/htop/Settings.c:392:21
        #3 0x4ecb57 in CommandLine_run /home/christian/Coding/workspaces/htop/CommandLine.c:303:25
        #4 0x4d6f32 in main /home/christian/Coding/workspaces/htop/htop.c:15:11
        #5 0x7f8a1102dd09 in __libc_start_main csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-use-after-free /home/christian/Coding/workspaces/htop/Settings.c:329:26 in Settings_write
2021-08-16 08:05:07 +02:00
b42c441ee0 Use proper metric to detect kernel threads
Querying kernel threads with `ps -o pid,lid,flags,state,lname -sp 0`
gives that kernel threads have state `K` and flags have mask `0x20000` set.
This corresponds to `LW_SYSTEM` in kernel which is mapped as `L_SYSTEM`/`P_SYSTEM` for userspace.
2021-08-16 08:03:57 +02:00
68123adb6f Build fix for NetBSD 2021-08-16 07:45:04 +02:00
ce27f8379d Respect "Show custom thread names" setting update
Update merged command-line when started with "Show custom thread names"
disabled and enabling at runtime.

Also only consider showThreadNames when working on userland threads.
2021-08-14 17:05:00 +02:00
2d1b6f4783 TasksMeter: save some float casts
Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2021-08-14 11:16:03 +02:00
fc2377f052 Build pcp-htop.5 only when --enable-pcp 2021-08-14 10:44:31 +02:00
4b59a2e6b7 Introduce versioned config files and config_reader_min_version 2021-08-13 23:21:54 +02:00
nia
dd91e9a9da netbsd: Add NetworkIOMeter support 2021-08-13 22:27:14 +02:00
9a07ba2700 Merge pull request #705 from natoscott/pcp-htop-manual
docs: updates and new manual page for pcp-htop
2021-08-13 16:05:38 +10:00
5b5836a2b1 Apply suggestions from code review
Co-authored-by: BenBE <BenBE@geshi.org>
2021-08-13 16:04:25 +10:00
f839095e3b Merge branch 'dynamic-columns' of https://github.com/smalinux/htop into smalinux-dynamic-columns 2021-08-13 15:56:01 +10:00
6f2021f3d9 PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns.  The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.

We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.

Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location.  Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop.  This
final location becomes the preferred place for our own
shipped meter and column files.

The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start.  Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-08-13 07:32:57 +02:00
6974ce8e79 Linux: do not include zram devices in DiskIO
The meter is intended to show *real* IO, which is significantly slower
than zram.
2021-08-10 22:01:42 +02:00
796bc36fe0 Add assert to improve backtraces on NULL function pointer 2021-08-10 21:26:50 +02:00
ba5ef1ac8b CPUMeter: show if a CPU is offline in text mode
Related to #729 as the text mode displays all zero values for offline
CPUs.
2021-08-10 17:09:04 +02:00
671282d309 Correct grammatical error in crash information
Spotted by @natoscott
2021-08-10 17:09:04 +02:00
a8b8f5f836 ScreenManager: drop unused member 2021-08-10 17:09:04 +02:00
51669ecba8 Solaris: the average CPU utilization value must never be marked 'offline'
Similar to #729 only for Solaris
2021-08-10 17:09:04 +02:00
02cfd38671 The average CPU utilization value must never be marked 'offline'
Fixes https://github.com/htop-dev/htop/issues/729
2021-08-10 08:00:35 +02:00
nia
6d3b4a0f2e netbsd: handle repeated ENOMEM from HW_IOSTATS safely 2021-08-09 14:17:06 +02:00
c31fd3c691 Merge branch 'pcp-dynamic-cpu' 2021-08-09 19:24:29 +10:00
nia
324f9d048d netbsd: add more robust error handling for sysctl HW_IOSTATS 2021-08-09 09:08:37 +02:00
nia
5b8654d341 netbsd: Add support for DiskIOMeter 2021-08-09 09:08:37 +02:00
eb4ff3c69c Add Shift-F7, Shift-F8 keybindings for autogroups 2021-08-09 16:23:09 +10:00
1bd95983b2 Add columns for process autogroup identifier and nice value
Adds AGRP (autogroup) and ANI (autogroup nice) columns that
report the information from /proc/PID/autogroup, as well as
handlers for '{' and '}' to change the autogroup nice value.

This is guarded by /proc/sys/kernel/sched_autogroup_enabled
such that sampling and/or changing values wont be attempted
unless the kernel feature is enabled.

Fixes: #720
2021-08-09 07:56:13 +02:00
ee831263c3 PCP: implement a missing piece for offline and hotplug CPUs
Related: #656
2021-08-09 12:42:45 +10:00
aa0424ade8 configure: check for NaN compiler support
Compilers might due to optimizations, like -ffast-math (included in
-Ofast) expect floating point variables to be never NaN and replace each
call to isnan() with false.  Htop uses the value NaN for signaling no
data available for various information.

Warn at configure time if the compiler will ignore NaN values.

Note: this can not be implemented as a compile time static assert, as
some compilers handle compile NaNs differently than runtime NaNs.
2021-08-08 17:02:12 +02:00
10e9ffd8e5 Fix misc typos
[ci skip]
2021-08-08 15:10:58 +02:00
nia
97a859c5bd netbsd: Use newer proplib API. Create aliases so it works on 9.x.
This way we avoid deprecation warnings on the development branch
of NetBSD while keeping the code functioning on the stable branch.
2021-08-05 10:47:14 +02:00
nia
c85aafa608 netbsd: If at least one AC adapter is connected, keep its state. 2021-08-05 10:47:14 +02:00
nia
93ca5af953 netbsd: style: declare variables on first use rather than C89-style 2021-08-05 10:47:14 +02:00
nia
fdcdc54ec4 netbsd: Add battery support
This uses proplib and sysmon_envsys to determine the total charge
percentage of any number of connected batteries as well as the
AC adapter state. Should work with ACPI and non-ACPI systems.
2021-08-05 10:47:14 +02:00
2e3f34f5c1 NetBSD: Rework CPU counting. 2021-08-05 10:25:59 +02:00
04da92dfd1 docs: updates and new manual page for pcp-htop
Add some words about pcp-htop to the main man page, and add a
new man page describing the pcp-htop configuration files that
allow new meters and columns to be defined at runtime.
2021-08-03 14:11:21 +10:00
c1c4b5a1ab Read settings after applying defaults
Default settings are used as a base and only settings specified in `htoprc` are
applied on top of it. This patch removes the special case for applying some
defaults  when the config does not contain a `meters` key. All defauls are set
before any attempt to read settings, so only keys actually present in the config
file are overridden.
2021-08-02 17:33:34 +02:00
ed82ce6456 Merge branch 'cpu_count' of cgzones/htop 2021-08-02 15:21:07 +02:00
e341217fea Properly handle multiple batteries on darwin
This makes the behaviour consistent with other platforms where AC is
marked as present if at least one power source is marked as AC_PRESENT.

Fixes: #711
2021-08-02 14:37:44 +02:00
44e01dd32b Makefile.am fix that actually does a proper substitution 2021-08-02 00:43:10 +02:00
03705a20aa Fix portability issue in Makefile.am
Fixes #662
2021-08-02 00:00:46 +02:00
19ad28a560 PCP: fix per-process user and system time conversions 2021-07-29 10:15:43 +02:00
97d9b320ad PCP: use the correct metric for shared memory calculations 2021-07-29 10:14:51 +02:00
nia
4f3ba680fb Fix indentation style 2021-07-21 21:06:58 +02:00
nia
3fced48eea netbsd: convert snprintf use to xSnprintf 2021-07-21 21:06:58 +02:00
nia
a4b650fdec netbsd: re-initialize freqSize before sysctlbyname() 2021-07-21 21:06:58 +02:00
nia
72cea2881c netbsd: Remove conditional compilation of CPU frequency variables 2021-07-21 21:06:58 +02:00
nia
b4884373e5 netbsd: Support display of CPU frequency 2021-07-21 21:06:58 +02:00
370f89c086 Merge branch 'fix-dragon' of smalinux/htop 2021-07-18 13:03:13 +02:00
32faba0b6d DragonFlyBSD: fixup: ProcessList_new declaration & definition mismatch 2021-07-18 12:41:11 +02:00
82aa956940 PCP: fixup: missing setter for isUserlandThread
fixes the color of PROC_COMM for PCP...
2021-07-18 10:28:52 +02:00
2fe4a6351e Merge branch 'show-thread-names-fix' of BenBE/htop 2021-07-18 10:21:06 +02:00
90b209ee37 PCP: fixup: Missing headers for DynamicMeter 2021-07-18 09:36:59 +02:00
edf236f9fc OpenBSD: support offline CPUs and hot-swapping 2021-07-18 07:58:50 +02:00
f608fc5c8a OpenBSD: fix compile errors
openbsd/OpenBSDProcessList.c:176:56: error: no member named 'ki_pid' in 'struct kinfo_proc'; did you mean 'p_pid'?
   const int mib[] = { CTL_KERN, KERN_PROC_CWD, kproc->ki_pid };
                                                       ^~~~~~
                                                       p_pid
/usr/include/sys/sysctl.h:375:10: note: 'p_pid' declared here
        int32_t p_pid;                  /* PID_T: Process identifier. */
                ^
openbsd/OpenBSDProcessList.c:458:33: error: comparison of integers of different signs: 'int' and 'unsigned int' [-Werror,-Wsign-compare]
      if (opl->cpus[i].cpuIndex == id)
          ~~~~~~~~~~~~~~~~~~~~~ ^  ~~
2021-07-18 07:53:03 +02:00
90cc16efc0 Solaris: support offline CPUs and hot-swapping
Example hot-swapping:
    psradm -F -f 2
2021-07-18 07:53:01 +02:00
f47e88f5e8 DragonFlyBSD: calculate whether to show entry last
Wait until it has been decided what kind of task the entry actually is.
2021-07-18 07:50:50 +02:00
b148a4bed2 DragonFlyBSD: drop void TODO 2021-07-18 07:50:50 +02:00
1fb0c720fe Enable affinity support for non-Linux
sched_getaffinity() and sched_setaffinity() are also available on BSDs.
Remove the Linux restraint.
2021-07-18 07:50:48 +02:00
adcedf87f5 FreeBSD: mark the original kernel thread with pid 0 as such 2021-07-18 07:47:16 +02:00
3451b6c6b8 FreeBSD: calculate whether to show entry last
Wait until it has been decided what kind of task the entry actually is.
2021-07-18 07:47:16 +02:00
af0b67ccd2 FreeBSD: skip exe check for kernel thread
Kernel threads do not have an executable and the check can result in
garbage values as unprivileged user.
2021-07-18 07:47:16 +02:00
fbe3a2155f UptimeMeter: treat all non-positive values as error
Bogus uptime measurements can result in wrap-arounds, leading to
negative garbage values printed.
2021-07-18 07:47:16 +02:00
11d2206f40 Add ProcessList_isCPUonline 2021-07-18 07:47:09 +02:00
41af31be7f Rework CPU counting
Currently htop does not support offline CPUs and hot-swapping, e.g. via
    echo 0 > /sys/devices/system/cpu/cpu2/online

Split the current single cpuCount variable into activeCPUs and
existingCPUs.

Supersedes: #650
Related: #580
2021-07-18 07:44:02 +02:00
7bfd62b8e4 Respect "Show custom thread names" setting 2021-07-17 20:59:50 +02:00
c9abd788b1 Minor README wordsmithing on review of recent deps/build changes 2021-07-16 12:48:07 +10:00
0b787ca0b8 Merge branch 'README-update' of https://github.com/Eideen/htop into Eideen-README-update 2021-07-16 10:36:46 +10:00
nia
e8f27ebc26 Disable mouse option when support is unavailable 2021-07-15 19:09:08 +02:00
nia
2ab8fb83ba netbsd: Support curses libraries without ncurses mouse support
This adds a configure check for the ncurses getmouse() function
and disables mouse-related code paths when mouse support is
not present in the curses library.

This is necessary for stable versions of NetBSD's libcurses, the
development version has stub mouse functions for compatibility
with ncurses.

Signed-off-by: Nia Alarie <nia@NetBSD.org>
2021-07-15 19:09:08 +02:00
d45b4f4a43 Use PATH lookup for systemctl in systemd meter
Before this change, the systemd meter was broken on distros like NixOS,
which have systemctl in PATH, but not at /bin/systemctl. After the
change, it works on all my NixOS machines.
2021-07-15 10:21:12 +02:00
df435931b6 Proper label indentation 2021-07-15 06:57:24 +02:00
279140db21 Align descriptive comments 2021-07-15 06:57:24 +02:00
976c6123f4 Pointer indication aligned to typename 2021-07-15 06:57:24 +02:00
68edf92434 Indentation of string arguments 2021-07-15 06:57:24 +02:00
0d85af2872 Whitespace around operators 2021-07-15 06:57:24 +02:00
458749df45 Code indentation 2021-07-15 06:57:24 +02:00
e7f8d7bcc9 Split statements that should go onto multiple lines 2021-07-15 06:57:24 +02:00
nia
3bc73aa088 netbsd: update README.md (#694)
netbsd: update README.md
2021-07-15 06:41:42 +02:00
f21f81b2de Merge pull request #695 from smalinux/zfs-orgniz
PCP: cleanup: put ZFS in its rightful place
2021-07-15 12:11:09 +10:00
3853978538 PCP: cleanup: put ZFS in its rightful place
`PCPProcessList_updateHeader` for all meters...
2021-07-15 03:47:54 +02:00
2b69f44a9d Fix whitespace oddity in previous DynamicMeter updates
Thanks @BenBE for noticing.
2021-07-14 17:08:36 +10:00
0daefbe4b4 Improve the DynamicMeter_search API to make 'key' optional
Thanks to @BenBE for the suggestion.
2021-07-14 11:58:46 +10:00
9cbee01877 Additional pointer checks in dynamic meter code for Coverity 2021-07-14 11:58:46 +10:00
bf853addc3 Ensure PCP dynamic metric configuration definition uniqueness
It can happen that pcp-htop is presented multiple definitions
of the same dynamic meter, e.g. if /etc/pcp/htop/meters has a
definition matching one in ~/.config/htop/meters - instead of
exiting with a duplicate metric error provide more meaningful
diagnostics (on close) and also just skip over such entries.
System files override home directories which overrides those
found below the current working directory.

Also fix the derived metric error diagnostic; because this is
using CRT_fatalError, which is like perror(3), we must give a
meaningful prefix (like program name) at the string end.
2021-07-14 11:58:46 +10:00
a476490282 Ensure we do not attempt to add a DynamicMeter via the
htoprc that we didn't find during start up.  This just
leaves blank sections of the display as @smalinux found.

Related to https://github.com/htop-dev/htop/pull/682
2021-07-14 11:58:31 +10:00
bf22a8fb13 Add SIGINT handler
This SIGINT handler is installed on top of an optional
handler that some curses/ncurses implementations provide.

This ensures the curser is properly reset when hitting Ctrl+C.
2021-07-13 20:42:30 +02:00
nia
09c7e3e136 netbsd: Support building with libcurses
Right now Unicode support must be disabled, because htop peeks
into the ncurses cchar_t struct with Unicode enabled. NetBSD's cchar_t
has different contents.

Partially fixes #660

Signed-off-by: Nia Alarie <nia@NetBSD.org>
2021-07-13 20:42:30 +02:00
nia
4865e643ad netbsd: Fix display of in-use and cached memory 2021-07-13 19:06:30 +02:00
nia
67ca214cbe netbsd: Add dyanmicMeters stubs to fix the build
Signed-off-by: Nia Alarie <nia@NetBSD.org>
2021-07-13 19:05:24 +02:00
9bba1c6cf7 README updates/formating
Formating add section "prerequisite"
To make it easy to build
Merged  Compiling from source and Github tarball ref: #639
removed tarball downloads #680
2021-07-11 14:10:47 +02:00
e7aaf79166 Remove unnecessary include files from PCPDynamicMeter.c
Also resolve a few unintended style guide transgressions
in the PCP platform code.
2021-07-09 12:42:36 +10:00
9f667f2c74 Remove references to bintray in the README, no longer exists 2021-07-08 16:34:27 +10:00
01f5b89278 Pretty-print values in the PCP DynamicMeter code
Several improvements to the way values are displayed in the
PCP platform DynamicMeter implementation:
- handle the initial 'caption' setting as with regular meters,
  this required a new meter callback because we no longer have
  just a single meter caption for the DynamicMeter case
- if no label is provided for a metric in a configuration file
  use the short form metric name as a fallback
- honour the suffix setting in the configuration file
- convert metric values to the canonical units for htop (kbyte
  and seconds), and use Meter_humanUnit when it makes sense to
  do so.

Also improves the handling of fatal string error messages in a
couple of places, thanks to BenBE for the review feedback.
2021-07-08 10:56:05 +10:00
149774209b Remove Linux-specific cpp conditional in SwapMeter.c
Instead use the common NAN pattern to use of the swap
cached value on platforms that do not support it.
2021-07-07 14:24:32 +10:00
15a71f32fe Add more defensive checks to PCP paths if sampling fails 2021-07-07 14:00:36 +10:00
93be3211ae PCP: use palette meter text colour for dynamic meter labels 2021-07-07 13:59:33 +10:00
f0ed0fdafb Add a new DynamicMeter class for runtime Meter extension
This commit is based on exploratory work by Sohaib Mohamed.
The end goal is two-fold - to support addition of Meters we
build via configuration files for both the PCP platform and
for scripts ( https://github.com/htop-dev/htop/issues/526 )

Here, we focus on generic code and the PCP support.  A new
class DynamicMeter is introduced - it uses the special case
'param' field handling that previously was used only by the
CPUMeter, such that every runtime-configured Meter is given
a unique identifier.  Unlike with the CPUMeter this is used
internally only.  When reading/writing to htoprc instead of
CPU(N) - where N is an integer param (CPU number) - we use
the string name for each meter.  For example, if we have a
configuration for a DynamicMeter for some Redis metrics, we
might read and write "Dynamic(redis)".  This identifier is
subsequently matched (back) up to the configuration file so
we're able to re-create arbitrary user configurations.

The PCP platform configuration file format is fairly simple.
We expand configs from several directories, including the
users homedir alongside htoprc (below htop/meters/) and also
/etc/pcp/htop/meters.  The format will be described via a
new pcp-htop(5) man page, but its basically ini-style and
each Meter has one or more metric expressions associated, as
well as specifications for labels, color and so on via a dot
separated notation for individual metrics within the Meter.

A few initial sample configuration files are provided below
./pcp/meters that give the general idea.  The PCP "derived"
metric specification - see pmRegisterDerived(3) - is used
as the syntax for specifying metrics in PCP DynamicMeters.
2021-07-07 10:59:36 +10:00
865b85eb2d Fix an assert on kernel process name length on the PCP platform 2021-07-07 10:59:36 +10:00
a0f758009b Fix bitmask used to extract CPU identifier for CPUMeter
When manipulating CPUMeters in the AvailableMeterPanel we
use the bottom 16 bits to hold the CPU number.  However,
the bitmask used to extract the CPU number only masks the
lower 8 bits (0xff).
2021-07-07 10:59:36 +10:00
44d1200ca4 Check for alloc_size attribute in configure.ac 2021-07-06 17:20:32 +02:00
3da142b4b6 Merge branch 'solaris-define-fixes' of BenBE/htop
Tested on OmniOS v11 r151036
2021-07-05 07:51:39 +02:00
a60ff33e52 Merge branch 'check-set-escdelay' of BenBE/htop 2021-07-05 07:51:12 +02:00
364e4e692f Reduce visibility of GZONE and UZONE
Fixes #624
2021-07-04 19:34:03 +02:00
32414dace7 Remove unused define on Solaris 2021-07-04 19:32:47 +02:00
18e3fd5ce7 Check for set_escdelay in ncurses 2021-07-04 16:50:41 +02:00
874fb773a7 Fix typo in Generic_gettime_realtime on old Mac
Fixes #673
2021-07-01 23:27:54 +02:00
ecb6a8da78 PCP: Fix minor cut+paste typo 2021-06-30 07:45:47 +02:00
3bed682b1e Always update proc->st_uid + proc->user
Avoids issue #661.
2021-06-26 12:18:37 +02:00
686309e34c Redo the memory values based on the other BSD implementations. 2021-06-26 12:18:37 +02:00
5fe9bcb21c Adds support for counting user and kernel threads. 2021-06-26 12:18:37 +02:00
336acb0309 Adds support for PROC_EXE and CWD. 2021-06-26 12:18:37 +02:00
612462e33d Adds the ELAPSED column for NetBSD.
Additional details regarding ELAPSED column can be found in #627.
2021-06-26 12:18:37 +02:00
58a895e54c Fixes minor whitespace issues and re-arrange headers to conform to style guide. 2021-06-26 12:18:37 +02:00
9de463e756 Implements the NetBSD specific changes for makeCommandStr refactor.
Refer to #388 PR for more details.
2021-06-26 12:18:37 +02:00
fa65c30976 Sets a non-NULL process state in case of kvm_getlwps(3) returns NULL. Thanks @cgzone. 2021-06-26 12:18:37 +02:00
3770769ed1 Replaces WRAP_SUBTRACT with saturatingSub inline function to reduce code duplication. 2021-06-26 12:18:37 +02:00
2f5b3ef733 Refactor saturatingSub() to be part of Macros.h 2021-06-26 12:18:37 +02:00
e42ae55d69 Renames variable from opl to npl for consistency. 2021-06-26 12:18:37 +02:00
497f468ed0 Fix include paths and minor whitespace issues 2021-06-26 12:18:37 +02:00
9b6cecfede Replace strlcpy() by safer String_safeStrncpy() 2021-06-26 12:18:37 +02:00
3414d3b2d4 Replace maximum_PID value with INT32_MAX
Thank you @niacat.
2021-06-26 12:18:37 +02:00
9e3b7c439c Update README for NetBSD 2021-06-26 12:18:37 +02:00
ddcfb179b4 Remove unwanted code, updates the comments 2021-06-26 12:18:37 +02:00
b900e70e80 Update copyright notices 2021-06-26 12:18:37 +02:00
440bb87058 Minor code clean up and corrections. 2021-06-26 12:18:37 +02:00
db98623684 Sync changes from master and fix minor warnings 2021-06-26 12:18:37 +02:00
4b49de44a8 Add NetBSD platform support without procfs dependency
- TODO, clean up the code base and update comments in code.
2021-06-26 12:18:37 +02:00
30dc4a2812 Add a section on PRs for the styleguide 2021-06-26 11:11:13 +02:00
07170aee4c Unsupported: Remark on expectation of username field update 2021-06-22 09:32:11 +02:00
4dce2db832 Solaris: Always update username 2021-06-22 09:32:11 +02:00
1c0bd5155f PCP: Always update username 2021-06-22 09:32:11 +02:00
d2a476cddb OpenBSD: Always update username 2021-06-22 09:32:11 +02:00
6a6b09b431 Darwin: Always update username 2021-06-22 09:32:11 +02:00
8aca6fbfbd Change 3.0.6-dev -> 3.1.0-dev 2021-06-18 07:52:44 +02:00
ad1ca7ee57 Update IRC channel (Part 2) 2021-06-16 14:57:49 +02:00
78793c5584 Update IRC channel
The development channel on IRC moved to libera.chat
2021-06-16 14:54:20 +02:00
92324d3461 Minor whitespace issue in configure.ac 2021-06-13 19:51:00 +02:00
e3d0fc1a5a Fix a PCP diagnostics typo, add missing pmFreeResult null check. 2021-06-13 19:51:00 +02:00
6f9b161b24 Use the PACKAGE macro rather than htop directly, for overriding
Allow other projects (PCP) to be able to ship an htop binary
which uses the custom name (pcp-htop) in several diagnostics
so that its clear which (if any!) binary failed.
2021-06-13 19:51:00 +02:00
0bd1025e94 Resolve a couple of recent memory leaks in pcp-htop
Makes the pcp-htop binary valgrind-clean once more.
2021-06-13 19:51:00 +02:00
df752dd189 Do not override Linux process library size
The library size in statm is unused and always 0 since Linux 2.6.

Fixes: 8154125d4b
2021-06-12 20:44:33 +02:00
45ab05c56a Limit deleted library check
Reading and parsing /proc/<pid>/maps is quite expensive.

Do not check for deleted libraries if the main binary has been deleted;
in this case the deleted binary takes precedence.

Do not check in threads.  The check is void for kernel threads and user-
land threads can just inherit the state from the main process structure.
2021-06-12 16:02:23 +02:00
7a8a6dd828 Do not install recommended packages by default for the CI
This ensures, the minimal dependencies we specify are sufficient.
Also this reduces fallout from broken recommendations.
2021-06-12 15:27:52 +02:00
de1d06300d Apply stale lib highlighting for EXE too 2021-06-11 09:04:23 +02:00
9114cf6ea3 Linux: update process uid on change
Always check if the user of a process changed, e.g. by using setuid(2).
2021-06-09 22:52:18 +02:00
faabbaa71e Linux: drop O_PATH usage
O_PATH is available since Linux 2.6.39, but we are using fstat(2) on the
returned file descriptor in LinuxProcessList_statProcessDir(), which
is only supported since Linux 3.6.

Fixes #534
2021-06-09 22:52:18 +02:00
8154125d4b Check processes for using deleted shared libraries
Shared libraries can be replaced by an upgrade, highlight processes
using deleted shared libraries.

Link with highlightDeletedExe setting, enabled by default.

Currently only checked on Linux.
2021-06-09 14:40:04 +02:00
94d37989b4 Use macros to PCPProcessList value extraction, tweak configure.ac
Resolves a couple of remaining review notes from @BenBE.
2021-06-09 17:09:29 +10:00
144fd0a8d7 Update platform-specific header includes to use pcp paths.
Resolves a couple of remaining review notes from @BenBE.
2021-06-09 17:09:29 +10:00
4bcb5d116b Update the PCP platform to use common Process fields and code
Remove code now that we have common platform-independent command
line wrangling (thanks BenBE!).  Add PCP platform support for a
handful of other recently arriving odds and ends - ELAPSED time,
CWD, and so on.
2021-06-09 17:09:29 +10:00
4d7cee56f0 Rework TTY column for the PCP platform 2021-06-09 17:09:29 +10:00
9ce9557e69 Various code tidyups based on review commentary from BenBE 2021-06-09 17:09:29 +10:00
b232119e4b Resolve some Coverity scan misfires in PCP platform code 2021-06-09 17:09:29 +10:00
da454997bf Remove dynamic allocation of PCP metric atomvalues expansion
This is no longer used and confuses Coverity scans, drop it.
2021-06-09 17:09:29 +10:00
5abd7f2198 Drop CI distcheck on pcp build as pcp-htop.c now contains main 2021-06-09 17:09:29 +10:00
d4a2587568 Add time handling interfaces for the pcp platform
Related to https://github.com/htop-dev/htop/pull/574
2021-06-09 17:09:29 +10:00
5dfb524237 Implement command line and environment handling for pcp htop. 2021-06-09 17:09:29 +10:00
b424a5b137 Implement shared memory support on the PCP platform
Uses the mem.util.shared metric (Shmem from meminfo).
2021-06-09 17:09:29 +10:00
d3af4e670d Update PCP platform to use the old hostname API call
Fixes CI builds which are on an old version of PCP.
2021-06-09 17:09:29 +10:00
956b2ae70c Update PCP platform to match latest API changes
Updates for recent NetworkIO Meter changes, adds support
for the SysArch and HostName Meters.  The SysArch change
is based on work originally by Sohaib Mohamed.
2021-06-09 17:09:29 +10:00
c6f20fbcc6 Fixes and cleanups for ZFS Meters and metrics 2021-06-09 17:09:29 +10:00
0e7ae9a592 Ensure PCP platform ZramMeter always uses initialized data 2021-06-09 17:09:29 +10:00
407d32e121 Fix PCP ZramMeter in presense of missing zram metrics 2021-06-09 17:09:29 +10:00
e1d1a5cec6 Add ZFS ARC statistics and meters to the PCP platform 2021-06-09 17:09:29 +10:00
6bb59f8881 Fix cut+paste typo in --enable-pcp error message 2021-06-09 17:09:29 +10:00
5ef8706d72 Add new CI workflow to check pcp-enabled builds 2021-06-09 17:09:29 +10:00
c14a45ba35 Add a platform for Performance Co-Pilot (PCP) metrics
This introduces an initial platform for extracting metrics
using the PCP performance metrics API - PMAPI(3).  It can
be used via the --enable-pcp=yes configure option.

So far I've added support for live localhost metrics only,
and only using pre-defined metrics already found in htop.
If available, all sampling is performed by pmcd(1) - else,
we fallback to htop doing the metric sampling itself (all
below the PMAPI).  When pmcd is used, it may be configured
to run children with elevated privileges, so htop does not
need to be setuid (authentication with pmcd is available).

Additionally, the PMAPI allows us to support archives (for
historical analysis and for automated regression tests in
htop).  We'll need platform-specific command line argument
additions, which isn't yet feasible in htop (not difficult
to add though).

The goal of this first version is minimal impact in terms
of modifying the htop codebase, to introduce key ideas in
PCP (metric namespace, metadata, APIs and so on) and give
us something to discuss, experiment with and build on.
2021-06-09 17:09:29 +10:00
d075d49a0c htop.1.in: Some grammatical errors are fixed. 2021-05-30 11:15:45 +02:00
f171e360e0 htop.1.in: A grammatical error is fixed. 2021-05-30 11:15:45 +02:00
c752c542fe Unsupported: Implement CWD column 2021-05-25 21:55:04 +02:00
8420df62eb Solaris: Implement CWD column 2021-05-25 21:55:04 +02:00
5e92956abc OpenBSD: Implement CWD column 2021-05-25 21:55:04 +02:00
90f42695d2 FreeBSD: Implement CWD column 2021-05-25 21:55:04 +02:00
c2e2556403 DragonFlyBSD: Implement CWD column 2021-05-25 21:55:04 +02:00
06073699ba Darwin: Implement CWD column 2021-05-25 21:55:04 +02:00
b6ff5c8a2e Move CWD field handling to platform-neutral code 2021-05-25 21:55:04 +02:00
c408add108 Linux: add reset to heuristic
On hard to parse command lines tokenStart might be computed to be bigger
than tokenEnd.
Reset both values in such cases.
2021-05-25 18:20:09 +02:00
550a141860 Add ELAPSED process column
Add process columns showing the elapsed time since the process was
started.
Similar to STARTTIME, but shows the time passed since the process start
instead of the fixed start time of the process.

Closes https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=782636
2021-05-23 15:43:23 +02:00
3d5b6d9282 Fix assert failure on short running thread
The following assert failure might happen on short running threads with
an empty comm value in /proc/${pid}/stat:

htop: Process.c:1159: void Process_updateCmdline(Process *, const char *, int, int): Assertion `(cmdline && basenameStart < (int)strlen(cmdline)) || (!cmdline && basenameStart == 0)' failed.

The specific task is:
    comm=''
    exe='(null)'
    cmdline='/usr/bin/ruby /usr/bin/how-can-i-help --apt'

So basenameStart is 0, while strlen(cmdline) is also 0.
2021-05-23 15:25:23 +02:00
771a1be316 Update documentation for basename coloring of cmdline/exe columns 2021-05-23 09:30:36 +02:00
51ecc62d92 Force update when executable was recently deleted/replaced 2021-05-23 09:30:36 +02:00
bf07c713ba Allow for highlighting of deleted executables to be configured
Fixes #383
2021-05-23 09:30:36 +02:00
d9feff150c Solaris: add EXE and COMM columns and use merged command line helpers 2021-05-23 09:22:21 +02:00
72724d42f3 DragonFlyBSD: add EXE and COMM columns and use merged command line helpers 2021-05-23 09:22:21 +02:00
d445676f09 OpenBSD: add COMM column and use merged command line helpers 2021-05-23 09:22:21 +02:00
4da618030c FreeBSD: add EXE and COMM columns and use merged command line helpers 2021-05-23 09:22:21 +02:00
8ff4eb72ac Darwin: use merged command line helpers 2021-05-23 09:22:21 +02:00
7892ac68fb Linux: use merge command line helpers 2021-05-23 09:22:21 +02:00
6ad4f345dc Unsupported: use merge command line helpers 2021-05-23 09:22:21 +02:00
05fb681d5c Process: add convenience helper functions to update merged command line related data 2021-05-23 09:22:21 +02:00
7c654559c9 Linux: drop obsolete code now in Process_writeField 2021-05-23 09:22:21 +02:00
7ef58f2dcf Drop mc->maxLen field 2021-05-23 09:22:21 +02:00
2824e2989a Reduce code duplication for nearly identical code-paths 2021-05-23 09:22:21 +02:00
9a78155e17 Properly brace macro arguments 2021-05-23 09:22:21 +02:00
aa8552ba88 Move PROC_COMM/PROC_EXE column handling to global Process implementation 2021-05-23 09:22:21 +02:00
a61a2e6d47 Call makeCommandStr on all platforms 2021-05-23 09:22:21 +02:00
bcb18ef822 Move Process_makeCommandStr to global Process implementation 2021-05-23 09:22:21 +02:00
c0d0202440 Move LinuxProcess_getCommandStr to Process_getCommandStr 2021-05-23 09:22:21 +02:00
7224d0e083 Move kernel/userland thread handling to platform-independent implementation 2021-05-23 09:22:21 +02:00
1a1fddae85 Pre-calculate isUserlandThread flag 2021-05-23 09:22:21 +02:00
cdb660adab Move mergeCommand to global process struct 2021-05-23 09:22:21 +02:00
94a52cb5c9 Rename cmdlineBasenameOffset to cmdlineBasenameEnd to properly indicate the fields purpose 2021-05-23 09:22:21 +02:00
666f70c58c Move procCmdlineBasenameOffset as cmdlineBasenameStart to global Process structure 2021-05-23 09:22:21 +02:00
6dc485dd20 Remove duplicate field LinuxProcess->procCmdlineBasenameEnd
This field held practically the same value as cmdlineBasenameEnd
2021-05-23 09:22:21 +02:00
a685661866 Move procExeBasenameOffset to main Process structure
This drops procExeLen, as that field is implicit by strlen(Process->procExe)
2021-05-23 09:22:21 +02:00
93a44acf7e Move procExeDeleted flag to main Process structure 2021-05-23 09:22:21 +02:00
b839987df7 Rename basenameOffset to cmdlineBasenameOffset 2021-05-23 09:22:21 +02:00
d74e8b7554 Move procComm and procExe to main Process structure 2021-05-23 09:22:21 +02:00
10790f0a54 Process: Put the time field more to the end 2021-05-23 09:22:21 +02:00
02431c43e1 Rename command line field from comm to cmdline 2021-05-23 09:22:21 +02:00
fbec3e4005 Refactor makeCommandStr 2021-05-23 09:22:21 +02:00
07a4657a47 DragonFlyBSD: Fix included headers 2021-05-22 18:16:11 +02:00
2c8353e7cf DragonFlyBSD: Indentation and formatting fixes 2021-05-21 22:42:00 +02:00
ee9e7edbc1 Solaris: handle ERR macro redefinitions
On OmniOS /usr/include/sys/regset.h redefines ERR to 13 - \r, breaking
the Enter key.
Since ncruses macros use the ERR macro, we can not use another name.

Closes: #634
2021-05-20 19:16:29 +02:00
a62987c787 Solaris: improve process columns
- fill tty name
- fill session id
- show real tgid not adjusted
- drop unimplemented TPGID, MINFLT and MAJFLT
- adjust header width of ZONEID, which get auto-adjusted as a pid-column
2021-05-20 17:54:40 +02:00
013d2efa51 Solaris: correct process env memory handling
Allow strncpy to NUL-terminate the buffer and do not return a non free-
able string literal.
2021-05-20 16:43:40 +02:00
27be880d0f Solaris: reduce function scopes 2021-05-20 16:43:40 +02:00
6b57898034 Solaris: reduce variable scope
Also check for getloadavg(3c) failure
2021-05-20 16:43:40 +02:00
906dcf5cb3 Solaris: silence signed comparison 2021-05-20 16:43:40 +02:00
8f34225a49 Solaris: fix includes 2021-05-20 16:43:40 +02:00
fdda291a0e Solaris: add kstat lookup wrappers
The system interfaces kstat_lookup() and kstat_data_lookup() take a
non-constant string parameter, but passing string literals is valid.

Add wrapper functions to ignore all the const-discard warnings.
2021-05-20 16:43:40 +02:00
4676e35f42 DragonFlyBSD: fixup columns 2021-05-19 17:53:14 +02:00
69cfaf2381 configure: ignore warning about delay accounting on non-Linux platform
If pkg-config is not installed the following message gets printed, even
on non Linux platform:

"Linux delay accounting support can not be enabled, cause pkg-config is
required for checking its availability"
2021-05-16 20:01:25 +02:00
d2ee40597c Use STDERR_FILENO instead of magic number 2021-05-16 19:55:51 +02:00
1f5f40c091 Print current settings on crash 2021-05-16 19:55:31 +02:00
204bc710ba Adjust to current label reality and the fact that Github can't search for multiple labels ORed ... yet.
Has been only five years ... https://github.com/isaacs/github/issues/660
2021-05-14 11:29:29 +02:00
40ecde9d88 Add Github label disclaimer as per vi's comment
cf. 6900e57efd (commitcomment-50786333)
2021-05-14 11:17:35 +02:00
3f86a011e6 platform-dependent files included relative to main source directory 2021-05-10 18:40:53 +02:00
1b74dfe187 cleaned up includes with iwyu 2021-05-10 18:40:53 +02:00
d9c95369bc Enclose macro argument
Also enclosing is unnecessary in declaration as in
    int (VAR);
2021-05-10 17:48:05 +02:00
d918cd9f2a Align parameter name of Generic_gettime_realtime
Align with name in implementation.
2021-05-10 17:48:05 +02:00
54d7c6a080 Sort include headers 2021-05-10 17:48:05 +02:00
90ae730fd4 Ignore IDE configuration files
[skip ci]
2021-05-10 17:04:46 +02:00
323d7e73aa Linux: update IO fields
- fix header width of IO_READ_RATE

- save data in bytes (not kilobytes) to better compute rate

- fix rate data: multiply with 1000 to compensate time difference in
  milliseconds

- rename unit less variable now into realtimeMs

- use Process_printBytes(..., data * pageSize, ...) instead of
  Process_printKBytes(..., data * pageSizeKB, ...) to avoid wrapper
2021-04-26 18:02:58 +02:00
b41e4d9c54 Rework process field print functions
Make functions formatting data for a process field column less error
prone, unify interfaces and improve some internals.

* Process_printBytes
  - rename from Process_humanNumber
  - take number in bytes, not kilobytes
  - handle petabytes
  - increase buffer to avoid crashes when the passed value is
    ~ ULLONG_MAX

* Process_printKBytes
  - add wrapper for Process_printBytes taking kilobytes keeping -1 as
  special value

* Process_printCount
  - rename from Process_colorNumber

* Process_printTime
  - add coloring parameter as other print functions
  - improve coloring and formatting for larger times

* Process_printRate
  - rename from Process_outputRate
  - use local buffer instead of passed one; this function prints to the
    RichString after all
2021-04-26 18:02:58 +02:00
6bbb454881 LinuxProcess: print default buffer in ascii
`RichString_appendWide()` is more expensive than
`RichString_appendAscii()` due to the calls to `mbstowcs(3)` and
`iswprint(3)`.

Use the latter to print the process field buffer by default.

For the following fields this theoretically can corrupt the output:
  - SECATTR
  - CGROUP
  - CTID
2021-04-26 17:51:45 +02:00
a2be57d768 Process: print default buffer in ascii
`RichString_appendWide()` is more expensive than
`RichString_appendAscii()` due to the calls to `mbstowcs(3)` and
`iswprint(3)`.

Use the latter to print the process field buffer by default.

For the following fields this theoretically can corrupt the output:
  - TTY
2021-04-26 17:51:45 +02:00
436808ff99 Use RichString_appendnAscii where possible
`RichString_appendnAscii()` avoids a `strlen(3)` call over
` RichString_appendAscii()`.
Use the former where the length is available from a previous checked
`snprintf(3)` call.

Keep `RichString_appendAscii()` when passing a string literal and
rely on compilers to optimize the `strlen(3)` call away.
2021-04-26 17:51:45 +02:00
099dab88be ZfsCompressedArcMeter: avoid division by 0
On systems not using ZFS `this->values[0]` is zero.
2021-04-22 17:12:02 +02:00
2d7069feb4 Linux: handle Shmem being part of Cached
See https://lore.kernel.org/patchwork/patch/648763/

Do not show twice by subtracting from Cached.

Closes: #591
2021-04-22 10:48:15 +02:00
3db3737d75 Update FUNDING.yaml to use open_collective directly (thanks cgzones) 2021-04-22 14:37:09 +10:00
a75b99a15e Document '?' key to reach the help screen 2021-04-21 21:49:03 +02:00
615fc934ff Add assert for unreachable switch case
Like the default case in Process_writeField()
2021-04-21 20:58:28 +02:00
bd689ab0d3 Avoid implicit pointer to bool conversion in assignment
Improve readability
2021-04-21 20:58:28 +02:00
d58c2f0606 Drop ProcessList_get and ProcessList_size
Only used inside ProcessList.c and only once each.
2021-04-21 20:58:28 +02:00
5dbca0193d Make MainPanel_pidSearch a static function
Not used elsewhere.
2021-04-21 20:58:28 +02:00
a05e78f531 Linux: use more robust pid parsing
Also add comment to condition
2021-04-21 20:58:28 +02:00
ace5730f89 Add github funding link to htop opencollective page 2021-04-21 16:33:07 +10:00
feec16cbb5 don't include offline CPUs in summary for OpenBSD
By default, OpenBSD disables SMT (hyperthreading) cpu pseudo-cores.
This can be changed at runtime by setting the hw.smt sysctl so they
may become active later, therefore they are still present in cpu
stat structures but are marked as offline.

As done with native top(1), this drops them from the cpu summary
graphs.
2021-04-18 16:58:20 +02:00
d63394b5f6 DragonFlyBSD: resolve sign comparison
Compat.c: In function 'Compat_faccessat':
  Compat.c:46:14: error: comparison of integer expressions of different signedness: 'int' and 'unsigned int' [-Werror=sign-compare]
     46 |    if (dirfd != AT_FDCWD || mode != F_OK) {
        |              ^~
2021-04-14 17:29:56 +02:00
99cde7edec FreeBSD: silence unsigned integer underflow
freebsd/FreeBSDProcessList.c:252:47: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
      #0 0x397c32 in FreeBSDProcessList_scanCPU /root/workspace/htop/htop/freebsd/FreeBSDProcessList.c:252:47
      #1 0x38fe76 in ProcessList_goThroughEntries /root/workspace/htop/htop/freebsd/FreeBSDProcessList.c:438:4
      #2 0x35ef9a in ProcessList_scan /root/workspace/htop/htop/ProcessList.c:618:4
      #3 0x31ee9e in main /root/workspace/htop/htop/htop.c:468:4
      #4 0x26bbcf in _start /usr/src/lib/csu/amd64/crt1.c:76:7
2021-04-14 17:29:56 +02:00
9a8221568a Rework TTY column
* Rename internal identifier from TTY_NR to just TTY
* Unify column header on platforms
* Use devname(3) on BSD derivate to show the actual terminal,
  simplifies current FreeBSD implementation.
* Use 'unsigned long int' as id type, to fit dev_t on Linux.

Only on Solaris the terminal path is not yet resolved.
2021-04-14 17:29:56 +02:00
36880cd61c Add read-only option
Add command line option to disable all system and process changing
features.
2021-04-14 17:21:43 +02:00
812cfcb94d Rename drop-capabilities options none to off
None might be ambiguous whether we are dropping none or whether we keep
none.

Rename to off to make more clear this option does not drop any.
2021-04-14 17:19:26 +02:00
74d061700c LinuxProcessList_recurseProcTree(): drop non necessary parameter 2021-04-14 17:16:02 +02:00
f3d9ecaa62 Convert process time to days if applicable
With big multicore machines, it's easy to accumulate process time.
2021-04-10 14:43:23 +02:00
0006cc51b7 Merge pull request #593 from natoscott/init-pl-time
Update timestamps for the special process scans at startup also
2021-04-09 21:13:33 +10:00
367561175a Update timestamps for the special process scans at startup also
Resolves https://github.com/htop-dev/htop/issues/592
2021-04-09 10:43:33 +10:00
f3a37f9ef3 Merge branch 'smalinux-CtrTime' 2021-04-07 15:19:18 +10:00
356488aa53 Request the realtime and monotonic clock times once per sample
Refactor the sample time code to make one call to gettimeofday
(aka the realtime clock in clock_gettime, when available) and
one to the monotonic clock.  Stores each in more appropriately
named ProcessList fields for ready access when needed.  Every
platform gets the opportunity to provide their own clock code,
and the existing Mac OS X specific code is moved below darwin
instead of in Compat.

A couple of leftover time(2) calls are converted to use these
ProcessList fields as well, instead of yet again sampling the
system clock.

Related to https://github.com/htop-dev/htop/pull/574
2021-04-05 23:41:07 +02:00
421bdeec60 Merging all the points related to calculating time in one place
The end goal is to consolidate all the points in htop that can only work in
live-only mode today, so that will be able to inject PCP archive mode and have
a chance at it working.
The biggest problem we've got at this moment is all the places that are
independently asking the kernel to 'give me the time right now'.
Each of those needs to be audited and ultimately changed to allow platforms to
manage their own idea of time.
So, all the calls to gettimeofday(2) and time(2) are potential problems.
Ultimately I want to get these down to just one or two.

Related to https://github.com/htop-dev/htop/pull/574
2021-04-05 23:40:41 +02:00
f16aa483dd Merge branch 'illumos-compile-fix' of BenBE/htop 2021-04-04 22:12:54 +02:00
6c66f32fa7 Include signal.h, reorder headers 2021-04-03 21:40:27 +02:00
75fd9edf75 Reorder the header update and process scanning
BenBE points out that some header meters use values calculated
during process scanning - make sure we scan processes first in
order that current values are displayed.

Related to https://github.com/htop-dev/htop/pull/574
2021-03-31 07:50:45 +02:00
8163b8164f TaskMeter: always show number of threads
Always show the number of kernel and userland threads, even when they
are disabled to not be shown in the process list.

The data is already available and might improve understanding the system
utilization.

Use a shadow color in case the kind of thread is hidden, else the normal
meter one.
2021-03-31 00:27:14 +02:00
5afb57b49e FreeBSD: improve actual processor calculation logic 2021-03-30 23:38:32 +02:00
73f5ecf528 Linux: handle garbage in /proc/loadavg
When parsing the content of /proc/loadavg via fscanf(3), ensure client
passed parameters are set to sanitized values.

Related to: #581
2021-03-28 19:20:28 +02:00
272e72680b Merge pull request #575 from natoscott/refactor-command-line
Abstract htop main function to allow for a platform binary
2021-03-25 15:57:15 +11:00
36389fb0da Abstract htop main function to allow for a platform binary
One review request relating to the PCP platform is to have
a clearly separate binary from the regular htop so that we
have no confusion as to what is being requested to run, to
aid debugging, and a bunch of other good reasons.

This commit renames htop.c to CommandLine.c and provides a
minimal htop main function for 'native' platforms to use.
The PCP version of this will setup libpcp.so and then call
the same CommandLine_run function as regular htop.

Related to https://github.com/htop-dev/htop/pull/536
2021-03-25 15:56:15 +11:00
5ef3c26168 Drop always true condition
The variable 'dir' is checked in line 645:
    if (!dir)
        return AC_ERROR;
2021-03-24 19:36:34 +01:00
3e8da0fcb6 Add MEMORY_SHARED to help screen 2021-03-24 19:30:28 +01:00
a19b176099 Correct spelling in comment 2021-03-24 19:27:57 +01:00
9c437ceb0c Drop unused attributes of actually used function parameters
These parameters were once unused, but not anymore.
2021-03-24 19:27:03 +01:00
7b293dc3e2 Linux: fix --drop-capabilities
Do not return false (= argument not handled) when actually handled
2021-03-22 11:56:19 +01:00
6fd5b05151 Merge pull request #564 from natoscott/platform-options
Move libcap use to (Linux) platform-specific code
2021-03-22 17:25:01 +11:00
253ff23f9e Use a platform-specific routine for long option usage
Related to https://github.com/htop-dev/htop/pull/564
2021-03-22 17:16:40 +11:00
d56d23d91a Each platform defines its own long opt macro, prefer printf
Follow up on the two items of feedback from cgzones review,
and resolve a build failure picked up by CI on Mac OS X.

Related to https://github.com/htop-dev/htop/pull/564
2021-03-22 17:16:40 +11:00
0ada9f325f Move libcap use to (Linux) platform-specific code
The libcap code is Linux-specific so move it all below
the linux/ platform subdirectory.  As this feature has
custom command-line long options I provide a mechanism
whereby each platform can add custom long options that
augment the main htop options.  We'll make use this of
this with the pcp/ platform in due course to implement
the --host and --archive options there.

Related to https://github.com/htop-dev/htop/pull/536
2021-03-22 17:16:40 +11:00
57e0ce7b4f Use #if defined() syntax when #elif defined() is present
This prefers the `#if defined()` syntax over the `#ifdef` variant
whenever there's also a `#elif defined()` clause, thus making the
multiple branching structure more obvious and the overall use
more consistent.
2021-03-21 21:49:04 +01:00
1cb3aee07a Merge branch 'cputemp' of cgzones/htop 2021-03-21 18:09:14 +01:00
6ea93fc6c0 Merge branch 'openbsd' of cgzones/htop 2021-03-21 17:48:41 +01:00
63019065dc Merge branch 'cpu_proc_stat' of cgzones/htop 2021-03-21 17:48:02 +01:00
e4e3f6c390 OpenBSD: update
* Set process data for:
    - minflt
    - majflt
    - processor
    - nlwp

* Drop unimplemented nlwp column

* Scan userland threads

* Mark a 'Thread is currently on a CPU.' with 'R', and processes
  'Currently runnable' with 'P', do confine with man:ps(1) and Linux.
  See https://man.openbsd.org/ps.1

* Show CPU frequency
2021-03-20 18:30:08 +01:00
58ad020aca ProcessList: fix treeview on OpenBSD when hiding kernel threads
Currently the tree-view is empty on OpenBSD when kernel threads are
hidden, cause the kernel thread 'swapper' has pid 0 and gets treated as
root of the tree and parent of 'init'.

Do not build any tree with a pid 0 root node.
2021-03-20 18:30:08 +01:00
a11d01568c Use unsigned types for CPU counts and associated variables 2021-03-19 23:30:54 +01:00
70fecb4984 Use consistent style for include check 2021-03-19 22:39:06 +01:00
f46fcf094e Linux: Rework libsensors parsing
Do not read driver depended labels, just count the number of
temperatures given:

  on #CPU:
    platform temp = max cpu temp
    CPU temps = first to last
  on #CPU + 1:
    platform temp = first temp
    CPU temps = second to last
  on #CPU / 2:
    platform temp = max cpu temp
    CPU temps = first to last concat first to last
      (with SMT core x + cpu count is the logical core of the physical
      core x)
  on #CPU / 2 + 1:
    platform temp = first temp
    CPU temps = second to last concat second to last
      (with SMT core x + cpu count is the logical core of the physical
      core x)

Closes: #529
Closes: #538
2021-03-19 22:11:22 +01:00
53bcc5cbff ci: drop hwloc from clang-analyzer build
The hwloc header generates lots of warnings:

  In file included from Action.c:10:
  In file included from ./Action.h:15:
  In file included from ./Header.h:10:
  In file included from ./Meter.h:18:
  In file included from ./ProcessList.h:25:
  In file included from /usr/include/hwloc.h:2371:
  /usr/include/hwloc/helper.h:481:5: warning: Value stored to 'state' is never read [deadcode.DeadStores]
      state = 3;
      ^       ~
  1 warning generated.
2021-03-19 22:07:47 +01:00
db042f259b ci: use focal list for llvm mirror
The llvm bionic packages depend on libffi6, which is not available in
focal.
2021-03-19 22:07:47 +01:00
9a893b9a07 Merge branch 'richstring_memset' of cgzones/htop 2021-03-19 09:58:04 +01:00
67b815a817 Merge branch 'shared_before_cached' of cgzones/htop 2021-03-19 09:49:36 +01:00
ee97916fd5 Merge pull request #436 from cgzones/freebsd
FreeBSD: add support for CPU frequency and temperature
Tested on two physical systems running FreeBSD 12.1
2021-03-18 14:03:51 +02:00
1ba3915f73 Merge pull request #565 from cgzones/ci_clang12
ci: use clang 12
2021-03-18 08:20:17 +11:00
16243a4a7e Action: merge conditions 2021-03-17 17:53:23 +01:00
e942736267 LinuxProcessList: drop unnecessary parenthesis 2021-03-17 17:53:00 +01:00
9f41dc3332 MemoryMeter: show shared memory before cached
Shared memory is less free-able than cached memory.

Show it beforehand.
2021-03-17 16:32:16 +01:00
1e806f9899 RichString: do not unnecessarily clean whole buffer
The local stack buffer does not need to be cleaned to zeros when
  - just initialized, cause the length is set to 0 and the first
    character is set to '\0', so all printing functions will safely stop
  - no further used, i.e. the variable goes out of scope
2021-03-17 15:54:17 +01:00
ac27df373a ci: use clang 12
llvm 12 is stable enough to be used in the CI as compiler and static
analyzer.
2021-03-17 15:27:56 +01:00
d9f2eacbc5 Linux: individually show shared memory
Shmem: Total memory used by shared memory (shmem) and tmpfs

Source: https://www.kernel.org/doc/Documentation/filesystems/proc.txt

Closes: #556
2021-03-15 22:34:14 +01:00
a4173f5209 Improve process following
- stay in follow mode on sort inversion (I)
- stay in follow mode after viewing help screen (h)
- select parent process (where available) when having followed a thread
  and hiding these (H)

Closes: #560
2021-03-14 14:47:15 +01:00
1275139795 Settings_write: fix return value on error
Return a negative errno on fprintf() or flcose() failure, not a return
value of ferror() or flcose().
2021-03-13 18:15:20 +01:00
23797e730e CPUMeter_init: compactify branches 2021-03-12 17:43:23 +01:00
0cfc9b0980 LinuxProcessList: refactor /proc/stat parsing
Combine reading CPU count and CPU usage, only open the file once.
Do not separately initialize totalPeriod and totalTime, cause the value
0 is handled in Platform_setCPUValues().

Take the number of currently running process from the entry
procs_running in /proc/stat instead of counting all scanned process
with state 'R', to include hidden tasks, e.g. threads.
2021-03-12 17:31:45 +01:00
521f1343e3 Settings: check if writing configuration file was successful
Writing to the file stream might fail due to a immutable file or a
filesystem error.
Check the error indicator for the stream and for fclose() failures.
2021-03-12 16:56:06 +01:00
350b48e44c Meter: do not access RichString internals
Use a temporary local variable
2021-03-12 16:49:45 +01:00
c38819a675 Settings: mark non-modified pointer parameters const 2021-03-12 16:48:41 +01:00
d37d66bb3a InfoScreen/ProcessList: do not access Vector internals
Use wrapper function to encapsulate the Vector structure
2021-03-12 16:46:55 +01:00
3f99c2de24 Process: do not access RichString internals
Use wrapper macro to encapsulate the RichString structure
2021-03-12 16:46:04 +01:00
bea7f8e7af Process_compare: reorder checks
Check for result being 0 first, before checking if the result might be
negated, so we do not need to negate 0.
2021-03-12 16:44:46 +01:00
9adcd9051a Object: always include stdbool.h
The function Object_isA() returning bool is nowadays unconditional
2021-03-12 16:38:36 +01:00
8ba4ef327e configure: use portable AND
man:test(1)
    NOTE: Binary -a and -o are inherently ambiguous.  Use 'test EXPR1 &&
    test EXPR2' or 'test EXPR1 || test EXPR2' instead.

Also fix indent
2021-03-12 16:37:17 +01:00
31e59cc60d Merge branch 'misc' of https://github.com/cgzones/htop into cgzones-misc 2021-03-05 13:38:19 +11:00
b862e36ee7 Separate data-update and drawing of header 2021-03-04 23:57:45 +01:00
2d1042adb3 Save text buffer in Meter 2021-03-04 23:57:45 +01:00
23c5b9ce3c Ensure buffer for gethostname(2) is properly terminated 2021-03-04 23:42:24 +01:00
c5770c26af Merge branch 'follow' of cgzones/htop
Closes #557
2021-03-04 07:41:14 +01:00
8c421d527b Resolve trailing-whitespace failure in CI (merge issue) 2021-03-04 15:16:32 +11:00
adaf748ab6 Fix include file ordering of generic headers 2021-03-04 13:44:40 +11:00
61ef1134d9 Move generic (shared) code into its own sub-directory
Code that is shared across some (but not all) platforms
is moved into a 'generic' home. Makefile.am cleanups to
match plus some minor alphabetic reordering/formatting.

As discussed in https://github.com/htop-dev/htop/pull/553
2021-03-04 13:40:59 +11:00
5b50ae3aa3 Separate display from sampling in SysArch and Hostname Meters
Several of our newer meters have merged coding concerns in terms
of extracting values and displaying those values.  This commit
rectifies that for the SysArch and Hostname meters, allowing use
of this code with alternative front/back ends.  The SysArch code
is also refined to detect whether the platform has an os-release
file at all and/or the sys/utsname.h header via configure.ac.
2021-03-04 13:40:11 +11:00
59a150e8d7 Follow followed process when switching thread visibilities
Do not stop following a process when switching the visibility of
userland or kernel threads.

Related: #557
2021-03-03 20:06:14 +01:00
2328e52403 Document PERCENT_NORM_CPU and mention Irix / Solaris modes (top lingo) 2021-03-03 10:46:49 +01:00
0bdceb858d Unsupported: add normalized CPU percentage column 2021-03-03 08:44:37 +01:00
4f9cf1490f Darwin: add normalized CPU percentage column
Missed in 15eab2012d
2021-03-03 08:43:45 +01:00
635d4cfe60 Drop newline at end of if branch 2021-03-02 22:37:47 +01:00
ff4ee2eafc LinuxProcess: Drop dead assignment
Modern compilers are very good at finding uninitialized paths, lets rely
on them.
2021-03-02 22:37:47 +01:00
13b28fa9ed Enclose macro argument in parentheses 2021-03-02 22:03:20 +01:00
979aca98cc Use uppercase floating point literal suffix 2021-03-02 22:03:20 +01:00
df818b9904 Use ATTR_UNUSED instead of void casting 2021-03-02 22:03:20 +01:00
a40347e85b SysArchMeter: avoid static variable 2021-03-02 16:37:11 +01:00
dc8124e1a1 Fix compilation of the 'unsupported' platform (Process flags) 2021-03-02 16:01:14 +11:00
29570c0133 Merge pull request #550 from natoscott/diskio-types
Fix integer sizing issues in the DiskIO Meter
2021-03-02 13:34:52 +11:00
3fe297aa97 Merge pull request #549 from natoscott/network-types
Fix integer sizing issues in the NetworkIO Meter
2021-03-02 13:34:36 +11:00
88a11859a0 Switch NetworkIO Meter to using uint32_t and uint64_t
From review via @BenBE, this is now a whole lot cleaner.
2021-03-02 12:14:44 +11:00
b4736228dc Switch DiskIO Meter to using uint32_t and uint64_t
From review via @BenBE, this is now a whole lot cleaner.
2021-03-02 12:09:29 +11:00
8a1112141d Fix a possible truncation of the intermediate strings in the SysArch meter 2021-03-01 09:56:07 +01:00
7b48fec59a Merge pull request #533 from cgzones/os-release
SysArchMeter: read os-release instead of running lsb-release
2021-03-01 18:38:53 +11:00
00339087b0 Fix integer sizing issues in the DiskIO Meter
On Linux kernels the size of the values exported for block
device bytes has used a 64 bit integer for quite some time
(2.6+ IIRC).  Make the procfs value extraction use correct
types and change internal types used to rate convert these
counters (within the DiskIO Meter) 64 bit integers, where
appropriate.
2021-03-01 12:10:18 +11:00
2d1839289e Fix integer sizing issues in the NetworkIO Meter
On Linux kernels the size of the values exported for network
device bytes and packets has used a 64 bit integer for quite
some time (2.6+ IIRC).  Make the procfs value extraction use
correct types and change internal types used to rate convert
these counters (within the NetworkIO Meter) 64 bit integers,
where appropriate.
2021-03-01 11:55:15 +11:00
379421d3b2 Merge branch 'networkiograph' of Nudin/htop 2021-02-28 18:44:39 +01:00
bb9a60ee8a Implement bar and graph mode for NetworkIOMeter (#408) 2021-02-28 18:36:07 +01:00
07a6efcb22 Make the first tree item stable on expand / collapse again
Regression introduced with 06b1674
2021-02-28 18:16:29 +01:00
76350c0350 Rescale graph when value of total is changed 2021-02-28 17:42:10 +01:00
12c2337939 Merge branch 'remove-setuid' of BenBE/htop 2021-02-17 17:56:58 +01:00
067cd6deb8 Include note in changelog regarding removal of the setuid feature 2021-02-17 17:14:06 +01:00
82157f598e Refactor to remove no-op calls
This removes the call-sites of the removed setuid feature
2021-02-17 15:59:50 +01:00
a73064dda9 Remove setuid support
This support was rarely ever used and has been disabled by default for some time.

As far as the developer team is aware there's no distribution that activated this
feature in their packages by default.
2021-02-17 15:59:50 +01:00
b1befa3287 Merge branch 'enable-better-debug-on-enable-debug' of fasterit/htop 2021-02-17 15:19:59 +01:00
e0dec39203 Merge branch 'fix-duplicate-lines' of hiasen/htop 2021-02-17 15:19:28 +01:00
84e5682473 SysArchMeter: read os-release instead of running lsb-release
os-release is available on FreeBSD by default.
Also avoid executing a third-party program.

Examples:
  Linux 5.10.0-3-amd64 [x86_64] @ Debian GNU/Linux bullseye/sid
  FreeBSD 12.2-RELEASE-p3 [amd64]

Closes: #516
2021-02-17 15:05:36 +01:00
f42090fcfd Drop empty file zfs/ZfsArcStats.c 2021-02-17 00:05:16 +01:00
a89521ed7f Drop -DDEBUG (was removed in d69585b82a), add -Og for make debug target 2021-02-16 22:49:31 +01:00
135efd5705 Enable making with -ggdb3 on configure --enable-debug 2021-02-16 11:24:45 +01:00
525d37d6a4 Shorten keyboard help to fit default screen width 2021-02-16 09:12:07 +01:00
d8d83031d9 InfoScreen: Remove old lines before scanning again 2021-02-15 20:44:34 +01:00
1e57cab605 De-typo DiskIOMeter 2021-02-15 17:42:22 +01:00
b0fd44275d Merge branch 'collapse-tree-view' of fasterit/htop 2021-02-15 12:10:55 +01:00
61c943555b Merge branch 'fix-zero-btime' of natoscott/htop 2021-02-15 10:52:04 +01:00
7433bf4b18 Correctly detect failure to initialize boottime
A zero value for btime (boottime) in /proc/stat is a
real situation that happens, so deal with this case.

Resolves https://github.com/htop-dev/htop/issues/527
2021-02-15 19:32:55 +11:00
8cd90f0c4a Fix a couple of small spelling mistakes in comments 2021-02-15 12:54:20 +11:00
2c6222e30a Option and key ("*") to collapse / expand all branches under PID 1
(and PID 2 if kernel threads are shown)

Based on hishamhm/htop#510 by Krishna Chaitanya, B
Closes #68
2021-02-13 16:47:04 +01:00
c44b2ec795 Small update to test plan
from Krishna Chaitanya, B; found in hishamhm/htop#510
2021-02-13 14:04:15 +01:00
1e39c8fa4d Make ZFS Meter "Unavailable" text match others -> FAILED_READ coloring 2021-02-09 20:25:57 +01:00
4cb2b5fc1c Merge branch 'fix_zfs_arc_ratio_color' of overhacked/htop 2021-02-09 20:02:13 +01:00
f73c98abd4 Forgot to correctly color ZFS ARC ratio
`ZFS_RATIO` in `CRT.c` was unused, because I forgot
to colorize the ARC ratio in the Compressed ARC meter.

The intent was to improve readability of the meter by
highlighting the most relevant value, the ratio, in
a brighter color, for most themes. This change effects
that intent.
2021-02-09 17:07:00 +00:00
f273bfd083 Linux: restore memory calculation regarding HugePages
Subtract the total amount of huge page memory from total and used memory.

Restores behavior from #450 (see also #447)

Follow-up of 3d497a37
2021-02-09 16:01:05 +01:00
7ba3396a4c Update ChangeLog and report credits for the MemAvailable issue and initial implementation 2021-02-09 13:24:01 +01:00
69d3b9ccf1 Merge branch 'mem' of cgzones/htop
* Use MemAvailable info from Linux 3.14+ where available
* Thanks to Chris Cheney for reporting and Tomas Wido for an initial implementation

Closes #281
Closes #385
2021-02-09 13:15:52 +01:00
e86acd6893 Remove force sort order to ASC when returning to tree mode
Bug found by BenBE via IRC
2021-02-07 13:46:57 +01:00
3d497a3760 Linux: overhaul memory partition
Use similar calculation than procps.
Show AvailableMemory in text mode.
Use total minus available memory instead of manually computed used-
memory as fraction part in bar mode (if available).
2021-02-07 12:41:52 +01:00
0d67263b36 Merge branch 'stderr_cache' of cgzones/htop 2021-02-06 16:10:22 +01:00
7b1fa1bf49 Cache stderr to be able to print assert messages 2021-02-05 19:21:28 +01:00
fd2a0cf421 FreeBSD: add support for CPU frequency and temperature 2021-02-05 16:32:25 +01:00
64a1ab848f configure: ignore usage of C11 _Generic on FreeBSD
BatteryMeter.c:30:8: error: '_Generic' is a C11 extension [-Werror,-Wc11-extensions]
   if (isnan(percent)) {
       ^
/usr/include/math.h:114:2: note: expanded from macro 'isnan'
        __fp_type_select(x, __inline_isnanf, __inline_isnan, __inline_isnanl)
        ^
/usr/include/math.h:82:39: note: expanded from macro '__fp_type_select'
#define __fp_type_select(x, f, d, ld) _Generic((x),                     \
                                      ^
1 error generated.
2021-02-05 15:20:00 +01:00
cae47bb28d configure: add -lelf for static build on FreeBSD 2021-02-05 15:15:01 +01:00
fd4e6b432b Use MainPanel type in State struct
The State struct holds a pointer to the main process panel.
Use the distinct MainPanel type, to improve maintainability regrading
its usage.
This avoids usages of down-casts from Panel to MainPanel, only up-casts
from MainPanel to Panel are now required.
2021-02-05 14:12:49 +01:00
fd1ad863dc Merge branch 'lsb' of eworm-de/htop (skip "n/a" values for SysArchMeter) 2021-02-04 17:27:16 +01:00
85a855f5b2 SysArchMeter: skip "n/a" values
Unavailable values are returned as "n/a" from lsb_release, skip these.

$ lsb_release -a
LSB Version:    1.4
Distributor ID: Arch
Description:    Arch Linux
Release:        rolling
Codename:       n/a
2021-02-04 13:26:39 +01:00
8fb51627b2 Improve initial setup for systems with many CPUs
Resolves #435
2021-02-02 18:03:17 +01:00
b612256486 Leave less right margin next to long (text) meters 2021-02-02 11:07:29 +01:00
ba630e8ad5 Make descriptions to -shelp available so people find threads
Fixes #511
2021-02-02 10:08:59 +01:00
ef87877826 Fix typo, align with man page, drop dots 2021-02-02 10:08:59 +01:00
f3eab4e796 Explain historic naming of Light-Weight Processes column aka threads 2021-02-02 10:08:59 +01:00
de3e271206 Merge branch 'comm' of cgzones/htop
Already in Debian so making sure upstream has it, too
2021-02-02 09:56:32 +01:00
12208af777 DiD: Avoid negative cmdlineBasenameOffset 2021-02-01 22:09:39 +01:00
12f5f06e88 Check for sortTimeout to not run towards -inf
Seems to happen on Mac OS "Big Sur" (~forced application sleep)
Partial fix for #510
2021-02-01 16:02:31 +01:00
3808b3b553 Remove unused key definitions 2021-02-01 16:01:04 +01:00
06b5828dc4 Fix Shift+Function key on Qt-based terminals
Fixes #508.
2021-02-01 09:02:36 +01:00
8bd543562b Quote SYSCONFDIR definition
As SYSCONFDIR is a compile time string literal, use compile time string
concatenation instead of a runtime one.

Also drop related TODO, cause we indeed using the correct way of getting
$sysconfdir from autoconf
2021-01-31 21:44:34 +01:00
06b1674aa6 Improve handling when selected last process entry
If the last process entry is selected and the process dies, stay at the
end of the list and do not jump to the start.

Also if the last entry is selected keep, after rebuilding the process
list due to a new scan, the last entry selected.
2021-01-31 21:44:00 +01:00
51e79ddc07 [#480] SysArchMeter to view kernel/arch info
At start, SysArchMeter calls the uname function to obtain the kernel
version and architecture. If available, the distro version is obtained
by calling lsb_release. The obtained values are stored in static
variables and used when updating the meter.
2021-01-31 20:08:09 +01:00
7bfa466abe Linux: silence UBSAN implicit conversions
pgrp and session might be -1

linux/LinuxProcessList.c:312:20: runtime error: implicit conversion from type 'unsigned long' of value 18446744073709551615 (64-bit, unsigned) to type 'unsigned int' changed the value to 4294967295 (32-bit, unsigned)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior linux/LinuxProcessList.c:312:20 in
linux/LinuxProcessList.c:314:23: runtime error: implicit conversion from type 'unsigned long' of value 18446744073709551615 (64-bit, unsigned) to type 'unsigned int' changed the value to 4294967295 (32-bit, unsigned)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior linux/LinuxProcessList.c:314:23 in
2021-01-30 14:21:26 +01:00
1014e897a7 Linux: document /proc/PID/stat field parsing 2021-01-30 14:21:26 +01:00
69efa94f9f Use String_eq wrapper instead of raw strcmp 2021-01-30 14:21:26 +01:00
04cf590967 FreeBSD: drop minflt and implement majflt 2021-01-30 14:21:26 +01:00
46370231e3 FreeBSD: drop unused idle thread code 2021-01-30 14:21:26 +01:00
8c43856380 FreeBSD: populate processor field 2021-01-30 14:21:26 +01:00
79620d01c0 FreeBSD: drop unused jail_errmsg variable 2021-01-30 14:21:26 +01:00
399add39ca FreeBSD: simplify kernel thread logic 2021-01-30 14:21:26 +01:00
56c4055fd1 FreeBSD: drop unused ProcessList fields 2021-01-30 14:21:26 +01:00
fa499fc155 FreeBSD: misc 2021-01-30 14:21:26 +01:00
fdaa15bd8d Linux: overhaul io process fields
- avoid UBSAN conversions
- print N/A on no data (i.e. as unprivileged user)
- fix rate calculation to show bytes (instead of a thousandth)
- print bytes as human number (i.e. 8MB) instead of 8388608
- stabilize sorting by adjusting NAN values to very tiny negative number
2021-01-30 14:21:26 +01:00
fee744abd2 Update generic process field display
- sort cases by identifier
- use check snprintf
- color nice value of 0 as gray
- color cpu and memory percentages of 0.0 as gray
- color number of threads of 1 as gray
- color idle and sleeping state as gray
- color tgid matching pid (indicating main thread) as gray
2021-01-30 14:21:26 +01:00
d5de1bc23d Overhaul sorting of state process column
Do not sort by ascii value of the state identifier, sort by relevance
2021-01-30 14:21:26 +01:00
a3c8285237 Refactor to tty_nr process field display
If no terminal name can be found, fall back to generic display method
with major and minor device numbers.

Print special value '(none)' in case both are zero.
2021-01-30 14:21:26 +01:00
03d6345c89 Process: document process fields
Drop unused fields 'flags' and 'exit_signal'
2021-01-30 14:21:26 +01:00
93378b9ee5 fix typo/missing newline for --enable-static
https://i.imgur.com/byraZxG.png
2021-01-30 13:20:09 +01:00
3acf28c259 Unsupported: pass compilation 2021-01-29 14:12:44 +01:00
bd694c0ce6 Do not call exit(3) in signal handler
Call safe _exit(2) instead
2021-01-29 12:38:30 +01:00
fd8c0611af Use different function on different detection method to avoid caching
Using the same function for the same library causes AC_CHECK_LIB to use
cached results.
Since we change the detection method via different or no
ncurses(5|6)-config invocation, avoid such caching by using different
functions.
2021-01-28 23:40:37 +01:00
f27bab470b Drop duplicate option
Option subdir-objects is now define in configure.ac
2021-01-28 23:40:37 +01:00
34da6fdadb Avoid syntax injection inside code block
Co-authored-by: BenBE <BenBE@geshi.org>
2021-01-28 09:21:18 +01:00
e54a790b14 TraceScreen: draw panel header 2021-01-28 09:21:18 +01:00
3c61813ea6 InfoScreen: add mouse wheel scroll 2021-01-28 09:21:18 +01:00
fd45845829 InfoScreen: fix mouse selection 2021-01-28 09:21:18 +01:00
92fb69f5a0 Merge branch 'todo' of cgzones/htop
Make CRT_init get an instance of Settings instead of a separate colorScheme
2021-01-28 07:36:14 +01:00
5644d0194b Merge branch 'default_libcap' (configure overhaul) of cgzones/htop 2021-01-28 07:31:15 +01:00
6dba60f6bd Pass Settings to CRT_init
Resolve todo
2021-01-27 17:14:15 +01:00
211121f060 Drop invalid todo
The surrounding code has nothing to do with colors
2021-01-27 17:06:21 +01:00
d77703b3dc ci: use as-needed linker flag in gcc full-featured build
Test whether there are any linking issues
2021-01-27 15:36:50 +01:00
3035e29e74 Use typedef names instead of raw struct ones 2021-01-26 21:16:23 +01:00
575edffb4b Add configure option to create static htop binary 2021-01-25 18:01:39 +01:00
759a34039c configure: fail immediately on missing requirement 2021-01-25 17:57:21 +01:00
38b6a0148f configure: misc modernizations
- require autoconf version 2.69
  was released in 2012 and one still can configure and build on older
  systems (just not generate the configure script)
- use modern C99 compiler check
- drop obsolete checks: AC_C_CONST, AC_FUNC_CLOSEDIR_VOID, AC_FUNC_STAT
- drop AC_HEADER_STDBOOL in favor of C99 compatibility
2021-01-25 17:57:21 +01:00
f3623b7880 configure: reformat for improved reabability 2021-01-25 17:57:21 +01:00
5e103ff9d1 configure: overhaul option handling
Switch Linux capabilities default from "no" to "check"

Document default settings

Use more readable formatting
2021-01-25 17:54:37 +01:00
0f04714a03 Fix possible division by zero
Do not pass a nmemb of 0 to calloc, cause it's unportable and forbidden
with our wrapper.

Found by Coverity
2021-01-25 17:33:29 +01:00
2ec44098f9 Allow meters in text mode to span empty neighbors to the right
Closes: #484
2021-01-23 15:20:47 +01:00
6f6e0ec571 Update copyright for 2021 2021-01-22 20:06:51 +01:00
d269d7247f Merge branch 'mop-up-sort-mess' of fasterit/htop 2021-01-22 16:26:42 +01:00
041feeca18 Add note to users about sort logic changes to ChangeLog 2021-01-22 16:24:33 +01:00
074703bd5c Implement stable tie-breaker and add more defaultSortDesc fields as per cgzones' suggestions, simplify Process_compare flow from BenBE 2021-01-22 09:57:44 +01:00
4dadbe3b34 configure: add -Winit-self warning 2021-01-21 19:49:07 +01:00
4531b31d92 Sort out the mess around column sorting that had accumulated over time 2021-01-21 14:27:23 +01:00
b20bb543ce Find the correct library for clock_gettime before trying to use it
Otherwise if clock_gettime is librt then this code will incorrectly believe
that the function does not exist at all.
2021-01-20 15:04:03 +01:00
03824da684 Linux: individual huge page values in the huge page meter 2021-01-19 18:06:48 +01:00
4d85848988 Linux: handle hugepages
Subtract hugepages from normal memory.
Add a HugePageMeter.

Closes: #447
2021-01-19 18:06:48 +01:00
71f51a20c1 Define PATH_MAX for GNU/hurd
Otherwise fails with
"> linux/LinuxProcessList.c:889:20: error: ‘PATH_MAX’ undeclared (first use in this function)"
2021-01-16 12:31:44 +01:00
1f20c0fb3d Linux: fall back to cpuinfo on slow scaling_cur_freq read
On some AMD and Intel CPUs read()ing scaling_cur_freq is quite slow
(> 1ms). This delay accumulates for every core.
If the read on CPU 0 takes longer than 500us bail out and fall back to
reading the frequencies from /proc/cpuinfo.
Once the condition has been met, bail out early for the next couple of
scans.

Closes: #471
2021-01-15 20:55:53 +01:00
b5a5e83470 LED Meter: display wide characters and restore non-wide ncurses support
Print wide characters, like degree sign, properly via mvadd_wch().
Ignore attributes when returning value from RichString_getCharVal() in
non-wide ncurses mode to test against raw characters.
2021-01-15 20:41:10 +01:00
b9adc30b86 RichString: implement safe rewind
The current rewind logic causes issues when rewinding over the short
string optimization boundary.
2021-01-15 20:41:10 +01:00
08ac22ddb9 RichString: refactor writing limited amount of columns
Closes: #468
2021-01-15 20:41:10 +01:00
ceee96dcba Do not try to set not owned capabilities
If the process has already less capabilities than we are trying to keep,
do not try to set them.
2021-01-13 22:12:06 +01:00
5fde0e0127 RichString_appendChr: add parameter to set attributes
Allows to set attributes when padding process fields in non-wide ncurses
mode.

Closes: #475
2021-01-13 19:22:33 +01:00
78b993dbb4 kfreeBSD: include config.h for _GNU_SOURCE (part 2)
strcasestr(3) is a GNU extension and when compiling freebsd/Platform.c
on kfreebsd for Debian <string.h> is included before we define
_GNU_SOURCE, so the function is not available.

In file included from ./Object.h:16,
                 from ./ListItem.h:12,
                 from ./Meter.h:16,
                 from ./Header.h:10,
                 from ./Action.h:15,
                 from freebsd/Platform.h:13,
                 from freebsd/Platform.c:8:
./XUtils.h: In function ‘String_contains_i’:
./XUtils.h:43:11: warning: implicit declaration of function ‘strcasestr’; did you mean ‘strcasecmp’? [-Wimplicit-function-declaration]
   43 |    return strcasestr(s1, s2) != NULL;
      |           ^~~~~~~~~~
      |           strcasecmp
./XUtils.h:43:30: warning: comparison between pointer and integer
   43 |    return strcasestr(s1, s2) != NULL;
      |                              ^~
In file included from ./Object.h:16,
                 from ./ProcessList.h:16,
                 from freebsd/FreeBSDProcessList.h:15,
                 from freebsd/FreeBSDProcessList.c:8:
./XUtils.h: In function ‘String_contains_i’:
./XUtils.h:43:11: warning: implicit declaration of function ‘strcasestr’; did you mean ‘strcasecmp’? [-Wimplicit-function-declaration]
   43 |    return strcasestr(s1, s2) != NULL;
      |           ^~~~~~~~~~
      |           strcasecmp
./XUtils.h:43:30: warning: comparison between pointer and integer
   43 |    return strcasestr(s1, s2) != NULL;
      |                              ^~
2021-01-12 19:05:46 +01:00
47cebafd77 kfreeBSD: include config.h for _GNU_SOURCE
strcasestr(3) is a GNU extension and when compiling freebsd/Platform.c
on kfreebsd for Debian <string.h> is included before we define
_GNU_SOURCE, so the function is not available.

In file included from ./Object.h:16,
                 from ./ListItem.h:12,
                 from ./Meter.h:16,
                 from ./Header.h:10,
                 from ./Action.h:15,
                 from freebsd/Platform.h:13,
                 from freebsd/Platform.c:8:
./XUtils.h: In function ‘String_contains_i’:
./XUtils.h:43:11: warning: implicit declaration of function ‘strcasestr’; did you mean ‘strcasecmp’? [-Wimplicit-function-declaration]
   43 |    return strcasestr(s1, s2) != NULL;
      |           ^~~~~~~~~~
      |           strcasecmp
./XUtils.h:43:30: warning: comparison between pointer and integer
   43 |    return strcasestr(s1, s2) != NULL;
      |                              ^~
In file included from ./Object.h:16,
                 from ./ProcessList.h:16,
                 from freebsd/FreeBSDProcessList.h:15,
                 from freebsd/FreeBSDProcessList.c:8:
./XUtils.h: In function ‘String_contains_i’:
./XUtils.h:43:11: warning: implicit declaration of function ‘strcasestr’; did you mean ‘strcasecmp’? [-Wimplicit-function-declaration]
   43 |    return strcasestr(s1, s2) != NULL;
      |           ^~~~~~~~~~
      |           strcasecmp
./XUtils.h:43:30: warning: comparison between pointer and integer
   43 |    return strcasestr(s1, s2) != NULL;
      |                              ^~
2021-01-12 17:02:16 +01:00
c865313e2d Reset cache values when setting comm value
Maybe fixes #361
2021-01-12 16:43:06 +01:00
66dd77aa6b Hashtable: use appropriate return type for nextPrime
The return value is guaranteed to be smaller than SIZE_MAX, so return
size_t (matters on 32 bit architectures).
2021-01-12 16:37:43 +01:00
2b62126aea Mark several non-modified pointer variables const 2021-01-11 23:47:00 +01:00
960f52b783 SELinuxMeter: hardcode SELINUX_MAGIC value
Avoid <linux/magic.h> include, not found by musl-gcc.
The value of SELINUX_MAGIC should really never change.
2021-01-11 23:45:47 +01:00
e6d536dd3f Add compiler hints on memory allocating utility functions 2021-01-11 21:08:58 +01:00
37e186fd66 Linux: Add SwapCached to the swap meter
According to the Linux kernel documentation, "SwapCached" tracks "memory
that once was swapped out, is swapped back in but still also is
in the swapfile (if memory is needed it doesn't need to be swapped out
AGAIN because it is already in the swapfile. This saves I/O)."
2021-01-11 20:27:47 +01:00
f4404effa4 Add option to drop Linux capabilities
Conflicts with setuid support, but that is commonly not enabled.
2021-01-11 20:19:51 +01:00
d72b0a682e Mark several non-modified pointer variables const 2021-01-11 20:12:34 +01:00
1b2d48bc9a Remove dead code 2021-01-11 20:12:34 +01:00
d9240999e9 Process: drop commLen
It is only used on Linux to optimize memory handling in case the command
changes to a smaller-or-equal string.

This "optimization" however causes more code bloat and maintenance cost
on string handling issues than it gains.
2021-01-11 20:12:34 +01:00
70f48f1f44 Add wrapper function for free and strdup
Reduces code in callers and helps avoiding memory leaks.
2021-01-11 20:12:34 +01:00
958112c5a3 Refactor setting filter and use safe strncpy 2021-01-11 20:12:34 +01:00
a118928dee XUtils: add safe strncpy implementation
The standard strncpy fails to null-terminate the destination in case
the source is longer than the passed size.
2021-01-11 20:12:34 +01:00
3715301fe3 Drop always false condition
The previous if conditional branch would have been taken
in case this condition would be true,
2021-01-11 20:12:34 +01:00
d53398fb48 Fix git log remainder in ChangeLog 2021-01-11 19:40:19 +01:00
58ce887d14 Update version number to 3.0.6-dev to identify git repo builds 2021-01-11 18:59:55 +01:00
ce6d60e7de Release 3.0.5 2021-01-11 18:18:21 +01:00
5d92a9f20d Merge branch 'fix-palette2' of deviant/htop 2021-01-11 17:45:59 +01:00
b3500ac3b7 Clarify that only the main screen function bar is optionally hidden 2021-01-11 13:50:34 +01:00
2ba8a81d47 Fix clearing the last line in setup on function bar change (thanks cgzones) 2021-01-11 13:47:33 +01:00
V
f2f1c99ad9 Fix white text in the Light Terminal colour scheme 2021-01-11 12:54:19 +01:00
1ffe5d79bd Make Infoscreens the correct height 2021-01-11 12:53:07 +01:00
8502f4e64f Merge branch 'wide_proc_comm' of cgzones/htop 2021-01-11 12:43:39 +01:00
a5db139a0a Linux: use correct column alignment for wide fields
This affects:
- PROC_COMM, PROC_EXE and CWD on Linux
- JAIL on FreeBSD and DragonFlyBSD
- ZONE on Solaris
2021-01-11 12:02:25 +01:00
8a67d7f086 Merge branch 'RichString_attrn' of cgzones/htop 2021-01-11 09:36:42 +01:00
0b89c66f58 Merge branch 'following_exit' of cgzones/htop 2021-01-11 09:36:25 +01:00
3bb731c645 RichString_setAttrn: refactor to take a length instead of a stop index
Fixes: #459
2021-01-10 16:51:25 +01:00
fbaa0cd146 Exit follow mode cleanly after followed process dies 2021-01-10 16:43:24 +01:00
a076488809 Solaris: make Process callbacks static
Fixes prototype of SolarisProcess_compareByKey since 90ea3ac3
2021-01-09 20:17:31 +01:00
6301d5c1da Convert unnecessary static variables
They are not used in any other function and are not used maybe
uninitialized.
2021-01-09 14:31:07 +01:00
4979245aa5 Update help and man page for improved -t / -s options 2021-01-08 21:34:30 +01:00
0155980fd6 Free memory on multiple filter command line arguments 2021-01-08 21:07:05 +01:00
2af90b711f Merge branch 'err_h' of cgzones/htop 2021-01-08 17:39:04 +01:00
d55f394541 Merge branch 'light_color' of cgzones/htop 2021-01-08 17:35:26 +01:00
c7d93a8f30 Merge branch 'ncurses_format' of cgzones/htop 2021-01-08 17:31:06 +01:00
2d2a2df6f2 Refactor crash handler message to avoid embedded directive
CRT.c:821:2: error: embedding a directive within macro arguments has undefined behavior [-Werror,-Wembedded-directive]
#ifdef HAVE_EXECINFO_H
 ^
CRT.c:823:2: error: embedding a directive within macro arguments has undefined behavior [-Werror,-Wembedded-directive]
#endif
 ^
CRT.c:858:2: error: embedding a directive within macro arguments has undefined behavior [-Werror,-Wembedded-directive]
#ifdef HTOP_DARWIN
 ^
CRT.c:862:2: error: embedding a directive within macro arguments has undefined behavior [-Werror,-Wembedded-directive]
#endif
 ^

CRT.c:864:2: error: embedding a directive within macro arguments has undefined behavior [-Werror,-Wembedded-directive]
#ifdef HTOP_DARWIN
 ^
CRT.c:868:2: error: embedding a directive within macro arguments has undefined behavior [-Werror,-Wembedded-directive]
#endif
 ^
2021-01-08 16:53:16 +01:00
de645ea16c ci: enable format attributes in ncurses headers
Avoid format string issues like bfcb8ca0 by helping compilers spot such
bogus usages.

Also use LTO and O3 in the full-featured gcc job, which might trigger
additional warnings on advanced inlining, like
3695cbd5d8 and
ad3acfc847
2021-01-08 14:05:56 +01:00
6ae56f2578 Revert color change on LightTerminal
Partially revert 4b14ab9789

ColorPair(Black,Black) is not actually black on black, but due to
adjustments in CRT_setColors() black on default-background-color.

Thanks to V for reporting.
2021-01-08 11:25:25 +01:00
V
bfcb8ca019 InfoScreen: fix uncontrolled format string
mvwprintw takes a format string as its fourth argument, and title is
user-controlled. This results in e.g. crashing when trying to trace a
process with a format specifier in its command line.
2021-01-08 11:06:38 +01:00
d800d7a3ce Drop usage of formatted error messages from <err.h>
They do not clean up the ncurses environment, leaving the terminal in a
broken state.

Also drop bare usage of exit(3).
2021-01-07 16:10:05 +01:00
27db9297b7 Show arrow indicating order of sorted process column 2021-01-07 14:46:44 +01:00
330d4fe22f Unify prototype of Vector_get
Vector_get() currently takes a `const Vector*` in debug mode and a
`Vector*` else.
2021-01-06 17:14:06 +01:00
8e10cde800 Hashtable: fail hard on too big size request 2021-01-06 16:59:28 +01:00
ca2c01bd16 Hashtable: widen size from int to size_t 2021-01-06 16:59:28 +01:00
7043a93eba Hashtable: hide implementation of Hashtable and HashtableItem 2021-01-06 16:59:28 +01:00
8fe04b7494 Hashtable: use more distinct typename for key type 2021-01-06 16:59:28 +01:00
43d5c61884 LibSensors: add support for Ryzen CPUs 2021-01-06 16:54:59 +01:00
e103ec0317 Declare for loop variables inside the loop 2021-01-06 16:43:18 +01:00
7ff654f2df Drop useless double parenthesis 2021-01-06 16:42:54 +01:00
7386c6fed0 Avoid function cast by refactoring callback prototype 2021-01-06 16:42:45 +01:00
ce9e7fd14f Panel_new: reorder arguments
Reorder owner and type so they match the order of Panel_init
2021-01-04 23:12:43 +01:00
badeaf9e82 IncSet: do not resize on our own and do not search on resize
The supervising ScreenManager will resize all Panels.
Also do not start the search on resize.
2021-01-04 23:12:43 +01:00
a3cced9fb6 Add option to hide the Function Bar
Support three settings:
  - Always show Function Bar
  - Always hide the Function Bar, except in Infoscreens (Env/Locks...)
    and when editing the search and filter mode
  - Hide the Function Bar on ESC until the next user input

Closes: #439
2021-01-04 23:12:43 +01:00
24c5ca9ddf Panel: rework hight logic
The hight of a Panel dpends on whether the Panel has a header or not.
Also the header migth not be set on Panel creation, like in the
MainPanel. This currently causes the cursor to get hidden behind the
FunctionBar on down-scrolling.
2021-01-04 23:12:43 +01:00
eb6f8d569d Action: drop resize callback
The supervising ScreenManager will resize all Panels
2021-01-04 23:12:43 +01:00
8c8149d146 XUtils: check for multiplication overflow in allocation size 2021-01-02 22:35:13 +01:00
a150a81669 Fix CPU percentage on M1 silicon Macs 2021-01-02 22:33:20 +01:00
90ea3ac3c9 Object: return int on comparison
Comparisons do, due to the new introduced shaceship-comparisons,
only return -1, 0, 1 or the result of strcmp().
2021-01-02 00:00:17 +01:00
293c16e22d Only initialize and gather delay accounting data if a related column is enabled
Avoid creating and communicating over a netlink socket by default, which
triggers cap_net_admin checks as root.
2021-01-01 21:34:22 +01:00
f6aa5d29bb Action: remove trivial wrapper function 2021-01-01 21:31:30 +01:00
2c06566405 LoadMeter: dynamically adjust color and total of bar
Change the color and total based on the actual 1min load value:

    < 1         : green and total of 1.0
    < cpu-count : yellow and total of cpu-count
    else        : red and total of 2*cpu-count

Closes: #32
2020-12-26 13:32:29 +01:00
d609c04fe4 CRT: add METER_VALUE_ERROR and adjust some METER_VALUE_WARN colors 2020-12-26 13:32:29 +01:00
ca9d7cd708 Also find libsensors.so.4 for Fedora and friends 2020-12-25 13:05:37 +01:00
debeac49cd Merge branch 'cpufreq' of hadfl/htop for Solaris / OmniOS support 2020-12-25 12:24:03 +01:00
a0b899f29d Note Shift-F3 use in man page 2020-12-25 11:53:02 +01:00
8b83a9f055 Enable going back to previous search matches (Shift-F3) 2020-12-25 11:53:02 +01:00
495f2292dc add support to display CPU frequencies on Solarish platforms 2020-12-25 09:26:50 +00:00
1cc3f8074f Merge branch 'user_wide' of cgzones/htop 2020-12-23 22:55:35 +01:00
aa08279964 Linux: accept clock CPU frequency
processor   : 0
cpu         : POWER8 (architected), altivec supported
clock       : 4024.000000MHz
revision    : 2.0 (pvr 004d 0200)

Closes: #424
2020-12-23 19:58:10 +01:00
5359eae28b Process: use correct column aligning on wide username
Closes: #421
2020-12-23 19:56:51 +01:00
f1463fdd64 Added keybind 'N' for sorting by PID 2020-12-23 18:30:26 +01:00
3edb6e1ea3 Position help labels one step to the right 2020-12-23 18:24:22 +01:00
71ddc6a6a1 Merge branch 'remove-n-keybind' of jakem72360/htop 2020-12-23 18:22:17 +01:00
b9336af76f fix argument type following prototype change in "Invert Process_compare resolution so that superclass matches run first" 2020-12-23 17:35:23 +01:00
f46ddd3230 Remove 'n' and 'N' search inc/dec keybinds 2020-12-24 03:24:15 +11:00
94d7f0b585 RichString: return number of written characters on write/append functions 2020-12-23 12:47:53 +01:00
86d2931255 Restore highlighted header of current sorted process column 2020-12-23 12:47:04 +01:00
0672be7db1 Update version number for git repo builds 2020-12-22 17:41:14 +11:00
0b989ee38c Bump version number for 3.0.4 release 2020-12-22 17:39:42 +11:00
3fb0024fd3 Merge branch 'misc' of https://github.com/cgzones/htop into cgzones-misc 2020-12-22 17:30:29 +11:00
dfb9b82607 Resolve clang-analyzer signed/unsigned comparison CI failure 2020-12-22 16:58:17 +11:00
fc7aead36b Merge branch 'harden_makecommandstr' of https://github.com/BenBE/htop into BenBE-harden_makecommandstr 2020-12-22 16:55:11 +11:00
737cd6167a Merge branch 'resize_bar' of https://github.com/cgzones/htop into cgzones-resize_bar 2020-12-22 15:25:08 +11:00
6502b02666 DiD: Ensure string offsets are inside string boundaries 2020-12-21 22:35:38 +01:00
cdfd407e2e Panel_init: initialize selectedLen member 2020-12-21 22:34:50 +01:00
64c05a1ed5 EnvScreen: mark local class functions static 2020-12-21 22:34:50 +01:00
a7612b0b7d TraceScreen: mark local class functions static 2020-12-21 22:34:50 +01:00
3ec8f67ab2 InfoScreen: drop unused member 2020-12-21 22:34:50 +01:00
10c6810bff Avoid NULL dereference on zombie processes
Fixes #361
2020-12-21 22:29:18 +01:00
068561351f Document dynamic bindings and assumed external configuration 2020-12-21 22:15:28 +01:00
9b8b380c32 De-lazy @cgzones :) 2020-12-21 20:40:00 +01:00
a09ad6b8b4 Action: sort key binding assignments
Avoid accidental duplicate usage.
2020-12-21 15:53:42 +01:00
9a86577cf2 DragonFlyBSD update
- move some functions to file scope
- drop unused global variable
2020-12-20 18:32:04 +01:00
8db8b9edac DragonFlyBSD update
- drop unused kinfo includes and link argument
- detect kvm library necessity at configure step
- fix variable typo
2020-12-20 18:22:41 +01:00
4a73e80338 Make remaining number literals use uppercase 2020-12-20 17:17:51 +01:00
5fa1c7040d Minor typo and comment clarification 2020-12-20 17:15:51 +01:00
3f9c63d5c0 MetersPanel: drop color interruption in FunctionBar 2020-12-20 17:02:20 +01:00
358d20687f Use variable-length-array instead of small dynamic allocation 2020-12-20 17:01:50 +01:00
e3862aa67e Rework drawing of FunctionBar
Draw the FunctionBar within Panel_draw instead of manually throughout
the code.
Add an optional PanelClass function drawFunctionBar, to allow specific
panels to override the default FunctionBar_draw call.
Rework the code on color change, to really change all colors (selection
markers and panel headers).

Closes: #402
2020-12-20 17:01:50 +01:00
7e7a53c415 Mark event arrays const 2020-12-20 16:58:37 +01:00
6b100b0cf4 Use upper case numeric literals
See https://rules.sonarsource.com/c/RSPEC-818
2020-12-20 16:58:17 +01:00
6e46fd6f1f BarMeter: rework text padding
In case the text is too long for the bar, try to fit by truncating at a
space character.

E.g.
    [|24.1% 2000Mhz 40°C]
    [24.1% 2000Mhz 40°C]
    [||||24.1% 2000Mhz]
    [|||24.1% 2000Mhz]
    [||24.1% 2000Mhz]
    [|24.1% 2000Mhz]
    [24.1% 2000Mhz]
    [||||   24.1%]
    [||||  24.1%]
    [|||| 24.1%]
    [||||24.1%]
    [|||24.1%]
    [||24.1%]
    [|24.1%]
    [24.1%]
    [24.1]
    [24.]
    [24]
    [2]
2020-12-20 16:55:17 +01:00
22da57d621 CPUMeter: drop minimum width of CPU usage in bar mode
The usage percentage is the first text, no need to set a minimum width.
The BarMeter does already add padding.
2020-12-20 16:55:17 +01:00
c5e31ba4aa Meter: fix artifacts with very tiny width
- The Bar Meter might override the right border
- The TextMeter might wrap-around into the next line
2020-12-20 16:55:17 +01:00
f878f302ca Remove duplicate newline in CRT_fatalError calls 2020-12-19 21:30:39 +01:00
67ccd6b909 Unhardcode tick-to-ms conversion
Division by 100000.0 worked because `sysconf(_SC_CLK_TCK)` happened to be 100.

By unhardcoding:

1) It becomes more clear what this 100000.0 figure comes from.
2) It protects against bugs in the case `sysconf(_SC_CLK_TCK)` ever changes.
2020-12-19 21:30:39 +01:00
f614b8a19f Mark Platform_defaultFields const 2020-12-19 21:13:32 +01:00
c150e4bde9 Enable -Wformat=2
Now that the global format variable Process_pidFormat is gone, enable
the compiler warning -Wformat=2.
2020-12-19 21:13:32 +01:00
9f68c8d341 Merge Process_pidColumns into Process_fields and rework auto-fit for PID-like columns 2020-12-19 21:13:32 +01:00
89473cc9ae Rework enum ProcessField
Use only one enum instead of a global and a platform specific one.
Drop Platform_numberOfFields global variable.
Set known size of Process_fields array
2020-12-19 21:13:32 +01:00
d872e36308 LinuxProcess: drop dead Process columns 2020-12-19 21:13:32 +01:00
77db240b48 Split boilerplate and platform-independent field comparison
This acheives two things:
- Allows for simple tie-breaking if values compare equal (needed to make sorting the tree-view stable)
- Allows for platform-dependent overriding of the sort-order for specific fields

Also fixes a small oversight on DragonFlyBSD when default-sorting.
2020-12-19 16:02:34 +01:00
2327260ee8 Separate tree and list sort orders
Implements the suggestion from https://github.com/htop-dev/htop/issues/399#issuecomment-747861013

Thanks to the refactors from 0bd5c8fb5da and 6393baa74e5, this was really easy
and clean to do.

It maintains the "Tree view always by PID" option in the Settings, which
results in some specific behaviors such as "clicking on the column header to
exit tree view" and "picking a new sort order to exit tree view", for the sake
of the muscle memory of long time htop users. :)
2020-12-19 16:02:34 +01:00
e8c6994f40 Add "Tree view is always sorted by PID" option to mimic htop 2 behavior 2020-12-19 16:02:34 +01:00
3d1703f16f Invert Process_compare resolution so that superclass matches run first
* This removes duplicated code that adjusts the sort direction from every
  OS-specific folder.
* Most fields in a regular htop screen are OS-independent, so trying
  Process_compare first and only falling back to the OS-specific
  compareByKey function if it's an OS-specific field makes sense.
* This will allow us to override the sortKey in a global way without having
  to edit each OS-specific file.
2020-12-19 16:02:34 +01:00
52fa4e7ee4 Fix typo 2020-12-18 23:35:28 +01:00
27b8d81ed2 ProcessList: save scan time in millisecond
The delay is saved in deciseconds, use a bigger resolution to avoid
timing irregularities.
2020-12-18 22:43:21 +01:00
26993d2d2b Support clock_gettime() on OSX El Capitan and earlier 2020-12-18 22:43:21 +01:00
0401df8cbd Update key mapping documentation for sorting 2020-12-18 07:37:23 +01:00
0cb257586a Move macro definitions close to usage 2020-12-16 19:13:56 +01:00
1193c6e349 Use common naming for bare enum types 2020-12-16 19:13:56 +01:00
edd6130be7 MainPanel: use actual KEY_RESIZE instead of KEY_SHUFFLE
KEY_RESIZE (0632) is equal to KEY_SHUFFLE (0x19a)
2020-12-16 19:12:50 +01:00
107e3c8aa5 MainPanel: do not reset hideProcessSelection on KEY_SHUFFLE
KEY_SHUFFLE might get send from time to time, e.g. in a tmux session.
2020-12-15 14:23:09 +01:00
4eeeb63647 LibSensors: fix unversioned libsensors library name 2020-12-15 13:54:32 +01:00
eb36385a6b LibSensors: restore temperature for Raspberry Pi
sensors output:
  cpu_thermal-virtual-0
  Adapter: Virtual device
  temp1:        +58.0 C  (crit = +90.0 C)
2020-12-15 13:46:46 +01:00
79970f05f3 Meter: restore non-wide-character build
Use mbstowcs() only with wide ncurses support.

Closes: #401
2020-12-15 12:05:39 +01:00
61b8e31b41 Misc CRT cleanup 2020-12-14 21:11:20 +01:00
c9583c692d Handle absence of package CPU temperature
Resolves: #389
2020-12-14 21:07:07 +01:00
4507911cc3 Merge pull request #398 from natoscott/harden-linux-btime-init
Harden the extraction of boot time for the Linux platform
2020-12-14 17:53:24 +11:00
b7836515e8 Harden the extraction of boot time for the Linux platform
There is a possible path - albeit theoretical really - through
the btime initialization code in Linux ProcessList_new(), when
String_startsWith() is always false, which can result in btime
not being initialized.

This commit refactors the code to remove that possibility.
2020-12-14 12:16:32 +11:00
a3db2da4a7 Cleanup initialization of jiffies on the Linux platform
Small cleanups - add error handling, remove a local static
variable and refactor LinuxProcess_adjustTime (also rename
it, as its in LinuxProcessList.c not LinuxProcess.c) - and
while there, move the related 'btime' global variable into
LinuxProcessList.c so it can be made static.

Resolves https://github.com/htop-dev/htop/issues/384
2020-12-14 11:56:13 +11:00
cf982f2928 Merge pull request #395 from natoscott/man-page-linting
Remove superflous breaks around man page section heads
2020-12-14 11:48:01 +11:00
8d69a9a53e Simplify initialization of the Linux haveSmapsRollup variable 2020-12-14 01:46:29 +01:00
366b78edd9 Remove superflous breaks around man page section heads
There is no need to start a paragraph explicitly after
a section header (SH) in troff - some man linters will
complain about this as well.
2020-12-14 11:03:46 +11:00
f8a610e6e1 Merge branch 'fix-dlopen-libsensors-debian' of fasterit/htop 2020-12-13 20:09:06 +01:00
4b1a4a4ebd Merge branch 'fix_mach_timebase' of benbe/htop 2020-12-13 20:02:38 +01:00
3655b6ca0b Add column in darwin to indicate whether the the process is running under translation 2020-12-13 17:58:16 +01:00
1506283aff Move Process_fields from darwin/Platform to darwin/DarwinProcess 2020-12-13 17:58:16 +01:00
4b877eb16a Move Process_fields from unsupported/Platform to unsupported/UnsupportedProcess 2020-12-13 17:58:16 +01:00
f32f0188cd Correct timebase for non-x86 CPUs on Darwin
Fixes: #368
2020-12-13 11:47:34 +01:00
e65cdf947c Sort include in Darwin platform headers 2020-12-13 11:47:34 +01:00
ab60f59ed8 Check if clock_gettime needs linking of librt 2020-12-13 00:55:50 +01:00
8149823d56 Define O_PATH if not already defined 2020-12-13 00:55:50 +01:00
12421f460a Fix dlopen issue for libsensors5 in Debian Buster, Bullseye
libsensors.so is provided only by the -dev package, so search for
libsensors.so.5 (installed from the libsensors5 package) explicitly

see: dpkg-query -S libsensors.so
2020-12-12 20:08:17 +01:00
880eecabf5 Indentation and line continuation fixes in configure.ac 2020-12-12 19:49:52 +01:00
738d31b903 Add sys/dirent.h to iwyu/htop.imp 2020-12-11 20:57:19 +01:00
28bc087d8a Drop redundant sys/dirent.h include
sys/dirent.h is included by dirent.h in FreeBSD, and does not exist in Debian GNU/kFreeBSD
2020-12-11 20:57:19 +01:00
2700d99069 Merge pull request #379 from natoscott/streamline-pagesize-variables
Cull the definitions of pageSize and pageSizeKB from CRT.c
2020-12-11 11:06:40 +11:00
75e9f9a8d9 Cull the definitions of pageSize and pageSizeKB from CRT.c
By storing the per-process m_resident and m_virt values in the form
htop wants to display them in (KB, not pages), we no longer need to
have definitions of pageSize and pageSizeKB in the common CRT code.

These variables were never really CRT (i.e. display) related in the
first place.  It turns out the darwin platform code doesn't need to
use these at all (the process values are extracted from the kernel
in bytes not pages) and the other platforms can each use their own
local pagesize variables, in more appropriate locations.

Some platforms were actually already doing this, so this change is
removing duplication of logic and variables there.
2020-12-10 11:57:48 +11:00
db5687a355 Sort in paused mode after inverting sort order 2020-12-09 13:43:07 +01:00
7b739b6292 Fix pause mode ("Z") in tree view 2020-12-09 13:28:15 +01:00
ded9c5d363 PSI Meter: use constant width and only print ten-duration as bar 2020-12-08 23:09:35 +01:00
2d231d77ca Process: simplify 2020-12-08 22:37:15 +01:00
f6613db5cd Additional code simplification
Additional correction for #375
2020-12-08 21:24:19 +01:00
4c44a70f96 Fix broken tree display on inverted sort order
Fixes #375
2020-12-08 21:12:54 +01:00
157086e750 Split RichString_(append|appendn|write) into wide and ascii
RichString_writeFrom takes a top spot during performance analysis due to the
calls to mbstowcs() and iswprint().

Most of the time we know in advance that we are only going to print regular
ASCII characters.
2020-12-08 20:58:40 +01:00
5506925b34 Use sizeof buffer instead of magic number 2020-12-08 16:36:00 +01:00
c6d9fa279b travis CI: drop macOS and Linux builds
They are covered by GitHub CI
Also testing on s390x does not serve much
2020-12-08 16:07:45 +01:00
dcf7ad386c GitHub CI: add macOS build 2020-12-08 16:07:45 +01:00
30bf212185 Merge branch 'gentoo' of cgzones/htop 2020-12-07 16:29:52 +01:00
05969998c1 SELinuxMeter: silence comparison warning on 32-bit
linux/SELinuxMeter.c: In function ‘hasSELinuxMount’:
linux/SELinuxMeter.c:38:21: warning: comparison of integer expressions of different signedness: ‘__fsword_t’ {aka ‘int’} and ‘unsigned int’ [-Wsign-compare]
   38 |    if (sfbuf.f_type != SELINUX_MAGIC) {
      |                     ^~

Origin: 7df27b78e9/libselinux/src/init.c (L40)
2020-12-07 16:05:12 +01:00
ead978bce6 configure: check for additional linker flags for keypad(3)
Gentoo requires an explicit addition of -ltinfo

Resolves: https://bugs.gentoo.org/show_bug.cgi?id=690840
2020-12-07 15:33:16 +01:00
4f88d38256 Correct the version of htop development repo 2020-12-07 19:57:44 +11:00
f03f48a0fb Change version string to note development repo build 2020-12-07 12:16:06 +11:00
ad8aa2ce77 Bump version number for 3.0.3 release 2020-12-07 11:49:14 +11:00
b92cfa7d7a Merge branch 'conversion' of https://github.com/cgzones/htop into cgzones-conversion 2020-12-07 11:41:22 +11:00
57d9ecc551 OpenBSD update
- compilation failures like `return &this->this;` -> `return &this->super;`
- iwyu update
- misc cleanup
2020-12-06 16:20:55 +01:00
ad764ff972 Introduce METER_BUFFER_CHECK and METER_BUFFER_APPEND_CHR to cleanup writing to bar buffers
Closes: #294
2020-12-06 16:03:44 +01:00
77ec86aff4 Use size_t as type for buffer length in Process 2020-12-06 16:03:44 +01:00
e1ce141bc3 Use size_t as len type for Meter_UpdateValues
Most of the time the parameter is passed to snprintf type functions
2020-12-06 16:03:44 +01:00
d9224c66a4 Use size_t as len type for xSnprintf
Like the C snprintf function
2020-12-06 16:03:44 +01:00
3d15ba5197 Remove unused function Header_readMeterName 2020-12-06 16:03:25 +01:00
7ba25aa3c4 IWYU update 2020-12-06 15:32:16 +01:00
22f8f8000c Initialize buffer for retrieved path
This avoids a warning on GCC 11.

Fixes #369
2020-12-06 11:51:03 +01:00
4c4ba9d949 DragonFlyBSDProcessList: fix missing type 2020-12-06 00:43:41 +01:00
8d1595a20e FreeBSD: fix crash on empty environment
e.g. on kernel threads
2020-12-05 20:34:23 +01:00
876194492f LinuxProcessList: add underscore suffix for raw struct name
Fit the general coding style
2020-12-05 20:25:54 +01:00
5f528b7455 Meter: fix bar coloring without wide ncurses support
attrset() seems to not work with mvaddchnstr()
2020-12-05 20:01:10 +01:00
641fd2c4ad RichString: avoid signed integer misuse 2020-12-05 20:01:10 +01:00
f913680020 Hide degree character without wide ncurses support 2020-12-05 20:01:10 +01:00
f0a9dfc37e Resolve conversion from int to char 2020-12-05 19:58:32 +01:00
1e9b184367 Resolve conversion from int to unsigned and back 2020-12-05 19:58:32 +01:00
ba1549f99b Resolve conversion from int to short 2020-12-05 19:58:32 +01:00
f61e74a4af Resolve conversion from ssize_t to int for readlink return value 2020-12-05 19:58:32 +01:00
8029e9af04 Update htop logo, provide .svg file as well 2020-12-05 13:46:34 +01:00
ef0fc7129e Update AUTHORS file with htop-dev team 2020-12-05 11:07:32 +01:00
bc16fa037f Convert personal copyright authorship to team 2020-12-04 13:55:55 +01:00
cc7f16bb8f Some minor additions to the changelog 2020-12-04 07:51:33 +01:00
1f9e2ded9e Update changelog for upcoming 3.0.3 release, annotate rc1 2020-12-04 14:05:27 +11:00
bd6237eb31 Document implicit incremental search 2020-12-03 22:41:31 +01:00
bc91a382f6 Allow to pass '/' for item search 2020-12-03 22:41:31 +01:00
bda07fa42b Handle 'q' as quit if first character 2020-12-03 22:41:31 +01:00
9adb94a379 Some visual code cleanup 2020-12-03 22:41:31 +01:00
5fe2a88c08 Use common handling for scrolling 2020-12-03 22:41:31 +01:00
a7955c4966 Reduce code duplication 2020-12-03 22:41:31 +01:00
c49ca61dd9 Common order for ESC/q/F10 2020-12-03 22:41:31 +01:00
4f08d2d5ad Fix sensors configure argument 2020-12-03 16:42:38 +01:00
64230ee5cd ci: use clang-11 2020-12-03 16:28:14 +01:00
2ec940e0d2 ci: use correct configure flags for sensors 2020-12-03 16:28:14 +01:00
d1db9da936 Linux: avoid float division by 0 after system sleep
linux/LinuxProcessList.c:1403:63: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior linux/LinuxProcessList.c:1403:63 in
2020-12-03 13:25:17 +01:00
3695cbd5d8 Silence possible NULL dereference
Found by compiling with LTO

  ProcessList.c: In function ‘ProcessList_updateTreeSetLayer’:
  ProcessList.c:195:15: error: potential null pointer dereference [-Werror=null-dereference]
    195 |       if (proc->tree_depth == deep && proc->tree_left > left && proc->tree_right < right) {
        |               ^
  ProcessList.c:195:15: error: potential null pointer dereference [-Werror=null-dereference]
  ProcessList.c:195:15: error: potential null pointer dereference [-Werror=null-dereference]
2020-12-03 12:32:54 +01:00
fe84840314 Add Linux cwd process column 2020-12-03 09:21:28 +01:00
c6b66a75ea Minor code streamlining 2020-12-02 23:50:05 +01:00
709821ff55 Some minor spelling issues 2020-12-02 23:50:05 +01:00
2d874177bc Avoid expensive build of tree when not using it 2020-12-02 23:50:05 +01:00
bd24664fc2 Avoid useless search for pid 0 2020-12-02 23:50:05 +01:00
d0e71cb75f Reorder field initialization to group fields by task 2020-12-02 23:50:05 +01:00
e3b6049043 Code style cleanup and documentation/comments 2020-12-02 23:50:05 +01:00
b4b952d78d Use common values for initial size estimates for Hashtables 2020-12-02 23:50:05 +01:00
4907d90cff Fix issue with inconsistent displayTreeSet 2020-12-02 23:50:05 +01:00
cf306ff86e Implement sorting in tree mode 2020-12-02 23:50:05 +01:00
4f7d48aa24 Set locale only once and do not override it later 2020-12-02 22:08:25 +01:00
b76eaf187a Dynamically load libsensors at runtime 2020-12-02 21:03:24 +01:00
f7a8952933 Add xReadfile wrapper for reading small to medium size files
Inspired by proposed Linux syscall

Avoid file descriptor leaks like 4af8c63f
2020-12-02 20:39:36 +01:00
1d8192c10b PressureStallMeter: improve display strings
- Shorten name for header setup menu
- Improve caption in bar mode
2020-12-02 19:51:43 +01:00
472f0124cd Meter: document MeterClass string fields 2020-12-02 19:51:43 +01:00
c0b50164dd Use String_eq for readability and consistency 2020-12-02 19:14:22 +01:00
7975cd2ca3 Add cast to unsigned char to avoid signed char misuse 2020-12-02 19:14:22 +01:00
9029cc83ad Merge identical conditional branches 2020-12-02 19:14:22 +01:00
43ee295c23 Drop redundant return statements 2020-12-02 19:14:22 +01:00
ec0f5d0ba9 Compare indices not index with pair
Fixes always true condition.

Found by LGTM.com
2020-12-02 17:54:53 +01:00
bbac4c2a62 Use enum element name instead of magic number 2020-12-02 17:52:16 +01:00
65866c69d6 Fix a little typo (spelling) in the styleguide 2020-12-01 14:15:16 +11:00
f59af39684 Merge branch 'styleguide-tweak' of https://github.com/natoscott/htop into natoscott-styleguide-tweak 2020-12-01 14:11:19 +11:00
6ab1e468ef Update docs/styleguide.md
Co-authored-by: BenBE <BenBE@geshi.org>
2020-12-01 14:05:46 +11:00
cd305b4325 Print G in gigabyte color
When printing a size like 27.2G print the G like the 27 in the gigabyte color.
2020-11-29 15:06:08 +01:00
c1563337ae Implement Hashtable_clear to empty an existing Hashtable 2020-11-29 14:54:10 +01:00
9549ca8c88 Linux: fix process parsing for hidden pid directories 2020-11-29 12:46:25 +01:00
b2a8b2426e Tweak style guide wording around single code statements
There was wording about brace-enclosing single code statements
being 'strongly encouraged' - this isn't consistently used and
IMO it introduces unnecessary noise in otherwise neat, concise
code.

I've reworded (dropped) this section and also fixed a handful
of minor typos while reading this doc a little more carefully.
2020-11-28 23:47:13 +01:00
5ee6875f73 Typo 2020-11-28 20:53:49 +01:00
a7cf6c67d6 Typo fix in docs 2020-11-28 20:47:36 +01:00
0380d0bfd5 Include documentation for COMM and EXE 2020-11-28 20:23:33 +01:00
19b5141685 Hide process selection on ESC
Do not highlight the current process line after pressing ESC in the main
screen.
Restore after pressing any key.
2020-11-28 19:49:38 +01:00
ea4f33409a Update even more snprintfs
Use size of actual buffers instead of magic numbers
2020-11-28 19:33:07 +01:00
7899ae2eb1 Replace more snprintfs, reduce buffer sizes to what is printed 2020-11-28 17:57:51 +01:00
0b29e5074c Use 'N/A' instead of 'no perm' for more consistency 2020-11-28 17:43:08 +01:00
6c306315c8 Fix reading of device nodes > 2 chars from memory maps 2020-11-28 17:06:06 +01:00
a41e5c0a80 configure: do not check functions we are using unconditionally 2020-11-28 12:35:34 +01:00
2ff2859c23 Add compat mode for systems without openat(2) 2020-11-28 12:35:34 +01:00
638207a2ff LinuxProcessList: use openat instead of building path strings
openat() is available since Linux 2.6.16
2020-11-28 12:35:34 +01:00
f704baeb82 Drop unused global ProcessList memory fields
The global ProcessList structure contains a couple of unused
fields.  'sharedMem' has never been used by any Meter, since
its not been anything other than zero in Linux /proc/meminfo
for many, many years.  The freeMem field is only used in the
usedMem calculation, so it can reside on the stack like some
other memory variables used within-calculations-only and not
exposed to the user via a Meter.
2020-11-27 07:55:58 +01:00
fee217551c Drop unneeded parameters to the ScreenManager constructor
All calls to ScreenManager_new always pass the same first
five values, the orientation is always HORIZONTAL and the
y1 parameter is always the height of the passed-in header
struct pointer.  I think its safe to assert at this point
that no VERTICAL orientation will arrive (if it does, its
no harm in re-adding this then) - so we can remove unused
conditionals (and TODOs) based on orientation too.
2020-11-26 23:55:53 +01:00
83bf8cfad6 Make casing of N/A consistent (majority was N/A) 2020-11-26 22:58:34 +01:00
2c27f1d9ab Randomly refresh M_LRS calculation, but latest after 2s 2020-11-26 22:58:34 +01:00
08d6e25301 Distinguish display of no permissions for reading M_LRS 2020-11-26 22:58:34 +01:00
31044d1729 Roll our own strtoull implementation specialized to handle the parsing requirements 2020-11-26 22:58:34 +01:00
cceab5f803 Hardcode actual conversions to read the maps file data 2020-11-26 22:58:34 +01:00
721d9112d9 Only calculate M_LRS size every 5 seconds 2020-11-26 22:58:34 +01:00
7f18b352b0 Calculate library size (M_LRS column) from maps file 2020-11-26 22:58:34 +01:00
46a2e8ac63 IOPriorityPanel: drop unnecessary buffer size decrement
xSnprintf guarantees null-termination within the passed size.
2020-11-26 20:42:38 +01:00
15fe8717b1 configure: create typedefs for fixed-sized integers if needed
If not defined in stdint.h or inttypes.h

See https://www.gnu.org/software/autoconf/manual/autoconf-2.62/html_node/Particular-Types.html
2020-11-26 20:28:38 +01:00
748f3eb7d8 Fix crash when getCommandStr not overloaded for a platform process
Closes: #343
2020-11-26 15:21:01 +01:00
d62c2e9cca LinuxProcessList_recurseProcTree: compute time only once and mark parent const 2020-11-25 22:14:35 +01:00
a6a5686388 Track file descriptors in valgrind script 2020-11-25 22:09:39 +01:00
9b31ee5b63 Drop taskstats conditional
taskstats is only checked on runtime if the column RCHAR, WCHAR, SYSCR,
SYSCW, RBYTES, WBYTES, CNCLWB, IO_READ_RATE, IO_WRITE_RATE or IO_RATE is
selected.

taskstats is currently enabled by default.

Drop the taskstats configuration switch, to reduce the maintenance cost.
2020-11-25 20:49:39 +01:00
c88c80e3bd Drop cgroup conditional
cgroup is only checked on runtime if the column CGROUP is selected.

cgroup is currently disabled by default, but most distributions do
enable it.

Drop the cgroup configuration switch, to reduce the maintenance cost.
2020-11-25 20:49:39 +01:00
267014cbfe Add support to change numeric options in settings screen
Like delay or highlightDelaySecs
2020-11-25 20:46:27 +01:00
adf9185209 Fully support non-ascii characters in Meter-Bar
Currently the code does not handle multi-byte characters, so length-
computations take the raw count of C characters and not the to displayed
size into account.

An example is the degree sign for temperatures.

Closes: #329
2020-11-25 20:45:54 +01:00
c038326a70 LinuxProcessList: fix misspelling 2020-11-25 12:49:17 +01:00
601ad61e7d Unify naming of first argument of Platform_getBattery
Use percent throughout
2020-11-25 12:47:07 +01:00
a3221f3677 Improve Fahrenheit temperature configuration text 2020-11-25 12:44:01 +01:00
1d5b0522ac ProcessLocksScreen_draw: use Process_getCommand instead of raw comm 2020-11-25 12:43:30 +01:00
4af8c63f63 Fix file descriptor leak in LinuxProcessList_readCmdlineFile after xread failure
Found by Coverity
2020-11-24 19:54:25 +01:00
21e3063e2e Include comm before cmdline if exe could not be read, but comm mismatches basename from cmdline
Also highlights entries where exe was marked deleted
2020-11-24 19:05:48 +01:00
ec36c5ccf8 Group the "Merge Command" related options visually 2020-11-24 19:05:48 +01:00
46ee28e897 Refactor command string creation
Hopefully this patch makes it a bit more approachable how it's done.
2020-11-24 19:05:48 +01:00
27b36dab1a Make kernel thread display for COMM/EXE columns less visible and more consistent 2020-11-24 19:05:48 +01:00
45cb99d870 Minor indentation fix 2020-11-24 19:05:48 +01:00
f0a232568f Reduce visual noise to when comm and cmdline actually disagree on the program basename 2020-11-24 19:05:48 +01:00
dde2af1fdb Assume full basename matches COMM when matching full COMM buffer 2020-11-24 19:05:48 +01:00
e33d4d9460 Include merge status with column title when enabled 2020-11-24 19:05:48 +01:00
be60419630 Cleanup some documentation 2020-11-24 19:05:48 +01:00
fcda517a67 Add heuristic for space-separated cmdline 2020-11-24 19:05:48 +01:00
98fce1fb43 Compatibility function for faccessat 2020-11-24 19:05:48 +01:00
09fe94da18 Improving Command display/sort 2020-11-24 19:05:48 +01:00
42c842c190 LinuxProcess_adjustTime: simplify by not using double
Does not work with -ffast-math else.
2020-11-24 17:30:21 +01:00
95f553b10c Move treeView setting to make status bar item correct when using --sort-key, patch from @cgzones
Closes #340
2020-11-24 15:53:36 +01:00
952ee9cd77 LinuxProcessList: fix misspelling 2020-11-24 11:46:17 +01:00
72df930241 DarwinProcessList: retry getting list of all processes on ENOMEM
The process count might change between the two sysctl() calls getting
the size and getting the data.

Retry (3 times) in case the data-retrieval sysctl() call fails with ENOMEM.

see http://mirror.informatimago.com/next/developer.apple.com/qa/qa2001/qa1123.html

Related: #118
2020-11-23 17:00:32 +01:00
6c2849ec81 Linux: fix display of new thread for one cycle when hidden 2020-11-23 14:44:31 +01:00
003f2c06a4 Merge branch 'cleanup-init-done' into master 2020-11-23 17:34:44 +11:00
82a69ee87a Consistent ordering of function declarations for FreeBSD 2020-11-23 17:32:57 +11:00
17eeb7573a LinuxProcessList: skip parsing threads if the kind of thread is disabled 2020-11-22 16:49:43 +01:00
be39de14dd Reduce scope of cached values 2020-11-22 14:24:18 +01:00
be568b1153 Object: assert callbacks exists
Improves stacktraces.

Current stacktrace:
  ./htop(backtrace+0x5b)[0x45d98b]
  ./htop(CRT_handleSIGSEGV+0x189)[0x4eb5e9]
  /lib/x86_64-linux-gnu/libpthread.so.0(+0x14140)[0x7fbbfb1ea140]

New:
  ./htop(backtrace+0x5b)[0x45d98b]
  ./htop(CRT_handleSIGSEGV+0x189)[0x4eb7f9]
  /lib/x86_64-linux-gnu/libpthread.so.0(+0x14140)[0x7f62b0a65140]
  /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x141)[0x7f62b089ac41]
  /lib/x86_64-linux-gnu/libc.so.6(abort+0x123)[0x7f62b0884537]
  /lib/x86_64-linux-gnu/libc.so.6(+0x2540f)[0x7f62b088440f]
  /lib/x86_64-linux-gnu/libc.so.6(+0x345c2)[0x7f62b08935c2]
  ./htop(Vector_delete+0x873)[0x54b303]
  ./htop(Panel_done+0x7b)[0x51abbb]
  ./htop[0x4ed8ee]
  ./htop(Vector_delete+0x414)[0x54aea4]
  ./htop(ScreenManager_delete+0x37)[0x536ea7]
  ./htop[0x4d9d1a]
  ./htop[0x4d5516]
  ./htop[0x5078d7]
  ./htop(ScreenManager_run+0x69f)[0x5388bf]
  ./htop(main+0x7c6)[0x4fcf76]
  /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea)[0x7f62b0885cca]
  ./htop(_start+0x2a)[0x42688a]
2020-11-22 10:10:34 +01:00
03f9a86918 Reduce scope of local variables 2020-11-22 10:08:27 +01:00
ddda739cb2 Simplify code flow by inlining declarations where they are used
Note that xStrdup always returns non-NULL, thus the one error case cannot be reached.
2020-11-22 10:07:01 +01:00
3cb96f1a36 No need to check for change when no action is required 2020-11-22 10:04:54 +01:00
98943d595e Reduce scope of totaltime 2020-11-22 10:04:18 +01:00
51be2d5415 Fix NULL pointer dereference on kstat_lookup failure 2020-11-22 10:03:55 +01:00
d2c64c16e6 Fix build for custom make targets 2020-11-21 22:31:10 +01:00
0f4e3ebc95 Simplify page size related calculations 2020-11-21 19:39:45 +01:00
fa002c0ba9 Rename virtual memory column from M_SIZE to M_VIRT
Closes: #325
2020-11-21 19:39:45 +01:00
3e5cba91ce LinuxProcess: mark LinuxProcess_printDelay static 2020-11-21 19:26:55 +01:00
4fb82e301d fix indent 2020-11-21 19:26:42 +01:00
f752c6e2d1 Remove unnecessary parens 2020-11-21 16:07:19 +01:00
f5c3349bdb IWYU update (FreeBSD) 2020-11-19 23:51:50 +01:00
7cf5277594 IWYU update (Linux) 2020-11-19 23:51:50 +01:00
5d50f43d5f Add whitespace to improve Linux Platform_init readability 2020-11-19 19:00:00 +11:00
c75c5ef9c6 Minor cleanups to platform-specific init and done
Move platform-specific code out of the htop.c main function
and into the platform sub-directories - primarily this is
the Linux procfs path check and sensors setup/teardown; not
needed on any other platforms.  No functional changes here.
2020-11-19 12:32:07 +11:00
329011bb98 Add missing OpenBSD battery function declaration 2020-11-19 12:00:56 +11:00
0a2105eb22 Spelling corrections 2020-11-18 13:59:55 +01:00
f720868998 Align command line argument descriptions in help output
Also drop #link comment
2020-11-18 13:59:36 +01:00
0eb3c7589d Merge individual Battery.[ch] files into Platform.[ch]
Small changes from review - keep headers sorted and keep local
variable declarations at the top of source files.
2020-11-18 10:17:33 +11:00
ea9622b8c9 Merge individual Battery.[ch] files into Platform.[ch]
Consistent with everything else involving platform-specific
calls from core htop code.
2020-11-18 10:17:33 +11:00
e3af8d0d08 DarwinProcessList: mark local functions static and sort includes 2020-11-17 21:50:38 +01:00
ba2d59020d DarwinProcess: mark local function static and sort includes 2020-11-17 21:50:38 +01:00
b3b890f546 Use 0 as no-match value for sortkey
Field numbers start at 1, and using -1 as no-match special value triggers
static analyzers using a potential negative array access.
2020-11-17 13:06:31 +01:00
f38af725c2 Silence theoretical memory leak
In practice systemctl should never return multiple SystemState= lines.
2020-11-17 13:06:31 +01:00
fec9af4e6f Merge branch 'temperature_v2' of cgzones/htop
Closes #111, closes #49
Closes #93 - thank you for leading the way @DX37 (Maxim Kurnosenko)!
2020-11-17 11:05:15 +01:00
a94fd87b05 Avoid calling Object_isA from inside Vector_isConsistent 2020-11-17 08:06:02 +01:00
307c34b028 Hashtable: use dynamic growth and use primes as size
Dynamically increase the hashmap size to not exceed the load factor and
avoid too long chains.

Switch from Separate Chaining to Robin Hood linear probing to improve
cache locality.

Use primes as size to further avoid collisions.

E.g. on a standard kde system the number of entries in the ProcessTable
might be around 650.
2020-11-17 02:01:02 +01:00
7914ec201e Hashtable update
- use consistent type for key by introducing a new typedef
- use unsigned types for sizes
- name parameters in foreach function typedef
2020-11-17 02:01:02 +01:00
15eab2012d Add process column for normalized CPU usage
Shows the process CPU usage divided by the number of CPU cores
2020-11-16 18:14:06 +01:00
a8a723ffe9 Add debug state to the configure report (thanks @benbe for the idea) 2020-11-16 17:01:51 +01:00
1b225cd7a0 Show CPU temperature in CPU meter
Show the CPU temperature in the CPU meter, like CPU frequency, instead
of using an extra Meter.
2020-11-16 16:38:54 +01:00
309f1d7282 hwloc = (portable) HardWare LOCality, not related to lock 2020-11-16 13:29:37 +01:00
8bc083c6c6 Merge branch 'highlight-new-old-processes'
Thanks to @adsr for the great work
Closes #241, closes #74
Massive rebase, so #keepfingerscrossed
2020-11-16 13:19:31 +01:00
19868a3c29 Fix whitespace before comma in the new color definitions 2020-11-16 13:18:29 +01:00
8f2d129dce Apply patch from BenBE as per https://github.com/htop-dev/htop/pull/241#issuecomment-720081138 2020-11-16 12:55:32 +01:00
0951090fa4 Merge branch 'hili-new-old' of adsr/htop into highlight-new-old-processes 2020-11-16 12:55:07 +01:00
0411fdbcef Use spaceship comparison for TTYs 2020-11-15 22:54:14 +01:00
f856fe6463 Early skip non-directories when searching for process information 2020-11-15 22:54:14 +01:00
ad72b747fa Drop hideThreads Setting
It is only used to read process directories on RedHat beginning with a dot.
Unconditionally accept directories with a starting dot.
2020-11-15 22:54:14 +01:00
9f67b95308 Mark local functions static 2020-11-15 18:35:30 +01:00
91317322fe Mark ProcessList_keyAt argument const 2020-11-15 18:35:30 +01:00
42073babb9 Use uid_t type for Process_getuid 2020-11-15 18:35:30 +01:00
397b5c4bd0 Introduce spaceship comparison for Processes
If currently two unsigned values are compared via `a - b`, in the case b
is actually bigger than a, the result will not be an negative number (as
-1 is expected) but a huge positive number as the subtraction is an
unsigned subtraction.

Avoid over-/underflow affected operations; use comparisons.
Modern compilers will generate sane code, like:
    xor     eax, eax
    cmp     rdi, rsi
    seta    al
    sbb     eax, 0
    ret
2020-11-15 18:25:21 +01:00
d785b1bbc3 Fixup of SystemdMeter merge 2020-11-15 17:53:31 +01:00
f2b2735e07 Resolve merge conflicts, merge #229 "Add SystemdMeter" from @cgzones 2020-11-15 14:52:25 +01:00
bb908f3dc4 Resolve merge conflicts, merge #298 "Macro cleanup" from @BenBE 2020-11-15 14:33:09 +01:00
da2dcf9505 Remove duplicate test for NUL
Fixes #308, thanks @qarmin (Rafał Mikrut)
2020-11-15 14:16:23 +01:00
9e976b899b Merge pull request #239 from StoneBam/list-locks 2020-11-14 16:03:17 +01:00
d431786fca Split data array for file lock information into separate fields 2020-11-14 15:51:26 +01:00
18763051a2 Split platform dependent parts for file locks screen 2020-11-14 15:51:26 +01:00
2d6da2e520 Add compat wrapper for readlinkat 2020-11-09 19:17:57 +01:00
84dad4c38e Implement screen for active file locks 2020-11-09 19:17:57 +01:00
e7b95feee4 Remove unnecessary braces 2020-11-02 22:15:01 +01:00
0e922d4085 Integrate NAN check into assignment
The check for NAN is kept to avoid relying on implementation details of the CLAMP macro/function
2020-11-02 22:15:01 +01:00
cb8bb12974 Shorten initializer 2020-11-02 22:15:01 +01:00
1c060a9d6b Avoid RichString_beginAllocated being ammendable 2020-11-02 22:15:01 +01:00
0d64ca9262 Wrap inline structure definitions 2020-11-02 22:15:01 +01:00
45869513bf Embracing branches 2020-11-02 22:15:01 +01:00
61e14d4bb2 Spacing around operators 2020-11-02 22:15:01 +01:00
b23f8235e2 Whitespace and indentation issues 2020-11-02 22:15:01 +01:00
9a16b1079e Make scope of match macro symmetric 2020-11-02 22:15:01 +01:00
493217e814 Fix indentation to 3 spaces 2020-11-02 22:15:01 +01:00
adf797c295 Spacing after keywords (for) 2020-11-02 22:15:01 +01:00
374edb9ed5 Spacing after keywords (if) 2020-11-02 22:14:59 +01:00
0a51eae11f Spacing after keywords (while) 2020-11-02 22:14:26 +01:00
1877325329 Spacing after keywords (#define) 2020-11-02 22:14:26 +01:00
db0a13970e Convert addattrstr to static inline function
NB: The macro could have been a braced while(0) loop, which without optimization produces more code
2020-11-02 22:14:26 +01:00
c790b6ae67 Remove accidental syntax collision 2020-11-02 22:14:26 +01:00
7ab0915a6c Remove unnecessary trailing semicolon on macros 2020-11-02 22:14:26 +01:00
0806a7958b Assert Vector_get returns an object
It is generally assumed Vector_get returns a non-NULL object.
Use a generic assert in Vector_get instead of in callers.
2020-11-02 19:24:28 +01:00
742e610f1d Merge branch 'wrap' of cgzones/htop 2020-11-02 17:08:38 +01:00
0c1908832b Handle data wraparounds in IO Meters
If the current data is smaller than the previous one, either by a retrieve error
or a device removal or a original data wraparound, sanitize the value to zero.

Fixes: #299
2020-11-02 14:46:42 +01:00
a83f515f0f Address items from review 2020-10-31 20:36:53 -04:00
15652e7b81 Enclose macro arguments in parentheses 2020-10-31 19:54:03 +01:00
2a9e8ca074 Add SystemdMeter 2020-10-31 19:51:42 +01:00
ab17ef4dc0 Zram Meter feature 2020-10-31 18:51:53 +01:00
43d274a617 Use integer type for item count instead of char 2020-10-31 18:36:55 +01:00
59ef15b2ad Fix segmentation fault when column name is NULL.
So, some columns (ex: SECATTR) can be sortable now.
2020-10-31 18:34:34 +01:00
6787c43097 Merge branch 'source-format' of BenBE/htop
Closes #158
2020-10-31 17:58:30 +01:00
de884d17bb Documentation on the repository style guide 2020-10-31 11:11:40 +01:00
dde71c6637 Highlight new and old processes (#74) 2020-10-30 21:56:16 -04:00
bbf01054bf Add compat wrapper for fstatat 2020-10-29 22:21:42 +01:00
049046c700 FreeBSD: update Process 2020-10-29 22:21:42 +01:00
97ea45ca9a FreeBSD: update ProcessList 2020-10-29 22:21:42 +01:00
c2fdfd99eb FreeBSD: implement Platform_getDiskIO() 2020-10-29 22:21:42 +01:00
c91061c84b FreeBSD: Platform update 2020-10-29 22:21:42 +01:00
88eec2dc00 FreeBSD: rework tty process column 2020-10-29 22:21:42 +01:00
ddbb0c2c35 Add HTOP_$platform defines to config.h header
Can be used to conditionally compile platform specific code.
2020-10-29 22:17:52 +01:00
03b773b701 Small ListItem update 2020-10-28 20:49:11 +01:00
6375df49c9 Simplify RichString_begin 2020-10-28 19:57:10 +01:00
887dfde308 Implement Process_getParentPid and Process_isChildOf as functions
Make it more readable and fix unenclosed macro arguments
2020-10-28 19:57:10 +01:00
76797f8d92 Implement Process_isUserlandThread as function
Make it more readable and fix unenclosed macro arguments
2020-10-28 19:57:10 +01:00
d33b2be2ca Implement LinuxProcess_effectiveIOPriority as function
Make it more readable and fix unenclosed macro arguments
2020-10-28 19:57:10 +01:00
6b3dbd5c67 Implement IncSet_filter as function
Make it more readable and fix unenclosed macro arguments
2020-10-28 19:57:10 +01:00
7019949574 Implement RichString_setLen as function
Make it more readable and fix unenclosed macro arguments
2020-10-28 19:57:10 +01:00
8c1f5c5a6f Enclose macro arguments in parentheses 2020-10-28 19:57:10 +01:00
61bae4c9d2 Unify function argument names
Name first argument of ProcessList_goThroughEntries consistently super
Name first argument of ProcessList_new consistently userTable
2020-10-28 19:57:10 +01:00
cf1a9ec180 Refactor LinuxProcessList_readSmapsFile to work line-oriented 2020-10-28 19:46:23 +01:00
e89b289494 Drop duplicate assignment 2020-10-27 18:00:43 +01:00
059810ca65 Drop always true condition 2020-10-27 18:00:43 +01:00
ac2b07eddd Avoid some unnecessary casts and mark some not changing variables const 2020-10-27 18:00:43 +01:00
27870bd4de Drop unneeded variablw initialization and reduce scope 2020-10-27 18:00:43 +01:00
1533ea88a6 Drop duplicate and always true condition
This block is only entered if this->owner is true.
2020-10-27 18:00:43 +01:00
c98d4577c9 Refactor code for reading process environment from procfs 2020-10-27 17:54:37 +01:00
a3bb7cbe64 Hold only a const version of Settings in ProcessList 2020-10-26 19:30:38 +01:00
4eb443926f Hold only a const version of Settings in Process 2020-10-26 19:30:38 +01:00
7109172431 Mark process parameter of Process_writeField consistently const 2020-10-26 19:30:38 +01:00
72103e9613 Hold only a const version of the ProcessList in Meters 2020-10-26 19:30:38 +01:00
f757810f48 Improve handling of no data in Disk and Network IO Meters 2020-10-26 19:17:14 +01:00
167adc0a2b Parse POWER_SUPPLY_CAPACITY
If POWER_SUPPLY_{CHARGE,ENERGY}_NOW is missing then try to use
POWER_SUPPLY_CAPACITY to determine current charge level.
2020-10-26 19:03:09 +01:00
94e32cf1e8 Simplify environment-reading code
Suggested PR changes, thanks @cgzones
2020-10-26 19:01:11 +01:00
0ae2bb1f8e Add process environment for FreeBSD 2020-10-26 19:01:11 +01:00
11bf7be9c2 Mark user field of Process const
It's a non-owning pointer to a hashtable entry.
2020-10-22 22:26:22 +02:00
b08b255b41 Drop unused Platform functions Platform_setTasksValues 2020-10-22 22:26:12 +02:00
f8bd5acdc1 Merge branch 'Fix wrong strncmp replacement' of cgzones/htop 2020-10-20 22:41:24 +02:00
e12d48a661 Fix wrong strncmp replacement
Fixes 4c66eb6d4c
2020-10-20 22:30:13 +02:00
7429c22201 Drop unnecessary cast 2020-10-20 22:29:16 +02:00
45a22080c9 Increase print buffer in NetworkIOMeter_display
In case the packet values wrap-around or have other weird values, the
current buffer might be to small
2020-10-20 21:47:26 +02:00
8a08a3209c IWYU update
- Add Settings forward declaration in Process.h
- Add assert.h include in XUitls.c
- Add conditional stdbool.h include in Object.h
- Drop unneeded stddef.h include in Richstring.c
- Drop unneeded unistd.h include in Process.h
- Drop unneeded string.h include in linux/Platform.c
- Use String_eq to avoid string.h include in Action.c
- Improve script to run custom iwyu version
2020-10-20 21:44:25 +02:00
803234a58d update Github CI
- Add a full featured clang job
- Explicit disable options otherwise enabled by default in minimal job
2020-10-20 21:44:06 +02:00
f8208f2173 Drop tabs in source indentions 2020-10-20 21:43:36 +02:00
dea19b644f s390x support for travis 2020-10-20 21:43:10 +02:00
0c5430982e Merge branch 'screenshot' of nzbart/htop 2020-10-20 10:27:34 +02:00
0ea18a6edb Merge branch 'Xalloc_Cleanup' of cgzones/htop 2020-10-20 10:23:47 +02:00
9f1a9ab2c2 Merge branch 'header_pause' of cgzones/htop
Continue to update generic data in paused mode
2020-10-20 10:17:58 +02:00
a0fb6e34f9 Merge branch 'number-cpus-from-zero' of zevweiss/htop
* This changes the default to count CPUs from zero (instead of starting at one)
* Settings logic is inverted, backwards compatibility is preserved
2020-10-20 10:06:15 +02:00
475fd1ec2d Merge branch 'help_lines' of https://github.com/cgzones/htop 2020-10-20 10:01:16 +02:00
2d57d289b1 Merge branch 'cache_pagesize' of cgzones/htop 2020-10-20 09:52:27 +02:00
4c66eb6d4c XUtils string related updates
- allow count out-parameter of String_split() to be NULL
- introduce xStrndup()
- do not allow NULL pointers passed to String_eq()
  it is not used in any code
- implement String_startsWith(), String_contains_i() and String_eq()
  as inline header functions
- adjust several conversion issues
2020-10-19 15:38:45 +02:00
577416d1a9 Assert allocating non-zero size memory
Allocating zero size memory results in implementation-defined behavior:

  man:malloc(3) :
    If size is 0, then malloc() returns either NULL, or a unique pointer
    value that can later be successfully passed to free().
2020-10-19 15:35:43 +02:00
96e2a4259e Continue to update generic data in paused mode
Generic data, as CPU and memory usage, are used by Meters.
In paused mode they would stop receiving updates and especially Graph
Meters would stop showing continuous data.

Improves: #214
Closes: #253
2020-10-19 14:45:39 +02:00
361877454f Cache PAGE_SIZE
man:sysconf(3) states:
    The values obtained from these functions are system configuration constants.
    They do not change during the lifetime of a process.
2020-10-19 14:42:35 +02:00
0db398d4c3 Allow low and high value of CLAMP to be equal
Can for example occur in RichString_setAttrn(), when pausing and
resuming process tracing:

    htop: RichString.c:56: void RichString_setAttrn(RichString *, int, int, int): Assertion `(0) < (this->chlen - 1)' failed.

    ./htop(backtrace+0x5b)[0x45d9eb]
    ./htop(CRT_handleSIGSEGV+0x189)[0x4ebab9]
    /lib/x86_64-linux-gnu/libpthread.so.0(+0x14140)[0x7fd249d35140]
    /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x141)[0x7fd249b6ac41]
    /lib/x86_64-linux-gnu/libc.so.6(abort+0x123)[0x7fd249b54537]
    /lib/x86_64-linux-gnu/libc.so.6(+0x2540f)[0x7fd249b5440f]
    /lib/x86_64-linux-gnu/libc.so.6(+0x345c2)[0x7fd249b635c2]
    ./htop(RichString_setAttrn+0x234)[0x526de4]
    ./htop(RichString_setAttr+0x50)[0x5275c0]
    ./htop(Panel_draw+0x17b6)[0x514c26]
    ./htop(InfoScreen_run+0x305)[0x4fe7a5]
    ./htop[0x4d59d8]
    ./htop[0x5029cf]
    ./htop(ScreenManager_run+0x69f)[0x52a82f]
    ./htop(main+0x704)[0x4f8774]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea)[0x7fd249b55cca]
    ./htop(_start+0x2a)[0x4268ea]
2020-10-19 14:13:58 +02:00
0f5262917f Make all required includes explicit
Information as seen by IWYU 0.12 + clang 9 on Linux
2020-10-18 20:09:05 +02:00
29346d0561 Provide basic configuration for IWYU 2020-10-18 20:07:12 +02:00
8c93f31809 Merge branch 'misaligned-struct-access' of BenBE/htop
Closes #263
2020-10-18 19:43:59 +02:00
8534dcb87c Merge branch 'strace-leaks' of BenBE/htop
Closes #262
2020-10-18 19:43:24 +02:00
3e5bc034e5 Ensure full initialization of all fields 2020-10-18 17:35:32 +02:00
4dfedd3930 Fix various file descriptor leaks 2020-10-18 17:35:32 +02:00
81543253cf Fix misaligned access inside taskstats structure
Reported by UB sanitizer (alongside several other messages):
linux/LinuxProcessList.c:782:25: runtime error: member access within misaligned address 0x614000000264 for type 'struct taskstats', which requires 8 byte alignment
0x614000000264: note: pointer points here
  64 01 03 00 0a 00 00 00  00 00 00 00 02 00 00 00  00 00 00 00 4b c8 2e 00  00 00 00 00 3e 45 3c fd
              ^

The issue doesn't cause trouble on x86, but any architecture with stricter memory alignment requirements may inadvertedly break.
2020-10-18 17:20:34 +02:00
c138d14897 Release old memory on error
Avoids leaking memory upon realloc failure.
2020-10-17 20:54:14 +02:00
5e4b182616 Combine XAlloc.[ch] into XUtils.[ch] 2020-10-17 20:54:14 +02:00
872e542f4e Rename StringUtils.[ch] to XUtils.[ch] 2020-10-16 20:30:21 +02:00
c6f04a9c5d Move xAsprintf, xSnprintf and xStrdup to StringUtils.h 2020-10-16 20:29:45 +02:00
7cd093ce95 Add NetworkIOMeter 2020-10-16 20:00:14 +02:00
a802961286 Generalize Meter value colors for IO 2020-10-16 20:00:14 +02:00
e9246abff8 Misc Vector updates
- Move swap() macro to source file and implement as function
- Implement Vector_get() and Vector_size() as inline functions
  to make them type safe and avoid lhs usage
- Comment comparison statistics, they are only needed for performance
  testing
2020-10-16 19:47:34 +02:00
a63cfc8b7c Refactor generating starttime string into Process class 2020-10-16 19:23:40 +02:00
783be7711d Do not use extra starttime process field on Linux 2020-10-16 19:23:40 +02:00
d744dac7ee Add SELinuxMeter 2020-10-16 19:20:07 +02:00
af4f58d013 Misc conversion fixes 2020-10-16 19:16:53 +02:00
1d00893110 Automatically detect if backtrace(3) needs -lexecinfo 2020-10-16 10:58:14 +02:00
846fe8a71f Mark Vector parameter const for non-modifying functions 2020-10-15 20:45:39 +02:00
3c08fa3c63 Keep building on errors
Doing so allows for more than one error to be detected in builds
2020-10-15 20:45:39 +02:00
bfa7d1fbe2 Mark search parameter in Vector_indexOf const 2020-10-15 20:45:39 +02:00
2f9381d867 Keep building on errors
Doing so allows for more than one error to be detected in builds
2020-10-15 20:31:56 +02:00
898a690375 Do not hard-code line numbers in help screen building code 2020-10-14 14:34:40 +02:00
1df7fa387a Misc CRT cleanup 2020-10-14 14:28:02 +02:00
59edb2e80c Enclose macro argument in parentheses 2020-10-13 14:56:01 +02:00
7af06659e2 Mark remaining classes const 2020-10-13 14:56:01 +02:00
5cc20e7cb2 Settings: do not save initial cpu count
Not needed and confusing with ProcessList.cpuCount
2020-10-12 13:15:23 +02:00
9f5b50edd7 CPUMeter: avoid crashes and leaks in case the CPU count changes
E.g. if the HT/SMT mode changes

Use separate data for sub-meters
Do not reuse drawData for maintainability
2020-10-12 13:15:23 +02:00
0b9a001498 Meter: use explicit type for drawData 2020-10-12 13:15:23 +02:00
25022c219d Read CPU count every cycle to avoid issues when HT/SMT mode changes 2020-10-12 13:15:23 +02:00
601480003f Centralise fault handling
This should be done as all platforms essentially did the same anyway and there was nothing platform specific.
2020-10-12 13:06:12 +02:00
b47bc667a2 Add key to pause process list updates 2020-10-12 13:04:00 +02:00
fc301b7447 Compress size of default FunctionBar 2020-10-12 13:04:00 +02:00
55eafd3b39 Add conf*/ and callgrind.out.* to list of ignored files 2020-10-11 14:21:59 +02:00
f8b9ced93f OpenFilesScreen update
- Remove local types and function from header file
- Reduce OpenFiles_Data to neccessary size
- Print file access mode (r/w/u)
- Fix memory leak on consecutive items without an intermediate file item:

    ==15257==ERROR: LeakSanitizer: detected memory leaks

    Direct leak of 120 byte(s) in 12 object(s) allocated from:
        #0 0x48c864 in strdup (htop/htop+0x48c864)
        #1 0x542f68 in xStrdup htop/XAlloc.c:71:17
        #2 0x50e225 in OpenFilesScreen_getProcessData htop/OpenFilesScreen.c:112:25
        #3 0x50cd17 in OpenFilesScreen_scan htop/OpenFilesScreen.c:141:35
        #4 0x4fd3eb in InfoScreen_run htop/InfoScreen.c:81:35
        #5 0x4d58bb in actionLsof htop/Action.c:361:4
        #6 0x501766 in MainPanel_eventHandler htop/MainPanel.c:80:19
        #7 0x5289fa in ScreenManager_run htop/ScreenManager.c:227:19
        #8 0x4f748e in main htop/htop.c:300:4
        #9 0x7ff73e0d8cc9 in __libc_start_main csu/../csu/libc-start.c:308:16

    SUMMARY: AddressSanitizer: 120 byte(s) leaked in 12 allocation(s).
2020-10-10 11:26:43 +02:00
79ad39c718 Mark Object pointer to _display function const 2020-10-10 11:25:19 +02:00
e5fdb80c7d Fix Hashtable_put to allow storing the same pointer 2020-10-09 12:23:16 +02:00
f4439b1b60 Makefile sort correction 2020-10-09 10:40:54 +02:00
41eea8a355 Mark process argument of Process_isThread const 2020-10-09 10:18:40 +02:00
7fa0f19ffd Merge branch 'master' of https://github.com/ryenus/htop
Closes  #223
2020-10-09 09:45:41 +02:00
32a2caa692 use 'w' for command wrapping as 'M' is already used
since 'M' is already used for sort-by-memory, as with:

    keys['M'] = actionSortByMemory;

reorder help info about shortcut keys
2020-10-09 09:03:32 +08:00
4a78f4bb92 Some more locations for ARRAYSIZE 2020-10-08 15:37:03 +02:00
2970cae543 Handle parsing envID & VPid from process status file
Fixes #55
Fixes #192
2020-10-07 13:14:39 +02:00
ba282cfe19 Mark Object instances const 2020-10-07 13:01:53 +02:00
08d85e6143 Mark Object classes and Object class fields const 2020-10-07 13:01:53 +02:00
164051354f Replace copy loop by memmove in Vector_insert
This is basically the same change like in Vector_take,
just in the opposite direction.
2020-10-07 12:59:55 +02:00
1704c29b90 Use memmove for Vector_take
Doing a quick check with callgrind this gives
an average reduction from 1804 cycles/call
down to 491 cycles/call on my test system.

The average was taken over about 40k calls.
2020-10-07 12:59:55 +02:00
769df604b2 Set a -dev version to bug reports show a useful version and not the last release 2020-10-07 10:35:06 +02:00
fbf6424e64 Option to set initial filter
Closes #219
2020-10-07 10:34:25 +02:00
954d6c12f5 Simplify statm parsing and document unused fields 2020-10-06 18:59:02 +02:00
3653ee35c5 Drop redundant cast to same type 2020-10-06 11:46:41 +02:00
db159e7580 Enclose CLAMP macro arguments in parentheses 2020-10-06 11:46:41 +02:00
db472075a4 Enable -Wcast-qual compiler warning 2020-10-06 11:20:07 +02:00
ad3acfc847 Handle Panel_getSelected() returning NULL
Found by compiling with LTO:

    ColumnsPanel.c: In function ‘ColumnsPanel_eventHandler’:
    ColumnsPanel.c:46:59: error: potential null pointer dereference [-Werror=null-dereference]
       46 |             ((ListItem*)Panel_getSelected(super))->moving = this->moving;
          |                                                           ^
    AvailableColumnsPanel.c: In function ‘AvailableColumnsPanel_eventHandler’:
    AvailableColumnsPanel.c:31:8: error: potential null pointer dereference [-Werror=null-dereference]
       31 |    int key = ((ListItem*) Panel_getSelected(super))->key;
          |        ^
    AvailableMetersPanel.c: In function ‘AvailableMetersPanel_eventHandler’:
    AvailableMetersPanel.c:40:24: error: potential null pointer dereference [-Werror=null-dereference]
       40 |    int param = selected->key & 0xff;
          |                        ^
    linux/IOPriorityPanel.c: In function ‘IOPriorityPanel_getIOPriority’:
    linux/IOPriorityPanel.c:37:11: error: potential null pointer dereference [-Werror=null-dereference]
       37 |    return (IOPriority) ( ((ListItem*) Panel_getSelected(this))->key );
          |           ^
2020-10-06 11:17:23 +02:00
e9fa290019 Merge branch 'update-license-and-copyright-info' 2020-10-06 10:27:38 +11:00
dc6523bf60 DateMeter followup 2020-10-05 13:59:05 +02:00
d93cac12be Add a date and datetime meter (#159)
Add a date meter and sort header and source files in Makefile

Change the lists of header and source files sorted alphabetical and one
file per line. This way diffs become better readable and merges easier.
2020-10-05 13:52:58 +02:00
ffd90c28ab Mention platform for platform specific configure options 2020-10-05 12:48:23 +02:00
577984d875 Mark argument in Object_isA const 2020-10-05 12:47:56 +02:00
cdd3913647 Merge identical declarations 2020-10-05 12:47:56 +02:00
49bb1b57f8 Assert that low value is lower than the high value in CLAMP 2020-10-05 12:47:56 +02:00
7758774890 Add Copyright statement to --help (needed as it has the license info) 2020-10-05 12:31:24 +02:00
ff455b0004 limit max screen title length to window width
Applies screen title truncating to all InfoScreen classes.
2020-10-05 12:18:05 +02:00
079c2abf8e Update License consistently to GPLv2 as per COPYING file 2020-10-05 10:13:12 +02:00
90d16b6630 Update copyright statement 2020-10-05 09:47:49 +02:00
72613a38f4 Merge branch '0000/int-sizes/00' of https://github.com/mfwitten/htop into mfwitten-0000/int-sizes/00 2020-10-05 16:19:58 +11:00
c953257de6 Merge pull request #205 from cgzones/arraysize
Introduce ARRAYSIZE
2020-10-05 16:10:02 +11:00
576b82f86a Merge branch 'attr-nonnull' of https://github.com/BenBE/htop into BenBE-attr-nonnull 2020-10-05 15:57:52 +11:00
42946ec113 Introduce ARRAYSIZE 2020-10-03 19:05:40 +02:00
b82a13c6ba Add clang analyzer CI job 2020-10-03 19:04:27 +02:00
d69585b82a Resolve DEBUG compilation issues
Use NDEBUG conditional instead of DEBUG.

Do not call static functions in extern inline ones.
    Vector.c:67:11: error: static function 'Vector_isConsistent' is used in an inline function with external linkage [-Werror,-Wstatic-in-inline]
2020-10-03 19:04:27 +02:00
b7f63292e5 Add --enable-debug configure option to enable asserts
asserts are still disabled by default.
2020-10-03 19:04:27 +02:00
e518459981 Add DiskIOMeter for IO read/write usage 2020-10-03 19:01:38 +02:00
6f387008cb Add security attribute process column 2020-10-03 18:51:17 +02:00
4b14ab9789 Adjust colors
- do not reverse CPU steal and guest in monochrome
- black on black in Light Terminal is not visible, use blue on black
- white on blue in Light Terminal is display as blue on black, use
  yellow on black
- re-draw FunctionBar after color change
2020-10-02 14:41:27 +02:00
8efc88593a InfoScreen: update content on resize 2020-10-02 14:40:15 +02:00
3afa5dfbcc minor typo in Vector.c 2020-10-02 14:39:38 +02:00
816734e2d4 Add screen shot of htop to readme
Added a basic screenshot of htop in action to the readme so that
visitors to the page can quickly get a rough idea about what htop does.
2020-10-01 20:21:44 +13:00
2cde4a7f8e Enable NULL pointer checks via compiler if supported 2020-09-29 18:07:17 +02:00
ab3171d21d Process.{h,c}: Use integer types that are more portable
When building on a 32-bit system, the compiler warned that the
following line uses a constant whose value is the overflow result
of a compile-time computation:

  Process.c (line 109):   } else if (number < 10000 * ONE_M) {

Namely, this constant expression:

  10000 * ONE_M

was intended to produce the following value:

  10485760000

However, the result overflowed to produce:

   1895825408

The reason for this overflow is as follows:

  o The macros are expanded:

      10000 * (ONE_K * ONE_K)
      10000 * (1024L * 1024L)

  o The untyped constant expression "10000" is typed:

      10000U * (1024L * 1024L)

  o The parenthesized expression is evaluated:

      10000U * (1048576L)

  o The left operand ("10000U") is converted:

      10000L * (1048576L)

    Unbound by integer sizes, that last multiplication
    would produce the following value:

      10485760000

    However, on a 32-bit machine, where a long is 32 bits
    (really 31 bits when talking about positive numbers),
    the maximum value that can be computed is 2**31-1:

      2147483647

    Consequently, the computation overflows.

  o The compiler produces a long int value that is the
    the result of overflow (10485760000 % 2**31):

      1895825408L

    Actually, I think this overflow is implementation-defined,
    so it's not even a portable description of what happens.

The solution is to use a long long int (or, even better,
an unsigned long long int) type for the constant expression;
the C standard mandates a sufficiently large maximum value
for such types.

Hence, the following change is made to the bad line:

  -   } else if (number < 10000 * ONE_M) {
  +   } else if (number < 10000ULL * ONE_M) {

However, the whole line is now patently silly, because the
variable "number" is typed "unsigned long", and so it will
always be less than the constant expression (the compiler
will warn about this, too).

Hence, "number" must be typed "unsigned long long"; however,
this necessitates changing all of the string formats from
something like "%lu" to something like "%llu".

Et voila! This commit is born.

Then, for the sake of completeness, the declared types of the
constant-expression macros are updated:

  o ONE_K is made unsigned (a "UL" instead of "L")
  o ONE_T is computed by introducing "1ULL *"
  o Similar changes are made for ONE_DECIMAL_{K,T}

Also, a non-portable overflow-conversion to a signed value
has been replaced with a portable comparison:

  -   if ((long long) number == -1LL) {
  +   if (number == ULLONG_MAX) {

It might be worth reviewing the rest of the code for other
cases where overflows are not handled correctly; even at
runtime, it's often necessary to check for overflow unless
such behavior is expected (especially for signed integer
values, for which overflow has implementation-defined
behavior).
2020-09-29 15:47:52 +00:00
e1c96879f4 Sort headers/includes 2020-09-29 17:41:49 +02:00
dac1e05a2c Fix FreeBSD compile issue
This issue was previously hidden as xSnprintf expanded to only one large command that didn't trigger the GCC formatting check.
2020-09-29 17:41:31 +02:00
736c496dbf Cleanse xStrdup mess 2020-09-29 17:41:31 +02:00
8b55113ea8 Reimplement xAsnprintf and xSnprintf as type-safe functions 2020-09-29 17:41:31 +02:00
241e4b3dbf Drop redundant declarations
- `CRT_fatalError()` is declared twice in CRT.h
- `Process_pidFormat`, `Process_writeField()` and `Process_compare` are
  declared twice in Process.h
- `btime` is defined in LinuxProcess.c and also declared in
  LinuxProcess.h, so drop in LinuxProcessList.h
2020-09-29 10:44:42 +02:00
7ae967a04b Drop redundant return statements 2020-09-29 10:44:42 +02:00
6db2d52261 Covert Meter attributes to file-local constant arrays 2020-09-29 10:44:42 +02:00
843949131a Drop redundant casts to the same type 2020-09-29 10:44:42 +02:00
214c742ae1 command screen: fill current line when scanning 2020-09-29 10:11:28 +02:00
9ee72568dc CPUMeter: add octuple-column CPU meters.
This is a straightforward extension of the existing multi-column CPU meter
code, which now allows for up CPU meters to be displayed in up to 16 columns.

This also adds the meter declarations to all the platform-specific code.
2020-09-28 14:35:35 +02:00
491bf98b90 Add missing 4-column CPU meters to non-Linux platforms. 2020-09-28 14:35:35 +02:00
d22f6573f3 CPUMeter: refactor common CPU meter rendering code.
Instead of scanning the meter name to determine the number of columns in a
CPU meter, move the common code behind some wrapper functions, and specify the
number of columns as an explicit parameter when called from the wrappers.

While this does add a bit of code for all the necessary wrapper functions, this
should be less brittle in case of future changes to the CPU meter code.
2020-09-28 14:35:35 +02:00
e75077a9f8 Merge pull request #107 from cgzones/hwlock_linuxaffinity
Make --enable-hwloc and --enable-linux-affinity mutual exclusive
2020-09-28 16:47:47 +10:00
6191336498 Merge pull request #116 from cgzones/valgrind
Add Valgrind script
2020-09-28 16:46:58 +10:00
8c9bd20013 Merge pull request #181 from cgzones/missing_prototypes
Add -Wmissing-prototypes compiler warning
2020-09-28 16:30:57 +10:00
400178a89b Merge branch 'arc-is-not-cache' of https://github.com/multiplexd/htop into multiplexd-arc-is-not-cache 2020-09-28 14:44:12 +10:00
4e282eb845 Add -Wmissing-prototypes compiler warning 2020-09-25 17:20:35 +02:00
dfa40ad0eb Linux: consider the ZFS ARC to be cache.
This commit is based on a patch originally by @edef1c. The ZFS ARC is a cache
(it's in the name), which will be evicted by the kernel if memory pressure so
requires. Hence, the ARC should not be counted towards a system's total used
memory, and should instead be grouped with the other caches in the system.

Signed-off-by: edef <edef@edef.eu>
2020-09-24 23:27:27 +01:00
18b1e9fba9 Do not drop qualifier in cast
ListItem.c:73:33: warning: cast from 'const void *' to 'struct ListItem_ *' drops const qualifier [-Wcast-qual]
   ListItem* obj1 = (ListItem*) cast1;
                                ^
ListItem.c:74:33: warning: cast from 'const void *' to 'struct ListItem_ *' drops const qualifier [-Wcast-qual]
   ListItem* obj2 = (ListItem*) cast2;
                                ^

Process.c:434:28: warning: cast from 'const void *' to 'struct Process_ *' drops const qualifier [-Wcast-qual]
   Process* p1 = (Process*)v1;
                           ^
Process.c:435:28: warning: cast from 'const void *' to 'struct Process_ *' drops const qualifier [-Wcast-qual]
   Process* p2 = (Process*)v2;
                           ^
Process.c:441:36: warning: cast from 'const void *' to 'struct Process_ *' drops const qualifier [-Wcast-qual]
   Settings *settings = ((Process*)v1)->settings;
                                   ^
Process.c:443:22: warning: cast from 'const void *' to 'struct Process_ *' drops const qualifier [-Wcast-qual]
      p1 = (Process*)v1;
                     ^
Process.c:444:22: warning: cast from 'const void *' to 'struct Process_ *' drops const qualifier [-Wcast-qual]
      p2 = (Process*)v2;
                     ^
Process.c:446:22: warning: cast from 'const void *' to 'struct Process_ *' drops const qualifier [-Wcast-qual]
      p2 = (Process*)v1;
                     ^
Process.c:447:22: warning: cast from 'const void *' to 'struct Process_ *' drops const qualifier [-Wcast-qual]
      p1 = (Process*)v2;
                     ^

AffinityPanel.c:37:16: warning: cast from 'const char *' to 'void *' drops const qualifier [-Wcast-qual]
   free((void*)this->text);
               ^
AffinityPanel.c:39:19: warning: cast from 'const char *' to 'void *' drops const qualifier [-Wcast-qual]
      free((void*)this->indent);
                  ^

linux/LinuxProcess.c:294:36: warning: cast from 'const void *' to 'struct Process_ *' drops const qualifier [-Wcast-qual]
   Settings *settings = ((Process*)v1)->settings;
                                   ^
linux/LinuxProcess.c:296:27: warning: cast from 'const void *' to 'struct LinuxProcess_ *' drops const qualifier [-Wcast-qual]
      p1 = (LinuxProcess*)v1;
                          ^
linux/LinuxProcess.c:297:27: warning: cast from 'const void *' to 'struct LinuxProcess_ *' drops const qualifier [-Wcast-qual]
      p2 = (LinuxProcess*)v2;
                          ^
linux/LinuxProcess.c:299:27: warning: cast from 'const void *' to 'struct LinuxProcess_ *' drops const qualifier [-Wcast-qual]
      p2 = (LinuxProcess*)v1;
                          ^
linux/LinuxProcess.c:300:27: warning: cast from 'const void *' to 'struct LinuxProcess_ *' drops const qualifier [-Wcast-qual]
      p1 = (LinuxProcess*)v2;
                          ^

linux/LinuxProcessList.c:62:32: warning: cast from 'const void *' to 'struct TtyDriver_ *' drops const qualifier [-Wcast-qual]
   TtyDriver* a = (TtyDriver*) va;
                               ^
linux/LinuxProcessList.c:63:32: warning: cast from 'const void *' to 'struct TtyDriver_ *' drops const qualifier [-Wcast-qual]
   TtyDriver* b = (TtyDriver*) vb;
                               ^

linux/Battery.c:130:21: warning: cast from 'const char *' to 'char *' drops const qualifier [-Wcast-qual]
      free((char *) isOnline);
                    ^
linux/Battery.c:197:26: warning: cast from 'const char *' to 'char *' drops const qualifier [-Wcast-qual]
      xSnprintf((char *) filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/type", entryName);
                         ^
linux/Battery.c:209:29: warning: cast from 'const char *' to 'char *' drops const qualifier [-Wcast-qual]
         xSnprintf((char *) filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/uevent", entryName);
                            ^
linux/Battery.c:262:29: warning: cast from 'const char *' to 'char *' drops const qualifier [-Wcast-qual]
         xSnprintf((char *) filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/online", entryName);
                            ^
2020-09-24 20:14:17 +02:00
6a03cd237a Avoid warning about unreachable break statement
htop.c:112:13: warning: 'break' will never be executed [-Wunreachable-code-break]
            break;
            ^~~~~
htop.c:109:13: warning: 'break' will never be executed [-Wunreachable-code-break]
            break;
            ^~~~~
2020-09-24 20:14:17 +02:00
cd1ba1422b Avoid bad function cast warning
linux/Platform.c:142:17: warning: cast from function call of type 'double' to non-matching type 'int' [-Wbad-function-cast]
   return (int) floor(uptime);
                ^~~~~~~~~~~~~
2020-09-24 20:14:17 +02:00
4a1f3fca96 Drop unnecessary usage of comma operator 2020-09-24 20:14:17 +02:00
4296e74ada Include prototype in Battery implementation
linux/Battery.c:291:6: warning: no previous prototype for function 'Battery_getData' [-Wmissing-prototypes]
void Battery_getData(double* level, ACPresence* isOnAC) {
     ^
2020-09-24 20:14:17 +02:00
ce0fd5f6d8 Drop unused macros 2020-09-24 20:14:17 +02:00
edf1b10d2c Read CPU frequency from sysfs by default
Use the more portable sysfs node /sys/devices/system/cpu/cpuX/cpufreq/scaling_cur_freq
to get the CPU frequency.
In case of an error fall back to /proc/cpuinfo .

Also use a fixed width of 4 for the frequency to avoid position jumps
in case the frequency moves in the range 900-1100 MHz.
2020-09-24 20:11:28 +02:00
f4e1f4619f Add DeepCode inline suppression
We just want a non-NUll pointer in the matching pid hashtable.
The pointer is not dereferenced anyways.
2020-09-24 20:04:47 +02:00
594409f299 Add DeepCode inline suppression
commsize is bounded by the allocated length passed in by commLen, saved
into commLenIn
2020-09-24 19:56:30 +02:00
005c4d1f23 Make --enable-hwloc and --enable-linux-affinity mutual exclusive
They can not be supported both at the same time.
Fail configure step instead of silently only use hwloc.
2020-09-24 19:43:27 +02:00
f4bb50294a show selected command wrapped in a separate window
For a process with a very long command, especially with many long
command line arguments, inspecting the command and its arguments could
become inconvenient.

Meanwhile htop supports the concept of "screen", or window, which is
extended here to create a dedicated "CommandScreen", making it possible
to display the command of the selected process in a separate window
meanwhile being wrapped into multiple lines.

Another benefit of using a command screen is, the user can navigate
through the wrapped lines of the command and perform actions like
searching and filtering.
2020-09-24 19:22:25 +02:00
5233817122 Avoid unsigned integer overflow
unsigned integer overflows are well-defined, but they might point to a counting issue.
Having the code free of unsigned overflows makes it easier to spot potential bugs.

  Action.c:332:27: runtime error: implicit conversion from type 'int' of value -1 (32-bit, signed) to type 'uid_t' (aka 'unsigned int') changed the value to 4294967295 (32-bit, unsigned)
  SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Action.c:332:27 in
2020-09-24 18:06:59 +02:00
7ecea3d485 Use return value of CLAMP function 2020-09-24 18:06:36 +02:00
ba0fca1800 Add -Wfloat-equal to default build flags 2020-09-24 18:06:36 +02:00
321960bd96 Update delay accounting to use NAN on error 2020-09-24 18:06:36 +02:00
3c65d78d77 Update CPU freq display to use NAN on error 2020-09-24 18:06:36 +02:00
ebcf924643 Use threshold for display of guest/steal/irq meters 2020-09-24 18:06:36 +02:00
d0d3deb73c Properly query sysconf settting and use NAN if unavailable
This also fixes an issue with time returned negative if sysconf(_SC_CLK_TCK) returned an error.
2020-09-24 18:06:36 +02:00
29ec115143 Update IO rate display to use NAN on error 2020-09-24 18:06:36 +02:00
47e2cefe02 Update battery API to use NAN on error 2020-09-24 18:06:36 +02:00
f805093589 align cpu id to right 2020-09-24 17:53:57 +02:00
d2b3a7a375 Drop dead process fields
They are nowhere used.
2020-09-24 17:48:38 +02:00
c1b5201444 Consistent wording/formatting of field descriptions 2020-09-24 17:48:17 +02:00
83257744cc Document M_PSS and M_PSSWP in man page 2020-09-24 17:48:17 +02:00
7844e06eb0 Document field M_SWAP in man page 2020-09-24 17:48:17 +02:00
2565dd3c58 Drop dead code after break 2020-09-24 17:47:17 +02:00
6b11738744 Avoid arithmetic on booleans 2020-09-23 19:09:11 +02:00
f9966b5be3 Use checked allocation wrappers 2020-09-23 17:50:21 +02:00
e0e5997c53 Fix minor regression in number highlighting
Fixes #163
2020-09-21 14:10:07 +02:00
eb260af6bf Fix memory leak on cgroup read failure 2020-09-21 13:55:29 +02:00
2c933f210b htop shows no used memory in Solaris zone 2020-09-21 13:54:45 +02:00
543286256e htop crashes on Solaris 11.4 due to missing ZFS ARC kstats 2020-09-21 13:54:45 +02:00
5ea13e7ea9 Add format attribute 2020-09-18 12:28:40 +02:00
efb971f9df Fail travis CI on compiler warnings 2020-09-18 12:28:40 +02:00
475f729a36 Resolve unused variable on FreeBSD 2020-09-18 12:28:40 +02:00
e719a85994 Mark noreturn functions 2020-09-18 12:28:40 +02:00
b85a31415e Avoid checking of undefined macros
These feature macros are either define or not defined at all at the
configure step.
2020-09-18 12:28:40 +02:00
c3952e7c20 Use strict function prototypes
int foo(); declares a function taking any number of arguments.
2020-09-18 12:28:40 +02:00
7107d1db0b Refactor __attribute__ usage
Use internal macros for compatibility with non GNUC compilers.
2020-09-18 12:28:40 +02:00
f4602f7b4e Add some default compiler warnings
Compatible with gcc and clang.
2020-09-18 12:28:40 +02:00
dd6500c7c7 Sort option in help message 2020-09-18 12:27:45 +02:00
f6b0efded5 Convert short version option to capital V
v is generally used for enabling verbose mode
2020-09-18 12:27:45 +02:00
f3b4e248a3 Drop unused variable 2020-09-18 12:22:18 +02:00
1061bd719a Change option '-m' to '-M' for consistency of cli
`-m` was added as short option for `--no-mouse`, this is inconsistence
to the rest of the cli since otherwise the short options to disable a
feature are capital letters. Therefore this commit renames the option to
`-M`.

This commit also documents the option in the man page.
2020-09-18 12:04:21 +02:00
40441dca8e Enhance highlighting of semi-large and large numbers 2020-09-17 22:08:13 +02:00
3142077c76 Add script to run htop under valgrind
Includes suppressions for ncurses leaks.
2020-09-17 22:06:36 +02:00
c7568bc054 Fix memory leak in actionSetAffinity()
Call correct delete method for AffinityPanel
2020-09-17 22:04:11 +02:00
71c068ad28 Free movingBar memory on exit 2020-09-17 22:04:11 +02:00
8a849bc85a Call character checking function with unsigned char
See https://wiki.sei.cmu.edu/confluence/display/c/STR37-C.+Arguments+to+character-handling+functions+must+be+representable+as+an+unsigned+char
2020-09-17 22:03:24 +02:00
1f5bd5c4c8 Avoid modifying optarg
It might be working, but lets rather not modify getopt's global variable
`optarg`.

Also there is no need to call `getenv("USER")`, just use `geteuid()`.
2020-09-17 21:55:26 +02:00
5d4061732f Allow third party sigsegv handler
For example from sanitizers.
2020-09-17 21:54:21 +02:00
00665e2a2b Avoid unsigned integer overflow
unsigned overflow is well defined, but creates noise when using
sanitizers. unsigned overflow can be a symptom of logic issues of
counter, so its reasonable to use.

linux/LinuxProcessList.c:64:50: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior linux/LinuxProcessList.c:64:50 in
linux/LinuxProcessList.c:64:11: runtime error: implicit conversion from type 'unsigned int' of value 4294967295 (32-bit, unsigned) to type 'int' changed the value to -1 (32-bit, signed)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior linux/LinuxProcessList.c:64:11 in
linux/LinuxProcessList.c:64:78: runtime error: unsigned integer overflow: 4 - 136 cannot be represented in type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior linux/LinuxProcessList.c:64:78 in
2020-09-17 21:53:31 +02:00
98ee833932 Add Linux process column for context switches
Displays the incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches.
2020-09-17 21:53:15 +02:00
ffc65b3827 Reorder check to avoid crash on invalid process field setting
If using a setting from a different development version with an
unsupported process field, first dereferencing Process_fields[id] yields
to a crash:

=================================================================
==19530==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000612800 at pc 0x000000521d1a bp 0x7ffec47a5ff0 sp 0x7ffec47a5fe8
READ of size 8 at 0x000000612800 thread T0
    #0 0x521d19 in readFields .htop/Settings.c:107:40
    #1 0x51d117 in Settings_read .htop/Settings.c:141:10
    #2 0x51c0c4 in Settings_new .htop/Settings.c:382:12
    #3 0x4eafe2 in main .htop/htop.c:220:25
    #4 0x7fa450570cc9 in __libc_start_main csu/../csu/libc-start.c:308:16
    #5 0x427a59 in _start (.htop/htop+0x427a59)

0x000000612800 is located 0 bytes to the right of global variable 'Process_fields' defined in 'linux/LinuxProcess.c:24:18' (0x6118a0) of size 3936
SUMMARY: AddressSanitizer: global-buffer-overflow .htop/Settings.c:107:40 in readFields
Shadow bytes around the buggy address:
  0x0000800ba4b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800ba4c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800ba4d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800ba4e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800ba4f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0000800ba500:[f9]f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x0000800ba510: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x0000800ba520: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x0000800ba530: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x0000800ba540: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x0000800ba550: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==19530==ABORTING
2020-09-17 21:46:22 +02:00
84d39f95c6 autotools: enable warnings and cleanup
- enable warnings in autogen script
- drop unused m4/ directory usage
- drop AC_TYPE_SIGNAL:
  C99 guarantees the signal return type to be void
- drop AC_CHECK_FILE of procdir:
  most of the time compilation is done on a different system than htop is run
  and there is a runtime check in place
- improve linux_affinity corss compile logic:
  use fourth argument instead of pre-test
2020-09-17 21:45:11 +02:00
37921382f4 Use PROCDIR throughout instead of /proc on Linux 2020-09-17 21:44:27 +02:00
1efddaf1e5 Check for fdopen failure in OpenFilesScreen_getProcessData 2020-09-17 21:43:53 +02:00
b096fdbfc0 Avoid potential buffer overflow in LinuxProcessList_readStatFile
Pass size of allocated command buffer and limit write.
2020-09-17 21:43:53 +02:00
95012d6259 Avoid hardcoding of buffer size 2020-09-17 21:43:05 +02:00
443a943798 Properly close pipe handles when work is done 2020-09-17 21:43:05 +02:00
6921000481 Barely ever seen any 1000 digit PIDs … 2020-09-17 21:43:05 +02:00
6646030116 Update creation date to 2004 (thanks rubyFeedback)
Closes #140 (doc update)
2020-09-17 09:47:28 +02:00
3a1c698578 Update README with correct tarball locations, ncurses hints and support / bug reporting pointers.
Closes #63 (Release URL tarballs)
Closes #61, Closes #82 (Support requests on ncurses)
Closes #89 (ncurses docs)
Closes #28 (htop-dev vs. -legacy)
2020-09-16 18:10:29 +02:00
2899ed4cb0 Number CPUs from zero by default.
Numbering from one is idiosyncratic and inconsistent with basically
everything else in the world; it doesn't make much sense as default
behavior.

All naming is updated to reflect that numbering from one is a
non-default, opt-in option.  The old label of the flag saved in htoprc
("cpu_count_from_zero") is still supported for backwards compatibility
with existing configs, however.
2020-09-15 03:25:08 -05:00
a2fef38be7 Merge pull request #130 from gh-fork-dump/no-python
configure.ac: axe python check
2020-09-15 15:51:36 +10:00
a852fae8e0 configure.ac: axe python check
Now that the automated header script is gone, there's no need for python
now.
2020-09-15 15:19:55 +10:00
da62b44b16 Bump version, changelog for minor htop-3.0.2 release 2020-09-15 09:43:36 +10:00
c9ecd0fa74 Revert the vim_mode setting for now, needs a rethink
There have been too many bugs reported in vim_mode, and
the proposed fixes are increasingly fragile - hence we
have decided to back it out for now.  For reference:

   https://github.com/htop-dev/htop/issues/69
   https://github.com/htop-dev/htop/pull/37
   https://github.com/htop-dev/htop/pull/106

The whitespace changes also arrived in commit 12805f61d
not sure what that was about, but backed out as well.
2020-09-15 09:33:58 +10:00
f6662f97fd Merge pull request #120 from cgzones/null
Drop always true condition
2020-09-15 09:21:46 +10:00
ccf0960d5c Merge pull request #123 from hugomg/header-duplicates
Clean up some code duplication in the header files
2020-09-14 17:46:18 +10:00
313d7c980c Merge pull request #127 from gh-fork-dump/openbsd-fix
fix building on openbsd due to remaining WhiteList
2020-09-14 17:42:23 +10:00
fd4ada416d fix building on openbsd due to remaining WhiteList 2020-09-14 13:18:40 +10:00
b6828d7b86 Remove some unused #includes
As suggested by cppclean.
2020-09-12 23:32:31 -03:00
a2ef400e43 Merge identical ifdefs in Affinity.h 2020-09-12 19:21:27 -03:00
5ad3c11eaa Alignment tweak 2020-09-12 19:21:27 -03:00
9207401f97 Clean up some code duplication in the header files
PR htop-dev/htop#70 got rid of the infrastructure for generating header
files, but it left behind some code duplication.

Some of cases are things that belong in the header file and don't need
to be repeated in the C file. Other cases are things that belong in the
C file and don't need to be in the header file.

In this commit I tried to fix all of these that I could find. When given
a choice I preferred keeping things out of the header file, unless they
were being used by someone else.
2020-09-12 19:20:44 -03:00
d5eb72e64d Drop always true condition
`env` is allocated by checked allocation functions and can not be NULL.

This checks confuses clang analyzer and causes a null-dereference
warning on `env[size-1]`.
2020-09-12 18:14:39 +02:00
cd55cfd6d2 Merge branch 'BenBE-avoid-shadowing' 2020-09-09 19:41:16 +10:00
35c3a95ff9 Merge branch 'avoid-shadowing' of https://github.com/BenBE/htop into BenBE-avoid-shadowing 2020-09-09 19:40:50 +10:00
06ba81beec Merge branch 'rgouicem-master' 2020-09-09 19:38:59 +10:00
4d6e4ef53c Merge branch 'master' of https://github.com/rgouicem/htop into rgouicem-master 2020-09-09 19:38:53 +10:00
4597332959 Switch variable/field naming from WhiteList to MatchList 2020-09-09 19:38:15 +10:00
c5808c56db Consolidate repeated macro definitions into one header
The MIN, MAX, CLAMP, MINIMUM, and MAXIMUM macros appear
throughout the codebase with many re-definitions.  Make
a single copy of each in a common header file, and use
the BSD variants of MINIMUM/MAXIMUM due to conflicts in
the system <sys/param.h> headers.
2020-09-09 16:56:04 +10:00
8ec5d4a3a0 Further, minor cleanups to headers post-MakeHeaders
Remove leftover empty ifdef/endif pairs, whitespace.
The generated htop.h file was also unused - removed.
2020-09-08 17:33:50 +10:00
eede79b29a Merge branch 'noheadergen' of https://github.com/zevweiss/htop into zevweiss-noheadergen 2020-09-08 16:45:11 +10:00
13b1e96b12 Avoid shadowing of variables 2020-09-07 17:36:01 +02:00
85ff6960ed Merge branch 't6-patch-freebsd-ci' 2020-09-07 10:25:50 +10:00
a1f2532630 Merge branch 'patch-freebsd-ci' of https://github.com/t6/htop-1 into t6-patch-freebsd-ci 2020-09-07 10:25:44 +10:00
7805575114 fix for double symbol link error on solaris 2020-09-05 15:34:27 +10:00
f884beda97 htop should report the nice level properly 2020-09-05 15:29:15 +10:00
0750ff7e76 Fix regression in -u optional-argument handling
Resolves https://github.com/htop-dev/htop/issues/91
2020-09-04 09:50:18 +10:00
7758ffcdea Remove duplicate jail_errmsg declaration.
Fixes: 11ecc65ebb
2020-09-03 12:00:21 -05:00
7b7822b896 Remove superfluous 'extern's from function declarations.
Applied via:

  $ find * -name '*.h' -exec sed -i -r 's/^extern (.+\()/\1/;' {} +

Suggested-by: Bert Wesarg <bert.wesarg@googlemail.com>
2020-09-03 11:59:26 -05:00
a1a027b9bd Axe automated header generation.
Reasoning:
 - implementation was unsound -- broke down when I added a fairly
   basic macro definition expanding to a struct initializer in a *.c
   file.

 - made it way too easy (e.g. via otherwise totally innocuous git
   commands) to end up with timestamps such that it always ran
   MakeHeader.py but never used its output, leading to overbuild noise
   when running what should be a null 'make'.

 - but mostly: it's just an awkward way of dealing with C code.
2020-09-03 11:58:58 -05:00
35d7e42b88 Add FreeBSD to Travis
Signed-off-by: Tobias Kortkamp <t@tobik.me>
2020-09-03 09:00:17 +02:00
7734dfe55d Merge pull request #86 from t6/patch-freebsd-fno-common
Unbreak with -fno-common on FreeBSD
2020-09-03 16:47:30 +10:00
11ecc65ebb Unbreak with -fno-common on FreeBSD
GCC10 and Clang11 now default to -fno-common.

ld: error: duplicate symbol: jail_errmsg
>>> defined at Platform.c
>>>            freebsd/Platform.o:(jail_errmsg)
>>> defined at FreeBSDProcessList.c
>>>            freebsd/FreeBSDProcessList.o:(.bss+0x90)

Signed-off-by: Tobias Kortkamp <t@tobik.me>
2020-09-03 08:42:18 +02:00
dace850fa6 Bump version, changelog for minor htop-3.0.1 release 2020-09-03 13:23:43 +10:00
4f00a95364 Merge pull request #66 from ioquatix/patch-1
Fix image logo and titles.
2020-09-03 08:35:19 +10:00
0ab508e42b Merge pull request #57 from matthiasbeyer/patch-1
Do not link INSTALL file, because link target does not exist
2020-09-03 08:20:36 +10:00
f79591ef1b Merge branch 'eworm-de-unicode-runtime' 2020-09-02 15:09:58 +10:00
746a5f279a Fix image logo and titles. 2020-09-02 11:54:17 +12:00
8ee7d58cb0 Do not link INSTALL file, because link target does not exist 2020-09-01 14:47:00 +02:00
db5adbeae0 add option (-U, --no-unicode) to disable unicode at runtime 2020-09-01 10:09:00 +02:00
f5b3e8d2a3 Merge branch 'cgzones-oom2' 2020-09-01 15:17:32 +10:00
809e4db672 Merge branch 'oom2' of https://github.com/cgzones/htop into cgzones-oom2 2020-09-01 15:17:23 +10:00
e1e60f38dc CRT: note about possible use of replacement for + glyph in tree 2020-08-31 22:35:09 +02:00
19359cec5a affinity panel: use the tree collapsing as in the process list
With one exception, the root node does also have a `-`/`+` as a prefix.
2020-08-31 22:22:22 +02:00
b0f1336f79 affinity panel: show CPUs in the topology tree as CPU x
As it is in the non-topology list.
2020-08-31 22:18:18 +02:00
f861a2c616 Revert "Use UTF-8 for check buttons and tree open/closed"
This reverts commit 5d5913d355b3a9f03da589b3542b8f55467b4ed6.
2020-08-31 22:12:46 +02:00
d0e8ff9319 fix unit (GHz -> MHz) 2020-08-31 14:09:22 +02:00
0f5d2cd1e4 fixed compilation error 2020-08-31 13:32:29 +02:00
293e3a2931 remove unused variable 2020-08-31 13:29:24 +02:00
e7f6d1ce5f Reduce oom cast from long to int
Oom values should never be greater then INT_MAX, they should be in the
range 0 - 1000.

Improves: d9a5dd4b91
2020-08-31 11:55:53 +02:00
47a7d0bd74 Merge branch 'configure' of https://github.com/cgzones/htop into cgzones-configure 2020-08-31 17:13:37 +10:00
b321177b08 Merge branch 'master' of github.com:htop-dev/htop 2020-08-31 16:57:46 +10:00
800d8c735d Merge branch 'cov_fixes' of https://github.com/cgzones/htop into cgzones-cov_fixes 2020-08-31 16:56:32 +10:00
f14173038e Merge branch 'oom' of https://github.com/cgzones/htop
Closes: #18, #22
2020-08-31 08:32:39 +02:00
fdf8a28e60 Merge branch 'Ckath-vim_mode_setting' 2020-08-31 16:14:48 +10:00
244630f67f Merge branch 'vim_mode_setting' of https://github.com/Ckath/htop into Ckath-vim_mode_setting 2020-08-31 16:14:40 +10:00
0a835e13bf Simplify the --version output, old dates are confusing people
Drop the copyright notice from the version output as a number
of people seem to be confused by what this means, and we can
do without all the (well intentioned) bug reports.
2020-08-31 16:14:23 +10:00
4bd0859b80 Add a badge/link to the released source tarballs 2020-08-31 16:12:44 +10:00
338bd829b0 add toggle for vim mode in options 2020-08-29 15:15:52 +02:00
5c99c6e942 Check btime sscanf parse from /proc/stat
Found by Coverity
2020-08-28 16:46:50 +02:00
a850d81bf5 Avoid use of uninitialized variables
Found by Coverity
2020-08-28 16:46:50 +02:00
05a5fdc47f Ignore sscanf return value of /proc/stat
Found by Coverity
2020-08-28 16:46:50 +02:00
af84d3dfa9 Fail on out-of-range CPU number
Found by Coverity
2020-08-28 16:46:50 +02:00
df41979afc Ignore wmove return value
Found by Coverity
2020-08-28 16:46:50 +02:00
d9a5dd4b91 Improve OOM output
* Fix sort by adding cast
* Shrink column size to 4
* Drop unnecessary maximum field width specifier in sscanf
2020-08-28 14:24:59 +02:00
a48ce9d103 Really tell gcc to ignore return value of fscanf 2020-08-28 13:10:41 +02:00
3f5784a3f0 Convert hwlock CI run to a full featured one 2020-08-28 13:10:41 +02:00
3b084db1c4 Print configured state 2020-08-28 13:10:41 +02:00
979d004214 Improve indent 2020-08-28 13:10:16 +02:00
5bee902665 Drop configure option --enable-proc
Move to HTOP_LINUX, as --enable-proc implies my_htop_platform=linux, and
the Linux features do not work without a proc fs.
2020-08-28 13:10:16 +02:00
3ef5df25bc always display frequency in MHz 2020-08-28 12:15:32 +02:00
2d14269bcd Merge pull request #14 from zdykstra/master
Normalize ZFS ARC caption
2020-08-28 16:58:06 +10:00
b992d52bcf Increae the size of sysfs power supply path buffers
Resolves https://github.com/htop-dev/htop/issues/15
2020-08-28 16:57:21 +10:00
f97fbd668a Normalize ZFS ARC caption
Other captions take the form of LABEL:<space>. This moves the
uncompressed ZFS ARC caption into the same style.
2020-08-28 00:02:35 -05:00
b5e6952cc6 Update link to Coverity project, still pending. 2020-08-27 10:42:40 +10:00
4a8ae4b5d4 Merge branch 'bertwesarg-affinity-fix-panel-width' 2020-08-27 09:36:56 +10:00
94b8c2e714 fix width of AffinitPanel
The panel size of 15 includes the gap to the next panel, thus use 14 as
the minimum size and let the caller of `AffinityPanel_new` handle the
gap.
2020-08-26 22:03:11 +02:00
df7e4fcdc0 Update changelog with Berts latest addition 2020-08-26 10:44:22 +10:00
728b04bbb5 Merge branch 'ci-hwloc-job' of https://github.com/bertwesarg/htop into bertwesarg-ci-hwloc-job 2020-08-26 10:39:43 +10:00
d0f31ede56 Merge branch 'ci-hwloc-job' of https://github.com/bertwesarg/htop into bertwesarg-ci-hwloc-job 2020-08-26 10:15:00 +10:00
ba94e0dfda Merge branch 'ci2' of https://github.com/cgzones/htop into cgzones-ci2 2020-08-26 10:08:50 +10:00
fc4f74aa47 ci: add clang build 2020-08-25 12:01:56 +02:00
4e2b9f0965 Avoid shadowing warnings 2020-08-25 12:01:56 +02:00
b4ceb83d76 MakeHeader.py.in: remove unused import 2020-08-25 12:00:08 +02:00
1130ad8b73 MakeHeader.py.in: remove executable bit 2020-08-25 12:00:08 +02:00
11f558f934 Avoid discarding const qualifiers 2020-08-25 12:00:03 +02:00
7457bfe9f3 Avoid string overflow warning
Use xStrdup instead of xMallow and strncpy

    StringUtils.c: In function ‘String_split’:
    StringUtils.c:86:7: error: ‘strncpy’ specified bound depends on the length of the source argument [-Werror=stringop-overflow=]
       86 |       strncpy(token, s, size + 1);
          |       ^
    StringUtils.c:84:18: note: length computed here
       84 |       int size = strlen(s);
          |                  ^
2020-08-25 11:59:59 +02:00
21fb56e1e2 Avoid string overflow warning
Enough memory is allocated.

    Header.c: In function ‘Header_readMeterName’:
    Header.c:157:4: error: ‘strncpy’ specified bound depends on the length of the source argument [-Werror=stringop-overflow=]
      157 |    strncpy(name, Meter_name(meter), nameLen);
          |    ^
    Header.c:154:18: note: length computed here
      154 |    int nameLen = strlen(Meter_name(meter));
          |                  ^
2020-08-25 11:59:59 +02:00
6b11769448 Avoid conversion warning
linux/Platform.c:47:90: error: implicit conversion from ‘enum LinuxProcessFields’ to ‘enum ProcessFields’ [-Werror=enum-conversion]
       47 | ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 };
          |
2020-08-25 11:59:53 +02:00
d64a6a2453 CI: Add a HWLOC enabled job 2020-08-25 11:42:21 +02:00
345d415537 Do not include the generated config.h header into the package 2020-08-25 11:42:16 +02:00
054b7f2801 Fix out-of-tree builds 2020-08-25 10:36:27 +02:00
e172282002 Fix in AC_CONFIG_FILES, try #2 2020-08-24 21:37:28 +02:00
0bac7c9d94 Nope, configure works but make breaks.
This reverts commit dad62b6c9e.
2020-08-24 21:08:07 +02:00
dad62b6c9e Put Makeheader.py.in into AC_CONFIG_FILES 2020-08-24 21:01:50 +02:00
9eb9064fbd Cleanup unused CI build notes and whitespace 2020-08-24 10:22:44 +10:00
9e57b5c3f4 Generate an appropriate shebang line for MakeHeader script
Use configure.ac to handle platform differences where some
build hosts have only a python3, or only python, binary.

Related to https://github.com/htop-dev/htop/pull/6
2020-08-23 11:24:52 +10:00
b3aef4ea3a Revert "MakeHeader.py: use python3 shebang"
This reverts commit 40ac7a88af.
as it causes build failure on non-python3 platforms.
2020-08-23 09:42:11 +10:00
6900e57efd Updates to project URLs in docs and embedded in source code 2020-08-22 15:47:11 +10:00
5dad65ac2a Update header files to match whitespace changes in source files 2020-08-22 15:46:31 +10:00
6315f10725 Merge branch 'ginggs-patch-1' 2020-08-22 15:36:02 +10:00
45062b26d6 Merge branch 'patch-1' of https://github.com/ginggs/htop-1 into ginggs-patch-1 2020-08-22 15:35:55 +10:00
ada780c867 Merge branch 'cgzones-ci2' 2020-08-22 15:35:02 +10:00
6aed2be247 Fix build on FreeBSD 2020-08-21 16:49:28 +02:00
9fde0835ed Avoid empty translation unit warning
zfs/ZfsArcStats.c:22: error: ISO C forbids an empty translation unit [-Werror=pedantic]
       22 | }*/
          |
2020-08-21 10:38:44 +02:00
b92f62f912 Remove trailing whitespaces 2020-08-21 10:37:33 +02:00
3856bf574b Introduce xAsprintf as checked version of asprintf 2020-08-21 10:37:29 +02:00
40ac7a88af MakeHeader.py: use python3 shebang
Also drop unused import
2020-08-21 10:37:27 +02:00
d6adc2b681 github/ci: improve ci
- split steps for readability
- fail on compiler warnings
- add whitespace check
- run on all branches
- run `make distcheck`
2020-08-21 10:37:25 +02:00
57254cdd05 configure: add option --enable-werror
Adds the compiler flag -Werror to fail on warnings.
Useful for CI runs.
2020-08-21 10:37:20 +02:00
0b276f80f1 Mention change of maintainership in ChangeLog
Related to https://github.com/hishamhm/htop/issues/992
2020-08-21 16:42:16 +10:00
bba8c3bb2e Update the changelog to reflect content in the 3.0.0 release 2020-08-21 12:10:11 +10:00
9a55efc8b5 Merge branch 'hishamhm-pull-920' 2020-08-20 18:24:35 +10:00
31391b206c Merge branch 'hishamhm-pull-1012' 2020-08-20 15:51:21 +10:00
fed14a584d Merge branch 'hishamhm-pull-970' 2020-08-20 15:33:30 +10:00
cca07e9bc9 Merge branch 'hishamhm-pull-1011' 2020-08-20 15:18:20 +10:00
9aa816873f Merge branch 'hishamhm-pull-1010' 2020-08-20 15:16:47 +10:00
0622be6ab3 Merge branch 'hishamhm-pull-1009' 2020-08-20 15:14:26 +10:00
54b6143cf6 Merge branch 'hishamhm-pull-996' 2020-08-20 15:07:59 +10:00
5c5a599a2a Merge branch 'hishamhm-pull-959' 2020-08-20 14:57:30 +10:00
e25ac8557d Merge branch 'hishamhm-pull-949' 2020-08-20 14:48:47 +10:00
6b443c5da9 Merge branch 'hishamhm-pull-932' 2020-08-20 14:47:07 +10:00
011125dab2 Merge branch 'hishamhm-pull-923' 2020-08-20 14:42:18 +10:00
ab61ae3963 Merge branch 'hishamhm-pull-974' 2020-08-20 14:24:11 +10:00
f4b0067339 Merge branch 'hishamhm-pull-971' 2020-08-20 14:22:15 +10:00
1b8bed1294 Merge branch 'hishamhm-pull-964' 2020-08-20 14:21:49 +10:00
a82fd262d7 Merge branch 'hishamhm-pull-960' 2020-08-20 14:19:53 +10:00
cdff8aea2a Merge branch 'hishamhm-pull-946' 2020-08-20 14:13:07 +10:00
b30c22d687 Merge branch 'hishamhm-pull-914' 2020-08-20 14:09:27 +10:00
42c8e47cd6 Merge branch 'hishamhm-pull-906' 2020-08-20 14:02:51 +10:00
0f76359e4e Merge branch 'hishamhm-pull-890' 2020-08-20 14:01:47 +10:00
e833bf915f Merge branch 'hishamhm-pull-904' 2020-08-20 14:01:33 +10:00
2be0992700 Merge branch 'hishamhm-pull-890' 2020-08-20 14:00:13 +10:00
fb679dfb18 Merge branch 'hishamhm-pull-884' 2020-08-20 13:57:09 +10:00
a7a5e356c2 Documentation updates to reflect community maintainership
Document the htop.dev site, #htop and htop@groups.io for contacting
the community maintainers, and the upcoming 3.0.0 release.
2020-08-20 13:16:31 +10:00
dab4144f4a Merge branch 'hishamhm-pull-872' 2020-08-20 12:30:51 +10:00
45ae6191c1 Merge branch 'hishamhm-pull-866' 2020-08-20 12:29:25 +10:00
ed2b7791df Merge branch 'hishamhm-pull-871' 2020-08-20 09:53:39 +10:00
78f4d064de Merge branch 'hishamhm-pull-868' 2020-08-20 09:53:00 +10:00
e7d2f9383a Merge branch 'hishamhm-pull-857' 2020-08-20 09:47:13 +10:00
97d700082c Merge branch 'hishamhm-pull-855' 2020-08-20 09:44:25 +10:00
46ab1aa3bd Merge branch 'hishamhm-pull-850' 2020-08-20 09:42:40 +10:00
500fb283e9 Resolve compiler warnings and errors relating to the Arg union
Promote the Arg union to a core data type in Object.c such
that it is visible everywhere (many source files need it),
and correct declarations of several functions that use it.

The Process_sendSignal function is also corrected to have
the expected return type (bool, not void) - an error being
masked by ignoring this not-quite-harmless warning.  I've
also added error checking to the kill(2) call here, which
was previously overlooked / missing (?).
2020-08-20 09:35:33 +10:00
5228f5d47a Ensure result buffer termination in String_cat utility routine 2020-08-20 09:03:45 +10:00
74d547674d Merge branch 'hishamhm-pull-917' 2020-08-19 18:15:18 +10:00
034e56b3c0 Merge branch 'hishamhm-pull-891' 2020-08-19 18:13:48 +10:00
6310e5dc3a Merge branch 'hishamhm-pull-886' 2020-08-19 18:12:30 +10:00
36ef4d4fb6 Resolve compilation warning relating to dangling else in InfoScreen_run 2020-08-19 18:10:16 +10:00
80ce69c44f Merge branch 'hishamhm-pull-883' 2020-08-19 18:09:19 +10:00
6fbee8c1f4 Merge branch 'hishamhm-pull-881' 2020-08-19 18:06:57 +10:00
00d333cc7b Merge branch 'hishamhm-pull-869' 2020-08-19 18:04:28 +10:00
eef6bc447d Correction to smaps buffer size passed to smaps path snprintf 2020-08-19 17:50:43 +10:00
f9625cacf0 Merge branch 'hishamhm-pull-843' 2020-08-19 17:47:38 +10:00
e9947acfc6 Merge branch 'hishamhm-pull-818' 2020-08-19 16:49:43 +10:00
5a17cee74d Merge branch 'hishamhm-pull-817' 2020-08-19 16:43:55 +10:00
ed6f22a847 Merge branch 'master' of github.com:htop-dev/htop 2020-08-18 20:24:11 +10:00
2f59798b3b Merge pull request #2 from leetonidas/master
fixed display of blank bars
2020-08-18 20:22:24 +10:00
9a70e43129 fixed display of blank bars
The buffer for blank bars was left uninitialized resulting in random
looking characters sometimes even overwriting the end of the bar.
2020-08-18 11:48:08 +02:00
7ac1c709b7 Re-generate all headers with latest scripts/MakeHeader.py
Sync-up missing extern declarations for many functions.
2020-08-18 17:41:49 +10:00
579995c7c2 Merge branch 'hishamhm-pull-842' 2020-08-18 17:35:56 +10:00
98e8da8bd3 Merge pull request #1 from htop-dev/natoscott-continuous-integration
Create ci.yml with a workflow for Ubuntu latest
2020-08-17 16:02:20 +10:00
7fbbf25afe Update ci.yml
Comment out MacOSX for now - seems to be missing needed aclocal/m4 toolchain components.
2020-08-17 15:53:49 +10:00
e1f48c7c7c Update ci.yml
Correction to deb package name
2020-08-17 15:48:24 +10:00
6cd1615863 Update ci.yml
Attempt to fix Ubuntu dependencies, add macosx
2020-08-17 15:40:47 +10:00
c86ac5cf98 Update ci.yml
Install libncurses-dev package on the build system
2020-08-17 15:16:49 +10:00
b3003f02fa Create ci.yml
Initial version of htop CI using github actions.
2020-08-17 14:59:23 +10:00
dfd9279f87 Resolve complation issues with -fno-common (default from gcc-10)
Extends the MakeHeader script to auto-generate correct "extern"
function declarations in some cases that it currently does not.

Related to https://github.com/hishamhm/htop/pull/981
2020-07-10 10:35:32 +10:00
b55f9320bc fixed x/y coordinate mixup 2020-06-12 23:53:05 +02:00
7fdd8d3732 adding support for more than 2 smaller cpumeter columns 2020-06-11 23:21:52 +02:00
f74cde982f removed whitespace from end of lines 2020-06-11 23:00:16 +02:00
832e77c754 Let the user know about their error
If the user informed wrong value, then let them know about that.
2020-06-11 13:44:16 -03:00
8de04986cf Fix misleading indentation 2020-06-11 13:42:41 -03:00
1b4ed916b1 Fix use of '-rdynamic'
The option should be informed to the linker.
2020-06-11 13:30:30 -03:00
05c974f6cc format color 2020-04-27 12:32:58 +08:00
6b5b8bab2c fix "Broken Gray" didn't change the color of cpu-iowait 2020-04-27 12:31:17 +08:00
87c05ac136 Fix STARTTIME column on FreeBSD. 2019-12-31 19:28:23 +00:00
ccf0e18414 update man page text about delay 2019-12-16 15:45:55 -06:00
88c9ebb8f7 Properly identify zombie processes
This closes issue #930.
2019-12-14 11:47:03 +01:00
37cc11253e Added missing option 2019-11-11 00:54:51 +01:00
63fbc3b517 Add trim_trailing_whitespace to editorconfig 2019-10-31 11:39:57 -05:00
dd33444f7e Clean up existing whitespace 2019-10-31 11:39:12 -05:00
9ed47a213b Fix whitespace 2019-10-31 11:29:28 -05:00
12805f61d8 Add simple vim mode
This commit adds a "vim_mode" setting (false/`0` by default) that causes
keys to be remapped in the following way by the `ScreenManager`:

+ h -> LEFT
+ j -> DOWN
+ k -> UP
+ l -> RIGHT
+ LEFT -> h (toggle help)
+ DOWN -> j (noop)
+ UP -> k (open kill menu)
+ RIGHT -> l (lsof current process)
+ K (Shift+K) -> k (open kill menu)
+ J (Shift+J) -> K (toggle show/hide kernel threads)
+ L (Shift+L) -> l (lsof current process)

I couldn't figure out where the manpage documentation is in the repo,
though I admittedly did not look particularly hard.

I believe this change would be a welcome option for heavy vim users like myself
who would like a familiar way to get around in htop.
2019-10-31 11:20:55 -05:00
28840683cf Merge remote-tracking branch 'upstream/master' 2019-10-31 10:31:38 -05:00
18a60d668d MainPanel: add seventh char to main functions
reason: currently, for example 'search' and 'filter' look very densely packed
2019-09-12 22:45:34 +02:00
1886117c72 Linux: fixes sysfs battery discovery 2019-09-07 15:21:04 +01:00
a267003f2f Linux fixes 2019-09-03 19:56:38 +00:00
613556faeb Support for ZFS Compressed ARC statistics 2019-09-03 18:44:19 +00:00
e450b58636 Refactor openzfs_sysctl_init() and ZfsArcMeter...
openzfs_sysctl_init() now returns void instead of int.
The ZfsArcStats->enabled flag is set inside the init function
now, instead of having to be set from its return value.
Preparation for more flag setting in Compressed ARC commit.

ZfsArcMeter_readStats() added and all Meter->values[] setting
moved to it, eliminating duplicated code in
{darwin,freebsd,linux,solaris}/Platform.c.
2019-09-03 18:21:33 +00:00
81b64691a7 Move sysfs-reading code to LinuxProcessList.c and add average frequency.
This way the frequency is read from sysfs only once per update cycle
instead of every time the UI is redrawn.

This also changes the code to read from /proc/cpuinfo instead. This is because
reading from scaling_cur_freq stalls for 10ms if the previous read for the file
was more than one second ago. [1] Since htop's update cycle is
longer than that, it would cause the read of each CPU's scaling_cur_freq file
to block the UI for 20ms. This easily led to a noticeable half-second lag on
a 20+ CPU machine.

/proc/cpuinfo also has a 10ms delay, but this applies for the whole file
so the delay does not scale with the number of CPUs. [2]

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=4815d3c56d1e10449a44089a47544d9ba84fad0d
[2]: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7d5905dc14a87805a59f3c5bf70173aac2bb18f8
2019-08-10 22:19:32 -07:00
909bb86f05 Show N/A on unsupported platforms instead of 0KHz 2019-08-10 17:17:45 -07:00
43728b37e7 Fix typo. 2019-08-10 11:46:21 -07:00
1acfb0a752 Show N/A instead of 0KHz when CPU frequency is not available. 2019-08-10 11:37:35 -07:00
1d5e6a27a0 Add a display option to hide CPU usage number from CPU meter. 2019-08-10 11:20:21 -07:00
9703a25d1b Divide by 1000, not 1024, and show more decimals. 2019-08-09 23:22:05 -07:00
4b0600d8f8 Add new display option to also show CPU frequency in CPU meters.
The option is only implemented on Linux. On other platforms, and on Linuxes
that do not expose the relevant sysfs file, the frequency will be 0.

The "CPU average" meter does not show a frequency, only
the individual per-CPU meters.
2019-08-09 21:34:48 -07:00
7858ee6cee Added option to enable/disable the mouse. 2019-07-12 22:01:29 +02:00
b0e24cd5a5 Added an option to disable the mouse. 2019-07-12 21:41:09 +02:00
ff6914e4ad ZFS arcstats for Solaris 2019-07-07 23:10:54 -04:00
a88d2e313d Refactor common OpenZFS sysctl access
Darwin and FreeBSD export zfs kstats through the
same APIs, so moving functions into a common file.
2019-07-07 23:10:54 -04:00
fc8e9a2d3e ZFS arcstats for Darwin (macOS / OS X) 2019-07-07 23:10:46 -04:00
070fe90461 ZFS arcstats for Linux
If no pools are imported (ARC size == 0) or the
ZFS module is not in the kernel (/proc/spl/kstat/zfs/arcstats
does not exist), then the Meter reports "Unavailable".
2019-07-07 22:57:15 -04:00
a93edde1a2 Support ZFS ARC stats on FreeBSD
New meter displays same ARC stats as FreeBSD top(1).
Can be extended to other platforms that support ZFS.

Pulling kstat.zfs.misc.arcstats.c_max as the meter
total, so the meter has a meaningful value to work
up to.

The Text meter displays, first, the maximum
ARC size (Meter.total), then second, the total
ARC used, using the difference between Meter.maxItems
and Meter.curItems to "hide" the used value from the
Bar and Graph drawing functions by using an index
in Meter.values[] that is beyond curItems - 1, but
less than maxItems - 1.
2019-07-07 22:52:04 -04:00
92258e99e6 Specify correct MIB length
Could have resulted in a buffer overflow if the
FreeBSD kernel returned more bytes than expected.
2019-07-06 04:27:00 +00:00
886eb68102 Close pipe after lsof 2019-06-23 13:13:05 -04:00
3512971084 Fix configure 'major' workaround causing <sys/sysmacros.h> to miss.
A logic mistake in pull request #746 causes <sys/sysmacro.h> to be
*not* included when AC_HEADER_MAJOR (before autoconf-2.70) finds
'major' in <sys/types.h>. Though this would still build htop, it would
still bring deprecation warning in systems using glibc 2.25-2.27. Fix
the logic and suppress the warning.

Also, include config.h in Process.c for the sake of strengthening the
code.

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2019-06-14 10:10:23 +08:00
01a1cc063f fixed Linux build 2019-05-30 16:34:30 +02:00
423414937b does not work within NGZ 2019-05-26 21:20:35 +02:00
131a6c6e2b CPU_KERNEL redefined 2019-05-26 21:20:00 +02:00
c3fadf6b69 Add timestamps to the strace screen 2019-04-29 15:17:05 +02:00
fabe75685a Truncate overwide jail names on BSD. 2019-04-17 10:07:13 +01:00
078c2ddde5 Linux: Use /proc/*/smaps_rollup for improved PSS parsing speed 2019-03-20 17:00:49 +01:00
fc0bf546c3 Linux: Add PSS (proportional set size), Swap and SwapPSS calculation
Original code was written by *Craig M. Brandenburg* for htop 1.0.2
Many performance improvements by GitHub user *linvinus*, ported to htop 2.0.2
2019-03-20 17:00:41 +01:00
43875d94c9 Add danish translation to htop.desktop 2019-02-19 01:25:52 +01:00
08feb8585b Add pressure stall information (PSI) meters on Linux
The pressure stall information (PSI) metrics provide useful information
on delays caused by waiting for CPU, IO and memory. Particularly on busy
servers it can provide a quick overview of what's "slowing things down".

This feature is supported on Linux >= 4.20.
The interface is documented here:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/accounting/psi.txt
These links provide rationale:
https://lwn.net/Articles/759781/
https://facebookmicrosites.github.io/psi/

The following metrics are added, corresponding to the currently exposed
lines (see `head /proc/pressure/*`):
- PressureStallCPUSome
- PressureStallIOSome
- PressureStallIOFull
- PressureStallMemorySome
- PressureStallMemoryFull

The color scheme is the same as that used for Load Average, however I
gave it separate entries just in case someone wants to change them
specifically.

Tested on 4.20.7-arch1-1-ARCH, on the linux platform.
Also tested that other platforms still compile (changed configure to use
the unsupported platform).

Closes #879.
2019-02-13 22:38:10 +02:00
da60309fc9 Don't follow process when selecting non-process-specific options
Disable the follow process logic in Action_pickFromVector(), when
selecting sort order or user filter, since they don't apply on specific
process.

Fix #856
2019-02-12 22:15:51 -05:00
6f161e60e1 Restore meter name after used in Header_addMeterByName()
Fix #852
2019-02-12 22:13:58 -05:00
402e46bb82 Linting changes
as reported by lgtm.com
2019-02-10 14:16:46 +01:00
90518bfc84 Return of snprintf is not the number of written bytes 2019-02-10 14:16:46 +01:00
f49f545813 Fix printf() unsigned placeholders
Unsigned numbers should be using "%u".

Raised by cppcheck
2019-02-10 14:16:46 +01:00
60e557868a Prevent possible NULL pointer deference
Raised by cppcheck
2019-02-10 14:16:46 +01:00
79c939eb84 Remove duplicated if condition
The for loop already handles i being < nPanels

Raised by cppcheck
2019-02-10 14:16:46 +01:00
dc7d035238 htop.c: remove unused "--io" / "-i" (#811)
Introduced from 3383d8e556 (2.0.0) but never used.
2019-02-10 14:16:46 +01:00
6194c8dcc6 Honour setting of counting CPUs from 0/1 when presenting meters
In the listing of Available Meters for CPUs, the list of CPUs is always
presented by counting them from one.  However, if the user prefers to
count CPUs from zero, this is sometimes confusing when fine-tuning the
meters.
2019-02-07 10:39:08 -02:00
7c62db73fc User option "-u" now defaults to $USER 2019-01-31 00:28:09 +01:00
a360a80d16 fix a bug about use of unitialised variable. refer to https://github.com/hishamhm/htop/issues/882 2019-01-29 12:45:30 +08:00
9139d29bbb chore: add clarification to the docs 2019-01-26 09:56:19 -05:00
536941fb23 Deal with larger numbers in colorNumber and outputRate 2018-12-30 20:18:35 +08:00
ecfd6f685e Fix memory statistics display on FreeBSD/powerpc
Use the appropriate types when calling sysctl().

Currently, `unsigned long long int` is used for all sizes and on
FreeBSD/powerpc this causes all sysctl() calls in scanMemoryInfo()
to fail as they are actually of different sizes on powerpc, where
(sizeof(unsigned long long int), sizeof(u_long)) == (8, 4)
vs (8, 8) on amd64.  This results in bogus memory sizes being
reported by htop.

Signed-off-by: Tobias Kortkamp <tobik@FreeBSD.org>
2018-12-24 13:51:01 +01:00
f15d55c972 Fix numbers larger than 100 terabytes 2018-12-18 21:05:09 +08:00
27fe307d22 Remove a few unnecessary #includes 2018-12-16 11:34:15 +01:00
9197adf57e Fix CPU usage on OpenBSD
The current OpenBSD-specific CPU usage code is broken. The `cpu`
parameter of `Platform_setCPUValues` is an integer in the interval
[0, cpuCount], not [0, cpuCount-1]: Actual CPUs are numbered from
1, the “zero” CPU is a “virtual” one which represents the average
of actual CPUs (I guess it’s inherited from Linux’s `/proc/stats`).
This off-by-one error leads to random crashes.

Moreover, the displayed CPU usage is more detailed with system,
user and nice times.

I made the OpenBSD CPU code more similar to the Linux CPU code,
removing a few old bits from OpenBSD’s top(1). I think it will be
easier to understand, maintain and evolve.

I’d love some feedback from experienced OpenBSD people.
2018-12-16 11:30:06 +01:00
41754e5632 Remove unnecessary HAVE_SYS_SYSMACROS_H check
HAVE_SYS_SYSMACROS_H is always true if MAJOR_IN_SYSMACROS.

This way of checking is recommended in autoconf 2.70 documentation:
https://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=blobdiff;f=doc/autoconf.texi;h=4f041bd4e;hp=9ad7dc1c5f02c8ba25b2fe1218bf931c7113a5d5;hb=e17a30e987d7ee695fb4294a82d987ec3dc9b974;hpb=565a6dc50cfa01cec2fb4db894026689cdf4970c

NOTE: currently
      https://www.gnu.org/software/autoconf/manual/autoconf.html is the
      doc for autoconf 2.69.
2018-12-15 22:10:06 +09:00
8d7afb33e2 added MainPanel actions n and N for find next and find prev. closes #601 2018-11-03 15:59:55 -04:00
b7b4200f85 Fix printf() unsigned placeholders
Unsigned numbers should be using "%u".

Raised by cppcheck
2018-10-30 16:55:55 -03:00
4cb58460e5 Prevent possible NULL pointer deference
Raised by cppcheck
2018-10-30 16:55:55 -03:00
c39f710b52 Remove duplicated if condition
The for loop already handles i being < nPanels

Raised by cppcheck
2018-10-30 16:55:55 -03:00
c34be41e1c Widen ST_UID (UID) column to 5 chars to allow UIDs > 9999 without breaking alignment
Issue Github #841, Debian bug #910492
2018-10-07 11:16:12 +02:00
67e368914a htop.c: remove unused "--io" / "-i" (#811)
Introduced from 3383d8e556 (2.0.0) but never used.
2018-08-25 10:15:59 -03:00
bae27054e6 Linux: fix CPU count 2018-08-24 18:38:06 -03:00
8d01ae2054 Linux: remove warnings of unused variables 2018-08-24 18:38:06 -03:00
049af17be0 Improve Catalan translation for desktop file (#828) 2018-08-24 17:10:09 -03:00
009837b56d Improve htop.desktop file (#609)
- sort entries according to the spec
- add to the `Monitor` category
2018-08-19 01:38:05 -03:00
bd1d719a61 Linux: add process->starttime and use it for STARTTIME column (#700)
this way a remount of /proc will not reset starttimes
and we can also see startup times for processes started before the mount
of /proc

also record btime (boot time in seconds since epoch) as Linux semi-global
2018-08-19 01:29:03 -03:00
ca1cce4ce7 OpenBSD: make the STARTTIME column display correctly (#815) 2018-08-19 01:09:08 -03:00
c1fb585b6b OpenBSD: add environment reading support (#819) 2018-08-19 01:07:36 -03:00
d74b6dc8e0 Fix process name updates for shorter strings (#812)
When a process name changes from a long string to a short string,
truncate instead of just overwriting the beginning.
2018-07-28 00:08:40 -03:00
060aa2b20f remove wrongfix 2018-07-26 04:17:06 -05:00
3d79c72e9a Update OpenBSD maximum PID
The source code correctly states that the maximum PID number in
the OpenBSD kernel is fixed in sys/sys/proc.h, however this was
updated in revision 1.215 (two years ago!) from 32766 to 99999.
2018-07-17 18:46:55 +01:00
c005ffc3d7 Fix zero-index array bounds issue 2018-07-17 08:50:22 -05:00
48b807b0ff Fix CPU meters
Introduction of CP_SPIN sched state broke hard-coded state indexes
resulting in the meters incorrectly reporting bogus intr data instead of
CPU usage. Change hardcoded values to sched.h macros.
2018-07-17 08:43:50 -05:00
666e1e76b3 Fix virtualization color in help screen
Closes #785.
2018-06-13 00:47:08 -03:00
5f9e16b9da Unstage/gitignore INSTALL since it's regenerated by autogen.sh
As noted by @marcelpaulo. I've had ugly diffs that fiddled with
this file in the past, so it's good to see it gone.

Closes #800.
2018-06-13 00:36:05 -03:00
fd15ead51b Mention the "c" key (tag subtree) in the man
This was reported by @agguser.
2018-06-02 18:22:56 -03:00
103f1a497a Disable 'make dist' when pkg.m4 is unused in configure
This would prevent a careless future package maintainer from creating a
release tarball with a defective configure script. :)

Also, add a warning in the autogen.sh phase if pkg.m4 is unused.

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2018-05-22 23:21:42 -03:00
08a9b051c5 fix option string
This broke with commit db05ba6106.
2018-05-22 23:19:19 -03:00
e1e3791363 Fix #define to match header when regenerating with MakeHeader.py (#789)
from Debian https://sources.debian.org/src/htop/2.2.0-1/debian/patches/fix-linux-process.patch/
2018-05-22 23:09:20 -03:00
04cc193e3c Bump version to 2.2.0 2018-04-10 10:42:59 -03:00
5b38466eab Update ChangeLog 2018-04-10 10:42:46 -03:00
34dff098c5 Add tree view flag to man page (#777) 2018-04-10 10:36:34 -03:00
724aae60d1 Add tree view flag to man page 2018-04-06 21:52:50 -05:00
e85b072ad0 Require pkg-config as an optional build dependency on Linux (#775)
With this commit:

* if pkgconfig is installed, it will expand the code inside the shell if, adding the pkgconfig-based tests for the dependencies of Linux delay accounting.
* if pkgconfig is not installed, it will add an error message inside the test of Linux delay accounting, telling the user to install pkgconfig and rebuild the configure script if they want to use Linux delay accounting.

The end result is:

* people running Linux
  * will not need pkgconfig when not using delay accounting
  * will need pkgconfig when using delay accounting
    * if they don't have it
      * they are told by configure they need to install it and re-run autogen.sh when running from Git
      * they are told by configure they need to install it and re-run configure when running from the tarball
* people not running Linux
  * will never need pkgconfig

...and in none of the above scenarios the generated configure script produces unexpanded macros for users checking out the sources from Git.
2018-04-06 11:03:00 -03:00
7cfaa9dede MakeHeader.py: Fix for non-utf8 environments (#770)
Header creation fails with non-utf8 locale and python3.
Simply set LC_ALL="C" and use python3 to reproduce the issue.

env LC_ALL="C" ./scripts/MakeHeader.py MetersPanel.c
Traceback (most recent call last):
  File "./scripts/MakeHeader.py", line 32, in <module>
    for line in file.readlines():
  File "/usr/lib64/python3.5/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 956: ordinal not in range(128)

This changes is python2 and python3 compatible

cStringIO.StringIO module is removed because it is not able to accept unicode strings
https://docs.python.org/2/library/stringio.html#cStringIO.StringIO
2018-04-05 19:55:51 -03:00
db05ba6106 Add -t command-line flag for tree view 2018-04-05 19:52:19 -03:00
0505a7cfe1 macOS: fix the switched version test (#772) 2018-04-05 19:41:22 -03:00
cf04300d49 Solaris: update proc state letters to reflect Solaris usage 2018-04-05 19:38:13 -03:00
c53e384213 Solaris: bump copyright in Platform.{c,h} 2018-04-05 19:38:13 -03:00
da4877f48c Solaris: fix a memory leak caused by calling ProcessList_getProcess twice for each LWP 2018-04-05 19:38:13 -03:00
0969f83b21 Solaris: Implement process environment listing 2018-04-05 19:38:13 -03:00
155d7cbeee Solaris: add placeholder message about environment listing 2018-04-05 19:38:13 -03:00
1ae7625c42 Solaris: showing a dash for the top-level process is no longer necessary 2018-04-05 19:38:13 -03:00
3c96467f7b Solaris: add warning about proc_walk_f callback function 2018-04-05 19:38:13 -03:00
7f40a3a5af Solaris: condense separate process vs lwp handling down to a single workflow 2018-04-05 19:38:13 -03:00
45fad05b4a Solaris: get completely out of the file handling business using libproc 2018-04-05 19:38:13 -03:00
4ba06c51e5 Solaris: Condense conditional blocks for new vs old LWPs and procs 2018-04-05 19:38:13 -03:00
fa18ac964c Solaris: remove unneeded accumulators for process and thread counting 2018-04-05 19:38:13 -03:00
192e43c1ed Solaris: Assorted post-LWP code cleanup 2018-04-05 19:38:13 -03:00
75598c1389 Solaris: Implement kernel thread counting 2018-04-05 19:38:13 -03:00
c235b45cd6 Solaris: If a process has a running LWP, then the process is by definition running 2018-04-05 19:38:13 -03:00
0dbedf95a8 Collapse current subtree pressing Backspace 2018-04-05 19:38:13 -03:00
42c3a1fcb3 Solaris: Implement LWP enumeration (#768)
Squashed the following commits:

* Solaris: Get LWP enumeration working
* Solaris: Make showing and hiding of kernel threads behave
* Solaris: remove usage of lwpstatus that is no longer needed
* Solaris: no discrete access to parent proc structure needed
* Solaris: Restore runtime MaxPid detection after LWP changes
* Solaris: Workaround virtual PID signal issue by shadowing kill() with a macro
* Solaris: Fix unintention double-shifting of virtual PID for LWP enumeration
* Solaris: Add LWPID to default display since LWP enumeration is also default
* Solaris: use PAGE_SIZE_KB from Process.h instead of custom definition
* Solaris: stop LWP enumeration at 1023 LWPs per proc since that is all we can handle in the virtual PID
2018-03-27 13:27:12 -03:00
1cf8f429a5 OpenBSD: read Battery data
Signed-off-by: Hisham Muhammad <hisham@gobolinux.org>
2018-03-26 15:14:12 -03:00
23f96048c7 macOS: keep scanning thread for versions before High Sierra (#728)
Keep scanning threads for versions before High Sierra 13.0.0 and after 13.3.0.
2018-03-26 15:14:12 -03:00
70bc51a387 Solaris: Fix virt and resident memory sizes. Was using KiB, needed pages. 2018-03-26 15:14:12 -03:00
442b0d2576 New makefile targets to rebuild and clean htop headers.
`make htop-headers` will regenerate all '.h' headers in htop source for
all platforms.
`make clean-htop-headers` will delete all generated htop headers.

Because of the introduction of these two targets, I slightly changed
the style of platform-specific portions of makefile rules.
Please comment if you accept such a style, or need me to revert to old
style.

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2018-03-26 15:14:12 -03:00
47cf1532b0 Linux: change how kernel threads are detected
Use the same method that ps and top use to determine if a
process is a kernel thread on Linux: check if cmdline is empty.

Thanks to @wangqr's investigation reported here:
https://github.com/hishamhm/htop/issues/761#issuecomment-375306069

Fixes #761.
2018-03-25 15:26:05 -03:00
dc050e8088 Fix overflow for signals >= 100.
Thanks to @gzip4 for tracking this down.

Closes #764.
2018-03-25 15:15:37 -03:00
aa3dc634dc strace: increase string length 2018-03-25 15:14:04 -03:00
5a75797f4d Solaris: code indentation fix 2018-03-16 11:43:48 -03:00
cda84fcddc Solaris: enough changes made to justify a copyright bump to 2018 2018-03-16 11:43:48 -03:00
69355234d0 Solaris: fix memory allocation for usernames (some empty usernames in 32-bit builds) 2018-03-16 11:43:48 -03:00
cefbe499db Solaris: fix malloc() / free() issues with zone name handling 2018-03-16 11:43:48 -03:00
76ef3682db Solaris: Link against libmalloc to fix various crashes 2018-03-16 11:43:48 -03:00
4bd68809e4 Solaris: Import backtrace-on-abort from Linux, with minor modification for Solaris 2018-03-16 11:43:48 -03:00
a042cfece2 Use fork/exec instead of popen to run lsof (#757)
Fixes #675
2018-03-16 11:39:03 -03:00
2e3c35d66d Use AM_CFLAGS and AM_LDFLAGS in Makefile.am (#760)
This reduces generated Makefile.in size by 74%.
(217319 bytes -> 56326 bytes)

Automake considers that <prog>_CFLAGS and <prog>_LDFLAGS are
program-specific build rules, and when such are specified, Automake
will generate additional code just to avoid the "generic" and
package-wide AM_CFLAGS or AM_LDFLAGS. (Especially for <prog>_CFLAGS,
Automake will rename generated object files to become "prog-foo.o" and
such, and it's _a lot_ of code to achieve this in Makefile.)

There's no reason for htop to rename intermediate object files. It's
better to make things simpler.

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2018-03-16 11:31:48 -03:00
697f5bb9c1 Import Solaris support (#741)
This commit adds support for Solaris, squashed from PR #741:

Summary of additions:

* Initial setup of Solaris platform directory
* Add Solaris platform into autoconf template
* Uptime and load averages
* Add dependency on libkstat
* Basic process listing
* Zone name display
* CPU detection
* Per-process memory and CPU usage parsed correctly
* Uses sysconf to discover number of CPUs, instead of more complex libkstat code
* Simple memory display working
* Reduce repetitive calls to the PAGE_SIZE macro when reading memory info
* Add Project, Contract, Task, and Pool into process properties
* Use system major()/minor() implementations and remove extraneous definition of mkdev()
* Get the STARTTIME column working properly, using the Linux implementation as a guide
2018-03-02 18:20:46 -03:00
d4ea7cd65c Fix bashisms (#749)
The configure script relied on bash-specific extensions to shell syntax
and behavior, causing build failures on systems with other /bin/sh
implementations. This commit replaces those with equivalent constructs
that should work in all POSIX shells.
2018-02-26 20:07:52 -03:00
9ca1c993ac Add Contributing Guide! 2018-02-26 11:45:53 -03:00
ccd156f8ba Updates to generated header files 2018-02-26 11:44:46 -03:00
858af2505f Protect against overflows in RichString_setAttrn 2018-02-26 11:05:12 -03:00
655c7293d2 Update ChangeLog 2018-02-26 10:54:01 -03:00
bc5d46982f use CFLAGS from ncurses*-config, if present (#745)
Fixes #695.
2018-02-26 10:19:01 -03:00
c01f40eb3e Fix build failure ('major' undefined) in glibc 2.28. (#746)
glibc 2.28 no longer defines 'major' and 'minor' in <sys/types.h> and
requires us to include <sys/sysmacros.h>. (glibc 2.25 starts
deprecating the macros in <sys/types.h>.) Now do include the latter if
found on the system.

At the moment, let's also utilize AC_HEADER_MAJOR in configure script.
However as Autoconf 2.69 has not yet updated the AC_HEADER_MAJOR macro
to reflect the glibc change [1], so add a workaround code.

Fixes #663. Supersedes pull request #729.

Reference:
[1] https://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=commit;h=e17a30e987d7ee695fb4294a82d987ec3dc9b974

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2018-02-26 10:15:05 -03:00
eed18dd107 Remove unused function from unsupported/ 2018-02-18 21:18:53 -03:00
f914617508 Make settings file finding sequence more straightforward
Avoid unnecessary access() call and make code read more linearly.
2018-02-18 20:42:17 -03:00
03b2581745 Only consider a read successful when the file seems valid
Require at least the `fields` entry to be present,
so we can have a decent guess that it was indeed a settings file.
2018-02-18 20:35:23 -03:00
8c653212c0 Replace size_t with int/void* union
I was occasionally passing negative values to size_t.
Plus, this better reflects the intent of the variant argument.

Reported by Coverity:
https://scan8.coverity.com/reports.htm#v13253/p10402/fileInstanceId=22093891&defectInstanceId=7543346&mergedDefectId=174179&fileStart=251&fileEnd=500
2018-02-18 10:38:49 -03:00
b064d501ae linux/Battery.c: make sure fd is always closed
Detected by Coverity:
https://scan8.coverity.com/reports.htm#v13252/p10402/fileInstanceId=22093957&defectInstanceId=7543348&mergedDefectId=174180
2018-02-18 10:21:22 -03:00
ff78a1bfce Fix out-of-bounds read
Detected by Coverity:
https://scan8.coverity.com/reports.htm#v13252/p10402/fileInstanceId=22093847&defectInstanceId=7543344&mergedDefectId=174181
2018-02-18 10:17:56 -03:00
f4f35da7e0 Fix indentation 2018-02-18 10:17:29 -03:00
76366be3f1 Update ChangeLog 2018-02-17 21:11:54 -02:00
6dda8d2586 linux/LinuxProcessList.c: Fix indentation. 2018-02-17 20:52:46 -02:00
5fca258f33 call clear() function when SIGWINCH is received. (#660) 2018-02-17 16:25:57 -02:00
70ed51a303 linux/LinuxProcessList: fix reading of number of read syscalls of process
The "if" tests if the character at index "5" is 'r', as a first quick
check. However at index "5" will always be a colon ":". This patch fixes
the off-by-one error. htop now shows proper values in the RD_SYSC
column.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2018-02-17 16:14:34 -02:00
df9922a67e Fix preservation of LDFLAGS value during configure script
Fixes #738.
2018-02-17 14:50:55 -02:00
fcdff59f4c Update ChangeLog 2018-02-17 14:50:42 -02:00
b544c22c72 Fix issue with small terminals.
Fixes #733.
2018-02-13 06:41:44 -02:00
f37a050d3d Optimize Vector_size on non-debug builds 2018-02-05 11:01:35 +01:00
03f17688ad Handle unexpected values for character passed to isalnum
It seems that certain negative integer values can crash isalnum().
Let's protect against those.

Fixes #711.
2018-02-05 10:59:20 +01:00
a32d7528f6 Check for pkgconfig's presence before using it.
Fixes #710.
2018-02-05 10:22:16 +01:00
ac2dff2881 Fix color behavior on some terminals.
Fixes #635.
2018-02-05 07:20:27 +01:00
c50440f165 Bump version to 2.1.0 2018-02-04 20:13:55 +01:00
b0588d90ff parseBatInfo: check line for NULL before passing it to String_getToken() 2018-02-04 17:04:47 +01:00
b84ebfd4e8 Clarify we are looking for the null termination
Not for a comparison to zero
2018-02-04 17:02:30 +01:00
b86e14d3cf Typo in man page
*hightlight*
2018-02-04 17:01:39 +01:00
b34d76cd41 Fix: infinite loop in tree view on macOS
Fixes #688, the bug regressed on 584a9bc.

On Mac OS X 10.11.6, all processes have their parents since there's a
special process named "kernel_task", whose PID and PPID are 0. As a
result, `this->processes` is never changed causing infinite `while`.
2018-02-04 16:51:06 +01:00
87be623eac Add support for Linux TASK_IDLE
Linux commit 06eb61844d841d0032a9950ce7f8e783ee49c0d0 ("sched/debug:
Add explicit TASK_IDLE printing") exposes kthreads idling using
TASK_IDLE in procfs as "I (idle)".

Until now, when sorting the STATE ("S") column, htop used the raw
value of the state character for comparison, however that led to the
undesirable effect of TASK_IDLE ('I') tasks being sorted above tasks
that were running ('R').

Thus, explicitly recognize the idle process state, and sort it below
others.
2018-02-04 16:44:21 +01:00
b27712181a Darwin: disable thread reading due to bug in macOS High Sierra 2018-02-04 08:59:29 +01:00
ad99187680 htop scans /proc to determine how many running tasks exist. Since that
operation is not possible to be conducted in an atomic fashion, task
scheduling effects can lead to a count greater than the number of actual
processors; this is more easily noticed on machines with several CPUs
and under heavy workload.
This patch simply adds an upper bound on cpuCount to guarantee
consistent reports of the number of running tasks at any given time.
2018-01-23 14:11:47 -02:00
b7b66b76a5 Adds support for linux delay accounting (#667)
Adds support for showing columns with linux delay accounting.

This information can be read from the netlink interface, and thus we set up a socket to read from that when initializing the LinuxProcessList (LinuxProcessList_initNetlinkSocket). After that, for each process we call LinuxProcessList_readDelayAcctData, which sends a message thru the socket after setting up a callback to get the answer from the Kernel. That callback sets the process total delay time attribute. We then set the delay percent as the percentage of time process cpu time since last scan.
2017-12-04 00:15:29 -02:00
52831955c7 fix fallthough comments for GCC 7.x
GCC 7.x does some extended checks on fallthough for switch/case
statement. The warning looks like this:

warning: this statement may fall through [-Wimplicit-fallthrough=]

It can be told about implicit fallthough, however it does not
recognize comments within blocks, so move the comments outside.
2017-10-23 14:27:33 -04:00
ef34a83c54 Merge pull request #678 from evelikov/remove-libtool
Remove libtool references
2017-10-13 13:55:43 -07:00
4c1230b03b Remove libtool references
The project builds a single standalone binary.

There are no libraries created - be that static or shared ones.
Thus there's no need for libtool.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2017-09-22 16:53:26 +01:00
e3f65c8ec2 Make 'c' key work with threads as well. 2017-09-14 17:10:39 -03:00
b9934ffa08 minor style tweak 2017-09-04 13:53:03 -03:00
65ec0bd6a6 Merge pull request #676 from wangqr/master
Find roots when constructing process tree, fix #587
2017-09-01 19:56:55 -03:00
584a9bceab Find roots when constructing process tree, fix #587 2017-09-01 21:34:05 +08:00
9487bda330 Do not use xSnprintf when the result is used. Fixes #662. 2017-08-01 15:48:43 -07:00
4300a19592 Merge pull request #659 from guoci/patch-1
make script version agnostic
2017-07-28 21:07:54 -03:00
60acda0bce make script version agnostic 2017-07-27 17:02:01 -04:00
09e241fb12 Security review: check results of snprintf.
Calls marked with xSnprintf shouldn't fail.
Abort program cleanly if any of them does.
2017-07-27 16:07:50 -03:00
3975e9ce5c Merge branch 'master' of https://github.com/hishamhm/htop 2017-07-26 16:16:10 -03:00
821d50f0b4 Merge pull request #651 from Explorer09/graph-mode-draw
Round values in graph drawing (instead of implicit truncate)
2017-07-26 16:15:59 -03:00
543d65c6ab Security review: make privilege dropping-restoring optional.
This is/was necessary only on macOS, because you needed root in order
to read the process list. This was never necessary on Linux, and
it also raises security concerns, so now it needs to be enabled
explicitly at build time.
2017-07-26 15:40:55 -03:00
f205f7004c Use regular readdir since readdir_r is deprecated and newer GCC complains. 2017-07-26 15:35:39 -03:00
ef7817c17a Merge pull request #656 from rsaxvc/master
more const usage
2017-07-26 11:24:51 -03:00
33fda93271 Merge pull request #657 from kalbasit/remove_whitespace_from_config_file
Settings: do not emit trailing whitespace
2017-07-25 13:57:55 -03:00
ce0cf3c457 Settings: do not emit trailing whitespace 2017-07-24 16:36:27 -07:00
d5faf64374 Mark some things as const
Several string pointer arrays pointed to const strings
but were not const themselves.

A few various structures and arrays were also marked const.
2017-07-22 22:34:30 -05:00
18b3e5d255 .gitignore vim & nano swp files 2017-07-22 22:34:30 -05:00
143a7de6b2 Round values in graph drawing (instead of implicit truncate) 2017-07-15 22:14:44 +08:00
e940aecfb9 Add "no perm" status when other fields fail due to lack of permission.
Thanks @Sworddragon for the heads up.
See #88.
2017-07-10 20:57:34 -03:00
1a178ad581 Merge branch 'master' of https://github.com/hishamhm/htop 2017-07-10 20:14:53 -03:00
c39f18a7be Add a clear warning about unsupported platforms.
Closes #648.
2017-07-10 20:14:25 -03:00
978c9e1698 Merge pull request #647 from Explorer09/dragonfly-pid-max
DragonFlyBSD PID_MAX is 999999.
2017-07-10 10:19:26 -03:00
e70f447d54 DragonFlyBSD PID_MAX is 999999.
See DragonFlyBSD source "sys/sys/proc.h".

Fixes #646
2017-07-07 20:38:04 +08:00
71785e2ded Set idle I/O prio to 0x6007, like ionice.
As suggested by @wolfgang42 in #100.
2017-07-05 15:20:48 -03:00
e9ecbd05bc Use class value only to display idle I/O priority.
As suggested by @wolfgang42. Fixes #100.
2017-07-05 15:18:02 -03:00
89d15399c5 Merge branch 'master' into fixedgray 2017-06-06 15:27:02 -03:00
e03e45d819 Merge pull request #624 from mklein-de/xterm-256color
make special keys also work with TERM=xterm-256color
2017-06-06 15:23:58 -03:00
45f3769887 make special keys also work with TERM=xterm-256color 2017-06-01 12:52:14 +02:00
2d8dd0b29e Work around the strange behavior of gray. 2017-05-23 14:02:34 -03:00
b1028e03c5 Merge pull request #414 from Explorer09/meters-panel-edit
Mouse-friendly functions bar for meters panel
2017-04-24 23:48:13 -03:00
0c168471b6 F6 is actually used for both actions, depending on context. 2017-04-24 23:38:28 -03:00
68b8efb83f Merge pull request #612 from ryenus/keymap
update keymap in help
2017-04-24 23:35:38 -03:00
418fea33f4 Merge pull request #613 from dkgroot/master
Initial addition of dragonflybsd (based on FreeBSD)
2017-04-24 23:34:27 -03:00
975e22144e Merge pull request #614 from dkgroot/EnhanceMakeHeader
Enh: scripts/MakeHeader script
2017-04-24 23:30:42 -03:00
50f03f5950 Enh: scripts/MakeHeader script
Only write a new .h file if something changed for the header file being created.
This prevents a lot of recompilation during development
2017-04-21 16:39:03 +02:00
cb7a06379d Enh: Add support for backtrace using execinfo 2017-04-21 16:36:19 +02:00
cba695961a Fix: TreeView 2017-04-21 16:34:40 +02:00
49af12e7c6 implement: readJailName
Note: dragonflybsd does not have 'jail_get' like freebsd does.
It does however provide a sysctl "jail.list" which returns a list of all jails.
2017-04-20 15:14:33 +02:00
b258d6e53e Initial addition of dragonflybsd (based on FreeBSD) 2017-04-19 16:19:32 +02:00
e0e84401e4 update keymap in help 2017-04-19 18:20:42 +08:00
5570748dd2 Merge pull request #610 from coypoop/patch-1
Add missing include
2017-03-28 23:56:13 -03:00
3c09082422 Merge pull request #608 from giwhub/giwhub-patch-1
Add Comment[zh_CN] and GenericName[zh_CN] into htop.desktop
2017-03-28 23:24:03 -03:00
53d7c66ac3 Add missing include
sys/time.h for struct timeval
2017-03-25 14:12:26 +03:00
3b1260ac3d Add Comment[zh_CN] and GenericName[zh_CN] into htop.desktop 2017-03-24 01:45:10 +08:00
fa30938247 Merge branch 'master' of https://github.com/hishamhm/htop 2017-02-15 22:49:13 -02:00
bb8dec1582 Cap battery at 100%.
Apparently invalid results can be returned by buggy drivers in old laptops,
as reported by @thukydides. See #596.
2017-02-15 22:47:03 -02:00
aa813c7561 Merge pull request #593 from kamyarrasta/issue/502sessionid
Issue #502 update Session ID column
2017-02-04 21:46:29 -02:00
3f6d1262c0 Issue #502 fix SID colunm header width 2017-02-05 00:10:29 +01:00
84bc00a275 Issue #502 update Session ID column 2017-02-01 00:03:55 +01:00
6141edc74b Merge pull request #584 from EliteTK/buffer-lengths
Replace all uses of sprintf with snprintf
2016-12-30 19:28:38 -02:00
2b5c1b4b13 Replace all uses of sprintf with snprintf
In all the cases where sprintf was being used within htop, snprintf
could have been used. This patch replaces all uses of sprintf with
snprintf which makes sure that if a buffer is too small to hold the
resulting string, the string is simply cut short instead of causing
a buffer overflow which leads to undefined behaviour.

`sizeof(variable)` was used in these cases, as opposed to `sizeof
variable` which is my personal preference because `sizeof(variable)`
was already used in one way or another in other parts of the code.
2016-12-29 19:42:41 +01:00
8af4d9f453 Interpret TTY_NR column on Linux,
translate dev_t to major:minor on other platforms.
Closes #316.
2016-10-01 03:09:04 -03:00
8a147dd5b4 Merge branch 'master' of https://github.com/hishamhm/htop 2016-09-16 13:37:44 -03:00
5df425867c Protect against strange values of SIGRTMIN and SIGRTMAX,
and change alignment of numbers.
2016-09-16 13:37:07 -03:00
46d8f2eef2 Merge pull request #551 from Explorer09/rt-signals
Real-time signals support (kill command)
2016-09-16 13:36:58 -03:00
8fd6228bc1 Merge pull request #551 from Explorer09/rt-signals
Real-time signals support (kill command)
2016-09-16 13:03:46 -03:00
0ce4835f95 Real-time signals support (for kill command)
SignalsPanel_new now fetches SIGRTMIN and SIGRTMAX and generates real-
time signals entries at runtime.

All signals between SIGRTMIN and SIGRTMAX are written in "SIGRTMIN+n"
notation, per discussion in pull request #551.

Signed-off-by: Kang-Che Sung <explorer09 @ gmail.com>
2016-09-14 21:47:24 +08:00
823481ae22 Merge branch 'master' of https://github.com/hishamhm/htop 2016-09-11 23:29:21 -03:00
96157870af Downgrade requirement to Libtool 2.4.0.
Courtesy to OpenWRT environments as requested by @champtar in #540.
2016-09-11 23:28:17 -03:00
5a5a7c8d6b Merge pull request #555 from ivan/master
Fix column misalignment for priority -101 threads
2016-09-06 15:08:26 -03:00
07086fcf77 Fix column misalignment for priority -101 threads
BFS-patched kernels can have kernel threads with priority -101.
This change makes priority -101 display as "RT", just like priority -100.

Related: https://github.com/hishamhm/htop/issues/314
2016-09-06 09:22:38 +00:00
6d4df3d138 Merge branch 'master' of https://github.com/hishamhm/htop 2016-08-30 12:38:12 -03:00
d4a8023b72 Fix typos, by @Gelma.
Closes #546.
2016-08-30 12:37:31 -03:00
99f7ff9bd2 Merge pull request #550 from Explorer09/signals-tweaks
Mark signal tables 'const'
2016-08-30 12:17:20 -03:00
1f3d85b617 Mark signal tables 'const'
Specifically, Platform_signals[] and Platform_numberOfSignals. Both are
not supposed to be mutable. Marking them 'const' puts them into rodata
sections in binary. And for Platform_numberOfSignals, this aids
optimization (aids only Link Time Optimization for now). :)

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
2016-08-30 20:41:17 +08:00
cceab15b9d free(NULL) is a valid no-op, so let's make String_freeArray(NULL) valid too. 2016-08-24 18:12:35 -03:00
bd5d37f297 Return when reading cmdline fails (e.g. zombie process) 2016-08-24 18:11:10 -03:00
16406ea330 Point users to the official release tarballs. 2016-08-23 15:43:27 -03:00
d3f575264b Merge pull request #537 from Explorer09/string-utils
Optimize Strings_startWith()
2016-08-11 00:44:42 -03:00
bf35921abb Optimize Strings_startWith()
Use strncmp() combined with a strlen() will give better performance
than a strstr in worst case. Especially when the match prefix is a
constant and not a variable.

While we are at it, replace the match() function in linux/Battery.c,
which uses a naive algorithm, with a macro that does better job by
utilizing Strings_startWith().

    $ gcc --version | head -n 1
    gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
    $ uname -m
    x86_64
    $ size htop.old htop.new
       text   data    bss    dec    hex filename
     137929  15112   3776 156817  26491 htop.old
     137784  15104   3776 156664  263f8 htop.new

Signed-off-by: Kang-Che Sung <explorer09 @ gmail.com>
2016-08-11 10:49:35 +08:00
b269eb24b0 Merge pull request #534 from Explorer09/issue-532
Change scrolling behavior to make it more similar to other applications.
2016-08-09 13:06:33 -03:00
3d9868833e Fix scrolling behavior change caused by 759caf0f
Commit "Make PgDown behavior more usual." 759caf0f8f
silently changes the PageDown scrolling behavior that, instead of
scrolling one window down until the end of the window touches the end
of the list, the window simply repositions itself in a way that the
selected item always become the last item in the new window.

The commit reverts the behavior, and also fixes sanity conditionals
so that the scrollV variable will _never_ become negative or out-of-
bound.

Fixes issue #532. Also keep the problem #480 addressed.

Signed-off-by: Kang-Che Sung <explorer09 @ gmail.com>
2016-08-07 07:49:37 +08:00
3cd0339423 Merge branch 'master' of https://github.com/hishamhm/htop 2016-07-28 11:39:15 -03:00
ef879b4a22 'Follow' only if element is found in search 2016-07-28 11:37:44 -03:00
f161365d72 Merge pull request #526 from Explorer09/bar-tweaks
Let BarMeterMode_characters[] be const array.
2016-07-23 13:48:50 -03:00
6b9b6db655 Let BarMeterMode_characters[] be const array. 2016-07-22 14:58:29 +08:00
f80e577c59 Changelog for htop 2.0.2 2016-07-21 17:12:45 -03:00
81552d4ab5 Preparing release 2.0.2, a minor bugfix release. 2016-07-21 16:54:41 -03:00
0108117d0b Mouse-friendly functions bar for meters panel
Before:
SpaceStyle EnterMove  DelDeleteEscDone  |
~~~~~      ~~~~~      ~~~      ~~~      |
UpUp     DnDown  LtLeft  RtRight EnterConfirmDelDeleteEscDone  |
~~       ~~      ~~      ~~      ~~~~~       ~~~      ~~~      |

After:
SpaceStyle EnterMove                                           DelDeleteF10Done
~~~~~      ~~~~~      ~~                                       ~~~      ~~~
SpaceStyle EnterLock  UpUp    DnDown  <-Left  ->Right          DelDeleteF10Done
~~~~~      ~~~~~      ~~      ~~      ~~      ~~      ~~       ~~~      ~~~

* Align 'Delete' and 'Done' to the right to match functions on other
  screens. (Accidental clicking is avoided as a side benefit.)
* You could change meter type while in moving mode. New bar now hints
  this.
* Two Enter key functions are put in the same place and so mouse clicks
  there act like functions toggle. (The wording change to 'Lock' is
  also to reflect this.)
* '<-' and '->' instead of 'Lt' and 'Rt' abbreviation as the latter is
  not widely seen and arrows shapes are obvious. :)
* 'Esc' key for 'Done' in this context may not be intuitive, comparing
  to 'F10'. While I wish there be a Cancel/Undo function for 'Esc', it
  wouldn't hurt if we write 'F10' for 'Done' on functions bar for now.
2016-07-16 21:13:46 +08:00
a41c9b3925 Reword 'Type' to 'Style' for meters.
Per @hishamhm's suggestion. This is UI change only.
In code the class names and symbols still refer them as "modes".
2016-07-16 21:13:46 +08:00
265d04821a Merge pull request #524 from ricardo0y/cross_compile_with_ncurses_config
Allow to override ncurses*-config path
2016-07-12 10:02:51 -03:00
78b82d0fdc Allow to override ncurses*-config path
This will be used when cross-compiling with ncurses*-config generated for the
target, using constructs like
HTOP_NCURSES_CONFIG_SCRIPT=/path/to/ncurses5-config

Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com>
2016-07-11 20:17:13 -03:00
7f9c82f28d Refresh whole panel on Ctrl+L in infoscreen.
Closes #520.
2016-06-23 13:25:58 -03:00
7d5ef246f1 Let's keep it simple then! 2016-06-20 12:11:49 -03:00
0fa03322a9 Dynamically adjust the size of line reads
* Dynamically adjust the size of line reads.
* Remove some more uses of fgets with arbitrary sizes.
* Fix reading of lines and width of n column.

Fixes #514.
2016-06-19 18:55:35 -03:00
52f814481c While we're at it, get rid of another sprintf. 2016-06-19 18:30:20 -03:00
b139671cbd Moving left and right needs a full redraw. 2016-06-19 18:05:18 -03:00
adcc944e35 Use "-" as the Ctrl and Alt joiner. 2016-06-17 22:14:07 -03:00
a5ef374bb8 Merge pull request #511 from Explorer09/man-page
Document Alt+{h,j,k,l} and Ctrl+{A,E} into man page
2016-06-17 11:50:15 -03:00
6dd32d3604 Document Alt+{h,j,k,l} and Ctrl+{A,E} into man page
Rewrite the scrolling part in the man page so that each key become clearer on
what it does. Also officially document the Alt+{h,j,k,l} key alternatives and
Ctrl+A, Ctrl+E, '^', '$' keys (see issue #508).
2016-06-17 10:19:19 +08:00
8cd045cc79 Merge branch 'master' of https://github.com/hishamhm/htop 2016-06-15 12:46:34 -03:00
0128d222b9 Added Ctrl+A and Ctrl+E to go to beginning and end of line.
(Also, '^' and '$')
Closes #508.
2016-06-15 12:45:23 -03:00
1a13b4d0f4 Don't store invisible trailing whitespace 2016-06-15 12:41:50 -03:00
9ec41d1b65 Merge pull request #505 from Explorer09/xStrdup
Fix xStrdup debug build failure & allow Clang to use ((nonnull))
2016-06-04 11:45:29 -03:00
c0e37bc5f5 Fix xStrdup debug build failure & allow Clang to use ((nonnull)) 2016-06-03 10:14:27 +08:00
f9c1db514d Merge pull request #504 from Explorer09/xStrdup
Fixes upon xStrdup(NULL) problem
2016-06-02 17:29:14 -03:00
3297616efa Add assert and __attribute__((nonnull)) on xStrdup
__attribute__((nonnull)) will help catching "calling with NULL" mistake on
compile time.

I also convert xStrdup into a macro, that will do assert() inline when the
code is *not* built with -DNDEBUG . For release builds (with -DNDEBUG),
preprocessor trick will ensure that generated code remains the same.
2016-06-02 20:38:24 +08:00
e288f690af Don't check if (!str) in xStrdup
This effectively reverts "Stricter strdup." 4674b4a732

If str is NULL upon the calling of strdup(), it should crash with SIGSEGV.
Just let it crash. Adding the "if (!str) fail();" code serves nothing but
bloat.
2016-06-02 18:30:18 +08:00
ea9dc4ab74 Merge branch 'master' of https://github.com/hishamhm/htop 2016-05-30 15:06:52 -03:00
112db9a609 Handle SIGQUIT. Closes #503. 2016-05-30 15:06:22 -03:00
5db1b0e9a0 Remove extra checks made redundant by XAlloc. 2016-05-30 12:22:33 -03:00
4674b4a732 Stricter strdup. 2016-05-30 12:22:22 -03:00
7ededce9b5 Silence cast warning. 2016-05-30 12:22:07 -03:00
3126cfce6c Merge pull request #500 from Explorer09/meter-tweaks
Remove redundant is-null checks on free(Meter.drawData)
2016-05-27 16:30:45 -03:00
313b3d3752 Remove redundant is-null checks on free(Meter.drawData) 2016-05-27 17:11:54 +08:00
fa0c637c55 Silence warnings about seteuid return value.
Closes #483.
2016-05-25 21:37:07 -03:00
b7ac416634 Fixes #498. 2016-05-25 21:29:06 -03:00
6cc0a8c820 Make sure a pointer fits in the argument! 2016-05-25 16:46:47 -03:00
645057d81a Use set_escdelay() to avoid problems with ESCDELAY as a macro. 2016-05-19 16:09:47 -03:00
6c1be63291 Fail early if libtool is not present. 2016-05-19 16:04:04 -03:00
642ccb49ca Merge pull request #445 from Explorer09/configure-ac
configure.ac fixes
2016-05-19 15:57:31 -03:00
6028e1b4c4 Merge pull request #496 from tcreech/lwp_hack
FreeBSD: fix multithreaded CPU% in process list
2016-05-19 15:44:57 -03:00
95d1984339 Merge pull request #485 from Cubox-/master
Fix FreeBSD CPU bars calculation
2016-05-16 19:19:36 -03:00
c0df404701 Update INSTALL text from autoconf-2.69 2016-05-08 14:35:20 +08:00
b71b07f5e0 Reorder configure macros to avoid "missing script" warning.
3 effects in this commit, with the first being the main one:

1. Fix the "`missing' script is too old or missing" warning. See:
   <https://lists.gnu.org/archive/html/automake/2010-08/msg00108.html>

2. By moving AC_CANONICAL_TARGET down in order, we are now able to
   set the directory for auxiliary scripts. For now it's still './'.
   I added the line "AC_CONFIG_AUX_DIR([.])" to show that the directory
   change is possible.

3. AC_USE_SYSTEM_EXTENSIONS includes checks from AC_PROG_CC, by moving
   the former macro down, we can save size in 'configure' by not
   generating repeated checks.
2016-05-08 14:35:20 +08:00
f0df28a470 Replace deprecated autoconf macros.
AC_HELP_STRING -> AS_HELP_STRING
AC_TRY_COMPILE -> AC_COMPILE_IFELSE([AC_LANG_PROGRAM([...])],...)
AC_CONFIG_HEADER -> AC_CONFIG_HEADERS
AC_PROG_LIBTOOL -> LT_INIT

Note: There might be more deprecated macros that I haven't noticed.
I just wish to avoid painful highlighting from my text editor (gedit)
that complains about them. :)
2016-05-08 14:35:20 +08:00
7d72715a6b Merge pull request #490 from Explorer09/macro-fixes
Fix macro Header_forEachColumn
2016-05-07 14:34:50 -03:00
54621e8b8f Fix macro Header_forEachColumn
The (this_) token was not expanded properly, but the bug was not caught
because all uses of this macro specifies (this_)=this .

Also parenthesize macro tokens to prevent further problems.
2016-05-07 14:57:51 +08:00
572546f806 Auto-follow process after a search.
See #237.
2016-05-05 10:30:06 -03:00
d464be13db Merge branch 'master' of https://github.com/hishamhm/htop 2016-05-04 22:43:03 -03:00
759caf0f8f Make PgDown behavior more usual.
Closes #480.
2016-05-04 22:41:52 -03:00
cdc91b0b33 Merge pull request #472 from jrtc27/hurd
Use Linux backend on the Hurd
2016-05-04 15:42:16 -03:00
1754a1cd48 Merge pull request #473 from fasterit/upstream/typo1
Fix a typo in the man page (Debian Lintian spelling-error-in-manpage)
2016-05-04 15:40:31 -03:00
8e6ffdb0ab Merge pull request #475 from fasterit/upstream/desktop-keywords
Add Keywords entry to .desktop file (Debian Lintian warning desktop-e…
2016-05-04 15:40:16 -03:00
c37be409a9 Improve reproducible builds.
Use a SOURCE_DATA_EPOCH friendly date.
Suggested by @fasterit in #476.
2016-05-04 15:34:49 -03:00
fa1b5d1e2e Fix a small undefined behavior detected by libubsan. 2016-05-04 15:34:22 -03:00
19f0f4db27 Merge pull request #488 from Explorer09/func-naming
Rename Meter.setValues() functions to updateValues()
2016-05-04 15:18:52 -03:00
9dea20e068 Rename Meter.setValues() functions to updateValues()
Rationale (copied from htop issue #471):
The function name "setValues" is misleading. For most OOP (object-
oriented programming) contexts, setXXX functions mean they will change
some member variables of an object into something specified in
function arguments. But in the *Meter_setValues() case, the new values
are not from the arguments, but from a hard-coded source. The caller
is not supposed to change the values[] to anything it likes, but
rather to "update" the values from the source. Hence, updateValues is
a better name for this family of functions.
2016-05-04 13:39:26 +08:00
2ea4bee66d Merge pull request #486 from mmcco/null-check
Remove needless allocation error conditions
2016-04-29 23:01:32 -03:00
1809f4be98 Remove needless allocation error conditions
These allocations were converted to use xMalloc et al. and no longer
need error checks.
2016-04-29 21:10:05 -04:00
5776cb56b4 Revert "Fix FreeBSD CPU% calculation"
This reverts commit f554f08fa9.
2016-04-28 21:42:18 +02:00
74f8b31040 Add Keywords entry to .desktop file (Debian Lintian warning desktop-entry-lacks-keywords-entry)
Debian patch from
https://anonscm.debian.org/cgit/collab-maint/htop.git/tree/debian/patches/002-lintian-warning-fix-desktop-keywords.patch
2016-04-19 19:06:03 +02:00
4d3f483b96 Fix a typo in the man page (Debian Lintian spelling-error-in-manpage)
Debian patch from
https://anonscm.debian.org/cgit/collab-maint/htop.git/tree/debian/patches/001-lintian-warning-fix-man-typo.patch
2016-04-19 18:32:39 +02:00
2de52862a6 Use Linux backend on the Hurd 2016-04-18 23:57:30 +01:00
a9508275cc Use $target_os instead of $target in configure.ac 2016-04-18 23:55:55 +01:00
306c5443ae Update header. 2016-03-31 11:01:23 -03:00
d15555ed2c Merge branch 'master' of https://github.com/hishamhm/htop 2016-03-31 00:19:59 -03:00
d64f2bdd56 If task_for_pid fails, stop trying. 2016-03-31 00:18:42 -03:00
6c2f698a47 Merge pull request #458 from Explorer09/bar-tweaks
BarMeterMode_draw() minor code improvement
2016-03-25 01:57:10 -03:00
7b3c8bc77a BarMeterMode_draw minor code improvement
Removed a loop that sets the bar[] buffer with spaces and merged that
task to the snprintf() call just below. No need for the barOffset
variable. Display behavior is unchanged.

Size comparision (when compiled on Ubuntu 14.04 64-bit):

    $ size htop.old htop.new
       text    data     bss     dec     hex filename
     137312   15112    3776  156200   26228 htop.old
     137216   15112    3776  156104   261c8 htop.new
2016-03-22 14:52:31 +08:00
3a4c0fa2d6 Merge pull request #452 from Explorer09/cpu-meter-tweaks
Assert (Platform_meterTypes[0] == &CPUMeter_class)
2016-03-20 05:02:07 -03:00
328de35623 Assert (Platform_meterTypes[0]==&CPUMeter_class)
Just assume Platform_meterTypes[0] is always &CPUMeter_class for every
platform. This removes a conditional in AvailableMetersPanel_new().

Also adds some comments about the logic here. Without assuming
Platform_meterTypes[0], the (int i=1) clause in this for loop will not
make sense. (I.e. Why not (int i=0)? )

Also replaced a sprintf() call with safer snprintf() in code further
below.
2016-03-19 15:01:13 +08:00
c8a735e471 Merge pull request #444 from Explorer09/meter-maxitems
Explicit "maxItems" property of meters
2016-03-13 20:57:08 -03:00
99fb3070a2 Explicit "maxItems" property of meters
Two changes in this commit:
- All meters now explicitly specify "maxItems" property, even for just
  1 item. (Exception is "container" CPU meter classes, which use
  CUSTOM_METERMODE.)
- "maxItems" being 0 is now allowed. This will let bar meters and graph
  meters render an empty meter.
2016-03-11 10:54:34 +08:00
7d3f67e822 Revert 5c593fae42 (xCalloc)
calloc() allows 'nmemb' or 'size' to be zero, in which case NULL may be
returned. Letting htop die because of either argument being zero doesn't
make sense.

As a side note: As size_t is unsigned, compiler should be able to optimize
conditional (nmemb > 0 && size > 0) to (nmemb && size). This theorically
shouldn't increase code size too much.
2016-03-11 10:43:31 +08:00
3283c6d23c Merge pull request #441 from Explorer09/issue-438
Avoid overlapping key values defined by curses (Real fix).
2016-03-09 02:03:11 -03:00
8a928c8b89 Avoid overlapping key values defined by curses (Real fix).
Real fix for issue #438.
2016-03-09 10:16:34 +08:00
f295a52ed9 Avoid overlapping key values defined by curses.
Closes #438.
2016-03-08 12:23:18 -03:00
e2ccc7b240 Prepare for release 2.0.1. 2016-03-07 18:32:06 -03:00
ef1e62d1fa Merge branch 'juanfra684-openbsd-mem-used' 2016-03-07 15:03:50 -03:00
453105e77a Merge branch 'Sp1l-master' 2016-03-07 16:58:47 -03:00
db80f202f2 Avoid global, as done by @gaod in #387. 2016-03-07 16:58:02 -03:00
98e43816a5 Merge branch 'master' of https://github.com/Sp1l/htop into Sp1l-master 2016-03-07 16:54:38 -03:00
694addceb5 Merge pull request #436 from mmcco/tuneup
Misc. OpenBSD tuneup and improvement
2016-03-07 16:38:39 -03:00
4623394456 Merge pull request #435 from mmcco/freebsd
Improve error reporting on FreeBSD libkvm call
2016-03-07 16:35:59 -03:00
4ad7aa6432 Merge branch 'openbsd-mem-used' of https://github.com/juanfra684/htop into juanfra684-openbsd-mem-used 2016-03-07 15:03:18 -03:00
4b780a3499 A few more OpenBSD fixes
Namely:

 o use malloc where an xCalloc slipped in

 o safeguard against an empty arg list - I don't think it's possible,
   but it would be potentially exploitable

 o we need to initialize the arg string to an empty string because we no
 longer use strlcpy(3)

 o annotate a tricky use of strlcpy(3)'s truncation
2016-03-05 23:38:12 -05:00
b08cb7352e Misc. OpenBSD tuneup and improvement
Including:

 o set *basenameEnd even in error cases (FreeBSD probably needs this)

 o use kvm_openfiles(3) rather than kvm_open(3) so that we can report
   errors (as with FreeBSD)

 o sanify the process argument list creation by using strlcat(3)

 o drop the pageSizeKb variable and use the PAGE_SIZE_KB macro directly,
   as the page size can't change anyway

 o clean up a few macros, add MINIMUM() and MAXIMUM() (should be
   mirrored to FreeBSD)

 o fix some syntax

 o add some useful comments
2016-03-05 23:23:29 -05:00
b886ecc479 Improve error reporting on FreeBSD libkvm call
This involves switching from kvm_open(3) to kvm_openfiles(3). The only
difference is that the latter has saner error reporting (see the man
page for details). We can now fatally report the error rather than just
calling assert(3).
2016-03-05 22:59:39 -05:00
63c55854e5 Merge pull request #388 from mhinz/add-p-to-help
Add "p" to Help
2016-02-29 22:03:45 -03:00
4f1bd232d8 Merge branch 'master' of https://github.com/hishamhm/htop 2016-02-29 21:57:47 -03:00
84a69b1ea4 Release resource when using hwloc 2016-02-29 21:57:27 -03:00
e77811e99b any of these values may wrap 2016-02-29 21:57:03 -03:00
0a4a447d0d Add "p" to Help 2016-03-01 00:57:09 +01:00
cc8375f9ea FreeBSD: use KERN_PROC_PROC with kvm_getprocs to avoid erroneously combining LWPs 2016-02-28 22:41:50 -05:00
03af73bbc7 Merge pull request #427 from tcreech/master
Fix low CPU usage reporting in FreeBSD
2016-02-27 03:04:52 -03:00
0cf3cfa3af Fix low CPU usage reporting in FreeBSD 2016-02-26 23:23:27 -05:00
797bcd0961 Catch invalid IO values due to no permissions.
Display them properly. Not fully convinced of the "no perm" message...
2016-02-20 02:23:26 -02:00
baec4bdcb0 Try to retain last full name of a zombie process.
Once a process goes zombie on Linux, /proc/PID/cmdline
gets empty. So, when we detect it is a zombie we stop
reading this file.
For processes that were zombies before htop started,
there's no way to get the full name.
Closes #49.
2016-02-19 20:51:57 -02:00
a8a5e62760 Force -lgcov harder when running make coverage.
Shouldn't be needed, but I had to make this tweak to make this work again.
2016-02-19 13:40:21 -02:00
f5ddb974a1 Tweaks on the test suite, still problematic. 2016-02-19 13:40:00 -02:00
565101234a Remove old commented code. 2016-02-19 13:39:38 -02:00
d4741d5410 Fix error test — looks like nobody bumped into this one! 2016-02-19 13:39:16 -02:00
9668cd11ed Merge branch 'master' of https://github.com/hishamhm/htop 2016-02-19 13:38:54 -02:00
c23d4f12d1 Fix behavior of ESC key, getting rid of the annoying delay.
Thank you @Explorer09 for the push!
Closes #417.
2016-02-19 13:38:02 -02:00
34431dc7fd Merge branch 'master' of https://github.com/hishamhm/htop 2016-02-18 23:46:36 -02:00
42c4459375 Run through all command line arguments on Darwin.
Also fixes the basename offset for highlighting the basename.
Closes #379.
2016-02-18 23:45:17 -02:00
48254f92e4 Fix behavior of Panel on empty lists.
Closes #370.
2016-02-18 17:45:04 -02:00
5ee6715843 Scan threads for process state information.
Based on: http://stackoverflow.com/questions/6788274/ios-mac-cpu-usage-for-thread
and       e86692e869/ProcessList.c
This should be a fix for #361.
2016-02-18 14:57:09 -02:00
c18309466d Pre-reset 'show' for process.
This simplifies the protocol between the platform-independent
and platform-specific parts. The platform-specific parts
were supposed to re-determine the value of process->show
on each iteration, and the Darwin subsystem wasn't doing that.
Instead of adding the code to the Darwin part, I lifted the
burden of the OS-specific of resetting process->show: now
they can choose to hide a process if they want to (e.g.
detecting kernel threads) but are not required to
(e.g. on Darwin where we're not listing threads separately (yet?)).
Fixes tree view collapsing/expanding on OSX. Closes #416.
2016-02-18 14:32:49 -02:00
fe0ad86e6d Fix tree organization on OSX.
Closes #393.
2016-02-18 14:14:45 -02:00
dc4f145629 Merge pull request #413 from koresar/master
(Regression) Typo in the word "prority" -> "priority"
2016-02-17 10:38:38 -02:00
d43e709364 Typo in the word "priority" 2016-02-17 13:44:07 +11:00
0627a5f0e9 Merge branch 'master' of https://github.com/hishamhm/htop 2016-02-16 14:52:08 -02:00
d10f4f615a Merge pull request #391 from gaod/master
Add MEM% for processes in process list on FreeBSD.
2016-02-16 14:52:02 -02:00
e0c364b9cc Fix reading of io_syscr and io_syscw.
Issue noticed by GCC6 -Wmisleading-indentation.
Thanks @JIghtuse and @Explorer09!
Closes #409.
2016-02-16 14:34:25 -02:00
fd216309d9 Merge pull request #380 from fingolfin/patch-1
Simplify autogen.sh
2016-02-14 21:17:19 -02:00
474d26cea8 Portable affinity using hwloc 2016-02-14 19:57:29 -02:00
471cd60635 Simplify autogen.sh
Make use of the autoreconf tool
2016-02-14 22:36:40 +01:00
f554f08fa9 Fix FreeBSD CPU% calculation 2016-02-14 22:21:11 +01:00
d753996b96 Fix memory percentage display on FreeBSD 2016-02-14 21:48:36 +01:00
b10278318b Merge branch 'master' of https://github.com/hishamhm/htop 2016-02-14 17:47:29 +01:00
35657208d7 Disable the syscall on systems that don't have it.
Got a report in #397 that htop runs in NetBSD
masquerading as Linux and using a compatibility /proc
(like we used to in FreeBSD) and that it builds fine
apart from this syscall.
2016-02-14 12:05:35 -02:00
ae823c375a Make unsupported platform build again.
(Thanks @coypoop at #397 for the heads up!)
2016-02-14 11:45:47 -02:00
1b5025e6f5 Add support for cachedMem and fix usedMem on OpenBSD. 2016-02-14 13:04:18 +01:00
c66ac09a66 Add MEM% for processes in process list on FreeBSD. 2016-02-13 23:24:57 +08:00
0b70439316 Fix buffer reuse. 2016-02-13 02:18:28 -02:00
e9b32eb62f Fix memory accounting in Darwin.
htop currently expects m_size and m_resident in pages (Process.c).
According to the proc_info.h header, the values returned by libproc
are in bytes:
http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/sys/proc_info.h
Eventually we should change the htop crossplatform API to expect memory
in bytes, but this is the smaller change that should fix it.
Closes #385.
2016-02-13 02:13:57 -02:00
3b9a4b1024 Merge branch 'master' of https://github.com/hishamhm/htop 2016-02-12 23:34:28 -02:00
0e3cf6975f Fix crash when emptying column. Closes #381. 2016-02-12 23:33:53 -02:00
a618f477b2 Merge pull request #387 from gaod/master
Suppress compiler warnings on FreeBSD
2016-02-12 22:47:29 -02:00
cc4267cc5c Suppress compiler warnings. 2016-02-13 02:09:50 +08:00
d0d14da8d9 Fix implicit define isnan() 2016-02-12 14:37:24 +01:00
1bedac1ca2 Merge pull request #363 from myfreeweb/freebsd-memory-fix
Fix process memory on FreeBSD
2016-02-11 17:30:41 -02:00
011bf30d22 Minor tweaks to the README 2016-02-11 17:20:50 -02:00
c56b1a8830 Merge pull request #365 from deric/master
Add travis badge, update README
2016-02-11 17:18:20 -02:00
01edfcf4d4 link to the official website, paypal donate button 2016-02-11 19:17:00 +01:00
d916f6e6f0 remove Debian instructions 2016-02-11 18:58:20 +01:00
e46488463d Merge branch 'master' of https://github.com/hishamhm/htop 2016-02-11 15:24:49 -02:00
8fa9da47de don't mention installing to /usr 2016-02-11 17:32:06 +01:00
d408c74465 add travis badge, code formatting, updated compilation instructions 2016-02-11 14:59:45 +01:00
bb0333e45d fix process memory on FreeBSD 2016-02-11 15:52:39 +03:00
b6f927bffa Merge pull request #359 from myfreeweb/freebsd-battery
Add FreeBSD battery support
2016-02-11 08:46:42 -02:00
f1d1d6e0d6 add FreeBSD battery support 2016-02-11 13:42:37 +03:00
563d5d3ab9 Final touches to ChangeLog 2016-02-10 18:48:39 -02:00
f1f805f29f Support -1 as tpgid 2016-02-10 18:48:04 -02:00
807640e49b Shorten the code using the err() function. 2016-02-03 12:42:25 +00:00
5c593fae42 Be stricter! 2016-02-03 02:02:30 +00:00
d311e85b91 Avoid crash on huge screens.
Fix by @Explorer09 (see discussion on #355).
2016-02-02 23:20:11 +00:00
c148907e7b Try to make threads less confusing. 2016-02-02 16:39:08 +01:00
820c079b14 Initialize default meter modes properly. 2016-02-02 16:15:07 +01:00
f87462d60e Exit on failure! 2016-02-02 16:03:00 +01:00
b2c2b2bfb3 Merge branch 'reuse-comm' 2016-02-02 15:58:50 +01:00
ffcf48fb74 Merge branch 'xalloc' 2016-02-02 15:58:45 +01:00
1cfcc42a8f Reuse comm object if possible, avoid useless repetitions of free+strdup. 2016-02-02 15:56:52 +01:00
b54d2dde40 Check for failure in allocations. 2016-02-02 15:53:02 +01:00
301c346c85 Update generated headers. 2016-02-02 12:11:41 +01:00
21da044fb4 Add generated header. 2016-01-31 17:41:55 +01:00
6434db5b6b Differentiate threads by default. 2016-01-31 12:07:48 +01:00
a1f7f2869e Add allocation tests 2016-01-31 12:01:48 +01:00
dcfcae1ed4 Merge pull request #351 from Explorer09/graph-height
GRAPH_HEIGHT macro and 'dot' variable
2016-01-21 10:43:44 -02:00
040613db33 Change variable 'dot' to avoid division by reciprocal.
(Cherry-picked from d56bcd8e0d8d6a177fc2e40db32fc73ea4588684, the
experimental graph coloring branch)

The variable 'dot' in GraphMeterMode_draw now means "maximum number of
dots per value (column) in graph". The old meaning was "amount of value
that is to be represented by a dot" and was always a fraction. Due to
a limitation in floating point computing, if GRAPH_HEIGHT were not a
power of 2, then rounding errors will occur on numbers like (1.0/3).
(Currently GRAPH_HEIGHT is 4 and so no precision loss.) 'dot' was used
as a divisor, and it's "division by a reciprocal". We change that to
simple multiplication.
2016-01-21 14:06:11 +08:00
d54ab24d97 New macro GRAPH_HEIGHT for Graph Meter height
(Cherry-picked from e93028d7fa0c5f00b5dc3336fd28abaf905cd572, the
experimental graph coloring branch)

Currently GRAPH_HEIGHT=4 . This prevents hard-coding the height of the graph
meters, and allows user to change it at compile-time.
2016-01-21 10:11:54 +08:00
09cf369f2b Merge pull request #349 from Explorer09/clamp-macro
Introduce CLAMP macro. Unify all MAX(l,MIN(h,x)) uses.
2016-01-20 19:31:52 -02:00
6dae8108f8 Introduce CLAMP macro. Unify all MIN(MAX(a,b),c) uses.
With the CLAMP macro replacing the combination of MIN and MAX, we will
have at least two advantages:
1. It's more obvious semantically.
2. There are no more mixes of confusing uses like MIN(MAX(a,b),c) and
   MAX(MIN(a,b),c) and MIN(a,MAX(b,c)) appearing everywhere. We unify
   the 'clamping' with a single macro.
Note that the behavior of this CLAMP macro is different from
the combination `MAX(low,MIN(x,high))`.
* This CLAMP macro expands to two comparisons instead of three from
  MAX and MIN combination. In theory, this makes the code slightly
  smaller, in case that (low) or (high) or both are computed at
  runtime, so that compilers cannot optimize them. (The third
  comparison will matter if (low)>(high); see below.)
* CLAMP has a side effect, that if (low)>(high) it will produce weird
  results. Unlike MIN & MAX which will force either (low) or (high) to
  win. No assertion of ((low)<=(high)) is done in this macro, for now.

This CLAMP macro is implemented like described in glib
<http://developer.gnome.org/glib/stable/glib-Standard-Macros.html>
and does not handle weird uses like CLAMP(a++, low++, high--) .
2016-01-15 20:26:01 +08:00
195f5edbc8 Merge pull request #347 from mklein-de/darwin32+64
Darwin: replace vm_statistics64_* with vm_statistics_*
2016-01-13 21:32:43 -02:00
d312510223 Darwin: replace vm_statistics64_* with vm_statistics_*
Works with:
- Darwin 9.8.0 (OS X 10.5.8) PPC
- Darwin 15.2.0 (OS X 10.11.2) Intel
2016-01-13 20:57:29 +01:00
9c39422c71 Merge pull request #346 from mklein-de/vikeys
vi keys: translate ALT-h/j/k/l to arrow keys
2016-01-13 14:20:33 -02:00
99b947058f vi keys: translate ALT-h/j/k/l to arrow keys 2016-01-12 21:15:04 +01:00
466d4da0c6 refactor *Screen classes, add InfoScreen superclass 2016-01-12 06:00:58 -02:00
faf2860669 Merge branch 'mklein-de-envscreen' 2016-01-12 02:57:58 -02:00
032af1577c Merge branch 'envscreen' of https://github.com/mklein-de/htop into mklein-de-envscreen 2016-01-12 02:55:43 -02:00
d850803eb8 Merge branch 'master' of https://github.com/hishamhm/htop 2016-01-11 20:39:08 -02:00
c6ca311d18 Present IO-Wait as a dot in monochrome. Fixes #345.
Thank you @Explorer09 for the report!
2016-01-11 20:38:10 -02:00
fc61e25f5b Merge pull request #343 from FreedomBen/typo-priority
Fix typo: prority => priority
2016-01-06 22:00:52 -02:00
4b29e8485f Fix typo: prority => priority 2016-01-06 13:49:49 -09:00
b14f89e9d4 drop privileges before reading environment 2016-01-06 22:53:14 +01:00
b10e54cdee Merge remote-tracking branch 'upstream/master' into envscreen 2016-01-06 22:39:57 +01:00
fc4c9757b0 Merge pull request #315 from mklein-de/suid
add some security checks when running SUID root
2016-01-06 18:19:28 -02:00
82db9979b1 Merge pull request #339 from eworm-de/configure
use AC_HELP_STRING for proc dir
2016-01-06 18:15:39 -02:00
4c23a81d72 use AC_HELP_STRING for proc dir 2016-01-05 10:23:08 +01:00
6bc98bb227 Merge pull request #338 from mmcco/opl
Rename variable for consistency
2016-01-04 20:59:57 -02:00
e595f6865e Rename variable for consistency
Suggested by Hisham.
2016-01-04 16:20:51 -05:00
3ad2510fc2 Merge pull request #337 from eworm-de/help
align help output
2016-01-04 18:14:42 -02:00
be6b0c2830 Merge branch 'mmcco-freebsd-free' 2016-01-04 18:09:22 -02:00
f342a9eb83 Merge branch 'freebsd-free' of https://github.com/mmcco/htop into mmcco-freebsd-free 2016-01-04 18:08:51 -02:00
c5b9045f18 Plug leak in FreeBSD backend, as noted by @mmcco in #334. 2016-01-04 18:04:50 -02:00
77cffaacf6 Merge pull request #334 from mmcco/cpu
Plug mem leak, improve CPU enumeration logic
2016-01-04 18:02:36 -02:00
9ca646acbb align help output 2016-01-04 16:02:29 +01:00
61f2d674b0 Remove NULL-checks before free()
These are never necessary when using the standard library.
2016-01-03 16:59:44 -05:00
198592a0f1 Plug mem leak, improve CPU enumeration logic
I think this leak may still exist in the FreeBSD port.
2016-01-03 16:56:33 -05:00
be9edc5d43 Merge branch 'master' of https://github.com/hishamhm/htop 2016-01-03 16:32:48 -02:00
70cd5c2b88 Check range when accessing keys table.
Should fix #321.
2016-01-03 16:31:44 -02:00
86954f9204 Merge pull request #331 from mmcco/fixes
OpenBSD fixes and updates
2016-01-03 16:17:31 -02:00
fe83bc8e68 Merge pull request #332 from mmcco/maintainer
Fix spelling of "maintainer"
2016-01-03 16:12:29 -02:00
918cfd54d6 Fall back to sysctl's command name, and a bugfix
This is what OpenBSD's top(1) does when the libkvm call fails, and it's
a good idea.

This commit also fixes process name construction. The space was being
written one character too far.
2016-01-02 22:05:20 -05:00
3da36bbc61 Use dynamically allocated memory for process names
Even when they're constant, as is the case for zombie processes.
2016-01-02 17:11:23 -05:00
c1b3289219 Check for allocation failure
Pointed out by Michael Reed.
2016-01-02 12:20:40 -05:00
ae5c01f485 Use err() rather then errx() for sysctl()
So that we can see errno. Pointed out by Michael Reed.
2016-01-02 12:17:35 -05:00
7170382706 Fix spelling of "maintainer" 2016-01-02 12:11:26 -05:00
22cfda6332 OpenBSD fixes and updates
I forgot how awful the process name logic was. It was an initial hack to
get it running, and I forgot to clean it up.

I also had to change a few includes and error function uses.
2016-01-02 11:57:53 -05:00
c8cadfb905 Merge branch 'master' of https://github.com/hishamhm/htop 2015-12-23 13:58:35 -02:00
526eca9a19 Merge pull request #320 from etosan/master
major meters update
2015-12-23 13:57:51 -02:00
adaa4de295 Merge pull request #325 from Explorer09/master
Fix text on function bar when moving meters.
2015-12-22 13:24:55 -02:00
71ad9b304d Fix function bar when moving meters.
Before:
[Up]Up [Dn]Down [Lt]Left [Rt]Right [Arrow]Confirm [Enter]Delete [Del]Done

After:
[Up]Up [Dn]Down [Lt]Left [Rt]Right [Enter]Confirm [Del]Delete [Esc]Done
2015-12-22 17:43:31 +08:00
c67e482c67 fixed bug with PPID of parent not being set on first process list scan pass.
this caused htop to show processes as if freebsd kernel was their parent.
on next pass reparenting code took chance to run, and that caused process to jump around.
this fixed behaviour should be the correct one
2015-12-17 08:48:53 +01:00
802e216870 Extend buffer for reading lines from /proc.
Apparently a line longer than 255 chars was spotted in the wild:
http://serverfault.com/questions/577939/linux-ps-htop-show-processes-running-for-hundreds-or-thousands-of-days-though-h#comment676098_577939
2015-12-14 13:27:11 -02:00
e0b6e2eef2 enabled swap meter 2015-12-13 04:16:06 +01:00
9d55c56f26 added Support for memory meter, and slightly adjusted process monitor logic 2015-12-13 04:11:35 +01:00
80f594f314 added CPU% for processes in process list 2015-12-13 01:39:54 +01:00
c2769985cc added cpu monitoring for both single core and smp systems, some notes in process monitor 2015-12-13 00:21:02 +01:00
bc84920b91 added support for effective UID/username change detection 2015-12-11 11:01:24 +01:00
563abbc44b Merge pull request #319 from acatton/master
Redraw the panel when resizing the window during an incremental search
2015-12-10 18:34:57 -02:00
065aab5247 Redraw the panel when resizing the window during an incremental search
KEY_RESIZE wasn't handled by the incremental search. Resulting in this
bug:

  * Set your terminal window to a small size.
  * Press '\' to filter the processes
  * Maximize your terminal window
  * The list of processes didn't resize.

This change fixes this bug.

Thank you Julian Andrews (@julianandrews) for finding this bug.
2015-12-09 23:46:25 -07:00
cccc18dd2f Oops! 2015-12-09 17:34:57 -02:00
84783bd6f0 Fix fopen mode in Settings_read() 2015-12-09 20:34:11 +01:00
db6828617d More thorough checks for ncurses*-config scripts.
See #198.
2015-12-09 17:17:30 -02:00
ab3a7c2fa8 drop privileges before changing process priority or sending signals
- replaces uid check from d18e9a4895
2015-12-07 20:10:09 +01:00
6b1b073ae4 Merge branch 'master' of https://github.com/hishamhm/htop 2015-12-06 19:07:16 -02:00
c23770245e If ncurses*-config script is present, use it in configure
when testing for ncurses library. See #198.
2015-12-06 19:06:23 -02:00
cc23d13f87 Add Platform_getProcessEnv
- currently implemented for darwin and linux
2015-12-03 22:23:40 +01:00
42b08f2233 drop privileges during Settings_read()/Settings_write() 2015-12-02 23:42:10 +01:00
0919ea32f9 'e' displays environment of current process
- uses sysctl(KERN_PROCARGS2) on *BSD
- doesn't work on Linux yet
2015-12-02 23:26:00 +01:00
d18e9a4895 add some security checks when running SUID root
on Darwin, htop needs to run with root privileges to display information
about other users processes. This commit makes running htop SUID root a
bit more safe.
2015-12-02 22:56:01 +01:00
670a2de692 Merge pull request #313 from hishamhm/sreclaimable
Update calculation of used vs. free memory.
2015-11-30 18:27:33 -02:00
96c929f82b Use ncurses*-config scripts bundled with ncurses.
Ensure that all necessary libs and flags are passed along,
such as adding -ltinfo when needed.

Closes #198.
2015-11-30 16:36:22 -02:00
a84aa2e782 Cached memory calculations, take 2.
Thanks to @OmegaPhil for discussion and reviewing.
2015-11-29 23:55:31 -02:00
5bc1f5ed04 Account unreclaimable slab and shmem as used memory,
reclaimable slab as cached memory.

Hopefully this presents a more truthful representation of
available vs. used memory on Linux.
See brndnmtthws/conky#82, #242, #67, #263.
2015-11-28 22:22:00 -02:00
d34645f8f1 Array entries have been oddly flipped here for years. 2015-11-23 03:46:43 -02:00
f02d8f4386 Merge pull request #303 from kaefer/desc-load-averages-meter
match load averages description to what it actually shows
2015-11-23 02:55:27 -02:00
aae02bbfc9 Merge pull request #304 from Sworddragon/master
Manpage update
2015-11-23 02:50:30 -02:00
5521094b1e Merge pull request #309 from hishamhm/travis-ci
Integrate Travis-CI
2015-11-20 15:59:54 -02:00
347141502b Test for unicode-enabled libncurses 2015-11-19 13:26:11 -02:00
0837fc5b62 travis-ci should really detect autogen.sh... 2015-11-19 13:14:20 -02:00
d12084b032 ChangeLog updates. 2015-11-19 13:08:23 -02:00
c24270be0a Test on Linux and OSX 2015-11-19 12:58:00 -02:00
d820d11c80 Add initial .travis.yml 2015-11-19 12:56:26 -02:00
4b83a82dca Minimal stub 'make test' target. 2015-11-19 12:56:01 -02:00
ad5d9c2542 Merge pull request #308 from SaltwaterC/darwin-swap
Add Darwin swap meter
2015-11-19 12:53:47 -02:00
8895f09880 Add Darwin swap meter. 2015-11-16 17:32:22 +00:00
f097bdce8f Fixed/enhanced some entries in the manpage 2015-11-04 12:13:16 +01:00
1e31b63a7e Fixed some typos 2015-11-04 12:09:22 +01:00
33cdaf3ac0 match load averages desc. to what it actually shows 2015-11-04 11:53:17 +01:00
bef00a4fd9 Create directory m4 if it doesn't already exist.
(See #292.)
2015-11-03 02:21:53 -05:00
5e0f1788e6 Fix CRT_fatalError warning. 2015-11-02 10:22:10 -05:00
a7fcbba75a Add missing header, silence warning. Should fix #292. 2015-11-02 10:46:04 -05:00
3cfbcb72c8 Highlight moving meters in a different color. 2015-11-02 10:33:37 -05:00
f187be9296 Fix moving of meters 2015-11-02 10:33:22 -05:00
fd5dd6605a Merge pull request #299 from mmcco/master
OpenBSD port updates and error exit improvements
2015-11-02 08:46:40 -05:00
cd3d2337f8 Replace all err.h function uses with CRT_fatalError(). Failing with
err.h functions corrupts the terminal when using curses.
2015-11-01 13:26:57 -05:00
0fb9a8c389 Remove a debugging print 2015-11-01 13:19:01 -05:00
b669540e4e Merge pull request #298 from patrickmarlier/issue202
Fix a case where the usertime calculation can overflow (see issue #202)
2015-10-26 17:55:13 -04:00
ea8a8b2d6b Merge pull request #296 from hishamhm/darwin-cpu-average
Darwin cpu average
2015-10-24 23:29:47 -04:00
bd93b2e1d7 Initialize variables, silence warnings. 2015-10-24 23:28:29 -04:00
71190654bc Calculate CPU averages on Darwin (See #295). 2015-10-23 13:46:21 -02:00
9c146393a3 Improve prose a bit. 2015-10-19 17:26:53 -02:00
57333d8a47 Merge pull request #280 from eworm-de/man-htoprc
add hint about system configuration file
2015-10-19 17:26:22 -02:00
78f2933e2b Regenerate platform-dependent headers.
Closes #293.
2015-10-19 17:22:54 -02:00
8673a84e5f Remove some trailing whitespace 2015-10-13 11:05:52 -04:00
9f1884c28f Fix generation of openbsd/Platform.h and replace a vestigial dummy CPU utilization value 2015-10-09 14:57:01 -04:00
e906c0dddb Merge pull request #287 from etosan/master
PPID and JID update fix
2015-10-07 20:48:46 -03:00
93f05b459f fixed broken merge, where I forgot to check linux/Platform.c so that it matches upstream 2015-10-06 20:05:55 +02:00
23bf564d73 Fixed reparenting issue. PPID should be updated each refresh as any process can get reparented to either
PID1 or even any other PID (if there are custom reapers in the system).
Similar issue with jails, elevated process can ask kernel to attach itself into any jail at any time,
thus JID and jail name can change each refresh cycle.
2015-10-06 19:50:19 +02:00
214d0cff0d merge with 'upstream/master' 2015-10-06 19:39:12 +02:00
3ea7b34735 attempt to return to upstream/master 2015-10-06 19:39:01 +02:00
cc0fc3655d Add Darwin signals (same as FreeBSD)
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/signal.3.html
2015-10-06 13:03:47 -03:00
56193323ce let's let the user find SIGIOT if the look for it :) 2015-10-06 12:58:53 -03:00
ee0d602a47 Merge branch 'master' of https://github.com/hishamhm/htop 2015-10-06 12:52:48 -03:00
125c23ef23 Fix build in FreeBSD, and make sure SIGTERM is always the default. 2015-10-06 12:50:31 -03:00
384c92f7e4 Merge pull request #286 from mmcco/master
Add OpenBSD signals
2015-10-06 12:42:13 -03:00
c4eb99f264 Add header file reference for OpenBSD signals 2015-10-06 11:32:40 -04:00
77f12bbecd Add OpenBSD signals 2015-10-06 11:25:16 -04:00
2379835910 Added platform dependent DEFAULT_SIGNAL define, for now for:
FreeBSD
Linux
Other platforms will have it undefined for now.
2015-10-06 14:04:22 +02:00
86417e4157 Unless I move signal definitions into the comment used for header generation,
htop fails to compile with:

```text
SignalsPanel.c:32:49: error: use of undeclared identifier 'Platform_signals'
      Panel_set(this, i, (Object*) ListItem_new(Platform_signals[i].name, Platform_signals[i].number));
                                                ^
1 error generated.
*** Error code 1
```
2015-10-06 12:46:37 +02:00
7859857fdd add hint about system configuration file 2015-10-06 08:18:56 +02:00
3fe2f3e28e Move list of signals to platform-specific code.
Implementations for Linux (tested) and FreeBSD (still untested, thanks to @etosan for providing the table).
Darwin and OpenBSD(ping @mmcco) builds should be broken now, pending their own tables.
2015-10-06 03:02:49 -03:00
fbb4c49edd gcc warning cleanups. 2015-10-05 11:27:44 -03:00
bf276a0993 Merge pull request #274 from mmcco/master
Cleanup and initial OpenBSD support
2015-10-05 11:22:50 -03:00
5c2b0a6bbc Merge pull request #283 from eworm-de/editorconfig
add editorconfig file to give hints to editors
2015-10-05 11:19:59 -03:00
1cda2d7397 add editorconfig file to give hints to editors
We use an unusual indent of three spaces. Let's give editors a hint
about that.
2015-10-05 11:13:17 +02:00
68c3270be8 Merge pull request #281 from etosan/master
Added preliminary attempt at jails support on FreeBSD - JID and JAIL (name) columns
2015-09-30 22:28:40 -03:00
8c00fa4582 Added preliminary attempt at jails support on FreeBSD - JID and JAIL (name) columns, somewhat more correct kernel "thread" detection.
Seems FreeBSD kernel can spawn both kernel processes (what is what htop currently sees) and kernel threads.
For now let's consider kernel processes kernel "threads".
2015-09-30 22:04:26 +02:00
2d1507ad5a Merge pull request #275 from trebmuh/patch-1
Update htop.desktop (FR l10n)
2015-09-21 14:17:21 -03:00
6a21d2f3a6 Fix enumeratoin of on-CPU processes in OpenBSD 2015-09-19 12:45:22 -04:00
ad1a0ad08d Replace some remaining tabs 2015-09-19 12:21:22 -04:00
571cbc0aa1 Change more fprintf(stderr, ...); exit(...); to err[x](...). Tweak a few existing ones and fix some style. 2015-09-19 12:15:26 -04:00
e2bbd5cfa4 Change some tabs to three spaces 2015-09-19 12:08:34 -04:00
c5d725daf9 Update htop.desktop
fix
2015-09-19 00:12:41 +02:00
9c14fa6fad Merge pull request #273 from kaefer/fix-glibtoolize-detection
Mac build fixes
2015-09-18 15:41:41 -03:00
a9a5a539cf (Very) initial working OpenBSD port 2015-09-18 00:46:48 -04:00
b0e074f6b6 Update htop.desktop
This one is adding FR localisation to the desktop file.
Cheers.
2015-09-17 20:04:18 +02:00
02727bda81 ignore which errors 2015-09-17 08:44:34 +02:00
445222e48c Clean up some needless malloc casts, convert some mallocs to callocs, and fix some style 2015-09-16 23:42:36 -04:00
b37d4f172f Fix a case where the usertime calculation can overflow (see issue #202) 2015-09-14 22:51:14 +02:00
40525d85bc removing unnecessary include, which on top breaks compiling 2015-09-14 16:18:51 +02:00
661a4cec4a fix glibtoolize detection 2015-09-14 10:03:17 +02:00
1d805b36b4 Bring changelog up-to-date :) 2015-09-11 16:29:19 -03:00
8e81119c33 Merge branch 'master' of https://github.com/hishamhm/htop 2015-09-11 13:42:04 -03:00
0c2ccde306 Detect when libtoolize is called glibtoolize.
It's the case on Darwin, and might be in other BSDs as well.
As referred in #268.
Supersedes PR #269.
2015-09-11 13:39:06 -03:00
a92f803903 Merge pull request #268 from jweyrich/darwin-fixes
Darwin fixes - duplicate & conflicting decls
2015-09-10 16:41:53 -03:00
e52c070ef5 Remove conflicting declarations. 2015-09-10 10:46:44 -03:00
ffacac14a9 Remove duplicate declaration. 2015-09-10 10:45:22 -03:00
229d005851 Merge pull request #262 from eworm-de/calloc
fix calloc() calls
2015-09-08 14:43:33 -03:00
e8970b6f32 fix calloc() calls
* size_t nmemb (number of elements) first, then size_t size
* do not assume char is size 1 but use sizeof()
* allocate for char, not pointer to char (found by Michael McConville,
  fixes #261)
2015-09-07 07:52:39 +02:00
2df36ee2f2 Merge pull request #254 from eworm-de/kilobyte-precision
kilobytes is the smallest unit and never has precision
2015-08-29 19:45:47 -03:00
bf456972b7 kilobytes is the smallest unit and never has precision
Signed-off-by: Christian Hesse <mail@eworm.de>
2015-08-29 21:22:46 +02:00
a859e9204c Merge pull request #253 from eworm-de/clock
get a useful tolal for clock meter
2015-08-29 16:18:51 -03:00
08392ce5d3 Merge pull request #255 from eworm-de/missing-blank
add missing blank
2015-08-29 16:14:00 -03:00
ba3504fa26 add missing blank 2015-08-28 11:29:33 +02:00
804bd37dca get a useful tolal for clock meter 2015-08-28 10:15:00 +02:00
8a2dd83efa call for action! 2015-08-27 23:44:58 -03:00
a008cb73a4 Updated README 2015-08-27 23:44:15 -03:00
7985724933 Fixes for color glitches in ncurses ABI6.
Could no longer reproduce #244 after these fixes.
2015-08-27 21:45:02 -03:00
bdadd45a88 Fix indentation. 2015-08-27 21:37:06 -03:00
bde3406add Merge branch 'master' of https://github.com/hishamhm/htop 2015-08-27 19:14:45 -03:00
3c4326b450 Don't select last item when clicking past the end of the panel. 2015-08-27 19:14:25 -03:00
6082db2121 Improve feedback when moving meters. 2015-08-27 19:14:13 -03:00
f6c31eeaf5 Handle KEY_RECLICK events generated by ScreenManager 2015-08-27 18:43:22 -03:00
f6d48c172c Merge pull request #247 from eworm-de/dual-meters-margin
remove extra space in dual meters without margins
2015-08-27 18:42:36 -03:00
696e36cb45 remove extra space in dual meters without margins 2015-08-27 22:40:35 +02:00
f585fc9825 Merge pull request #208 from eworm-de/dynamic-unit
Dynamic unit
2015-08-27 17:33:24 -03:00
79356dc125 Merge pull request #250 from eworm-de/ascii-blank
use ASCII blank even for graphical meter in UTF-8 mode
2015-08-27 17:32:33 -03:00
cf47f4fca1 use dynamic units for text display
Signed-off-by: Christian Hesse <mail@eworm.de>
2015-08-27 06:13:27 +02:00
6f58fbc5dd make units more dynamic
Signed-off-by: Christian Hesse <mail@eworm.de>
2015-08-27 06:13:27 +02:00
f3a9f5406b Merge pull request #248 from eworm-de/wctype
include wctype.h for iswprint()
2015-08-26 23:42:32 -03:00
93b811a051 use ASCII blank even for graphical meter in UTF-8 mode
If the terminal has no font with braille characters we see... Nothing
useful. Use an ASCII blank at least, so we have an idea about what's
going on.
2015-08-25 17:40:36 +02:00
f10cbaa812 include wctype.h for iswprint() 2015-08-25 15:23:50 +02:00
8f07868fef A more portable version of the note suggested in #113.
Closes #113.
2015-08-20 02:17:11 -03:00
0507cd38f7 Merge pull request #43 from ErkiDerLoony/master
Fix tree view if userland threads are hidden.
2015-08-20 02:15:04 -03:00
544c7efa6b Omit non-printable characters with widechar curses.
Closes PR #111.
2015-08-20 02:07:24 -03:00
c7387fac15 Fix mouse click on meters setup function bar 2015-08-20 01:34:52 -03:00
4597014ea3 Standardize variable name. 2015-08-20 01:27:07 -03:00
f019f4cd9e Merge pull request #221 from eworm-de/define-array-size
use a define for graphical meter array size
2015-08-20 01:26:38 -03:00
ea18a50091 Merge pull request #134 from jeffgarrett/pid-selection
Interpret command line PIDs as PIDs, not TIDs
2015-08-20 01:20:21 -03:00
c9cab824e9 Extra checks. 2015-08-20 01:13:20 -03:00
5e4f1e46cc Reduce scope of variables. 2015-08-20 01:12:34 -03:00
9428010121 Make column width calculation dynamic.
Closes #228.
2015-08-20 00:32:47 -03:00
8bd603cb68 Make Unicode strings safe for ncurses 6 ABI.
Closes #241.
2015-08-20 00:31:48 -03:00
78be8201dc Add expand/collapse on additional clicks! 2015-08-19 19:09:54 -03:00
b003636958 Support for NCurses 6.0 and mouse wheel 2015-08-19 18:55:24 -03:00
a2a34e89a1 simplify Meter loop
* Use MIN() and MAX() to make sure values are inside bounds. This should
  fix an issue where Meters were missing dots at the bottom.
* Remove variable 'level' and calculate on the fly.
2015-08-19 22:42:34 +02:00
d8e23bb084 remove UTF-8 code when compiling with --disable-unicode 2015-08-19 22:42:34 +02:00
9e67b6585e make arrays one dimensional
With more dimensional arrays we have to define the array size. Use
one dimensional arrays to be more flexible.
Additionally this allows to shrink array size for ASCII.
2015-08-19 22:42:34 +02:00
3e93f9b852 Fix comment. 2015-08-19 13:58:29 -03:00
f70649a178 Standardize indentation. 2015-08-19 13:56:46 -03:00
907f8298a0 CPU per process implemented 2015-08-19 13:52:57 -03:00
57ab332d5a Fix the thread counts 2015-08-19 13:52:38 -03:00
6463ea2956 Fixed CPU updating 2015-08-19 13:52:18 -03:00
7f3faa276a Static CPU meter 2015-08-19 13:52:04 -03:00
43ef703f03 Start supporting actual data 2015-08-19 13:51:49 -03:00
70e7c8db59 Added darwin with working battery meter 2015-08-19 13:47:26 -03:00
feb7a01fd3 Make unsupported run 2015-08-19 13:46:41 -03:00
5e602f18d5 Rename String to StringUtils.
Fixes building on case-insensitive filesystems where String.h gets confused with <string.h>.

From d734dacea0a10d0465dad4e95b3421511e7da112 Mon Sep 17 00:00:00 2001
From: David Hunt <dhunt@iolanthe.attlocal.net>
Date: Sat, 11 Jul 2015 20:56:31 -0500
Subject: [PATCH 1/8] Rename String to StringUtils
2015-08-19 13:45:20 -03:00
f2c053a884 Add translations for desktop file.
Translations obtained by @glixx from Mandriva Linux.

Closes #227.
2015-08-12 18:05:46 -03:00
0ebe688d24 Avoid future confusions with how default values are set. 2015-08-12 17:29:32 -03:00
e1e3ffad19 Ensure default matches classic htop behavior. 2015-08-12 17:24:41 -03:00
4d44c35519 Merge pull request #148 from nckx/display-basename
[PATCH] New setting: "Show program path"
2015-08-12 17:16:50 -03:00
4e135bb6b6 Merge pull request #218 from eworm-de/remove-autoconf-files
remove autoconf files, generate by autogen.sh
2015-08-12 17:13:22 -03:00
2ed83d6902 Merge branch 'master' of https://github.com/hishamhm/htop 2015-08-12 17:11:28 -03:00
041fa9ffa6 Update Settings.h 2015-08-12 17:11:07 -03:00
c34b574073 Merge pull request #223 from eworm-de/langinfo
simplify UTF-8 detection
2015-08-12 17:11:03 -03:00
e42d78007e Merge pull request #230 from maksqwe/cstime_fix
Fix sort by cstime
2015-08-12 17:08:26 -03:00
fc0e44662c Add shortcut key 'p' to toggle full program paths. 2015-08-07 14:20:14 +02:00
293eec4265 New setting: "Show program path"
Add a setting to hide all but the last component from the programme
path, leaving only the "basename". Makes htop more usable on smaller
screens, or systems with longer than average paths. Off by default.

"Highlight program basename" will still be respected, to further
visually separate process names from their arguments.
2015-08-07 14:20:14 +02:00
c33d32e66b Merge pull request #235 from peter-warhzner/patch-1
Fix typo in comment
2015-08-04 16:36:26 -03:00
6f6f0e36ad Fix typo in comment 2015-08-04 18:48:34 +05:00
cea591181d initialize locale for LC_CTYPE only
htop uses scanf functions to parse values from proc filesystem. This
breaks when initializing locale for LC_NUMERIC because of unexpected
commas. So initialize locale for LC_CTYPE only.
2015-07-29 11:28:15 +02:00
1bdee6b6ba Fix sort by cstime 2015-07-23 14:24:39 +03:00
77df258636 remove duplicate code 2015-07-16 08:17:12 +02:00
1728483aa2 simplify UTF-8 detection 2015-07-16 08:12:48 +02:00
016dbbe6a4 initialize locale
This has two effects:

* The locale may have impact on string formatting. So depending on the
  locale we may end up with different decimal point.
* We can use nl_langinfo() for UTF-8 detection.
2015-07-16 08:08:18 +02:00
ff49f558b2 remove autoconf files, generate by autogen.sh 2015-07-15 09:30:38 +02:00
e5f810e0a2 Merge pull request #226 from eworm-de/nice
paint PROCESS_LOW_PRIORITY in green
2015-07-14 23:16:11 -03:00
a588c6d179 paint PROCESS_LOW_PRIORITY in green
... and thus make it use a different color than PROCESS_HIGH_PRIORITY.
2015-07-14 12:43:38 +02:00
b1aea7f748 Merge pull request #207 from eworm-de/settings
write header length (number of columns) back to configuration
2015-06-16 16:13:50 -03:00
5f60486002 Merge pull request #211 from eworm-de/empty-meter
ignore enter, delete and space on empty panel
2015-06-16 16:12:00 -03:00
67a88ae11d Merge pull request #205 from EliteTK/issue-201
Change all displayed memory size specifiers to use GNU Coreutils style size specifiers
2015-06-16 16:09:32 -03:00
b796362e90 ignore enter, delete and space on empty panel 2015-06-15 11:09:32 +02:00
a804f1f848 write header length (number of columns) back to configuration 2015-06-12 01:35:12 +02:00
03826fbc54 Added information about memory sizes to man page
The man page now contains the section "MEMORY SIZES" which talks about
the convention used for representing memory sizes and why it was chosen.
2015-06-09 00:11:43 +01:00
16d8cc7c38 Changed MemoryMeter and SwapMeter to use short memory sizes
The MemoryMeter and SwapMeter now use the short GNU Coreutils style
format to represent memory sizes.
2015-06-09 00:08:06 +01:00
abe165fe5c Merge pull request #194 from eworm-de/warnings
fix compiler warnings
2015-06-08 15:26:24 -03:00
2351fdea31 Merge pull request #195 from eworm-de/gitignore
add */.dirstamp to .gitignore
2015-06-08 15:24:55 -03:00
75d0eda6f9 Merge pull request #196 from sherpya/master
added missing defines for android
2015-06-08 15:23:12 -03:00
d7c3dc748f Merge pull request #203 from Lance0312/fix-freebsd-compilation-errors
Fix several FreeBSD compilation errors
2015-06-08 15:22:10 -03:00
5a5dc71770 Cast FreeBSDProcess_new to Process_New
`Process_new_fn` had been renamed to `Process_New` in
d880def0e9
2015-06-07 17:31:05 +08:00
1efa544e1b Re-run MakeHeader.py on freebsd/FreeBSDProcess.c
Several functions and struct had changed in
b291fba02b
2015-06-07 17:30:55 +08:00
a8e1c1c63f added missing defines for android 2015-05-20 04:30:11 +02:00
867dece8fe add */.dirstamp to .gitignore 2015-05-15 11:38:16 +02:00
08829cbc3b fix compiler warnings
gcc gives warnings like this:

warning: ignoring return value of ‘fscanf’, declared with attribute
warn_unused_result

Assign value to a variable, cast to (void) to discard it.
2015-05-15 11:33:25 +02:00
f1e8a074f2 store cpuCount in an attribute 2015-05-13 15:13:55 -03:00
f4f6d54ffd Fix compilation of OpenVZ support.
Closes #185.
Closes #190.
2015-05-13 15:00:58 -03:00
64ecba2583 update bar when clicking header. 2015-04-09 16:02:14 -03:00
ac8b934498 Fix failing stuff. 2015-04-09 15:56:43 -03:00
01737ed66b Reset to the default scheme, not the last one. 2015-04-09 15:44:26 -03:00
2f45008477 Enable OOM support unconditionally on Linux.
Read OOM data only if column is enabled.
Make sort ordering more consistent. Closes #182.
2015-04-09 15:41:21 -03:00
b291fba02b Fixes to use platform-specific compare routines. 2015-04-09 15:40:46 -03:00
dc4576d327 Fix saving new color scheme. 2015-04-09 15:19:31 -03:00
b1f934c5d5 Visual tweaks: change color when following, add Broken Gray theme. 2015-04-09 15:17:20 -03:00
01a29f0267 84.9% test coverage in the wip branch! 2015-04-08 21:27:52 -03:00
094ddc4051 This assert is no longer valid. 2015-04-08 21:27:36 -03:00
d4256d6300 Keep following status when no key is pressed. 2015-04-08 21:25:31 -03:00
fde3457235 Make test more robust. 2015-04-08 19:07:41 -03:00
86d5750451 Merge branch 'master' into wip 2015-04-08 18:47:01 -03:00
e3d1ca0d20 83.9% test coverage! 2015-04-02 03:33:12 -03:00
4e29cad4fe Merge branch 'master' into wip 2015-04-02 02:13:18 -03:00
e5b08447fe Better support for testing under wip branch 2015-04-02 02:13:07 -03:00
d880def0e9 Merge branch 'master' into wip
Conflicts:
	Process.c
	Process.h
	htop.c
	linux/LinuxProcess.c
	linux/LinuxProcess.h
	test_spec.lua
2015-04-02 01:57:37 -03:00
4315e0c2a0 78.8% test coverage! 2015-04-02 01:44:44 -03:00
1179906e95 Add test, change env variable name 2015-04-02 01:41:52 -03:00
cb8ac6b0f1 Ignore coverage files. 2015-03-31 23:24:06 -03:00
a7236559a7 81.1% test coverage! 2015-03-31 23:23:40 -03:00
4c24a9b462 Fixes to subclassing Process. 2015-03-31 23:23:10 -03:00
5320bab202 Cleanup unused field. 2015-03-31 22:31:06 -03:00
849adf6155 78.8% test coverage! 2015-03-30 01:52:39 -03:00
99e58b3200 Add test, change env variable name 2015-03-28 19:36:06 -03:00
4eee71051b Add coverage testing rules 2015-03-28 19:25:48 -03:00
2939a84ea3 Beginnings of a test suite! 2015-03-27 16:30:02 -03:00
63aa02c7a9 Beginnings of a test suite! 2015-03-27 16:29:09 -03:00
80ef119fe7 Add coverage testing rules 2015-03-25 17:14:40 -03:00
70abaadbaf Fix NULL-termination of array for later use by String_freeArray. 2015-03-25 16:36:42 -03:00
a93db5234c handle clicks on panel header line 2015-03-24 23:12:43 -03:00
38fd1bfaba Add a test plan.
A list of functionality to go through and test before releases.
2015-03-23 19:25:57 -03:00
7cb8cb05fb Simplify constructors. 2015-03-23 19:24:34 -03:00
8a11281c67 Merge branch 'master' into wip
Conflicts:
	Panel.c
	htop.c
	htop.h
2015-03-23 18:16:47 -03:00
b1b3f57976 Tempus fugit.
Conflicts:
	htop.c
	htop.h
2015-03-23 18:15:56 -03:00
54f8d8154b Do not trust isalpha(c) for values > 255.
Fixes #174.

Conflicts:
	Panel.c
2015-03-23 18:14:35 -03:00
ade7993fcb incremental search and filter reintegrated! 2015-03-23 17:04:53 -03:00
d0c72c3fb2 Move FunctionBar inside Panel 2015-03-23 15:26:56 -03:00
442a0d33e4 Do not trust isalpha(c) for values > 255.
Fixes #174.
2015-03-22 22:56:28 -03:00
1084a3ff8f Working on integration of IncSet in new branch. 2015-03-22 22:39:33 -03:00
09c7152990 Refactor state control variables. 2015-03-22 02:50:40 -03:00
1e0c530a46 Tempus fugit. 2015-03-21 16:52:54 -03:00
4e064e0db7 Build fixes to resync with FreeBSD changes. 2015-03-16 23:03:40 -03:00
272e2d9b34 Major advances in FreeBSD port. 2015-03-16 23:02:03 -03:00
9ff5d2b243 Fix saving of header states, motion in Setup screen. 2015-03-16 23:01:21 -03:00
14a177800b Remove spurious UTF-8 char from ASCII mode. 2015-03-16 22:58:56 -03:00
59914bfd5b Rename Setup_run to Action_runSetup. 2015-03-16 22:58:23 -03:00
7fd4af80ff Linux build fixes. 2015-03-16 03:25:43 -03:00
5c8b83405b Merge branch 'master' into wip
Conflicts:
	Process.c
	Process.h
	linux/LinuxProcess.c
	linux/LinuxProcess.h
	linux/LinuxProcessList.c
	unsupported/Platform.c
	unsupported/Platform.h
2015-03-16 03:22:33 -03:00
ddbb71d1c8 Add files to unsupported platform. 2015-03-16 03:16:18 -03:00
adbfe3c3f1 Get FreeBSD tree to compile again with latest changes. 2015-03-16 03:14:20 -03:00
40f3391a3c Merge branch 'wip' of https://github.com/hishamhm/htop into freebsd 2015-03-16 01:45:05 -03:00
be1700cf94 Isolate portable and Linux-specific process fields. 2015-03-16 01:43:04 -03:00
a44a64d0ee Merge branch 'wip' of https://github.com/hishamhm/htop into freebsd 2015-03-15 23:03:43 -03:00
bc928d7f47 Add MainPanel.c 2015-03-15 23:03:26 -03:00
967b6569a1 Merge branch 'wip' of https://github.com/hishamhm/htop into freebsd 2015-03-15 22:57:01 -03:00
d2acffa59a Merge branch 'wip' of https://github.com/hishamhm/htop into freebsd
Conflicts:
	htop.c
	unsupported/Platform.h
2015-03-15 22:53:10 -03:00
e3fe3962cb Move more Linux-specific code into Linux subdir. 2015-03-15 20:29:13 -03:00
e7d6eb6a82 Fix deletion of processes. Closes #172.
Conflicts:
	linux/LinuxProcess.c
2015-03-08 19:52:28 -03:00
a4b03e8875 Improve reading of cgroups. 2015-03-08 19:47:49 -03:00
39a725abc2 Fix deletion of processes. Closes #172. 2015-03-08 19:45:56 -03:00
0a184b769f Merge fixes 2015-02-23 03:53:36 -03:00
50000d808e Silence warnings reported in #70. 2015-02-23 03:34:06 -03:00
8b5b73825e Oops, remove test code committed by accident. 2015-02-23 01:14:20 -03:00
9780c312f4 Fix allocation of processes. Closes #166.
Conflicts:
	Process.c
	Process.h
	ProcessList.c
	ScreenManager.c
	linux/LinuxProcessList.c
2015-02-23 01:13:40 -03:00
cce2202a1f Work on fixing build of "unsupported" platform 2015-02-23 01:02:27 -03:00
5ca9b8e002 Work on fixing build of "unsupported" platform 2015-02-23 00:59:24 -03:00
6f868b00c0 Fix allocation of processes. Closes #166. 2015-02-20 14:52:10 -02:00
f97d1bc54a Merge branch 'master' into wip 2015-02-04 12:19:52 -02:00
aed9b9d18e Test if -Wextra is supported. Closes #155. 2015-02-04 12:19:04 -02:00
cc26974129 Match IO field descriptions with new labels. 2015-02-04 11:47:00 -02:00
574c3decb5 Move graph according to configured CRT_delay. 2015-02-04 11:42:54 -02:00
4a26ac05b0 Let's see if responsiveness is still good using the full CRT_delay
in ncurses. CPU usage goes down noticeably.
(Also, add missing comma, sorry.)
2015-02-04 11:41:53 -02:00
cfc773f7ee Use UTF-8 only when using UTF-8 :-) 2015-02-04 11:41:02 -02:00
6302b3e593 Make sure these are initialized. 2015-02-04 11:40:44 -02:00
d7c843c23b Complete cursor-based movement of headers. 2015-02-03 22:32:07 +01:00
14bd77c5f4 Add longer descriptions to available meters. 2015-02-03 22:31:44 +01:00
f5f29ceeb9 Make the implementation of color schemes declarative. 2015-02-03 22:30:05 +01:00
c3a7b2f134 Merge branch 'master' into wip 2015-01-23 11:23:44 -02:00
83a829a286 Remove bogus assertion. Closes #159. 2015-01-23 11:22:55 -02:00
c2108e5a48 Another mega-patch for the refactoring process.
Kinda runs, but functionality from the original main loop
is still missing. Patience.
2015-01-23 03:08:21 -02:00
3383d8e556 Sorry about the mega-patch.
This is a work-in-progress, code is currently broken.
(Some actions, and notably, the header, are missing.)
2015-01-21 23:27:31 -02:00
36b7832884 Fix initialization of cpuData structure. Closes #159. 2015-01-19 16:24:56 -02:00
c29e53c5d5 Add a stub for the battery meter. 2014-11-27 21:07:42 -02:00
d4c26a3932 Merge branch 'master' into freebsd 2014-11-27 21:05:30 -02:00
d20160cb4f Merge branch 'master' of https://github.com/hishamhm/htop 2014-11-27 21:05:20 -02:00
430c7c9a9b Move platform-dependent parts of Linux battery meter. 2014-11-27 21:04:57 -02:00
f4c49ff92e "get max pid" for FreeBSD 2014-11-27 20:18:01 -02:00
da0956d1cd Merge branch 'master' into freebsd 2014-11-27 20:10:53 -02:00
03ca7da85f Merge branch 'master' of https://github.com/hishamhm/htop 2014-11-27 20:10:42 -02:00
b4f6b11092 Move "get max pid" code into platform specific area. 2014-11-27 20:10:23 -02:00
a89758094f check /proc only if using /proc 2014-11-27 20:04:53 -02:00
6d92d7f73d Load averages for FreeBSD! 2014-11-27 20:03:29 -02:00
96e03739c4 Merge branch 'master' into freebsd 2014-11-27 19:58:35 -02:00
5578a316f0 Merge branch 'master' of https://github.com/hishamhm/htop 2014-11-27 19:58:07 -02:00
529095607c Isolate cross-platform code for load average. 2014-11-27 19:57:24 -02:00
e748401588 Build fix. 2014-11-27 19:46:01 -02:00
3ba3d6fa6f Add uptime calculation code. 2014-11-27 19:44:20 -02:00
1dd165c14b Merge branch 'master' into freebsd 2014-11-27 19:41:31 -02:00
ca03094bb2 Make UptimeMeter cross-platform again. 2014-11-27 19:41:14 -02:00
2dcdd87658 Move UptimeMeter back into cross-platform code.
We'll just isolate the platform-dependent bit.
2014-11-27 19:34:47 -02:00
a9f05c2a8b Uptime meter for FreeBSD.
This will produce too much replicated code.
I think I'll use a lighter abstraction in things like this.
2014-11-27 19:33:37 -02:00
79662291fa Merge branch 'master' into freebsd 2014-11-27 19:19:54 -02:00
357e7a3243 Move UptimeMeter into platform-dependent area.
Set up environment to move other meters.
2014-11-27 19:18:14 -02:00
b192af006f Decouple Header from Meter classes.
(Yes, that's dynamic typing!)
2014-11-27 18:38:52 -02:00
0aa485cf47 Reading swap data! 2014-11-27 18:31:39 -02:00
d8f2b5abf7 Merge branch 'master' into freebsd 2014-11-27 17:49:05 -02:00
cda6bdd56b Add ProcessList_delete to the variable interface. 2014-11-27 17:48:38 -02:00
28712f22b1 Reading first bits of data! 2014-11-27 17:44:55 -02:00
8a2e235a48 Merge branch 'master' into freebsd 2014-11-27 16:32:32 -02:00
ff4d1b466f Build fixes. 2014-11-27 16:31:42 -02:00
6afacee50d A little refactoring 2014-11-27 16:28:32 -02:00
8915b29395 Beginnings of FreeBSD port! 2014-11-27 16:27:34 -02:00
a75161f862 Get Linux "emulation" working again for our FreeBSD folks using linprocfs. 2014-11-24 20:11:33 -02:00
aaaaf063a1 Builds on Linux again! 2014-11-24 19:22:50 -02:00
26422af608 Files moved and added for supporting separate platforms. 2014-11-24 18:55:49 -02:00
eb229d9aef Changes for supporting separate platform subdirectories. 2014-11-24 18:55:03 -02:00
1eda099d06 Another portability tweak. 2014-11-19 23:27:21 -02:00
9faf4938b8 Refactored key handlers.
Made the logic more modular, hopefully easier to follow,
and removed repeated code.
Plus, some optimization in RichString code.
2014-11-19 23:17:52 -02:00
300af4b829 Minor reorganization. 2014-11-19 23:17:16 -02:00
66ec872fc6 Merge pull request #137 from Kayvlim/master
Added new color for 'D' state.
2014-10-13 23:01:37 -03:00
b2e94d626d Fixed a wrong attribution. 2014-10-14 02:48:17 +01:00
64e0d9452d Added new color for 'D' state. 2014-10-14 02:30:17 +01:00
ab0bceb550 Interpret command line PIDs as PIDs, not TIDs 2014-10-08 11:52:56 -05:00
0e8a02367e Merge branch 'master' of https://github.com/hishamhm/htop 2014-06-04 16:49:33 -03:00
eb196f8ba4 Get two data points for meters.
Ensure one mini-reading-cycle runs before getting the UI active
so we have two data points to get better meter measurements from
the get-go.
2014-06-04 16:45:55 -03:00
e4882ed9fb Merge pull request #95 from Sworddragon/master
FLT columns for the manpage
2014-05-23 22:45:54 -03:00
0fc388f2ee Added columns for the page faults in the manpage 2014-05-17 20:22:30 +02:00
0341cb3b5f Minor fixes for the manpage 2014-05-17 20:20:58 +02:00
56cf323ccf Merge pull request #93 from Sworddragon/master
Manpage update
2014-05-15 12:00:16 -03:00
afe0c8cb45 Reordered columns in the manpage 2014-05-15 10:19:37 +02:00
bbd62c1929 Added columns and added/fixed aliases in the manpage 2014-05-15 10:19:22 +02:00
9ba8e2ed05 Merge pull request #86 from stefanbeller/gitignore
Add a .gitignore file
2014-05-06 11:56:00 -03:00
4eeb9d5e64 Add a .gitignore file
This file tells git to ignore the files generated via
./autogen.sh && ./configure && make
2014-05-06 16:21:15 +02:00
8a1c304bed Merge branch 'master' of https://github.com/hishamhm/htop 2014-05-05 23:19:07 -03:00
b7de9bd0f5 Don't stop refreshing if clock was adjusted. 2014-05-05 23:18:14 -03:00
f0e2a0e771 Merge pull request #82 from yardenac/processlist
pass processlist flags to readOpenVZData (fixes build error)
2014-05-04 18:52:11 -03:00
yar
730ab0c9a8 pass processlist flags to readOpenVZData (fixes build error) 2014-05-04 09:43:45 -07:00
ff6cddfd16 Document $HTOPRC. Closes #73. 2014-05-03 18:14:08 -03:00
da16de5a86 Update changelog. 2014-05-03 18:09:31 -03:00
4939468df0 Fix crash when scrolling in a filter view with no processes. Closes #76. 2014-05-03 18:08:46 -03:00
7f92c58916 Avoid weird behavior when exiting help pressing keys such as F2. 2014-05-03 18:08:12 -03:00
f54a37b4a9 Update values for fields whose columns may appear later. Fixes #80. 2014-05-03 17:51:19 -03:00
c3e66b2d81 Make VPID use PID-width format. Closes #79. 2014-05-03 17:26:11 -03:00
ebd5de37ac Fix behavior of htop -d 1. Closes #72. 2014-04-28 17:55:52 -03:00
78d09f955a Compare with long, for 64-bit systems 2014-04-25 19:41:23 -03:00
d7e5020169 Merge branch 'master' of https://github.com/hishamhm/htop 2014-04-25 19:37:41 -03:00
ea191b53bd Fix time-based sorting 2014-04-25 19:37:07 -03:00
88c3758051 Now, when you disable a filter (F4 → Esc), it will go back to unfiltered mode
but the current process will remain selected (so you can filter, choose and
then go back to unfiltered mode to see the children of that process).

Inspired by feedback at http://www.reddit.com/r/linux/comments/23wpc7/announcing_htop_103_with_new_features_bugfixes/ch1paos
2014-04-25 16:05:25 -03:00
43c3e4d3d9 Preparing release 1.0.3. 2014-04-24 19:54:35 -03:00
9eec37c432 More sanity checks. 2014-04-24 19:54:06 -03:00
27da00f339 Improve function prototype, helping analysis. 2014-04-24 19:50:33 -03:00
d5b3b6d692 Add corresponding .h file. 2014-04-24 19:50:03 -03:00
616ee966d7 Fix out-of-bounds write. 2014-04-24 19:48:34 -03:00
50b701258d Make static analyzers happy. 2014-04-24 19:46:10 -03:00
814ce89b45 Oops, fix use of memset. 2014-04-24 19:44:41 -03:00
659251c501 Fix array limit. 2014-04-24 19:43:27 -03:00
e0209da88f Support pagefaults stats. Closes #45. 2014-04-24 19:40:47 -03:00
4e2c2d7927 Fix resource leak. 2014-04-24 19:29:20 -03:00
eb1cd4aca6 change swap to M for consistency. Closes #63. 2014-04-24 19:03:07 -03:00
ab118c2dbe Update changelog items. 2014-04-24 15:10:29 -03:00
2f30cd1070 Boost field buffer size - crashes when trying to draw very deep UTF-8 trees
Test by nesting 30 shells
Patch from ArchLinux. Closes #65.
2014-04-24 15:08:32 -03:00
a939cdf827 Better consistency in coloring. Closes #66.
For now rates won't be colored gray when zero; I'll think about that.
2014-04-24 15:00:09 -03:00
100bd10b1d Make blue text more readable. Closes #55. 2014-04-24 13:15:52 -03:00
f86851766b Both IO_PRIO and IO_RATE had the same column heading. Closes #61. 2014-04-24 12:52:26 -03:00
6795d8b692 Report as an exit function. 2014-04-24 12:20:03 -03:00
6fbc5a31da Report this as an exit function. 2014-04-24 12:17:11 -03:00
446d86c7a2 Let's see if this assert makes static analyzers happier. 2014-04-24 12:16:51 -03:00
2fdebf6a29 Remove useless test. 2014-04-24 12:16:21 -03:00
34b89a9747 Add sanity checks. 2014-04-24 12:15:56 -03:00
823bdbae13 safer code, check result of lstat 2014-04-22 20:35:57 -03:00
1afbc19087 safer code, test for return of fcntl 2014-04-22 20:35:44 -03:00
28d4cad5fe xread may return -1. 2014-04-22 18:48:27 -03:00
2ee1c41274 Add .h file ref previous commit 2014-04-22 18:48:15 -03:00
1de8762e71 Fix display of open files.
Cleanup the code to prevent this bug from happening again.
2014-04-22 18:45:47 -03:00
d28b281165 Fix compiler complaints. 2014-04-22 18:19:24 -03:00
b1564c2be9 Refactor and fix resource leaks. 2014-04-22 18:19:01 -03:00
79e390120a Remove use of usleep, which is sadly obsolete. 2014-04-21 19:37:57 -03:00
f239b62b90 Restrict size of read. 2014-04-21 19:18:08 -03:00
f677843288 Restrict size of inputs on sscanf reads. 2014-04-21 19:17:57 -03:00
3fbd1ef76d check return of topoErr 2014-04-21 19:17:46 -03:00
30bafafb24 avoid strtok and reduce scope of variables. 2014-04-21 19:16:16 -03:00
57b393f783 shorten scope of variable. 2014-04-21 19:01:15 -03:00
5b30280810 shorten scope of variables. 2014-04-21 19:00:35 -03:00
0a4ddab2a4 Use proper format string for unsigned data. 2014-04-21 19:00:12 -03:00
2bf8754bc2 Remove useless assignment. 2014-04-21 18:59:52 -03:00
f5a469b5a8 Use reentrant version to silence warnings. 2014-04-21 18:59:30 -03:00
4027e5ee44 goto considered harmful and confuses cppcheck. 2014-04-21 18:55:58 -03:00
2f0a4b3d3a Test realloc failure to make cppcheck happy 2014-04-21 18:23:34 -03:00
99bc23771f Fix resource leak detected by cppcheck 2014-04-21 18:23:21 -03:00
af02749722 Merge branch 'master' of https://github.com/hishamhm/htop 2014-04-11 20:18:27 -03:00
4716a9857b Fix logic for skipping non-numeric directories.
Closes #42.
2014-04-11 20:17:07 -03:00
c8be3701b8 Fix tree view if userland threads are hidden. 2014-04-11 13:45:24 +02:00
1ac517be52 Fix padding in large numbers. (See #40) 2014-04-10 13:22:33 -03:00
96858744b5 Avoid "else" trick with #ifdef, hopefully makes code easier to follow. 2014-04-09 23:14:41 -03:00
5d6ad853fa Support for very large numbers, now tested on a 64-bit machine. 2014-04-09 22:49:36 -03:00
127f847ca5 Support really large numbers on 64-bit architectures; first try. 2014-04-09 22:32:54 -03:00
19b438de10 Improve discoverability of the expand/collapse feature.
It is now accessible via F6 when on tree view (as a bonus, it is
now also reachable via the mouse). The function bar now dynamically
changes to reflect the toggle nature of the tree-view mode (F5)
and the F6 key serves as expand/collapse when on tree mode,
and its previous behavior of bringing up the "Sort By" menu
(which only made sense on non-tree mode). Users wishing to go to
the "Sort By" menu straight from Tree View can still do so with the
"<" and ">" keys (the top-compatible keys for sort selection).
2014-04-09 18:02:50 -03:00
af4c412ebf Better support for Home and End keys 2014-04-09 17:47:22 -03:00
cb297af848 Fix invalid access when highlighting basename of threads. 2014-04-09 17:43:54 -03:00
f2e4556b5e Updated icon! 2014-04-09 14:47:58 -03:00
1d9e1b0118 Add missing check for return value and be more conservative in constructs to avoid future slips of this kind. 2014-04-09 14:47:32 -03:00
369bef279a a nicer look 2014-04-05 19:56:35 -03:00
c0fc5bf898 alert to Mac users 2014-04-05 19:53:15 -03:00
f2a190b0e9 New logic for highlighting basenames with spaces 2014-02-27 17:11:23 -03:00
61bd770689 Merge branch 'master' of https://github.com/hishamhm/htop 2014-02-27 16:43:39 -03:00
6d90e58c01 alignment improvements 2014-02-27 16:35:22 -03:00
88ca9dcfa0 Update README 2014-02-24 21:05:12 -03:00
953ec71235 Add README.md for Github 2014-02-03 09:11:39 -02:00
817e292ac9 Update README file 2014-02-03 09:11:08 -02:00
11b251a577 Update changelog 2014-01-30 15:47:32 -02:00
96b57ea812 Merge pull request #10 from simpleigh/master
Added additional column to monitor OOM killer score of each process
2014-01-30 09:46:32 -08:00
da236ca318 Added additional column to monitor OOM killer score of each process 2014-01-29 22:41:55 +00:00
558b001e2b Merge pull request #6 from zed-0xff/patch-1
fix column shift on wrong megabytes format
2014-01-29 13:17:39 -08:00
6fcceeff04 Merge pull request #4 from robberos/master
Possible to regenerate headers outside of srcdir
2014-01-29 13:15:33 -08:00
7afda7f5a1 fix column shift on wrong megabytes format
see http://0xff.me/htop_bug.png
2014-01-21 11:35:53 +03:00
5aac1733a6 Possible to regenerate headers outside of srcdir 2014-01-17 09:33:52 +01:00
76a715ee8c Fix order of calloc arguments.
(Patch by Dawid Gajownik)
2014-01-16 18:51:16 -02:00
c1e0f6e17c BUGFIX: Fix crash when adding meters and toggling detailed CPU time.
See https://bugzilla.redhat.com/show_bug.cgi?id=987805 for details.
(thanks to Dawid Gajownik for the detailed analysis!)
2014-01-16 01:40:47 -02:00
4256c23d84 Refactor the drawing of the help screen 2014-01-14 00:24:12 -02:00
1c0e93c1bd First new feature of the git era! "c" key tags all children of a process. 2014-01-14 00:23:41 -02:00
cd692f27f4 There was a bug in my implementaion. No reason not to use the glibc version. 2014-01-14 00:21:37 -02:00
7fd5e80429 New home, new life! 2014-01-14 00:19:44 -02:00
8ace29c267 Make CPU meter optionally account guest time in its percentages 2013-12-18 02:58:34 +00:00
af285d1d3b Fixes in accounting of guest time when using virtualization
(thanks to Patrick Marlier)
2013-12-18 02:20:39 +00:00
6cfa9e0bf2 Performance improvements due to conditional parsing of IO data depending on selected fields.
On my machine, this gives a ~20% improvement in htop process time use with the default config.
2013-05-24 22:46:01 +00:00
5c2d84aba3 Apply patch fixing typos, and catch another one. Closes #3613760. 2013-05-23 00:19:16 +00:00
322ba274ea Performance improvements
(thanks to Jann Horn)
2013-04-29 23:00:15 +00:00
ee5dc46fee Don't end up killing init if process selected to be killed terminates before the user selects a signal. Closes #3606072. 2013-02-26 20:24:27 +00:00
a0810561f3 Add extra checks in configure.ac for different locations of (n)curses.h 2013-02-26 17:10:11 +00:00
43a7231615 Remove explicit calls to curses.h in other files 2013-02-26 16:50:21 +00:00
8d5dd51cf2 Fix crash when pressing 'u'. Thanks to Quentin Carbonneaux. 2012-12-12 13:03:52 +00:00
00b324bfc1 Changes in object model: separate class objects to store vtable. Also, nicer UTF-8 display of big numbers. 2012-12-05 15:12:20 +00:00
2a73405cd0 search and filter for the strace and lsof screens! 2012-11-10 00:31:37 +00:00
259e1a2938 fixes PGRP and SESN columns in case of big pids. Patch #3567904. 2012-10-20 01:45:41 +00:00
f44a8f2009 Option to update process names on every refresh
(thanks to Rob Hoelz)
2012-10-20 00:43:25 +00:00
1b21827f1f Fail gracefully when /proc is not mounted
(thanks to Philipp Hagemeister)
2012-10-19 18:59:48 +00:00
47e881f460 Add IO priority support ('i' key) 2012-10-04 23:59:45 +00:00
e6c6d7fbf7 Add -p flag, contributed by Rob Hoelz 2012-08-10 21:54:41 +00:00
6c71b7ed2d improve crash message 2012-07-12 16:20:16 +00:00
078b831696 don't downcast to int before determining number of hours 2012-06-25 03:06:36 +00:00
0d8f654343 allow 'k' to kill multiple processes again (when did this break?...) 2012-06-05 19:18:54 +00:00
fae598fce8 Continue following when switching to tree view. Patch by Richard Wang. 2012-05-28 20:42:40 +00:00
ac36e4acbf fix message in help screen 2012-05-28 01:02:06 +00:00
90d567531a Fix CPU percentage. Patch 3522180 for bug 3516978, by Richard. 2012-05-28 00:47:05 +00:00
05a78c8111 Auto-follow process when selecting which signal to use when killing a process.
This avoids killing the wrong process.
2012-03-30 01:20:32 +00:00
bca656c79e Fix crashes when process list is empty 2012-03-05 11:18:27 +00:00
368cb1fe20 avoid deleting valid symbolic links to .htoprc
so that home directories can be used with both old and new versions of htop
(see #3496731).
2012-03-05 11:12:58 +00:00
571ae33bb4 Fix warning on ARM processors.
Thanks to Kelly Anderson.
2012-02-17 13:45:58 +00:00
1a604a05a5 BUGFIX: behavior of 'F' (follow) key was broken, also affecting the
persistence of mouse selections. Closes #3165065.
2012-02-02 23:45:40 +00:00
58676d7001 minor style cleanups 2012-02-02 22:03:07 +00:00
ff8d54c221 Extra check if Process_getAffinity fails.
I could not reproduce the crash in current SVN 
(I've been adding checks for problems like this),
but the sanity check looks correct.
Thanks to Cybjit. Closes #3481053.
2012-01-29 23:51:36 +00:00
8b73d11ac6 make htop trunk compile on FreeBSD 8.2-STABLE
(thanks to Trond Endestrol)
2012-01-03 18:19:11 +00:00
5b3cc559b2 remove old reference to hwloc directory 2011-12-26 22:09:59 +00:00
45f7a4fc8d Remove old memory debugging routines. We have Valgrind nowadays. 2011-12-26 22:04:29 +00:00
84281bdc44 major header cleanup 2011-12-26 21:35:57 +00:00
81e44312b4 Use strdup explicitly 2011-12-25 20:23:53 +00:00
93233a67ea Move .htoprc to XDG-compliant path ~/.config/htop/htoprc,
respecting $XDG_CONFIG_HOME 
(thanks to Hadzhimurad Ustarkhan for the suggestion.)
2011-12-25 20:22:41 +00:00
5b0b2255ef Fix typo that has been lurking since 2006 2011-12-23 19:12:17 +00:00
59d5eecdfd fix pagedown in some panels 2011-12-14 23:30:16 +00:00
9c44f589d2 show proper values for very large times 2011-12-14 23:29:07 +00:00
0bb8dba937 update changelog, following confirmation of fix from users 2011-12-01 13:13:17 +00:00
bfd86a60cc Keep panel structure up-to-date as process list changes when headers are updated during the screen manager. Hopefully closes #3444533. 2011-12-01 12:31:57 +00:00
dfad0afb36 Don't run sched_setaffinity compatibility test when cross compiling 2011-11-23 18:43:35 +00:00
ae7e68321b cleanup old stuff 2011-11-21 02:58:34 +00:00
bc87a8ff8c Remove bundled hwloc-1.2.1. Use either native Linux affinity support or an external libhwloc.
(for details see https://sourceforge.net/mailarchive/forum.php?thread_name=CAJpkDYeZpwqcWxZ77wq6bMrnhn-KzkU1xAqb3cU0drfnA3n9FQ%40mail.gmail.com&forum_name=htop-general )
2011-11-21 02:52:41 +00:00
7ca1081712 Mega-commit with features and tweaks for 1.0:
* Performance improvements
* Support for splitting CPU meters into two or four columns
  (thanks to Wim Heirman)
* Switch from PLPA, which is now deprecated, to HWLOC.
* Bring back support for native Linux sched_setaffinity,
  so we don't have to use HWLOC where we don't need to.
* Support for typing in user names and column fields in selection panels.
2011-11-18 06:08:56 +00:00
3885648881 reduce code 2011-11-05 04:55:05 +00:00
88f6de2352 build fixes 2011-11-05 04:42:35 +00:00
539b32dc31 simplify code 2011-11-05 04:42:15 +00:00
9f29e92777 update changelog 2011-11-05 04:24:41 +00:00
e204861de5 Allow typing to select items in various panels (sort, user, signal).
Factored code from the SignalsPanel to apply to all selections from main screen.
Closes feature request #3425304.
2011-11-05 04:19:47 +00:00
4c4cceee5d naming consistency 2011-11-05 03:50:44 +00:00
ca6b9238a3 Support for UTF-8 tree drawing
(thanks to Bin Guo)
2011-11-03 22:12:12 +00:00
b45b9e2b33 use unicode header first 2011-11-03 22:07:10 +00:00
9b87e52d41 try to use unicode headers first 2011-11-03 22:01:54 +00:00
c18ccdb910 store cppcheck rule for future use 2011-10-25 00:46:37 +00:00
d1b1cbc757 cleanups and fixes, thanks to cppcheck and gcc -Wextra 2011-10-25 00:05:46 +00:00
75080ce79d Use wider PID columns in 64-bit machines with larger pid_max values. 2011-09-29 18:40:23 +00:00
d25a0bc213 Fix regression in documentation 2011-09-27 00:03:40 +00:00
d1eff65fa5 Add changelog entry. 2011-09-26 03:25:12 +00:00
1afef1899d Add flag to allow using the system install of hwloc. 2011-09-26 03:24:22 +00:00
ec17b7029a Convert affinity control from the deprecated PLPA to HWLOC 2011-09-24 00:30:47 +00:00
d07b043ee0 Fix --sort-key=help 2011-09-08 04:47:48 +00:00
bb3e773c49 Interface improvements for large numbers. 2011-09-08 04:41:03 +00:00
b288eb88c0 minor change to improve portability 2011-09-08 04:29:23 +00:00
3e265ce4ab Add missing header titles. Closes #3152630. 2011-09-08 04:21:31 +00:00
f1f77653e0 removes some basic checks that succeed on most systems anyway and which cause problems for the uClibc folks. Closes #3204565. 2011-09-08 03:40:26 +00:00
5a8307a10b Fix panel inconsistency that could lead to crashes. Closes #2422267. 2011-09-08 03:38:48 +00:00
978019d34f sanity checks 2011-09-08 02:54:02 +00:00
f7fe4b4722 Fix off-by-one error in PROCESSOR display 2011-09-08 02:48:53 +00:00
4e72e790e3 make sure PLPA debug message never shows 2011-09-08 02:32:59 +00:00
31c995e663 Man page updates
(thanks to Vincent Launchbury)
2011-09-08 02:16:11 +00:00
a7bcf1d2e4 Try harder to find the ncurses header, fixes detection in SuSE SLES9.
(thanks to Moritz Barsnick)
2011-09-08 01:45:16 +00:00
25a2aada3c Fix on-screen documentation regarding [ and ] 2011-09-08 01:36:08 +00:00
03322b62ec Realign display of text-mode CPU meters. Closes #3369526. 2011-09-08 01:29:59 +00:00
11092662ee incremental filtering
plus some fixes
2011-09-08 01:17:26 +00:00
3f3213b2e2 show cursor when function bar allows typing an entry. 2011-09-08 01:10:58 +00:00
60e5106098 cleanup our own leak checker so that valgrind is happy with it. 2011-09-08 01:06:12 +00:00
636bb94fe6 improve Valgrind output 2011-09-08 01:01:44 +00:00
27b470e10d Don't simply trust that string splits were successful... 2011-08-29 20:45:29 +00:00
5dfb46e14f Stricter checks for command-line options
(thanks to Sebastian Pipping)
2011-08-26 21:04:26 +00:00
7eeb52dfbb Fix number of supported backtrace frames (thanks to Sebastian Pipping) 2011-08-26 20:56:39 +00:00
717758409e Fix segfault in BarMeterMode_draw() for small terminal widths 2011-08-26 20:55:09 +00:00
aa167adb90 Remove generated files from version history 2011-08-26 20:52:35 +00:00
da604d355a be more precise in the comment 2011-08-12 16:37:27 +00:00
0a81172f62 changelog and future version bump 2011-05-26 16:59:53 +00:00
300caa076e Tempus fugit. 2011-05-26 16:35:07 +00:00
7a9615960f ncurses does not support the scrollwheel well, but this is a step in that direction. 2011-05-26 16:32:50 +00:00
9599e5650e larger numbers 2011-05-26 16:32:05 +00:00
9b3514062f nicer display for large numbers 2011-05-26 16:31:18 +00:00
6382e03b68 fix broken height for All CPUs meter 2011-05-26 16:22:50 +00:00
bd459776a4 retain meter state when it is reinit'ed in the Setup screen 2011-03-31 20:24:59 +00:00
b57b7e9a9e only reinit initializable meters 2011-03-29 15:02:46 +00:00
219bb9ccff handle large values for process time 2011-03-28 19:06:06 +00:00
391eab2866 add missing update to header file 2011-03-28 17:13:28 +00:00
7d7118b1f6 launch lsof for parent process when called on threads. 2011-03-22 22:09:42 +00:00
a9c0ea3753 * Option for counting CPUs from zero
(thanks to Sean Noonan)
* Meters update in every screen (no longer halting while on Setup, etc.)
2011-03-22 20:37:08 +00:00
b561956637 ignore checks for /proc when cross-compiling
(as suggested by Andy Kennedy)
2011-03-22 17:04:39 +00:00
8bdec7155e show names of zombie processes properly 2011-03-17 04:26:28 +00:00
36ef1a93be make htop friendly to uclibc (thanks to Matt for the report) 2010-12-05 15:43:56 +00:00
72dbb72b68 All processes where showing as belonging to 'root'. Fixed.
Thanks to Sven Hartrumpf for pointing this out in htop-0.9-rc2
2010-11-26 16:51:20 +00:00
4367e64b1d Fix online help! 2010-11-24 18:43:31 +00:00
3e7822d660 This seems necessary. 2010-11-24 18:43:02 +00:00
5effb12e46 Fix behavior of expand/collapse-tree. Thanks Rob for the heads up! 2010-11-24 12:00:34 +00:00
941ad72f67 correct thread detection 2010-11-24 01:02:29 +00:00
831538b0f9 Split process and thread counts in tasks meter 2010-11-23 13:28:47 +00:00
d8e1480a27 Remove arbitrary limit from rich strings
Fix subtree hiding
Fix reading of CPU values in hidden threads
Fix hiding of zombie processes as kernel threads
Remove "debug proc" code
Code cleanup in processElements
2010-11-22 12:40:20 +00:00
25551d44c1 Fix off-by-one in Vector (the probable cause for many user-reported crashes?) 2010-11-22 12:38:53 +00:00
9604e02106 Correct tests for missing libraries and optional use of PLPA 2010-11-22 12:24:46 +00:00
e0f364a6f8 Don't install include/ and lib/ directories.
Quick hack to the plpa-1.3.2 Makefile.am to suppress this problem.
Closes #2814374.
2010-11-21 01:58:56 +00:00
2960a8162e BUGFIX: Fix alignment for display of memory values above 100G (sign of the times!)
(thanks to Jan van Haarst for the report.)
Closes #2865619.
2010-11-20 20:35:07 +00:00
10f007e07e Fix for systems where there's no /proc/PID/task/PID/. Closes #2789634. 2010-11-20 20:27:37 +00:00
0ff54ebac9 Fix search by process name when processes are filtered by user. Closes #2803481. 2010-11-20 20:00:31 +00:00
d82e31be24 clarify README about unsupported platforms. 2010-11-20 19:49:24 +00:00
f919ed7cdf Don't ask for bug reports when running on unsupported platforms. 2010-11-20 19:44:08 +00:00
4e29c8235d Use a more correct name for memory option.
User 'sworddragon' in sf.net points out that highlighting '90' in '90000'
is not highlighting a "megabyte", since 90000 is not 90MB.
Closes #3094939.
2010-11-20 19:21:26 +00:00
3fcbcbfda6 Improve battery meter support (thanks to Richard W.) Closes #3063541. 2010-11-20 19:13:12 +00:00
5fd1436a92 Build fixes. BTW, we're going for 0.9 now. 2010-11-20 18:54:39 +00:00
f110ecdabb Fix IO-wait color on "Black on White" scheme. Closes #3054717. 2010-11-20 18:06:49 +00:00
45de5694ac no need to pad values; provide a default on machines without cgroup 2010-10-30 19:30:19 +00:00
84ed4c01f6 Support for cgroups (thanks to Guillaume Zitta and Daniel Lezcano) 2010-10-30 19:24:07 +00:00
b2fee47a14 don't resolve port names 2010-09-02 20:26:16 +00:00
40eac57aef update changelog 2010-08-24 23:20:55 +00:00
6486229308 add support for steal/guest CPU time measurement
simplify processor data accounting (add CPUData structure)
remove Process_clone trick
2010-08-24 23:20:38 +00:00
c166e172a8 little note missing from changelog 2010-07-31 00:15:27 +00:00
0b0bd25e42 home and end keys in trace screens 2010-07-31 00:11:34 +00:00
655c29bce5 Fix display of nan% in CPU meters
(Fix by Steven Hampson)
2010-06-30 18:29:54 +00:00
65bc58ed50 add documentation 2010-06-17 19:04:22 +00:00
9eb912149e expand/collapse tree 2010-06-17 19:02:03 +00:00
bc4f7147cc update changelog 2010-03-29 19:10:20 +00:00
6501432ef6 upgrade PLPA to 1.3.2 2010-03-29 19:08:14 +00:00
8d0fff2f66 Good heuristic for processes started in the same second 2010-03-29 18:44:14 +00:00
dc262f4df6 STARTTIME column 2010-03-29 18:36:11 +00:00
22b0d7df64 oops
(Thanks to Bert Wesarg for the heads up)
2010-03-26 23:03:13 +00:00
b4a63409f5 * Add Bash/emacs style navigation keys
(thanks to Daniel Schuler)
2010-03-03 21:13:33 +00:00
282f16c4b8 fix memory leak 2010-03-03 21:10:51 +00:00
a600d5a6e9 Tempus fugit. 2010-02-25 02:08:18 +00:00
62a31673cb getopt-based long options and --no-color
(thanks to Vincent Launchbury)
2010-02-25 02:04:24 +00:00
02a30bfecd warning fixes 2010-02-25 01:43:18 +00:00
5cc8998688 never show nan% 2010-02-25 01:40:14 +00:00
8f230920cd show custom thread names 2010-02-25 01:37:31 +00:00
aff118ab39 warning fixes 2010-02-25 01:35:12 +00:00
23fc40976e Resolve license incompatibility issues,
as reported by Tom "spot" Callaway from Fedora Legal.
2010-02-24 21:13:45 +00:00
ef31893067 minor tweak 2010-02-22 20:57:25 +00:00
c9e59b4a33 minor tweaks by David Weber 2010-02-22 20:54:01 +00:00
7dcd2beb90 extra checks for lsof failures 2009-10-16 20:15:01 +00:00
a20ba78b5e simplify code 2009-10-16 20:06:47 +00:00
1e124da059 coverity fixes 2009-10-16 20:03:18 +00:00
dd86b9b646 prepare release 0.8.3 2009-06-23 14:02:14 +00:00
2b53419983 * BUGFIX: Fix crash on F6 key
(thanks to Rainer Suhm)
2009-06-23 13:51:36 +00:00
3e6be2d7f7 fix to minor bug affecting the build process, a maintenance release will follow shortly. 2009-06-08 21:08:02 +00:00
4206828d17 oops, add missing files. 2009-06-02 19:29:22 +00:00
7ee2646808 oops, add missing files 2009-06-02 19:28:19 +00:00
4488caa70a Tempus Fugit. 2009-06-02 05:07:08 +00:00
9b8d11d9f1 doc fix 2009-06-02 05:06:20 +00:00
6330ff3a0a changes for htop 0.8.2 2009-06-02 04:51:23 +00:00
1371ee28a7 don't use unbounded operations 2009-06-02 04:49:26 +00:00
b62f9cea6f improve man-page 2009-06-02 04:29:26 +00:00
20bb68824d updated battery meter code from Ian Hands, slightly tweaked 2009-04-27 21:48:09 +00:00
510213591b clean inc search buffer code 2009-04-22 19:26:49 +00:00
843aded57c sort by PROCESSOR and SESSION 2009-03-11 13:52:39 +00:00
31b3a2d2db catch nonprintable characters 2009-03-11 13:51:50 +00:00
385a7dbe1e simplify uptime calculation 2009-03-11 13:26:39 +00:00
3b950e4189 BSD related fixes:
* BUGFIX: Correct page size calculation for FreeBSD systems
  (thanks to Andrew Paulsen)
* Allow compilation without PLPA on systems that don't support it
  (thanks to Timothy Redaelli)
2009-03-11 13:15:43 +00:00
b93e5c00b6 Rename VEID to CTID in OpenVZ systems
(thanks to Thorsten Schifferdecker)
2009-03-11 13:05:19 +00:00
10213f3ea1 improve help on monochrome, fix bug #2430855 2009-02-18 00:34:18 +00:00
f2ef3b74a0 * corrections to the desktop entry file
(thanks by Samuli Suominen)
2009-02-18 00:06:18 +00:00
ac5cecb6fc Option to display hostname in the meters area 2009-02-17 18:33:32 +00:00
c3d682b0f6 fix bug #2171752 2009-02-17 18:13:25 +00:00
dc38fc2da3 Fix missing tree view when userland threads are hidden
(thanks to Josh Stone)
2009-02-17 17:12:59 +00:00
0baba6d7b4 Fix for VPID on OpenVZ systems
(thanks to Wolfgang Frisch)
2009-02-17 15:36:43 +00:00
a2f6eea0c4 Remove assertion that fails on hardened kernels
(thanks to Wolfram Schlich for the report)
2008-09-23 06:29:03 +00:00
11931f1bc8 ACPI Battery meter
contributed by Ian Hands
2008-09-23 06:21:28 +00:00
c3550e18e8 Avoid reading process IO info multiple times on multithreaded processes.
Bugfix from Gerhard Heift.
2008-09-23 05:56:15 +00:00
a5dfaa2393 Add Linux-VServer support,
contributed by Jonathan Sambrook and Benedikt Bohm
2008-09-23 04:31:13 +00:00
6beb27d803 Prepare for release 0.8 2008-05-07 23:02:38 +00:00
ce3114079c Fix mouseclick handling in top bar 2008-05-07 23:02:23 +00:00
15ab0ad706 Let mouseclicks tick/untick checkboxes 2008-05-07 23:01:45 +00:00
23615d63a8 Make setup screen fully mouse-driveable 2008-04-23 07:24:27 +00:00
b09339d643 Enabling taskstats by default since they don't break
on systems that don't have them.
2008-03-16 00:31:31 +00:00
2338ad5820 Ability to change sort column with the mouse by
clicking column titles (click again to invert order).
Also, add a consolidated IO kbyte/s column.
2008-03-14 18:50:49 +00:00
fa6f919059 Add missing bits to build system, needed by the inclusion of PLPA.
Thanks to Bert Wesarg for the heads up.
2008-03-11 19:22:17 +00:00
da23c8c5a1 Clean up headers by using 'static' whenever possible.
Reduces resulting code size.
2008-03-09 08:58:38 +00:00
12f4f09e6e Add support for Linux per-process IO statistics,
enabled with the --enable-taskstats flag, which
requires a kernel compiled with taskstats support.
Thanks to Tobias Oetiker!
2008-03-09 08:02:22 +00:00
460608d6e2 Make column operation more comfortable. 2008-03-09 07:42:19 +00:00
8fa33dc336 Add Unicode support, enabled with the --enable-unicode
flag, which requires libncursesw.
Thanks to Sergej Pupykin!
2008-03-09 02:33:23 +00:00
fa87ff0251 Clean up htop's configure options. 2008-03-09 02:16:21 +00:00
93f091c47e BUGFIX: Fix display of CPU count for threaded processes.
When user threads are hidden, process now shows the
sum of processor usage for all processors. When user
threads are displayed, each thread shows its own
processor usage, including the root thread.
(thanks to Bert Wesarg for the report)
Also, add option to display thread colors differently.
2008-03-08 23:39:48 +00:00
52840406ac Make sure help screen is properly filled.
Make behavior of H key consistent.
2008-03-08 23:30:35 +00:00
4df76d127b Embed PLPA (Portable Linux Processor Affinity) in order to support
conflicting affinity API of different Linux kernel versions.
2008-03-05 09:46:47 +00:00
5ed2b85c84 Make clicks on leftmost panel in the Setup screen change setup pages,
like the keyboard navigation does. Fixes bug reported by Tero Keinanen.
https://sourceforge.net/tracker/index.php?func=detail&aid=1754735&group_id=108839&atid=651633
2008-03-05 06:54:30 +00:00
062433fe04 Time keeps passing by 2008-03-05 06:52:22 +00:00
657b0f5efc Time keeps passing by 2008-03-05 06:51:32 +00:00
37bb2fc5c7 Fix display of time with the "Black on White" theme. 2008-03-05 06:39:29 +00:00
cf7fdcd1d6 Experimental feature: beep on permission failures.
Update dates.
2007-12-17 05:57:28 +00:00
a839c3f2ca Adding affinity panel 2007-12-17 05:50:00 +00:00
807df03671 Avoid crashing when using many meters (thanks to David Cho for the report) 2007-11-26 22:06:25 +00:00
277 changed files with 36528 additions and 7311 deletions

17
.editorconfig Normal file
View File

@ -0,0 +1,17 @@
# EditorConfig configuration for htop
# http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file, utf-8 charset
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
# match C source and header files, set indent to three spaces
[*.{c,h}]
indent_style = space
indent_size = 3
trim_trailing_whitespace = true

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
open_collective: htop

171
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,171 @@
name: CI
on: [ push, pull_request ]
env:
# Enable format attributes in ncurses headers
# Enable fortified memory/string handling
CPPFLAGS: -DGCC_PRINTF -DGCC_SCANF -D_FORTIFY_SOURCE=2
jobs:
build-ubuntu-latest-minimal-gcc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends libncursesw5-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-werror --enable-affinity --disable-unicode --disable-sensors
- name: Enable compatibility modes
run: |
sed -i 's/#define HAVE_FSTATAT 1/#undef HAVE_FSTATAT/g' config.h
sed -i 's/#define HAVE_OPENAT 1/#undef HAVE_OPENAT/g' config.h
sed -i 's/#define HAVE_READLINKAT 1/#undef HAVE_READLINKAT/g' config.h
- name: Build
run: make -k
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS="--enable-werror --enable-affinity --disable-unicode --disable-sensors"
build-ubuntu-latest-minimal-clang:
runs-on: ubuntu-latest
env:
CC: clang-12
steps:
- uses: actions/checkout@v2
- name: install clang repo
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y
sudo apt-get update -q
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends clang-12 libncursesw5-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-werror --enable-affinity --disable-unicode --disable-sensors
- name: Build
run: make -k
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS="--enable-werror --enable-affinity --disable-unicode --disable-sensors"
build-ubuntu-latest-full-featured-gcc:
runs-on: ubuntu-latest
# Enable LTO, might trigger additional warnings on advanced inlining
env:
CFLAGS: -O3 -g -flto
LDFLAGS: -O3 -g -flto -Wl,--as-needed
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities
- name: Build
run: make -k
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities'
build-ubuntu-latest-full-featured-clang:
runs-on: ubuntu-latest
env:
CC: clang-12
steps:
- uses: actions/checkout@v2
- name: install clang repo
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y
sudo apt-get update -q
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends clang-12 libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities
- name: Build
run: make -k
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities'
build-ubuntu-latest-gcc-static:
runs-on: ubuntu-latest
# Enable LTO, might trigger additional warnings on advanced inlining
env:
CFLAGS: -O3 -g -flto
LDFLAGS: -O3 -g -flto
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends libncursesw5-dev libtinfo-dev libgpm-dev libsensors4-dev libcap-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-static --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --disable-hwloc --disable-delayacct --enable-sensors --enable-capabilities
- name: Build
run: make -k
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-static --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --disable-hwloc --disable-delayacct --enable-sensors --enable-capabilities'
build-ubuntu-latest-pcp:
# Turns out 'ubuntu-latest' can be older than 20.04, we want PCP v5+
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends libpcp3-dev libncursesw5-dev libtinfo-dev libgpm-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
# Until Ubuntu catches up with pcp-5.2.3+, cannot use -werror due to:
# passing argument 2 of pmLookupName from incompatible pointer type
run: ./configure --enable-pcp --enable-unicode
- name: Build
run: make -k
build-ubuntu-latest-clang-analyzer:
runs-on: ubuntu-latest
env:
CC: clang-12
steps:
- uses: actions/checkout@v2
- name: install clang repo
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y
sudo apt-get update -q
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends clang-12 clang-tools-12 libncursesw5-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: scan-build-12 -analyze-headers --status-bugs ./configure --enable-debug --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-delayacct --enable-sensors --enable-capabilities
- name: Build
run: scan-build-12 -analyze-headers --status-bugs make -j"$(nproc)"
build-macos-latest-clang:
runs-on: macOS-latest
env:
CC: clang
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: brew install automake
- name: Bootstrap
run: ./autogen.sh
- name: Configure
run: ./configure --enable-werror
- name: Build
run: make -k
- name: Distcheck
run: make distcheck DISTCHECK_CONFIGURE_FLAGS="--enable-werror"
whitespace_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: check-whitespaces
run: git diff-tree --check $(git hash-object -t tree /dev/null) HEAD

53
.gitignore vendored Normal file
View File

@ -0,0 +1,53 @@
# the binaries:
htop
pcp-htop
# all object files
*.o
# skip all backups
*.bak
*~
.*.sw?
# skip coverage files
*.gcda
*/*.gcda
*.gcno
*/*.gcno
*.h.gch
*/.dirstamp
# automake/autoconf related files
.deps/
Makefile
Makefile.in
INSTALL
aclocal.m4
autom4te.cache/
compile
conf*/
config.guess
config.h
config.h.in
config.log
config.status
config.cache
config.sub
configure
depcomp
htop.1
pcp-htop.5
install-sh
libtool
ltmain.sh
m4/
missing
stamp-h1
# files related to valgrind/callgrind
callgrind.out.*
# IDE workspace configurations
/.idea/
/.vscode/

15
.travis.yml Normal file
View File

@ -0,0 +1,15 @@
language: c
compiler:
- clang
- gcc
os:
- freebsd
script:
- ./autogen.sh
# clang might warn about C11 generic selections in isnan()
- CFLAGS=-Wno-c11-extensions ./configure --enable-werror
- make -k
- CFLAGS=-Wno-c11-extensions make distcheck DISTCHECK_CONFIGURE_FLAGS=--enable-werror

12
AUTHORS
View File

@ -1 +1,11 @@
Hisham H. Muhammad
Originally authored by:
Hisham H. Muhammad
Currently maintained by the htop dev team:
Benny Baumann
Christian Göttsche
Daniel Lange
Nathan Scott
For the full list of contributors see:
git log --format="%aN" | sort -u

714
Action.c Normal file
View File

@ -0,0 +1,714 @@
/*
htop - Action.c
(C) 2015 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "Action.h"
#include <pwd.h>
#include <stdbool.h>
#include <stdlib.h>
#include "CRT.h"
#include "CategoriesPanel.h"
#include "CommandScreen.h"
#include "DynamicColumn.h"
#include "EnvScreen.h"
#include "FunctionBar.h"
#include "Hashtable.h"
#include "IncSet.h"
#include "InfoScreen.h"
#include "ListItem.h"
#include "Macros.h"
#include "MainPanel.h"
#include "OpenFilesScreen.h"
#include "Process.h"
#include "ProcessLocksScreen.h"
#include "ProvideCurses.h"
#include "ScreenManager.h"
#include "SignalsPanel.h"
#include "TraceScreen.h"
#include "Vector.h"
#include "XUtils.h"
#if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
#include "Affinity.h"
#include "AffinityPanel.h"
#endif
Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess) {
MainPanel* mainPanel = st->mainPanel;
Header* header = st->header;
int y = ((Panel*)mainPanel)->y;
ScreenManager* scr = ScreenManager_new(header, st->settings, st, false);
scr->allowFocusChange = false;
ScreenManager_add(scr, list, x);
ScreenManager_add(scr, (Panel*)mainPanel, -1);
Panel* panelFocus;
int ch;
bool unfollow = false;
int pid = followProcess ? MainPanel_selectedPid(mainPanel) : -1;
if (followProcess && header->pl->following == -1) {
header->pl->following = pid;
unfollow = true;
}
ScreenManager_run(scr, &panelFocus, &ch);
if (unfollow) {
header->pl->following = -1;
}
ScreenManager_delete(scr);
Panel_move((Panel*)mainPanel, 0, y);
Panel_resize((Panel*)mainPanel, COLS, LINES - y - 1);
if (panelFocus == list && ch == 13) {
if (followProcess) {
const Process* selected = (const Process*)Panel_getSelected((Panel*)mainPanel);
if (selected && selected->pid == pid)
return Panel_getSelected(list);
beep();
} else {
return Panel_getSelected(list);
}
}
return NULL;
}
// ----------------------------------------
static void Action_runSetup(State* st) {
ScreenManager* scr = ScreenManager_new(st->header, st->settings, st, true);
CategoriesPanel_new(scr, st->settings, st->header, st->pl);
ScreenManager_run(scr, NULL, NULL);
ScreenManager_delete(scr);
if (st->settings->changed) {
Header_writeBackToSettings(st->header);
}
}
static bool changePriority(MainPanel* panel, int delta) {
bool anyTagged;
bool ok = MainPanel_foreachProcess(panel, Process_changePriorityBy, (Arg) { .i = delta }, &anyTagged);
if (!ok)
beep();
return anyTagged;
}
static void addUserToVector(ht_key_t key, void* userCast, void* panelCast) {
const char* user = userCast;
Panel* panel = panelCast;
Panel_add(panel, (Object*) ListItem_new(user, key));
}
bool Action_setUserOnly(const char* userName, uid_t* userId) {
const struct passwd* user = getpwnam(userName);
if (user) {
*userId = user->pw_uid;
return true;
}
*userId = (uid_t)-1;
return false;
}
static void tagAllChildren(Panel* panel, Process* parent) {
parent->tag = true;
pid_t ppid = parent->pid;
for (int i = 0; i < Panel_size(panel); i++) {
Process* p = (Process*) Panel_get(panel, i);
if (!p->tag && Process_isChildOf(p, ppid)) {
tagAllChildren(panel, p);
}
}
}
static bool expandCollapse(Panel* panel) {
Process* p = (Process*) Panel_getSelected(panel);
if (!p)
return false;
p->showChildren = !p->showChildren;
return true;
}
static bool collapseIntoParent(Panel* panel) {
const Process* p = (Process*) Panel_getSelected(panel);
if (!p)
return false;
pid_t ppid = Process_getParentPid(p);
for (int i = 0; i < Panel_size(panel); i++) {
Process* q = (Process*) Panel_get(panel, i);
if (q->pid == ppid) {
q->showChildren = false;
Panel_setSelected(panel, i);
return true;
}
}
return false;
}
Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) {
Settings_setSortKey(settings, sortKey);
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING;
}
// ----------------------------------------
static Htop_Reaction actionSetSortColumn(State* st) {
Htop_Reaction reaction = HTOP_OK;
Panel* sortPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Sort ", "Cancel "));
Panel_setHeader(sortPanel, "Sort by");
const ProcessField* fields = st->settings->fields;
Hashtable* dynamicColumns = st->settings->dynamicColumns;
for (int i = 0; fields[i]; i++) {
char* name = NULL;
if (fields[i] >= LAST_PROCESSFIELD) {
DynamicColumn* column = Hashtable_get(dynamicColumns, fields[i]);
if (!column)
continue;
name = xStrdup(column->caption ? column->caption : column->name);
} else {
name = String_trim(Process_fields[fields[i]].name);
}
Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i]));
if (fields[i] == Settings_getActiveSortKey(st->settings))
Panel_setSelected(sortPanel, i);
free(name);
}
const ListItem* field = (const ListItem*) Action_pickFromVector(st, sortPanel, 14, false);
if (field) {
reaction |= Action_setSortKey(st->settings, field->key);
}
Object_delete(sortPanel);
if (st->pauseProcessUpdate)
ProcessList_sort(st->pl);
return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
static Htop_Reaction actionSortByPID(State* st) {
return Action_setSortKey(st->settings, PID);
}
static Htop_Reaction actionSortByMemory(State* st) {
return Action_setSortKey(st->settings, PERCENT_MEM);
}
static Htop_Reaction actionSortByCPU(State* st) {
return Action_setSortKey(st->settings, PERCENT_CPU);
}
static Htop_Reaction actionSortByTime(State* st) {
return Action_setSortKey(st->settings, TIME);
}
static Htop_Reaction actionToggleKernelThreads(State* st) {
st->settings->hideKernelThreads = !st->settings->hideKernelThreads;
return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionToggleUserlandThreads(State* st) {
st->settings->hideUserlandThreads = !st->settings->hideUserlandThreads;
return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionToggleProgramPath(State* st) {
st->settings->showProgramPath = !st->settings->showProgramPath;
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
}
static Htop_Reaction actionToggleMergedCommand(State* st) {
st->settings->showMergedCommand = !st->settings->showMergedCommand;
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
}
static Htop_Reaction actionToggleTreeView(State* st) {
st->settings->treeView = !st->settings->treeView;
if (!st->settings->allBranchesCollapsed)
ProcessList_expandTree(st->pl);
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
static Htop_Reaction actionExpandOrCollapseAllBranches(State* st) {
st->settings->allBranchesCollapsed = !st->settings->allBranchesCollapsed;
if (st->settings->allBranchesCollapsed)
ProcessList_collapseAllBranches(st->pl);
else
ProcessList_expandTree(st->pl);
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
}
static Htop_Reaction actionIncFilter(State* st) {
IncSet* inc = (st->mainPanel)->inc;
IncSet_activate(inc, INC_FILTER, (Panel*)st->mainPanel);
st->pl->incFilter = IncSet_filter(inc);
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionIncSearch(State* st) {
IncSet_reset(st->mainPanel->inc, INC_SEARCH);
IncSet_activate(st->mainPanel->inc, INC_SEARCH, (Panel*)st->mainPanel);
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionHigherPriority(State* st) {
if (Settings_isReadonly())
return HTOP_OK;
bool changed = changePriority(st->mainPanel, -1);
return changed ? HTOP_REFRESH : HTOP_OK;
}
static Htop_Reaction actionLowerPriority(State* st) {
if (Settings_isReadonly())
return HTOP_OK;
bool changed = changePriority(st->mainPanel, 1);
return changed ? HTOP_REFRESH : HTOP_OK;
}
static Htop_Reaction actionInvertSortOrder(State* st) {
Settings_invertSortOrder(st->settings);
if (st->pauseProcessUpdate)
ProcessList_sort(st->pl);
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionExpandOrCollapse(State* st) {
bool changed = expandCollapse((Panel*)st->mainPanel);
return changed ? HTOP_RECALCULATE : HTOP_OK;
}
static Htop_Reaction actionCollapseIntoParent(State* st) {
if (!st->settings->treeView) {
return HTOP_OK;
}
bool changed = collapseIntoParent((Panel*)st->mainPanel);
return changed ? HTOP_RECALCULATE : HTOP_OK;
}
static Htop_Reaction actionExpandCollapseOrSortColumn(State* st) {
return st->settings->treeView ? actionExpandOrCollapse(st) : actionSetSortColumn(st);
}
static Htop_Reaction actionQuit(ATTR_UNUSED State* st) {
return HTOP_QUIT;
}
static Htop_Reaction actionSetAffinity(State* st) {
if (Settings_isReadonly())
return HTOP_OK;
if (st->pl->activeCPUs == 1)
return HTOP_OK;
#if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
const Process* p = (const Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
Affinity* affinity1 = Affinity_get(p, st->pl);
if (!affinity1)
return HTOP_OK;
int width;
Panel* affinityPanel = AffinityPanel_new(st->pl, affinity1, &width);
Affinity_delete(affinity1);
const void* set = Action_pickFromVector(st, affinityPanel, width, true);
if (set) {
Affinity* affinity2 = AffinityPanel_getAffinity(affinityPanel, st->pl);
bool ok = MainPanel_foreachProcess(st->mainPanel, Affinity_set, (Arg) { .v = affinity2 }, NULL);
if (!ok)
beep();
Affinity_delete(affinity2);
}
Object_delete(affinityPanel);
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
#else
return HTOP_OK;
#endif
}
static Htop_Reaction actionKill(State* st) {
if (Settings_isReadonly())
return HTOP_OK;
Panel* signalsPanel = SignalsPanel_new();
const ListItem* sgn = (ListItem*) Action_pickFromVector(st, signalsPanel, 14, true);
if (sgn && sgn->key != 0) {
Panel_setHeader((Panel*)st->mainPanel, "Sending...");
Panel_draw((Panel*)st->mainPanel, false, true, true, State_hideFunctionBar(st));
refresh();
MainPanel_foreachProcess(st->mainPanel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL);
napms(500);
}
Panel_delete((Object*)signalsPanel);
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
static Htop_Reaction actionFilterByUser(State* st) {
Panel* usersPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Show ", "Cancel "));
Panel_setHeader(usersPanel, "Show processes of:");
UsersTable_foreach(st->ut, addUserToVector, usersPanel);
Vector_insertionSort(usersPanel->items);
ListItem* allUsers = ListItem_new("All users", -1);
Panel_insert(usersPanel, 0, (Object*) allUsers);
const ListItem* picked = (ListItem*) Action_pickFromVector(st, usersPanel, 19, false);
if (picked) {
if (picked == allUsers) {
st->pl->userId = (uid_t)-1;
} else {
Action_setUserOnly(ListItem_getRef(picked), &(st->pl->userId));
}
}
Panel_delete((Object*)usersPanel);
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
Htop_Reaction Action_follow(State* st) {
st->pl->following = MainPanel_selectedPid(st->mainPanel);
Panel_setSelectionColor((Panel*)st->mainPanel, PANEL_SELECTION_FOLLOW);
return HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionSetup(State* st) {
Action_runSetup(st);
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR | HTOP_RESIZE;
}
static Htop_Reaction actionLsof(State* st) {
if (Settings_isReadonly())
return HTOP_OK;
const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
OpenFilesScreen* ofs = OpenFilesScreen_new(p);
InfoScreen_run((InfoScreen*)ofs);
OpenFilesScreen_delete((Object*)ofs);
clear();
CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}
static Htop_Reaction actionShowLocks(State* st) {
const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
ProcessLocksScreen* pls = ProcessLocksScreen_new(p);
InfoScreen_run((InfoScreen*)pls);
ProcessLocksScreen_delete((Object*)pls);
clear();
CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}
static Htop_Reaction actionStrace(State* st) {
if (Settings_isReadonly())
return HTOP_OK;
const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
TraceScreen* ts = TraceScreen_new(p);
bool ok = TraceScreen_forkTracer(ts);
if (ok) {
InfoScreen_run((InfoScreen*)ts);
}
TraceScreen_delete((Object*)ts);
clear();
CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}
static Htop_Reaction actionTag(State* st) {
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
Process_toggleTag(p);
Panel_onKey((Panel*)st->mainPanel, KEY_DOWN);
return HTOP_OK;
}
static Htop_Reaction actionRedraw(ATTR_UNUSED State* st) {
clear();
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}
static Htop_Reaction actionTogglePauseProcessUpdate(State* st) {
st->pauseProcessUpdate = !st->pauseProcessUpdate;
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}
static const struct {
const char* key;
bool roInactive;
const char* info;
} helpLeft[] = {
{ .key = " Arrows: ", .roInactive = false, .info = "scroll process list" },
{ .key = " Digits: ", .roInactive = false, .info = "incremental PID search" },
{ .key = " F3 /: ", .roInactive = false, .info = "incremental name search" },
{ .key = " F4 \\: ", .roInactive = false, .info = "incremental name filtering" },
{ .key = " F5 t: ", .roInactive = false, .info = "tree view" },
{ .key = " p: ", .roInactive = false, .info = "toggle program path" },
{ .key = " m: ", .roInactive = false, .info = "toggle merged command" },
{ .key = " Z: ", .roInactive = false, .info = "pause/resume process updates" },
{ .key = " u: ", .roInactive = false, .info = "show processes of a single user" },
{ .key = " H: ", .roInactive = false, .info = "hide/show user process threads" },
{ .key = " K: ", .roInactive = false, .info = "hide/show kernel threads" },
{ .key = " F: ", .roInactive = false, .info = "cursor follows process" },
{ .key = " + - *: ", .roInactive = false, .info = "expand/collapse tree/toggle all" },
{ .key = "N P M T: ", .roInactive = false, .info = "sort by PID, CPU%, MEM% or TIME" },
{ .key = " I: ", .roInactive = false, .info = "invert sort order" },
{ .key = " F6 > .: ", .roInactive = false, .info = "select sort column" },
{ .key = NULL, .info = NULL }
};
static const struct {
const char* key;
bool roInactive;
const char* info;
} helpRight[] = {
{ .key = " Space: ", .roInactive = false, .info = "tag process" },
{ .key = " c: ", .roInactive = false, .info = "tag process and its children" },
{ .key = " U: ", .roInactive = false, .info = "untag all processes" },
{ .key = " F9 k: ", .roInactive = true, .info = "kill process/tagged processes" },
{ .key = " F7 ]: ", .roInactive = true, .info = "higher priority (root only)" },
{ .key = " F8 [: ", .roInactive = false, .info = "lower priority (+ nice)" },
#if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
{ .key = " a: ", .roInactive = true, .info = "set CPU affinity" },
#endif
{ .key = " e: ", .roInactive = false, .info = "show process environment" },
{ .key = " i: ", .roInactive = true, .info = "set IO priority" },
{ .key = " l: ", .roInactive = true, .info = "list open files with lsof" },
{ .key = " x: ", .roInactive = false, .info = "list file locks of process" },
{ .key = " s: ", .roInactive = true, .info = "trace syscalls with strace" },
{ .key = " w: ", .roInactive = false, .info = "wrap process command in multiple lines" },
{ .key = " F2 C S: ", .roInactive = false, .info = "setup" },
{ .key = " F1 h ?: ", .roInactive = false, .info = "show this help screen" },
{ .key = " F10 q: ", .roInactive = false, .info = "quit" },
{ .key = NULL, .info = NULL }
};
static inline void addattrstr( int attr, const char* str) {
attrset(attr);
addstr(str);
}
static Htop_Reaction actionHelp(State* st) {
clear();
attrset(CRT_colors[HELP_BOLD]);
for (int i = 0; i < LINES - 1; i++)
mvhline(i, 0, ' ', COLS);
int line = 0;
mvaddstr(line++, 0, "htop " VERSION " - " COPYRIGHT);
mvaddstr(line++, 0, "Released under the GNU GPLv2. See 'man' page for more info.");
attrset(CRT_colors[DEFAULT_COLOR]);
line++;
mvaddstr(line++, 0, "CPU usage bar: ");
addattrstr(CRT_colors[BAR_BORDER], "[");
if (st->settings->detailedCPUTime) {
addattrstr(CRT_colors[CPU_NICE_TEXT], "low"); addstr("/");
addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/");
addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/");
addattrstr(CRT_colors[CPU_IRQ], "irq"); addstr("/");
addattrstr(CRT_colors[CPU_SOFTIRQ], "soft-irq"); addstr("/");
addattrstr(CRT_colors[CPU_STEAL], "steal"); addstr("/");
addattrstr(CRT_colors[CPU_GUEST], "guest"); addstr("/");
addattrstr(CRT_colors[CPU_IOWAIT], "io-wait");
addattrstr(CRT_colors[BAR_SHADOW], " used%");
} else {
addattrstr(CRT_colors[CPU_NICE_TEXT], "low-priority"); addstr("/");
addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/");
addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/");
addattrstr(CRT_colors[CPU_GUEST], "virtualized");
addattrstr(CRT_colors[BAR_SHADOW], " used%");
}
addattrstr(CRT_colors[BAR_BORDER], "]");
attrset(CRT_colors[DEFAULT_COLOR]);
mvaddstr(line++, 0, "Memory bar: ");
addattrstr(CRT_colors[BAR_BORDER], "[");
addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/");
addattrstr(CRT_colors[MEMORY_BUFFERS_TEXT], "buffers"); addstr("/");
addattrstr(CRT_colors[MEMORY_SHARED], "shared"); addstr("/");
addattrstr(CRT_colors[MEMORY_CACHE], "cache");
addattrstr(CRT_colors[BAR_SHADOW], " used/total");
addattrstr(CRT_colors[BAR_BORDER], "]");
attrset(CRT_colors[DEFAULT_COLOR]);
mvaddstr(line++, 0, "Swap bar: ");
addattrstr(CRT_colors[BAR_BORDER], "[");
addattrstr(CRT_colors[SWAP], "used");
#ifdef HTOP_LINUX
addattrstr(CRT_colors[BAR_SHADOW], "/");
addattrstr(CRT_colors[SWAP_CACHE], "cache");
addattrstr(CRT_colors[BAR_SHADOW], " used/total");
#else
addattrstr(CRT_colors[BAR_SHADOW], " used/total");
#endif
addattrstr(CRT_colors[BAR_BORDER], "]");
attrset(CRT_colors[DEFAULT_COLOR]);
mvaddstr(line++, 0, "Type and layout of header meters are configurable in the setup screen.");
if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
mvaddstr(line, 0, "In monochrome, meters display as different chars, in order: |#*@$%&.");
}
line++;
mvaddstr(line++, 0, "Process state: R: running; S: sleeping; T: traced/stopped; Z: zombie; D: disk sleep");
line++;
const bool readonly = Settings_isReadonly();
int item;
for (item = 0; helpLeft[item].key; item++) {
attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[DEFAULT_COLOR]);
mvaddstr(line + item, 10, helpLeft[item].info);
attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[HELP_BOLD]);
mvaddstr(line + item, 1, helpLeft[item].key);
if (String_eq(helpLeft[item].key, " H: ")) {
attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[PROCESS_THREAD]);
mvaddstr(line + item, 33, "threads");
} else if (String_eq(helpLeft[item].key, " K: ")) {
attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[PROCESS_THREAD]);
mvaddstr(line + item, 27, "threads");
}
}
int leftHelpItems = item;
for (item = 0; helpRight[item].key; item++) {
attrset((helpRight[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[HELP_BOLD]);
mvaddstr(line + item, 41, helpRight[item].key);
attrset((helpRight[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[DEFAULT_COLOR]);
mvaddstr(line + item, 50, helpRight[item].info);
}
line += MAXIMUM(leftHelpItems, item);
line++;
attrset(CRT_colors[HELP_BOLD]);
mvaddstr(line++, 0, "Press any key to return.");
attrset(CRT_colors[DEFAULT_COLOR]);
refresh();
CRT_readKey();
clear();
return HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_KEEP_FOLLOWING;
}
static Htop_Reaction actionUntagAll(State* st) {
for (int i = 0; i < Panel_size((Panel*)st->mainPanel); i++) {
Process* p = (Process*) Panel_get((Panel*)st->mainPanel, i);
p->tag = false;
}
return HTOP_REFRESH;
}
static Htop_Reaction actionTagAllChildren(State* st) {
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
tagAllChildren((Panel*)st->mainPanel, p);
return HTOP_OK;
}
static Htop_Reaction actionShowEnvScreen(State* st) {
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
EnvScreen* es = EnvScreen_new(p);
InfoScreen_run((InfoScreen*)es);
EnvScreen_delete((Object*)es);
clear();
CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}
static Htop_Reaction actionShowCommandScreen(State* st) {
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
CommandScreen* cmdScr = CommandScreen_new(p);
InfoScreen_run((InfoScreen*)cmdScr);
CommandScreen_delete((Object*)cmdScr);
clear();
CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}
void Action_setBindings(Htop_Action* keys) {
keys[' '] = actionTag;
keys['*'] = actionExpandOrCollapseAllBranches;
keys['+'] = actionExpandOrCollapse;
keys[','] = actionSetSortColumn;
keys['-'] = actionExpandOrCollapse;
keys['.'] = actionSetSortColumn;
keys['/'] = actionIncSearch;
keys['<'] = actionSetSortColumn;
keys['='] = actionExpandOrCollapse;
keys['>'] = actionSetSortColumn;
keys['?'] = actionHelp;
keys['C'] = actionSetup;
keys['F'] = Action_follow;
keys['H'] = actionToggleUserlandThreads;
keys['I'] = actionInvertSortOrder;
keys['K'] = actionToggleKernelThreads;
keys['M'] = actionSortByMemory;
keys['N'] = actionSortByPID;
keys['P'] = actionSortByCPU;
keys['S'] = actionSetup;
keys['T'] = actionSortByTime;
keys['U'] = actionUntagAll;
keys['Z'] = actionTogglePauseProcessUpdate;
keys['['] = actionLowerPriority;
keys['\014'] = actionRedraw; // Ctrl+L
keys['\177'] = actionCollapseIntoParent;
keys['\\'] = actionIncFilter;
keys[']'] = actionHigherPriority;
keys['a'] = actionSetAffinity;
keys['c'] = actionTagAllChildren;
keys['e'] = actionShowEnvScreen;
keys['h'] = actionHelp;
keys['k'] = actionKill;
keys['l'] = actionLsof;
keys['m'] = actionToggleMergedCommand;
keys['p'] = actionToggleProgramPath;
keys['q'] = actionQuit;
keys['s'] = actionStrace;
keys['t'] = actionToggleTreeView;
keys['u'] = actionFilterByUser;
keys['w'] = actionShowCommandScreen;
keys['x'] = actionShowLocks;
keys[KEY_F(1)] = actionHelp;
keys[KEY_F(2)] = actionSetup;
keys[KEY_F(3)] = actionIncSearch;
keys[KEY_F(4)] = actionIncFilter;
keys[KEY_F(5)] = actionToggleTreeView;
keys[KEY_F(6)] = actionSetSortColumn;
keys[KEY_F(7)] = actionHigherPriority;
keys[KEY_F(8)] = actionLowerPriority;
keys[KEY_F(9)] = actionKill;
keys[KEY_F(10)] = actionQuit;
keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
keys[KEY_RECLICK] = actionExpandOrCollapse;
}

64
Action.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef HEADER_Action
#define HEADER_Action
/*
htop - Action.h
(C) 2015 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include <stdbool.h>
#include <sys/types.h>
#include "Header.h"
#include "Object.h"
#include "Panel.h"
#include "Process.h"
#include "ProcessList.h"
#include "Settings.h"
#include "UsersTable.h"
typedef enum {
HTOP_OK = 0x00,
HTOP_REFRESH = 0x01,
HTOP_RECALCULATE = 0x02 | HTOP_REFRESH,
HTOP_SAVE_SETTINGS = 0x04,
HTOP_KEEP_FOLLOWING = 0x08,
HTOP_QUIT = 0x10,
HTOP_REDRAW_BAR = 0x20,
HTOP_UPDATE_PANELHDR = 0x40 | HTOP_REFRESH,
HTOP_RESIZE = 0x80 | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR,
} Htop_Reaction;
struct MainPanel_; // IWYU pragma: keep
typedef struct State_ {
Settings* settings;
UsersTable* ut;
ProcessList* pl;
struct MainPanel_* mainPanel;
Header* header;
bool pauseProcessUpdate;
bool hideProcessSelection;
} State;
static inline bool State_hideFunctionBar(const State* st) {
return st->settings->hideFunctionBar == 2 || (st->settings->hideFunctionBar == 1 && st->hideProcessSelection);
}
typedef Htop_Reaction (*Htop_Action)(State* st);
Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess);
bool Action_setUserOnly(const char* userName, uid_t* userId);
Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey);
Htop_Reaction Action_follow(State* st);
void Action_setBindings(Htop_Action* keys);
#endif

115
Affinity.c Normal file
View File

@ -0,0 +1,115 @@
/*
htop - Affinity.c
(C) 2004-2011 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "Affinity.h"
#include <stdlib.h>
#include "XUtils.h"
#if defined(HAVE_LIBHWLOC)
#include <hwloc.h>
#include <hwloc/bitmap.h>
#ifdef __linux__
#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_THREAD
#else
#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_PROCESS
#endif
#elif defined(HAVE_AFFINITY)
#include <sched.h>
#endif
Affinity* Affinity_new(ProcessList* pl) {
Affinity* this = xCalloc(1, sizeof(Affinity));
this->size = 8;
this->cpus = xCalloc(this->size, sizeof(unsigned int));
this->pl = pl;
return this;
}
void Affinity_delete(Affinity* this) {
free(this->cpus);
free(this);
}
void Affinity_add(Affinity* this, unsigned int id) {
if (this->used == this->size) {
this->size *= 2;
this->cpus = xRealloc(this->cpus, sizeof(unsigned int) * this->size);
}
this->cpus[this->used] = id;
this->used++;
}
#if defined(HAVE_LIBHWLOC)
Affinity* Affinity_get(const Process* proc, ProcessList* pl) {
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
bool ok = (hwloc_get_proc_cpubind(pl->topology, proc->pid, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
Affinity* affinity = NULL;
if (ok) {
affinity = Affinity_new(pl);
if (hwloc_bitmap_last(cpuset) == -1) {
for (unsigned int i = 0; i < pl->existingCPUs; i++) {
Affinity_add(affinity, i);
}
} else {
unsigned int id;
hwloc_bitmap_foreach_begin(id, cpuset);
Affinity_add(affinity, id);
hwloc_bitmap_foreach_end();
}
}
hwloc_bitmap_free(cpuset);
return affinity;
}
bool Affinity_set(Process* proc, Arg arg) {
Affinity* this = arg.v;
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
for (unsigned int i = 0; i < this->used; i++) {
hwloc_bitmap_set(cpuset, this->cpus[i]);
}
bool ok = (hwloc_set_proc_cpubind(this->pl->topology, proc->pid, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
hwloc_bitmap_free(cpuset);
return ok;
}
#elif defined(HAVE_AFFINITY)
Affinity* Affinity_get(const Process* proc, ProcessList* pl) {
cpu_set_t cpuset;
bool ok = (sched_getaffinity(proc->pid, sizeof(cpu_set_t), &cpuset) == 0);
if (!ok)
return NULL;
Affinity* affinity = Affinity_new(pl);
for (unsigned int i = 0; i < pl->existingCPUs; i++) {
if (CPU_ISSET(i, &cpuset)) {
Affinity_add(affinity, i);
}
}
return affinity;
}
bool Affinity_set(Process* proc, Arg arg) {
Affinity* this = arg.v;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
for (unsigned int i = 0; i < this->used; i++) {
CPU_SET(this->cpus[i], &cpuset);
}
bool ok = (sched_setaffinity(proc->pid, sizeof(unsigned long), &cpuset) == 0);
return ok;
}
#endif

49
Affinity.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef HEADER_Affinity
#define HEADER_Affinity
/*
htop - Affinity.h
(C) 2004-2011 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "ProcessList.h"
#if defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY)
#include <stdbool.h>
#include "Object.h"
#include "Process.h"
#endif
#if defined(HAVE_LIBHWLOC) && defined(HAVE_AFFINITY)
#error hwloc and affinity support are mutual exclusive.
#endif
typedef struct Affinity_ {
ProcessList* pl;
unsigned int size;
unsigned int used;
unsigned int* cpus;
} Affinity;
Affinity* Affinity_new(ProcessList* pl);
void Affinity_delete(Affinity* this);
void Affinity_add(Affinity* this, unsigned int id);
#if defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY)
Affinity* Affinity_get(const Process* proc, ProcessList* pl);
bool Affinity_set(Process* proc, Arg arg);
#endif /* HAVE_LIBHWLOC || HAVE_AFFINITY */
#endif

View File

@ -1,48 +1,442 @@
/*
htop - AffinityPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "AffinityPanel.h"
#include "Panel.h"
#include "CheckItem.h"
#include "debug.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
Panel* AffinityPanel_new(int processorCount, unsigned long mask) {
Panel* this = Panel_new(1, 1, 1, 1, CHECKITEM_CLASS, true, ListItem_compare);
this->eventHandler = AffinityPanel_eventHandler;
#include "CRT.h"
#include "FunctionBar.h"
#include "Object.h"
#include "ProvideCurses.h"
#include "RichString.h"
#include "Settings.h"
#include "Vector.h"
#include "XUtils.h"
Panel_setHeader(this, "Use CPUs:");
for (int i = 0; i < processorCount; i++) {
char number[10];
snprintf(number, 9, "%d", i+1);
Panel_add(this, (Object*) CheckItem_new(String_copy(number), NULL, mask & (1 << i)));
#ifdef HAVE_LIBHWLOC
#include <hwloc.h>
#include <hwloc/bitmap.h>
#endif
typedef struct MaskItem_ {
Object super;
char* text;
char* indent; /* used also as an condition whether this is a tree node */
int value; /* tri-state: 0 - off, 1 - some set, 2 - all set */
int sub_tree; /* tri-state: 0 - no sub-tree, 1 - open sub-tree, 2 - closed sub-tree */
Vector* children;
#ifdef HAVE_LIBHWLOC
bool ownCpuset;
hwloc_bitmap_t cpuset;
#else
int cpu;
#endif
} MaskItem;
static void MaskItem_delete(Object* cast) {
MaskItem* this = (MaskItem*) cast;
free(this->text);
free(this->indent);
Vector_delete(this->children);
#ifdef HAVE_LIBHWLOC
if (this->ownCpuset)
hwloc_bitmap_free(this->cpuset);
#endif
free(this);
}
static void MaskItem_display(const Object* cast, RichString* out) {
const MaskItem* this = (const MaskItem*)cast;
assert (this != NULL);
RichString_appendAscii(out, CRT_colors[CHECK_BOX], "[");
if (this->value == 2) {
RichString_appendAscii(out, CRT_colors[CHECK_MARK], "x");
} else if (this->value == 1) {
RichString_appendAscii(out, CRT_colors[CHECK_MARK], "o");
} else {
RichString_appendAscii(out, CRT_colors[CHECK_MARK], " ");
}
RichString_appendAscii(out, CRT_colors[CHECK_BOX], "]");
RichString_appendAscii(out, CRT_colors[CHECK_TEXT], " ");
if (this->indent) {
RichString_appendWide(out, CRT_colors[PROCESS_TREE], this->indent);
RichString_appendWide(out, CRT_colors[PROCESS_TREE],
this->sub_tree == 2
? CRT_treeStr[TREE_STR_OPEN]
: CRT_treeStr[TREE_STR_SHUT]);
RichString_appendAscii(out, CRT_colors[CHECK_TEXT], " ");
}
RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->text);
}
static const ObjectClass MaskItem_class = {
.display = MaskItem_display,
.delete = MaskItem_delete
};
#ifdef HAVE_LIBHWLOC
static MaskItem* MaskItem_newMask(const char* text, const char* indent, hwloc_bitmap_t cpuset, bool owner) {
MaskItem* this = AllocThis(MaskItem);
this->text = xStrdup(text);
this->indent = xStrdup(indent); /* nonnull for tree node */
this->value = 0;
this->ownCpuset = owner;
this->cpuset = cpuset;
this->sub_tree = hwloc_bitmap_weight(cpuset) > 1 ? 1 : 0;
this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE);
return this;
}
unsigned long AffinityPanel_getAffinity(Panel* this) {
int size = Panel_getSize(this);
unsigned long mask = 0;
for (int i = 0; i < size; i++) {
if (CheckItem_get((CheckItem*)Panel_get(this, i)))
mask = mask | (1 << i);
}
return mask;
#endif
static MaskItem* MaskItem_newSingleton(const char* text, int cpu, bool isSet) {
MaskItem* this = AllocThis(MaskItem);
this->text = xStrdup(text);
this->indent = NULL; /* not a tree node */
this->sub_tree = 0;
this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE);
#ifdef HAVE_LIBHWLOC
this->ownCpuset = true;
this->cpuset = hwloc_bitmap_alloc();
hwloc_bitmap_set(this->cpuset, cpu);
#else
this->cpu = cpu;
#endif
this->value = isSet ? 2 : 0;
return this;
}
HandlerResult AffinityPanel_eventHandler(Panel* this, int ch) {
typedef struct AffinityPanel_ {
Panel super;
ProcessList* pl;
bool topoView;
Vector* cpuids;
unsigned width;
#ifdef HAVE_LIBHWLOC
MaskItem* topoRoot;
hwloc_const_cpuset_t allCpuset;
hwloc_bitmap_t workCpuset;
#endif
} AffinityPanel;
static void AffinityPanel_delete(Object* cast) {
AffinityPanel* this = (AffinityPanel*) cast;
Panel* super = (Panel*) this;
Panel_done(super);
Vector_delete(this->cpuids);
#ifdef HAVE_LIBHWLOC
hwloc_bitmap_free(this->workCpuset);
MaskItem_delete((Object*) this->topoRoot);
#endif
free(this);
}
#ifdef HAVE_LIBHWLOC
static void AffinityPanel_updateItem(AffinityPanel* this, MaskItem* item) {
Panel* super = (Panel*) this;
item->value = hwloc_bitmap_isincluded(item->cpuset, this->workCpuset) ? 2 :
hwloc_bitmap_intersects(item->cpuset, this->workCpuset) ? 1 : 0;
Panel_add(super, (Object*) item);
}
static void AffinityPanel_updateTopo(AffinityPanel* this, MaskItem* item) {
AffinityPanel_updateItem(this, item);
if (item->sub_tree == 2)
return;
for (int i = 0; i < Vector_size(item->children); i++)
AffinityPanel_updateTopo(this, (MaskItem*) Vector_get(item->children, i));
}
#endif
static void AffinityPanel_update(AffinityPanel* this, bool keepSelected) {
Panel* super = (Panel*) this;
FunctionBar_setLabel(super->currentBar, KEY_F(3), this->topoView ? "Collapse/Expand" : "");
int oldSelected = Panel_getSelectedIndex(super);
Panel_prune(super);
#ifdef HAVE_LIBHWLOC
if (this->topoView) {
AffinityPanel_updateTopo(this, this->topoRoot);
} else {
for (int i = 0; i < Vector_size(this->cpuids); i++) {
AffinityPanel_updateItem(this, (MaskItem*) Vector_get(this->cpuids, i));
}
}
#else
Panel_splice(super, this->cpuids);
#endif
if (keepSelected)
Panel_setSelected(super, oldSelected);
super->needsRedraw = true;
}
static HandlerResult AffinityPanel_eventHandler(Panel* super, int ch) {
AffinityPanel* this = (AffinityPanel*) super;
HandlerResult result = IGNORED;
CheckItem* selected = (CheckItem*) Panel_getSelected(this);
MaskItem* selected = (MaskItem*) Panel_getSelected(super);
bool keepSelected = true;
switch(ch) {
case KEY_MOUSE:
case KEY_RECLICK:
case ' ':
CheckItem_set(selected, ! (CheckItem_get(selected)) );
#ifdef HAVE_LIBHWLOC
if (selected->value == 2) {
/* Item was selected, so remove this mask from the top cpuset. */
hwloc_bitmap_andnot(this->workCpuset, this->workCpuset, selected->cpuset);
selected->value = 0;
} else {
/* Item was not or only partial selected, so set all bits from this object
in the top cpuset. */
hwloc_bitmap_or(this->workCpuset, this->workCpuset, selected->cpuset);
selected->value = 2;
}
#else
selected->value = selected->value ? 0 : 2; /* toggle between 0 and 2 */
#endif
result = HANDLED;
break;
#ifdef HAVE_LIBHWLOC
case KEY_F(1):
hwloc_bitmap_copy(this->workCpuset, this->allCpuset);
result = HANDLED;
break;
case KEY_F(2):
this->topoView = !this->topoView;
keepSelected = false;
result = HANDLED;
break;
case KEY_F(3):
case '-':
case '+':
if (selected->sub_tree)
selected->sub_tree = 1 + !(selected->sub_tree - 1); /* toggle between 1 and 2 */
result = HANDLED;
break;
#endif
case 0x0a:
case 0x0d:
case KEY_ENTER:
result = BREAK_LOOP;
break;
}
if (HANDLED == result)
AffinityPanel_update(this, keepSelected);
return result;
}
#ifdef HAVE_LIBHWLOC
static MaskItem* AffinityPanel_addObject(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem* parent) {
const char* type_name = hwloc_obj_type_string(obj->type);
const char* index_prefix = "#";
unsigned depth = obj->depth;
unsigned index = obj->logical_index;
size_t off = 0, left = 10 * depth;
char buf[64], indent_buf[left + 1];
if (obj->type == HWLOC_OBJ_PU) {
index = Settings_cpuId(this->pl->settings, obj->os_index);
type_name = "CPU";
index_prefix = "";
}
indent_buf[0] = '\0';
if (depth > 0) {
for (unsigned i = 1; i < depth; i++) {
xSnprintf(&indent_buf[off], left, "%s ", (indent & (1U << i)) ? CRT_treeStr[TREE_STR_VERT] : " ");
size_t len = strlen(&indent_buf[off]);
off += len;
left -= len;
}
xSnprintf(&indent_buf[off], left, "%s",
obj->next_sibling ? CRT_treeStr[TREE_STR_RTEE] : CRT_treeStr[TREE_STR_BEND]);
// Uncomment when further appending to indent_buf
//size_t len = strlen(&indent_buf[off]);
//off += len;
//left -= len;
}
xSnprintf(buf, sizeof(buf), "%s %s%u", type_name, index_prefix, index);
MaskItem* item = MaskItem_newMask(buf, indent_buf, obj->complete_cpuset, false);
if (parent)
Vector_add(parent->children, item);
if (item->sub_tree && parent && parent->sub_tree == 1) {
/* if obj is fully included or fully excluded, collapse the item */
hwloc_bitmap_t result = hwloc_bitmap_alloc();
hwloc_bitmap_and(result, obj->complete_cpuset, this->workCpuset);
int weight = hwloc_bitmap_weight(result);
hwloc_bitmap_free(result);
if (weight == 0 || weight == (hwloc_bitmap_weight(this->workCpuset) + hwloc_bitmap_weight(obj->complete_cpuset))) {
item->sub_tree = 2;
}
}
/* "[x] " + "|- " * depth + ("- ")?(if root node) + name */
unsigned width = 4 + 3 * depth + (2 * !depth) + strlen(buf);
if (width > this->width) {
this->width = width;
}
return item;
}
static MaskItem* AffinityPanel_buildTopology(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem* parent) {
MaskItem* item = AffinityPanel_addObject(this, obj, indent, parent);
if (obj->next_sibling) {
indent |= (1U << obj->depth);
} else {
indent &= ~(1U << obj->depth);
}
for (unsigned i = 0; i < obj->arity; i++) {
AffinityPanel_buildTopology(this, obj->children[i], indent, item);
}
return parent == NULL ? item : NULL;
}
#endif
const PanelClass AffinityPanel_class = {
.super = {
.extends = Class(Panel),
.delete = AffinityPanel_delete
},
.eventHandler = AffinityPanel_eventHandler
};
static const char* const AffinityPanelFunctions[] = {
"Set ",
"Cancel ",
#ifdef HAVE_LIBHWLOC
"All",
"Topology",
" ",
#endif
NULL
};
static const char* const AffinityPanelKeys[] = {"Enter", "Esc", "F1", "F2", "F3"};
static const int AffinityPanelEvents[] = {13, 27, KEY_F(1), KEY_F(2), KEY_F(3)};
Panel* AffinityPanel_new(ProcessList* pl, const Affinity* affinity, int* width) {
AffinityPanel* this = AllocThis(AffinityPanel);
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, Class(MaskItem), false, FunctionBar_new(AffinityPanelFunctions, AffinityPanelKeys, AffinityPanelEvents));
this->pl = pl;
/* defaults to 15, this also includes the gap between the panels,
* but this will be added by the caller */
this->width = 14;
this->cpuids = Vector_new(Class(MaskItem), true, DEFAULT_SIZE);
#ifdef HAVE_LIBHWLOC
this->topoView = pl->settings->topologyAffinity;
#else
this->topoView = false;
#endif
#ifdef HAVE_LIBHWLOC
this->allCpuset = hwloc_topology_get_complete_cpuset(pl->topology);
this->workCpuset = hwloc_bitmap_alloc();
#endif
Panel_setHeader(super, "Use CPUs:");
unsigned int curCpu = 0;
for (unsigned int i = 0; i < pl->existingCPUs; i++) {
if (!ProcessList_isCPUonline(this->pl, i))
continue;
char number[16];
xSnprintf(number, 9, "CPU %d", Settings_cpuId(pl->settings, i));
unsigned cpu_width = 4 + strlen(number);
if (cpu_width > this->width) {
this->width = cpu_width;
}
bool isSet = false;
if (curCpu < affinity->used && affinity->cpus[curCpu] == i) {
#ifdef HAVE_LIBHWLOC
hwloc_bitmap_set(this->workCpuset, i);
#endif
isSet = true;
curCpu++;
}
MaskItem* cpuItem = MaskItem_newSingleton(number, i, isSet);
Vector_add(this->cpuids, (Object*) cpuItem);
}
#ifdef HAVE_LIBHWLOC
this->topoRoot = AffinityPanel_buildTopology(this, hwloc_get_root_obj(pl->topology), 0, NULL);
#endif
if (width) {
*width = this->width;
}
AffinityPanel_update(this, false);
return super;
}
Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl) {
const AffinityPanel* this = (AffinityPanel*) super;
Affinity* affinity = Affinity_new(pl);
#ifdef HAVE_LIBHWLOC
unsigned int i;
hwloc_bitmap_foreach_begin(i, this->workCpuset)
Affinity_add(affinity, i);
hwloc_bitmap_foreach_end();
#else
for (int i = 0; i < Vector_size(this->cpuids); i++) {
const MaskItem* item = (const MaskItem*)Vector_get(this->cpuids, i);
if (item->value) {
Affinity_add(affinity, item->cpu);
}
}
#endif
return affinity;
}

View File

@ -1,19 +1,21 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AffinityPanel
#define HEADER_AffinityPanel
/*
htop - AffinityPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Affinity.h"
#include "Panel.h"
#include "CheckItem.h"
#include "ProcessList.h"
#include "debug.h"
#include <assert.h>
Panel* AffinityPanel_new(int processorCount, unsigned long mask);
extern const PanelClass AffinityPanel_class;
unsigned long AffinityPanel_getAffinity(Panel* this);
Panel* AffinityPanel_new(ProcessList* pl, const Affinity* affinity, int* width);
HandlerResult AffinityPanel_eventHandler(Panel* this, int ch);
Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl);
#endif

View File

@ -1,57 +1,48 @@
/*
htop - AvailableColumnsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "AvailableColumnsPanel.h"
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "ColumnsPanel.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
/*{
#include "ColumnsPanel.h"
#include "DynamicColumn.h"
#include "FunctionBar.h"
#include "Hashtable.h"
#include "ListItem.h"
#include "Object.h"
#include "Process.h"
#include "ProvideCurses.h"
#include "XUtils.h"
typedef struct AvailableColumnsPanel_ {
Panel super;
Panel* columns;
Settings* settings;
ScreenManager* scr;
} AvailableColumnsPanel;
static const char* const AvailableColumnsFunctions[] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done ", NULL};
}*/
AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr) {
AvailableColumnsPanel* this = (AvailableColumnsPanel*) malloc(sizeof(AvailableColumnsPanel));
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = AvailableColumnsPanel_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = AvailableColumnsPanel_eventHandler;
Panel_setHeader(super, "Available Columns");
for (int i = 1; i < LAST_PROCESSFIELD; i++) {
if (i != COMM)
Panel_add(super, (Object*) ListItem_new(Process_fieldNames[i], 0));
}
this->columns = columns;
return this;
}
void AvailableColumnsPanel_delete(Object* object) {
static void AvailableColumnsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
AvailableColumnsPanel* this = (AvailableColumnsPanel*) object;
Panel_done(super);
free(this);
}
HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
static void AvailableColumnsPanel_insert(AvailableColumnsPanel* this, int at, int key) {
const char* name;
if (key >= LAST_PROCESSFIELD)
name = DynamicColumn_init(key);
else
name = Process_fields[key].name;
Panel_insert(this->columns, at, (Object*) ListItem_new(name, key));
}
static HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
AvailableColumnsPanel* this = (AvailableColumnsPanel*) super;
char* text = ((ListItem*) Panel_getSelected(super))->value;
HandlerResult result = IGNORED;
switch(ch) {
@ -59,14 +50,73 @@ HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
case KEY_ENTER:
case KEY_F(5):
{
int at = Panel_getSelectedIndex(this->columns) + 1;
if (at == Panel_getSize(this->columns))
at--;
Panel_insert(this->columns, at, (Object*) ListItem_new(text, 0));
const ListItem* selected = (ListItem*) Panel_getSelected(super);
if (!selected)
break;
int at = Panel_getSelectedIndex(this->columns);
AvailableColumnsPanel_insert(this, at, selected->key);
Panel_setSelected(this->columns, at + 1);
ColumnsPanel_update(this->columns);
result = HANDLED;
break;
}
default:
{
if (0 < ch && ch < 255 && isgraph((unsigned char)ch))
result = Panel_selectByTyping(super, ch);
break;
}
}
return result;
}
const PanelClass AvailableColumnsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = AvailableColumnsPanel_delete
},
.eventHandler = AvailableColumnsPanel_eventHandler
};
static void AvailableColumnsPanel_addDynamicColumn(ht_key_t key, void* value, void* data) {
const DynamicColumn* column = (const DynamicColumn*) value;
Panel* super = (Panel*) data;
const char* title = column->caption ? column->caption : column->heading;
if (!title)
title = column->name; // fallback to the only mandatory field
char description[256];
xSnprintf(description, sizeof(description), "%s - %s", title, column->description);
Panel_add(super, (Object*) ListItem_new(description, key));
}
// Handle DynamicColumns entries in the AvailableColumnsPanel
static void AvailableColumnsPanel_addDynamicColumns(Panel* super, Hashtable* dynamicColumns) {
assert(dynamicColumns);
Hashtable_foreach(dynamicColumns, AvailableColumnsPanel_addDynamicColumn, super);
}
// Handle remaining Platform Meter entries in the AvailableColumnsPanel
static void AvailableColumnsPanel_addPlatformColumn(Panel* super) {
for (int i = 1; i < LAST_PROCESSFIELD; i++) {
if (i != COMM && Process_fields[i].description) {
char description[256];
xSnprintf(description, sizeof(description), "%s - %s", Process_fields[i].name, Process_fields[i].description);
Panel_add(super, (Object*) ListItem_new(description, i));
}
}
}
AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns, Hashtable* dynamicColumns) {
AvailableColumnsPanel* this = AllocThis(AvailableColumnsPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(AvailableColumnsFunctions, NULL, NULL);
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar);
Panel_setHeader(super, "Available Columns");
AvailableColumnsPanel_addPlatformColumn(super);
AvailableColumnsPanel_addDynamicColumns(super, dynamicColumns);
this->columns = columns;
return this;
}

View File

@ -1,32 +1,23 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AvailableColumnsPanel
#define HEADER_AvailableColumnsPanel
/*
htop - AvailableColumnsPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "ColumnsPanel.h"
#include "Hashtable.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
typedef struct AvailableColumnsPanel_ {
Panel super;
Panel* columns;
Settings* settings;
ScreenManager* scr;
} AvailableColumnsPanel;
extern const PanelClass AvailableColumnsPanel_class;
AvailableColumnsPanel* AvailableColumnsPanel_new(Settings* settings, Panel* columns, ScreenManager* scr);
void AvailableColumnsPanel_delete(Object* object);
HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch);
AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns, Hashtable* dynamicColumns);
#endif

View File

@ -1,106 +1,170 @@
/*
htop - AvailableMetersPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "AvailableMetersPanel.h"
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "CPUMeter.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
/*{
#include "CPUMeter.h"
#include "DynamicMeter.h"
#include "FunctionBar.h"
#include "Hashtable.h"
#include "Header.h"
#include "ListItem.h"
#include "Macros.h"
#include "Meter.h"
#include "MetersPanel.h"
#include "Object.h"
#include "Platform.h"
#include "ProvideCurses.h"
#include "XUtils.h"
typedef struct AvailableMetersPanel_ {
Panel super;
Settings* settings;
Panel* leftPanel;
Panel* rightPanel;
ScreenManager* scr;
} AvailableMetersPanel;
}*/
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr) {
AvailableMetersPanel* this = (AvailableMetersPanel*) malloc(sizeof(AvailableMetersPanel));
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = AvailableMetersPanel_delete;
this->settings = settings;
this->leftPanel = leftMeters;
this->rightPanel = rightMeters;
this->scr = scr;
super->eventHandler = AvailableMetersPanel_EventHandler;
Panel_setHeader(super, "Available meters");
for (int i = 1; Meter_types[i]; i++) {
MeterType* type = Meter_types[i];
if (type != &CPUMeter) {
Panel_add(super, (Object*) ListItem_new(type->uiName, i << 16));
}
}
MeterType* type = &CPUMeter;
int processors = settings->pl->processorCount;
if (processors > 1) {
Panel_add(super, (Object*) ListItem_new("CPU average", 0));
for (int i = 1; i <= processors; i++) {
char buffer[50];
sprintf(buffer, "%s %d", type->uiName, i);
Panel_add(super, (Object*) ListItem_new(buffer, i));
}
} else {
Panel_add(super, (Object*) ListItem_new("CPU", 1));
}
return this;
}
void AvailableMetersPanel_delete(Object* object) {
static void AvailableMetersPanel_delete(Object* object) {
Panel* super = (Panel*) object;
AvailableMetersPanel* this = (AvailableMetersPanel*) object;
Panel_done(super);
free(this->meterPanels);
free(this);
}
static inline void AvailableMetersPanel_addHeader(Header* header, Panel* panel, MeterType* type, int param, HeaderSide side) {
Meter* meter = (Meter*) Header_addMeter(header, type, param, side);
Panel_add(panel, (Object*) Meter_toListItem(meter));
static inline void AvailableMetersPanel_addMeter(Header* header, MetersPanel* panel, const MeterClass* type, unsigned int param, size_t column) {
const Meter* meter = Header_addMeterByClass(header, type, param, column);
Panel_add((Panel*)panel, (Object*) Meter_toListItem(meter, false));
Panel_setSelected((Panel*)panel, Panel_size((Panel*)panel) - 1);
MetersPanel_setMoving(panel, true);
}
HandlerResult AvailableMetersPanel_EventHandler(Panel* super, int ch) {
static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) {
AvailableMetersPanel* this = (AvailableMetersPanel*) super;
Header* header = this->settings->header;
Header* header = this->header;
ListItem* selected = (ListItem*) Panel_getSelected(super);
int param = selected->key & 0xff;
const ListItem* selected = (ListItem*) Panel_getSelected(super);
if (!selected)
return IGNORED;
unsigned int param = selected->key & 0xffff;
int type = selected->key >> 16;
HandlerResult result = IGNORED;
bool update = false;
switch(ch) {
case KEY_F(5):
case 'l':
case 'L':
{
AvailableMetersPanel_addHeader(header, this->leftPanel, Meter_types[type], param, LEFT_HEADER);
AvailableMetersPanel_addMeter(header, this->meterPanels[0], Platform_meterTypes[type], param, 0);
result = HANDLED;
update = true;
break;
}
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_F(6):
case 'r':
case 'R':
{
AvailableMetersPanel_addHeader(header, this->rightPanel, Meter_types[type], param, RIGHT_HEADER);
result = HANDLED;
AvailableMetersPanel_addMeter(header, this->meterPanels[this->columns - 1], Platform_meterTypes[type], param, this->columns - 1);
result = (KEY_LEFT << 16) | SYNTH_KEY;
update = true;
break;
}
}
if (result == HANDLED) {
if (update) {
this->settings->changed = true;
Header_calculateHeight(header);
Header_updateData(header);
Header_draw(header);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
ScreenManager_resize(this->scr);
}
return result;
}
const PanelClass AvailableMetersPanel_class = {
.super = {
.extends = Class(Panel),
.delete = AvailableMetersPanel_delete
},
.eventHandler = AvailableMetersPanel_eventHandler
};
// Handle (&CPUMeter_class) entries in the AvailableMetersPanel
static void AvailableMetersPanel_addCPUMeters(Panel* super, const MeterClass* type, const ProcessList* pl) {
if (pl->existingCPUs > 1) {
Panel_add(super, (Object*) ListItem_new("CPU average", 0));
for (unsigned int i = 1; i <= pl->existingCPUs; i++) {
char buffer[50];
xSnprintf(buffer, sizeof(buffer), "%s %d", type->uiName, Settings_cpuId(pl->settings, i - 1));
Panel_add(super, (Object*) ListItem_new(buffer, i));
}
} else {
Panel_add(super, (Object*) ListItem_new(type->uiName, 1));
}
}
typedef struct {
Panel* super;
unsigned int id;
unsigned int offset;
} DynamicIterator;
static void AvailableMetersPanel_addDynamicMeter(ATTR_UNUSED ht_key_t key, void* value, void* data) {
const DynamicMeter* meter = (const DynamicMeter*)value;
DynamicIterator* iter = (DynamicIterator*)data;
unsigned int identifier = (iter->offset << 16) | iter->id;
const char* label = meter->description ? meter->description : meter->caption;
if (!label)
label = meter->name; /* last fallback to name, guaranteed set */
Panel_add(iter->super, (Object*) ListItem_new(label, identifier));
iter->id++;
}
// Handle (&DynamicMeter_class) entries in the AvailableMetersPanel
static void AvailableMetersPanel_addDynamicMeters(Panel* super, const ProcessList* pl, unsigned int offset) {
DynamicIterator iter = { .super = super, .id = 1, .offset = offset };
assert(pl->dynamicMeters != NULL);
Hashtable_foreach(pl->dynamicMeters, AvailableMetersPanel_addDynamicMeter, &iter);
}
// Handle remaining Platform Meter entries in the AvailableMetersPanel
static void AvailableMetersPanel_addPlatformMeter(Panel* super, const MeterClass* type, unsigned int offset) {
const char* label = type->description ? type->description : type->uiName;
Panel_add(super, (Object*) ListItem_new(label, offset << 16));
}
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, size_t columns, MetersPanel** meterPanels, ScreenManager* scr, const ProcessList* pl) {
AvailableMetersPanel* this = AllocThis(AvailableMetersPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_newEnterEsc("Add ", "Done ");
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar);
this->settings = settings;
this->header = header;
this->columns = columns;
this->meterPanels = meterPanels;
this->scr = scr;
Panel_setHeader(super, "Available meters");
// Platform_meterTypes[0] should be always (&CPUMeter_class) which we will
// handle separately in the code below. Likewise, identifiers for Dynamic
// Meters are handled separately - similar to CPUs, this allows generation
// of multiple different Meters (also using 'param' to distinguish them).
for (unsigned int i = 1; Platform_meterTypes[i]; i++) {
const MeterClass* type = Platform_meterTypes[i];
assert(type != &CPUMeter_class);
if (type == &DynamicMeter_class)
AvailableMetersPanel_addDynamicMeters(super, pl, i);
else
AvailableMetersPanel_addPlatformMeter(super, type, i);
}
AvailableMetersPanel_addCPUMeters(super, &CPUMeter_class, pl);
return this;
}

View File

@ -1,33 +1,34 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_AvailableMetersPanel
#define HEADER_AvailableMetersPanel
/*
htop - AvailableMetersPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include <stddef.h>
#include "Settings.h"
#include "Header.h"
#include "ScreenManager.h"
#include "CPUMeter.h"
#include "MetersPanel.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
#include "ProcessList.h"
#include "ScreenManager.h"
#include "Settings.h"
typedef struct AvailableMetersPanel_ {
Panel super;
ScreenManager* scr;
Settings* settings;
Panel* leftPanel;
Panel* rightPanel;
ScreenManager* scr;
Header* header;
size_t columns;
MetersPanel** meterPanels;
} AvailableMetersPanel;
extern const PanelClass AvailableMetersPanel_class;
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr);
void AvailableMetersPanel_delete(Object* object);
HandlerResult AvailableMetersPanel_EventHandler(Panel* super, int ch);
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, size_t columns, MetersPanel **meterPanels, ScreenManager* scr, const ProcessList* pl);
#endif

68
BatteryMeter.c Normal file
View File

@ -0,0 +1,68 @@
/*
htop - BatteryMeter.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
*/
#include "BatteryMeter.h"
#include <math.h>
#include "CRT.h"
#include "Object.h"
#include "Platform.h"
#include "XUtils.h"
static const int BatteryMeter_attributes[] = {
BATTERY
};
static void BatteryMeter_updateValues(Meter* this) {
ACPresence isOnAC;
double percent;
Platform_getBattery(&percent, &isOnAC);
if (isnan(percent)) {
this->values[0] = NAN;
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "N/A");
return;
}
this->values[0] = percent;
const char* text;
switch (isOnAC) {
case AC_PRESENT:
text = this->mode == TEXT_METERMODE ? " (Running on A/C)" : "(A/C)";
break;
case AC_ABSENT:
text = this->mode == TEXT_METERMODE ? " (Running on battery)" : "(bat)";
break;
case AC_ERROR:
default:
text = "";
break;
}
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1f%%%s", percent, text);
}
const MeterClass BatteryMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.updateValues = BatteryMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 1,
.total = 100.0,
.attributes = BatteryMeter_attributes,
.name = "Battery",
.uiName = "Battery",
.caption = "Battery: "
};

23
BatteryMeter.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef HEADER_BatteryMeter
#define HEADER_BatteryMeter
/*
htop - BatteryMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
*/
#include "Meter.h"
typedef enum ACPresence_ {
AC_ABSENT,
AC_PRESENT,
AC_ERROR
} ACPresence;
extern const MeterClass BatteryMeter_class;
#endif

45
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,45 @@
Contributing Guide
==================
Thank you so much for taking the time to contribute in to htop!
Bug Reports
-----------
Bug reports should be posted in the [Github issue
tracker](https://github.com/htop-dev/htop/issues).
Bug reports are extremely important since it's impossible for us to test
htop in every possible system, distribution and scenario. Your feedback
is what keeps the tool stable and always improving! Thank you!
Pull Requests
-------------
Code contributions are most welcome! Just [fork the
repo](https://github.com/htop-dev/htop) and send a [pull
request](https://github.com/htop-dev/htop/pulls). Help is especially
appreciated for support of platforms other than Linux. If proposing new
features, please be mindful that htop is a system tool that needs to keep a
small footprint and perform well on systems under stress -- so unfortunately
we can't accept every new feature proposed, as we need to keep the tool slim
and maintainable. Great ideas backed by a PR are always carefully considered
for inclusion though! Also, PRs containing bug fixes and portability tweaks
are always included, please send those in!
Feature Requests
----------------
Please label Github issues that are feature requests with one of the `feature request`
labels. If you can't do this yourself, don't worry. The friendly folks from the
core team will distribute and fixup Github labels as part of the regular reviews.
Style Guide
-----------
To make working with the code easier a set of guidelines have evolved in
the past that new contributions should try to follow. While they are not set
in stone and always up for changes should the need arise they still provide
a first orientation to go by when contributing to this repository.
The details of the coding style as well as what to take care about with your
contributions can be found in our [style guide](docs/styleguide.md).

30
COPYING
View File

@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,7 +55,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -278,8 +278,8 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -303,16 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -335,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,32 +1,350 @@
/*
htop - CPUMeter.c
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "CPUMeter.h"
#include "Meter.h"
#include "ProcessList.h"
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include <assert.h>
#include "CRT.h"
#include "Object.h"
#include "Platform.h"
#include "ProcessList.h"
#include "RichString.h"
#include "Settings.h"
#include "XUtils.h"
int CPUMeter_attributes[] = {
CPU_NICE, CPU_NORMAL, CPU_KERNEL, CPU_IRQ, CPU_SOFTIRQ, CPU_IOWAIT
static const int CPUMeter_attributes[] = {
CPU_NICE,
CPU_NORMAL,
CPU_SYSTEM,
CPU_IRQ,
CPU_SOFTIRQ,
CPU_STEAL,
CPU_GUEST,
CPU_IOWAIT
};
MeterType CPUMeter = {
.setValues = CPUMeter_setValues,
.display = CPUMeter_display,
.mode = BAR_METERMODE,
.items = 6,
typedef struct CPUMeterData_ {
unsigned int cpus;
Meter** meters;
} CPUMeterData;
static void CPUMeter_init(Meter* this) {
unsigned int cpu = this->param;
if (cpu == 0) {
Meter_setCaption(this, "Avg");
} else if (this->pl->activeCPUs > 1) {
char caption[10];
xSnprintf(caption, sizeof(caption), "%3u", Settings_cpuId(this->pl->settings, cpu - 1));
Meter_setCaption(this, caption);
}
}
// Custom uiName runtime logic to include the param (processor)
static void CPUMeter_getUiName(const Meter* this, char* buffer, size_t length) {
if (this->param > 0)
xSnprintf(buffer, sizeof(length), "%s %u", Meter_uiName(this), this->param);
else
xSnprintf(buffer, sizeof(length), "%s", Meter_uiName(this));
}
static void CPUMeter_updateValues(Meter* this) {
memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT);
unsigned int cpu = this->param;
if (cpu > this->pl->existingCPUs) {
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "absent");
return;
}
double percent = Platform_setCPUValues(this, cpu);
if (isnan(percent)) {
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "offline");
return;
}
char cpuUsageBuffer[8] = { 0 };
char cpuFrequencyBuffer[16] = { 0 };
char cpuTemperatureBuffer[16] = { 0 };
if (this->pl->settings->showCPUUsage) {
xSnprintf(cpuUsageBuffer, sizeof(cpuUsageBuffer), "%.1f%%", percent);
}
if (this->pl->settings->showCPUFrequency) {
double cpuFrequency = this->values[CPU_METER_FREQUENCY];
if (isnan(cpuFrequency)) {
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A");
} else {
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz", (unsigned)cpuFrequency);
}
}
#ifdef BUILD_WITH_CPU_TEMP
if (this->pl->settings->showCPUTemperature) {
double cpuTemperature = this->values[CPU_METER_TEMPERATURE];
if (isnan(cpuTemperature))
xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A");
else if (this->pl->settings->degreeFahrenheit)
xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%3d%sF", (int)(cpuTemperature * 9 / 5 + 32), CRT_degreeSign);
else
xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%d%sC", (int)cpuTemperature, CRT_degreeSign);
}
#endif
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s%s%s%s%s",
cpuUsageBuffer,
(cpuUsageBuffer[0] && (cpuFrequencyBuffer[0] || cpuTemperatureBuffer[0])) ? " " : "",
cpuFrequencyBuffer,
(cpuFrequencyBuffer[0] && cpuTemperatureBuffer[0]) ? " " : "",
cpuTemperatureBuffer);
}
static void CPUMeter_display(const Object* cast, RichString* out) {
char buffer[50];
int len;
const Meter* this = (const Meter*)cast;
if (this->param > this->pl->existingCPUs) {
RichString_appendAscii(out, CRT_colors[METER_SHADOW], " absent");
return;
}
if (this->curItems == 0) {
RichString_appendAscii(out, CRT_colors[METER_SHADOW], " offline");
return;
}
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NORMAL]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], ":");
RichString_appendnAscii(out, CRT_colors[CPU_NORMAL], buffer, len);
if (this->pl->settings->detailedCPUTime) {
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "sy:");
RichString_appendnAscii(out, CRT_colors[CPU_SYSTEM], buffer, len);
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "ni:");
RichString_appendnAscii(out, CRT_colors[CPU_NICE_TEXT], buffer, len);
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IRQ]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "hi:");
RichString_appendnAscii(out, CRT_colors[CPU_IRQ], buffer, len);
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_SOFTIRQ]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "si:");
RichString_appendnAscii(out, CRT_colors[CPU_SOFTIRQ], buffer, len);
if (!isnan(this->values[CPU_METER_STEAL])) {
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_STEAL]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "st:");
RichString_appendnAscii(out, CRT_colors[CPU_STEAL], buffer, len);
}
if (!isnan(this->values[CPU_METER_GUEST])) {
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_GUEST]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "gu:");
RichString_appendnAscii(out, CRT_colors[CPU_GUEST], buffer, len);
}
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IOWAIT]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "wa:");
RichString_appendnAscii(out, CRT_colors[CPU_IOWAIT], buffer, len);
} else {
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "sys:");
RichString_appendnAscii(out, CRT_colors[CPU_SYSTEM], buffer, len);
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "low:");
RichString_appendnAscii(out, CRT_colors[CPU_NICE_TEXT], buffer, len);
if (!isnan(this->values[CPU_METER_IRQ])) {
len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IRQ]);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "vir:");
RichString_appendnAscii(out, CRT_colors[CPU_GUEST], buffer, len);
}
}
#ifdef BUILD_WITH_CPU_TEMP
if (this->pl->settings->showCPUTemperature) {
char cpuTemperatureBuffer[10];
double cpuTemperature = this->values[CPU_METER_TEMPERATURE];
if (isnan(cpuTemperature)) {
len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A");
} else if (this->pl->settings->degreeFahrenheit) {
len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%5.1f%sF", cpuTemperature * 9 / 5 + 32, CRT_degreeSign);
} else {
len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%5.1f%sC", cpuTemperature, CRT_degreeSign);
}
RichString_appendAscii(out, CRT_colors[METER_TEXT], "temp:");
RichString_appendnWide(out, CRT_colors[METER_VALUE], cpuTemperatureBuffer, len);
}
#endif
}
static void AllCPUsMeter_getRange(const Meter* this, int* start, int* count) {
const CPUMeterData* data = this->meterData;
unsigned int cpus = data->cpus;
switch(Meter_name(this)[0]) {
default:
case 'A': // All
*start = 0;
*count = cpus;
break;
case 'L': // First Half
*start = 0;
*count = (cpus+1) / 2;
break;
case 'R': // Second Half
*start = (cpus+1) / 2;
*count = cpus / 2;
break;
}
}
static void AllCPUsMeter_updateValues(Meter* this) {
CPUMeterData* data = this->meterData;
Meter** meters = data->meters;
int start, count;
AllCPUsMeter_getRange(this, &start, &count);
for (int i = 0; i < count; i++)
Meter_updateValues(meters[i]);
}
static void CPUMeterCommonInit(Meter* this, int ncol) {
unsigned int cpus = this->pl->existingCPUs;
CPUMeterData* data = this->meterData;
if (!data) {
data = this->meterData = xMalloc(sizeof(CPUMeterData));
data->cpus = cpus;
data->meters = xCalloc(cpus, sizeof(Meter*));
}
Meter** meters = data->meters;
int start, count;
AllCPUsMeter_getRange(this, &start, &count);
for (int i = 0; i < count; i++) {
if (!meters[i])
meters[i] = Meter_new(this->pl, start + i + 1, (const MeterClass*) Class(CPUMeter));
Meter_init(meters[i]);
}
if (this->mode == 0)
this->mode = BAR_METERMODE;
int h = Meter_modes[this->mode]->h;
this->h = h * ((count + ncol - 1) / ncol);
}
static void CPUMeterCommonUpdateMode(Meter* this, int mode, int ncol) {
CPUMeterData* data = this->meterData;
Meter** meters = data->meters;
this->mode = mode;
int h = Meter_modes[mode]->h;
int start, count;
AllCPUsMeter_getRange(this, &start, &count);
for (int i = 0; i < count; i++) {
Meter_setMode(meters[i], mode);
}
this->h = h * ((count + ncol - 1) / ncol);
}
static void AllCPUsMeter_done(Meter* this) {
CPUMeterData* data = this->meterData;
Meter** meters = data->meters;
int start, count;
AllCPUsMeter_getRange(this, &start, &count);
for (int i = 0; i < count; i++)
Meter_delete((Object*)meters[i]);
free(data->meters);
free(data);
}
static void SingleColCPUsMeter_init(Meter* this) {
CPUMeterCommonInit(this, 1);
}
static void SingleColCPUsMeter_updateMode(Meter* this, int mode) {
CPUMeterCommonUpdateMode(this, mode, 1);
}
static void DualColCPUsMeter_init(Meter* this) {
CPUMeterCommonInit(this, 2);
}
static void DualColCPUsMeter_updateMode(Meter* this, int mode) {
CPUMeterCommonUpdateMode(this, mode, 2);
}
static void QuadColCPUsMeter_init(Meter* this) {
CPUMeterCommonInit(this, 4);
}
static void QuadColCPUsMeter_updateMode(Meter* this, int mode) {
CPUMeterCommonUpdateMode(this, mode, 4);
}
static void OctoColCPUsMeter_init(Meter* this) {
CPUMeterCommonInit(this, 8);
}
static void OctoColCPUsMeter_updateMode(Meter* this, int mode) {
CPUMeterCommonUpdateMode(this, mode, 8);
}
static void CPUMeterCommonDraw(Meter* this, int x, int y, int w, int ncol) {
CPUMeterData* data = this->meterData;
Meter** meters = data->meters;
int start, count;
AllCPUsMeter_getRange(this, &start, &count);
int colwidth = (w - ncol) / ncol + 1;
int diff = (w - (colwidth * ncol));
int nrows = (count + ncol - 1) / ncol;
for (int i = 0; i < count; i++) {
int d = (i / nrows) > diff ? diff : (i / nrows); // dynamic spacer
int xpos = x + ((i / nrows) * colwidth) + d;
int ypos = y + ((i % nrows) * meters[0]->h);
meters[i]->draw(meters[i], xpos, ypos, colwidth);
}
}
static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) {
CPUMeterCommonDraw(this, x, y, w, 2);
}
static void QuadColCPUsMeter_draw(Meter* this, int x, int y, int w) {
CPUMeterCommonDraw(this, x, y, w, 4);
}
static void OctoColCPUsMeter_draw(Meter* this, int x, int y, int w) {
CPUMeterCommonDraw(this, x, y, w, 8);
}
static void SingleColCPUsMeter_draw(Meter* this, int x, int y, int w) {
CPUMeterData* data = this->meterData;
Meter** meters = data->meters;
int start, count;
AllCPUsMeter_getRange(this, &start, &count);
for (int i = 0; i < count; i++) {
meters[i]->draw(meters[i], x, y, w);
y += meters[i]->h;
}
}
const MeterClass CPUMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = CPUMeter_updateValues,
.getUiName = CPUMeter_getUiName,
.defaultMode = BAR_METERMODE,
.maxItems = CPU_METER_ITEMCOUNT,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "CPU",
@ -35,124 +353,242 @@ MeterType CPUMeter = {
.init = CPUMeter_init
};
MeterType AllCPUsMeter = {
.mode = 0,
.items = 1,
const MeterClass AllCPUsMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "AllCPUs",
.uiName = "All CPUs",
.uiName = "CPUs (1/1)",
.description = "CPUs (1/1): all CPUs",
.caption = "CPU",
.draw = AllCPUsMeter_draw,
.init = AllCPUsMeter_init,
.setMode = AllCPUsMeter_setMode,
.draw = SingleColCPUsMeter_draw,
.init = SingleColCPUsMeter_init,
.updateMode = SingleColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
const MeterClass AllCPUs2Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "AllCPUs2",
.uiName = "CPUs (1&2/2)",
.description = "CPUs (1&2/2): all CPUs in 2 shorter columns",
.caption = "CPU",
.draw = DualColCPUsMeter_draw,
.init = DualColCPUsMeter_init,
.updateMode = DualColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
void CPUMeter_init(Meter* this) {
int processor = this->param;
if (this->pl->processorCount > 1) {
char caption[10];
sprintf(caption, "%-3d", processor);
Meter_setCaption(this, caption);
}
if (this->param == 0)
Meter_setCaption(this, "Avg");
}
const MeterClass LeftCPUsMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "LeftCPUs",
.uiName = "CPUs (1/2)",
.description = "CPUs (1/2): first half of list",
.caption = "CPU",
.draw = SingleColCPUsMeter_draw,
.init = SingleColCPUsMeter_init,
.updateMode = SingleColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
void CPUMeter_setValues(Meter* this, char* buffer, int size) {
ProcessList* pl = this->pl;
int processor = this->param;
double total = (double) pl->totalPeriod[processor];
double cpu;
this->values[0] = pl->nicePeriod[processor] / total * 100.0;
this->values[1] = pl->userPeriod[processor] / total * 100.0;
if (pl->detailedCPUTime) {
this->values[2] = pl->systemPeriod[processor] / total * 100.0;
this->values[3] = pl->irqPeriod[processor] / total * 100.0;
this->values[4] = pl->softIrqPeriod[processor] / total * 100.0;
this->values[5] = pl->ioWaitPeriod[processor] / total * 100.0;
this->type->items = 6;
cpu = MIN(100.0, MAX(0.0, (this->values[0]+this->values[1]+this->values[2]+
this->values[3]+this->values[4])));
} else {
this->values[2] = pl->systemAllPeriod[processor] / total * 100.0;
this->type->items = 3;
cpu = MIN(100.0, MAX(0.0, (this->values[0]+this->values[1]+this->values[2])));
}
snprintf(buffer, size, "%5.1f%%", cpu );
}
const MeterClass RightCPUsMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "RightCPUs",
.uiName = "CPUs (2/2)",
.description = "CPUs (2/2): second half of list",
.caption = "CPU",
.draw = SingleColCPUsMeter_draw,
.init = SingleColCPUsMeter_init,
.updateMode = SingleColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
void CPUMeter_display(Object* cast, RichString* out) {
char buffer[50];
Meter* this = (Meter*)cast;
RichString_init(out);
sprintf(buffer, "%5.1f%% ", this->values[1]);
RichString_append(out, CRT_colors[METER_TEXT], ":");
RichString_append(out, CRT_colors[CPU_NORMAL], buffer);
if (this->pl->detailedCPUTime) {
sprintf(buffer, "%5.1f%% ", this->values[2]);
RichString_append(out, CRT_colors[METER_TEXT], "sy:");
RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
sprintf(buffer, "%5.1f%% ", this->values[0]);
RichString_append(out, CRT_colors[METER_TEXT], "ni:");
RichString_append(out, CRT_colors[CPU_NICE], buffer);
sprintf(buffer, "%5.1f%% ", this->values[3]);
RichString_append(out, CRT_colors[METER_TEXT], "hi:");
RichString_append(out, CRT_colors[CPU_IRQ], buffer);
sprintf(buffer, "%5.1f%% ", this->values[4]);
RichString_append(out, CRT_colors[METER_TEXT], "si:");
RichString_append(out, CRT_colors[CPU_SOFTIRQ], buffer);
sprintf(buffer, "%5.1f%% ", this->values[5]);
RichString_append(out, CRT_colors[METER_TEXT], "wa:");
RichString_append(out, CRT_colors[CPU_IOWAIT], buffer);
} else {
sprintf(buffer, "%5.1f%% ", this->values[2]);
RichString_append(out, CRT_colors[METER_TEXT], "sys:");
RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
sprintf(buffer, "%5.1f%% ", this->values[0]);
RichString_append(out, CRT_colors[METER_TEXT], "low:");
RichString_append(out, CRT_colors[CPU_NICE], buffer);
}
}
const MeterClass LeftCPUs2Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "LeftCPUs2",
.uiName = "CPUs (1&2/4)",
.description = "CPUs (1&2/4): first half in 2 shorter columns",
.caption = "CPU",
.draw = DualColCPUsMeter_draw,
.init = DualColCPUsMeter_init,
.updateMode = DualColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
void AllCPUsMeter_init(Meter* this) {
int processors = this->pl->processorCount;
this->drawBuffer = malloc(sizeof(Meter*) * processors);
Meter** meters = (Meter**) this->drawBuffer;
for (int i = 0; i < processors; i++)
meters[i] = Meter_new(this->pl, i+1, &CPUMeter);
this->h = processors;
this->mode = BAR_METERMODE;
}
const MeterClass RightCPUs2Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "RightCPUs2",
.uiName = "CPUs (3&4/4)",
.description = "CPUs (3&4/4): second half in 2 shorter columns",
.caption = "CPU",
.draw = DualColCPUsMeter_draw,
.init = DualColCPUsMeter_init,
.updateMode = DualColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
void AllCPUsMeter_done(Meter* this) {
int processors = this->pl->processorCount;
Meter** meters = (Meter**) this->drawBuffer;
for (int i = 0; i < processors; i++)
Meter_delete((Object*)meters[i]);
}
const MeterClass AllCPUs4Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "AllCPUs4",
.uiName = "CPUs (1&2&3&4/4)",
.description = "CPUs (1&2&3&4/4): all CPUs in 4 shorter columns",
.caption = "CPU",
.draw = QuadColCPUsMeter_draw,
.init = QuadColCPUsMeter_init,
.updateMode = QuadColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
void AllCPUsMeter_setMode(Meter* this, int mode) {
this->mode = mode;
int processors = this->pl->processorCount;
int h = Meter_modes[this->mode]->h;
this->h = h * processors;
}
const MeterClass LeftCPUs4Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "LeftCPUs4",
.uiName = "CPUs (1-4/8)",
.description = "CPUs (1-4/8): first half in 4 shorter columns",
.caption = "CPU",
.draw = QuadColCPUsMeter_draw,
.init = QuadColCPUsMeter_init,
.updateMode = QuadColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
void AllCPUsMeter_draw(Meter* this, int x, int y, int w) {
int processors = this->pl->processorCount;
Meter** meters = (Meter**) this->drawBuffer;
for (int i = 0; i < processors; i++) {
Meter_setMode(meters[i], this->mode);
meters[i]->draw(meters[i], x, y, w);
y += meters[i]->h;
}
}
const MeterClass RightCPUs4Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "RightCPUs4",
.uiName = "CPUs (5-8/8)",
.description = "CPUs (5-8/8): second half in 4 shorter columns",
.caption = "CPU",
.draw = QuadColCPUsMeter_draw,
.init = QuadColCPUsMeter_init,
.updateMode = QuadColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
const MeterClass AllCPUs8Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "AllCPUs8",
.uiName = "CPUs (1-8/8)",
.description = "CPUs (1-8/8): all CPUs in 8 shorter columns",
.caption = "CPU",
.draw = OctoColCPUsMeter_draw,
.init = OctoColCPUsMeter_init,
.updateMode = OctoColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
const MeterClass LeftCPUs8Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "LeftCPUs8",
.uiName = "CPUs (1-8/16)",
.description = "CPUs (1-8/16): first half in 8 shorter columns",
.caption = "CPU",
.draw = OctoColCPUsMeter_draw,
.init = OctoColCPUsMeter_init,
.updateMode = OctoColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};
const MeterClass RightCPUs8Meter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = CPUMeter_display
},
.updateValues = AllCPUsMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.total = 100.0,
.attributes = CPUMeter_attributes,
.name = "RightCPUs8",
.uiName = "CPUs (9-16/16)",
.description = "CPUs (9-16/16): second half in 8 shorter columns",
.caption = "CPU",
.draw = OctoColCPUsMeter_draw,
.init = OctoColCPUsMeter_init,
.updateMode = OctoColCPUsMeter_updateMode,
.done = AllCPUsMeter_done
};

View File

@ -1,51 +1,53 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CPUMeter
#define HEADER_CPUMeter
/*
htop - CPUMeter.h
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
#include "ProcessList.h"
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <math.h>
typedef enum {
CPU_METER_NICE = 0,
CPU_METER_NORMAL = 1,
CPU_METER_KERNEL = 2,
CPU_METER_IRQ = 3,
CPU_METER_SOFTIRQ = 4,
CPU_METER_STEAL = 5,
CPU_METER_GUEST = 6,
CPU_METER_IOWAIT = 7,
CPU_METER_FREQUENCY = 8,
CPU_METER_TEMPERATURE = 9,
CPU_METER_ITEMCOUNT = 10, // number of entries in this enum
} CPUMeterValues;
#include "debug.h"
#include <assert.h>
extern const MeterClass CPUMeter_class;
extern int CPUMeter_attributes[];
extern const MeterClass AllCPUsMeter_class;
extern MeterType CPUMeter;
extern const MeterClass AllCPUs2Meter_class;
extern MeterType AllCPUsMeter;
extern const MeterClass LeftCPUsMeter_class;
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
extern const MeterClass RightCPUsMeter_class;
void CPUMeter_init(Meter* this);
extern const MeterClass LeftCPUs2Meter_class;
void CPUMeter_setValues(Meter* this, char* buffer, int size);
extern const MeterClass RightCPUs2Meter_class;
void CPUMeter_display(Object* cast, RichString* out);
extern const MeterClass AllCPUs4Meter_class;
void AllCPUsMeter_init(Meter* this);
extern const MeterClass LeftCPUs4Meter_class;
void AllCPUsMeter_done(Meter* this);
extern const MeterClass RightCPUs4Meter_class;
void AllCPUsMeter_setMode(Meter* this, int mode);
extern const MeterClass AllCPUs8Meter_class;
void AllCPUsMeter_draw(Meter* this, int x, int y, int w);
extern const MeterClass LeftCPUs8Meter_class;
extern const MeterClass RightCPUs8Meter_class;
#endif

1457
CRT.c

File diff suppressed because it is too large Load Diff

169
CRT.h
View File

@ -1,47 +1,43 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CRT
#define HEADER_CRT
/*
htop - CRT.h
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h"
#include <curses.h>
#include <signal.h>
#include <stdlib.h>
#include <stdbool.h>
#include "String.h"
#include "Macros.h"
#include "ProvideCurses.h"
#include "Settings.h"
#include "config.h"
#include "debug.h"
#define ColorPair(i,j) COLOR_PAIR((7-i)*8+j)
#define COLORSCHEME_DEFAULT 0
#define COLORSCHEME_MONOCHROME 1
#define COLORSCHEME_BLACKONWHITE 2
#define COLORSCHEME_BLACKONWHITE2 3
#define COLORSCHEME_MIDNIGHT 4
#define COLORSCHEME_BLACKNIGHT 5
#define Black COLOR_BLACK
#define Red COLOR_RED
#define Green COLOR_GREEN
#define Yellow COLOR_YELLOW
#define Blue COLOR_BLUE
#define Magenta COLOR_MAGENTA
#define Cyan COLOR_CYAN
#define White COLOR_WHITE
//#link curses
bool CRT_hasColors;
typedef enum TreeStr_ {
TREE_STR_VERT,
TREE_STR_RTEE,
TREE_STR_BEND,
TREE_STR_TEND,
TREE_STR_OPEN,
TREE_STR_SHUT,
TREE_STR_ASC,
TREE_STR_DESC,
LAST_TREE_STR
} TreeStr;
typedef enum ColorScheme_ {
COLORSCHEME_DEFAULT,
COLORSCHEME_MONOCHROME,
COLORSCHEME_BLACKONWHITE,
COLORSCHEME_LIGHTTERMINAL,
COLORSCHEME_MIDNIGHT,
COLORSCHEME_BLACKNIGHT,
COLORSCHEME_BROKENGRAY,
LAST_COLORSCHEME
} ColorScheme;
typedef enum ColorElements_ {
RESET_COLOR,
@ -49,41 +45,59 @@ typedef enum ColorElements_ {
FUNCTION_BAR,
FUNCTION_KEY,
FAILED_SEARCH,
FAILED_READ,
PAUSED,
PANEL_HEADER_FOCUS,
PANEL_HEADER_UNFOCUS,
PANEL_HIGHLIGHT_FOCUS,
PANEL_HIGHLIGHT_UNFOCUS,
PANEL_SELECTION_FOCUS,
PANEL_SELECTION_FOLLOW,
PANEL_SELECTION_UNFOCUS,
LARGE_NUMBER,
METER_SHADOW,
METER_TEXT,
METER_VALUE,
METER_VALUE_ERROR,
METER_VALUE_IOREAD,
METER_VALUE_IOWRITE,
METER_VALUE_NOTICE,
METER_VALUE_OK,
METER_VALUE_WARN,
LED_COLOR,
UPTIME,
TASKS_TOTAL,
BATTERY,
TASKS_RUNNING,
SWAP,
SWAP_CACHE,
PROCESS,
PROCESS_SHADOW,
PROCESS_TAG,
PROCESS_MEGABYTES,
PROCESS_GIGABYTES,
PROCESS_TREE,
PROCESS_R_STATE,
PROCESS_D_STATE,
PROCESS_BASENAME,
PROCESS_HIGH_PRIORITY,
PROCESS_LOW_PRIORITY,
PROCESS_NEW,
PROCESS_TOMB,
PROCESS_THREAD,
PROCESS_THREAD_BASENAME,
PROCESS_COMM,
PROCESS_THREAD_COMM,
BAR_BORDER,
BAR_SHADOW,
GRAPH_1,
GRAPH_2,
GRAPH_3,
GRAPH_4,
GRAPH_5,
GRAPH_6,
GRAPH_7,
GRAPH_8,
GRAPH_9,
MEMORY_USED,
MEMORY_BUFFERS,
MEMORY_BUFFERS_TEXT,
MEMORY_CACHE,
MEMORY_SHARED,
HUGEPAGE_1,
HUGEPAGE_2,
HUGEPAGE_3,
HUGEPAGE_4,
LOAD,
LOAD_AVERAGE_FIFTEEN,
LOAD_AVERAGE_FIVE,
@ -92,42 +106,83 @@ typedef enum ColorElements_ {
CHECK_MARK,
CHECK_TEXT,
CLOCK,
CPU_NICE,
CPU_NORMAL,
CPU_KERNEL,
DATE,
DATETIME,
HELP_BOLD,
HELP_SHADOW,
HOSTNAME,
CPU_NICE,
CPU_NICE_TEXT,
CPU_NORMAL,
CPU_SYSTEM,
CPU_IOWAIT,
CPU_IRQ,
CPU_SOFTIRQ,
CPU_STEAL,
CPU_GUEST,
PRESSURE_STALL_TEN,
PRESSURE_STALL_SIXTY,
PRESSURE_STALL_THREEHUNDRED,
ZFS_MFU,
ZFS_MRU,
ZFS_ANON,
ZFS_HEADER,
ZFS_OTHER,
ZFS_COMPRESSED,
ZFS_RATIO,
ZRAM,
DYNAMIC_GRAY,
DYNAMIC_DARKGRAY,
DYNAMIC_RED,
DYNAMIC_GREEN,
DYNAMIC_BLUE,
DYNAMIC_CYAN,
DYNAMIC_MAGENTA,
DYNAMIC_YELLOW,
DYNAMIC_WHITE,
LAST_COLORELEMENT
} ColorElements;
void CRT_fatalError(const char* note) ATTR_NORETURN;
// TODO: centralize these in Settings.
void CRT_handleSIGSEGV(int signal) ATTR_NORETURN;
extern int CRT_delay;
#define KEY_WHEELUP KEY_F(20)
#define KEY_WHEELDOWN KEY_F(21)
#define KEY_RECLICK KEY_F(22)
#define KEY_ALT(x) (KEY_F(64 - 26) + ((x) - 'A'))
extern int CRT_colorScheme;
extern const char* CRT_degreeSign;
extern int CRT_colors[LAST_COLORELEMENT];
#ifdef HAVE_LIBNCURSESW
char* CRT_termType;
extern bool CRT_utf8;
// TODO: pass an instance of Settings instead.
#endif
void CRT_init(int delay, int colorScheme);
extern const char* const* CRT_treeStr;
void CRT_done();
extern const int* CRT_colors;
int CRT_readKey();
extern int CRT_cursorX;
void CRT_disableDelay();
extern int CRT_scrollHAmount;
void CRT_enableDelay();
extern int CRT_scrollWheelVAmount;
void CRT_handleSIGSEGV(int signal);
extern ColorScheme CRT_colorScheme;
void CRT_handleSIGTERM(int signal);
void CRT_init(const Settings* settings, bool allowUnicode);
void CRT_done(void);
void CRT_resetSignalHandlers(void);
int CRT_readKey(void);
void CRT_disableDelay(void);
void CRT_enableDelay(void);
void CRT_setColors(int colorScheme);

View File

@ -1,128 +1,167 @@
/*
htop - CategoriesPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "CategoriesPanel.h"
#include "AvailableMetersPanel.h"
#include "MetersPanel.h"
#include "DisplayOptionsPanel.h"
#include "ColumnsPanel.h"
#include "ColorsPanel.h"
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include "AvailableColumnsPanel.h"
#include "AvailableMetersPanel.h"
#include "ColorsPanel.h"
#include "ColumnsPanel.h"
#include "DisplayOptionsPanel.h"
#include "FunctionBar.h"
#include "Header.h"
#include "HeaderLayout.h"
#include "HeaderOptionsPanel.h"
#include "ListItem.h"
#include "Macros.h"
#include "MetersPanel.h"
#include "Object.h"
#include "ProvideCurses.h"
#include "Vector.h"
#include "XUtils.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
static const char* const CategoriesFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
/*{
typedef struct CategoriesPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} CategoriesPanel;
}*/
static char* MetersFunctions[10] = {" ", " ", " ", "Type ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done "};
static char* AvailableMetersFunctions[10] = {" ", " ", " ", " ", "Add L ", "Add R ", " ", " ", " ", "Done "};
static char* DisplayOptionsFunctions[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done "};
static char* ColumnsFunctions[10] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done "};
static char* ColorsFunctions[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done "};
static char* AvailableColumnsFunctions[10] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done "};
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr) {
CategoriesPanel* this = (CategoriesPanel*) malloc(sizeof(CategoriesPanel));
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = CategoriesPanel_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = CategoriesPanel_eventHandler;
Panel_setHeader(super, "Setup");
Panel_add(super, (Object*) ListItem_new("Meters", 0));
Panel_add(super, (Object*) ListItem_new("Display options", 0));
Panel_add(super, (Object*) ListItem_new("Colors", 0));
Panel_add(super, (Object*) ListItem_new("Columns", 0));
return this;
}
void CategoriesPanel_delete(Object* object) {
static void CategoriesPanel_delete(Object* object) {
Panel* super = (Panel*) object;
CategoriesPanel* this = (CategoriesPanel*) object;
Panel_done(super);
free(this);
}
HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
static void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
size_t columns = HeaderLayout_getColumns(this->scr->header->headerLayout);
MetersPanel** meterPanels = xMallocArray(columns, sizeof(MetersPanel));
for (size_t i = 0; i < columns; i++) {
char titleBuffer[32];
xSnprintf(titleBuffer, sizeof(titleBuffer), "Column %zu", i + 1);
meterPanels[i] = MetersPanel_new(this->settings, titleBuffer, this->header->columns[i], this->scr);
if (i != 0) {
meterPanels[i]->leftNeighbor = meterPanels[i - 1];
meterPanels[i - 1]->rightNeighbor = meterPanels[i];
}
ScreenManager_add(this->scr, (Panel*) meterPanels[i], 20);
}
Panel* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, this->header, columns, meterPanels, this->scr, this->pl);
ScreenManager_add(this->scr, availableMeters, -1);
}
static void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this) {
Panel* displayOptions = (Panel*) DisplayOptionsPanel_new(this->settings, this->scr);
ScreenManager_add(this->scr, displayOptions, -1);
}
static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) {
Panel* colors = (Panel*) ColorsPanel_new(this->settings);
ScreenManager_add(this->scr, colors, -1);
}
static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) {
Panel* columns = (Panel*) ColumnsPanel_new(this->settings);
Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(columns, this->settings->dynamicColumns);
ScreenManager_add(this->scr, columns, 20);
ScreenManager_add(this->scr, availableColumns, -1);
}
static void CategoriesPanel_makeHeaderOptionsPage(CategoriesPanel* this) {
Panel* colors = (Panel*) HeaderOptionsPanel_new(this->settings, this->scr);
ScreenManager_add(this->scr, colors, -1);
}
typedef void (* CategoriesPanel_makePageFunc)(CategoriesPanel* ref);
typedef struct CategoriesPanelPage_ {
const char* name;
CategoriesPanel_makePageFunc ctor;
} CategoriesPanelPage;
static const CategoriesPanelPage categoriesPanelPages[] = {
{ .name = "Display options", .ctor = CategoriesPanel_makeDisplayOptionsPage },
{ .name = "Header layout", .ctor = CategoriesPanel_makeHeaderOptionsPage },
{ .name = "Meters", .ctor = CategoriesPanel_makeMetersPage },
{ .name = "Columns", .ctor = CategoriesPanel_makeColumnsPage },
{ .name = "Colors", .ctor = CategoriesPanel_makeColorsPage },
};
static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
CategoriesPanel* this = (CategoriesPanel*) super;
HandlerResult result = IGNORED;
int previous = Panel_getSelectedIndex(super);
int selected = Panel_getSelectedIndex(super);
switch (ch) {
case EVENT_SET_SELECTED:
result = HANDLED;
break;
case KEY_UP:
case KEY_CTRL('P'):
case KEY_DOWN:
case KEY_CTRL('N'):
case KEY_NPAGE:
case KEY_PPAGE:
case KEY_HOME:
case KEY_END: {
int previous = selected;
Panel_onKey(super, ch);
int selected = Panel_getSelectedIndex(super);
if (previous != selected) {
selected = Panel_getSelectedIndex(super);
if (previous != selected)
result = HANDLED;
break;
}
default:
if (0 < ch && ch < 255 && isgraph((unsigned char)ch))
result = Panel_selectByTyping(super, ch);
if (result == BREAK_LOOP)
result = IGNORED;
break;
}
if (result == HANDLED) {
int size = ScreenManager_size(this->scr);
for (int i = 1; i < size; i++)
ScreenManager_remove(this->scr, 1);
switch (selected) {
case 0:
CategoriesPanel_makeMetersPage(this);
break;
case 1:
CategoriesPanel_makeDisplayOptionsPage(this);
break;
case 2:
CategoriesPanel_makeColorsPage(this);
break;
case 3:
CategoriesPanel_makeColumnsPage(this);
break;
}
}
result = HANDLED;
}
}
if (selected >= 0 && (size_t)selected < ARRAYSIZE(categoriesPanelPages)) {
categoriesPanelPages[selected].ctor(this);
}
}
return result;
}
void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
Panel* leftMeters = (Panel*) MetersPanel_new(this->settings, "Left column", this->settings->header->leftMeters, this->scr);
Panel* rightMeters = (Panel*) MetersPanel_new(this->settings, "Right column", this->settings->header->rightMeters, this->scr);
Panel* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, leftMeters, rightMeters, this->scr);
ScreenManager_add(this->scr, leftMeters, FunctionBar_new(10, MetersFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, rightMeters, FunctionBar_new(10, MetersFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, availableMeters, FunctionBar_new(10, AvailableMetersFunctions, NULL, NULL), -1);
}
const PanelClass CategoriesPanel_class = {
.super = {
.extends = Class(Panel),
.delete = CategoriesPanel_delete
},
.eventHandler = CategoriesPanel_eventHandler
};
void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this) {
Panel* displayOptions = (Panel*) DisplayOptionsPanel_new(this->settings, this->scr);
ScreenManager_add(this->scr, displayOptions, FunctionBar_new(10, DisplayOptionsFunctions, NULL, NULL), -1);
}
CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Header* header, ProcessList* pl) {
CategoriesPanel* this = AllocThis(CategoriesPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(CategoriesFunctions, NULL, NULL);
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar);
void CategoriesPanel_makeColorsPage(CategoriesPanel* this) {
Panel* colors = (Panel*) ColorsPanel_new(this->settings, this->scr);
ScreenManager_add(this->scr, colors, FunctionBar_new(10, ColorsFunctions, NULL, NULL), -1);
}
this->scr = scr;
this->settings = settings;
this->header = header;
this->pl = pl;
Panel_setHeader(super, "Setup");
for (size_t i = 0; i < ARRAYSIZE(categoriesPanelPages); i++)
Panel_add(super, (Object*) ListItem_new(categoriesPanelPages[i].name, 0));
void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) {
Panel* columns = (Panel*) ColumnsPanel_new(this->settings, this->scr);
Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(this->settings, columns, this->scr);
ScreenManager_add(this->scr, columns, FunctionBar_new(10, ColumnsFunctions, NULL, NULL), 20);
ScreenManager_add(this->scr, availableColumns, FunctionBar_new(10, AvailableColumnsFunctions, NULL, NULL), -1);
ScreenManager_add(scr, super, 16);
categoriesPanelPages[0].ctor(this);
return this;
}

View File

@ -1,41 +1,30 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CategoriesPanel
#define HEADER_CategoriesPanel
/*
htop - CategoriesPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "AvailableMetersPanel.h"
#include "MetersPanel.h"
#include "DisplayOptionsPanel.h"
#include "ColumnsPanel.h"
#include "ColorsPanel.h"
#include "AvailableColumnsPanel.h"
#include "Header.h"
#include "Panel.h"
#include "debug.h"
#include <assert.h>
#include "ProcessList.h"
#include "ScreenManager.h"
#include "Settings.h"
typedef struct CategoriesPanel_ {
Panel super;
ScreenManager* scr;
Settings* settings;
ScreenManager* scr;
Header* header;
ProcessList* pl;
} CategoriesPanel;
extern const PanelClass CategoriesPanel_class;
CategoriesPanel* CategoriesPanel_new(Settings* settings, ScreenManager* scr);
void CategoriesPanel_delete(Object* object);
HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch);
void CategoriesPanel_makeMetersPage(CategoriesPanel* this);
void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this);
void CategoriesPanel_makeColorsPage(CategoriesPanel* this);
void CategoriesPanel_makeColumnsPage(CategoriesPanel* this);
CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Header* header, ProcessList* pl);
#endif

650
ChangeLog
View File

@ -1,3 +1,653 @@
What's new in version 3.1.0
* Updated COPYING file to remove the PLPA exemption (appendix 2)
With this change the license is now GPLv2 without any additional wording.
* Improved default sort ordering
Note for users: This may lead to an inverted sort order on startup of
htop 3.1.0 compared to previous versions.
This is due to what is stored in your htoprc file. Solution: Press I
(to invert sort order).
This changed setting will be saved by htop on exit as long as it can
write to your htoprc file.
* The compile-time option to cater specifically for running htop as
setuid has been removed
* Add read-only option
This allows htop to be run in an non-intrusive fashion where it acts only
as a process viewer disabling all functions to manipulate system state.
Note: This is not a security feature!
* Move the code for handling the command line formatting related tasks
to be shared across all platforms
This means important features like stale binary/library highlighting
can now be available on all supported platforms.
* Make the EXE and COMM columns available on all platforms
All supported platforms have the name of the executable (EXE) and a
self-chosen thread/command name (COMM) available one way or the other.
Moving this column to be handled as a platform-independently available
information simplifies the markup of the command line.
* Introduce configuration file versioning and config_reader_min_version
Starting with this version the configuration file contains an version
identifying the minimum version of the configuration parser needed to
fully understand the configuration file format.
Old configuration file formats are automatically upgraded on startup.
* Make the configuration parser friendlier to users (thanks to Bart Bakker)
With this change only settings that cannot be parsed properly are
reset to their defaults.
* Improve default display for systems with many CPUs
* Add the process ELAPSED time column
* Improve the process STATE column sorting
* Reworked handling resize and redrawing of the UI
* Fixed an issue where the LED meter mode could overflow allotted space
* Allow text mode Meters to span empty neighbors to the right
* Rescale graph meters when value of total changes
(thanks to Michael Schönitzer)
* Update generic process field display
Usually "uninteresting" values in columns like 1 thread, nice value
of 0, CPU and memory of 0%, idle/sleeping state, etc. are shown with
reduced intensity (dark grey)
* Option and key ("*") to collapse / expand all branches under PID 1
(and PID 2 if kernel threads are shown) (thanks to Krishna Chaitanya)
* Keep following a process when inverting the sort order, displaying
the help screen or hiding/unhiding userland threads
If a thread is currently selected the selection is updated to point
to the thread's parent process. (thanks to Gonzalo, et.al.)
* Reorder process scanning to be performed before updating the display
of the meters in the header
* Always check the user for a process for any changes
This affects multiple platforms that previously didn't correctly handle
the user field for a process to change at runtime (e.g. due to seteuid
or similar syscalls).
* Disable mouse option when support is unavailable
* Support curses libraries without ncurses mouse support
(thanks to Santhosh Raju)
* Support offline and hot-swapping of CPUs on all platforms
* Fix the CPU Meter for machines with more than 256 CPUs
* Supplemented the "show updated/deleted executables" feature (red basename)
to indicate when linked libraries were updated (yellow basename)
* Apply the stale binary highlighting for the EXE column in addition to
the command line field
* Add new combined Memory and Swap meter
* Implement bar and graph mode for NetworkIO Meter
(thanks to Michael F. Schönitzer)
* Rework TTY column to be more consistent across platforms
* Make the CWD column generally available on all platforms
(thanks to Santhosh Raju et. al.)
* Add Performance Co-Pilot (PCP) platform support
This is added via a separate pcp-htop(1) binary which provides remote host
analysis, new Meters for any PCP metric and new Columns for any PCP process
metric - see the pcp-htop(5) man page for further details.
(thanks to Sohaib Mohamed)
* Add Linux columns and key bindings for process autogroup identifier
and nice value
* Change available and used memory reporting on Linux to be based on
MemAvailable (Kernel 3.14+) (thanks to Chris Cheney and Tomas Wido)
* Add a new SysArchMeter showing kernel and platform information
(thanks to ahgamut)
* Linux memory usage explicitly treats tmpfs memory usage as shared memory
This is to make memory used by tmpfs visible as this cannot be freed
unlike normal filesystem cache data.
* Exclude zram devices when calculating DiskIO on Linux
* Use PATH lookup for systemctl in systemd meter (thanks to Scott Olson)
* Add native platform support for NetBSD
This allows htop to run on NetBSD without the need for active Linux
emulation of the procfs filesystem.
(thanks to Santhosh Raju and Nia Alarie)
* Add NetworkIO, DiskIO, CPU frequency, and battery meter support on NetBSD
(thanks to Nia Alarie)
* Fix NetBSD display of in-use and cached memory (thanks to Nia Alarie)
* Rework NetBSD CPU and memory accounting (thanks to Santhosh Raju)
* Fix NetBSD accounting of user and kernel threads (thanks to Santhosh Raju)
* Initial work to allow building with default libcurses on NetBSD
(thanks to Santhosh Raju)
* FreeBSD updates - implement process majflt and processor column values
* Add FreeBSD support for CPU frequency and temperature
* Fixes and cleanups for ZFS Meters and metrics
* Correctly color the ZFS ARC ratio (thanks to Ross Williams)
* Bugfixes related to CPU time display/calculations for darwin on M1 systems
(thanks to Alexander Momchilov)
* Harmonize the handling of multiple batteries across different platforms
The system is now considered to run on AC if at least one power supply
marked as AC is found in the system.
Battery capacity is summed up over all batteries found.
This also changes the old behavior that batteries reported by the
system after the first AC adapter where sometimes ignored.
* Correctly handle multiple batteries on Darwin
Resolves a possible memory leak on systems with multiple batteries
* Handle Linux Shmem being part of Cached in the MemoryMeter
* Add SwapCached to the Linux swap meter (thanks to David Zarzycki)
* Convert process time to days if applicable (thanks to David Zarzycki)
* Always show the number of threads in the TaskMeter, even when threads
are not shown in the process list
* Fix Linux --drop-capabilities option handling
* Correctly detect failure to initialize Linux boottime
* Overhaul the Linux memory fields to partition them like free(1) now does
* Improve the Linux process I/O column values
* Rework the libsensors parsing on Linux
* Update the MemoryMeter to display shared memory
* Update OpenBSD platform - implement additional columns, scan LWP,
proper markup for STATE, show CPU frequency
* Fix the tree view on OpenBSD when hiding kernel threads
* Remove old InfoScreen lines before re-scanning (thanks to Øystein Hiåsen)
* Document historic naming of Light-Weight Processes column aka threads
* Improve user interaction when the last process entry is selected
* Draw the panel header on the TraceScreen (thanks to Youngjae Lee)
* Add mouse wheel scroll and fix mouse selection on the InfoScreen
(thanks to Youngjae Lee)
* Add a HugepageMeter and subtract hugepages from normal memory
* Display wide characters in LED meters and restore non-wide ncurses support
* Add command line option to drop Linux capabilities
* Support scheduler affinity on platforms beyond Linux
* Report on any failure to write the configuration file
* Cache stderr to be able to print assert messages
These messages are shown in case htop terminates unexpectedly.
* Print current settings on crash
* Reset signal handlers on program exit
* Add configure script option to create a static htop binary
* Resolved longer-standing compilation issues on Solaris/Illumos
* Check for availability of set_escdelay in configure
(thanks to Stefan Polluks)
* Build system updates for autotools 2.70
What's new in version 3.0.5
* BUGFIX / SECURITY: InfoScreen: fix uncontrolled format string
* BUGFIX: Improve white text in the Light Terminal colour scheme
(both of the above thanks to V)
* Enable the function bar on the main screen to be hidden (see Setup -> Display options)
* BUGFIX: Reduce layout issues esp. around printing wide characters (not complete yet)
* BUGFIX: Make the follow function exit cleanly after followed process died
* Solaris: make Process callbacks static
* Update help and man page for improved -t / -s options
* Drop usage of formatted error messages from <err.h>
* Show arrow indicating order of sorted process column
* Lots of plumbing around the internal Hashtable, hardening and code cleanups
* LibSensors: add support for Ryzen CPUs
(thanks to Matej Dian)
* BUGFIX: Fix CPU percentage on M1 silicon Macs
(thanks to Luke Groeninger)
* LoadMeter: dynamically adjust color and total of bar
* Find libsensors.so.4 for Fedora and friends
* Add support to display CPU frequencies on Solarish platforms
(thanks to Dominik Hassler)
* Enable going back to previous search matches (Shift-F3)
* Added keybind 'N' for sorting by PID (drops 'n'/'N' as not used before much)
(thanks to Jake Mannens)
What's new in version 3.0.4
* Separate tree and list sort orders
* Invert Process_compare so that superclass matches run first
(thanks to Hisham Muhammad)
* Unhardcode Mac OS tick-to-milliseconds conversion
(thanks to Alexander Momchilov)
* Check if clock_gettime needs linking of librt
* Define O_PATH if not already defined
(thanks to Chris Burr)
* Add column on Mac for processes running under translation
(thanks to Dániel Bakai)
* Configure check for additional linker flags for keypad(3)
* PSI Meter: constant width and only print ten-duration as bar
* Sort in paused mode after inverting sort order
* Handle absence of package CPU temperature
* Meter: restore non-wide-character build
* LibSensors: restore temperature for Raspberry Pi
* MainPanel: do not reset hideProcessSelection on KEY_SHUFFLE
* BarMeter: rework text padding
* Panel: rework drawing of FunctionBar
* Meter: fix artifacts with very tiny width
* DragonFlyBSD updates
* BUGFIX: Fix dlopen issue for libsensors5 for some platforms
* BUGFIX: Fix broken tree display on inverted sort order
* BUGFIX: Fix pause mode ("Z") in tree view
* BUGFIX: Correct timebase for non-x86 CPUs on Darwin
* BUGFIX: Avoid NULL dereference on zombie processes
* Document dynamic bindings and assumed external configuration
* Update key mapping documentation for sorting
What's new in version 3.0.3
* Process sorting in 'tree' mode
(thanks to Maxim Zhiburt)
* Improved command display/sort functionality
(thanks to Narendran Gopalakrishnan)
* Add screen for active file locks
(thanks to Fynn J. Wulf)
* Calculate library size (M_LRS column) from maps file
(thanks to Fynn J. Wulf)
* Add a Zram meter
(thanks to Murloc Knight)
* Add Linux cwd process column
* Dynamically load libsensors at runtime
* Improve PressureStall Meter display strings
* Hide process selection on ESC
* Fully support non-ascii characters in Meter-Bar
* Add support to change numeric options in settings screen
* Rename virtual memory column from M_SIZE to M_VIRT
* Add process column for normalized CPU usage
* Show CPU temperature in CPU meter
* Drop hideThreads Setting
* Add a systemd meter
* Add a network IO meter
* Add a SELinux meter
* Compress size of default FunctionBar
* Updates to the OpenFiles screen
* Continue updating header data in paused mode
* BUGFIX: Handle data wraparounds in IO meters
* BUGFIX: Update InfoScreen content on resize
* Add security attribute process column
* Add DiskIOMeter for IO read/write usage
* Read CPU frequency from sysfs by default
* Add Linux process column for context switches
* Several FreeBSD and Mac OS X platform updates
(thanks to Christian Göttsche)
* Add process environment for FreeBSD
(thanks to Ross Williams)
* Parse POWER_SUPPLY_CAPACITY for Linux Battery meter
(thanks to Jan Palus)
* Add octuple-column CPU meters.
* BUGFIX: On Linux consider ZFS ARC to be cache
(thanks to @multi)
* BUGFIX: Limit screen title length to window width
* Show selected command wrapped in a separate window
(thanks to @ryenus)
* Allow to pass '/' for item search
* Document implicit incremental search
* Handle 'q' as quit if first character
* Avoid expensive build of process tree when not using it
* Include documentation for COMM and EXE
* Distinguish display of no permissions for reading M_LRS
* Only calculate M_LRS size every 2 seconds
* Improvements to comm / cmdline display functionality
* Merged view for COMM, EXE and cmdline
(thanks to Narendran Gopalakrishnan and Benny Baumann)
* Consistent kernel thread display for COMM/EXE columns
* Central fault handling for all platforms
* Handle parsing envID & VPid from process status file
* Use threshold for display of guest/steal/irq meters
* Enhance highlighting of semi-large and large numbers
* Documentation on the repository style guide
(thanks to Benny Baumann)
* Align processor identifier to the right
(thanks to Christian Hesse)
* Document M_PSS, M_PSSWP, M_SWAP in man page
* Add Date and DateTime meters
(thanks to Michael F. Schönitzer)
* BUGFIX: Fix Solaris 11.4 due to missing ZFS ARC kstats
(thanks to @senjan)
* Code hardening, speedups, fd and memory leak fixes
(thanks to Christian Göttsche and Benny Baumann)
* Number CPUs from zero by default
(thanks to Zev Weiss)
* Remove residual python checks during the build process
(thanks to Stephen Gregoratto)
What's new in version 3.0.2
* BUGFIX: Drop 'vim_mode' - several issues, needs rethink
* BUGFIX: fix regression in -u optional-argument handling
* Build system rework to remove python, header generation
(thanks to Zev Weiss and Hugo Musso Gualandi)
* BUGFIX: report nice level correctly on Solaris
(thanks to Dominik Hassler)
* CI, code quality improvements
(thanks to Tobias Kortkamp, Christian Hesse, Benny Baumann)
What's new in version 3.0.1
* Coverity fixes, CI improvements, documentation updates
* BUGFIX: Fix early exit with longer sysfs battery paths
* BUGFIX: Improve OOM output, fix sorting
(thanks to Christian Göttsche)
* Rework check buttons and tree open/closed
(thanks to Bert Wesarg)
* Add -U/--no-unicode option to disable unicode
(thanks to Christian Hesse)
* Improvements to the affinity panel
(thanks to Bert Wesarg)
What's new in version 3.0.0
* New maintainers - after a prolonged period of inactivity
from Hisham, the creator and original maintainer, a team
of community maintainers have volunteered to take over a
fork at https://htop.dev and https://github.com/htop-dev
to keep the project going.
* Support ZFS ARC statistics
(thanks to Ross Williams)
* Support more than 2 smaller CPU meter columns
(thanks to Christoph Budziszewski)
* Support Linux proportional set size metrics
(thanks to @linvinus, @ntninja and @himikof)
* Support Linux pressure stall information metrics
(thanks to Ran Benita)
* New display option to show CPU frequency in CPU meters
(thanks to Arnav Singh)
* Update Linux sysfs battery discovery for recent kernels
(thanks to @smattie)
* Add hardware topology information in the affinity panel
(thanks to Bert Wesarg)
* Add timestamp reporting to the strace screen
(thanks to Mario Harjac)
* Add simple, optional vim key mapping mode
(thanks to Daniel Flanagan)
* Added an option to disable the mouse
(thanks to MartinJM)
* Add Solaris11 compatibility
(thanks to Jan Senolt)
* Without an argument -u uses $USER value automatically
(thanks to @solanav)
* Support less(1) search navigation shortcuts
(thanks to @syrrim)
* Update the FreeBSD maximum PID to match FreeBSD change
(thanks to @multiplexd)
* Report values larger than 100 terabytes
(thanks to @adrien1018)
* Widen ST_UID (UID) column to allow for UIDs > 9999
(thanks to DLange)
* BUGFIX: fix makefiles for building with clang
(thanks to Jorge Pereira)
* BUGFIX: fix <sys/sysmacros.h> major() usage
(thanks to @wataash and Kang-Che Sung)
* BUGFIX: fix the STARTTIME column on FreeBSD
(thanks to Rob Crowston)
* BUGFIX: truncate overwide jail names on FreeBSD
(thanks to Rob Crowston)
* BUGFIX: fix reported memory values on FreeBSD
(thanks to Tobias Kortkamp)
* BUGFIX: fix reported CPU meter values on OpenBSD
(thanks to @motet-a)
* BUGFIX: correctly identify other types of zombie process
(thanks to @joder)
* BUGFIX: improve follow-process handling in some situations
(thanks to @wangqr)
* BUGFIX: fix custom meters reverting to unexpected setting
(thanks to @wangqr)
* BUGFIX: close pipe after running lsof(1)
(thanks to Jesin)
* BUGFIX: meters honour setting of counting CPUs from 0/1
(thanks to @rnsanchez)
What's new in version 2.2.0
* Solaris/Illumos/OpenIndiana support
(thanks to Guy M. Broome)
* -t/--tree flag for starting in tree-view mode
(thanks to Daniel Flanagan)
* macOS: detects High Sierra version to avoid OS bug
(thanks to Pierre Malhaire)
* OpenBSD: read battery data
(thanks to @nerd972)
* Various automake and build improvements
(thanks to Kang-Che Sung)
* Check for pkg-config when building with --enable-delayacct
(thanks to @florian2833z for the report)
* Avoid some bashisms in configure script
(thanks to Jesin)
* Use CFLAGS from ncurses*-config if present
(thanks to Michael Klein)
* Header generator supports non-UTF-8 environments
(thanks to @volkov-am)
* Linux: changed detection of kernel threads
* Collapse current subtree pressing Backspace
* BUGFIX: fix behavior of SYSCR column
(thanks to Marc Kleine-Budde)
* BUGFIX: obtain exit code of lsof correctly
(thanks to @wangqr)
* BUGFIX: fix crash with particular keycodes
(thanks to Wellington Torrejais da Silva for the report)
* BUGFIX: fix issue with small terminals
(thanks to Daniel Elf for the report)
* BUGFIX: fix terminal color issues
(thanks to Kang-Che Sung for the report)
* BUGFIX: preserve LDFLAGS when building
(thanks to Lance Frederickson for the report)
* BUGFIX: fixed overflow for systems with >= 100 signals
What's new in version 2.1.0
* Linux: Delay accounting metrics
(thanks to André Carvalho)
* DragonFlyBSD support
(thanks to Diederik de Groot)
* Support for real-time signals
(thanks to Kang-Che Sung)
* 'c' key now works with threads as well
* Session column renamed from SESN to SID
(thanks to Kamyar Rasta)
* Improved UI for meter style selection
(thanks to Kang-Che Sung)
* Improved code for constructing process tree
(thanks to wangqr)
* Compile-time option to disable setuid
* Error checking of various standard library operations
* Replacement of sprintf with snprintf
(thanks to Tomasz Kramkowski)
* Linux: performance improvements in battery meter
* Linux: update process TTY device
* Linux: add support for sorting TASK_IDLE
(thanks to Vladimir Panteleev)
* Linux: add upper-bound to running process counter
(thanks to Lucas Correia Villa Real)
* BUGFIX: avoid crash when battery is removed
(thanks to Jan Chren)
* BUGFIX: macOS: fix infinite loop in tree view
(thanks to Wataru Ashihara)
What's new in version 2.0.2
* Mac OS X: stop trying when task_for_pid fails for a process,
stops spamming logs with errors.
* Add Ctrl+A and Ctrl+E to go to beginning and end of line
* FreeBSD: fixes for CPU calculation
(thanks to Tim Creech, Andy Pilate)
* Usability: auto-follow process after a search.
* Use Linux backend on GNU Hurd
* Improvement for reproducible builds.
* BUGFIX: Fix behavior of Alt-key combinations
(thanks to Kang-Che Sung)
* Various code tweaks and cleanups
(thanks to Kang-Che Sung)
What's new in version 2.0.1
* OpenBSD: Various fixes and improvements
(thanks to Michael McConville and Juan Francisco Cantero Hurtado)
* FreeBSD: fix CPU and memory readings
(thanks to Tim Creech, Hung-Yi Chen, Bernard Spil, Greg V)
* FreeBSD: add battery support
(thanks to Greg V)
* Linux: Retain last-obtained name of a zombie process
* Mac OS X: Improve portability for OS X versions
(thanks to Michael Klein)
* Mac OS X: Fix reading command-line arguments and basename
* Mac OS X: Fix process state information
* Mac OS X: Fix tree view collapsing/expanding
* Mac OS X: Fix tree organization
* Mac OS X: Fix memory accounting
* Fix crash when emptying a column of meters
* Make Esc key more responsive
What's new in version 2.0.0
* Platform abstraction layer
* Initial FreeBSD support
* Initial Mac OS X support
(thanks to David Hunt)
* Swap meter for Mac OSX
(thanks to Ștefan Rusu)
* OpenBSD port
(thanks to Michael McConville)
* FreeBSD support improvements
(thanks to Martin Misuth)
* Support for NCurses 6 ABI, including mouse wheel support
* Much improved mouse responsiveness
* Process environment variables screen
(thanks to Michael Klein)
* Higher-resolution UTF-8 based Graph mode
(Thanks to James Hall from vtop for the idea!)
* Show program path settings
(thanks to Tobias Geerinckx-Rice)
* BUGFIX: Fix crash when scrolling an empty filtered list.
* Use dynamic units for text display, and several fixes
(thanks to Christian Hesse)
* BUGFIX: fix error caused by overflow in usertime calculation.
(thanks to Patrick Marlier)
* Catch all memory allocation errors
(thanks to Michael McConville for the push)
* Several tweaks and bugfixes
(See the Git log for details and contributors!)
What's new in version 1.0.3
* Tag all children ('c' key)
* Fixes in accounting of guest time when using virtualization
(thanks to Patrick Marlier)
* Performance improvements
(thanks to Jann Horn)
* Further performance improvements due to conditional parsing
of IO data depending on selected fields.
* Better consistency in coloring.
* Increase limit of buffer when tracing a deep nested process tree.
* Display pagefault stats.
* BUGFIX: Fix crash when adding meters and toggling detailed CPU time.
(thanks to Dawid Gajownik)
* Add column to track the OOM-killer score of processes
(thanks to Leigh Simpson)
What's new in version 1.0.2
* Add IO priority support ('i' key)
* Avoid deleting .htoprc if it is a symlink
* Fail gracefully when /proc is not mounted
(thanks to Philipp Hagemeister)
* Option to update process names on every refresh
(thanks to Rob Hoelz)
* BUGFIX: Fix crashes when process list is empty
What's new in version 1.0.1
* Move .htoprc to XDG-compliant path ~/.config/htop/htoprc,
respecting $XDG_CONFIG_HOME
(thanks to Hadzhimurad Ustarkhan for the suggestion.)
* Safer behavior on the kill screen, to make it harder to kill the wrong process.
* Fix for building in FreeBSD 8.2
(thanks to Trond Endrestol)
* BUGFIX: behavior of 'F' (follow) key was broken, also affecting the
persistence of mouse selections.
* BUGFIX: keep main panel up-to-date when running the screen manager,
to fix crash when processes die while on the F9/Kill screen.
What's new in version 1.0
* Performance improvements
* Support for splitting CPU meters into two or four columns
(thanks to Wim Heirman)
* Switch from PLPA, which is now deprecated, to HWLOC.
* Bring back support for native Linux sched_setaffinity,
so we don't have to use HWLOC where we don't need to.
* Support for typing in user names and column fields in selection panels.
* Support for UTF-8 tree drawing
(thanks to Bin Guo)
* Option for counting CPUs from zero
(thanks to Sean Noonan)
* Meters update in every screen (no longer halting while on Setup, etc.)
* Stricter checks for command-line options
(thanks to Sebastian Pipping)
* Incremental filtering
(thanks to Seth Heeren for the idea and initial implementation)
* Try harder to find the ncurses header
(thanks to Moritz Barsnick)
* Man page updates
(thanks to Vincent Launchbury)
* BUGFIX: Support larger numbers for process times.
(thanks to Tristan Nakagawa for the report.)
* BUGFIX: Segfault in BarMeterMode_draw() for small terminal widths
(patch by Sebastian Pipping)
What's new in version 0.9
* Add support for "steal"/guest CPU time measurement
in virtualization environments
* Expand and collapse subtrees using '+' and '-' when in tree-view
* Support for cgroups
(thanks to Guillaume Zitta and Daniel Lezcano)
* Show custom thread names
(thanks to Anders Torger)
* Add support for STARTTIME field
* Upgrade PLPA to version 1.3.2
* Fix license terms with regard to PLPA
(thanks to Tom Callaway)
* getopt-based long options and --no-color
(thanks to Vincent Launchbury)
* BUGFIX: Fix display of nan% in CPU meters
(thanks to Steven Hampson)
* BUGFIX: Fix memory leak
(thanks to Pavol Rusnak)
* Add Bash/emacs style navigation keys
(thanks to Daniel Schuler)
* Improve battery meter support
(thanks to Richard W.)
* BUGFIX: Fix IO-wait color in "Black on White" scheme
* BUGFIX: Fix search by process name when list is filtered by user.
(thanks to Sergej Pupykin for the report.)
* BUGFIX: Fix alignment for display of memory values above 100G (sign of the times!)
(thanks to Jan van Haarst for the report.)
What's new in version 0.8.3
* BUGFIX: Fix crash on F6 key
(thanks to Rainer Suhm)
* BUGFIX: Fix a minor bug which affected the build process.
What's new in version 0.8.2
* Integrated lsof (press 'l')
* Fix display of gigabyte-sized values
(thanks to Andika Triwidada)
* Option to display hostname in the meters area
* Rename VEID to CTID in OpenVZ systems
(thanks to Thorsten Schifferdecker)
* Corrections to the desktop entry file
(thanks by Samuli Suominen)
* BUGFIX: Correct page size calculation for FreeBSD systems
(thanks to Andrew Paulsen)
* Allow compilation without PLPA on systems that don't support it
(thanks to Timothy Redaelli)
* BUGFIX: Fix missing tree view when userland threads are hidden
(thanks to Josh Stone)
* BUGFIX: Fix for VPID on OpenVZ systems
(thanks to Wolfgang Frisch)
What's new in version 0.8.1
* Linux-VServer support
(thanks to Jonathan Sambrook and Benedikt Bohm)
* Battery meter
(thanks to Ian Page Hands)
* BUGFIX: Fix collection of IO stats in multithreaded processes
(thanks to Gerhard Heift)
* Remove assertion that fails on hardened kernels
(thanks to Wolfram Schlich for the report)
What's new in version 0.8
* Ability to change sort column with the mouse by
clicking column titles (click again to invert order)
* Add support for Linux per-process IO statistics,
enabled with the --enable-taskstats flag, which
requires a kernel compiled with taskstats support.
(thanks to Tobias Oetiker)
* Add Unicode support, enabled with the --enable-unicode
flag, which requires libncursesw.
(thanks to Sergej Pupykin)
* BUGFIX: Fix display of CPU count for threaded processes.
When user threads are hidden, process now shows the
sum of processor usage for all processors. When user
threads are displayed, each thread shows its own
processor usage, including the root thread.
(thanks to Bert Wesarg for the report)
* BUGFIX: avoid crashing when using many meters
(thanks to David Cho for the report)
What's new in version 0.7

View File

@ -1,74 +0,0 @@
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "CheckItem.h"
#include "Object.h"
#include "CRT.h"
#include "debug.h"
/*{
typedef struct CheckItem_ {
Object super;
char* text;
bool value;
bool* ref;
} CheckItem;
}*/
#ifdef DEBUG
char* CHECKITEM_CLASS = "CheckItem";
#else
#define CHECKITEM_CLASS NULL
#endif
CheckItem* CheckItem_new(char* text, bool* ref, bool value) {
CheckItem* this = malloc(sizeof(CheckItem));
Object_setClass(this, CHECKITEM_CLASS);
((Object*)this)->display = CheckItem_display;
((Object*)this)->delete = CheckItem_delete;
this->text = text;
this->value = value;
this->ref = ref;
return this;
}
void CheckItem_delete(Object* cast) {
CheckItem* this = (CheckItem*)cast;
assert (this != NULL);
free(this->text);
free(this);
}
void CheckItem_set(CheckItem* this, bool value) {
if (this->ref)
*(this->ref) = value;
else
this->value = value;
}
bool CheckItem_get(CheckItem* this) {
if (this->ref)
return *(this->ref);
else
return this->value;
}
void CheckItem_display(Object* cast, RichString* out) {
CheckItem* this = (CheckItem*)cast;
assert (this != NULL);
RichString_write(out, CRT_colors[CHECK_BOX], "[");
if (CheckItem_get(this))
RichString_append(out, CRT_colors[CHECK_MARK], "x");
else
RichString_append(out, CRT_colors[CHECK_MARK], " ");
RichString_append(out, CRT_colors[CHECK_BOX], "] ");
RichString_append(out, CRT_colors[CHECK_TEXT], this->text);
}

View File

@ -1,42 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_CheckItem
#define HEADER_CheckItem
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Object.h"
#include "CRT.h"
#include "debug.h"
typedef struct CheckItem_ {
Object super;
char* text;
bool value;
bool* ref;
} CheckItem;
#ifdef DEBUG
extern char* CHECKITEM_CLASS;
#else
#define CHECKITEM_CLASS NULL
#endif
CheckItem* CheckItem_new(char* text, bool* ref, bool value);
void CheckItem_delete(Object* cast);
void CheckItem_set(CheckItem* this, bool value);
bool CheckItem_get(CheckItem* this);
void CheckItem_display(Object* cast, RichString* out);
#endif

View File

@ -1,36 +1,46 @@
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - ClockMeter.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "ClockMeter.h"
#include "Meter.h"
#include <time.h>
#include <sys/time.h>
#include "debug.h"
#include "CRT.h"
#include "Object.h"
#include "ProcessList.h"
int ClockMeter_attributes[] = {
static const int ClockMeter_attributes[] = {
CLOCK
};
MeterType ClockMeter = {
.setValues = ClockMeter_setValues,
.display = NULL,
.mode = TEXT_METERMODE,
.total = 100.0,
.items = 1,
static void ClockMeter_updateValues(Meter* this) {
const ProcessList* pl = this->pl;
struct tm result;
const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result);
this->values[0] = lt->tm_hour * 60 + lt->tm_min;
strftime(this->txtBuffer, sizeof(this->txtBuffer), "%H:%M:%S", lt);
}
const MeterClass ClockMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.updateValues = ClockMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 1,
.total = 1440, /* 24*60 */
.attributes = ClockMeter_attributes,
.name = "Clock",
.uiName = "Clock",
.caption = "Time: ",
};
void ClockMeter_setValues(Meter* this, char* buffer, int size) {
time_t t = time(NULL);
struct tm *lt = localtime(&t);
this->values[0] = lt->tm_hour * 60 + lt->tm_min;
strftime(buffer, size, "%H:%M:%S", lt);
}

View File

@ -1,24 +1,15 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ClockMeter
#define HEADER_ClockMeter
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - ClockMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
#include <time.h>
#include "debug.h"
extern int ClockMeter_attributes[];
extern MeterType ClockMeter;
void ClockMeter_setValues(Meter* this, char* buffer, int size);
extern const MeterClass ClockMeter_class;
#endif

View File

@ -1,95 +1,105 @@
/*
htop - ColorsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "CRT.h"
#include "ColorsPanel.h"
#include "Panel.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include "CRT.h"
#include "FunctionBar.h"
#include "Macros.h"
#include "Object.h"
#include "OptionItem.h"
#include "ProvideCurses.h"
// TO ADD A NEW SCHEME:
// * Increment the size of bool check in ColorsPanel.h
// * Add the entry in the ColorSchemes array below in the file
// * Add the entry in the ColorSchemeNames array below in the file
// * Add a define in CRT.h that matches the order of the array
// * Add the colors in CRT_setColors
/*{
typedef struct ColorsPanel_ {
Panel super;
static const char* const ColorsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
Settings* settings;
ScreenManager* scr;
} ColorsPanel;
}*/
static char* ColorSchemes[] = {
static const char* const ColorSchemeNames[] = {
"Default",
"Monochromatic",
"Black on White",
"Light Terminal",
"MC",
"Black Night",
"Broken Gray",
NULL
};
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr) {
ColorsPanel* this = (ColorsPanel*) malloc(sizeof(ColorsPanel));
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, CHECKITEM_CLASS, true);
((Object*)this)->delete = ColorsPanel_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = ColorsPanel_EventHandler;
Panel_setHeader(super, "Colors");
for (int i = 0; ColorSchemes[i] != NULL; i++) {
Panel_add(super, (Object*) CheckItem_new(String_copy(ColorSchemes[i]), NULL, false));
}
CheckItem_set((CheckItem*)Panel_get(super, settings->colorScheme), true);
return this;
}
void ColorsPanel_delete(Object* object) {
static void ColorsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
ColorsPanel* this = (ColorsPanel*) object;
Panel_done(super);
free(this);
}
HandlerResult ColorsPanel_EventHandler(Panel* super, int ch) {
static HandlerResult ColorsPanel_eventHandler(Panel* super, int ch) {
ColorsPanel* this = (ColorsPanel*) super;
HandlerResult result = IGNORED;
int mark = Panel_getSelectedIndex(super);
int mark;
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_MOUSE:
case KEY_RECLICK:
case ' ':
for (int i = 0; ColorSchemes[i] != NULL; i++)
mark = Panel_getSelectedIndex(super);
assert(mark >= 0);
assert(mark < LAST_COLORSCHEME);
for (int i = 0; ColorSchemeNames[i] != NULL; i++)
CheckItem_set((CheckItem*)Panel_get(super, i), false);
CheckItem_set((CheckItem*)Panel_get(super, mark), true);
this->settings->colorScheme = mark;
result = HANDLED;
this->settings->changed = true;
CRT_setColors(mark);
clear();
result = HANDLED | REDRAW;
}
if (result == HANDLED) {
this->settings->changed = true;
Header* header = this->settings->header;
CRT_setColors(mark);
Panel* menu = (Panel*) Vector_get(this->scr->items, 0);
Header_draw(header);
RichString_setAttr(&(super->header), CRT_colors[PANEL_HEADER_FOCUS]);
RichString_setAttr(&(menu->header), CRT_colors[PANEL_HEADER_UNFOCUS]);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
}
return result;
}
const PanelClass ColorsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = ColorsPanel_delete
},
.eventHandler = ColorsPanel_eventHandler
};
ColorsPanel* ColorsPanel_new(Settings* settings) {
ColorsPanel* this = AllocThis(ColorsPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(ColorsFunctions, NULL, NULL);
Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true, fuBar);
this->settings = settings;
assert(ARRAYSIZE(ColorSchemeNames) == LAST_COLORSCHEME + 1);
Panel_setHeader(super, "Colors");
for (int i = 0; ColorSchemeNames[i] != NULL; i++) {
Panel_add(super, (Object*) CheckItem_newByVal(ColorSchemeNames[i], false));
}
CheckItem_set((CheckItem*)Panel_get(super, settings->colorScheme), true);
return this;
}

View File

@ -1,38 +1,24 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ColorsPanel
#define HEADER_ColorsPanel
#include "CRT.h"
/*
htop - ColorsPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
// TO ADD A NEW SCHEME:
// * Increment the size of bool check in ColorsPanel.h
// * Add the entry in the ColorSchemes array below in the file
// * Add a define in CRT.h that matches the order of the array
// * Add the colors in CRT_setColors
typedef struct ColorsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} ColorsPanel;
extern const PanelClass ColorsPanel_class;
ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr);
void ColorsPanel_delete(Object* object);
HandlerResult ColorsPanel_EventHandler(Panel* super, int ch);
ColorsPanel* ColorsPanel_new(Settings* settings);
#endif

View File

@ -1,81 +1,67 @@
/*
htop - ColumnsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "ColumnsPanel.h"
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
/*{
#include "CRT.h"
#include "DynamicColumn.h"
#include "FunctionBar.h"
#include "Hashtable.h"
#include "ListItem.h"
#include "Object.h"
#include "Process.h"
#include "ProvideCurses.h"
#include "XUtils.h"
typedef struct ColumnsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
} ColumnsPanel;
static const char* const ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL};
}*/
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr) {
ColumnsPanel* this = (ColumnsPanel*) malloc(sizeof(ColumnsPanel));
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = ColumnsPanel_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = ColumnsPanel_eventHandler;
Panel_setHeader(super, "Active Columns");
ProcessField* fields = this->settings->pl->fields;
for (; *fields; fields++) {
Panel_add(super, (Object*) ListItem_new(Process_fieldNames[*fields], 0));
}
return this;
}
void ColumnsPanel_delete(Object* object) {
static void ColumnsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
ColumnsPanel* this = (ColumnsPanel*) object;
Panel_done(super);
free(this);
}
int ColumnsPanel_fieldNameToIndex(const char* name) {
for (int j = 1; j <= LAST_PROCESSFIELD; j++) {
if (String_eq(name, Process_fieldNames[j])) {
return j;
}
}
return 0;
}
void ColumnsPanel_update(Panel* super) {
ColumnsPanel* this = (ColumnsPanel*) super;
int size = Panel_getSize(super);
this->settings->changed = true;
// FIXME: this is crappily inefficient
free(this->settings->pl->fields);
this->settings->pl->fields = (ProcessField*) malloc(sizeof(ProcessField) * (size+1));
for (int i = 0; i < size; i++) {
char* text = ((ListItem*) Panel_get(super, i))->value;
int j = ColumnsPanel_fieldNameToIndex(text);
if (j > 0)
this->settings->pl->fields[i] = j;
}
this->settings->pl->fields[size] = 0;
}
HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
ColumnsPanel* const this = (ColumnsPanel*) super;
int selected = Panel_getSelectedIndex(super);
HandlerResult result = IGNORED;
int size = Panel_getSize(super);
int size = Panel_size(super);
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_MOUSE:
case KEY_RECLICK:
{
if (selected < size - 1) {
this->moving = !(this->moving);
Panel_setSelectionColor(super, this->moving ? PANEL_SELECTION_FOLLOW : PANEL_SELECTION_FOCUS);
ListItem* selectedItem = (ListItem*) Panel_getSelected(super);
if (selectedItem)
selectedItem->moving = this->moving;
result = HANDLED;
}
break;
}
case KEY_UP:
{
if (!this->moving) {
break;
}
}
/* else fallthrough */
case KEY_F(7):
case '[':
case '-':
@ -85,6 +71,13 @@ HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
result = HANDLED;
break;
}
case KEY_DOWN:
{
if (!this->moving) {
break;
}
}
/* else fallthrough */
case KEY_F(8):
case ']':
case '+':
@ -103,8 +96,83 @@ HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
result = HANDLED;
break;
}
default:
{
if (0 < ch && ch < 255 && isgraph((unsigned char)ch))
result = Panel_selectByTyping(super, ch);
if (result == BREAK_LOOP)
result = IGNORED;
break;
}
}
if (result == HANDLED)
ColumnsPanel_update(super);
return result;
}
const PanelClass ColumnsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = ColumnsPanel_delete
},
.eventHandler = ColumnsPanel_eventHandler
};
typedef struct {
Panel* super;
unsigned int id;
unsigned int offset;
} DynamicIterator;
static void ColumnsPanel_add(Panel* super, unsigned int key, Hashtable* columns) {
const char* name;
if (key < LAST_PROCESSFIELD) {
name = Process_fields[key].name;
} else {
const DynamicColumn* column = Hashtable_get(columns, key);
assert(column);
if (!column) {
name = NULL;
} else {
name = column->caption ? column->caption : column->heading;
if (!name)
name = column->name; /* name is a mandatory field */
}
}
if (name == NULL)
name = "- ";
Panel_add(super, (Object*) ListItem_new(name, key));
}
ColumnsPanel* ColumnsPanel_new(Settings* settings) {
ColumnsPanel* this = AllocThis(ColumnsPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(ColumnsFunctions, NULL, NULL);
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar);
this->settings = settings;
this->moving = false;
Panel_setHeader(super, "Active Columns");
Hashtable* dynamicColumns = settings->dynamicColumns;
const ProcessField* fields = settings->fields;
for (; *fields; fields++)
ColumnsPanel_add(super, *fields, dynamicColumns);
return this;
}
void ColumnsPanel_update(Panel* super) {
ColumnsPanel* this = (ColumnsPanel*) super;
int size = Panel_size(super);
this->settings->changed = true;
this->settings->fields = xRealloc(this->settings->fields, sizeof(ProcessField) * (size + 1));
this->settings->flags = 0;
for (int i = 0; i < size; i++) {
int key = ((ListItem*) Panel_get(super, i))->key;
this->settings->fields[i] = key;
if (key < LAST_PROCESSFIELD)
this->settings->flags |= Process_fields[key].flags;
}
this->settings->fields[size] = 0;
}

View File

@ -1,33 +1,29 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ColumnsPanel
#define HEADER_ColumnsPanel
/*
htop - ColumnsPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include <stdbool.h>
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
typedef struct ColumnsPanel_ {
Panel super;
Settings* settings;
ScreenManager* scr;
bool moving;
} ColumnsPanel;
extern const PanelClass ColumnsPanel_class;
ColumnsPanel* ColumnsPanel_new(Settings* settings, ScreenManager* scr);
void ColumnsPanel_delete(Object* object);
int ColumnsPanel_fieldNameToIndex(const char* name);
ColumnsPanel* ColumnsPanel_new(Settings* settings);
void ColumnsPanel_update(Panel* super);
HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch);
#endif

402
CommandLine.c Normal file
View File

@ -0,0 +1,402 @@
/*
htop - CommandLine.c
(C) 2004-2011 Hisham H. Muhammad
(C) 2020-2021 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "CommandLine.h"
#include <assert.h>
#include <getopt.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "Action.h"
#include "CRT.h"
#include "DynamicColumn.h"
#include "DynamicMeter.h"
#include "Hashtable.h"
#include "Header.h"
#include "IncSet.h"
#include "MainPanel.h"
#include "MetersPanel.h"
#include "Panel.h"
#include "Platform.h"
#include "Process.h"
#include "ProcessList.h"
#include "ProvideCurses.h"
#include "ScreenManager.h"
#include "Settings.h"
#include "UsersTable.h"
#include "XUtils.h"
static void printVersionFlag(const char* name) {
printf("%s " VERSION "\n", name);
}
static void printHelpFlag(const char* name) {
printf("%s " VERSION "\n"
COPYRIGHT "\n"
"Released under the GNU GPLv2.\n\n"
"-C --no-color Use a monochrome color scheme\n"
"-d --delay=DELAY Set the delay between updates, in tenths of seconds\n"
"-F --filter=FILTER Show only the commands matching the given filter\n"
"-h --help Print this help screen\n"
"-H --highlight-changes[=DELAY] Highlight new and old processes\n"
"-M --no-mouse Disable the mouse\n"
"-p --pid=PID[,PID,PID...] Show only the given PIDs\n"
" --readonly Disable all system and process changing features\n"
"-s --sort-key=COLUMN Sort by COLUMN in list view (try --sort-key=help for a list)\n"
"-t --tree Show the tree view (can be combined with -s)\n"
"-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
"-U --no-unicode Do not use unicode but plain ASCII\n"
"-V --version Print version info\n", name);
Platform_longOptionsUsage(name);
printf("\n"
"Long options may be passed with a single dash.\n\n"
"Press F1 inside %s for online help.\n"
"See 'man %s' for more information.\n", name, name);
}
// ----------------------------------------
typedef struct CommandLineSettings_ {
Hashtable* pidMatchList;
char* commFilter;
uid_t userId;
int sortKey;
int delay;
bool useColors;
bool enableMouse;
bool treeView;
bool allowUnicode;
bool highlightChanges;
int highlightDelaySecs;
bool readonly;
} CommandLineSettings;
static CommandLineSettings parseArguments(const char* program, int argc, char** argv) {
CommandLineSettings flags = {
.pidMatchList = NULL,
.commFilter = NULL,
.userId = (uid_t)-1, // -1 is guaranteed to be an invalid uid_t (see setreuid(2))
.sortKey = 0,
.delay = -1,
.useColors = true,
.enableMouse = true,
.treeView = false,
.allowUnicode = true,
.highlightChanges = false,
.highlightDelaySecs = -1,
.readonly = false,
};
const struct option long_opts[] =
{
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"delay", required_argument, 0, 'd'},
{"sort-key", required_argument, 0, 's'},
{"user", optional_argument, 0, 'u'},
{"no-color", no_argument, 0, 'C'},
{"no-colour", no_argument, 0, 'C'},
{"no-mouse", no_argument, 0, 'M'},
{"no-unicode", no_argument, 0, 'U'},
{"tree", no_argument, 0, 't'},
{"pid", required_argument, 0, 'p'},
{"filter", required_argument, 0, 'F'},
{"highlight-changes", optional_argument, 0, 'H'},
{"readonly", no_argument, 0, 128},
PLATFORM_LONG_OPTIONS
{0, 0, 0, 0}
};
int opt, opti = 0;
/* Parse arguments */
while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:H::", long_opts, &opti))) {
if (opt == EOF)
break;
switch (opt) {
case 'h':
printHelpFlag(program);
exit(0);
case 'V':
printVersionFlag(program);
exit(0);
case 's':
assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */
if (String_eq(optarg, "help")) {
for (int j = 1; j < LAST_PROCESSFIELD; j++) {
const char* name = Process_fields[j].name;
const char* description = Process_fields[j].description;
if (name) printf("%19s %s\n", name, description);
}
exit(0);
}
flags.sortKey = 0;
for (int j = 1; j < LAST_PROCESSFIELD; j++) {
if (Process_fields[j].name == NULL)
continue;
if (String_eq(optarg, Process_fields[j].name)) {
flags.sortKey = j;
break;
}
}
if (flags.sortKey == 0) {
fprintf(stderr, "Error: invalid column \"%s\".\n", optarg);
exit(1);
}
break;
case 'd':
if (sscanf(optarg, "%16d", &(flags.delay)) == 1) {
if (flags.delay < 1) flags.delay = 1;
if (flags.delay > 100) flags.delay = 100;
} else {
fprintf(stderr, "Error: invalid delay value \"%s\".\n", optarg);
exit(1);
}
break;
case 'u':
{
const char *username = optarg;
if (!username && optind < argc && argv[optind] != NULL &&
(argv[optind][0] != '\0' && argv[optind][0] != '-')) {
username = argv[optind++];
}
if (!username) {
flags.userId = geteuid();
} else if (!Action_setUserOnly(username, &(flags.userId))) {
fprintf(stderr, "Error: invalid user \"%s\".\n", username);
exit(1);
}
break;
}
case 'C':
flags.useColors = false;
break;
case 'M':
#ifdef HAVE_GETMOUSE
flags.enableMouse = false;
#endif
break;
case 'U':
flags.allowUnicode = false;
break;
case 't':
flags.treeView = true;
break;
case 'p': {
assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */
char* argCopy = xStrdup(optarg);
char* saveptr;
const char* pid = strtok_r(argCopy, ",", &saveptr);
if (!flags.pidMatchList) {
flags.pidMatchList = Hashtable_new(8, false);
}
while(pid) {
unsigned int num_pid = atoi(pid);
// deepcode ignore CastIntegerToAddress: we just want a non-NUll pointer here
Hashtable_put(flags.pidMatchList, num_pid, (void *) 1);
pid = strtok_r(NULL, ",", &saveptr);
}
free(argCopy);
break;
}
case 'F': {
assert(optarg);
free_and_xStrdup(&flags.commFilter, optarg);
break;
}
case 'H': {
const char *delay = optarg;
if (!delay && optind < argc && argv[optind] != NULL &&
(argv[optind][0] != '\0' && argv[optind][0] != '-')) {
delay = argv[optind++];
}
if (delay) {
if (sscanf(delay, "%16d", &(flags.highlightDelaySecs)) == 1) {
if (flags.highlightDelaySecs < 1)
flags.highlightDelaySecs = 1;
} else {
fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay);
exit(1);
}
}
flags.highlightChanges = true;
break;
}
case 128:
flags.readonly = true;
break;
default:
if (Platform_getLongOption(opt, argc, argv) == false)
exit(1);
break;
}
}
return flags;
}
static void CommandLine_delay(ProcessList* pl, unsigned long millisec) {
struct timespec req = {
.tv_sec = 0,
.tv_nsec = millisec * 1000000L
};
while (nanosleep(&req, &req) == -1)
continue;
Platform_gettime_realtime(&pl->realtime, &pl->realtimeMs);
}
static void setCommFilter(State* state, char** commFilter) {
ProcessList* pl = state->pl;
IncSet* inc = state->mainPanel->inc;
IncSet_setFilter(inc, *commFilter);
pl->incFilter = IncSet_filter(inc);
free(*commFilter);
*commFilter = NULL;
}
int CommandLine_run(const char* name, int argc, char** argv) {
/* initialize locale */
const char* lc_ctype;
if ((lc_ctype = getenv("LC_CTYPE")) || (lc_ctype = getenv("LC_ALL")))
setlocale(LC_CTYPE, lc_ctype);
else
setlocale(LC_CTYPE, "");
CommandLineSettings flags = parseArguments(name, argc, argv);
if (flags.readonly)
Settings_enableReadonly();
Platform_init();
Process_setupColumnWidths();
UsersTable* ut = UsersTable_new();
Hashtable* dc = DynamicColumns_new();
Hashtable* dm = DynamicMeters_new();
if (!dc)
dc = Hashtable_new(0, true);
ProcessList* pl = ProcessList_new(ut, dm, dc, flags.pidMatchList, flags.userId);
Settings* settings = Settings_new(pl->activeCPUs, dc);
pl->settings = settings;
Header* header = Header_new(pl, settings, 2);
Header_populateFromSettings(header);
if (flags.delay != -1)
settings->delay = flags.delay;
if (!flags.useColors)
settings->colorScheme = COLORSCHEME_MONOCHROME;
#ifdef HAVE_GETMOUSE
if (!flags.enableMouse)
settings->enableMouse = false;
#endif
if (flags.treeView)
settings->treeView = true;
if (flags.highlightChanges)
settings->highlightChanges = true;
if (flags.highlightDelaySecs != -1)
settings->highlightDelaySecs = flags.highlightDelaySecs;
if (flags.sortKey > 0) {
// -t -s <key> means "tree sorted by key"
// -s <key> means "list sorted by key" (previous existing behavior)
if (!flags.treeView) {
settings->treeView = false;
}
Settings_setSortKey(settings, flags.sortKey);
}
CRT_init(settings, flags.allowUnicode);
MainPanel* panel = MainPanel_new();
ProcessList_setPanel(pl, (Panel*) panel);
MainPanel_updateTreeFunctions(panel, settings->treeView);
State state = {
.settings = settings,
.ut = ut,
.pl = pl,
.mainPanel = panel,
.header = header,
.pauseProcessUpdate = false,
.hideProcessSelection = false,
};
MainPanel_setState(panel, &state);
if (flags.commFilter)
setCommFilter(&state, &(flags.commFilter));
ScreenManager* scr = ScreenManager_new(header, settings, &state, true);
ScreenManager_add(scr, (Panel*) panel, -1);
ProcessList_scan(pl, false);
CommandLine_delay(pl, 75);
ProcessList_scan(pl, false);
if (settings->allBranchesCollapsed)
ProcessList_collapseAllBranches(pl);
ScreenManager_run(scr, NULL, NULL);
attron(CRT_colors[RESET_COLOR]);
mvhline(LINES - 1, 0, ' ', COLS);
attroff(CRT_colors[RESET_COLOR]);
refresh();
Platform_done();
CRT_done();
if (settings->changed) {
int r = Settings_write(settings, false);
if (r < 0)
fprintf(stderr, "Can not save configuration to %s: %s\n", settings->filename, strerror(-r));
}
Header_delete(header);
ProcessList_delete(pl);
ScreenManager_delete(scr);
MetersPanel_cleanup();
UsersTable_delete(ut);
if (flags.pidMatchList)
Hashtable_delete(flags.pidMatchList);
CRT_resetSignalHandlers();
/* Delete these last, since they can get accessed in the crash handler */
Settings_delete(settings);
if (dc)
Hashtable_delete(dc);
if (dm)
Hashtable_delete(dm);
return 0;
}

14
CommandLine.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef HEADER_CommandLine
#define HEADER_CommandLine
/*
htop - CommandLine.h
(C) 2004-2011 Hisham H. Muhammad
(C) 2020-2021 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
int CommandLine_run(const char* name, int argc, char** argv);
#endif

68
CommandScreen.c Normal file
View File

@ -0,0 +1,68 @@
#include "config.h" // IWYU pragma: keep
#include "CommandScreen.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "Macros.h"
#include "Panel.h"
#include "ProvideCurses.h"
static void CommandScreen_scan(InfoScreen* this) {
Panel* panel = this->display;
int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0);
Panel_prune(panel);
const char* p = Process_getCommand(this->process);
char line[COLS + 1];
int line_offset = 0, last_spc = -1, len;
for (; *p != '\0'; p++, line_offset++) {
assert(line_offset >= 0 && (size_t)line_offset < sizeof(line));
line[line_offset] = *p;
if (*p == ' ') {
last_spc = line_offset;
}
if (line_offset == COLS) {
len = (last_spc == -1) ? line_offset : last_spc;
line[len] = '\0';
InfoScreen_addLine(this, line);
line_offset -= len;
last_spc = -1;
memcpy(line, p - line_offset, line_offset + 1);
}
}
if (line_offset > 0) {
line[line_offset] = '\0';
InfoScreen_addLine(this, line);
}
Panel_setSelected(panel, idx);
}
static void CommandScreen_draw(InfoScreen* this) {
InfoScreen_drawTitled(this, "Command of process %d - %s", this->process->pid, Process_getCommand(this->process));
}
const InfoScreenClass CommandScreen_class = {
.super = {
.extends = Class(Object),
.delete = CommandScreen_delete
},
.scan = CommandScreen_scan,
.draw = CommandScreen_draw
};
CommandScreen* CommandScreen_new(Process* process) {
CommandScreen* this = AllocThis(CommandScreen);
return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ");
}
void CommandScreen_delete(Object* this) {
free(InfoScreen_done((InfoScreen*)this));
}

19
CommandScreen.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef HEADER_CommandScreen
#define HEADER_CommandScreen
#include "InfoScreen.h"
#include "Object.h"
#include "Process.h"
typedef struct CommandScreen_ {
InfoScreen super;
} CommandScreen;
extern const InfoScreenClass CommandScreen_class;
CommandScreen* CommandScreen_new(Process* process);
void CommandScreen_delete(Object* this);
#endif

119
Compat.c Normal file
View File

@ -0,0 +1,119 @@
/*
htop - Compat.c
(C) 2020 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "Compat.h"
#include <errno.h>
#include <fcntl.h> // IWYU pragma: keep
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h> // IWYU pragma: keep
#include "XUtils.h" // IWYU pragma: keep
int Compat_faccessat(int dirfd,
const char* pathname,
int mode,
int flags) {
int ret;
#ifdef HAVE_FACCESSAT
// Implementation note: AT_SYMLINK_NOFOLLOW unsupported on FreeBSD, fallback to lstat in that case
errno = 0;
ret = faccessat(dirfd, pathname, mode, flags);
if (!ret || errno != EINVAL)
return ret;
#endif
// Error out on unsupported configurations
if (dirfd != (int)AT_FDCWD || mode != F_OK) {
errno = EINVAL;
return -1;
}
// Fallback to stat(2)/lstat(2) depending on flags
struct stat statinfo;
if(flags) {
ret = lstat(pathname, &statinfo);
} else {
ret = stat(pathname, &statinfo);
}
return ret;
}
int Compat_fstatat(int dirfd,
const char* dirpath,
const char* pathname,
struct stat* statbuf,
int flags) {
#ifdef HAVE_FSTATAT
(void)dirpath;
return fstatat(dirfd, pathname, statbuf, flags);
#else
(void)dirfd;
char path[4096];
xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname);
if (flags & AT_SYMLINK_NOFOLLOW)
return lstat(path, statbuf);
return stat(path, statbuf);
#endif
}
#ifndef HAVE_OPENAT
int Compat_openat(const char* dirpath,
const char* pathname,
int flags) {
char path[4096];
xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname);
return open(path, flags);
}
#endif /* !HAVE_OPENAT */
ssize_t Compat_readlinkat(int dirfd,
const char* dirpath,
const char* pathname,
char* buf,
size_t bufsize) {
#ifdef HAVE_READLINKAT
(void)dirpath;
return readlinkat(dirfd, pathname, buf, bufsize);
#else
(void)dirfd;
char path[4096];
xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname);
return readlink(path, buf, bufsize);
#endif
}

59
Compat.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef HEADER_Compat
#define HEADER_Compat
/*
htop - Compat.h
(C) 2020 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include <fcntl.h>
#include <stddef.h>
#include <unistd.h>
#include <sys/stat.h> // IWYU pragma: keep
int Compat_faccessat(int dirfd,
const char* pathname,
int mode,
int flags);
int Compat_fstatat(int dirfd,
const char* dirpath,
const char* pathname,
struct stat* statbuf,
int flags);
#ifdef HAVE_OPENAT
typedef int openat_arg_t;
static inline void Compat_openatArgClose(openat_arg_t dirfd) {
close(dirfd);
}
static inline int Compat_openat(openat_arg_t dirfd, const char* pathname, int flags) {
return openat(dirfd, pathname, flags);
}
#else /* HAVE_OPENAT */
typedef const char* openat_arg_t;
static inline void Compat_openatArgClose(openat_arg_t dirpath) {
(void)dirpath;
}
int Compat_openat(openat_arg_t dirpath, const char* pathname, int flags);
#endif /* HAVE_OPENAT */
ssize_t Compat_readlinkat(int dirfd,
const char* dirpath,
const char* pathname,
char* buf,
size_t bufsize);
#endif /* HEADER_Compat */

52
DateMeter.c Normal file
View File

@ -0,0 +1,52 @@
/*
htop - DateMeter.c
(C) 2004-2020 Hisham H. Muhammad, Michael Schönitzer
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "DateMeter.h"
#include <time.h>
#include <sys/time.h>
#include "CRT.h"
#include "Object.h"
#include "ProcessList.h"
static const int DateMeter_attributes[] = {
DATE
};
static void DateMeter_updateValues(Meter* this) {
const ProcessList* pl = this->pl;
struct tm result;
const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result);
this->values[0] = lt->tm_yday;
int year = lt->tm_year + 1900;
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
this->total = 366;
} else {
this->total = 365;
}
strftime(this->txtBuffer, sizeof(this->txtBuffer), "%F", lt);
}
const MeterClass DateMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.updateValues = DateMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 1,
.total = 365,
.attributes = DateMeter_attributes,
.name = "Date",
.uiName = "Date",
.caption = "Date: ",
};

15
DateMeter.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef HEADER_DateMeter
#define HEADER_DateMeter
/*
htop - DateMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
extern const MeterClass DateMeter_class;
#endif

52
DateTimeMeter.c Normal file
View File

@ -0,0 +1,52 @@
/*
htop - DateTimeMeter.c
(C) 2004-2020 Hisham H. Muhammad, Michael Schönitzer
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "DateTimeMeter.h"
#include <time.h>
#include <sys/time.h>
#include "CRT.h"
#include "Object.h"
#include "ProcessList.h"
static const int DateTimeMeter_attributes[] = {
DATETIME
};
static void DateTimeMeter_updateValues(Meter* this) {
const ProcessList* pl = this->pl;
struct tm result;
const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result);
int year = lt->tm_year + 1900;
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
this->total = 366;
} else {
this->total = 365;
}
this->values[0] = lt->tm_yday;
strftime(this->txtBuffer, sizeof(this->txtBuffer), "%F %H:%M:%S", lt);
}
const MeterClass DateTimeMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.updateValues = DateTimeMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 1,
.total = 365,
.attributes = DateTimeMeter_attributes,
.name = "DateTime",
.uiName = "Date and Time",
.caption = "Date & Time: ",
};

15
DateTimeMeter.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef HEADER_DateTimeMeter
#define HEADER_DateTimeMeter
/*
htop - DateTimeMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
extern const MeterClass DateTimeMeter_class;
#endif

View File

@ -1,227 +0,0 @@
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#undef strdup
#undef malloc
#undef realloc
#undef calloc
#undef free
#include "DebugMemory.h"
/*{
typedef struct DebugMemoryItem_ DebugMemoryItem;
struct DebugMemoryItem_ {
int magic;
void* data;
char* file;
int line;
DebugMemoryItem* next;
};
typedef struct DebugMemory_ {
DebugMemoryItem* first;
int allocations;
int deallocations;
int size;
bool totals;
FILE* file;
} DebugMemory;
}*/
#if defined(DEBUG)
static DebugMemory* singleton = NULL;
void DebugMemory_new() {
if (singleton)
return;
singleton = malloc(sizeof(DebugMemory));
singleton->first = NULL;
singleton->allocations = 0;
singleton->deallocations = 0;
singleton->size = 0;
#ifdef DEBUG_ALLOC
singleton->file = fopen("/tmp/htop-debug-alloc.txt", "w");
#else
singleton->file = NULL;
#endif
singleton->totals = true;
//singleton->file = NULL;
}
void* DebugMemory_malloc(int size, char* file, int line, char* str) {
void* data = malloc(size);
DebugMemory_registerAllocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "%d\t%s:%d (%s)\n", size, file, line, str);
}
return data;
}
void* DebugMemory_calloc(int a, int b, char* file, int line) {
void* data = calloc(a, b);
DebugMemory_registerAllocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "%d\t%s:%d\n", a*b, file, line);
}
return data;
}
void* DebugMemory_realloc(void* ptr, int size, char* file, int line, char* str) {
if (ptr != NULL)
DebugMemory_registerDeallocation(ptr, file, line);
void* data = realloc(ptr, size);
DebugMemory_registerAllocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "%d\t%s:%d (%s)\n", size, file, line, str);
}
return data;
}
void* DebugMemory_strdup(char* str, char* file, int line) {
assert(str);
char* data = strdup(str);
DebugMemory_registerAllocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "%d\t%s:%d\n", (int) strlen(str), file, line);
}
return data;
}
void DebugMemory_free(void* data, char* file, int line) {
assert(data);
DebugMemory_registerDeallocation(data, file, line);
if (singleton->file) {
if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
fprintf(singleton->file, "free\t%s:%d\n", file, line);
}
free(data);
}
void DebugMemory_assertSize() {
if (!singleton->first) {
assert (singleton->size == 0);
}
DebugMemoryItem* walk = singleton->first;
int i = 0;
while (walk != NULL) {
assert(walk->magic == 11061980);
i++;
walk = walk->next;
}
assert (i == singleton->size);
}
int DebugMemory_getBlockCount() {
if (!singleton->first) {
return 0;
}
DebugMemoryItem* walk = singleton->first;
int i = 0;
while (walk != NULL) {
assert(walk->magic == 11061980);
i++;
walk = walk->next;
}
return i;
}
void DebugMemory_registerAllocation(void* data, char* file, int line) {
if (!singleton)
DebugMemory_new();
DebugMemory_assertSize();
DebugMemoryItem* item = (DebugMemoryItem*) malloc(sizeof(DebugMemoryItem));
item->magic = 11061980;
item->data = data;
item->file = file;
item->line = line;
item->next = NULL;
int val = DebugMemory_getBlockCount();
if (singleton->first == NULL) {
assert (val == 0);
singleton->first = item;
} else {
DebugMemoryItem* walk = singleton->first;
while (true) {
if (walk->next == NULL) {
walk->next = item;
break;
}
assert(walk->magic == 11061980);
walk = walk->next;
}
}
int nval = DebugMemory_getBlockCount();
assert(nval == val + 1);
singleton->allocations++;
singleton->size++;
DebugMemory_assertSize();
}
void DebugMemory_registerDeallocation(void* data, char* file, int line) {
assert(singleton);
assert(singleton->first);
DebugMemoryItem* walk = singleton->first;
DebugMemoryItem* prev = NULL;
int val = DebugMemory_getBlockCount();
while (walk != NULL) {
assert(walk->magic == 11061980);
if (walk->data == data) {
if (prev == NULL) {
singleton->first = walk->next;
} else {
prev->next = walk->next;
}
free(walk);
assert(DebugMemory_getBlockCount() == val - 1);
singleton->deallocations++;
singleton->size--;
DebugMemory_assertSize();
return;
}
DebugMemoryItem* tmp = walk;
walk = walk->next;
prev = tmp;
}
DebugMemory_report();
fprintf(stderr, "Couldn't find allocation for memory freed at %s:%d\n", file, line);
assert(false);
}
void DebugMemory_report() {
assert(singleton);
DebugMemoryItem* walk = singleton->first;
int i = 0;
while (walk != NULL) {
assert(walk->magic == 11061980);
i++;
fprintf(stderr, "%p %s:%d\n", walk->data, walk->file, walk->line);
walk = walk->next;
}
fprintf(stderr, "Total:\n");
fprintf(stderr, "%d allocations\n", singleton->allocations);
fprintf(stderr, "%d deallocations\n", singleton->deallocations);
fprintf(stderr, "%d size\n", singleton->size);
fprintf(stderr, "%d non-freed blocks\n", i);
if (singleton->file)
fclose(singleton->file);
}
#elif defined(DEBUGLITE)
//#include "efence.h"
#endif

View File

@ -1,71 +0,0 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_DebugMemory
#define HEADER_DebugMemory
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#undef strdup
#undef malloc
#undef realloc
#undef calloc
#undef free
typedef struct DebugMemoryItem_ DebugMemoryItem;
struct DebugMemoryItem_ {
int magic;
void* data;
char* file;
int line;
DebugMemoryItem* next;
};
typedef struct DebugMemory_ {
DebugMemoryItem* first;
int allocations;
int deallocations;
int size;
bool totals;
FILE* file;
} DebugMemory;
#if defined(DEBUG)
void DebugMemory_new();
void* DebugMemory_malloc(int size, char* file, int line, char* str);
void* DebugMemory_calloc(int a, int b, char* file, int line);
void* DebugMemory_realloc(void* ptr, int size, char* file, int line, char* str);
void* DebugMemory_strdup(char* str, char* file, int line);
void DebugMemory_free(void* data, char* file, int line);
void DebugMemory_assertSize();
int DebugMemory_getBlockCount();
void DebugMemory_registerAllocation(void* data, char* file, int line);
void DebugMemory_registerDeallocation(void* data, char* file, int line);
void DebugMemory_report();
#elif defined(DEBUGLITE)
//#include "efence.h"
#endif
#endif

129
DiskIOMeter.c Normal file
View File

@ -0,0 +1,129 @@
/*
htop - DiskIOMeter.c
(C) 2020 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "DiskIOMeter.h"
#include <stdbool.h>
#include <stdio.h>
#include "CRT.h"
#include "Macros.h"
#include "Object.h"
#include "Platform.h"
#include "ProcessList.h"
#include "RichString.h"
#include "XUtils.h"
static const int DiskIOMeter_attributes[] = {
METER_VALUE_NOTICE,
METER_VALUE_IOREAD,
METER_VALUE_IOWRITE,
};
static bool hasData = false;
static uint32_t cached_read_diff;
static uint32_t cached_write_diff;
static double cached_utilisation_diff;
static void DiskIOMeter_updateValues(Meter* this) {
const ProcessList* pl = this->pl;
static uint64_t cached_last_update;
uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update;
/* update only every 500ms */
if (passedTimeInMs > 500) {
static uint64_t cached_read_total;
static uint64_t cached_write_total;
static uint64_t cached_msTimeSpend_total;
uint64_t diff;
cached_last_update = pl->realtimeMs;
DiskIOData data;
hasData = Platform_getDiskIO(&data);
if (!hasData) {
this->values[0] = 0;
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "no data");
return;
}
if (data.totalBytesRead > cached_read_total) {
diff = data.totalBytesRead - cached_read_total;
diff /= 1024; /* Meter_humanUnit() expects unit in kilo */
cached_read_diff = (uint32_t)diff;
} else {
cached_read_diff = 0;
}
cached_read_total = data.totalBytesRead;
if (data.totalBytesWritten > cached_write_total) {
diff = data.totalBytesWritten - cached_write_total;
diff /= 1024; /* Meter_humanUnit() expects unit in kilo */
cached_write_diff = (uint32_t)diff;
} else {
cached_write_diff = 0;
}
cached_write_total = data.totalBytesWritten;
if (data.totalMsTimeSpend > cached_msTimeSpend_total) {
diff = data.totalMsTimeSpend - cached_msTimeSpend_total;
cached_utilisation_diff = 100.0 * (double)diff / passedTimeInMs;
} else {
cached_utilisation_diff = 0.0;
}
cached_msTimeSpend_total = data.totalMsTimeSpend;
}
this->values[0] = cached_utilisation_diff;
this->total = MAXIMUM(this->values[0], 100.0); /* fix total after (initial) spike */
char bufferRead[12], bufferWrite[12];
Meter_humanUnit(bufferRead, cached_read_diff, sizeof(bufferRead));
Meter_humanUnit(bufferWrite, cached_write_diff, sizeof(bufferWrite));
snprintf(this->txtBuffer, sizeof(this->txtBuffer), "%sB %sB %.1f%%", bufferRead, bufferWrite, cached_utilisation_diff);
}
static void DiskIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out) {
if (!hasData) {
RichString_writeAscii(out, CRT_colors[METER_VALUE_ERROR], "no data");
return;
}
char buffer[16];
int len;
int color = cached_utilisation_diff > 40.0 ? METER_VALUE_NOTICE : METER_VALUE;
len = xSnprintf(buffer, sizeof(buffer), "%.1f%%", cached_utilisation_diff);
RichString_appendnAscii(out, CRT_colors[color], buffer, len);
RichString_appendAscii(out, CRT_colors[METER_TEXT], " read: ");
Meter_humanUnit(buffer, cached_read_diff, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], buffer);
RichString_appendAscii(out, CRT_colors[METER_TEXT], " write: ");
Meter_humanUnit(buffer, cached_write_diff, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], buffer);
}
const MeterClass DiskIOMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = DiskIOMeter_display
},
.updateValues = DiskIOMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 1,
.total = 100.0,
.attributes = DiskIOMeter_attributes,
.name = "DiskIO",
.uiName = "Disk IO",
.caption = "Disk IO: "
};

21
DiskIOMeter.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef HEADER_DiskIOMeter
#define HEADER_DiskIOMeter
/*
htop - DiskIOMeter.h
(C) 2020 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
typedef struct DiskIOData_ {
uint64_t totalBytesRead;
uint64_t totalBytesWritten;
uint64_t totalMsTimeSpend;
} DiskIOData;
extern const MeterClass DiskIOMeter_class;
#endif /* HEADER_DiskIOMeter */

View File

@ -1,76 +1,145 @@
/*
htop - DisplayOptionsPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "DisplayOptionsPanel.h"
#include "Panel.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include <stdbool.h>
#include <stdlib.h>
#include "debug.h"
#include <assert.h>
#include "CRT.h"
#include "FunctionBar.h"
#include "Header.h"
#include "Object.h"
#include "OptionItem.h"
#include "ProvideCurses.h"
/*{
typedef struct DisplayOptionsPanel_ {
Panel super;
static const char* const DisplayOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
Settings* settings;
ScreenManager* scr;
} DisplayOptionsPanel;
}*/
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr) {
DisplayOptionsPanel* this = (DisplayOptionsPanel*) malloc(sizeof(DisplayOptionsPanel));
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, CHECKITEM_CLASS, true);
((Object*)this)->delete = DisplayOptionsPanel_delete;
this->settings = settings;
this->scr = scr;
super->eventHandler = DisplayOptionsPanel_eventHandler;
Panel_setHeader(super, "Display options");
Panel_add(super, (Object*) CheckItem_new(String_copy("Tree view"), &(settings->pl->treeView), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Shadow other users' processes"), &(settings->pl->shadowOtherUsers), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Hide kernel threads"), &(settings->pl->hideKernelThreads), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Hide userland threads"), &(settings->pl->hideUserlandThreads), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight program \"basename\""), &(settings->pl->highlightBaseName), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight megabytes in memory counters"), &(settings->pl->highlightMegabytes), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Leave a margin around header"), &(settings->header->margin), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ)"), &(settings->pl->detailedCPUTime), false));
return this;
}
void DisplayOptionsPanel_delete(Object* object) {
static void DisplayOptionsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
DisplayOptionsPanel* this = (DisplayOptionsPanel*) object;
Panel_done(super);
free(this);
}
HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
DisplayOptionsPanel* this = (DisplayOptionsPanel*) super;
HandlerResult result = IGNORED;
CheckItem* selected = (CheckItem*) Panel_getSelected(super);
OptionItem* selected = (OptionItem*) Panel_getSelected(super);
switch(ch) {
case 0x0a:
case 0x0d:
switch (ch) {
case '\n':
case '\r':
case KEY_ENTER:
case KEY_MOUSE:
case KEY_RECLICK:
case ' ':
CheckItem_set(selected, ! (CheckItem_get(selected)) );
switch (OptionItem_kind(selected)) {
case OPTION_ITEM_CHECK:
CheckItem_toggle((CheckItem*)selected);
result = HANDLED;
break;
case OPTION_ITEM_NUMBER:
NumberItem_toggle((NumberItem*)selected);
result = HANDLED;
break;
}
break;
case '-':
if (OptionItem_kind(selected) == OPTION_ITEM_NUMBER) {
NumberItem_decrease((NumberItem*)selected);
result = HANDLED;
}
break;
case '+':
if (OptionItem_kind(selected) == OPTION_ITEM_NUMBER) {
NumberItem_increase((NumberItem*)selected);
result = HANDLED;
}
break;
}
if (result == HANDLED) {
this->settings->changed = true;
Header* header = this->settings->header;
Header* header = this->scr->header;
Header_calculateHeight(header);
Header_reinit(header);
Header_updateData(header);
Header_draw(header);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
ScreenManager_resize(this->scr);
}
return result;
}
const PanelClass DisplayOptionsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = DisplayOptionsPanel_delete
},
.eventHandler = DisplayOptionsPanel_eventHandler
};
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr) {
DisplayOptionsPanel* this = AllocThis(DisplayOptionsPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(DisplayOptionsFunctions, NULL, NULL);
Panel_init(super, 1, 1, 1, 1, Class(OptionItem), true, fuBar);
this->settings = settings;
this->scr = scr;
Panel_setHeader(super, "Display options");
Panel_add(super, (Object*) CheckItem_newByRef("Tree view", &(settings->treeView)));
Panel_add(super, (Object*) CheckItem_newByRef("- Tree view is always sorted by PID (htop 2 behavior)", &(settings->treeViewAlwaysByPID)));
Panel_add(super, (Object*) CheckItem_newByRef("- Tree view is collapsed by default", &(settings->allBranchesCollapsed)));
Panel_add(super, (Object*) CheckItem_newByRef("Shadow other users' processes", &(settings->shadowOtherUsers)));
Panel_add(super, (Object*) CheckItem_newByRef("Hide kernel threads", &(settings->hideKernelThreads)));
Panel_add(super, (Object*) CheckItem_newByRef("Hide userland process threads", &(settings->hideUserlandThreads)));
Panel_add(super, (Object*) CheckItem_newByRef("Display threads in a different color", &(settings->highlightThreads)));
Panel_add(super, (Object*) CheckItem_newByRef("Show custom thread names", &(settings->showThreadNames)));
Panel_add(super, (Object*) CheckItem_newByRef("Show program path", &(settings->showProgramPath)));
Panel_add(super, (Object*) CheckItem_newByRef("Highlight program \"basename\"", &(settings->highlightBaseName)));
Panel_add(super, (Object*) CheckItem_newByRef("Highlight out-dated/removed programs", &(settings->highlightDeletedExe)));
Panel_add(super, (Object*) CheckItem_newByRef("Merge exe, comm and cmdline in Command", &(settings->showMergedCommand)));
Panel_add(super, (Object*) CheckItem_newByRef("- Try to find comm in cmdline (when Command is merged)", &(settings->findCommInCmdline)));
Panel_add(super, (Object*) CheckItem_newByRef("- Try to strip exe from cmdline (when Command is merged)", &(settings->stripExeFromCmdline)));
Panel_add(super, (Object*) CheckItem_newByRef("Highlight large numbers in memory counters", &(settings->highlightMegabytes)));
Panel_add(super, (Object*) CheckItem_newByRef("Leave a margin around header", &(settings->headerMargin)));
Panel_add(super, (Object*) CheckItem_newByRef("Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ/Steal/Guest)", &(settings->detailedCPUTime)));
Panel_add(super, (Object*) CheckItem_newByRef("Count CPUs from 1 instead of 0", &(settings->countCPUsFromOne)));
Panel_add(super, (Object*) CheckItem_newByRef("Update process names on every refresh", &(settings->updateProcessNames)));
Panel_add(super, (Object*) CheckItem_newByRef("Add guest time in CPU meter percentage", &(settings->accountGuestInCPUMeter)));
Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU percentage numerically", &(settings->showCPUUsage)));
Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU frequency", &(settings->showCPUFrequency)));
#ifdef BUILD_WITH_CPU_TEMP
Panel_add(super, (Object*) CheckItem_newByRef(
#if defined(HTOP_LINUX)
"Also show CPU temperature (requires libsensors)",
#elif defined(HTOP_FREEBSD)
"Also show CPU temperature",
#else
#error Unknown temperature implementation!
#endif
&(settings->showCPUTemperature)));
Panel_add(super, (Object*) CheckItem_newByRef("- Show temperature in degree Fahrenheit instead of Celsius", &(settings->degreeFahrenheit)));
#endif
#ifdef HAVE_GETMOUSE
Panel_add(super, (Object*) CheckItem_newByRef("Enable the mouse", &(settings->enableMouse)));
#endif
Panel_add(super, (Object*) NumberItem_newByRef("Update interval (in seconds)", &(settings->delay), -1, 1, 255));
Panel_add(super, (Object*) CheckItem_newByRef("Highlight new and old processes", &(settings->highlightChanges)));
Panel_add(super, (Object*) NumberItem_newByRef("- Highlight time (in seconds)", &(settings->highlightDelaySecs), 0, 1, 24 * 60 * 60));
Panel_add(super, (Object*) NumberItem_newByRef("Hide main function bar (0 - off, 1 - on ESC until next input, 2 - permanently)", &(settings->hideFunctionBar), 0, 0, 2));
#ifdef HAVE_LIBHWLOC
Panel_add(super, (Object*) CheckItem_newByRef("Show topology when selecting affinity by default", &(settings->topologyAffinity)));
#endif
return this;
}

View File

@ -1,16 +1,15 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_DisplayOptionsPanel
#define HEADER_DisplayOptionsPanel
/*
htop - DisplayOptionsPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h"
#include "CheckItem.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
#include "Settings.h"
typedef struct DisplayOptionsPanel_ {
@ -20,12 +19,8 @@ typedef struct DisplayOptionsPanel_ {
ScreenManager* scr;
} DisplayOptionsPanel;
extern const PanelClass DisplayOptionsPanel_class;
DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr);
void DisplayOptionsPanel_delete(Object* object);
HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch);
#endif

59
DynamicColumn.c Normal file
View File

@ -0,0 +1,59 @@
/*
htop - DynamicColumn.c
(C) 2021 Sohaib Mohammed
(C) 2021 htop dev team
(C) 2021 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "DynamicColumn.h"
#include <stddef.h>
#include "Platform.h"
#include "RichString.h"
#include "XUtils.h"
Hashtable* DynamicColumns_new(void) {
return Platform_dynamicColumns();
}
const char* DynamicColumn_init(unsigned int key) {
return Platform_dynamicColumnInit(key);
}
typedef struct {
const char* name;
const DynamicColumn* data;
unsigned int key;
} DynamicIterator;
static void DynamicColumn_compare(ht_key_t key, void* value, void* data) {
const DynamicColumn* column = (const DynamicColumn*)value;
DynamicIterator* iter = (DynamicIterator*)data;
if (String_eq(iter->name, column->name)) {
iter->data = column;
iter->key = key;
}
}
const DynamicColumn* DynamicColumn_search(Hashtable* dynamics, const char* name, unsigned int* key) {
DynamicIterator iter = { .key = 0, .data = NULL, .name = name };
if (dynamics)
Hashtable_foreach(dynamics, DynamicColumn_compare, &iter);
if (key)
*key = iter.key;
return iter.data;
}
const DynamicColumn* DynamicColumn_lookup(Hashtable* dynamics, unsigned int key) {
return (const DynamicColumn*) Hashtable_get(dynamics, key);
}
bool DynamicColumn_writeField(const Process* proc, RichString* str, unsigned int key) {
return Platform_dynamicColumnWriteField(proc, str, key);
}

32
DynamicColumn.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef HEADER_DynamicColumn
#define HEADER_DynamicColumn
#include <stdbool.h>
#include "Hashtable.h"
#include "Process.h"
#include "RichString.h"
#define DYNAMIC_MAX_COLUMN_WIDTH 28
#define DYNAMIC_DEFAULT_COLUMN_WIDTH -5
typedef struct DynamicColumn_ {
char name[32]; /* unique, internal-only name */
char* heading; /* displayed in main screen */
char* caption; /* displayed in setup menu (short name) */
char* description; /* displayed in setup menu (detail) */
int width; /* display width +/- for value alignment */
} DynamicColumn;
Hashtable* DynamicColumns_new(void);
const char* DynamicColumn_init(unsigned int key);
const DynamicColumn* DynamicColumn_lookup(Hashtable* dynamics, unsigned int key);
const DynamicColumn* DynamicColumn_search(Hashtable* dynamics, const char* name, unsigned int* key);
bool DynamicColumn_writeField(const Process* proc, RichString* str, unsigned int key);
#endif

124
DynamicMeter.c Normal file
View File

@ -0,0 +1,124 @@
/*
htop - DynamicMeter.c
(C) 2021 htop dev team
(C) 2021 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "DynamicMeter.h"
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "CRT.h"
#include "Object.h"
#include "Platform.h"
#include "ProcessList.h"
#include "RichString.h"
#include "XUtils.h"
static const int DynamicMeter_attributes[] = {
DYNAMIC_GRAY,
DYNAMIC_DARKGRAY,
DYNAMIC_RED,
DYNAMIC_GREEN,
DYNAMIC_BLUE,
DYNAMIC_CYAN,
DYNAMIC_MAGENTA,
DYNAMIC_YELLOW,
DYNAMIC_WHITE
};
Hashtable* DynamicMeters_new(void) {
return Platform_dynamicMeters();
}
typedef struct {
unsigned int key;
const char* name;
bool found;
} DynamicIterator;
static void DynamicMeter_compare(ht_key_t key, void* value, void* data) {
const DynamicMeter* meter = (const DynamicMeter*)value;
DynamicIterator* iter = (DynamicIterator*)data;
if (String_eq(iter->name, meter->name)) {
iter->found = true;
iter->key = key;
}
}
bool DynamicMeter_search(Hashtable* dynamics, const char* name, unsigned int* key) {
DynamicIterator iter = { .key = 0, .name = name, .found = false };
if (dynamics)
Hashtable_foreach(dynamics, DynamicMeter_compare, &iter);
if (key)
*key = iter.key;
return iter.found;
}
const char* DynamicMeter_lookup(Hashtable* dynamics, unsigned int key) {
const DynamicMeter* meter = Hashtable_get(dynamics, key);
return meter ? meter->name : NULL;
}
static void DynamicMeter_init(Meter* meter) {
Platform_dynamicMeterInit(meter);
}
static void DynamicMeter_updateValues(Meter* meter) {
Platform_dynamicMeterUpdateValues(meter);
}
static void DynamicMeter_display(const Object* cast, RichString* out) {
const Meter* meter = (const Meter*)cast;
Platform_dynamicMeterDisplay(meter, out);
}
static const char* DynamicMeter_getCaption(const Meter* this) {
const ProcessList* pl = this->pl;
const DynamicMeter* meter = Hashtable_get(pl->dynamicMeters, this->param);
if (meter)
return meter->caption ? meter->caption : meter->name;
return this->caption;
}
static void DynamicMeter_getUiName(const Meter* this, char* name, size_t length) {
const ProcessList* pl = this->pl;
const DynamicMeter* meter = Hashtable_get(pl->dynamicMeters, this->param);
if (meter) {
const char* uiName = meter->caption;
if (uiName) {
int len = strlen(uiName);
if (len > 2 && uiName[len - 2] == ':')
len -= 2;
xSnprintf(name, length, "%.*s", len, uiName);
} else {
xSnprintf(name, length, "%s", meter->name);
}
}
}
const MeterClass DynamicMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = DynamicMeter_display
},
.init = DynamicMeter_init,
.updateValues = DynamicMeter_updateValues,
.getCaption = DynamicMeter_getCaption,
.getUiName = DynamicMeter_getUiName,
.defaultMode = TEXT_METERMODE,
.maxItems = 0,
.total = 100.0,
.attributes = DynamicMeter_attributes,
.name = "Dynamic",
.uiName = "Dynamic",
.caption = "",
};

26
DynamicMeter.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef HEADER_DynamicMeter
#define HEADER_DynamicMeter
#include <stdbool.h>
#include "Hashtable.h"
#include "Meter.h"
typedef struct DynamicMeter_ {
char name[32]; /* unique name, cannot contain spaces */
char* caption;
char* description;
unsigned int type;
double maximum;
} DynamicMeter;
Hashtable* DynamicMeters_new(void);
const char* DynamicMeter_lookup(Hashtable* dynamics, unsigned int key);
bool DynamicMeter_search(Hashtable* dynamics, const char* name, unsigned int* key);
extern const MeterClass DynamicMeter_class;
#endif

58
EnvScreen.c Normal file
View File

@ -0,0 +1,58 @@
#include "config.h" // IWYU pragma: keep
#include "EnvScreen.h"
#include <stdlib.h>
#include <string.h>
#include "Macros.h"
#include "Panel.h"
#include "Platform.h"
#include "ProvideCurses.h"
#include "Vector.h"
#include "XUtils.h"
EnvScreen* EnvScreen_new(Process* process) {
EnvScreen* this = xMalloc(sizeof(EnvScreen));
Object_setClass(this, Class(EnvScreen));
return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ");
}
void EnvScreen_delete(Object* this) {
free(InfoScreen_done((InfoScreen*)this));
}
static void EnvScreen_draw(InfoScreen* this) {
InfoScreen_drawTitled(this, "Environment of process %d - %s", this->process->pid, Process_getCommand(this->process));
}
static void EnvScreen_scan(InfoScreen* this) {
Panel* panel = this->display;
int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0);
Panel_prune(panel);
char* env = Platform_getProcessEnv(this->process->pid);
if (env) {
for (const char* p = env; *p; p = strrchr(p, 0) + 1)
InfoScreen_addLine(this, p);
free(env);
}
else {
InfoScreen_addLine(this, "Could not read process environment.");
}
Vector_insertionSort(this->lines);
Vector_insertionSort(panel->items);
Panel_setSelected(panel, idx);
}
const InfoScreenClass EnvScreen_class = {
.super = {
.extends = Class(Object),
.delete = EnvScreen_delete
},
.scan = EnvScreen_scan,
.draw = EnvScreen_draw
};

19
EnvScreen.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef HEADER_EnvScreen
#define HEADER_EnvScreen
#include "InfoScreen.h"
#include "Object.h"
#include "Process.h"
typedef struct EnvScreen_ {
InfoScreen super;
} EnvScreen;
extern const InfoScreenClass EnvScreen_class;
EnvScreen* EnvScreen_new(Process* process);
void EnvScreen_delete(Object* this);
#endif

View File

@ -1,125 +1,148 @@
/*
htop - FunctionBar.c
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Object.h"
#include "config.h" // IWYU pragma: keep
#include "FunctionBar.h"
#include "CRT.h"
#include "debug.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <curses.h>
#include <string.h>
/*{
#include "CRT.h"
#include "Macros.h"
#include "ProvideCurses.h"
#include "XUtils.h"
typedef struct FunctionBar_ {
Object super;
int size;
char** functions;
char** keys;
int* events;
bool staticData;
} FunctionBar;
}*/
static const char* const FunctionBar_FKeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", NULL};
#ifdef DEBUG
char* FUNCTIONBAR_CLASS = "FunctionBar";
#else
#define FUNCTIONBAR_CLASS NULL
#endif
static const char* const FunctionBar_FLabels[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", NULL};
static char* FunctionBar_FKeys[10] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10"};
static int FunctionBar_FEvents[] = {KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10)};
static char* FunctionBar_FLabels[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " "};
static const char* const FunctionBar_EnterEscKeys[] = {"Enter", "Esc", NULL};
static const int FunctionBar_EnterEscEvents[] = {13, 27};
static int FunctionBar_FEvents[10] = {KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10)};
static int currentLen = 0;
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events) {
FunctionBar* this = malloc(sizeof(FunctionBar));
Object_setClass(this, FUNCTIONBAR_CLASS);
((Object*) this)->delete = FunctionBar_delete;
this->functions = functions;
this->size = size;
FunctionBar* FunctionBar_newEnterEsc(const char* enter, const char* esc) {
const char* functions[] = {enter, esc, NULL};
return FunctionBar_new(functions, FunctionBar_EnterEscKeys, FunctionBar_EnterEscEvents);
}
FunctionBar* FunctionBar_new(const char* const* functions, const char* const* keys, const int* events) {
FunctionBar* this = xCalloc(1, sizeof(FunctionBar));
this->functions = xCalloc(16, sizeof(char*));
if (!functions) {
functions = FunctionBar_FLabels;
}
for (int i = 0; i < 15 && functions[i]; i++) {
this->functions[i] = xStrdup(functions[i]);
}
if (keys && events) {
this->staticData = false;
this->functions = malloc(sizeof(char*) * size);
this->keys = malloc(sizeof(char*) * size);
this->events = malloc(sizeof(int) * size);
for (int i = 0; i < size; i++) {
this->functions[i] = String_copy(functions[i]);
this->keys[i] = String_copy(keys[i]);
this->keys.keys = xCalloc(15, sizeof(char*));
this->events = xCalloc(15, sizeof(int));
int i = 0;
while (i < 15 && functions[i]) {
this->keys.keys[i] = xStrdup(keys[i]);
this->events[i] = events[i];
i++;
}
this->size = i;
} else {
this->staticData = true;
this->functions = functions ? functions : FunctionBar_FLabels;
this->keys = FunctionBar_FKeys;
this->keys.constKeys = FunctionBar_FKeys;
this->events = FunctionBar_FEvents;
assert((!functions) || this->size == 10);
this->size = ARRAYSIZE(FunctionBar_FEvents);
}
return this;
}
void FunctionBar_delete(Object* cast) {
FunctionBar* this = (FunctionBar*) cast;
if (!this->staticData) {
for (int i = 0; i < this->size; i++) {
void FunctionBar_delete(FunctionBar* this) {
for (int i = 0; i < 15 && this->functions[i]; i++) {
free(this->functions[i]);
free(this->keys[i]);
}
free(this->functions);
free(this->keys);
if (!this->staticData) {
for (int i = 0; i < this->size; i++) {
free(this->keys.keys[i]);
}
free(this->keys.keys);
free(this->events);
}
free(this);
}
void FunctionBar_setLabel(FunctionBar* this, int event, char* text) {
assert(!this->staticData);
void FunctionBar_setLabel(FunctionBar* this, int event, const char* text) {
for (int i = 0; i < this->size; i++) {
if (this->events[i] == event) {
free(this->functions[i]);
this->functions[i] = String_copy(text);
this->functions[i] = xStrdup(text);
break;
}
}
}
void FunctionBar_draw(FunctionBar* this, char* buffer) {
FunctionBar_drawAttr(this, buffer, CRT_colors[FUNCTION_BAR]);
void FunctionBar_draw(const FunctionBar* this) {
FunctionBar_drawExtra(this, NULL, -1, false);
}
void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr) {
void FunctionBar_drawExtra(const FunctionBar* this, const char* buffer, int attr, bool setCursor) {
attrset(CRT_colors[FUNCTION_BAR]);
mvhline(LINES-1, 0, ' ', COLS);
mvhline(LINES - 1, 0, ' ', COLS);
int x = 0;
for (int i = 0; i < this->size; i++) {
attrset(CRT_colors[FUNCTION_KEY]);
mvaddstr(LINES-1, x, this->keys[i]);
x += strlen(this->keys[i]);
mvaddstr(LINES - 1, x, this->keys.constKeys[i]);
x += strlen(this->keys.constKeys[i]);
attrset(CRT_colors[FUNCTION_BAR]);
mvaddstr(LINES-1, x, this->functions[i]);
mvaddstr(LINES - 1, x, this->functions[i]);
x += strlen(this->functions[i]);
}
if (buffer != NULL) {
if (buffer) {
if (attr == -1) {
attrset(CRT_colors[FUNCTION_BAR]);
} else {
attrset(attr);
mvaddstr(LINES-1, x, buffer);
}
mvaddstr(LINES - 1, x, buffer);
x += strlen(buffer);
}
attrset(CRT_colors[RESET_COLOR]);
if (setCursor) {
CRT_cursorX = x;
curs_set(1);
} else {
curs_set(0);
}
currentLen = x;
}
int FunctionBar_synthesizeEvent(FunctionBar* this, int pos) {
void FunctionBar_append(const char* buffer, int attr) {
if (attr == -1) {
attrset(CRT_colors[FUNCTION_BAR]);
} else {
attrset(attr);
}
mvaddstr(LINES - 1, currentLen + 1, buffer);
attrset(CRT_colors[RESET_COLOR]);
currentLen += strlen(buffer) + 1;
}
int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos) {
int x = 0;
for (int i = 0; i < this->size; i++) {
x += strlen(this->keys[i]);
x += strlen(this->keys.constKeys[i]);
x += strlen(this->functions[i]);
if (pos < x) {
return this->events[i];

View File

@ -1,52 +1,40 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_FunctionBar
#define HEADER_FunctionBar
/*
htop - FunctionBar.h
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Object.h"
#include "CRT.h"
#include "debug.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <curses.h>
typedef struct FunctionBar_ {
Object super;
int size;
char** functions;
union {
char** keys;
const char* const* constKeys;
} keys;
int* events;
bool staticData;
} FunctionBar;
FunctionBar* FunctionBar_newEnterEsc(const char* enter, const char* esc);
#ifdef DEBUG
extern char* FUNCTIONBAR_CLASS;
#else
#define FUNCTIONBAR_CLASS NULL
#endif
FunctionBar* FunctionBar_new(const char* const* functions, const char* const* keys, const int* events);
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events);
void FunctionBar_delete(FunctionBar* this);
void FunctionBar_delete(Object* cast);
void FunctionBar_setLabel(FunctionBar* this, int event, const char* text);
void FunctionBar_setLabel(FunctionBar* this, int event, char* text);
void FunctionBar_draw(const FunctionBar* this);
void FunctionBar_draw(FunctionBar* this, char* buffer);
void FunctionBar_drawExtra(const FunctionBar* this, const char* buffer, int attr, bool setCursor);
void FunctionBar_drawAttr(FunctionBar* this, char* buffer, int attr);
void FunctionBar_append(const char* buffer, int attr);
int FunctionBar_synthesizeEvent(FunctionBar* this, int pos);
int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos);
#endif

View File

@ -1,177 +1,326 @@
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - Hashtable.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "Hashtable.h"
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "CRT.h"
#include "Macros.h"
#include "XUtils.h"
/*{
typedef struct Hashtable_ Hashtable;
#ifndef NDEBUG
#include <stdio.h>
#endif
typedef void(*Hashtable_PairFunction)(int, void*, void*);
typedef struct HashtableItem {
unsigned int key;
typedef struct HashtableItem_ {
ht_key_t key;
size_t probe;
void* value;
struct HashtableItem* next;
} HashtableItem;
struct Hashtable_ {
int size;
HashtableItem** buckets;
int items;
size_t size;
HashtableItem* buckets;
size_t items;
bool owner;
};
}*/
#ifdef DEBUG
bool Hashtable_isConsistent(Hashtable* this) {
int items = 0;
for (int i = 0; i < this->size; i++) {
HashtableItem* bucket = this->buckets[i];
while (bucket) {
#ifndef NDEBUG
static void Hashtable_dump(const Hashtable* this) {
fprintf(stderr, "Hashtable %p: size=%zu items=%zu owner=%s\n",
(const void*)this,
this->size,
this->items,
this->owner ? "yes" : "no");
size_t items = 0;
for (size_t i = 0; i < this->size; i++) {
fprintf(stderr, " item %5zu: key = %5u probe = %2zu value = %p\n",
i,
this->buckets[i].key,
this->buckets[i].probe,
this->buckets[i].value ? (const void*)this->buckets[i].value : "(nil)");
if (this->buckets[i].value)
items++;
bucket = bucket->next;
}
}
return items == this->items;
fprintf(stderr, "Hashtable %p: items=%zu counted=%zu\n",
(const void*)this,
this->items,
items);
}
int Hashtable_count(Hashtable* this) {
int items = 0;
for (int i = 0; i < this->size; i++) {
HashtableItem* bucket = this->buckets[i];
while (bucket) {
static bool Hashtable_isConsistent(const Hashtable* this) {
size_t items = 0;
for (size_t i = 0; i < this->size; i++) {
if (this->buckets[i].value)
items++;
bucket = bucket->next;
}
bool res = items == this->items;
if (!res)
Hashtable_dump(this);
return res;
}
size_t Hashtable_count(const Hashtable* this) {
size_t items = 0;
for (size_t i = 0; i < this->size; i++) {
if (this->buckets[i].value)
items++;
}
assert(items == this->items);
return items;
}
#endif
#endif /* NDEBUG */
HashtableItem* HashtableItem_new(unsigned int key, void* value) {
HashtableItem* this;
/* https://oeis.org/A014234 */
static const uint64_t OEISprimes[] = {
2, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191,
16381, 32749, 65521, 131071, 262139, 524287, 1048573,
2097143, 4194301, 8388593, 16777213, 33554393,
67108859, 134217689, 268435399, 536870909, 1073741789,
2147483647, 4294967291, 8589934583, 17179869143,
34359738337, 68719476731, 137438953447
};
this = (HashtableItem*) malloc(sizeof(HashtableItem));
this->key = key;
this->value = value;
this->next = NULL;
return this;
static size_t nextPrime(size_t n) {
/* on 32-bit make sure we do not return primes not fitting in size_t */
for (size_t i = 0; i < ARRAYSIZE(OEISprimes) && OEISprimes[i] < SIZE_MAX; i++) {
if (n <= OEISprimes[i])
return OEISprimes[i];
}
CRT_fatalError("Hashtable: no prime found");
}
Hashtable* Hashtable_new(int size, bool owner) {
Hashtable* Hashtable_new(size_t size, bool owner) {
Hashtable* this;
this = (Hashtable*) malloc(sizeof(Hashtable));
this = xMalloc(sizeof(Hashtable));
this->items = 0;
this->size = size;
this->buckets = (HashtableItem**) calloc(sizeof(HashtableItem*), size);
this->size = size ? nextPrime(size) : 13;
this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem));
this->owner = owner;
assert(Hashtable_isConsistent(this));
return this;
}
void Hashtable_delete(Hashtable* this) {
assert(Hashtable_isConsistent(this));
for (int i = 0; i < this->size; i++) {
HashtableItem* walk = this->buckets[i];
while (walk != NULL) {
if (this->owner)
free(walk->value);
HashtableItem* savedWalk = walk;
walk = savedWalk->next;
free(savedWalk);
}
}
Hashtable_clear(this);
free(this->buckets);
free(this);
}
inline int Hashtable_size(Hashtable* this) {
void Hashtable_clear(Hashtable* this) {
assert(Hashtable_isConsistent(this));
return this->items;
}
void Hashtable_put(Hashtable* this, unsigned int key, void* value) {
unsigned int index = key % this->size;
HashtableItem** bucketPtr = &(this->buckets[index]);
while (true)
if (*bucketPtr == NULL) {
*bucketPtr = HashtableItem_new(key, value);
this->items++;
break;
} else if ((*bucketPtr)->key == key) {
if (this->owner)
free((*bucketPtr)->value);
(*bucketPtr)->value = value;
break;
} else
bucketPtr = &((*bucketPtr)->next);
for (size_t i = 0; i < this->size; i++)
free(this->buckets[i].value);
memset(this->buckets, 0, this->size * sizeof(HashtableItem));
this->items = 0;
assert(Hashtable_isConsistent(this));
}
void* Hashtable_remove(Hashtable* this, unsigned int key) {
unsigned int index = key % this->size;
static void insert(Hashtable* this, ht_key_t key, void* value) {
size_t index = key % this->size;
size_t probe = 0;
#ifndef NDEBUG
size_t origIndex = index;
#endif
for (;;) {
if (!this->buckets[index].value) {
this->items++;
this->buckets[index].key = key;
this->buckets[index].probe = probe;
this->buckets[index].value = value;
return;
}
if (this->buckets[index].key == key) {
if (this->owner && this->buckets[index].value != value)
free(this->buckets[index].value);
this->buckets[index].value = value;
return;
}
/* Robin Hood swap */
if (probe > this->buckets[index].probe) {
HashtableItem tmp = this->buckets[index];
this->buckets[index].key = key;
this->buckets[index].probe = probe;
this->buckets[index].value = value;
key = tmp.key;
probe = tmp.probe;
value = tmp.value;
}
index = (index + 1) % this->size;
probe++;
assert(index != origIndex);
}
}
void Hashtable_setSize(Hashtable* this, size_t size) {
assert(Hashtable_isConsistent(this));
HashtableItem** bucket;
for (bucket = &(this->buckets[index]); *bucket; bucket = &((*bucket)->next) ) {
if ((*bucket)->key == key) {
void* value = (*bucket)->value;
HashtableItem* next = (*bucket)->next;
free(*bucket);
(*bucket) = next;
this->items--;
if (size <= this->items)
return;
HashtableItem* oldBuckets = this->buckets;
size_t oldSize = this->size;
this->size = nextPrime(size);
this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem));
this->items = 0;
/* rehash */
for (size_t i = 0; i < oldSize; i++) {
if (!oldBuckets[i].value)
continue;
insert(this, oldBuckets[i].key, oldBuckets[i].value);
}
free(oldBuckets);
assert(Hashtable_isConsistent(this));
}
void Hashtable_put(Hashtable* this, ht_key_t key, void* value) {
assert(Hashtable_isConsistent(this));
assert(this->size > 0);
assert(value);
/* grow on load-factor > 0.7 */
if (10 * this->items > 7 * this->size) {
if (SIZE_MAX / 2 < this->size)
CRT_fatalError("Hashtable: size overflow");
Hashtable_setSize(this, 2 * this->size);
}
insert(this, key, value);
assert(Hashtable_isConsistent(this));
assert(Hashtable_get(this, key) != NULL);
assert(this->size > this->items);
}
void* Hashtable_remove(Hashtable* this, ht_key_t key) {
size_t index = key % this->size;
size_t probe = 0;
#ifndef NDEBUG
size_t origIndex = index;
#endif
assert(Hashtable_isConsistent(this));
void* res = NULL;
while (this->buckets[index].value) {
if (this->buckets[index].key == key) {
if (this->owner) {
free(value);
assert(Hashtable_isConsistent(this));
return NULL;
free(this->buckets[index].value);
} else {
res = this->buckets[index].value;
}
size_t next = (index + 1) % this->size;
while (this->buckets[next].value && this->buckets[next].probe > 0) {
this->buckets[index] = this->buckets[next];
this->buckets[index].probe -= 1;
index = next;
next = (index + 1) % this->size;
}
/* set empty after backward shifting */
this->buckets[index].value = NULL;
this->items--;
break;
}
if (this->buckets[index].probe < probe)
break;
index = (index + 1) % this->size;
probe++;
assert(index != origIndex);
}
assert(Hashtable_isConsistent(this));
return value;
}
}
}
assert(Hashtable_isConsistent(this));
return NULL;
assert(Hashtable_get(this, key) == NULL);
/* shrink on load-factor < 0.125 */
if (8 * this->items < this->size)
Hashtable_setSize(this, this->size / 2);
return res;
}
inline void* Hashtable_get(Hashtable* this, unsigned int key) {
unsigned int index = key % this->size;
HashtableItem* bucketPtr = this->buckets[index];
while (true) {
if (bucketPtr == NULL) {
void* Hashtable_get(Hashtable* this, ht_key_t key) {
size_t index = key % this->size;
size_t probe = 0;
void* res = NULL;
#ifndef NDEBUG
size_t origIndex = index;
#endif
assert(Hashtable_isConsistent(this));
return NULL;
} else if (bucketPtr->key == key) {
assert(Hashtable_isConsistent(this));
return bucketPtr->value;
} else
bucketPtr = bucketPtr->next;
while (this->buckets[index].value) {
if (this->buckets[index].key == key) {
res = this->buckets[index].value;
break;
}
if (this->buckets[index].probe < probe)
break;
index = (index + 1) != this->size ? (index + 1) : 0;
probe++;
assert(index != origIndex);
}
return res;
}
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) {
assert(Hashtable_isConsistent(this));
for (int i = 0; i < this->size; i++) {
HashtableItem* walk = this->buckets[i];
while (walk != NULL) {
for (size_t i = 0; i < this->size; i++) {
HashtableItem* walk = &this->buckets[i];
if (walk->value)
f(walk->key, walk->value, userData);
walk = walk->next;
}
}
assert(Hashtable_isConsistent(this));
}

View File

@ -1,59 +1,41 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Hashtable
#define HEADER_Hashtable
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - Hashtable.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <stddef.h>
#include "debug.h"
typedef unsigned int ht_key_t;
typedef void(*Hashtable_PairFunction)(ht_key_t key, void* value, void* userdata);
typedef struct Hashtable_ Hashtable;
typedef void(*Hashtable_PairFunction)(int, void*, void*);
#ifndef NDEBUG
typedef struct HashtableItem {
unsigned int key;
void* value;
struct HashtableItem* next;
} HashtableItem;
size_t Hashtable_count(const Hashtable* this);
struct Hashtable_ {
int size;
HashtableItem** buckets;
int items;
bool owner;
};
#endif /* NDEBUG */
#ifdef DEBUG
bool Hashtable_isConsistent(Hashtable* this);
int Hashtable_count(Hashtable* this);
#endif
HashtableItem* HashtableItem_new(unsigned int key, void* value);
Hashtable* Hashtable_new(int size, bool owner);
Hashtable* Hashtable_new(size_t size, bool owner);
void Hashtable_delete(Hashtable* this);
extern int Hashtable_size(Hashtable* this);
void Hashtable_clear(Hashtable* this);
void Hashtable_put(Hashtable* this, unsigned int key, void* value);
void Hashtable_setSize(Hashtable* this, size_t size);
void* Hashtable_remove(Hashtable* this, unsigned int key);
void Hashtable_put(Hashtable* this, ht_key_t key, void* value);
extern void* Hashtable_get(Hashtable* this, unsigned int key);
void* Hashtable_remove(Hashtable* this, ht_key_t key);
void* Hashtable_get(Hashtable* this, ht_key_t key);
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);

350
Header.c
View File

@ -1,169 +1,285 @@
/*
htop - Header.c
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Header.h"
#include "Meter.h"
#include "debug.h"
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*{
#include "CRT.h"
#include "CPUMeter.h"
#include "DynamicMeter.h"
#include "Macros.h"
#include "Object.h"
#include "Platform.h"
#include "ProvideCurses.h"
#include "XUtils.h"
typedef enum HeaderSide_ {
LEFT_HEADER,
RIGHT_HEADER
} HeaderSide;
typedef struct Header_ {
Vector* leftMeters;
Vector* rightMeters;
ProcessList* pl;
bool margin;
int height;
int pad;
} Header;
}*/
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
Header* Header_new(ProcessList* pl) {
Header* this = malloc(sizeof(Header));
this->leftMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
this->rightMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
this->margin = true;
Header* Header_new(ProcessList* pl, Settings* settings, HeaderLayout hLayout) {
Header* this = xCalloc(1, sizeof(Header));
this->columns = xMallocArray(HeaderLayout_getColumns(hLayout), sizeof(Vector*));
this->settings = settings;
this->pl = pl;
this->headerLayout = hLayout;
Header_forEachColumn(this, i) {
this->columns[i] = Vector_new(Class(Meter), true, DEFAULT_SIZE);
}
return this;
}
void Header_delete(Header* this) {
Vector_delete(this->leftMeters);
Vector_delete(this->rightMeters);
Header_forEachColumn(this, i) {
Vector_delete(this->columns[i]);
}
free(this->columns);
free(this);
}
void Header_createMeter(Header* this, char* name, HeaderSide side) {
Vector* meters = side == LEFT_HEADER
? this->leftMeters
: this->rightMeters;
void Header_setLayout(Header* this, HeaderLayout hLayout) {
size_t oldColumns = HeaderLayout_getColumns(this->headerLayout);
size_t newColumns = HeaderLayout_getColumns(hLayout);
char* paren = strchr(name, '(');
int param = 0;
if (paren) {
int ok = sscanf(paren, "(%d)", &param);
if (!ok) param = 0;
*paren = '\0';
this->headerLayout = hLayout;
if (newColumns == oldColumns)
return;
if (newColumns > oldColumns) {
this->columns = xReallocArray(this->columns, newColumns, sizeof(Vector*));
for (size_t i = oldColumns; i < newColumns; i++)
this->columns[i] = Vector_new(Class(Meter), true, DEFAULT_SIZE);
} else {
// move meters from to-be-deleted columns into last one
for (size_t i = newColumns; i < oldColumns; i++) {
for (int j = this->columns[i]->items - 1; j >= 0; j--) {
Vector_add(this->columns[newColumns - 1], Vector_take(this->columns[i], j));
}
for (MeterType** type = Meter_types; *type; type++) {
if (String_eq(name, (*type)->name)) {
Vector_add(meters, Meter_new(this->pl, param, *type));
Vector_delete(this->columns[i]);
}
this->columns = xReallocArray(this->columns, newColumns, sizeof(Vector*));
}
Header_calculateHeight(this);
}
static void Header_addMeterByName(Header* this, const char* name, MeterModeId mode, unsigned int column) {
assert(column < HeaderLayout_getColumns(this->headerLayout));
Vector* meters = this->columns[column];
const char* paren = strchr(name, '(');
unsigned int param = 0;
size_t nameLen;
if (paren) {
int ok = sscanf(paren, "(%10u)", &param); // CPUMeter
if (!ok) {
char* end, dynamic[32] = {0};
if (sscanf(paren, "(%30s)", dynamic)) { // DynamicMeter
if ((end = strrchr(dynamic, ')')) == NULL)
return; // htoprc parse failure
*end = '\0';
if (!DynamicMeter_search(this->pl->dynamicMeters, dynamic, &param))
return; // name lookup failure
} else {
param = 0;
}
}
nameLen = paren - name;
} else {
nameLen = strlen(name);
}
for (const MeterClass* const* type = Platform_meterTypes; *type; type++) {
if (0 == strncmp(name, (*type)->name, nameLen) && (*type)->name[nameLen] == '\0') {
Meter* meter = Meter_new(this->pl, param, *type);
if (mode != 0) {
Meter_setMode(meter, mode);
}
Vector_add(meters, meter);
break;
}
}
}
void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side) {
Vector* meters = side == LEFT_HEADER
? this->leftMeters
: this->rightMeters;
void Header_populateFromSettings(Header* this) {
Header_setLayout(this, this->settings->hLayout);
Meter* meter = (Meter*) Vector_get(meters, i);
Meter_setMode(meter, mode);
Header_forEachColumn(this, col) {
const MeterColumnSetting* colSettings = &this->settings->hColumns[col];
Vector_prune(this->columns[col]);
for (size_t i = 0; i < colSettings->len; i++) {
Header_addMeterByName(this, colSettings->names[i], colSettings->modes[i], col);
}
}
Header_calculateHeight(this);
}
Meter* Header_addMeter(Header* this, MeterType* type, int param, HeaderSide side) {
Vector* meters = side == LEFT_HEADER
? this->leftMeters
: this->rightMeters;
void Header_writeBackToSettings(const Header* this) {
Settings_setHeaderLayout(this->settings, this->headerLayout);
Header_forEachColumn(this, col) {
MeterColumnSetting* colSettings = &this->settings->hColumns[col];
if (colSettings->names) {
for (size_t j = 0; j < colSettings->len; j++)
free(colSettings->names[j]);
free(colSettings->names);
}
free(colSettings->modes);
const Vector* vec = this->columns[col];
int len = Vector_size(vec);
colSettings->names = len ? xCalloc(len, sizeof(char*)) : NULL;
colSettings->modes = len ? xCalloc(len, sizeof(int)) : NULL;
colSettings->len = len;
for (int i = 0; i < len; i++) {
const Meter* meter = (Meter*) Vector_get(vec, i);
char* name;
if (meter->param && As_Meter(meter) == &DynamicMeter_class) {
const char* dynamic = DynamicMeter_lookup(this->pl->dynamicMeters, meter->param);
xAsprintf(&name, "%s(%s)", As_Meter(meter)->name, dynamic);
} else if (meter->param && As_Meter(meter) == &CPUMeter_class) {
xAsprintf(&name, "%s(%u)", As_Meter(meter)->name, meter->param);
} else {
xAsprintf(&name, "%s", As_Meter(meter)->name);
}
colSettings->names[i] = name;
colSettings->modes[i] = meter->mode;
}
}
}
Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, unsigned int column) {
assert(column < HeaderLayout_getColumns(this->headerLayout));
Vector* meters = this->columns[column];
Meter* meter = Meter_new(this->pl, param, type);
Vector_add(meters, meter);
return meter;
}
int Header_size(Header* this, HeaderSide side) {
Vector* meters = side == LEFT_HEADER
? this->leftMeters
: this->rightMeters;
return Vector_size(meters);
void Header_reinit(Header* this) {
Header_forEachColumn(this, col) {
for (int i = 0; i < Vector_size(this->columns[col]); i++) {
Meter* meter = (Meter*) Vector_get(this->columns[col], i);
if (Meter_initFn(meter)) {
Meter_init(meter);
}
}
}
}
char* Header_readMeterName(Header* this, int i, HeaderSide side) {
Vector* meters = side == LEFT_HEADER
? this->leftMeters
: this->rightMeters;
Meter* meter = (Meter*) Vector_get(meters, i);
int nameLen = strlen(meter->type->name);
int len = nameLen + 100;
char* name = malloc(len);
strncpy(name, meter->type->name, nameLen);
name[nameLen] = '\0';
if (meter->param)
snprintf(name + nameLen, len - nameLen, "(%d)", meter->param);
return name;
}
MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side) {
Vector* meters = side == LEFT_HEADER
? this->leftMeters
: this->rightMeters;
Meter* meter = (Meter*) Vector_get(meters, i);
return meter->mode;
}
void Header_defaultMeters(Header* this) {
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &AllCPUsMeter));
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &MemoryMeter));
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &SwapMeter));
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &TasksMeter));
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &LoadAverageMeter));
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &UptimeMeter));
}
void Header_draw(Header* this) {
int height = this->height;
int pad = this->pad;
void Header_draw(const Header* this) {
const int height = this->height;
const int pad = this->pad;
attrset(CRT_colors[RESET_COLOR]);
for (int y = 0; y < height; y++) {
mvhline(y, 0, ' ', COLS);
}
for (int y = (pad / 2), i = 0; i < Vector_size(this->leftMeters); i++) {
Meter* meter = (Meter*) Vector_get(this->leftMeters, i);
meter->draw(meter, pad, y, COLS / 2 - (pad * 2 - 1) - 1);
const int width = COLS - pad;
int x = pad;
float roundingLoss = 0.0f;
Header_forEachColumn(this, col) {
Vector* meters = this->columns[col];
float colWidth = (float)width * HeaderLayout_layouts[this->headerLayout].widths[col] / 100.0f;
roundingLoss += colWidth - floorf(colWidth);
if (roundingLoss >= 1.0f) {
colWidth += 1.0f;
roundingLoss -= 1.0f;
}
for (int y = (pad / 2), i = 0; i < Vector_size(meters); i++) {
Meter* meter = (Meter*) Vector_get(meters, i);
float actualWidth = colWidth;
if (meter->mode == TEXT_METERMODE) {
for (int j = 1; j < meter->columnWidthCount; j++) {
actualWidth += (float)width * HeaderLayout_layouts[this->headerLayout].widths[col + j] / 100.0f;
}
}
assert(meter->draw);
meter->draw(meter, x, y, floorf(actualWidth));
y += meter->h;
}
for (int y = (pad / 2), i = 0; i < Vector_size(this->rightMeters); i++) {
Meter* meter = (Meter*) Vector_get(this->rightMeters, i);
meter->draw(meter, COLS / 2 + pad, y, COLS / 2 - (pad * 2 - 1) - 1);
y += meter->h;
x += floorf(colWidth);
}
}
void Header_updateData(Header* this) {
Header_forEachColumn(this, col) {
Vector* meters = this->columns[col];
int items = Vector_size(meters);
for (int i = 0; i < items; i++) {
Meter* meter = (Meter*) Vector_get(meters, i);
Meter_updateValues(meter);
}
}
}
/*
* Calculate how many columns the current meter is allowed to span,
* by counting how many columns to the right are empty or contain a BlankMeter.
* Returns the number of columns to span, i.e. if the direct neighbor is occupied 1.
*/
static int calcColumnWidthCount(const Header* this, const Meter* curMeter, const int pad, const unsigned int curColumn, const int curHeight) {
for (size_t i = curColumn + 1; i < HeaderLayout_getColumns(this->headerLayout); i++) {
const Vector* meters = this->columns[i];
int height = pad;
for (int j = 0; j < Vector_size(meters); j++) {
const Meter* meter = (const Meter*) Vector_get(meters, j);
if (height >= curHeight + curMeter->h)
break;
height += meter->h;
if (height <= curHeight)
continue;
if (!Object_isA((const Object*) meter, (const ObjectClass*) &BlankMeter_class))
return i - curColumn;
}
}
return HeaderLayout_getColumns(this->headerLayout) - curColumn;
}
int Header_calculateHeight(Header* this) {
int pad = this->margin ? 2 : 0;
int leftHeight = pad;
int rightHeight = pad;
const int pad = this->settings->headerMargin ? 2 : 0;
int maxHeight = pad;
for (int i = 0; i < Vector_size(this->leftMeters); i++) {
Meter* meter = (Meter*) Vector_get(this->leftMeters, i);
leftHeight += meter->h;
Header_forEachColumn(this, col) {
const Vector* meters = this->columns[col];
int height = pad;
for (int i = 0; i < Vector_size(meters); i++) {
Meter* meter = (Meter*) Vector_get(meters, i);
meter->columnWidthCount = calcColumnWidthCount(this, meter, pad, col, height);
height += meter->h;
}
for (int i = 0; i < Vector_size(this->rightMeters); i++) {
Meter* meter = (Meter*) Vector_get(this->rightMeters, i);
rightHeight += meter->h;
maxHeight = MAXIMUM(maxHeight, height);
}
this->height = maxHeight;
this->pad = pad;
this->height = MAX(leftHeight, rightHeight);
return this->height;
return maxHeight;
}

View File

@ -1,58 +1,47 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Header
#define HEADER_Header
/*
htop - Header.h
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "HeaderLayout.h"
#include "Meter.h"
#include "ProcessList.h"
#include "Settings.h"
#include "Vector.h"
#include "debug.h"
#include <assert.h>
typedef enum HeaderSide_ {
LEFT_HEADER,
RIGHT_HEADER
} HeaderSide;
typedef struct Header_ {
Vector* leftMeters;
Vector* rightMeters;
Vector** columns;
Settings* settings;
ProcessList* pl;
bool margin;
int height;
HeaderLayout headerLayout;
int pad;
int height;
} Header;
#define Header_forEachColumn(this_, i_) for (size_t (i_)=0; (i_) < HeaderLayout_getColumns((this_)->headerLayout); ++(i_))
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
Header* Header_new(ProcessList* pl);
Header* Header_new(ProcessList* pl, Settings* settings, HeaderLayout hLayout);
void Header_delete(Header* this);
void Header_createMeter(Header* this, char* name, HeaderSide side);
void Header_setLayout(Header* this, HeaderLayout hLayout);
void Header_setMode(Header* this, int i, MeterModeId mode, HeaderSide side);
void Header_populateFromSettings(Header* this);
Meter* Header_addMeter(Header* this, MeterType* type, int param, HeaderSide side);
void Header_writeBackToSettings(const Header* this);
int Header_size(Header* this, HeaderSide side);
Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, unsigned int column);
char* Header_readMeterName(Header* this, int i, HeaderSide side);
void Header_reinit(Header* this);
MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side);
void Header_draw(const Header* this);
void Header_defaultMeters(Header* this);
void Header_draw(Header* this);
void Header_updateData(Header* this);
int Header_calculateHeight(Header* this);

77
HeaderLayout.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef HEADER_HeaderLayout
#define HEADER_HeaderLayout
/*
htop - HeaderLayout.h
(C) 2021 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "Macros.h"
#include "XUtils.h"
typedef enum HeaderLayout_ {
HF_TWO_50_50,
HF_TWO_33_67,
HF_TWO_67_33,
HF_THREE_33_34_33,
HF_THREE_25_25_50,
HF_THREE_25_50_25,
HF_THREE_50_25_25,
HF_THREE_40_20_40,
HF_FOUR_25_25_25_25,
LAST_HEADER_LAYOUT
} HeaderLayout;
static const struct {
uint8_t columns;
const uint8_t widths[4];
const char* name;
const char* description;
} HeaderLayout_layouts[LAST_HEADER_LAYOUT] = {
[HF_TWO_50_50] = { 2, { 50, 50, 0, 0 }, "two_50_50", "2 columns - 50/50 (default)", },
[HF_TWO_33_67] = { 2, { 33, 67, 0, 0 }, "two_33_67", "2 columns - 33/67", },
[HF_TWO_67_33] = { 2, { 67, 33, 0, 0 }, "two_67_33", "2 columns - 67/33", },
[HF_THREE_33_34_33] = { 3, { 33, 34, 33, 0 }, "three_33_34_33", "3 columns - 33/34/33", },
[HF_THREE_25_25_50] = { 3, { 25, 25, 50, 0 }, "three_25_25_50", "3 columns - 25/25/50", },
[HF_THREE_25_50_25] = { 3, { 25, 50, 25, 0 }, "three_25_50_25", "3 columns - 25/50/25", },
[HF_THREE_50_25_25] = { 3, { 50, 25, 25, 0 }, "three_50_25_25", "3 columns - 50/25/25", },
[HF_THREE_40_20_40] = { 3, { 40, 20, 40, 0 }, "three_40_20_40", "3 columns - 40/20/40", },
[HF_FOUR_25_25_25_25] = { 4, { 25, 25, 25, 25 }, "four_25_25_25_25", "4 columns - 25/25/25/25", },
};
static inline size_t HeaderLayout_getColumns(HeaderLayout hLayout) {
/* assert the layout is initialized */
assert(0 <= hLayout);
assert(hLayout < LAST_HEADER_LAYOUT);
assert(HeaderLayout_layouts[hLayout].name[0]);
assert(HeaderLayout_layouts[hLayout].description[0]);
return HeaderLayout_layouts[hLayout].columns;
}
static inline const char* HeaderLayout_getName(HeaderLayout hLayout) {
/* assert the layout is initialized */
assert(0 <= hLayout);
assert(hLayout < LAST_HEADER_LAYOUT);
assert(HeaderLayout_layouts[hLayout].name[0]);
assert(HeaderLayout_layouts[hLayout].description[0]);
return HeaderLayout_layouts[hLayout].name;
}
static inline HeaderLayout HeaderLayout_fromName(const char* name) {
for (size_t i = 0; i < LAST_HEADER_LAYOUT; i++) {
if (String_eq(HeaderLayout_layouts[i].name, name))
return (HeaderLayout) i;
}
return LAST_HEADER_LAYOUT;
}
#endif /* HEADER_HeaderLayout */

87
HeaderOptionsPanel.c Normal file
View File

@ -0,0 +1,87 @@
/*
htop - HeaderOptionsPanel.c
(C) 2021 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "HeaderOptionsPanel.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include "CRT.h"
#include "FunctionBar.h"
#include "Header.h"
#include "HeaderLayout.h"
#include "Object.h"
#include "OptionItem.h"
#include "ProvideCurses.h"
static const char* const HeaderOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
static void HeaderOptionsPanel_delete(Object* object) {
Panel* super = (Panel*) object;
HeaderOptionsPanel* this = (HeaderOptionsPanel*) object;
Panel_done(super);
free(this);
}
static HandlerResult HeaderOptionsPanel_eventHandler(Panel* super, int ch) {
HeaderOptionsPanel* this = (HeaderOptionsPanel*) super;
HandlerResult result = IGNORED;
int mark;
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
case KEY_MOUSE:
case KEY_RECLICK:
case ' ':
mark = Panel_getSelectedIndex(super);
assert(mark >= 0);
assert(mark < LAST_HEADER_LAYOUT);
for (int i = 0; i < LAST_HEADER_LAYOUT; i++)
CheckItem_set((CheckItem*)Panel_get(super, i), false);
CheckItem_set((CheckItem*)Panel_get(super, mark), true);
Header_setLayout(this->scr->header, mark);
this->settings->changed = true;
ScreenManager_resize(this->scr);
result = HANDLED;
}
return result;
}
const PanelClass HeaderOptionsPanel_class = {
.super = {
.extends = Class(Panel),
.delete = HeaderOptionsPanel_delete
},
.eventHandler = HeaderOptionsPanel_eventHandler
};
HeaderOptionsPanel* HeaderOptionsPanel_new(Settings* settings, ScreenManager* scr) {
HeaderOptionsPanel* this = AllocThis(HeaderOptionsPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(HeaderOptionsFunctions, NULL, NULL);
Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true, fuBar);
this->scr = scr;
this->settings = settings;
Panel_setHeader(super, "Header Layout");
for (int i = 0; i < LAST_HEADER_LAYOUT; i++) {
Panel_add(super, (Object*) CheckItem_newByVal(HeaderLayout_layouts[i].description, false));
}
CheckItem_set((CheckItem*)Panel_get(super, settings->hLayout), true);
return this;
}

26
HeaderOptionsPanel.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef HEADER_HeaderOptionsPanel
#define HEADER_HeaderOptionsPanel
/*
htop - ColorsPanel.h
(C) 2021 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Panel.h"
#include "ScreenManager.h"
#include "Settings.h"
typedef struct HeaderOptionsPanel_ {
Panel super;
ScreenManager* scr;
Settings* settings;
} HeaderOptionsPanel;
extern const PanelClass HeaderOptionsPanel_class;
HeaderOptionsPanel* HeaderOptionsPanel_new(Settings* settings, ScreenManager* scr);
#endif /* HEADER_HeaderOptionsPanel */

38
HostnameMeter.c Normal file
View File

@ -0,0 +1,38 @@
/*
htop - HostnameMeter.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "HostnameMeter.h"
#include "CRT.h"
#include "Object.h"
#include "Platform.h"
static const int HostnameMeter_attributes[] = {
HOSTNAME
};
static void HostnameMeter_updateValues(Meter* this) {
Platform_getHostname(this->txtBuffer, sizeof(this->txtBuffer));
}
const MeterClass HostnameMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete
},
.updateValues = HostnameMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 0,
.total = 100.0,
.attributes = HostnameMeter_attributes,
.name = "Hostname",
.uiName = "Hostname",
.caption = "Hostname: ",
};

15
HostnameMeter.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef HEADER_HostnameMeter
#define HEADER_HostnameMeter
/*
htop - HostnameMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
extern const MeterClass HostnameMeter_class;
#endif

229
INSTALL
View File

@ -1,229 +0,0 @@
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

234
IncSet.c Normal file
View File

@ -0,0 +1,234 @@
/*
htop - IncSet.c
(C) 2005-2012 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "IncSet.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "CRT.h"
#include "ListItem.h"
#include "Object.h"
#include "ProvideCurses.h"
#include "XUtils.h"
static void IncMode_reset(IncMode* mode) {
mode->index = 0;
mode->buffer[0] = 0;
}
void IncSet_reset(IncSet* this, IncType type) {
IncMode_reset(&this->modes[type]);
}
void IncSet_setFilter(IncSet* this, const char* filter) {
IncMode* mode = &this->modes[INC_FILTER];
size_t len = String_safeStrncpy(mode->buffer, filter, sizeof(mode->buffer));
mode->index = len;
this->filtering = true;
}
static const char* const searchFunctions[] = {"Next ", "Prev ", "Cancel ", " Search: ", NULL};
static const char* const searchKeys[] = {"F3", "S-F3", "Esc", " "};
static const int searchEvents[] = {KEY_F(3), KEY_F(15), 27, ERR};
static inline void IncMode_initSearch(IncMode* search) {
memset(search, 0, sizeof(IncMode));
search->bar = FunctionBar_new(searchFunctions, searchKeys, searchEvents);
search->isFilter = false;
}
static const char* const filterFunctions[] = {"Done ", "Clear ", " Filter: ", NULL};
static const char* const filterKeys[] = {"Enter", "Esc", " "};
static const int filterEvents[] = {13, 27, ERR};
static inline void IncMode_initFilter(IncMode* filter) {
memset(filter, 0, sizeof(IncMode));
filter->bar = FunctionBar_new(filterFunctions, filterKeys, filterEvents);
filter->isFilter = true;
}
static inline void IncMode_done(IncMode* mode) {
FunctionBar_delete(mode->bar);
}
IncSet* IncSet_new(FunctionBar* bar) {
IncSet* this = xMalloc(sizeof(IncSet));
IncMode_initSearch(&(this->modes[INC_SEARCH]));
IncMode_initFilter(&(this->modes[INC_FILTER]));
this->active = NULL;
this->defaultBar = bar;
this->filtering = false;
this->found = false;
return this;
}
void IncSet_delete(IncSet* this) {
IncMode_done(&(this->modes[0]));
IncMode_done(&(this->modes[1]));
free(this);
}
static void updateWeakPanel(const IncSet* this, Panel* panel, Vector* lines) {
const Object* selected = Panel_getSelected(panel);
Panel_prune(panel);
if (this->filtering) {
int n = 0;
const char* incFilter = this->modes[INC_FILTER].buffer;
for (int i = 0; i < Vector_size(lines); i++) {
ListItem* line = (ListItem*)Vector_get(lines, i);
if (String_contains_i(line->value, incFilter)) {
Panel_add(panel, (Object*)line);
if (selected == (Object*)line) {
Panel_setSelected(panel, n);
}
n++;
}
}
} else {
for (int i = 0; i < Vector_size(lines); i++) {
Object* line = Vector_get(lines, i);
Panel_add(panel, line);
if (selected == line) {
Panel_setSelected(panel, i);
}
}
}
}
static bool search(const IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue) {
int size = Panel_size(panel);
for (int i = 0; i < size; i++) {
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
Panel_setSelected(panel, i);
return true;
}
}
return false;
}
static bool IncMode_find(const IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue, int step) {
int size = Panel_size(panel);
int here = Panel_getSelectedIndex(panel);
int i = here;
for (;;) {
i += step;
if (i == size) {
i = 0;
}
if (i == -1) {
i = size - 1;
}
if (i == here) {
return false;
}
if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
Panel_setSelected(panel, i);
return true;
}
}
}
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) {
if (ch == ERR)
return true;
IncMode* mode = this->active;
int size = Panel_size(panel);
bool filterChanged = false;
bool doSearch = true;
if (ch == KEY_F(3) || ch == KEY_F(15)) {
if (size == 0)
return true;
IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1);
doSearch = false;
} else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) {
if (mode->index < INCMODE_MAX) {
mode->buffer[mode->index] = ch;
mode->index++;
mode->buffer[mode->index] = 0;
if (mode->isFilter) {
filterChanged = true;
if (mode->index == 1) {
this->filtering = true;
}
}
}
} else if (ch == KEY_BACKSPACE || ch == 127) {
if (mode->index > 0) {
mode->index--;
mode->buffer[mode->index] = 0;
if (mode->isFilter) {
filterChanged = true;
if (mode->index == 0) {
this->filtering = false;
IncMode_reset(mode);
}
}
} else {
doSearch = false;
}
} else if (ch == KEY_RESIZE) {
doSearch = (mode->index > 0);
} else {
if (mode->isFilter) {
filterChanged = true;
if (ch == 27) {
this->filtering = false;
IncMode_reset(mode);
}
} else {
if (ch == 27) {
IncMode_reset(mode);
}
}
this->active = NULL;
Panel_setDefaultBar(panel);
doSearch = false;
}
if (doSearch) {
this->found = search(mode, panel, getPanelValue);
}
if (filterChanged && lines) {
updateWeakPanel(this, panel, lines);
}
return filterChanged;
}
const char* IncSet_getListItemValue(Panel* panel, int i) {
const ListItem* l = (const ListItem*) Panel_get(panel, i);
return l ? l->value : "";
}
void IncSet_activate(IncSet* this, IncType type, Panel* panel) {
this->active = &(this->modes[type]);
panel->currentBar = this->active->bar;
}
void IncSet_drawBar(const IncSet* this) {
if (this->active) {
FunctionBar_drawExtra(this->active->bar, this->active->buffer, (this->active->isFilter || this->found) ? -1 : CRT_colors[FAILED_SEARCH], true);
} else {
FunctionBar_draw(this->defaultBar);
}
}
int IncSet_synthesizeEvent(IncSet* this, int x) {
if (this->active) {
return FunctionBar_synthesizeEvent(this->active->bar, x);
} else {
return FunctionBar_synthesizeEvent(this->defaultBar, x);
}
}

64
IncSet.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef HEADER_IncSet
#define HEADER_IncSet
/*
htop - IncSet.h
(C) 2005-2012 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include <stdbool.h>
#include <stddef.h>
#include "FunctionBar.h"
#include "Panel.h"
#include "Vector.h"
#define INCMODE_MAX 40
typedef enum {
INC_SEARCH = 0,
INC_FILTER = 1
} IncType;
typedef struct IncMode_ {
char buffer[INCMODE_MAX + 1];
int index;
FunctionBar* bar;
bool isFilter;
} IncMode;
typedef struct IncSet_ {
IncMode modes[2];
IncMode* active;
FunctionBar* defaultBar;
bool filtering;
bool found;
} IncSet;
static inline const char* IncSet_filter(const IncSet* this) {
return this->filtering ? this->modes[INC_FILTER].buffer : NULL;
}
void IncSet_setFilter(IncSet* this, const char* filter);
typedef const char* (*IncMode_GetPanelValue)(Panel*, int);
void IncSet_reset(IncSet* this, IncType type);
IncSet* IncSet_new(FunctionBar* bar);
void IncSet_delete(IncSet* this);
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines);
const char* IncSet_getListItemValue(Panel* panel, int i);
void IncSet_activate(IncSet* this, IncType type, Panel* panel);
void IncSet_drawBar(const IncSet* this);
int IncSet_synthesizeEvent(IncSet* this, int x);
#endif

183
InfoScreen.c Normal file
View File

@ -0,0 +1,183 @@
#include "config.h" // IWYU pragma: keep
#include "InfoScreen.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "CRT.h"
#include "IncSet.h"
#include "ListItem.h"
#include "Object.h"
#include "ProvideCurses.h"
#include "XUtils.h"
static const char* const InfoScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL};
static const char* const InfoScreenKeys[] = {"F3", "F4", "F5", "Esc"};
static const int InfoScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27};
InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBar* bar, int height, const char* panelHeader) {
this->process = process;
if (!bar) {
bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents);
}
this->display = Panel_new(0, 1, COLS, height, Class(ListItem), false, bar);
this->inc = IncSet_new(bar);
this->lines = Vector_new(Vector_type(this->display->items), true, DEFAULT_SIZE);
Panel_setHeader(this->display, panelHeader);
return this;
}
InfoScreen* InfoScreen_done(InfoScreen* this) {
Panel_delete((Object*)this->display);
IncSet_delete(this->inc);
Vector_delete(this->lines);
return this;
}
void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
char title[COLS + 1];
int len = vsnprintf(title, sizeof(title), fmt, ap);
va_end(ap);
if (len > COLS) {
memset(&title[COLS - 3], '.', 3);
}
attrset(CRT_colors[METER_TEXT]);
mvhline(0, 0, ' ', COLS);
mvaddstr(0, 0, title);
attrset(CRT_colors[DEFAULT_COLOR]);
Panel_draw(this->display, true, true, true, false);
IncSet_drawBar(this->inc);
}
void InfoScreen_addLine(InfoScreen* this, const char* line) {
Vector_add(this->lines, (Object*) ListItem_new(line, 0));
const char* incFilter = IncSet_filter(this->inc);
if (!incFilter || String_contains_i(line, incFilter)) {
Panel_add(this->display, Vector_get(this->lines, Vector_size(this->lines) - 1));
}
}
void InfoScreen_appendLine(InfoScreen* this, const char* line) {
ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines) - 1);
ListItem_append(last, line);
const char* incFilter = IncSet_filter(this->inc);
if (incFilter && Panel_get(this->display, Panel_size(this->display) - 1) != (Object*)last && String_contains_i(line, incFilter)) {
Panel_add(this->display, (Object*)last);
}
}
void InfoScreen_run(InfoScreen* this) {
Panel* panel = this->display;
if (As_InfoScreen(this)->scan)
InfoScreen_scan(this);
InfoScreen_draw(this);
bool looping = true;
while (looping) {
Panel_draw(panel, false, true, true, false);
IncSet_drawBar(this->inc);
if (this->inc->active) {
(void) move(LINES - 1, CRT_cursorX);
}
#ifdef HAVE_SET_ESCDELAY
set_escdelay(25);
#endif
int ch = getch();
if (ch == ERR) {
if (As_InfoScreen(this)->onErr) {
InfoScreen_onErr(this);
continue;
}
}
#ifdef HAVE_GETMOUSE
if (ch == KEY_MOUSE) {
MEVENT mevent;
int ok = getmouse(&mevent);
if (ok == OK) {
if (mevent.bstate & BUTTON1_RELEASED) {
if (mevent.y >= panel->y && mevent.y < LINES - 1) {
Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
ch = 0;
} else if (mevent.y == LINES - 1) {
ch = IncSet_synthesizeEvent(this->inc, mevent.x);
}
}
#if NCURSES_MOUSE_VERSION > 1
else if (mevent.bstate & BUTTON4_PRESSED) {
ch = KEY_WHEELUP;
} else if (mevent.bstate & BUTTON5_PRESSED) {
ch = KEY_WHEELDOWN;
}
#endif
}
}
#endif
if (this->inc->active) {
IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines);
continue;
}
switch(ch) {
case ERR:
continue;
case KEY_F(3):
case '/':
IncSet_activate(this->inc, INC_SEARCH, panel);
break;
case KEY_F(4):
case '\\':
IncSet_activate(this->inc, INC_FILTER, panel);
break;
case KEY_F(5):
clear();
if (As_InfoScreen(this)->scan) {
Vector_prune(this->lines);
InfoScreen_scan(this);
}
InfoScreen_draw(this);
break;
case '\014': // Ctrl+L
clear();
InfoScreen_draw(this);
break;
case 27:
case 'q':
case KEY_F(10):
looping = false;
break;
case KEY_RESIZE:
Panel_resize(panel, COLS, LINES - 2);
if (As_InfoScreen(this)->scan) {
Vector_prune(this->lines);
InfoScreen_scan(this);
}
InfoScreen_draw(this);
break;
default:
if (As_InfoScreen(this)->onKey && InfoScreen_onKey(this, ch)) {
continue;
}
Panel_onKey(panel, ch);
}
}
}

55
InfoScreen.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef HEADER_InfoScreen
#define HEADER_InfoScreen
#include <stdbool.h>
#include "FunctionBar.h"
#include "IncSet.h"
#include "Macros.h"
#include "Object.h"
#include "Panel.h"
#include "Process.h"
#include "Vector.h"
typedef struct InfoScreen_ {
Object super;
const Process* process;
Panel* display;
IncSet* inc;
Vector* lines;
} InfoScreen;
typedef void(*InfoScreen_Scan)(InfoScreen*);
typedef void(*InfoScreen_Draw)(InfoScreen*);
typedef void(*InfoScreen_OnErr)(InfoScreen*);
typedef bool(*InfoScreen_OnKey)(InfoScreen*, int);
typedef struct InfoScreenClass_ {
const ObjectClass super;
const InfoScreen_Scan scan;
const InfoScreen_Draw draw;
const InfoScreen_OnErr onErr;
const InfoScreen_OnKey onKey;
} InfoScreenClass;
#define As_InfoScreen(this_) ((const InfoScreenClass*)(((InfoScreen*)(this_))->super.klass))
#define InfoScreen_scan(this_) As_InfoScreen(this_)->scan((InfoScreen*)(this_))
#define InfoScreen_draw(this_) As_InfoScreen(this_)->draw((InfoScreen*)(this_))
#define InfoScreen_onErr(this_) As_InfoScreen(this_)->onErr((InfoScreen*)(this_))
#define InfoScreen_onKey(this_, ch_) As_InfoScreen(this_)->onKey((InfoScreen*)(this_), ch_)
InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBar* bar, int height, const char* panelHeader);
InfoScreen* InfoScreen_done(InfoScreen* this);
ATTR_FORMAT(printf, 2, 3)
void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...);
void InfoScreen_addLine(InfoScreen* this, const char* line);
void InfoScreen_appendLine(InfoScreen* this, const char* line);
void InfoScreen_run(InfoScreen* this);
#endif

View File

@ -1,73 +1,68 @@
/*
htop - ListItem.c
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "ListItem.h"
#include "String.h"
#include "Object.h"
#include "RichString.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "CRT.h"
#include "RichString.h"
#include "XUtils.h"
/*{
typedef struct ListItem_ {
Object super;
char* value;
int key;
} ListItem;
}*/
#ifdef DEBUG
char* LISTITEM_CLASS = "ListItem";
#else
#define LISTITEM_CLASS NULL
#endif
ListItem* ListItem_new(char* value, int key) {
ListItem* this = malloc(sizeof(ListItem));
Object_setClass(this, LISTITEM_CLASS);
((Object*)this)->display = ListItem_display;
((Object*)this)->delete = ListItem_delete;
this->value = String_copy(value);
this->key = key;
return this;
}
void ListItem_append(ListItem* this, char* text) {
char* buf = malloc(strlen(this->value) + strlen(text) + 1);
sprintf(buf, "%s%s", this->value, text);
free(this->value);
this->value = buf;
}
void ListItem_delete(Object* cast) {
static void ListItem_delete(Object* cast) {
ListItem* this = (ListItem*)cast;
free(this->value);
free(this);
}
void ListItem_display(Object* cast, RichString* out) {
ListItem* this = (ListItem*)cast;
static void ListItem_display(const Object* cast, RichString* out) {
const ListItem* const this = (const ListItem*)cast;
assert (this != NULL);
int len = strlen(this->value)+1;
char buffer[len+1];
snprintf(buffer, len, "%s", this->value);
RichString_write(out, CRT_colors[DEFAULT_COLOR], buffer);
if (this->moving) {
RichString_writeWide(out, CRT_colors[DEFAULT_COLOR],
#ifdef HAVE_LIBNCURSESW
CRT_utf8 ? "" :
#endif
"+ ");
}
RichString_appendWide(out, CRT_colors[DEFAULT_COLOR], this->value);
}
const char* ListItem_getRef(ListItem* this) {
return this->value;
ListItem* ListItem_new(const char* value, int key) {
ListItem* this = AllocThis(ListItem);
this->value = xStrdup(value);
this->key = key;
this->moving = false;
return this;
}
int ListItem_compare(const void* cast1, const void* cast2) {
ListItem* obj1 = (ListItem*) cast1;
ListItem* obj2 = (ListItem*) cast2;
void ListItem_append(ListItem* this, const char* text) {
size_t oldLen = strlen(this->value);
size_t textLen = strlen(text);
size_t newLen = oldLen + textLen;
this->value = xRealloc(this->value, newLen + 1);
memcpy(this->value + oldLen, text, textLen);
this->value[newLen] = '\0';
}
static int ListItem_compare(const void* cast1, const void* cast2) {
const ListItem* obj1 = (const ListItem*) cast1;
const ListItem* obj2 = (const ListItem*) cast2;
return strcmp(obj1->value, obj2->value);
}
const ObjectClass ListItem_class = {
.display = ListItem_display,
.delete = ListItem_delete,
.compare = ListItem_compare
};

View File

@ -1,46 +1,32 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ListItem
#define HEADER_ListItem
/*
htop - ListItem.h
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "String.h"
#include "Object.h"
#include "RichString.h"
#include <string.h>
#include <stdbool.h>
#include "debug.h"
#include "Object.h"
typedef struct ListItem_ {
Object super;
char* value;
int key;
bool moving;
} ListItem;
extern const ObjectClass ListItem_class;
#ifdef DEBUG
extern char* LISTITEM_CLASS;
#else
#define LISTITEM_CLASS NULL
#endif
ListItem* ListItem_new(const char* value, int key);
ListItem* ListItem_new(char* value, int key);
void ListItem_append(ListItem* this, char* text);
void ListItem_delete(Object* cast);
void ListItem_display(Object* cast, RichString* out);
const char* ListItem_getRef(ListItem* this);
int ListItem_compare(const void* cast1, const void* cast2);
void ListItem_append(ListItem* this, const char* text);
static inline const char* ListItem_getRef(const ListItem* this) {
return this->value;
}
#endif

View File

@ -1,87 +1,134 @@
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - LoadAverageMeter.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "LoadAverageMeter.h"
#include "Meter.h"
#include <curses.h>
#include "CRT.h"
#include "Object.h"
#include "Platform.h"
#include "ProcessList.h"
#include "RichString.h"
#include "XUtils.h"
#include "debug.h"
int LoadAverageMeter_attributes[] = {
LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_ONE
static const int LoadAverageMeter_attributes[] = {
LOAD_AVERAGE_ONE,
LOAD_AVERAGE_FIVE,
LOAD_AVERAGE_FIFTEEN
};
MeterType LoadAverageMeter = {
.setValues = LoadAverageMeter_setValues,
static const int LoadMeter_attributes[] = {
LOAD
};
static const int OK_attributes[] = {
METER_VALUE_OK
};
static const int Medium_attributes[] = {
METER_VALUE_WARN
};
static const int High_attributes[] = {
METER_VALUE_ERROR
};
static void LoadAverageMeter_updateValues(Meter* this) {
Platform_getLoadAverage(&this->values[0], &this->values[1], &this->values[2]);
// only show bar for 1min value
this->curItems = 1;
// change bar color and total based on value
if (this->values[0] < 1.0) {
this->curAttributes = OK_attributes;
this->total = 1.0;
} else if (this->values[0] < this->pl->activeCPUs) {
this->curAttributes = Medium_attributes;
this->total = this->pl->activeCPUs;
} else {
this->curAttributes = High_attributes;
this->total = 2 * this->pl->activeCPUs;
}
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.2f/%.2f/%.2f", this->values[0], this->values[1], this->values[2]);
}
static void LoadAverageMeter_display(const Object* cast, RichString* out) {
const Meter* this = (const Meter*)cast;
char buffer[20];
int len;
len = xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[0]);
RichString_appendnAscii(out, CRT_colors[LOAD_AVERAGE_ONE], buffer, len);
len = xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[1]);
RichString_appendnAscii(out, CRT_colors[LOAD_AVERAGE_FIVE], buffer, len);
len = xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[2]);
RichString_appendnAscii(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer, len);
}
static void LoadMeter_updateValues(Meter* this) {
double five, fifteen;
Platform_getLoadAverage(&this->values[0], &five, &fifteen);
// change bar color and total based on value
if (this->values[0] < 1.0) {
this->curAttributes = OK_attributes;
this->total = 1.0;
} else if (this->values[0] < this->pl->activeCPUs) {
this->curAttributes = Medium_attributes;
this->total = this->pl->activeCPUs;
} else {
this->curAttributes = High_attributes;
this->total = 2 * this->pl->activeCPUs;
}
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.2f", this->values[0]);
}
static void LoadMeter_display(const Object* cast, RichString* out) {
const Meter* this = (const Meter*)cast;
char buffer[20];
int len;
len = xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[0]);
RichString_appendnAscii(out, CRT_colors[LOAD], buffer, len);
}
const MeterClass LoadAverageMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = LoadAverageMeter_display,
.mode = TEXT_METERMODE,
.items = 3,
},
.updateValues = LoadAverageMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 3,
.total = 100.0,
.attributes = LoadAverageMeter_attributes,
.name = "LoadAverage",
.uiName = "Load average",
.description = "Load averages: 1 minute, 5 minutes, 15 minutes",
.caption = "Load average: "
};
int LoadMeter_attributes[] = { LOAD };
MeterType LoadMeter = {
.setValues = LoadMeter_setValues,
const MeterClass LoadMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = LoadMeter_display,
.mode = TEXT_METERMODE,
.items = 1,
},
.updateValues = LoadMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 1,
.total = 100.0,
.attributes = LoadMeter_attributes,
.name = "Load",
.uiName = "Load",
.description = "Load: average of ready processes in the last minute",
.caption = "Load: "
};
static inline void LoadAverageMeter_scan(double* one, double* five, double* fifteen) {
int activeProcs, totalProcs, lastProc;
FILE *fd = fopen(PROCDIR "/loadavg", "r");
int read = fscanf(fd, "%lf %lf %lf %d/%d %d", one, five, fifteen,
&activeProcs, &totalProcs, &lastProc);
(void) read;
assert(read == 6);
fclose(fd);
}
void LoadAverageMeter_setValues(Meter* this, char* buffer, int size) {
LoadAverageMeter_scan(&this->values[2], &this->values[1], &this->values[0]);
snprintf(buffer, size, "%.2f/%.2f/%.2f", this->values[2], this->values[1], this->values[0]);
}
void LoadAverageMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast;
char buffer[20];
RichString_init(out);
sprintf(buffer, "%.2f ", this->values[2]);
RichString_append(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer);
sprintf(buffer, "%.2f ", this->values[1]);
RichString_append(out, CRT_colors[LOAD_AVERAGE_FIVE], buffer);
sprintf(buffer, "%.2f ", this->values[0]);
RichString_append(out, CRT_colors[LOAD_AVERAGE_ONE], buffer);
}
void LoadMeter_setValues(Meter* this, char* buffer, int size) {
double five, fifteen;
LoadAverageMeter_scan(&this->values[0], &five, &fifteen);
if (this->values[0] > this->total) {
this->total = this->values[0];
}
snprintf(buffer, size, "%.2f", this->values[0]);
}
void LoadMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast;
char buffer[20];
RichString_init(out);
sprintf(buffer, "%.2f ", ((Meter*)this)->values[0]);
RichString_append(out, CRT_colors[LOAD], buffer);
}

View File

@ -1,34 +1,17 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_LoadAverageMeter
#define HEADER_LoadAverageMeter
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - LoadAverageMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
#include <curses.h>
#include "debug.h"
extern const MeterClass LoadAverageMeter_class;
extern int LoadAverageMeter_attributes[];
extern MeterType LoadAverageMeter;
extern int LoadMeter_attributes[];
extern MeterType LoadMeter;
void LoadAverageMeter_setValues(Meter* this, char* buffer, int size);
void LoadAverageMeter_display(Object* cast, RichString* out);
void LoadMeter_setValues(Meter* this, char* buffer, int size);
void LoadMeter_display(Object* cast, RichString* out);
extern const MeterClass LoadMeter_class;
#endif

85
Macros.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef HEADER_Macros
#define HEADER_Macros
#include <assert.h> // IWYU pragma: keep
#ifndef MINIMUM
#define MINIMUM(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAXIMUM
#define MAXIMUM(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef CLAMP
#define CLAMP(x, low, high) (assert((low) <= (high)), ((x) > (high)) ? (high) : MAXIMUM(x, low))
#endif
#ifndef ARRAYSIZE
#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
#ifndef SPACESHIP_NUMBER
#define SPACESHIP_NUMBER(a, b) (((a) > (b)) - ((a) < (b)))
#endif
#ifndef SPACESHIP_NULLSTR
#define SPACESHIP_NULLSTR(a, b) strcmp((a) ? (a) : "", (b) ? (b) : "")
#endif
#ifndef SPACESHIP_DEFAULTSTR
#define SPACESHIP_DEFAULTSTR(a, b, s) strcmp((a) ? (a) : (s), (b) ? (b) : (s))
#endif
#ifdef __GNUC__ // defined by GCC and Clang
#define ATTR_FORMAT(type, index, check) __attribute__((format (type, index, check)))
#define ATTR_NONNULL __attribute__((nonnull))
#define ATTR_NORETURN __attribute__((noreturn))
#define ATTR_UNUSED __attribute__((unused))
#define ATTR_MALLOC __attribute__((malloc))
#else /* __GNUC__ */
#define ATTR_FORMAT(type, index, check)
#define ATTR_NONNULL
#define ATTR_NORETURN
#define ATTR_UNUSED
#define ATTR_MALLOC
#endif /* __GNUC__ */
#ifdef HAVE_ATTR_ALLOC_SIZE
#define ATTR_ALLOC_SIZE1(a) __attribute__((alloc_size (a)))
#define ATTR_ALLOC_SIZE2(a, b) __attribute__((alloc_size (a, b)))
#else
#define ATTR_ALLOC_SIZE1(a)
#define ATTR_ALLOC_SIZE2(a, b)
#endif /* HAVE_ATTR_ALLOC_SIZE */
// ignore casts discarding const specifier, e.g.
// const char [] -> char * / void *
// const char *[2]' -> char *const *
#if defined(__clang__)
#define IGNORE_WCASTQUAL_BEGIN _Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wcast-qual\"")
#define IGNORE_WCASTQUAL_END _Pragma("clang diagnostic pop")
#elif defined(__GNUC__)
#define IGNORE_WCASTQUAL_BEGIN _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
#define IGNORE_WCASTQUAL_END _Pragma("GCC diagnostic pop")
#else
#define IGNORE_WCASTQUAL_BEGIN
#define IGNORE_WCASTQUAL_END
#endif
/* This subtraction is used by Linux / NetBSD / OpenBSD for calculation of CPU usage items. */
static inline unsigned long long saturatingSub(unsigned long long a, unsigned long long b) {
return a > b ? a - b : 0;
}
#endif

223
MainPanel.c Normal file
View File

@ -0,0 +1,223 @@
/*
htop - ColumnsPanel.c
(C) 2004-2015 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "MainPanel.h"
#include <ctype.h>
#include <stdlib.h>
#include "CRT.h"
#include "FunctionBar.h"
#include "Platform.h"
#include "Process.h"
#include "ProcessList.h"
#include "ProvideCurses.h"
#include "Settings.h"
#include "XUtils.h"
static const char* const MainFunctions[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", "Nice -", "Nice +", "Kill ", "Quit ", NULL};
static const char* const MainFunctions_ro[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", " ", " ", " ", "Quit ", NULL};
void MainPanel_updateTreeFunctions(MainPanel* this, bool mode) {
FunctionBar* bar = MainPanel_getFunctionBar(this);
FunctionBar_setLabel(bar, KEY_F(5), mode ? "List " : "Tree ");
}
static void MainPanel_pidSearch(MainPanel* this, int ch) {
Panel* super = (Panel*) this;
pid_t pid = ch - 48 + this->pidSearch;
for (int i = 0; i < Panel_size(super); i++) {
const Process* p = (const Process*) Panel_get(super, i);
if (p && p->pid == pid) {
Panel_setSelected(super, i);
break;
}
}
this->pidSearch = pid * 10;
if (this->pidSearch > 10000000) {
this->pidSearch = 0;
}
}
static const char* MainPanel_getValue(Panel* this, int i) {
const Process* p = (const Process*) Panel_get(this, i);
return Process_getCommand(p);
}
static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
MainPanel* this = (MainPanel*) super;
HandlerResult result = IGNORED;
Htop_Reaction reaction = HTOP_OK;
/* Let supervising ScreenManager handle resize */
if (ch == KEY_RESIZE)
return IGNORED;
/* reset on every normal key */
if (ch != ERR)
this->state->hideProcessSelection = false;
if (EVENT_IS_HEADER_CLICK(ch)) {
int x = EVENT_HEADER_CLICK_GET_X(ch);
const ProcessList* pl = this->state->pl;
Settings* settings = this->state->settings;
int hx = super->scrollH + x + 1;
ProcessField field = ProcessList_keyAt(pl, hx);
if (settings->treeView && settings->treeViewAlwaysByPID) {
settings->treeView = false;
settings->direction = 1;
reaction |= Action_setSortKey(settings, field);
} else if (field == Settings_getActiveSortKey(settings)) {
Settings_invertSortOrder(settings);
} else {
reaction |= Action_setSortKey(settings, field);
}
reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS;
result = HANDLED;
} else if (ch != ERR && this->inc->active) {
bool filterChanged = IncSet_handleKey(this->inc, ch, super, MainPanel_getValue, NULL);
if (filterChanged) {
this->state->pl->incFilter = IncSet_filter(this->inc);
reaction = HTOP_REFRESH | HTOP_REDRAW_BAR;
}
if (this->inc->found) {
reaction |= Action_follow(this->state);
reaction |= HTOP_KEEP_FOLLOWING;
}
result = HANDLED;
} else if (ch == 27) {
this->state->hideProcessSelection = true;
return HANDLED;
} else if (ch != ERR && ch > 0 && ch < KEY_MAX && this->keys[ch]) {
reaction |= (this->keys[ch])(this->state);
result = HANDLED;
} else if (0 < ch && ch < 255 && isdigit((unsigned char)ch)) {
MainPanel_pidSearch(this, ch);
} else {
if (ch != ERR) {
this->pidSearch = 0;
} else {
reaction |= HTOP_KEEP_FOLLOWING;
}
}
if (reaction & HTOP_REDRAW_BAR) {
MainPanel_updateTreeFunctions(this, this->state->settings->treeView);
}
if (reaction & HTOP_RESIZE) {
result |= RESIZE;
}
if (reaction & HTOP_UPDATE_PANELHDR) {
result |= REDRAW;
}
if (reaction & HTOP_REFRESH) {
result |= REFRESH;
}
if (reaction & HTOP_RECALCULATE) {
result |= RESCAN;
}
if (reaction & HTOP_SAVE_SETTINGS) {
this->state->settings->changed = true;
}
if (reaction & HTOP_QUIT) {
return BREAK_LOOP;
}
if (!(reaction & HTOP_KEEP_FOLLOWING)) {
this->state->pl->following = -1;
Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS);
}
return result;
}
int MainPanel_selectedPid(MainPanel* this) {
const Process* p = (const Process*) Panel_getSelected((Panel*)this);
if (p) {
return p->pid;
}
return -1;
}
bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged) {
Panel* super = (Panel*) this;
bool ok = true;
bool anyTagged = false;
for (int i = 0; i < Panel_size(super); i++) {
Process* p = (Process*) Panel_get(super, i);
if (p->tag) {
ok = fn(p, arg) && ok;
anyTagged = true;
}
}
if (!anyTagged) {
Process* p = (Process*) Panel_getSelected(super);
if (p) {
ok &= fn(p, arg);
}
}
if (wasAnyTagged)
*wasAnyTagged = anyTagged;
return ok;
}
static void MainPanel_drawFunctionBar(Panel* super, bool hideFunctionBar) {
MainPanel* this = (MainPanel*) super;
// Do not hide active search and filter bar.
if (hideFunctionBar && !this->inc->active)
return;
IncSet_drawBar(this->inc);
if (this->state->pauseProcessUpdate) {
FunctionBar_append("PAUSED", CRT_colors[PAUSED]);
}
}
static void MainPanel_printHeader(Panel* super) {
MainPanel* this = (MainPanel*) super;
ProcessList_printHeader(this->state->pl, &super->header);
}
const PanelClass MainPanel_class = {
.super = {
.extends = Class(Panel),
.delete = MainPanel_delete
},
.eventHandler = MainPanel_eventHandler,
.drawFunctionBar = MainPanel_drawFunctionBar,
.printHeader = MainPanel_printHeader
};
MainPanel* MainPanel_new() {
MainPanel* this = AllocThis(MainPanel);
Panel_init((Panel*) this, 1, 1, 1, 1, Class(Process), false, FunctionBar_new(Settings_isReadonly() ? MainFunctions_ro : MainFunctions, NULL, NULL));
this->keys = xCalloc(KEY_MAX, sizeof(Htop_Action));
this->inc = IncSet_new(MainPanel_getFunctionBar(this));
Action_setBindings(this->keys);
Platform_setBindings(this->keys);
return this;
}
void MainPanel_setState(MainPanel* this, State* state) {
this->state = state;
}
void MainPanel_delete(Object* object) {
Panel* super = (Panel*) object;
MainPanel* this = (MainPanel*) object;
Panel_done(super);
IncSet_delete(this->inc);
free(this->keys);
free(this);
}

49
MainPanel.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef HEADER_MainPanel
#define HEADER_MainPanel
/*
htop - ColumnsPanel.h
(C) 2004-2015 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include <stdbool.h>
#include <sys/types.h>
#include "Action.h"
#include "IncSet.h"
#include "Object.h"
#include "Panel.h"
#include "Process.h"
typedef struct MainPanel_ {
Panel super;
State* state;
IncSet* inc;
Htop_Action* keys;
pid_t pidSearch;
} MainPanel;
typedef bool(*MainPanel_ForeachProcessFn)(Process*, Arg);
#define MainPanel_getFunctionBar(this_) (((Panel*)(this_))->defaultBar)
void MainPanel_updateTreeFunctions(MainPanel* this, bool mode);
int MainPanel_selectedPid(MainPanel* this);
bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged);
extern const PanelClass MainPanel_class;
MainPanel* MainPanel_new(void);
void MainPanel_setState(MainPanel* this, State* state);
void MainPanel_delete(Object* object);
#endif

View File

@ -1,52 +1,457 @@
bin_PROGRAMS = htop
dist_man_MANS = htop.1
EXTRA_DIST = $(dist_man_MANS) htop.desktop htop.png scripts/MakeHeader.py \
install-sh autogen.sh missing
EXTRA_DIST = \
$(dist_man_MANS) \
autogen.sh \
htop.desktop \
htop.png \
htop.svg \
build-aux/compile \
build-aux/depcomp \
build-aux/install-sh \
build-aux/missing
applicationsdir = $(datadir)/applications
applications_DATA = htop.desktop
pixmapdir = $(datadir)/pixmaps
pixmap_DATA = htop.png
appicondir = $(datadir)/icons/hicolor/scalable/apps
appicon_DATA = htop.svg
AM_CFLAGS = -pedantic -Wall -std=c99
AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\"
AM_CFLAGS += -pedantic -std=c99 -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR="\"$(sysconfdir)\"" -I"$(top_srcdir)/$(my_htop_platform)"
AM_LDFLAGS =
myhtopsources = AvailableMetersPanel.c CategoriesPanel.c CheckItem.c \
ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c DebugMemory.c \
DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \
LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \
Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
SignalItem.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \
UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c
myhtopsources = \
Action.c \
Affinity.c \
AffinityPanel.c \
AvailableColumnsPanel.c \
AvailableMetersPanel.c \
BatteryMeter.c \
CategoriesPanel.c \
ClockMeter.c \
ColorsPanel.c \
ColumnsPanel.c \
CommandLine.c \
CommandScreen.c \
Compat.c \
CPUMeter.c \
CRT.c \
DateMeter.c \
DateTimeMeter.c \
DiskIOMeter.c \
DisplayOptionsPanel.c \
DynamicColumn.c \
DynamicMeter.c \
EnvScreen.c \
FunctionBar.c \
Hashtable.c \
Header.c \
HeaderOptionsPanel.c \
HostnameMeter.c \
IncSet.c \
InfoScreen.c \
ListItem.c \
LoadAverageMeter.c \
MainPanel.c \
MemoryMeter.c \
MemorySwapMeter.c \
Meter.c \
MetersPanel.c \
NetworkIOMeter.c \
Object.c \
OpenFilesScreen.c \
OptionItem.c \
Panel.c \
Process.c \
ProcessList.c \
ProcessLocksScreen.c \
RichString.c \
ScreenManager.c \
Settings.c \
SignalsPanel.c \
SwapMeter.c \
SysArchMeter.c \
TasksMeter.c \
TraceScreen.c \
UptimeMeter.c \
UsersTable.c \
Vector.c \
XUtils.c
myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \
CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
CPUMeter.h CRT.h DebugMemory.h DisplayOptionsPanel.h FunctionBar.h \
Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \
Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
ScreenManager.h Settings.h SignalItem.h SignalsPanel.h String.h \
SwapMeter.h TasksMeter.h TraceScreen.h UptimeMeter.h UsersTable.h Vector.h \
Process.h AffinityPanel.h
myhtopheaders = \
Action.h \
Affinity.h \
AffinityPanel.h \
AvailableColumnsPanel.h \
AvailableMetersPanel.h \
BatteryMeter.h \
CPUMeter.h \
CRT.h \
CategoriesPanel.h \
ClockMeter.h \
ColorsPanel.h \
ColumnsPanel.h \
CommandLine.h \
CommandScreen.h \
Compat.h \
DateMeter.h \
DateTimeMeter.h \
DiskIOMeter.h \
DisplayOptionsPanel.h \
DynamicColumn.h \
DynamicMeter.h \
EnvScreen.h \
FunctionBar.h \
Hashtable.h \
Header.h \
HeaderLayout.h \
HeaderOptionsPanel.h \
HostnameMeter.h \
IncSet.h \
InfoScreen.h \
ListItem.h \
LoadAverageMeter.h \
Macros.h \
MainPanel.h \
MemoryMeter.h \
MemorySwapMeter.h \
Meter.h \
MetersPanel.h \
NetworkIOMeter.h \
Object.h \
OpenFilesScreen.h \
OptionItem.h \
Panel.h \
Process.h \
ProcessList.h \
ProcessLocksScreen.h \
ProvideCurses.h \
RichString.h \
ScreenManager.h \
Settings.h \
SignalsPanel.h \
SwapMeter.h \
SysArchMeter.h \
TasksMeter.h \
TraceScreen.h \
UptimeMeter.h \
UsersTable.h \
Vector.h \
XUtils.h
SUFFIXES = .h
# Linux
# -----
BUILT_SOURCES = $(myhtopheaders)
htop_SOURCES = $(myhtopheaders) $(myhtopsources) config.h debug.h
linux_platform_headers = \
generic/gettime.h \
generic/hostname.h \
generic/uname.h \
linux/HugePageMeter.h \
linux/IOPriority.h \
linux/IOPriorityPanel.h \
linux/LibSensors.h \
linux/LinuxProcess.h \
linux/LinuxProcessList.h \
linux/Platform.h \
linux/PressureStallMeter.h \
linux/ProcessField.h \
linux/SELinuxMeter.h \
linux/SystemdMeter.h \
linux/ZramMeter.h \
linux/ZramStats.h \
zfs/ZfsArcMeter.h \
zfs/ZfsArcStats.h \
zfs/ZfsCompressedArcMeter.h
linux_platform_sources = \
generic/gettime.c \
generic/hostname.c \
generic/uname.c \
linux/HugePageMeter.c \
linux/IOPriorityPanel.c \
linux/LibSensors.c \
linux/LinuxProcess.c \
linux/LinuxProcessList.c \
linux/Platform.c \
linux/PressureStallMeter.c \
linux/SELinuxMeter.c \
linux/SystemdMeter.c \
linux/ZramMeter.c \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c
if HTOP_LINUX
AM_LDFLAGS += -rdynamic
myhtopplatprogram = htop
myhtopplatheaders = $(linux_platform_headers)
myhtopplatsources = $(linux_platform_sources)
endif
# FreeBSD
# -------
freebsd_platform_headers = \
freebsd/FreeBSDProcessList.h \
freebsd/FreeBSDProcess.h \
freebsd/Platform.h \
freebsd/ProcessField.h \
generic/gettime.h \
generic/hostname.h \
generic/openzfs_sysctl.h \
generic/uname.h \
zfs/ZfsArcMeter.h \
zfs/ZfsArcStats.h \
zfs/ZfsCompressedArcMeter.h
freebsd_platform_sources = \
freebsd/Platform.c \
freebsd/FreeBSDProcessList.c \
freebsd/FreeBSDProcess.c \
generic/gettime.c \
generic/hostname.c \
generic/openzfs_sysctl.c \
generic/uname.c \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c
if HTOP_FREEBSD
myhtopplatprogram = htop
myhtopplatheaders = $(freebsd_platform_headers)
myhtopplatsources = $(freebsd_platform_sources)
endif
# DragonFlyBSD
# ------------
dragonflybsd_platform_headers = \
dragonflybsd/DragonFlyBSDProcessList.h \
dragonflybsd/DragonFlyBSDProcess.h \
dragonflybsd/Platform.h \
dragonflybsd/ProcessField.h \
generic/gettime.h \
generic/hostname.h \
generic/uname.h
dragonflybsd_platform_sources = \
dragonflybsd/DragonFlyBSDProcessList.c \
dragonflybsd/DragonFlyBSDProcess.c \
dragonflybsd/Platform.c \
generic/gettime.c \
generic/hostname.c \
generic/uname.c
if HTOP_DRAGONFLYBSD
myhtopplatprogram = htop
myhtopplatheaders = $(dragonflybsd_platform_headers)
myhtopplatsources = $(dragonflybsd_platform_sources)
endif
# NetBSD
# -------
netbsd_platform_headers = \
generic/gettime.h \
generic/hostname.h \
generic/uname.h \
netbsd/Platform.h \
netbsd/ProcessField.h \
netbsd/NetBSDProcess.h \
netbsd/NetBSDProcessList.h
netbsd_platform_sources = \
generic/gettime.c \
generic/hostname.c \
generic/uname.c \
netbsd/Platform.c \
netbsd/NetBSDProcess.c \
netbsd/NetBSDProcessList.c
if HTOP_NETBSD
myhtopplatprogram = htop
myhtopplatheaders = $(netbsd_platform_headers)
myhtopplatsources = $(netbsd_platform_sources)
endif
# OpenBSD
# -------
openbsd_platform_headers = \
generic/gettime.h \
generic/hostname.h \
generic/uname.h \
openbsd/OpenBSDProcessList.h \
openbsd/OpenBSDProcess.h \
openbsd/Platform.h \
openbsd/ProcessField.h
openbsd_platform_sources = \
generic/gettime.c \
generic/hostname.c \
generic/uname.c \
openbsd/OpenBSDProcessList.c \
openbsd/OpenBSDProcess.c \
openbsd/Platform.c
if HTOP_OPENBSD
myhtopplatprogram = htop
myhtopplatheaders = $(openbsd_platform_headers)
myhtopplatsources = $(openbsd_platform_sources)
endif
# Darwin
# ------
darwin_platform_headers = \
darwin/DarwinProcess.h \
darwin/DarwinProcessList.h \
darwin/Platform.h \
darwin/ProcessField.h \
generic/gettime.h \
generic/hostname.h \
generic/openzfs_sysctl.h \
generic/uname.h \
zfs/ZfsArcMeter.h \
zfs/ZfsArcStats.h \
zfs/ZfsCompressedArcMeter.h
darwin_platform_sources = \
darwin/Platform.c \
darwin/DarwinProcess.c \
darwin/DarwinProcessList.c \
generic/gettime.c \
generic/hostname.c \
generic/openzfs_sysctl.c \
generic/uname.c \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c
if HTOP_DARWIN
AM_LDFLAGS += -framework IOKit -framework CoreFoundation
myhtopplatprogram = htop
myhtopplatheaders = $(darwin_platform_headers)
myhtopplatsources = $(darwin_platform_sources)
endif
# Solaris
# -------
solaris_platform_headers = \
generic/gettime.h \
generic/hostname.h \
generic/uname.h \
solaris/ProcessField.h \
solaris/Platform.h \
solaris/SolarisProcess.h \
solaris/SolarisProcessList.h \
zfs/ZfsArcMeter.h \
zfs/ZfsArcStats.h \
zfs/ZfsCompressedArcMeter.h
solaris_platform_sources = \
generic/gettime.c \
generic/hostname.c \
generic/uname.c \
solaris/Platform.c \
solaris/SolarisProcess.c \
solaris/SolarisProcessList.c \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c
if HTOP_SOLARIS
myhtopplatprogram = htop
myhtopplatheaders = $(solaris_platform_headers)
myhtopplatsources = $(solaris_platform_sources)
endif
# Performance Co-Pilot (PCP)
# --------------------------
pcp_platform_headers = \
linux/PressureStallMeter.h \
linux/ZramMeter.h \
linux/ZramStats.h \
pcp/PCPDynamicColumn.h \
pcp/PCPDynamicMeter.h \
pcp/PCPMetric.h \
pcp/PCPProcess.h \
pcp/PCPProcessList.h \
pcp/Platform.h \
pcp/ProcessField.h \
zfs/ZfsArcMeter.h \
zfs/ZfsArcStats.h \
zfs/ZfsCompressedArcMeter.h
pcp_platform_sources = \
linux/PressureStallMeter.c \
linux/ZramMeter.c \
pcp/PCPDynamicColumn.c \
pcp/PCPDynamicMeter.c \
pcp/PCPMetric.c \
pcp/PCPProcess.c \
pcp/PCPProcessList.c \
pcp/Platform.c \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c
if HTOP_PCP
myhtopplatprogram = pcp-htop
myhtopplatheaders = $(pcp_platform_headers)
myhtopplatsources = $(pcp_platform_sources)
pcp_htop_SOURCES = $(myhtopplatprogram).c $(myhtopheaders) $(myhtopplatheaders) $(myhtopsources) $(myhtopplatsources)
endif
# Unsupported
# -----------
unsupported_platform_headers = \
generic/gettime.h \
unsupported/Platform.h \
unsupported/ProcessField.h \
unsupported/UnsupportedProcess.h \
unsupported/UnsupportedProcessList.h
unsupported_platform_sources = \
generic/gettime.c \
unsupported/Platform.c \
unsupported/UnsupportedProcess.c \
unsupported/UnsupportedProcessList.c
if HTOP_UNSUPPORTED
myhtopplatprogram = htop
myhtopplatsources = $(unsupported_platform_sources)
myhtopplatheaders = $(unsupported_platform_headers)
endif
# ----
bin_PROGRAMS = $(myhtopplatprogram)
htop_SOURCES = $(myhtopplatprogram).c $(myhtopheaders) $(myhtopplatheaders) $(myhtopsources) $(myhtopplatsources)
nodist_htop_SOURCES = config.h
target:
echo $(htop_SOURCES)
profile:
$(MAKE) all CFLAGS="-pg -O2"
$(MAKE) all AM_CPPFLAGS="-pg -O2 -DNDEBUG"
debug:
$(MAKE) all CFLAGS="-ggdb -DDEBUG"
$(MAKE) all AM_CPPFLAGS="-ggdb3 -Og" CFLAGS="`printf ' %s ' "$(CFLAGS)"|sed -E 's#[[:space:]]-O[^[:space:]]+[[:space:]]# #g'` -ggdb3 -Og"
hardened-debug:
$(MAKE) all CFLAGS="-ggdb -DDEBUG" LDFLAGS="-nopie"
coverage:
$(MAKE) all AM_CPPFLAGS="-fprofile-arcs -ftest-coverage" AM_LDFLAGS="-lgcov"
debuglite:
$(MAKE) all CFLAGS="-ggdb -DDEBUGLITE"
.c.h:
scripts/MakeHeader.py $<
cppcheck:
cppcheck -q -v . --enable=all -DHAVE_OPENVZ
dist-hook: $(top_distdir)/configure
@if grep 'pkg_m4_absent' '$(top_distdir)/configure'; then \
echo 'configure is generated without pkg.m4. Please supply pkg.m4 and run ./autogen.sh to rebuild the configure script.'>&2; \
(exit 1); \
else :; \
fi
.PHONY: lcov
lcov:
mkdir -p lcov
lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory lcov

View File

@ -1,71 +1,96 @@
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - MemoryMeter.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "MemoryMeter.h"
#include "Meter.h"
#include "ProcessList.h"
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <math.h>
#include <sys/param.h>
#include <stddef.h>
#include "debug.h"
#include <assert.h>
#include "CRT.h"
#include "Object.h"
#include "Platform.h"
#include "RichString.h"
int MemoryMeter_attributes[] = {
MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE
static const int MemoryMeter_attributes[] = {
MEMORY_USED,
MEMORY_BUFFERS,
MEMORY_SHARED,
MEMORY_CACHE
};
MeterType MemoryMeter = {
.setValues = MemoryMeter_setValues,
static void MemoryMeter_updateValues(Meter* this) {
char* buffer = this->txtBuffer;
size_t size = sizeof(this->txtBuffer);
int written;
/* shared and available memory are not supported on all platforms */
this->values[2] = NAN;
this->values[4] = NAN;
Platform_setMemoryValues(this);
/* Do not print available memory in bar mode */
this->curItems = 4;
written = Meter_humanUnit(buffer, isnan(this->values[4]) ? this->values[0] : this->total - this->values[4], size);
METER_BUFFER_CHECK(buffer, size, written);
METER_BUFFER_APPEND_CHR(buffer, size, '/');
Meter_humanUnit(buffer, this->total, size);
}
static void MemoryMeter_display(const Object* cast, RichString* out) {
char buffer[50];
const Meter* this = (const Meter*)cast;
RichString_writeAscii(out, CRT_colors[METER_TEXT], ":");
Meter_humanUnit(buffer, this->total, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer);
Meter_humanUnit(buffer, this->values[0], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:");
RichString_appendAscii(out, CRT_colors[MEMORY_USED], buffer);
Meter_humanUnit(buffer, this->values[1], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " buffers:");
RichString_appendAscii(out, CRT_colors[MEMORY_BUFFERS_TEXT], buffer);
/* shared memory is not supported on all platforms */
if (!isnan(this->values[2])) {
Meter_humanUnit(buffer, this->values[2], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " shared:");
RichString_appendAscii(out, CRT_colors[MEMORY_SHARED], buffer);
}
Meter_humanUnit(buffer, this->values[3], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " cache:");
RichString_appendAscii(out, CRT_colors[MEMORY_CACHE], buffer);
/* available memory is not supported on all platforms */
if (!isnan(this->values[4])) {
Meter_humanUnit(buffer, this->values[4], sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_TEXT], " available:");
RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer);
}
}
const MeterClass MemoryMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = MemoryMeter_display,
.mode = BAR_METERMODE,
.items = 3,
},
.updateValues = MemoryMeter_updateValues,
.defaultMode = BAR_METERMODE,
.maxItems = 5,
.total = 100.0,
.attributes = MemoryMeter_attributes,
"Memory",
"Memory",
"Mem"
.name = "Memory",
.uiName = "Memory",
.caption = "Mem"
};
void MemoryMeter_setValues(Meter* this, char* buffer, int size) {
long int usedMem = this->pl->usedMem;
long int buffersMem = this->pl->buffersMem;
long int cachedMem = this->pl->cachedMem;
usedMem -= buffersMem + cachedMem;
this->total = this->pl->totalMem;
this->values[0] = usedMem;
this->values[1] = buffersMem;
this->values[2] = cachedMem;
snprintf(buffer, size, "%ld/%ldMB", (long int) usedMem / 1024, (long int) this->total / 1024);
}
void MemoryMeter_display(Object* cast, RichString* out) {
char buffer[50];
Meter* this = (Meter*)cast;
int div = 1024; char* format = "%ldM ";
long int totalMem = this->total / div;
long int usedMem = this->values[0] / div;
long int buffersMem = this->values[1] / div;
long int cachedMem = this->values[2] / div;
RichString_init(out);
RichString_append(out, CRT_colors[METER_TEXT], ":");
sprintf(buffer, format, totalMem);
RichString_append(out, CRT_colors[METER_VALUE], buffer);
sprintf(buffer, format, usedMem);
RichString_append(out, CRT_colors[METER_TEXT], "used:");
RichString_append(out, CRT_colors[MEMORY_USED], buffer);
sprintf(buffer, format, buffersMem);
RichString_append(out, CRT_colors[METER_TEXT], "buffers:");
RichString_append(out, CRT_colors[MEMORY_BUFFERS], buffer);
sprintf(buffer, format, cachedMem);
RichString_append(out, CRT_colors[METER_TEXT], "cache:");
RichString_append(out, CRT_colors[MEMORY_CACHE], buffer);
}

View File

@ -1,33 +1,15 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_MemoryMeter
#define HEADER_MemoryMeter
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - MemoryMeter.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
#include "ProcessList.h"
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <math.h>
#include <sys/param.h>
#include "debug.h"
#include <assert.h>
extern int MemoryMeter_attributes[];
extern MeterType MemoryMeter;
void MemoryMeter_setValues(Meter* this, char* buffer, int size);
void MemoryMeter_display(Object* cast, RichString* out);
extern const MeterClass MemoryMeter_class;
#endif

102
MemorySwapMeter.c Normal file
View File

@ -0,0 +1,102 @@
/*
htop - MemorySwapMeter.c
(C) 2021 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "MemorySwapMeter.h"
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include "Macros.h"
#include "MemoryMeter.h"
#include "Object.h"
#include "SwapMeter.h"
#include "XUtils.h"
typedef struct MemorySwapMeterData_ {
Meter* memoryMeter;
Meter* swapMeter;
} MemorySwapMeterData;
static void MemorySwapMeter_updateValues(Meter* this) {
MemorySwapMeterData* data = this->meterData;
Meter_updateValues(data->memoryMeter);
Meter_updateValues(data->swapMeter);
}
static void MemorySwapMeter_draw(Meter* this, int x, int y, int w) {
MemorySwapMeterData* data = this->meterData;
assert(data->memoryMeter->draw);
data->memoryMeter->draw(data->memoryMeter, x, y, w / 2);
assert(data->swapMeter->draw);
data->swapMeter->draw(data->swapMeter, x + w / 2, y, w - w / 2);
}
static void MemorySwapMeter_init(Meter* this) {
MemorySwapMeterData* data = this->meterData;
if (!data) {
data = this->meterData = xMalloc(sizeof(MemorySwapMeterData));
data->memoryMeter = NULL;
data->swapMeter = NULL;
}
if (!data->memoryMeter)
data->memoryMeter = Meter_new(this->pl, 0, (const MeterClass*) Class(MemoryMeter));
if (!data->swapMeter)
data->swapMeter = Meter_new(this->pl, 0, (const MeterClass*) Class(SwapMeter));
if (Meter_initFn(data->memoryMeter))
Meter_init(data->memoryMeter);
if (Meter_initFn(data->swapMeter))
Meter_init(data->swapMeter);
if (this->mode == 0)
this->mode = BAR_METERMODE;
this->h = MAXIMUM(Meter_modes[data->memoryMeter->mode]->h, Meter_modes[data->swapMeter->mode]->h);
}
static void MemorySwapMeter_updateMode(Meter* this, int mode) {
MemorySwapMeterData* data = this->meterData;
this->mode = mode;
Meter_setMode(data->memoryMeter, mode);
Meter_setMode(data->swapMeter, mode);
this->h = MAXIMUM(Meter_modes[data->memoryMeter->mode]->h, Meter_modes[data->swapMeter->mode]->h);
}
static void MemorySwapMeter_done(Meter* this) {
MemorySwapMeterData* data = this->meterData;
Meter_delete((Object*)data->swapMeter);
Meter_delete((Object*)data->memoryMeter);
free(data);
}
const MeterClass MemorySwapMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
},
.updateValues = MemorySwapMeter_updateValues,
.defaultMode = CUSTOM_METERMODE,
.name = "MemorySwap",
.uiName = "Memory & Swap",
.description = "Combined memory and swap usage",
.caption = "M&S",
.draw = MemorySwapMeter_draw,
.init = MemorySwapMeter_init,
.updateMode = MemorySwapMeter_updateMode,
.done = MemorySwapMeter_done
};

15
MemorySwapMeter.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef HEADER_MemorySwapMeter
#define HEADER_MemorySwapMeter
/*
htop - MemorySwapMeter.h
(C) 2021 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Meter.h"
extern const MeterClass MemorySwapMeter_class;
#endif

786
Meter.c
View File

@ -1,127 +1,428 @@
/*
htop - Meter.c
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#define _GNU_SOURCE
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <curses.h>
#include <stdarg.h>
#include "config.h" // IWYU pragma: keep
#include "Meter.h"
#include "Object.h"
#include "CRT.h"
#include "ListItem.h"
#include "String.h"
#include "ProcessList.h"
#include "debug.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifndef USE_FUNKY_MODES
#define USE_FUNKY_MODES 1
#endif
#include "CRT.h"
#include "Macros.h"
#include "Object.h"
#include "ProvideCurses.h"
#include "RichString.h"
#include "Settings.h"
#include "XUtils.h"
#define METER_BUFFER_LEN 128
/*{
#define GRAPH_HEIGHT 4 /* Unit: rows (lines) */
typedef struct Meter_ Meter;
typedef struct MeterType_ MeterType;
typedef struct MeterMode_ MeterMode;
typedef void(*MeterType_Init)(Meter*);
typedef void(*MeterType_Done)(Meter*);
typedef void(*MeterType_SetMode)(Meter*, int);
typedef void(*Meter_SetValues)(Meter*, char*, int);
typedef void(*Meter_Draw)(Meter*, int, int, int);
struct MeterMode_ {
Meter_Draw draw;
char* uiName;
int h;
const MeterClass Meter_class = {
.super = {
.extends = Class(Object)
}
};
struct MeterType_ {
Meter_SetValues setValues;
Object_Display display;
int mode;
int items;
double total;
int* attributes;
char* name;
char* uiName;
char* caption;
MeterType_Init init;
MeterType_Done done;
MeterType_SetMode setMode;
Meter_Draw draw;
Meter* Meter_new(const struct ProcessList_* pl, unsigned int param, const MeterClass* type) {
Meter* this = xCalloc(1, sizeof(Meter));
Object_setClass(this, type);
this->h = 1;
this->param = param;
this->pl = pl;
this->curItems = type->maxItems;
this->curAttributes = NULL;
this->values = type->maxItems ? xCalloc(type->maxItems, sizeof(double)) : NULL;
this->total = type->total;
this->caption = xStrdup(type->caption);
if (Meter_initFn(this)) {
Meter_init(this);
}
Meter_setMode(this, type->defaultMode);
return this;
}
int Meter_humanUnit(char* buffer, unsigned long int value, size_t size) {
const char* prefix = "KMGTPEZY";
unsigned long int powi = 1;
unsigned int powj = 1, precision = 2;
for (;;) {
if (value / 1024 < powi)
break;
if (prefix[1] == '\0')
break;
powi *= 1024;
++prefix;
}
if (*prefix == 'K')
precision = 0;
for (; precision > 0; precision--) {
powj *= 10;
if (value / powi < powj)
break;
}
return snprintf(buffer, size, "%.*f%c", precision, (double) value / powi, *prefix);
}
void Meter_delete(Object* cast) {
if (!cast)
return;
Meter* this = (Meter*) cast;
if (Meter_doneFn(this)) {
Meter_done(this);
}
free(this->drawData);
free(this->caption);
free(this->values);
free(this);
}
void Meter_setCaption(Meter* this, const char* caption) {
free_and_xStrdup(&this->caption, caption);
}
static inline void Meter_displayBuffer(const Meter* this, RichString* out) {
if (Object_displayFn(this)) {
Object_display(this, out);
} else {
RichString_writeWide(out, CRT_colors[Meter_attributes(this)[0]], this->txtBuffer);
}
}
void Meter_setMode(Meter* this, int modeIndex) {
if (modeIndex > 0 && modeIndex == this->mode) {
return;
}
if (!modeIndex) {
modeIndex = 1;
}
assert(modeIndex < LAST_METERMODE);
if (Meter_defaultMode(this) == CUSTOM_METERMODE) {
this->draw = Meter_drawFn(this);
if (Meter_updateModeFn(this)) {
Meter_updateMode(this, modeIndex);
}
} else {
assert(modeIndex >= 1);
free(this->drawData);
this->drawData = NULL;
const MeterMode* mode = Meter_modes[modeIndex];
this->draw = mode->draw;
this->h = mode->h;
}
this->mode = modeIndex;
}
ListItem* Meter_toListItem(const Meter* this, bool moving) {
char mode[20];
if (this->mode) {
xSnprintf(mode, sizeof(mode), " [%s]", Meter_modes[this->mode]->uiName);
} else {
mode[0] = '\0';
}
char name[32];
if (Meter_getUiNameFn(this))
Meter_getUiName(this, name, sizeof(name));
else
xSnprintf(name, sizeof(name), "%s", Meter_uiName(this));
char buffer[50];
xSnprintf(buffer, sizeof(buffer), "%s%s", name, mode);
ListItem* li = ListItem_new(buffer, 0);
li->moving = moving;
return li;
}
/* ---------- TextMeterMode ---------- */
static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
const char* caption = Meter_getCaption(this);
attrset(CRT_colors[METER_TEXT]);
mvaddnstr(y, x, caption, w - 1);
attrset(CRT_colors[RESET_COLOR]);
int captionLen = strlen(caption);
x += captionLen;
w -= captionLen;
if (w <= 0)
return;
RichString_begin(out);
Meter_displayBuffer(this, &out);
RichString_printoffnVal(out, y, x, 0, w - 1);
RichString_delete(&out);
}
/* ---------- BarMeterMode ---------- */
static const char BarMeterMode_characters[] = "|#*@$%&.";
static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
const char* caption = Meter_getCaption(this);
w -= 2;
attrset(CRT_colors[METER_TEXT]);
int captionLen = 3;
mvaddnstr(y, x, caption, captionLen);
x += captionLen;
w -= captionLen;
attrset(CRT_colors[BAR_BORDER]);
mvaddch(y, x, '[');
mvaddch(y, x + MAXIMUM(w, 0), ']');
attrset(CRT_colors[RESET_COLOR]);
w--;
x++;
if (w < 1)
return;
// The text in the bar is right aligned;
// Pad with maximal spaces and then calculate needed starting position offset
RichString_begin(bar);
RichString_appendChr(&bar, 0, ' ', w);
RichString_appendWide(&bar, 0, this->txtBuffer);
int startPos = RichString_sizeVal(bar) - w;
if (startPos > w) {
// Text is too large for bar
// Truncate meter text at a space character
for (int pos = 2 * w; pos > w; pos--) {
if (RichString_getCharVal(bar, pos) == ' ') {
while (pos > w && RichString_getCharVal(bar, pos - 1) == ' ')
pos--;
startPos = pos - w;
break;
}
}
// If still too large, print the start not the end
startPos = MINIMUM(startPos, w);
}
assert(startPos >= 0);
assert(startPos <= w);
assert(startPos + w <= RichString_sizeVal(bar));
int blockSizes[10];
// First draw in the bar[] buffer...
int offset = 0;
for (uint8_t i = 0; i < this->curItems; i++) {
double value = this->values[i];
value = CLAMP(value, 0.0, this->total);
if (value > 0) {
blockSizes[i] = ceil((value / this->total) * w);
} else {
blockSizes[i] = 0;
}
int nextOffset = offset + blockSizes[i];
// (Control against invalid values)
nextOffset = CLAMP(nextOffset, 0, w);
for (int j = offset; j < nextOffset; j++)
if (RichString_getCharVal(bar, startPos + j) == ' ') {
if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
RichString_setChar(&bar, startPos + j, BarMeterMode_characters[i]);
} else {
RichString_setChar(&bar, startPos + j, '|');
}
}
offset = nextOffset;
}
// ...then print the buffer.
offset = 0;
for (uint8_t i = 0; i < this->curItems; i++) {
int attr = this->curAttributes ? this->curAttributes[i] : Meter_attributes(this)[i];
RichString_setAttrn(&bar, CRT_colors[attr], startPos + offset, blockSizes[i]);
RichString_printoffnVal(bar, y, x + offset, startPos + offset, MINIMUM(blockSizes[i], w - offset));
offset += blockSizes[i];
offset = CLAMP(offset, 0, w);
}
if (offset < w) {
RichString_setAttrn(&bar, CRT_colors[BAR_SHADOW], startPos + offset, w - offset);
RichString_printoffnVal(bar, y, x + offset, startPos + offset, w - offset);
}
RichString_delete(&bar);
move(y, x + w + 1);
attrset(CRT_colors[RESET_COLOR]);
}
/* ---------- GraphMeterMode ---------- */
#ifdef HAVE_LIBNCURSESW
#define PIXPERROW_UTF8 4
static const char* const GraphMeterMode_dotsUtf8[] = {
/*00*/" ", /*01*/"", /*02*/"", /*03*/"", /*04*/ "",
/*10*/"", /*11*/"", /*12*/"", /*13*/"", /*14*/ "",
/*20*/"", /*21*/"", /*22*/"", /*23*/"", /*24*/ "",
/*30*/"", /*31*/"", /*32*/"", /*33*/"", /*34*/ "",
/*40*/"", /*41*/"", /*42*/"", /*43*/"", /*44*/ ""
};
struct Meter_ {
Object super;
char* caption;
MeterType* type;
int mode;
int param;
Meter_Draw draw;
void* drawBuffer;
int h;
ProcessList* pl;
double* values;
double total;
#endif
#define PIXPERROW_ASCII 2
static const char* const GraphMeterMode_dotsAscii[] = {
/*00*/" ", /*01*/".", /*02*/":",
/*10*/".", /*11*/".", /*12*/":",
/*20*/":", /*21*/":", /*22*/":"
};
typedef enum {
CUSTOM_METERMODE = 0,
BAR_METERMODE,
TEXT_METERMODE,
#ifdef USE_FUNKY_MODES
GRAPH_METERMODE,
LED_METERMODE,
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
const ProcessList* pl = this->pl;
if (!this->drawData) {
this->drawData = xCalloc(1, sizeof(GraphData));
}
GraphData* data = this->drawData;
const int nValues = METER_GRAPHDATA_SIZE;
const char* const* GraphMeterMode_dots;
int GraphMeterMode_pixPerRow;
#ifdef HAVE_LIBNCURSESW
if (CRT_utf8) {
GraphMeterMode_dots = GraphMeterMode_dotsUtf8;
GraphMeterMode_pixPerRow = PIXPERROW_UTF8;
} else
#endif
LAST_METERMODE
} MeterModeId;
{
GraphMeterMode_dots = GraphMeterMode_dotsAscii;
GraphMeterMode_pixPerRow = PIXPERROW_ASCII;
}
}*/
const char* caption = Meter_getCaption(this);
attrset(CRT_colors[METER_TEXT]);
int captionLen = 3;
mvaddnstr(y, x, caption, captionLen);
x += captionLen;
w -= captionLen;
#include "CPUMeter.h"
#include "MemoryMeter.h"
#include "SwapMeter.h"
#include "TasksMeter.h"
#include "LoadAverageMeter.h"
#include "UptimeMeter.h"
#include "ClockMeter.h"
if (!timercmp(&pl->realtime, &(data->time), <)) {
int globalDelay = this->pl->settings->delay;
struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay % 10) * 100000L };
timeradd(&pl->realtime, &delay, &(data->time));
for (int i = 0; i < nValues - 1; i++)
data->values[i] = data->values[i + 1];
double value = 0.0;
for (uint8_t i = 0; i < this->curItems; i++)
value += this->values[i];
data->values[nValues - 1] = value;
}
int i = nValues - (w * 2) + 2, k = 0;
if (i < 0) {
k = -i / 2;
i = 0;
}
for (; i < nValues - 1; i += 2, k++) {
int pix = GraphMeterMode_pixPerRow * GRAPH_HEIGHT;
if (this->total < 1)
this->total = 1;
int v1 = CLAMP((int) lround(data->values[i] / this->total * pix), 1, pix);
int v2 = CLAMP((int) lround(data->values[i + 1] / this->total * pix), 1, pix);
int colorIdx = GRAPH_1;
for (int line = 0; line < GRAPH_HEIGHT; line++) {
int line1 = CLAMP(v1 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow);
int line2 = CLAMP(v2 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow);
attrset(CRT_colors[colorIdx]);
mvaddstr(y + line, x + k, GraphMeterMode_dots[line1 * (GraphMeterMode_pixPerRow + 1) + line2]);
colorIdx = GRAPH_2;
}
}
attrset(CRT_colors[RESET_COLOR]);
}
/* ---------- LEDMeterMode ---------- */
static const char* const LEDMeterMode_digitsAscii[] = {
" __ ", " ", " __ ", " __ ", " ", " __ ", " __ ", " __ ", " __ ", " __ ",
"| |", " |", " __|", " __|", "|__|", "|__ ", "|__ ", " |", "|__|", "|__|",
"|__|", " |", "|__ ", " __|", " |", " __|", "|__|", " |", "|__|", " __|"
};
#ifdef HAVE_LIBNCURSESW
static const char* const LEDMeterMode_digitsUtf8[] = {
"┌──┐", "", "╶──┐", "╶──┐", "╷ ╷", "┌──╴", "┌──╴", "╶──┐", "┌──┐", "┌──┐",
"│ │", "", "┌──┘", " ──┤", "└──┤", "└──┐", "├──┐", "", "├──┤", "└──┤",
"└──┘", "", "└──╴", "╶──┘", "", "╶──┘", "└──┘", "", "└──┘", " ──┘"
};
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifdef DEBUG
char* METER_CLASS = "Meter";
static const char* const* LEDMeterMode_digits;
static void LEDMeterMode_drawDigit(int x, int y, int n) {
for (int i = 0; i < 3; i++)
mvaddstr(y + i, x, LEDMeterMode_digits[i * 10 + n]);
}
static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
#ifdef HAVE_LIBNCURSESW
if (CRT_utf8)
LEDMeterMode_digits = LEDMeterMode_digitsUtf8;
else
#endif
LEDMeterMode_digits = LEDMeterMode_digitsAscii;
RichString_begin(out);
Meter_displayBuffer(this, &out);
int yText =
#ifdef HAVE_LIBNCURSESW
CRT_utf8 ? y + 1 :
#endif
y + 2;
attrset(CRT_colors[LED_COLOR]);
const char* caption = Meter_getCaption(this);
mvaddstr(yText, x, caption);
int xx = x + strlen(caption);
int len = RichString_sizeVal(out);
for (int i = 0; i < len; i++) {
int c = RichString_getCharVal(out, i);
if (c >= '0' && c <= '9') {
if (xx - x + 4 > w)
break;
LEDMeterMode_drawDigit(xx, y, c - '0');
xx += 4;
} else {
if (xx - x + 1 > w)
break;
#ifdef HAVE_LIBNCURSESW
const cchar_t wc = { .chars = { c, '\0' }, .attr = 0 }; /* use LED_COLOR from attrset() */
mvadd_wch(yText, xx, &wc);
#else
#define METER_CLASS NULL
mvaddch(yText, xx, c);
#endif
MeterType* Meter_types[] = {
&CPUMeter,
&ClockMeter,
&LoadAverageMeter,
&LoadMeter,
&MemoryMeter,
&SwapMeter,
&TasksMeter,
&UptimeMeter,
&AllCPUsMeter,
NULL
};
xx += 1;
}
}
attrset(CRT_colors[RESET_COLOR]);
RichString_delete(&out);
}
static MeterMode BarMeterMode = {
.uiName = "Bar",
@ -135,11 +436,9 @@ static MeterMode TextMeterMode = {
.draw = TextMeterMode_draw,
};
#ifdef USE_FUNKY_MODES
static MeterMode GraphMeterMode = {
.uiName = "Graph",
.h = 3,
.h = GRAPH_HEIGHT,
.draw = GraphMeterMode_draw,
};
@ -149,285 +448,40 @@ static MeterMode LEDMeterMode = {
.draw = LEDMeterMode_draw,
};
#endif
MeterMode* Meter_modes[] = {
const MeterMode* const Meter_modes[] = {
NULL,
&BarMeterMode,
&TextMeterMode,
#ifdef USE_FUNKY_MODES
&GraphMeterMode,
&LEDMeterMode,
#endif
NULL
};
static RichString Meter_stringBuffer;
/* Blank meter */
Meter* Meter_new(ProcessList* pl, int param, MeterType* type) {
Meter* this = calloc(sizeof(Meter), 1);
Object_setClass(this, METER_CLASS);
((Object*)this)->delete = Meter_delete;
((Object*)this)->display = type->display;
this->h = 1;
this->type = type;
this->param = param;
this->pl = pl;
this->values = calloc(sizeof(double), type->items);
this->total = type->total;
this->caption = strdup(type->caption);
Meter_setMode(this, type->mode);
if (this->type->init)
this->type->init(this);
return this;
static void BlankMeter_updateValues(Meter* this) {
this->txtBuffer[0] = '\0';
}
void Meter_delete(Object* cast) {
Meter* this = (Meter*) cast;
assert (this != NULL);
if (this->type->done) {
this->type->done(this);
}
if (this->drawBuffer)
free(this->drawBuffer);
free(this->caption);
free(this->values);
free(this);
static void BlankMeter_display(ATTR_UNUSED const Object* cast, ATTR_UNUSED RichString* out) {
}
void Meter_setCaption(Meter* this, char* caption) {
free(this->caption);
this->caption = strdup(caption);
}
static inline void Meter_displayToStringBuffer(Meter* this, char* buffer) {
MeterType* type = this->type;
Object_Display display = ((Object*)this)->display;
if (display) {
display((Object*)this, &Meter_stringBuffer);
} else {
RichString_initVal(Meter_stringBuffer);
RichString_append(&Meter_stringBuffer, CRT_colors[type->attributes[0]], buffer);
}
}
void Meter_setMode(Meter* this, int modeIndex) {
if (modeIndex > 0 && modeIndex == this->mode)
return;
if (!modeIndex)
modeIndex = 1;
assert(modeIndex < LAST_METERMODE);
if (this->type->mode == 0) {
this->draw = this->type->draw;
if (this->type->setMode)
this->type->setMode(this, modeIndex);
} else {
assert(modeIndex >= 1);
if (this->drawBuffer)
free(this->drawBuffer);
this->drawBuffer = NULL;
MeterMode* mode = Meter_modes[modeIndex];
this->draw = mode->draw;
this->h = mode->h;
}
this->mode = modeIndex;
}
ListItem* Meter_toListItem(Meter* this) {
MeterType* type = this->type;
char mode[21];
if (this->mode)
snprintf(mode, 20, " [%s]", Meter_modes[this->mode]->uiName);
else
mode[0] = '\0';
char number[11];
if (this->param > 0)
snprintf(number, 10, " %d", this->param);
else
number[0] = '\0';
char buffer[51];
snprintf(buffer, 50, "%s%s%s", type->uiName, number, mode);
return ListItem_new(buffer, 0);
}
/* ---------- TextMeterMode ---------- */
void TextMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type;
char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
attrset(CRT_colors[METER_TEXT]);
mvaddstr(y, x, this->caption);
int captionLen = strlen(this->caption);
w -= captionLen;
x += captionLen;
Meter_displayToStringBuffer(this, buffer);
mvhline(y, x, ' ', CRT_colors[DEFAULT_COLOR]);
attrset(CRT_colors[RESET_COLOR]);
mvaddchstr(y, x, Meter_stringBuffer.chstr);
}
/* ---------- BarMeterMode ---------- */
static char BarMeterMode_characters[] = "|#*@$%&";
void BarMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type;
char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
w -= 2;
attrset(CRT_colors[METER_TEXT]);
mvaddstr(y, x, this->caption);
int captionLen = strlen(this->caption);
x += captionLen;
w -= captionLen;
attrset(CRT_colors[BAR_BORDER]);
mvaddch(y, x, '[');
mvaddch(y, x + w, ']');
w--;
x++;
char bar[w];
int blockSizes[10];
for (int i = 0; i < w; i++)
bar[i] = ' ';
sprintf(bar + (w-strlen(buffer)), "%s", buffer);
// First draw in the bar[] buffer...
double total = 0.0;
int offset = 0;
for (int i = 0; i < type->items; i++) {
double value = this->values[i];
value = MAX(value, 0);
value = MIN(value, this->total);
if (value > 0) {
blockSizes[i] = ceil((value/this->total) * w);
} else {
blockSizes[i] = 0;
}
int nextOffset = offset + blockSizes[i];
// (Control against invalid values)
nextOffset = MIN(MAX(nextOffset, 0), w);
for (int j = offset; j < nextOffset; j++)
if (bar[j] == ' ') {
if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
bar[j] = BarMeterMode_characters[i];
} else {
bar[j] = '|';
}
}
offset = nextOffset;
total += this->values[i];
}
// ...then print the buffer.
offset = 0;
for (int i = 0; i < type->items; i++) {
attrset(CRT_colors[type->attributes[i]]);
mvaddnstr(y, x + offset, bar + offset, blockSizes[i]);
offset += blockSizes[i];
offset = MAX(offset, 0);
offset = MIN(offset, w);
}
if (offset < w) {
attrset(CRT_colors[BAR_SHADOW]);
mvaddnstr(y, x + offset, bar + offset, w - offset);
}
move(y, x + w + 1);
attrset(CRT_colors[RESET_COLOR]);
}
#ifdef USE_FUNKY_MODES
/* ---------- GraphMeterMode ---------- */
#define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0)
static int GraphMeterMode_colors[21] = {
GRAPH_1, GRAPH_1, GRAPH_1,
GRAPH_2, GRAPH_2, GRAPH_2,
GRAPH_3, GRAPH_3, GRAPH_3,
GRAPH_4, GRAPH_4, GRAPH_4,
GRAPH_5, GRAPH_5, GRAPH_6,
GRAPH_7, GRAPH_7, GRAPH_7,
GRAPH_8, GRAPH_8, GRAPH_9
static const int BlankMeter_attributes[] = {
DEFAULT_COLOR
};
static char* GraphMeterMode_characters = "^`'-.,_~'`-.,_~'`-.,_";
void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
if (!this->drawBuffer) this->drawBuffer = calloc(sizeof(double), METER_BUFFER_LEN);
double* drawBuffer = (double*) this->drawBuffer;
for (int i = 0; i < METER_BUFFER_LEN - 1; i++)
drawBuffer[i] = drawBuffer[i+1];
MeterType* type = this->type;
char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
double value = 0.0;
for (int i = 0; i < type->items; i++)
value += this->values[i];
value /= this->total;
drawBuffer[METER_BUFFER_LEN - 1] = value;
for (int i = METER_BUFFER_LEN - w, k = 0; i < METER_BUFFER_LEN; i++, k++) {
double value = drawBuffer[i];
DrawDot( CRT_colors[DEFAULT_COLOR], y, ' ' );
DrawDot( CRT_colors[DEFAULT_COLOR], y+1, ' ' );
DrawDot( CRT_colors[DEFAULT_COLOR], y+2, ' ' );
double threshold = 1.00;
for (int i = 0; i < 21; i++, threshold -= 0.05)
if (value >= threshold) {
DrawDot(CRT_colors[GraphMeterMode_colors[i]], y+(i/7.0), GraphMeterMode_characters[i]);
break;
}
}
attrset(CRT_colors[RESET_COLOR]);
}
/* ---------- LEDMeterMode ---------- */
static char* LEDMeterMode_digits[3][10] = {
{ " __ "," "," __ "," __ "," "," __ "," __ "," __ "," __ "," __ "},
{ "| |"," |"," __|"," __|","|__|","|__ ","|__ "," |","|__|","|__|"},
{ "|__|"," |","|__ "," __|"," |"," __|","|__|"," |","|__|"," __|"},
const MeterClass BlankMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = BlankMeter_display,
},
.updateValues = BlankMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 0,
.total = 100.0,
.attributes = BlankMeter_attributes,
.name = "Blank",
.uiName = "Blank",
.caption = ""
};
static void LEDMeterMode_drawDigit(int x, int y, int n) {
for (int i = 0; i < 3; i++)
mvaddstr(y+i, x, LEDMeterMode_digits[i][n]);
}
void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type;
char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
Meter_displayToStringBuffer(this, buffer);
attrset(CRT_colors[LED_COLOR]);
mvaddstr(y+2, x, this->caption);
int xx = x + strlen(this->caption);
for (int i = 0; i < Meter_stringBuffer.len; i++) {
char c = Meter_stringBuffer.chstr[i];
if (c >= '0' && c <= '9') {
LEDMeterMode_drawDigit(xx, y, c-48);
xx += 4;
} else {
mvaddch(y+2, xx, c);
xx += 1;
}
}
attrset(CRT_colors[RESET_COLOR]);
}
#endif

207
Meter.h
View File

@ -1,154 +1,153 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Meter
#define HEADER_Meter
/*
htop - Meter.h
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#define _GNU_SOURCE
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <curses.h>
#include <stdarg.h>
#include "config.h" // IWYU pragma: keep
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/time.h>
#include "Object.h"
#include "CRT.h"
#include "ListItem.h"
#include "String.h"
#include "Object.h"
#include "ProcessList.h"
#include "debug.h"
#include <assert.h>
#ifndef USE_FUNKY_MODES
#define USE_FUNKY_MODES 1
#endif
#define METER_TXTBUFFER_LEN 256
#define METER_GRAPHDATA_SIZE 256
#define METER_BUFFER_LEN 128
#define METER_BUFFER_CHECK(buffer, size, written) \
do { \
if ((written) < 0 || (size_t)(written) >= (size)) { \
return; \
} \
(buffer) += (written); \
(size) -= (size_t)(written); \
} while (0)
#define METER_BUFFER_APPEND_CHR(buffer, size, c) \
do { \
if ((size) < 2) { \
return; \
} \
*(buffer)++ = c; \
*(buffer) = '\0'; \
(size)--; \
if ((size) == 0) { \
return; \
} \
} while (0)
struct Meter_;
typedef struct Meter_ Meter;
typedef struct MeterType_ MeterType;
typedef struct MeterMode_ MeterMode;
typedef void(*MeterType_Init)(Meter*);
typedef void(*MeterType_Done)(Meter*);
typedef void(*MeterType_SetMode)(Meter*, int);
typedef void(*Meter_SetValues)(Meter*, char*, int);
typedef void(*Meter_Init)(Meter*);
typedef void(*Meter_Done)(Meter*);
typedef void(*Meter_UpdateMode)(Meter*, int);
typedef void(*Meter_UpdateValues)(Meter*);
typedef void(*Meter_Draw)(Meter*, int, int, int);
typedef const char* (*Meter_GetCaption)(const Meter*);
typedef void(*Meter_GetUiName)(const Meter*, char*, size_t);
struct MeterMode_ {
Meter_Draw draw;
char* uiName;
int h;
};
typedef struct MeterClass_ {
const ObjectClass super;
const Meter_Init init;
const Meter_Done done;
const Meter_UpdateMode updateMode;
const Meter_UpdateValues updateValues;
const Meter_Draw draw;
const Meter_GetCaption getCaption;
const Meter_GetUiName getUiName;
const int defaultMode;
const double total;
const int* const attributes;
const char* const name; /* internal name of the meter, must not contain any space */
const char* const uiName; /* display name in header setup menu */
const char* const caption; /* prefix in the actual header */
const char* const description; /* optional meter description in header setup menu */
const uint8_t maxItems;
} MeterClass;
struct MeterType_ {
Meter_SetValues setValues;
Object_Display display;
int mode;
int items;
double total;
int* attributes;
char* name;
char* uiName;
char* caption;
MeterType_Init init;
MeterType_Done done;
MeterType_SetMode setMode;
Meter_Draw draw;
};
#define As_Meter(this_) ((const MeterClass*)((this_)->super.klass))
#define Meter_initFn(this_) As_Meter(this_)->init
#define Meter_init(this_) As_Meter(this_)->init((Meter*)(this_))
#define Meter_done(this_) As_Meter(this_)->done((Meter*)(this_))
#define Meter_updateModeFn(this_) As_Meter(this_)->updateMode
#define Meter_updateMode(this_, m_) As_Meter(this_)->updateMode((Meter*)(this_), m_)
#define Meter_drawFn(this_) As_Meter(this_)->draw
#define Meter_doneFn(this_) As_Meter(this_)->done
#define Meter_updateValues(this_) As_Meter(this_)->updateValues((Meter*)(this_))
#define Meter_getUiNameFn(this_) As_Meter(this_)->getUiName
#define Meter_getUiName(this_,n_,l_) As_Meter(this_)->getUiName((const Meter*)(this_),n_,l_)
#define Meter_getCaptionFn(this_) As_Meter(this_)->getCaption
#define Meter_getCaption(this_) (Meter_getCaptionFn(this_) ? As_Meter(this_)->getCaption((const Meter*)(this_)) : (this_)->caption)
#define Meter_defaultMode(this_) As_Meter(this_)->defaultMode
#define Meter_attributes(this_) As_Meter(this_)->attributes
#define Meter_name(this_) As_Meter(this_)->name
#define Meter_uiName(this_) As_Meter(this_)->uiName
typedef struct GraphData_ {
struct timeval time;
double values[METER_GRAPHDATA_SIZE];
} GraphData;
struct Meter_ {
Object super;
char* caption;
MeterType* type;
int mode;
int param;
Meter_Draw draw;
void* drawBuffer;
char* caption;
int mode;
unsigned int param;
GraphData* drawData;
int h;
ProcessList* pl;
int columnWidthCount; /**< only used internally by the Header */
const ProcessList* pl;
uint8_t curItems;
const int* curAttributes;
char txtBuffer[METER_TXTBUFFER_LEN];
double* values;
double total;
void* meterData;
};
typedef struct MeterMode_ {
Meter_Draw draw;
const char* uiName;
int h;
} MeterMode;
typedef enum {
CUSTOM_METERMODE = 0,
BAR_METERMODE,
TEXT_METERMODE,
#ifdef USE_FUNKY_MODES
GRAPH_METERMODE,
LED_METERMODE,
#endif
LAST_METERMODE
} MeterModeId;
extern const MeterClass Meter_class;
#include "CPUMeter.h"
#include "MemoryMeter.h"
#include "SwapMeter.h"
#include "TasksMeter.h"
#include "LoadAverageMeter.h"
#include "UptimeMeter.h"
#include "ClockMeter.h"
Meter* Meter_new(const ProcessList* pl, unsigned int param, const MeterClass* type);
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifdef DEBUG
extern char* METER_CLASS;
#else
#define METER_CLASS NULL
#endif
extern MeterType* Meter_types[];
#ifdef USE_FUNKY_MODES
#endif
extern MeterMode* Meter_modes[];
Meter* Meter_new(ProcessList* pl, int param, MeterType* type);
int Meter_humanUnit(char* buffer, unsigned long int value, size_t size);
void Meter_delete(Object* cast);
void Meter_setCaption(Meter* this, char* caption);
void Meter_setCaption(Meter* this, const char* caption);
void Meter_setMode(Meter* this, int modeIndex);
ListItem* Meter_toListItem(Meter* this);
ListItem* Meter_toListItem(const Meter* this, bool moving);
/* ---------- TextMeterMode ---------- */
extern const MeterMode* const Meter_modes[];
void TextMeterMode_draw(Meter* this, int x, int y, int w);
/* ---------- BarMeterMode ---------- */
void BarMeterMode_draw(Meter* this, int x, int y, int w);
#ifdef USE_FUNKY_MODES
/* ---------- GraphMeterMode ---------- */
#define DrawDot(a,y,c) do { attrset(a); mvaddch(y, x+k, c); } while(0)
void GraphMeterMode_draw(Meter* this, int x, int y, int w);
/* ---------- LEDMeterMode ---------- */
void LEDMeterMode_draw(Meter* this, int x, int y, int w);
#endif
extern const MeterClass BlankMeter_class;
#endif

View File

@ -1,71 +1,128 @@
/*
htop - MetersPanel.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "MetersPanel.h"
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include <stdlib.h>
#include "debug.h"
#include <assert.h>
#include "CRT.h"
#include "FunctionBar.h"
#include "Header.h"
#include "ListItem.h"
#include "Meter.h"
#include "Object.h"
#include "ProvideCurses.h"
/*{
typedef struct MetersPanel_ {
Panel super;
// Note: In code the meters are known to have bar/text/graph "Modes", but in UI
// we call them "Styles".
static const char* const MetersFunctions[] = {"Style ", "Move ", " ", "Delete", "Done ", NULL};
static const char* const MetersKeys[] = {"Space", "Enter", "", "Del", "F10"};
static const int MetersEvents[] = {' ', 13, ERR, KEY_DC, KEY_F(10)};
Settings* settings;
Vector* meters;
ScreenManager* scr;
} MetersPanel;
// We avoid UTF-8 arrows ← → here as they might display full-width on Chinese
// terminals, breaking our aligning.
// In <http://unicode.org/reports/tr11/>, arrows (U+2019..U+2199) are
// considered "Ambiguous characters".
static const char* const MetersMovingFunctions[] = {"Style ", "Lock ", "Up ", "Down ", "Left ", "Right ", " ", "Delete", "Done ", NULL};
static const char* const MetersMovingKeys[] = {"Space", "Enter", "Up", "Dn", "<-", "->", " ", "Del", "F10"};
static const int MetersMovingEvents[] = {' ', 13, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, ERR, KEY_DC, KEY_F(10)};
static FunctionBar* Meters_movingBar = NULL;
}*/
MetersPanel* MetersPanel_new(Settings* settings, char* header, Vector* meters, ScreenManager* scr) {
MetersPanel* this = (MetersPanel*) malloc(sizeof(MetersPanel));
Panel* super = (Panel*) this;
Panel_init(super, 1, 1, 1, 1, LISTITEM_CLASS, true);
((Object*)this)->delete = MetersPanel_delete;
this->settings = settings;
this->meters = meters;
this->scr = scr;
super->eventHandler = MetersPanel_EventHandler;
Panel_setHeader(super, header);
for (int i = 0; i < Vector_size(meters); i++) {
Meter* meter = (Meter*) Vector_get(meters, i);
Panel_add(super, (Object*) Meter_toListItem(meter));
void MetersPanel_cleanup() {
if (Meters_movingBar) {
FunctionBar_delete(Meters_movingBar);
Meters_movingBar = NULL;
}
return this;
}
void MetersPanel_delete(Object* object) {
static void MetersPanel_delete(Object* object) {
Panel* super = (Panel*) object;
MetersPanel* this = (MetersPanel*) object;
Panel_done(super);
free(this);
}
HandlerResult MetersPanel_EventHandler(Panel* super, int ch) {
void MetersPanel_setMoving(MetersPanel* this, bool moving) {
Panel* super = (Panel*) this;
this->moving = moving;
ListItem* selected = (ListItem*)Panel_getSelected(super);
if (selected) {
selected->moving = moving;
}
if (!moving) {
Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS);
Panel_setDefaultBar(super);
} else {
Panel_setSelectionColor(super, PANEL_SELECTION_FOLLOW);
super->currentBar = Meters_movingBar;
}
}
static inline bool moveToNeighbor(MetersPanel* this, MetersPanel* neighbor, int selected) {
Panel* super = (Panel*) this;
if (this->moving) {
if (neighbor) {
if (selected < Vector_size(this->meters)) {
MetersPanel_setMoving(this, false);
Meter* meter = (Meter*) Vector_take(this->meters, selected);
Panel_remove(super, selected);
Vector_insert(neighbor->meters, selected, meter);
Panel_insert(&(neighbor->super), selected, (Object*) Meter_toListItem(meter, false));
Panel_setSelected(&(neighbor->super), selected);
MetersPanel_setMoving(neighbor, true);
return true;
}
}
}
return false;
}
static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) {
MetersPanel* this = (MetersPanel*) super;
int selected = Panel_getSelectedIndex(super);
HandlerResult result = IGNORED;
bool sideMove = false;
switch(ch) {
case 0x0a:
case 0x0d:
case KEY_ENTER:
{
if (!Vector_size(this->meters))
break;
MetersPanel_setMoving(this, !(this->moving));
result = HANDLED;
break;
}
case ' ':
case KEY_F(4):
case 't':
{
if (!Vector_size(this->meters))
break;
Meter* meter = (Meter*) Vector_get(this->meters, selected);
int mode = meter->mode + 1;
if (mode == LAST_METERMODE) mode = 1;
Meter_setMode(meter, mode);
Panel_set(super, selected, (Object*) Meter_toListItem(meter));
Panel_set(super, selected, (Object*) Meter_toListItem(meter, this->moving));
result = HANDLED;
break;
}
case KEY_UP:
{
if (!this->moving) {
break;
}
}
/* else fallthrough */
case KEY_F(7):
case '[':
case '-':
@ -75,6 +132,13 @@ HandlerResult MetersPanel_EventHandler(Panel* super, int ch) {
result = HANDLED;
break;
}
case KEY_DOWN:
{
if (!this->moving) {
break;
}
}
/* else fallthrough */
case KEY_F(8):
case ']':
case '+':
@ -84,22 +148,75 @@ HandlerResult MetersPanel_EventHandler(Panel* super, int ch) {
result = HANDLED;
break;
}
case KEY_RIGHT:
{
sideMove = moveToNeighbor(this, this->rightNeighbor, selected);
if (this->moving && !sideMove) {
// lock user here until it exits positioning-mode
result = HANDLED;
}
// if user is free, don't set HANDLED;
// let ScreenManager handle focus.
break;
}
case KEY_LEFT:
{
sideMove = moveToNeighbor(this, this->leftNeighbor, selected);
if (this->moving && !sideMove) {
result = HANDLED;
}
break;
}
case KEY_F(9):
case KEY_DC:
{
if (!Vector_size(this->meters))
break;
if (selected < Vector_size(this->meters)) {
Vector_remove(this->meters, selected);
Panel_remove(super, selected);
}
MetersPanel_setMoving(this, false);
result = HANDLED;
break;
}
}
if (result == HANDLED) {
Header* header = this->settings->header;
if (result == HANDLED || sideMove) {
Header* header = this->scr->header;
this->settings->changed = true;
Header_calculateHeight(header);
Header_draw(header);
ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2);
ScreenManager_resize(this->scr);
}
return result;
}
const PanelClass MetersPanel_class = {
.super = {
.extends = Class(Panel),
.delete = MetersPanel_delete
},
.eventHandler = MetersPanel_eventHandler
};
MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr) {
MetersPanel* this = AllocThis(MetersPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(MetersFunctions, MetersKeys, MetersEvents);
if (!Meters_movingBar) {
Meters_movingBar = FunctionBar_new(MetersMovingFunctions, MetersMovingKeys, MetersMovingEvents);
}
Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar);
this->settings = settings;
this->meters = meters;
this->scr = scr;
this->moving = false;
this->rightNeighbor = NULL;
this->leftNeighbor = NULL;
Panel_setHeader(super, header);
for (int i = 0; i < Vector_size(meters); i++) {
const Meter* meter = (const Meter*) Vector_get(meters, i);
Panel_add(super, (Object*) Meter_toListItem(meter, false));
}
return this;
}

View File

@ -1,30 +1,40 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_MetersPanel
#define HEADER_MetersPanel
/*
htop - MetersPanel.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include <stdbool.h>
#include "Panel.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "debug.h"
#include <assert.h>
#include "Settings.h"
#include "Vector.h"
typedef struct MetersPanel_ {
struct MetersPanel_;
typedef struct MetersPanel_ MetersPanel;
struct MetersPanel_ {
Panel super;
Settings* settings;
Vector* meters;
ScreenManager* scr;
} MetersPanel;
MetersPanel* leftNeighbor;
MetersPanel* rightNeighbor;
bool moving;
};
void MetersPanel_cleanup(void);
MetersPanel* MetersPanel_new(Settings* settings, char* header, Vector* meters, ScreenManager* scr);
void MetersPanel_setMoving(MetersPanel* this, bool moving);
void MetersPanel_delete(Object* object);
extern const PanelClass MetersPanel_class;
HandlerResult MetersPanel_EventHandler(Panel* super, int ch);
MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr);
#endif

5
NEWS
View File

@ -1,5 +1,4 @@
See the ChangeLog for news of the past.
See the TODO list for news of the future.
See the commit history for news of the past.
See the bug tracker for news of the future.
Run the program for news of the present.

137
NetworkIOMeter.c Normal file
View File

@ -0,0 +1,137 @@
#include "NetworkIOMeter.h"
#include <stdbool.h>
#include <stdint.h>
#include "CRT.h"
#include "Macros.h"
#include "Object.h"
#include "Platform.h"
#include "Process.h"
#include "ProcessList.h"
#include "RichString.h"
#include "XUtils.h"
static const int NetworkIOMeter_attributes[] = {
METER_VALUE_IOREAD,
METER_VALUE_IOWRITE,
};
static bool hasData = false;
static uint32_t cached_rxb_diff;
static uint32_t cached_rxp_diff;
static uint32_t cached_txb_diff;
static uint32_t cached_txp_diff;
static void NetworkIOMeter_updateValues(Meter* this) {
const ProcessList* pl = this->pl;
static uint64_t cached_last_update = 0;
uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update;
/* update only every 500ms */
if (passedTimeInMs > 500) {
static uint64_t cached_rxb_total;
static uint64_t cached_rxp_total;
static uint64_t cached_txb_total;
static uint64_t cached_txp_total;
uint64_t diff;
cached_last_update = pl->realtimeMs;
NetworkIOData data;
hasData = Platform_getNetworkIO(&data);
if (!hasData) {
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "no data");
return;
}
if (data.bytesReceived > cached_rxb_total) {
diff = data.bytesReceived - cached_rxb_total;
diff /= ONE_K; /* Meter_humanUnit() expects unit in kilo */
diff = (1000 * diff) / passedTimeInMs; /* convert to per second */
cached_rxb_diff = (uint32_t)diff;
} else {
cached_rxb_diff = 0;
}
cached_rxb_total = data.bytesReceived;
if (data.packetsReceived > cached_rxp_total) {
diff = data.packetsReceived - cached_rxp_total;
cached_rxp_diff = (uint32_t)diff;
} else {
cached_rxp_diff = 0;
}
cached_rxp_total = data.packetsReceived;
if (data.bytesTransmitted > cached_txb_total) {
diff = data.bytesTransmitted - cached_txb_total;
diff /= ONE_K; /* Meter_humanUnit() expects unit in kilo */
diff = (1000 * diff) / passedTimeInMs; /* convert to per second */
cached_txb_diff = (uint32_t)diff;
} else {
cached_txb_diff = 0;
}
cached_txb_total = data.bytesTransmitted;
if (data.packetsTransmitted > cached_txp_total) {
diff = data.packetsTransmitted - cached_txp_total;
cached_txp_diff = (uint32_t)diff;
} else {
cached_txp_diff = 0;
}
cached_txp_total = data.packetsTransmitted;
}
this->values[0] = cached_rxb_diff;
this->values[1] = cached_txb_diff;
if (cached_rxb_diff + cached_txb_diff > this->total) {
this->total = cached_rxb_diff + cached_txb_diff;
}
char bufferBytesReceived[12], bufferBytesTransmitted[12];
Meter_humanUnit(bufferBytesReceived, cached_rxb_diff, sizeof(bufferBytesReceived));
Meter_humanUnit(bufferBytesTransmitted, cached_txb_diff, sizeof(bufferBytesTransmitted));
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "rx:%siB/s tx:%siB/s", bufferBytesReceived, bufferBytesTransmitted);
}
static void NetworkIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out) {
if (!hasData) {
RichString_writeAscii(out, CRT_colors[METER_VALUE_ERROR], "no data");
return;
}
char buffer[64];
int len;
RichString_writeAscii(out, CRT_colors[METER_TEXT], "rx: ");
Meter_humanUnit(buffer, cached_rxb_diff, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], buffer);
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], "iB/s");
RichString_appendAscii(out, CRT_colors[METER_TEXT], " tx: ");
Meter_humanUnit(buffer, cached_txb_diff, sizeof(buffer));
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], buffer);
RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], "iB/s");
len = xSnprintf(buffer, sizeof(buffer), " (%u/%u packets) ", cached_rxp_diff, cached_txp_diff);
RichString_appendnAscii(out, CRT_colors[METER_TEXT], buffer, len);
}
const MeterClass NetworkIOMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = NetworkIOMeter_display
},
.updateValues = NetworkIOMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 2,
.total = 100.0,
.attributes = NetworkIOMeter_attributes,
.name = "NetworkIO",
.uiName = "Network IO",
.caption = "Network: "
};

16
NetworkIOMeter.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef HEADER_NetworkIOMeter
#define HEADER_NetworkIOMeter
#include "Meter.h"
typedef struct NetworkIOData_ {
uint64_t bytesReceived;
uint64_t packetsReceived;
uint64_t bytesTransmitted;
uint64_t packetsTransmitted;
} NetworkIOData;
extern const MeterClass NetworkIOMeter_class;
#endif /* HEADER_NetworkIOMeter */

View File

@ -1,57 +1,29 @@
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - Object.c
(C) 2004-2012 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Object.h"
#include "RichString.h"
#include "CRT.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "debug.h"
#include <stddef.h>
/*{
#ifndef DEBUG
#define Object_setClass(obj, class)
#endif
typedef struct Object_ Object;
typedef void(*Object_Display)(Object*, RichString*);
typedef int(*Object_Compare)(const void*, const void*);
typedef void(*Object_Delete)(Object*);
struct Object_ {
#ifdef DEBUG
char* class;
#endif
Object_Display display;
Object_Delete delete;
const ObjectClass Object_class = {
.extends = NULL
};
}*/
#ifdef DEBUG
char* OBJECT_CLASS = "Object";
bool Object_isA(const Object* o, const ObjectClass* klass) {
if (!o)
return false;
#else
#define OBJECT_CLASS NULL
#endif
for (const ObjectClass* type = o->klass; type; type = type->extends) {
if (type == klass) {
return true;
}
}
#ifdef DEBUG
void Object_setClass(void* this, char* class) {
((Object*)this)->class = class;
return false;
}
void Object_display(Object* this, RichString* out) {
char objAddress[50];
sprintf(objAddress, "%s @ %p", this->class, (void*) this);
RichString_write(out, CRT_colors[DEFAULT_COLOR], objAddress);
}
#endif

View File

@ -1,54 +1,59 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Object
#define HEADER_Object
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
htop - Object.h
(C) 2004-2012 Hisham H. Muhammad
(C) 2020 Red Hat, Inc. All Rights Reserved.
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "RichString.h"
#include "CRT.h"
#include <stdlib.h>
#include <stdio.h>
#include "config.h" // IWYU pragma: keep
#include <assert.h>
#include <stdbool.h>
#include "debug.h"
#include "RichString.h"
#include "XUtils.h" // IWYU pragma: keep
#ifndef DEBUG
#define Object_setClass(obj, class)
#endif
struct Object_;
typedef struct Object_ Object;
typedef void(*Object_Display)(Object*, RichString*);
typedef void(*Object_Display)(const Object*, RichString*);
typedef int(*Object_Compare)(const void*, const void*);
typedef void(*Object_Delete)(Object*);
#define Object_getClass(obj_) ((const Object*)(obj_))->klass
#define Object_setClass(obj_, class_) (((Object*)(obj_))->klass = (const ObjectClass*) (class_))
#define Object_delete(obj_) (assert(Object_getClass(obj_)->delete), Object_getClass(obj_)->delete((Object*)(obj_)))
#define Object_displayFn(obj_) Object_getClass(obj_)->display
#define Object_display(obj_, str_) (assert(Object_getClass(obj_)->display), Object_getClass(obj_)->display((const Object*)(obj_), str_))
#define Object_compare(obj_, other_) (assert(Object_getClass(obj_)->compare), Object_getClass(obj_)->compare((const void*)(obj_), other_))
#define Class(class_) ((const ObjectClass*)(&(class_ ## _class)))
#define AllocThis(class_) (class_*) xMalloc(sizeof(class_)); Object_setClass(this, Class(class_))
typedef struct ObjectClass_ {
const void* const extends;
const Object_Display display;
const Object_Delete delete;
const Object_Compare compare;
} ObjectClass;
struct Object_ {
#ifdef DEBUG
char* class;
#endif
Object_Display display;
Object_Delete delete;
const ObjectClass* klass;
};
#ifdef DEBUG
extern char* OBJECT_CLASS;
typedef union {
int i;
void* v;
} Arg;
#else
#define OBJECT_CLASS NULL
#endif
extern const ObjectClass Object_class;
#ifdef DEBUG
void Object_setClass(void* this, char* class);
void Object_display(Object* this, RichString* out);
#endif
bool Object_isA(const Object* o, const ObjectClass* klass);
#endif

247
OpenFilesScreen.c Normal file
View File

@ -0,0 +1,247 @@
/*
htop - OpenFilesScreen.c
(C) 2005-2006 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "OpenFilesScreen.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Macros.h"
#include "Panel.h"
#include "ProvideCurses.h"
#include "Vector.h"
#include "XUtils.h"
typedef struct OpenFiles_Data_ {
char* data[7];
} OpenFiles_Data;
typedef struct OpenFiles_ProcessData_ {
OpenFiles_Data data;
int error;
struct OpenFiles_FileData_* files;
} OpenFiles_ProcessData;
typedef struct OpenFiles_FileData_ {
OpenFiles_Data data;
struct OpenFiles_FileData_* next;
} OpenFiles_FileData;
static size_t getIndexForType(char type) {
switch (type) {
case 'f':
return 0;
case 'a':
return 1;
case 'D':
return 2;
case 'i':
return 3;
case 'n':
return 4;
case 's':
return 5;
case 't':
return 6;
}
/* should never reach here */
abort();
}
static const char* getDataForType(const OpenFiles_Data* data, char type) {
size_t index = getIndexForType(type);
return data->data[index] ? data->data[index] : "";
}
OpenFilesScreen* OpenFilesScreen_new(const Process* process) {
OpenFilesScreen* this = xMalloc(sizeof(OpenFilesScreen));
Object_setClass(this, Class(OpenFilesScreen));
if (Process_isThread(process)) {
this->pid = process->tgid;
} else {
this->pid = process->pid;
}
return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " FD TYPE MODE DEVICE SIZE NODE NAME");
}
void OpenFilesScreen_delete(Object* this) {
free(InfoScreen_done((InfoScreen*)this));
}
static void OpenFilesScreen_draw(InfoScreen* this) {
InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, Process_getCommand(this->process));
}
static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
OpenFiles_ProcessData* pdata = xCalloc(1, sizeof(OpenFiles_ProcessData));
int fdpair[2] = {0, 0};
if (pipe(fdpair) == -1) {
pdata->error = 1;
return pdata;
}
pid_t child = fork();
if (child == -1) {
close(fdpair[1]);
close(fdpair[0]);
pdata->error = 1;
return pdata;
}
if (child == 0) {
close(fdpair[0]);
dup2(fdpair[1], STDOUT_FILENO);
close(fdpair[1]);
int fdnull = open("/dev/null", O_WRONLY);
if (fdnull < 0) {
exit(1);
}
dup2(fdnull, STDERR_FILENO);
close(fdnull);
char buffer[32] = {0};
xSnprintf(buffer, sizeof(buffer), "%d", pid);
execlp("lsof", "lsof", "-P", "-p", buffer, "-F", NULL);
exit(127);
}
close(fdpair[1]);
OpenFiles_Data* item = &(pdata->data);
OpenFiles_FileData* fdata = NULL;
FILE* fd = fdopen(fdpair[0], "r");
if (!fd) {
pdata->error = 1;
return pdata;
}
for (;;) {
char* line = String_readLine(fd);
if (!line) {
break;
}
unsigned char cmd = line[0];
switch (cmd) {
case 'f': /* file descriptor */
{
OpenFiles_FileData* nextFile = xCalloc(1, sizeof(OpenFiles_FileData));
if (fdata == NULL) {
pdata->files = nextFile;
} else {
fdata->next = nextFile;
}
fdata = nextFile;
item = &(fdata->data);
} /* FALLTHRU */
case 'a': /* file access mode */
case 'D': /* file's major/minor device number */
case 'i': /* file's inode number */
case 'n': /* file name, comment, Internet address */
case 's': /* file's size */
case 't': /* file's type */
{
size_t index = getIndexForType(cmd);
free(item->data[index]);
item->data[index] = xStrdup(line + 1);
break;
}
case 'c': /* process command name */
case 'd': /* file's device character code */
case 'g': /* process group ID */
case 'G': /* file flags */
case 'k': /* link count */
case 'l': /* file's lock status */
case 'L': /* process login name */
case 'o': /* file's offset */
case 'p': /* process ID */
case 'P': /* protocol name */
case 'R': /* parent process ID */
case 'T': /* TCP/TPI information, identified by prefixes */
case 'u': /* process user ID */
/* ignore */
break;
}
free(line);
}
fclose(fd);
int wstatus;
if (waitpid(child, &wstatus, 0) == -1) {
pdata->error = 1;
return pdata;
}
if (!WIFEXITED(wstatus)) {
pdata->error = 1;
} else {
pdata->error = WEXITSTATUS(wstatus);
}
return pdata;
}
static void OpenFiles_Data_clear(OpenFiles_Data* data) {
for (size_t i = 0; i < ARRAYSIZE(data->data); i++)
free(data->data[i]);
}
static void OpenFilesScreen_scan(InfoScreen* this) {
Panel* panel = this->display;
int idx = Panel_getSelectedIndex(panel);
Panel_prune(panel);
OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(((OpenFilesScreen*)this)->pid);
if (pdata->error == 127) {
InfoScreen_addLine(this, "Could not execute 'lsof'. Please make sure it is available in your $PATH.");
} else if (pdata->error == 1) {
InfoScreen_addLine(this, "Failed listing open files.");
} else {
OpenFiles_FileData* fdata = pdata->files;
while (fdata) {
OpenFiles_Data* data = &fdata->data;
size_t lenN = strlen(getDataForType(data, 'n'));
size_t sizeEntry = 5 + 7 + 4 + 10 + 10 + 10 + lenN + 7 /*spaces*/ + 1 /*null*/;
char entry[sizeEntry];
xSnprintf(entry, sizeof(entry), "%5.5s %-7.7s %-4.4s %-10.10s %10.10s %10.10s %s",
getDataForType(data, 'f'),
getDataForType(data, 't'),
getDataForType(data, 'a'),
getDataForType(data, 'D'),
getDataForType(data, 's'),
getDataForType(data, 'i'),
getDataForType(data, 'n'));
InfoScreen_addLine(this, entry);
OpenFiles_Data_clear(data);
OpenFiles_FileData* old = fdata;
fdata = fdata->next;
free(old);
}
OpenFiles_Data_clear(&pdata->data);
}
free(pdata);
Vector_insertionSort(this->lines);
Vector_insertionSort(panel->items);
Panel_setSelected(panel, idx);
}
const InfoScreenClass OpenFilesScreen_class = {
.super = {
.extends = Class(Object),
.delete = OpenFilesScreen_delete
},
.scan = OpenFilesScreen_scan,
.draw = OpenFilesScreen_draw
};

28
OpenFilesScreen.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef HEADER_OpenFilesScreen
#define HEADER_OpenFilesScreen
/*
htop - OpenFilesScreen.h
(C) 2005-2006 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include <sys/types.h>
#include "InfoScreen.h"
#include "Object.h"
#include "Process.h"
typedef struct OpenFilesScreen_ {
InfoScreen super;
pid_t pid;
} OpenFilesScreen;
extern const InfoScreenClass OpenFilesScreen_class;
OpenFilesScreen* OpenFilesScreen_new(const Process* process);
void OpenFilesScreen_delete(Object* this);
#endif

191
OptionItem.c Normal file
View File

@ -0,0 +1,191 @@
/*
htop - OptionItem.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "OptionItem.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include "CRT.h"
#include "Macros.h"
#include "RichString.h"
#include "XUtils.h"
static void OptionItem_delete(Object* cast) {
OptionItem* this = (OptionItem*)cast;
assert (this != NULL);
free(this->text);
free(this);
}
static void CheckItem_display(const Object* cast, RichString* out) {
const CheckItem* this = (const CheckItem*)cast;
assert (this != NULL);
RichString_writeAscii(out, CRT_colors[CHECK_BOX], "[");
if (CheckItem_get(this)) {
RichString_appendAscii(out, CRT_colors[CHECK_MARK], "x");
} else {
RichString_appendAscii(out, CRT_colors[CHECK_MARK], " ");
}
RichString_appendAscii(out, CRT_colors[CHECK_BOX], "] ");
RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->super.text);
}
static void NumberItem_display(const Object* cast, RichString* out) {
const NumberItem* this = (const NumberItem*)cast;
assert (this != NULL);
char buffer[12];
RichString_writeAscii(out, CRT_colors[CHECK_BOX], "[");
int written;
if (this->scale < 0) {
written = xSnprintf(buffer, sizeof(buffer), "%.*f", -this->scale, pow(10, this->scale) * NumberItem_get(this));
} else if (this->scale > 0) {
written = xSnprintf(buffer, sizeof(buffer), "%d", (int) (pow(10, this->scale) * NumberItem_get(this)));
} else {
written = xSnprintf(buffer, sizeof(buffer), "%d", NumberItem_get(this));
}
RichString_appendnAscii(out, CRT_colors[CHECK_MARK], buffer, written);
RichString_appendAscii(out, CRT_colors[CHECK_BOX], "]");
for (int i = written; i < 5; i++) {
RichString_appendAscii(out, CRT_colors[CHECK_BOX], " ");
}
RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->super.text);
}
const OptionItemClass OptionItem_class = {
.super = {
.extends = Class(Object),
.delete = OptionItem_delete
}
};
const OptionItemClass CheckItem_class = {
.super = {
.extends = Class(OptionItem),
.delete = OptionItem_delete,
.display = CheckItem_display
},
.kind = OPTION_ITEM_CHECK
};
const OptionItemClass NumberItem_class = {
.super = {
.extends = Class(OptionItem),
.delete = OptionItem_delete,
.display = NumberItem_display
},
.kind = OPTION_ITEM_NUMBER
};
CheckItem* CheckItem_newByRef(const char* text, bool* ref) {
CheckItem* this = AllocThis(CheckItem);
this->super.text = xStrdup(text);
this->value = false;
this->ref = ref;
return this;
}
CheckItem* CheckItem_newByVal(const char* text, bool value) {
CheckItem* this = AllocThis(CheckItem);
this->super.text = xStrdup(text);
this->value = value;
this->ref = NULL;
return this;
}
bool CheckItem_get(const CheckItem* this) {
if (this->ref) {
return *(this->ref);
} else {
return this->value;
}
}
void CheckItem_set(CheckItem* this, bool value) {
if (this->ref) {
*(this->ref) = value;
} else {
this->value = value;
}
}
void CheckItem_toggle(CheckItem* this) {
if (this->ref) {
*(this->ref) = !*(this->ref);
} else {
this->value = !this->value;
}
}
NumberItem* NumberItem_newByRef(const char* text, int* ref, int scale, int min, int max) {
assert(min <= max);
NumberItem* this = AllocThis(NumberItem);
this->super.text = xStrdup(text);
this->value = 0;
this->ref = ref;
this->scale = scale;
this->min = min;
this->max = max;
return this;
}
NumberItem* NumberItem_newByVal(const char* text, int value, int scale, int min, int max) {
assert(min <= max);
NumberItem* this = AllocThis(NumberItem);
this->super.text = xStrdup(text);
this->value = CLAMP(value, min, max);
this->ref = NULL;
this->scale = scale;
this->min = min;
this->max = max;
return this;
}
int NumberItem_get(const NumberItem* this) {
if (this->ref) {
return *(this->ref);
} else {
return this->value;
}
}
void NumberItem_decrease(NumberItem* this) {
if (this->ref) {
*(this->ref) = CLAMP(*(this->ref) - 1, this->min, this->max);
} else {
this->value = CLAMP(this->value - 1, this->min, this->max);
}
}
void NumberItem_increase(NumberItem* this) {
if (this->ref) {
*(this->ref) = CLAMP(*(this->ref) + 1, this->min, this->max);
} else {
this->value = CLAMP(this->value + 1, this->min, this->max);
}
}
void NumberItem_toggle(NumberItem* this) {
if (this->ref) {
if (*(this->ref) >= this->max)
*(this->ref) = this->min;
else
*(this->ref) += 1;
} else {
if (this->value >= this->max)
this->value = this->min;
else
this->value += 1;
}
}

70
OptionItem.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef HEADER_OptionItem
#define HEADER_OptionItem
/*
htop - OptionItem.h
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include <stdbool.h>
#include "Object.h"
enum OptionItemType {
OPTION_ITEM_CHECK,
OPTION_ITEM_NUMBER,
};
typedef struct OptionItemClass_ {
const ObjectClass super;
enum OptionItemType kind;
} OptionItemClass;
#define As_OptionItem(this_) ((const OptionItemClass*)((this_)->super.klass))
#define OptionItem_kind(this_) As_OptionItem(this_)->kind
typedef struct OptionItem_ {
Object super;
char* text;
} OptionItem;
typedef struct CheckItem_ {
OptionItem super;
bool* ref;
bool value;
} CheckItem;
typedef struct NumberItem_ {
OptionItem super;
char* text;
int* ref;
int value;
int scale;
int min;
int max;
} NumberItem;
extern const OptionItemClass OptionItem_class;
extern const OptionItemClass CheckItem_class;
extern const OptionItemClass NumberItem_class;
CheckItem* CheckItem_newByRef(const char* text, bool* ref);
CheckItem* CheckItem_newByVal(const char* text, bool value);
bool CheckItem_get(const CheckItem* this);
void CheckItem_set(CheckItem* this, bool value);
void CheckItem_toggle(CheckItem* this);
NumberItem* NumberItem_newByRef(const char* text, int* ref, int scale, int min, int max);
NumberItem* NumberItem_newByVal(const char* text, int value, int scale, int min, int max);
int NumberItem_get(const NumberItem* this);
void NumberItem_decrease(NumberItem* this);
void NumberItem_increase(NumberItem* this);
void NumberItem_toggle(NumberItem* this);
#endif

462
Panel.c
View File

@ -1,73 +1,40 @@
/*
htop - Panel.c
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Object.h"
#include "Panel.h"
#include "Vector.h"
#include "CRT.h"
#include "RichString.h"
#include "ListItem.h"
#include <math.h>
#include <stdbool.h>
#include "debug.h"
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <curses.h>
//#link curses
#include "CRT.h"
#include "ListItem.h"
#include "Macros.h"
#include "ProvideCurses.h"
#include "RichString.h"
#include "XUtils.h"
/*{
typedef struct Panel_ Panel;
typedef enum HandlerResult_ {
HANDLED,
IGNORED,
BREAK_LOOP
} HandlerResult;
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
struct Panel_ {
Object super;
int x, y, w, h;
WINDOW* window;
Vector* items;
int selected;
int scrollV, scrollH;
int scrollHAmount;
int oldSelected;
bool needsRedraw;
RichString header;
Panel_EventHandler eventHandler;
const PanelClass Panel_class = {
.super = {
.extends = Class(Object),
.delete = Panel_delete
},
.eventHandler = Panel_selectByTyping,
};
}*/
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifdef DEBUG
char* PANEL_CLASS = "Panel";
#else
#define PANEL_CLASS NULL
#endif
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) {
Panel* this;
this = malloc(sizeof(Panel));
Panel_init(this, x, y, w, h, type, owner);
this->items->compare = compare;
this = xMalloc(sizeof(Panel));
Object_setClass(this, Class(Panel));
Panel_init(this, x, y, w, h, type, owner, fuBar);
return this;
}
@ -77,48 +44,43 @@ void Panel_delete(Object* cast) {
free(this);
}
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner) {
Object* super = (Object*) this;
Object_setClass(this, PANEL_CLASS);
super->delete = Panel_delete;
void Panel_init(Panel* this, int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) {
this->x = x;
this->y = y;
this->w = w;
this->h = h;
this->eventHandler = NULL;
this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
this->eventHandlerState = NULL;
this->items = Vector_new(type, owner, DEFAULT_SIZE);
this->scrollV = 0;
this->scrollH = 0;
this->selected = 0;
this->oldSelected = 0;
this->selectedLen = 0;
this->needsRedraw = true;
this->header.len = 0;
if (String_eq(CRT_termType, "linux"))
this->scrollHAmount = 40;
else
this->scrollHAmount = 5;
this->wasFocus = false;
RichString_beginAllocated(this->header);
this->defaultBar = fuBar;
this->currentBar = fuBar;
this->selectionColorId = PANEL_SELECTION_FOCUS;
}
void Panel_done(Panel* this) {
assert (this != NULL);
free(this->eventHandlerState);
Vector_delete(this->items);
FunctionBar_delete(this->defaultBar);
RichString_delete(&this->header);
}
inline void Panel_setRichHeader(Panel* this, RichString header) {
assert (this != NULL);
void Panel_setSelectionColor(Panel* this, ColorElements colorId) {
this->selectionColorId = colorId;
}
this->header = header;
inline void Panel_setHeader(Panel* this, const char* header) {
RichString_writeWide(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
this->needsRedraw = true;
}
inline void Panel_setHeader(Panel* this, char* header) {
Panel_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
}
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
this->eventHandler = eh;
}
void Panel_move(Panel* this, int x, int y) {
assert (this != NULL);
@ -130,8 +92,6 @@ void Panel_move(Panel* this, int x, int y) {
void Panel_resize(Panel* this, int w, int h) {
assert (this != NULL);
if (this->header.len > 0)
h--;
this->w = w;
this->h = h;
this->needsRedraw = true;
@ -178,40 +138,47 @@ Object* Panel_remove(Panel* this, int i) {
this->needsRedraw = true;
Object* removed = Vector_remove(this->items, i);
if (this->selected > 0 && this->selected >= Vector_size(this->items))
if (this->selected > 0 && this->selected >= Vector_size(this->items)) {
this->selected--;
}
return removed;
}
Object* Panel_getSelected(Panel* this) {
assert (this != NULL);
if (Vector_size(this->items) > 0) {
return Vector_get(this->items, this->selected);
} else {
return NULL;
}
}
void Panel_moveSelectedUp(Panel* this) {
assert (this != NULL);
Vector_moveUp(this->items, this->selected);
if (this->selected > 0)
if (this->selected > 0) {
this->selected--;
}
}
void Panel_moveSelectedDown(Panel* this) {
assert (this != NULL);
Vector_moveDown(this->items, this->selected);
if (this->selected + 1 < Vector_size(this->items))
if (this->selected + 1 < Vector_size(this->items)) {
this->selected++;
}
}
int Panel_getSelectedIndex(Panel* this) {
int Panel_getSelectedIndex(const Panel* this) {
assert (this != NULL);
return this->selected;
}
int Panel_getSize(Panel* this) {
int Panel_size(const Panel* this) {
assert (this != NULL);
return Vector_size(this->items);
@ -220,142 +187,301 @@ int Panel_getSize(Panel* this) {
void Panel_setSelected(Panel* this, int selected) {
assert (this != NULL);
selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
int size = Vector_size(this->items);
if (selected >= size) {
selected = size - 1;
}
if (selected < 0) {
selected = 0;
}
this->selected = selected;
if (Panel_eventHandlerFn(this)) {
Panel_eventHandler(this, EVENT_SET_SELECTED);
}
}
void Panel_draw(Panel* this, bool focus) {
void Panel_splice(Panel* this, Vector* from) {
assert (this != NULL);
assert (from != NULL);
Vector_splice(this->items, from);
this->needsRedraw = true;
}
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar) {
assert (this != NULL);
int first, last;
int itemCount = Vector_size(this->items);
int size = Vector_size(this->items);
int scrollH = this->scrollH;
int y = this->y; int x = this->x;
first = this->scrollV;
int y = this->y;
int x = this->x;
int h = this->h;
if (this->h > itemCount) {
last = this->scrollV + itemCount;
move(y + last, x + 0);
} else {
last = MIN(itemCount, this->scrollV + this->h);
}
if (this->selected < first) {
first = this->selected;
this->scrollV = first;
this->needsRedraw = true;
}
if (this->selected >= last) {
last = MIN(itemCount, this->selected + 1);
first = MAX(0, last - this->h);
this->scrollV = first;
this->needsRedraw = true;
}
assert(first >= 0);
assert(last <= itemCount);
if (hideFunctionBar)
h++;
if (this->header.len > 0) {
int attr = focus
const int header_attr = focus
? CRT_colors[PANEL_HEADER_FOCUS]
: CRT_colors[PANEL_HEADER_UNFOCUS];
attrset(attr);
if (force_redraw) {
if (Panel_printHeaderFn(this))
Panel_printHeader(this);
else
RichString_setAttr(&this->header, header_attr);
}
int headerLen = RichString_sizeVal(this->header);
if (headerLen > 0) {
attrset(header_attr);
mvhline(y, x, ' ', this->w);
if (scrollH < this->header.len) {
mvaddchnstr(y, x, this->header.chstr + scrollH,
MIN(this->header.len - scrollH, this->w));
if (scrollH < headerLen) {
RichString_printoffnVal(this->header, y, x, scrollH,
MINIMUM(headerLen - scrollH, this->w));
}
attrset(CRT_colors[RESET_COLOR]);
y++;
h--;
}
int highlight = focus
? CRT_colors[PANEL_HIGHLIGHT_FOCUS]
: CRT_colors[PANEL_HIGHLIGHT_UNFOCUS];
// ensure scroll area is on screen
if (this->scrollV < 0) {
this->scrollV = 0;
this->needsRedraw = true;
} else if (this->scrollV > size - h) {
this->scrollV = MAXIMUM(size - h, 0);
this->needsRedraw = true;
}
// ensure selection is on screen
if (this->selected < this->scrollV) {
this->scrollV = this->selected;
this->needsRedraw = true;
} else if (this->selected >= this->scrollV + h) {
this->scrollV = this->selected - h + 1;
this->needsRedraw = true;
}
if (this->needsRedraw) {
int first = this->scrollV;
int upTo = MINIMUM(first + h, size);
for(int i = first, j = 0; j < this->h && i < last; i++, j++) {
Object* itemObj = Vector_get(this->items, i);
RichString itemRef;
RichString_initVal(itemRef);
itemObj->display(itemObj, &itemRef);
int amt = MIN(itemRef.len - scrollH, this->w);
if (i == this->selected) {
attrset(highlight);
RichString_setAttr(&itemRef, highlight);
mvhline(y + j, x+0, ' ', this->w);
int selectionColor = focus
? CRT_colors[this->selectionColorId]
: CRT_colors[PANEL_SELECTION_UNFOCUS];
if (this->needsRedraw || force_redraw) {
int line = 0;
for (int i = first; line < h && i < upTo; i++) {
const Object* itemObj = Vector_get(this->items, i);
RichString_begin(item);
Object_display(itemObj, &item);
int itemLen = RichString_sizeVal(item);
int amt = MINIMUM(itemLen - scrollH, this->w);
if (highlightSelected && i == this->selected) {
item.highlightAttr = selectionColor;
}
if (item.highlightAttr) {
attrset(item.highlightAttr);
RichString_setAttr(&item, item.highlightAttr);
this->selectedLen = itemLen;
}
mvhline(y + line, x, ' ', this->w);
if (amt > 0)
mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt);
RichString_printoffnVal(item, y + line, x, scrollH, amt);
if (item.highlightAttr)
attrset(CRT_colors[RESET_COLOR]);
} else {
mvhline(y+j, x+0, ' ', this->w);
if (amt > 0)
mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt);
RichString_delete(&item);
line++;
}
while (line < h) {
mvhline(y + line, x, ' ', this->w);
line++;
}
for (int i = y + (last - first); i < y + this->h; i++)
mvhline(i, x+0, ' ', this->w);
this->needsRedraw = false;
} else {
Object* oldObj = Vector_get(this->items, this->oldSelected);
RichString oldRef;
RichString_initVal(oldRef);
oldObj->display(oldObj, &oldRef);
Object* newObj = Vector_get(this->items, this->selected);
RichString newRef;
RichString_initVal(newRef);
newObj->display(newObj, &newRef);
mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
if (scrollH < oldRef.len)
mvaddchnstr(y+ this->oldSelected - this->scrollV, x+0, oldRef.chstr + this->scrollH, MIN(oldRef.len - scrollH, this->w));
attrset(highlight);
mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
RichString_setAttr(&newRef, highlight);
if (scrollH < newRef.len)
mvaddchnstr(y+this->selected - this->scrollV, x+0, newRef.chstr + this->scrollH, MIN(newRef.len - scrollH, this->w));
const Object* oldObj = Vector_get(this->items, this->oldSelected);
RichString_begin(old);
Object_display(oldObj, &old);
int oldLen = RichString_sizeVal(old);
const Object* newObj = Vector_get(this->items, this->selected);
RichString_begin(new);
Object_display(newObj, &new);
int newLen = RichString_sizeVal(new);
this->selectedLen = newLen;
mvhline(y + this->oldSelected - first, x + 0, ' ', this->w);
if (scrollH < oldLen)
RichString_printoffnVal(old, y + this->oldSelected - first, x,
scrollH, MINIMUM(oldLen - scrollH, this->w));
attrset(selectionColor);
mvhline(y + this->selected - first, x + 0, ' ', this->w);
RichString_setAttr(&new, selectionColor);
if (scrollH < newLen)
RichString_printoffnVal(new, y + this->selected - first, x,
scrollH, MINIMUM(newLen - scrollH, this->w));
attrset(CRT_colors[RESET_COLOR]);
RichString_delete(&new);
RichString_delete(&old);
}
if (focus && (this->needsRedraw || force_redraw || !this->wasFocus)) {
if (Panel_drawFunctionBarFn(this))
Panel_drawFunctionBar(this, hideFunctionBar);
else if (!hideFunctionBar)
FunctionBar_draw(this->currentBar);
}
this->oldSelected = this->selected;
this->wasFocus = focus;
this->needsRedraw = false;
move(0, 0);
}
void Panel_onKey(Panel* this, int key) {
static int Panel_headerHeight(const Panel* this) {
return RichString_sizeVal(this->header) > 0 ? 1 : 0;
}
bool Panel_onKey(Panel* this, int key) {
assert (this != NULL);
const int size = Vector_size(this->items);
#define PANEL_SCROLL(amount) \
do { \
this->selected += (amount); \
this->scrollV = CLAMP(this->scrollV + (amount), 0, MAXIMUM(0, (size - this->h - Panel_headerHeight(this)))); \
this->needsRedraw = true; \
} while (0)
switch (key) {
case KEY_DOWN:
if (this->selected + 1 < Vector_size(this->items))
case KEY_CTRL('N'):
#ifdef KEY_C_DOWN
case KEY_C_DOWN:
#endif
this->selected++;
break;
case KEY_UP:
if (this->selected > 0)
case KEY_CTRL('P'):
#ifdef KEY_C_UP
case KEY_C_UP:
#endif
this->selected--;
break;
case KEY_LEFT:
case KEY_CTRL('B'):
if (this->scrollH > 0) {
this->scrollH -= this->scrollHAmount;
this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0);
this->needsRedraw = true;
}
break;
case KEY_RIGHT:
this->scrollH += this->scrollHAmount;
case KEY_CTRL('F'):
this->scrollH += CRT_scrollHAmount;
this->needsRedraw = true;
break;
case KEY_PPAGE:
this->selected -= this->h;
if (this->selected < 0)
this->selected = 0;
PANEL_SCROLL(-(this->h - Panel_headerHeight(this)));
break;
case KEY_NPAGE:
this->selected += this->h;
int size = Vector_size(this->items);
if (this->selected >= size)
this->selected = size - 1;
PANEL_SCROLL(+(this->h - Panel_headerHeight(this)));
break;
case KEY_WHEELUP:
PANEL_SCROLL(-CRT_scrollWheelVAmount);
break;
case KEY_WHEELDOWN:
PANEL_SCROLL(+CRT_scrollWheelVAmount);
break;
case KEY_HOME:
this->selected = 0;
break;
case KEY_END:
this->selected = Vector_size(this->items) - 1;
this->selected = size - 1;
break;
case KEY_CTRL('A'):
case '^':
this->scrollH = 0;
this->needsRedraw = true;
break;
case KEY_CTRL('E'):
case '$':
this->scrollH = MAXIMUM(this->selectedLen - this->w, 0);
this->needsRedraw = true;
break;
default:
return false;
}
#undef PANEL_SCROLL
// ensure selection within bounds
if (this->selected < 0 || size == 0) {
this->selected = 0;
this->needsRedraw = true;
} else if (this->selected >= size) {
this->selected = size - 1;
this->needsRedraw = true;
}
return true;
}
HandlerResult Panel_selectByTyping(Panel* this, int ch) {
int size = Panel_size(this);
if (!this->eventHandlerState)
this->eventHandlerState = xCalloc(100, sizeof(char));
char* buffer = this->eventHandlerState;
if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) {
int len = strlen(buffer);
if (!len) {
if ('/' == ch) {
ch = '\001';
} else if ('q' == ch) {
return BREAK_LOOP;
}
} else if (1 == len && '\001' == buffer[0]) {
len--;
}
if (len < 99) {
buffer[len] = ch;
buffer[len + 1] = '\0';
}
for (int try = 0; try < 2; try++) {
len = strlen(buffer);
for (int i = 0; i < size; i++) {
const char* cur = ((ListItem*) Panel_get(this, i))->value;
while (*cur == ' ') cur++;
if (strncasecmp(cur, buffer, len) == 0) {
Panel_setSelected(this, i);
return HANDLED;
}
}
// if current word did not match,
// retry considering the character the start of a new word.
buffer[0] = ch;
buffer[1] = '\0';
}
return HANDLED;
} else if (ch != ERR) {
buffer[0] = '\0';
}
if (ch == 13) {
return BREAK_LOOP;
}
return IGNORED;
}

110
Panel.h
View File

@ -1,82 +1,98 @@
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_Panel
#define HEADER_Panel
/*
htop - Panel.h
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
#include "Object.h"
#include "Vector.h"
#include "CRT.h"
#include "RichString.h"
#include "ListItem.h"
#include "config.h" // IWYU pragma: keep
#include <math.h>
#include <assert.h>
#include <stdbool.h>
#include "debug.h"
#include <assert.h>
#include <curses.h>
//#link curses
#include "CRT.h"
#include "FunctionBar.h"
#include "Object.h"
#include "RichString.h"
#include "Vector.h"
struct Panel_;
typedef struct Panel_ Panel;
typedef enum HandlerResult_ {
HANDLED,
IGNORED,
BREAK_LOOP
HANDLED = 0x01,
IGNORED = 0x02,
BREAK_LOOP = 0x04,
REFRESH = 0x08,
REDRAW = 0x10,
RESCAN = 0x20,
RESIZE = 0x40,
SYNTH_KEY = 0x80,
} HandlerResult;
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
#define EVENT_SET_SELECTED (-1)
#define EVENT_HEADER_CLICK(x_) (-10000 + (x_))
#define EVENT_IS_HEADER_CLICK(ev_) ((ev_) >= -10000 && (ev_) <= -9000)
#define EVENT_HEADER_CLICK_GET_X(ev_) ((ev_) + 10000)
typedef HandlerResult (*Panel_EventHandler)(Panel*, int);
typedef void (*Panel_DrawFunctionBar)(Panel*, bool);
typedef void (*Panel_PrintHeader)(Panel*);
typedef struct PanelClass_ {
const ObjectClass super;
const Panel_EventHandler eventHandler;
const Panel_DrawFunctionBar drawFunctionBar;
const Panel_PrintHeader printHeader;
} PanelClass;
#define As_Panel(this_) ((const PanelClass*)((this_)->super.klass))
#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler
#define Panel_eventHandler(this_, ev_) (assert(As_Panel(this_)->eventHandler), As_Panel(this_)->eventHandler((Panel*)(this_), ev_))
#define Panel_drawFunctionBarFn(this_) As_Panel(this_)->drawFunctionBar
#define Panel_drawFunctionBar(this_, hideFB_) (assert(As_Panel(this_)->drawFunctionBar), As_Panel(this_)->drawFunctionBar((Panel*)(this_), hideFB_))
#define Panel_printHeaderFn(this_) As_Panel(this_)->printHeader
#define Panel_printHeader(this_) (assert(As_Panel(this_)->printHeader), As_Panel(this_)->printHeader((Panel*)(this_)))
struct Panel_ {
Object super;
int x, y, w, h;
WINDOW* window;
Vector* items;
int selected;
int scrollV, scrollH;
int scrollHAmount;
int oldSelected;
int selectedLen;
void* eventHandlerState;
int scrollV;
short scrollH;
bool needsRedraw;
bool wasFocus;
FunctionBar* currentBar;
FunctionBar* defaultBar;
RichString header;
Panel_EventHandler eventHandler;
ColorElements selectionColorId;
};
#define Panel_setDefaultBar(this_) do { (this_)->currentBar = (this_)->defaultBar; } while (0)
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#define KEY_CTRL(l) ((l)-'A'+1)
#ifdef DEBUG
extern char* PANEL_CLASS;
#else
#define PANEL_CLASS NULL
#endif
extern const PanelClass Panel_class;
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare);
Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar);
void Panel_delete(Object* cast);
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner);
void Panel_init(Panel* this, int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar);
void Panel_done(Panel* this);
extern void Panel_setRichHeader(Panel* this, RichString header);
void Panel_setSelectionColor(Panel* this, ColorElements colorId);
extern void Panel_setHeader(Panel* this, char* header);
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh);
void Panel_setHeader(Panel* this, const char* header);
void Panel_move(Panel* this, int x, int y);
@ -100,14 +116,18 @@ void Panel_moveSelectedUp(Panel* this);
void Panel_moveSelectedDown(Panel* this);
int Panel_getSelectedIndex(Panel* this);
int Panel_getSelectedIndex(const Panel* this);
int Panel_getSize(Panel* this);
int Panel_size(const Panel* this);
void Panel_setSelected(Panel* this, int selected);
void Panel_draw(Panel* this, bool focus);
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar);
void Panel_onKey(Panel* this, int key);
void Panel_splice(Panel* this, Vector* from);
bool Panel_onKey(Panel* this, int key);
HandlerResult Panel_selectByTyping(Panel* this, int ch);
#endif

Some files were not shown because too many files have changed in this diff Show More