7 Commits
3.2.1 ... main

Author SHA1 Message Date
eebd5e8517 add rpi model 3b+ to tested list 2022-06-10 20:19:39 +03:00
7044d546ea rename ui names for cpu freq/temp 2022-06-10 20:14:06 +03:00
765e3de1e7 fix temp meter duplication 2022-06-10 20:12:16 +03:00
637550ed51 disclaimer 2022-06-07 20:14:57 +03:00
fc016ae780 new screenshot 2022-06-07 22:36:05 +03:00
36260b5814 CPU Temperature and Frequency meter for Linux platform 2022-06-07 22:16:47 +03:00
611ea4606f Prevent null pointer dereference on early error
If a fatal error occurs before CRT_init has been called, CRT_done
dereferences NULL in CRT_colors.

Simply check if CRT_crashSettings is not NULL, which is eventually
set when CRT_init has been called.

If it is not set, then do not try to disable ncurses.

Proof of Concept (on Linux):

$ ./configure --with-proc=/var/empty
$ make
$ ./htop
2022-06-03 20:11:24 +02:00
12 changed files with 1989 additions and 1439 deletions

333
CRT.c
View File

@ -27,21 +27,20 @@ in the source distribution for its full text.
#endif #endif
#if defined(HAVE_LIBUNWIND_H) && defined(HAVE_LIBUNWIND) #if defined(HAVE_LIBUNWIND_H) && defined(HAVE_LIBUNWIND)
# define PRINT_BACKTRACE #define PRINT_BACKTRACE
# define UNW_LOCAL_ONLY #define UNW_LOCAL_ONLY
# include <libunwind.h> #include <libunwind.h>
# if defined(HAVE_DLADDR) #if defined(HAVE_DLADDR)
# include <dlfcn.h> #include <dlfcn.h>
# endif #endif
#elif defined(HAVE_EXECINFO_H) #elif defined(HAVE_EXECINFO_H)
# define PRINT_BACKTRACE #define PRINT_BACKTRACE
# include <execinfo.h> #include <execinfo.h>
#endif #endif
#define ColorIndex(i, j) ((7 - (i)) * 8 + (j))
#define ColorIndex(i,j) ((7-(i))*8+(j)) #define ColorPair(i, j) COLOR_PAIR(ColorIndex(i, j))
#define ColorPair(i,j) COLOR_PAIR(ColorIndex(i,j))
#define Black COLOR_BLACK #define Black COLOR_BLACK
#define Red COLOR_RED #define Red COLOR_RED
@ -52,13 +51,13 @@ in the source distribution for its full text.
#define Cyan COLOR_CYAN #define Cyan COLOR_CYAN
#define White COLOR_WHITE #define White COLOR_WHITE
#define ColorPairGrayBlack ColorPair(Magenta,Magenta) #define ColorPairGrayBlack ColorPair(Magenta, Magenta)
#define ColorIndexGrayBlack ColorIndex(Magenta,Magenta) #define ColorIndexGrayBlack ColorIndex(Magenta, Magenta)
#define ColorPairWhiteDefault ColorPair(Red, Red) #define ColorPairWhiteDefault ColorPair(Red, Red)
#define ColorIndexWhiteDefault ColorIndex(Red, Red) #define ColorIndexWhiteDefault ColorIndex(Red, Red)
static const char* const CRT_treeStrAscii[LAST_TREE_STR] = { static const char *const CRT_treeStrAscii[LAST_TREE_STR] = {
[TREE_STR_VERT] = "|", [TREE_STR_VERT] = "|",
[TREE_STR_RTEE] = "`", [TREE_STR_RTEE] = "`",
[TREE_STR_BEND] = "`", [TREE_STR_BEND] = "`",
@ -71,7 +70,7 @@ static const char* const CRT_treeStrAscii[LAST_TREE_STR] = {
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
static const char* const CRT_treeStrUtf8[LAST_TREE_STR] = { static const char *const CRT_treeStrUtf8[LAST_TREE_STR] = {
[TREE_STR_VERT] = "\xe2\x94\x82", // │ [TREE_STR_VERT] = "\xe2\x94\x82", // │
[TREE_STR_RTEE] = "\xe2\x94\x9c", // ├ [TREE_STR_RTEE] = "\xe2\x94\x9c", // ├
[TREE_STR_BEND] = "\xe2\x94\x94", // └ [TREE_STR_BEND] = "\xe2\x94\x94", // └
@ -88,14 +87,15 @@ bool CRT_utf8 = false;
#endif #endif
const char* const* CRT_treeStr = CRT_treeStrAscii; const char *const *CRT_treeStr = CRT_treeStrAscii;
static const Settings* CRT_crashSettings; static const Settings *CRT_crashSettings;
static const int* CRT_delay; static const int *CRT_delay;
const char* CRT_degreeSign; const char *CRT_degreeSign;
static const char* initDegreeSign(void) { static const char *initDegreeSign(void)
{
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
if (CRT_utf8) if (CRT_utf8)
return "\xc2\xb0"; return "\xc2\xb0";
@ -110,7 +110,7 @@ static const char* initDegreeSign(void) {
return ""; return "";
} }
const int* CRT_colors; const int *CRT_colors;
static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[COLORSCHEME_DEFAULT] = { [COLORSCHEME_DEFAULT] = {
@ -127,6 +127,8 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[FAILED_READ] = A_BOLD | ColorPair(Red, Black), [FAILED_READ] = A_BOLD | ColorPair(Red, Black),
[PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan),
[UPTIME] = A_BOLD | ColorPair(Cyan, Black), [UPTIME] = A_BOLD | ColorPair(Cyan, Black),
[TEMP] = A_BOLD | ColorPair(Cyan, Black),
[FREQ] = A_BOLD | ColorPair(Cyan, Black),
[BATTERY] = A_BOLD | ColorPair(Cyan, Black), [BATTERY] = A_BOLD | ColorPair(Cyan, Black),
[LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black), [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black),
[METER_SHADOW] = A_BOLD | ColorPairGrayBlack, [METER_SHADOW] = A_BOLD | ColorPairGrayBlack,
@ -234,6 +236,8 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[FAILED_READ] = A_BOLD, [FAILED_READ] = A_BOLD,
[PAUSED] = A_BOLD | A_REVERSE, [PAUSED] = A_BOLD | A_REVERSE,
[UPTIME] = A_BOLD, [UPTIME] = A_BOLD,
[TEMP] = A_BOLD,
[FREQ] = A_BOLD,
[BATTERY] = A_BOLD, [BATTERY] = A_BOLD,
[LARGE_NUMBER] = A_BOLD, [LARGE_NUMBER] = A_BOLD,
[METER_SHADOW] = A_DIM, [METER_SHADOW] = A_DIM,
@ -341,6 +345,8 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[FAILED_READ] = ColorPair(Red, White), [FAILED_READ] = ColorPair(Red, White),
[PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan),
[UPTIME] = ColorPair(Yellow, White), [UPTIME] = ColorPair(Yellow, White),
[TEMP] = ColorPair(Yellow, White),
[FREQ] = ColorPair(Yellow, White),
[BATTERY] = ColorPair(Yellow, White), [BATTERY] = ColorPair(Yellow, White),
[LARGE_NUMBER] = ColorPair(Red, White), [LARGE_NUMBER] = ColorPair(Red, White),
[METER_SHADOW] = ColorPair(Blue, White), [METER_SHADOW] = ColorPair(Blue, White),
@ -408,11 +414,11 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue, White), [CPU_SOFTIRQ] = ColorPair(Blue, White),
[CPU_STEAL] = ColorPair(Cyan, White), [CPU_STEAL] = ColorPair(Cyan, White),
[CPU_GUEST] = ColorPair(Cyan, White), [CPU_GUEST] = ColorPair(Cyan, White),
[PANEL_EDIT] = ColorPair(White,Blue), [PANEL_EDIT] = ColorPair(White, Blue),
[SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Black,White), [SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Black, White),
[SCREENS_OTH_TEXT] = A_BOLD | ColorPair(Black,White), [SCREENS_OTH_TEXT] = A_BOLD | ColorPair(Black, White),
[SCREENS_CUR_BORDER] = ColorPair(Green,Green), [SCREENS_CUR_BORDER] = ColorPair(Green, Green),
[SCREENS_CUR_TEXT] = ColorPair(Black,Green), [SCREENS_CUR_TEXT] = ColorPair(Black, Green),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, White), [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, White),
[PRESSURE_STALL_SIXTY] = ColorPair(Black, White), [PRESSURE_STALL_SIXTY] = ColorPair(Black, White),
[PRESSURE_STALL_TEN] = ColorPair(Black, White), [PRESSURE_STALL_TEN] = ColorPair(Black, White),
@ -448,6 +454,8 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[FAILED_READ] = ColorPair(Red, Black), [FAILED_READ] = ColorPair(Red, Black),
[PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan),
[UPTIME] = ColorPair(Yellow, Black), [UPTIME] = ColorPair(Yellow, Black),
[TEMP] = ColorPair(Yellow, Black),
[FREQ] = ColorPair(Yellow, Black),
[BATTERY] = ColorPair(Yellow, Black), [BATTERY] = ColorPair(Yellow, Black),
[LARGE_NUMBER] = ColorPair(Red, Black), [LARGE_NUMBER] = ColorPair(Red, Black),
[METER_SHADOW] = A_BOLD | ColorPairGrayBlack, [METER_SHADOW] = A_BOLD | ColorPairGrayBlack,
@ -515,11 +523,11 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue, Black), [CPU_SOFTIRQ] = ColorPair(Blue, Black),
[CPU_STEAL] = ColorPair(Black, Black), [CPU_STEAL] = ColorPair(Black, Black),
[CPU_GUEST] = ColorPair(Black, Black), [CPU_GUEST] = ColorPair(Black, Black),
[PANEL_EDIT] = ColorPair(White,Blue), [PANEL_EDIT] = ColorPair(White, Blue),
[SCREENS_OTH_BORDER] = ColorPair(Blue,Black), [SCREENS_OTH_BORDER] = ColorPair(Blue, Black),
[SCREENS_OTH_TEXT] = ColorPair(Blue,Black), [SCREENS_OTH_TEXT] = ColorPair(Blue, Black),
[SCREENS_CUR_BORDER] = ColorPair(Green,Green), [SCREENS_CUR_BORDER] = ColorPair(Green, Green),
[SCREENS_CUR_TEXT] = ColorPair(Black,Green), [SCREENS_CUR_TEXT] = ColorPair(Black, Green),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, Black), [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, Black),
[PRESSURE_STALL_SIXTY] = ColorPair(Black, Black), [PRESSURE_STALL_SIXTY] = ColorPair(Black, Black),
[PRESSURE_STALL_TEN] = ColorPair(Black, Black), [PRESSURE_STALL_TEN] = ColorPair(Black, Black),
@ -555,6 +563,8 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[FAILED_READ] = A_BOLD | ColorPair(Red, Blue), [FAILED_READ] = A_BOLD | ColorPair(Red, Blue),
[PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan),
[UPTIME] = A_BOLD | ColorPair(Yellow, Blue), [UPTIME] = A_BOLD | ColorPair(Yellow, Blue),
[TEMP] = A_BOLD | ColorPair(Yellow, Blue),
[FREQ] = A_BOLD | ColorPair(Yellow, Blue),
[BATTERY] = A_BOLD | ColorPair(Yellow, Blue), [BATTERY] = A_BOLD | ColorPair(Yellow, Blue),
[LARGE_NUMBER] = A_BOLD | ColorPair(Red, Blue), [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Blue),
[METER_SHADOW] = ColorPair(Cyan, Blue), [METER_SHADOW] = ColorPair(Cyan, Blue),
@ -622,11 +632,11 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Black, Blue), [CPU_SOFTIRQ] = ColorPair(Black, Blue),
[CPU_STEAL] = ColorPair(White, Blue), [CPU_STEAL] = ColorPair(White, Blue),
[CPU_GUEST] = ColorPair(White, Blue), [CPU_GUEST] = ColorPair(White, Blue),
[PANEL_EDIT] = ColorPair(White,Blue), [PANEL_EDIT] = ColorPair(White, Blue),
[SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Yellow,Blue), [SCREENS_OTH_BORDER] = A_BOLD | ColorPair(Yellow, Blue),
[SCREENS_OTH_TEXT] = ColorPair(Cyan,Blue), [SCREENS_OTH_TEXT] = ColorPair(Cyan, Blue),
[SCREENS_CUR_BORDER] = ColorPair(Cyan,Cyan), [SCREENS_CUR_BORDER] = ColorPair(Cyan, Cyan),
[SCREENS_CUR_TEXT] = ColorPair(Black,Cyan), [SCREENS_CUR_TEXT] = ColorPair(Black, Cyan),
[PRESSURE_STALL_THREEHUNDRED] = A_BOLD | ColorPair(Black, Blue), [PRESSURE_STALL_THREEHUNDRED] = A_BOLD | ColorPair(Black, Blue),
[PRESSURE_STALL_SIXTY] = A_NORMAL | ColorPair(White, Blue), [PRESSURE_STALL_SIXTY] = A_NORMAL | ColorPair(White, Blue),
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Blue), [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Blue),
@ -662,6 +672,8 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[FAILED_READ] = A_BOLD | ColorPair(Red, Black), [FAILED_READ] = A_BOLD | ColorPair(Red, Black),
[PAUSED] = A_BOLD | ColorPair(Yellow, Green), [PAUSED] = A_BOLD | ColorPair(Yellow, Green),
[UPTIME] = ColorPair(Green, Black), [UPTIME] = ColorPair(Green, Black),
[TEMP] = ColorPair(Green, Black),
[FREQ] = ColorPair(Green, Black),
[BATTERY] = ColorPair(Green, Black), [BATTERY] = ColorPair(Green, Black),
[LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black), [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black),
[METER_SHADOW] = A_BOLD | ColorPairGrayBlack, [METER_SHADOW] = A_BOLD | ColorPairGrayBlack,
@ -727,11 +739,11 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue, Black), [CPU_SOFTIRQ] = ColorPair(Blue, Black),
[CPU_STEAL] = ColorPair(Cyan, Black), [CPU_STEAL] = ColorPair(Cyan, Black),
[CPU_GUEST] = ColorPair(Cyan, Black), [CPU_GUEST] = ColorPair(Cyan, Black),
[PANEL_EDIT] = ColorPair(White,Cyan), [PANEL_EDIT] = ColorPair(White, Cyan),
[SCREENS_OTH_BORDER] = ColorPair(White,Black), [SCREENS_OTH_BORDER] = ColorPair(White, Black),
[SCREENS_OTH_TEXT] = ColorPair(Cyan,Black), [SCREENS_OTH_TEXT] = ColorPair(Cyan, Black),
[SCREENS_CUR_BORDER] = A_BOLD | ColorPair(White,Black), [SCREENS_CUR_BORDER] = A_BOLD | ColorPair(White, Black),
[SCREENS_CUR_TEXT] = A_BOLD | ColorPair(Green,Black), [SCREENS_CUR_TEXT] = A_BOLD | ColorPair(Green, Black),
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Green, Black), [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Green, Black),
[PRESSURE_STALL_SIXTY] = ColorPair(Green, Black), [PRESSURE_STALL_SIXTY] = ColorPair(Green, Black),
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(Green, Black), [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(Green, Black),
@ -753,7 +765,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[DYNAMIC_YELLOW] = ColorPair(Yellow, Black), [DYNAMIC_YELLOW] = ColorPair(Yellow, Black),
[DYNAMIC_WHITE] = ColorPair(White, Black), [DYNAMIC_WHITE] = ColorPair(White, Black),
}, },
[COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated. [COLORSCHEME_BROKENGRAY] = {0} // dynamically generated.
}; };
int CRT_scrollHAmount = 5; int CRT_scrollHAmount = 5;
@ -763,7 +775,8 @@ int CRT_scrollWheelVAmount = 10;
ColorScheme CRT_colorScheme = COLORSCHEME_DEFAULT; ColorScheme CRT_colorScheme = COLORSCHEME_DEFAULT;
ATTR_NORETURN ATTR_NORETURN
static void CRT_handleSIGTERM(ATTR_UNUSED int sgn) { static void CRT_handleSIGTERM(ATTR_UNUSED int sgn)
{
CRT_done(); CRT_done();
_exit(0); _exit(0);
} }
@ -773,7 +786,8 @@ static void CRT_handleSIGTERM(ATTR_UNUSED int sgn) {
static int stderrRedirectNewFd = -1; static int stderrRedirectNewFd = -1;
static int stderrRedirectBackupFd = -1; static int stderrRedirectBackupFd = -1;
static int createStderrCacheFile(void) { static int createStderrCacheFile(void)
{
#if defined(HAVE_MEMFD_CREATE) #if defined(HAVE_MEMFD_CREATE)
return memfd_create("htop.stderr-redirect", 0); return memfd_create("htop.stderr-redirect", 0);
#elif defined(O_TMPFILE) #elif defined(O_TMPFILE)
@ -786,15 +800,17 @@ static int createStderrCacheFile(void) {
if (r < 0) if (r < 0)
return r; return r;
(void) unlink(tmpName); (void)unlink(tmpName);
return r; return r;
#endif /* HAVE_MEMFD_CREATE */ #endif /* HAVE_MEMFD_CREATE */
} }
static void redirectStderr(void) { static void redirectStderr(void)
{
stderrRedirectNewFd = createStderrCacheFile(); stderrRedirectNewFd = createStderrCacheFile();
if (stderrRedirectNewFd < 0) { if (stderrRedirectNewFd < 0)
{
/* ignore failure */ /* ignore failure */
return; return;
} }
@ -803,7 +819,8 @@ static void redirectStderr(void) {
dup2(stderrRedirectNewFd, STDERR_FILENO); dup2(stderrRedirectNewFd, STDERR_FILENO);
} }
static void dumpStderr(void) { static void dumpStderr(void)
{
if (stderrRedirectNewFd < 0) if (stderrRedirectNewFd < 0)
return; return;
@ -815,26 +832,31 @@ static void dumpStderr(void) {
bool header = false; bool header = false;
char buffer[8192]; char buffer[8192];
for (;;) { for (;;)
{
errno = 0; errno = 0;
ssize_t res = read(stderrRedirectNewFd, buffer, sizeof(buffer)); ssize_t res = read(stderrRedirectNewFd, buffer, sizeof(buffer));
if (res < 0) { if (res < 0)
{
if (errno == EINTR) if (errno == EINTR)
continue; continue;
break; break;
} }
if (res == 0) { if (res == 0)
{
break; break;
} }
if (res > 0) { if (res > 0)
if (!header) { {
if (!header)
{
fprintf(stderr, ">>>>>>>>>> stderr output >>>>>>>>>>\n"); fprintf(stderr, ">>>>>>>>>> stderr output >>>>>>>>>>\n");
header = true; header = true;
} }
(void)! write(STDERR_FILENO, buffer, res); (void)!write(STDERR_FILENO, buffer, res);
} }
} }
@ -845,7 +867,8 @@ static void dumpStderr(void) {
stderrRedirectNewFd = -1; stderrRedirectNewFd = -1;
} }
void CRT_debug_impl(const char* file, size_t lineno, const char* func, const char* fmt, ...) { void CRT_debug_impl(const char *file, size_t lineno, const char *func, const char *fmt, ...)
{
va_list args; va_list args;
fprintf(stderr, "[%s:%zu (%s)]: ", file, lineno, func); fprintf(stderr, "[%s:%zu (%s)]: ", file, lineno, func);
@ -857,28 +880,31 @@ void CRT_debug_impl(const char* file, size_t lineno, const char* func, const cha
#else /* !NDEBUG */ #else /* !NDEBUG */
static void redirectStderr(void) { static void redirectStderr(void)
{
} }
static void dumpStderr(void) { static void dumpStderr(void)
{
} }
#endif /* !NDEBUG */ #endif /* !NDEBUG */
static struct sigaction old_sig_handler[32]; static struct sigaction old_sig_handler[32];
static void CRT_installSignalHandlers(void) { static void CRT_installSignalHandlers(void)
{
struct sigaction act; struct sigaction act;
sigemptyset (&act.sa_mask); sigemptyset(&act.sa_mask);
act.sa_flags = (int)SA_RESETHAND | SA_NODEFER; act.sa_flags = (int)SA_RESETHAND | SA_NODEFER;
act.sa_handler = CRT_handleSIGSEGV; act.sa_handler = CRT_handleSIGSEGV;
sigaction (SIGSEGV, &act, &old_sig_handler[SIGSEGV]); sigaction(SIGSEGV, &act, &old_sig_handler[SIGSEGV]);
sigaction (SIGFPE, &act, &old_sig_handler[SIGFPE]); sigaction(SIGFPE, &act, &old_sig_handler[SIGFPE]);
sigaction (SIGILL, &act, &old_sig_handler[SIGILL]); sigaction(SIGILL, &act, &old_sig_handler[SIGILL]);
sigaction (SIGBUS, &act, &old_sig_handler[SIGBUS]); sigaction(SIGBUS, &act, &old_sig_handler[SIGBUS]);
sigaction (SIGPIPE, &act, &old_sig_handler[SIGPIPE]); sigaction(SIGPIPE, &act, &old_sig_handler[SIGPIPE]);
sigaction (SIGSYS, &act, &old_sig_handler[SIGSYS]); sigaction(SIGSYS, &act, &old_sig_handler[SIGSYS]);
sigaction (SIGABRT, &act, &old_sig_handler[SIGABRT]); sigaction(SIGABRT, &act, &old_sig_handler[SIGABRT]);
signal(SIGCHLD, SIG_DFL); signal(SIGCHLD, SIG_DFL);
signal(SIGINT, CRT_handleSIGTERM); signal(SIGINT, CRT_handleSIGTERM);
@ -886,35 +912,41 @@ static void CRT_installSignalHandlers(void) {
signal(SIGQUIT, CRT_handleSIGTERM); signal(SIGQUIT, CRT_handleSIGTERM);
} }
void CRT_resetSignalHandlers(void) { void CRT_resetSignalHandlers(void)
sigaction (SIGSEGV, &old_sig_handler[SIGSEGV], NULL); {
sigaction (SIGFPE, &old_sig_handler[SIGFPE], NULL); sigaction(SIGSEGV, &old_sig_handler[SIGSEGV], NULL);
sigaction (SIGILL, &old_sig_handler[SIGILL], NULL); sigaction(SIGFPE, &old_sig_handler[SIGFPE], NULL);
sigaction (SIGBUS, &old_sig_handler[SIGBUS], NULL); sigaction(SIGILL, &old_sig_handler[SIGILL], NULL);
sigaction (SIGPIPE, &old_sig_handler[SIGPIPE], NULL); sigaction(SIGBUS, &old_sig_handler[SIGBUS], NULL);
sigaction (SIGSYS, &old_sig_handler[SIGSYS], NULL); sigaction(SIGPIPE, &old_sig_handler[SIGPIPE], NULL);
sigaction (SIGABRT, &old_sig_handler[SIGABRT], NULL); sigaction(SIGSYS, &old_sig_handler[SIGSYS], NULL);
sigaction(SIGABRT, &old_sig_handler[SIGABRT], NULL);
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL); signal(SIGTERM, SIG_DFL);
signal(SIGQUIT, SIG_DFL); signal(SIGQUIT, SIG_DFL);
} }
void CRT_setMouse(bool enabled) { void CRT_setMouse(bool enabled)
{
#ifdef HAVE_GETMOUSE #ifdef HAVE_GETMOUSE
if (enabled) { if (enabled)
{
#if NCURSES_MOUSE_VERSION > 1 #if NCURSES_MOUSE_VERSION > 1
mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL); mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL);
#else #else
mousemask(BUTTON1_RELEASED, NULL); mousemask(BUTTON1_RELEASED, NULL);
#endif #endif
} else { }
else
{
mousemask(0, NULL); mousemask(0, NULL);
} }
#endif #endif
} }
void CRT_init(const Settings* settings, bool allowUnicode) { void CRT_init(const Settings *settings, bool allowUnicode)
{
redirectStderr(); redirectStderr();
initscr(); initscr();
@ -924,7 +956,8 @@ void CRT_init(const Settings* settings, bool allowUnicode) {
CRT_colors = CRT_colorSchemes[settings->colorScheme]; CRT_colors = CRT_colorSchemes[settings->colorScheme];
CRT_colorScheme = settings->colorScheme; CRT_colorScheme = settings->colorScheme;
for (int i = 0; i < LAST_COLORELEMENT; i++) { for (int i = 0; i < LAST_COLORELEMENT; i++)
{
unsigned int color = CRT_colorSchemes[COLORSCHEME_DEFAULT][i]; unsigned int color = CRT_colorSchemes[COLORSCHEME_DEFAULT][i];
CRT_colorSchemes[COLORSCHEME_BROKENGRAY][i] = color == (A_BOLD | ColorPairGrayBlack) ? ColorPair(White, Black) : color; CRT_colorSchemes[COLORSCHEME_BROKENGRAY][i] = color == (A_BOLD | ColorPairGrayBlack) ? ColorPair(White, Black) : color;
} }
@ -938,21 +971,26 @@ void CRT_init(const Settings* settings, bool allowUnicode) {
#endif #endif
curs_set(0); curs_set(0);
if (has_colors()) { if (has_colors())
{
start_color(); start_color();
} }
const char* termType = getenv("TERM"); const char *termType = getenv("TERM");
if (termType && String_eq(termType, "linux")) { if (termType && String_eq(termType, "linux"))
{
CRT_scrollHAmount = 20; CRT_scrollHAmount = 20;
} else { }
else
{
CRT_scrollHAmount = 5; CRT_scrollHAmount = 5;
} }
if (termType && (String_startsWith(termType, "xterm") || String_eq(termType, "vt220"))) { if (termType && (String_startsWith(termType, "xterm") || String_eq(termType, "vt220")))
{
#ifdef HTOP_NETBSD #ifdef HTOP_NETBSD
#define define_key(s_, k_) define_key((char*)s_, k_) #define define_key(s_, k_) define_key((char *)s_, k_)
IGNORE_WCASTQUAL_BEGIN IGNORE_WCASTQUAL_BEGIN
#endif #endif
define_key("\033[H", KEY_HOME); define_key("\033[H", KEY_HOME);
define_key("\033[F", KEY_END); define_key("\033[F", KEY_END);
@ -971,16 +1009,18 @@ IGNORE_WCASTQUAL_BEGIN
define_key("\033[17;2~", KEY_F(18)); define_key("\033[17;2~", KEY_F(18));
define_key("\033[Z", KEY_SHIFT_TAB); define_key("\033[Z", KEY_SHIFT_TAB);
char sequence[3] = "\033a"; char sequence[3] = "\033a";
for (char c = 'a'; c <= 'z'; c++) { for (char c = 'a'; c <= 'z'; c++)
{
sequence[1] = c; sequence[1] = c;
define_key(sequence, KEY_ALT('A' + (c - 'a'))); define_key(sequence, KEY_ALT('A' + (c - 'a')));
} }
#ifdef HTOP_NETBSD #ifdef HTOP_NETBSD
IGNORE_WCASTQUAL_END IGNORE_WCASTQUAL_END
#undef define_key #undef define_key
#endif #endif
} }
if (termType && (String_startsWith(termType, "rxvt"))) { if (termType && (String_startsWith(termType, "rxvt")))
{
define_key("\033[Z", KEY_SHIFT_TAB); define_key("\033[Z", KEY_SHIFT_TAB);
} }
@ -992,13 +1032,16 @@ IGNORE_WCASTQUAL_END
CRT_setColors(CRT_colorScheme); CRT_setColors(CRT_colorScheme);
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
if (allowUnicode && String_eq(nl_langinfo(CODESET), "UTF-8")) { if (allowUnicode && String_eq(nl_langinfo(CODESET), "UTF-8"))
{
CRT_utf8 = true; CRT_utf8 = true;
} else { }
else
{
CRT_utf8 = false; CRT_utf8 = false;
} }
#else #else
(void) allowUnicode; (void)allowUnicode;
#endif #endif
CRT_treeStr = CRT_treeStr =
@ -1012,10 +1055,13 @@ IGNORE_WCASTQUAL_END
CRT_degreeSign = initDegreeSign(); CRT_degreeSign = initDegreeSign();
} }
void CRT_done() { void CRT_done()
attron(CRT_colors[RESET_COLOR]); {
int resetColor = CRT_colors ? CRT_colors[RESET_COLOR] : CRT_colorSchemes[COLORSCHEME_DEFAULT][RESET_COLOR];
attron(resetColor);
mvhline(LINES - 1, 0, ' ', COLS); mvhline(LINES - 1, 0, ' ', COLS);
attroff(CRT_colors[RESET_COLOR]); attroff(resetColor);
refresh(); refresh();
curs_set(1); curs_set(1);
@ -1024,14 +1070,16 @@ void CRT_done() {
dumpStderr(); dumpStderr();
} }
void CRT_fatalError(const char* note) { void CRT_fatalError(const char *note)
const char* sysMsg = strerror(errno); {
const char *sysMsg = strerror(errno);
CRT_done(); CRT_done();
fprintf(stderr, "%s: %s\n", note, sysMsg); fprintf(stderr, "%s: %s\n", note, sysMsg);
exit(2); exit(2);
} }
int CRT_readKey() { int CRT_readKey()
{
nocbreak(); nocbreak();
cbreak(); cbreak();
nodelay(stdscr, FALSE); nodelay(stdscr, FALSE);
@ -1040,22 +1088,28 @@ int CRT_readKey() {
return ret; return ret;
} }
void CRT_disableDelay() { void CRT_disableDelay()
{
nocbreak(); nocbreak();
cbreak(); cbreak();
nodelay(stdscr, TRUE); nodelay(stdscr, TRUE);
} }
void CRT_enableDelay() { void CRT_enableDelay()
{
halfdelay(*CRT_delay); halfdelay(*CRT_delay);
} }
void CRT_setColors(int colorScheme) { void CRT_setColors(int colorScheme)
{
CRT_colorScheme = colorScheme; CRT_colorScheme = colorScheme;
for (short int i = 0; i < 8; i++) { for (short int i = 0; i < 8; i++)
for (short int j = 0; j < 8; j++) { {
if (ColorIndex(i, j) != ColorIndexGrayBlack && ColorIndex(i, j) != ColorIndexWhiteDefault) { for (short int j = 0; j < 8; j++)
{
if (ColorIndex(i, j) != ColorIndexGrayBlack && ColorIndex(i, j) != ColorIndexWhiteDefault)
{
short int bg = (colorScheme != COLORSCHEME_BLACKNIGHT) short int bg = (colorScheme != COLORSCHEME_BLACKNIGHT)
? (j == 0 ? -1 : j) ? (j == 0 ? -1 : j)
: j; : j;
@ -1074,7 +1128,8 @@ void CRT_setColors(int colorScheme) {
} }
#ifdef PRINT_BACKTRACE #ifdef PRINT_BACKTRACE
static void print_backtrace(void) { static void print_backtrace(void)
{
#if defined(HAVE_LIBUNWIND_H) && defined(HAVE_LIBUNWIND) #if defined(HAVE_LIBUNWIND_H) && defined(HAVE_LIBUNWIND)
unw_context_t context; unw_context_t context;
unw_getcontext(&context); unw_getcontext(&context);
@ -1084,7 +1139,8 @@ static void print_backtrace(void) {
unsigned int item = 0; unsigned int item = 0;
while (unw_step(&cursor) > 0) { while (unw_step(&cursor) > 0)
{
unw_word_t pc; unw_word_t pc;
unw_get_reg(&cursor, UNW_REG_IP, &pc); unw_get_reg(&cursor, UNW_REG_IP, &pc);
if (pc == 0) if (pc == 0)
@ -1097,26 +1153,27 @@ static void print_backtrace(void) {
unw_proc_info_t pip; unw_proc_info_t pip;
pip.unwind_info = NULL; pip.unwind_info = NULL;
const char* fname = "?"; const char *fname = "?";
const void* ptr = 0; const void *ptr = 0;
if (unw_get_proc_info(&cursor, &pip) == 0) { if (unw_get_proc_info(&cursor, &pip) == 0)
ptr = (const void*)(pip.start_ip + offset); {
ptr = (const void *)(pip.start_ip + offset);
#ifdef HAVE_DLADDR #ifdef HAVE_DLADDR
Dl_info dlinfo; Dl_info dlinfo;
if (dladdr(ptr, &dlinfo) && dlinfo.dli_fname && *dlinfo.dli_fname) if (dladdr(ptr, &dlinfo) && dlinfo.dli_fname && *dlinfo.dli_fname)
fname = dlinfo.dli_fname; fname = dlinfo.dli_fname;
#endif #endif
} }
const char* frame = ""; const char *frame = "";
if (unw_is_signal_frame(&cursor) > 0) if (unw_is_signal_frame(&cursor) > 0)
frame = "{signal frame}"; frame = "{signal frame}";
fprintf(stderr, "%2u: %#14lx %s (%s+%#lx) [%p]%s%s\n", item++, pc, fname, symbolName, offset, ptr, frame ? " " : "", frame); fprintf(stderr, "%2u: %#14lx %s (%s+%#lx) [%p]%s%s\n", item++, pc, fname, symbolName, offset, ptr, frame ? " " : "", frame);
} }
#elif defined(HAVE_EXECINFO_H) #elif defined(HAVE_EXECINFO_H)
void* backtraceArray[256]; void *backtraceArray[256];
size_t size = backtrace(backtraceArray, ARRAYSIZE(backtraceArray)); size_t size = backtrace(backtraceArray, ARRAYSIZE(backtraceArray));
backtrace_symbols_fd(backtraceArray, size, STDERR_FILENO); backtrace_symbols_fd(backtraceArray, size, STDERR_FILENO);
@ -1126,7 +1183,8 @@ static void print_backtrace(void) {
} }
#endif #endif
void CRT_handleSIGSEGV(int signal) { void CRT_handleSIGSEGV(int signal)
{
CRT_done(); CRT_done();
fprintf(stderr, "\n\n" fprintf(stderr, "\n\n"
@ -1134,22 +1192,21 @@ void CRT_handleSIGSEGV(int signal) {
"============================\n" "============================\n"
"Please check at https://htop.dev/issues whether this issue has already been reported.\n" "Please check at https://htop.dev/issues whether this issue has already been reported.\n"
"If no similar issue has been reported before, please create a new issue with the following information:\n" "If no similar issue has been reported before, please create a new issue with the following information:\n"
" - Your "PACKAGE" version: '"VERSION"'\n" " - Your " PACKAGE " version: '" VERSION "'\n"
" - Your OS and kernel version (uname -a)\n" " - Your OS and kernel version (uname -a)\n"
" - Your distribution and release (lsb_release -a)\n" " - Your distribution and release (lsb_release -a)\n"
" - Likely steps to reproduce (How did it happen?)\n" " - Likely steps to reproduce (How did it happen?)\n");
);
#ifdef PRINT_BACKTRACE #ifdef PRINT_BACKTRACE
fprintf(stderr, " - Backtrace of the issue (see below)\n"); fprintf(stderr, " - Backtrace of the issue (see below)\n");
#endif #endif
fprintf(stderr, fprintf(stderr,
"\n" "\n");
);
const char* signal_str = strsignal(signal); const char *signal_str = strsignal(signal);
if (!signal_str) { if (!signal_str)
{
signal_str = "unknown reason"; signal_str = "unknown reason";
} }
fprintf(stderr, fprintf(stderr,
@ -1157,8 +1214,7 @@ void CRT_handleSIGSEGV(int signal) {
"------------------\n" "------------------\n"
"A signal %d (%s) was received.\n" "A signal %d (%s) was received.\n"
"\n", "\n",
signal, signal_str signal, signal_str);
);
fprintf(stderr, fprintf(stderr,
"Setting information:\n" "Setting information:\n"
@ -1169,44 +1225,40 @@ void CRT_handleSIGSEGV(int signal) {
#ifdef PRINT_BACKTRACE #ifdef PRINT_BACKTRACE
fprintf(stderr, fprintf(stderr,
"Backtrace information:\n" "Backtrace information:\n"
"----------------------\n" "----------------------\n");
);
print_backtrace(); print_backtrace();
fprintf(stderr, fprintf(stderr,
"\n" "\n"
"To make the above information more practical to work with, " "To make the above information more practical to work with, "
"please also provide a disassembly of your "PACKAGE" binary. " "please also provide a disassembly of your " PACKAGE " binary. "
"This can usually be done by running the following command:\n" "This can usually be done by running the following command:\n"
"\n" "\n");
);
#ifdef HTOP_DARWIN #ifdef HTOP_DARWIN
fprintf(stderr, " otool -tvV `which "PACKAGE"` > ~/htop.otool\n"); fprintf(stderr, " otool -tvV `which " PACKAGE "` > ~/htop.otool\n");
#else #else
fprintf(stderr, " objdump -d -S -w `which "PACKAGE"` > ~/htop.objdump\n"); fprintf(stderr, " objdump -d -S -w `which " PACKAGE "` > ~/htop.objdump\n");
#endif #endif
fprintf(stderr, fprintf(stderr,
"\n" "\n"
"Please include the generated file in your report.\n" "Please include the generated file in your report.\n");
);
#endif #endif
fprintf(stderr, fprintf(stderr,
"Running this program with debug symbols or inside a debugger may provide further insights.\n" "Running this program with debug symbols or inside a debugger may provide further insights.\n"
"\n" "\n"
"Thank you for helping to improve "PACKAGE"!\n" "Thank you for helping to improve " PACKAGE "!\n"
"\n" "\n");
);
/* Call old sigsegv handler; may be default exit or third party one (e.g. ASAN) */ /* Call old sigsegv handler; may be default exit or third party one (e.g. ASAN) */
if (sigaction (signal, &old_sig_handler[signal], NULL) < 0) { if (sigaction(signal, &old_sig_handler[signal], NULL) < 0)
{
/* This avoids an infinite loop in case the handler could not be reset. */ /* This avoids an infinite loop in case the handler could not be reset. */
fprintf(stderr, fprintf(stderr,
"!!! Chained handler could not be restored. Forcing exit.\n" "!!! Chained handler could not be restored. Forcing exit.\n");
);
_exit(1); _exit(1);
} }
@ -1215,7 +1267,6 @@ void CRT_handleSIGSEGV(int signal) {
// Always terminate, even if installed handler returns // Always terminate, even if installed handler returns
fprintf(stderr, fprintf(stderr,
"!!! Chained handler did not exit. Forcing exit.\n" "!!! Chained handler did not exit. Forcing exit.\n");
);
_exit(1); _exit(1);
} }

28
CRT.h
View File

@ -15,8 +15,8 @@ in the source distribution for its full text.
#include "ProvideCurses.h" #include "ProvideCurses.h"
#include "Settings.h" #include "Settings.h"
typedef enum TreeStr_
typedef enum TreeStr_ { {
TREE_STR_VERT, TREE_STR_VERT,
TREE_STR_RTEE, TREE_STR_RTEE,
TREE_STR_BEND, TREE_STR_BEND,
@ -28,7 +28,8 @@ typedef enum TreeStr_ {
LAST_TREE_STR LAST_TREE_STR
} TreeStr; } TreeStr;
typedef enum ColorScheme_ { typedef enum ColorScheme_
{
COLORSCHEME_DEFAULT, COLORSCHEME_DEFAULT,
COLORSCHEME_MONOCHROME, COLORSCHEME_MONOCHROME,
COLORSCHEME_BLACKONWHITE, COLORSCHEME_BLACKONWHITE,
@ -39,7 +40,8 @@ typedef enum ColorScheme_ {
LAST_COLORSCHEME LAST_COLORSCHEME
} ColorScheme; } ColorScheme;
typedef enum ColorElements_ { typedef enum ColorElements_
{
RESET_COLOR, RESET_COLOR,
DEFAULT_COLOR, DEFAULT_COLOR,
FUNCTION_BAR, FUNCTION_BAR,
@ -64,6 +66,8 @@ typedef enum ColorElements_ {
METER_VALUE_WARN, METER_VALUE_WARN,
LED_COLOR, LED_COLOR,
UPTIME, UPTIME,
TEMP,
FREQ,
BATTERY, BATTERY,
TASKS_RUNNING, TASKS_RUNNING,
SWAP, SWAP,
@ -148,13 +152,13 @@ typedef enum ColorElements_ {
LAST_COLORELEMENT LAST_COLORELEMENT
} ColorElements; } ColorElements;
void CRT_fatalError(const char* note) ATTR_NORETURN; void CRT_fatalError(const char *note) ATTR_NORETURN;
#ifdef NDEBUG #ifdef NDEBUG
# define CRT_debug(...) #define CRT_debug(...)
#else #else
void CRT_debug_impl(const char* file, size_t lineno, const char* func, const char* fmt, ...) ATTR_FORMAT(printf, 4, 5); void CRT_debug_impl(const char *file, size_t lineno, const char *func, const char *fmt, ...) ATTR_FORMAT(printf, 4, 5);
# define CRT_debug(...) CRT_debug_impl(__FILE__, __LINE__, __func__, __VA_ARGS__) #define CRT_debug(...) CRT_debug_impl(__FILE__, __LINE__, __func__, __VA_ARGS__)
#endif #endif
void CRT_handleSIGSEGV(int signal) ATTR_NORETURN; void CRT_handleSIGSEGV(int signal) ATTR_NORETURN;
@ -165,7 +169,7 @@ void CRT_handleSIGSEGV(int signal) ATTR_NORETURN;
#define KEY_SHIFT_TAB KEY_F(33) #define KEY_SHIFT_TAB KEY_F(33)
#define KEY_ALT(x) (KEY_F(64 - 26) + ((x) - 'A')) #define KEY_ALT(x) (KEY_F(64 - 26) + ((x) - 'A'))
extern const char* CRT_degreeSign; extern const char *CRT_degreeSign;
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
@ -173,9 +177,9 @@ extern bool CRT_utf8;
#endif #endif
extern const char* const* CRT_treeStr; extern const char *const *CRT_treeStr;
extern const int* CRT_colors; extern const int *CRT_colors;
extern int CRT_cursorX; extern int CRT_cursorX;
@ -187,7 +191,7 @@ extern ColorScheme CRT_colorScheme;
void CRT_setMouse(bool enabled); void CRT_setMouse(bool enabled);
void CRT_init(const Settings* settings, bool allowUnicode); void CRT_init(const Settings *settings, bool allowUnicode);
void CRT_done(void); void CRT_done(void);

29
FreqMeter.c Normal file
View File

@ -0,0 +1,29 @@
#include "FreqMeter.h"
#include "CRT.h"
#include "Object.h"
#include "Platform.h"
#include "XUtils.h"
static const int FreqMeter_attributes[] = {
FREQ};
static void FreqMeter_updateValues(Meter *this)
{
float freq = Platform_getFreq();
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1lf GHz", freq);
}
const MeterClass FreqMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete},
.updateValues = FreqMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 1,
.total = 100.0,
.attributes = FreqMeter_attributes,
.name = "Freq",
.uiName = "CPU Frequency",
.caption = "CPU/Frequency: "};

8
FreqMeter.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef HEADER_FreqMeter
#define HEADER_FreqMeter
#include "Meter.h"
extern const MeterClass FreqMeter_class;
#endif

View File

@ -82,6 +82,8 @@ myhtopsources = \
TasksMeter.c \ TasksMeter.c \
TraceScreen.c \ TraceScreen.c \
UptimeMeter.c \ UptimeMeter.c \
FreqMeter.c \
TempMeter.c \
UsersTable.c \ UsersTable.c \
Vector.c \ Vector.c \
XUtils.c XUtils.c
@ -144,6 +146,8 @@ myhtopheaders = \
TasksMeter.h \ TasksMeter.h \
TraceScreen.h \ TraceScreen.h \
UptimeMeter.h \ UptimeMeter.h \
FreqMeter.h \
TempMeter.h \
UsersTable.h \ UsersTable.h \
Vector.h \ Vector.h \
XUtils.h XUtils.h

91
README
View File

@ -8,7 +8,22 @@
[![Packaging status](https://repology.org/badge/tiny-repos/htop.svg)](https://repology.org/project/htop/versions) [![Packaging status](https://repology.org/badge/tiny-repos/htop.svg)](https://repology.org/project/htop/versions)
[![License: GPL v2+](https://img.shields.io/badge/License-GPL%20v2+-blue.svg)](COPYING?raw=true) [![License: GPL v2+](https://img.shields.io/badge/License-GPL%20v2+-blue.svg)](COPYING?raw=true)
![Screenshot of htop](docs/images/screenshot.png?raw=true) ![Screenshot of htop](https://i.imgur.com/dCSsvSv.png)
## **Warning!**
This fork was created for personal use; correct operation is not guaranteed.
<details>
<summary>Tested on</summary>
- Manjaro ARM Minimal (Raspberry Pi 4)
- Debian 11 (Raspberry Pi 4)
- Ubuntu Server 22.04 (Raspberry Pi 4)
- Raspbian 64bit (Raspberry Pi 3B+)
- Arch Linux (x86 PC), used for the screenshot above
</details>
## Introduction ## Introduction
@ -30,55 +45,66 @@ For more information and details visit [htop.dev](https://htop.dev).
## Build instructions ## Build instructions
### Prerequisite ### Prerequisite
List of build-time dependencies: List of build-time dependencies:
* standard GNU autotools-based C toolchain
- standard GNU autotools-based C toolchain
- C99 compliant compiler - C99 compliant compiler
- `autoconf` - `autoconf`
- `autotools` - `autotools`
* `ncurses` - `ncurses`
**Note about `ncurses`:** **Note about `ncurses`:**
> `htop` requires `ncurses` 6.0. Be aware the appropriate package is sometimes still called libncurses5 (on Debian/Ubuntu). Also `ncurses` usually comes in two flavours: > `htop` requires `ncurses` 6.0. Be aware the appropriate package is sometimes still called libncurses5 (on Debian/Ubuntu). Also `ncurses` usually comes in two flavours:
>* With Unicode support. >
>* Without Unicode support. >- With Unicode support.
>- Without Unicode support.
> >
> This is also something that is reflected in the package name on Debian/Ubuntu (via the additional 'w' - 'w'ide character support). > This is also something that is reflected in the package name on Debian/Ubuntu (via the additional 'w' - 'w'ide character support).
List of additional build-time dependencies (based on feature flags): List of additional build-time dependencies (based on feature flags):
* `sensors`
* `hwloc` - `sensors`
* `libcap` (v2.21 or later) - `hwloc`
* `libnl-3` - `libcap` (v2.21 or later)
- `libnl-3`
Install these and other required packages for C development from your package manager. Install these and other required packages for C development from your package manager.
**Debian/Ubuntu** **Debian/Ubuntu**
~~~ shell ~~~ shell
sudo apt install libncursesw5-dev autotools-dev autoconf build-essential sudo apt install libncursesw5-dev autotools-dev autoconf build-essential
~~~ ~~~
**Fedora/RHEL** **Fedora/RHEL**
~~~ shell ~~~ shell
sudo dnf install ncurses-devel automake autoconf gcc sudo dnf install ncurses-devel automake autoconf gcc
~~~ ~~~
**Archlinux/Manjaro** **Archlinux/Manjaro**
~~~ shell ~~~ shell
sudo pacman -S ncurses automake autoconf gcc sudo pacman -S ncurses automake autoconf gcc
~~~ ~~~
**macOS** **macOS**
~~~ shell ~~~ shell
brew install ncurses automake autoconf gcc brew install ncurses automake autoconf gcc
~~~ ~~~
### Compile from source: ### Compile from source
To compile from source, download from the Git repository (`git clone` or downloads from [GitHub releases](https://github.com/htop-dev/htop/releases/)), then run: To compile from source, download from the Git repository (`git clone` or downloads from [GitHub releases](https://github.com/htop-dev/htop/releases/)), then run:
~~~ shell ~~~ shell
./autogen.sh && ./configure && make ./autogen.sh && ./configure && make
~~~ ~~~
### Install ### Install
To install on the local system run `make install`. By default `make install` installs into `/usr/local`. To change this path use `./configure --prefix=/some/path`. To install on the local system run `make install`. By default `make install` installs into `/usr/local`. To change this path use `./configure --prefix=/some/path`.
### Build Options ### Build Options
@ -87,80 +113,85 @@ To install on the local system run `make install`. By default `make install` ins
#### Generic #### Generic
* `--enable-unicode`: - `--enable-unicode`:
enable Unicode support enable Unicode support
- dependency: *libncursesw* - dependency: *libncursesw*
- default: *yes* - default: *yes*
* `--enable-affinity`: - `--enable-affinity`:
enable `sched_setaffinity(2)` and `sched_getaffinity(2)` for affinity support; conflicts with hwloc enable `sched_setaffinity(2)` and `sched_getaffinity(2)` for affinity support; conflicts with hwloc
- default: *check* - default: *check*
* `--enable-hwloc`: - `--enable-hwloc`:
enable hwloc support for CPU affinity; disables affinity support enable hwloc support for CPU affinity; disables affinity support
- dependency: *libhwloc* - dependency: *libhwloc*
- default: *no* - default: *no*
* `--enable-static`: - `--enable-static`:
build a static htop binary; hwloc and delay accounting are not supported build a static htop binary; hwloc and delay accounting are not supported
- default: *no* - default: *no*
* `--enable-debug`: - `--enable-debug`:
Enable asserts and internal sanity checks; implies a performance penalty Enable asserts and internal sanity checks; implies a performance penalty
- default: *no* - default: *no*
#### Performance Co-Pilot #### Performance Co-Pilot
* `--enable-pcp`: - `--enable-pcp`:
enable Performance Co-Pilot support via a new pcp-htop utility enable Performance Co-Pilot support via a new pcp-htop utility
- dependency: *libpcp* - dependency: *libpcp*
- default: *no* - default: *no*
#### Linux #### Linux
* `--enable-sensors`: - `--enable-sensors`:
enable libsensors(3) support for reading temperature data enable libsensors(3) support for reading temperature data
- dependencies: *libsensors-dev*(build-time), at runtime *libsensors* is loaded via `dlopen(3)` if available - dependencies: *libsensors-dev*(build-time), at runtime *libsensors* is loaded via `dlopen(3)` if available
- default: *check* - default: *check*
* `--enable-capabilities`: - `--enable-capabilities`:
enable Linux capabilities support enable Linux capabilities support
- dependency: *libcap* - dependency: *libcap*
- default: *check* - default: *check*
* `--with-proc`: - `--with-proc`:
location of a Linux-compatible proc filesystem location of a Linux-compatible proc filesystem
- default: */proc* - default: */proc*
* `--enable-openvz`: - `--enable-openvz`:
enable OpenVZ support enable OpenVZ support
- default: *no* - default: *no*
* `--enable-vserver`: - `--enable-vserver`:
enable VServer support enable VServer support
- default: *no* - default: *no*
* `--enable-ancient-vserver`: - `--enable-ancient-vserver`:
enable ancient VServer support (implies `--enable-vserver`) enable ancient VServer support (implies `--enable-vserver`)
- default: *no* - default: *no*
* `--enable-delayacct`: - `--enable-delayacct`:
enable Linux delay accounting support enable Linux delay accounting support
- dependencies: *pkg-config*(build-time), *libnl-3* and *libnl-genl-3* - dependencies: *pkg-config*(build-time), *libnl-3* and *libnl-genl-3*
- default: *check* - default: *check*
## Runtime dependencies
## Runtime dependencies:
`htop` has a set of fixed minimum runtime dependencies, which is kept as minimal as possible: `htop` has a set of fixed minimum runtime dependencies, which is kept as minimal as possible:
* `ncurses` libraries for terminal handling (wide character support).
### Runtime optional dependencies: - `ncurses` libraries for terminal handling (wide character support).
### Runtime optional dependencies
`htop` has a set of fixed optional dependencies, depending on build/configure option used: `htop` has a set of fixed optional dependencies, depending on build/configure option used:
#### Linux #### Linux
* `libdl`, if not building a static binary, is always required when support for optional dependencies (i.e. `libsensors`, `libsystemd`) is present.
* `libcap`, user-space interfaces to POSIX 1003.1e capabilities, is always required when `--enable-capabilities` was used to configure `htop`. - `libdl`, if not building a static binary, is always required when support for optional dependencies (i.e. `libsensors`, `libsystemd`) is present.
* `libsensors`, readout of temperatures and CPU speeds, is optional even when `--enable-sensors` was used to configure `htop`. - `libcap`, user-space interfaces to POSIX 1003.1e capabilities, is always required when `--enable-capabilities` was used to configure `htop`.
* `libsystemd` is optional when `--enable-static` was not used to configure `htop`. If building statically and `libsystemd` is not found by `configure`, support for the systemd meter is disabled entirely. - `libsensors`, readout of temperatures and CPU speeds, is optional even when `--enable-sensors` was used to configure `htop`.
- `libsystemd` is optional when `--enable-static` was not used to configure `htop`. If building statically and `libsystemd` is not found by `configure`, support for the systemd meter is disabled entirely.
`htop` checks for the availability of the actual runtime libraries as `htop` runs. `htop` checks for the availability of the actual runtime libraries as `htop` runs.
#### BSD #### BSD
On most BSD systems `kvm` is a requirement to read kernel information. On most BSD systems `kvm` is a requirement to read kernel information.
More information on required and optional dependencies can be found in [configure.ac](configure.ac). More information on required and optional dependencies can be found in [configure.ac](configure.ac).
## Usage ## Usage
See the manual page (`man htop`) or the help menu (**F1** or **h** inside `htop`) for a list of supported key commands. See the manual page (`man htop`) or the help menu (**F1** or **h** inside `htop`) for a list of supported key commands.
## Support ## Support

File diff suppressed because it is too large Load Diff

29
TempMeter.c Normal file
View File

@ -0,0 +1,29 @@
#include "TempMeter.h"
#include "CRT.h"
#include "Object.h"
#include "Platform.h"
#include "XUtils.h"
static const int TempMeter_attributes[] = {
TEMP};
static void TempMeter_updateValues(Meter *this)
{
float temp_c = Platform_getTemp();
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1lf °C", temp_c);
}
const MeterClass TempMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete},
.updateValues = TempMeter_updateValues,
.defaultMode = TEXT_METERMODE,
.maxItems = 1,
.total = 100.0,
.attributes = TempMeter_attributes,
.name = "Temp",
.uiName = "CPU Temperature",
.caption = "CPU/Temperature: "};

8
TempMeter.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef HEADER_TempMeter
#define HEADER_TempMeter
#include "Meter.h"
extern const MeterClass TempMeter_class;
#endif

View File

@ -17,60 +17,61 @@ in the source distribution for its full text.
#include "Compat.h" #include "Compat.h"
#include "Macros.h" #include "Macros.h"
void fail(void) ATTR_NORETURN; void fail(void) ATTR_NORETURN;
void* xMalloc(size_t size) ATTR_ALLOC_SIZE1(1) ATTR_MALLOC; void *xMalloc(size_t size) ATTR_ALLOC_SIZE1(1) ATTR_MALLOC;
void* xMallocArray(size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(1, 2) ATTR_MALLOC; void *xMallocArray(size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(1, 2) ATTR_MALLOC;
void* xCalloc(size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(1, 2) ATTR_MALLOC; void *xCalloc(size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(1, 2) ATTR_MALLOC;
void* xRealloc(void* ptr, size_t size) ATTR_ALLOC_SIZE1(2); void *xRealloc(void *ptr, size_t size) ATTR_ALLOC_SIZE1(2);
void* xReallocArray(void* ptr, size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(2, 3); void *xReallocArray(void *ptr, size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(2, 3);
void* xReallocArrayZero(void* ptr, size_t prevmemb, size_t newmemb, size_t size) ATTR_ALLOC_SIZE2(3, 4); void *xReallocArrayZero(void *ptr, size_t prevmemb, size_t newmemb, size_t size) ATTR_ALLOC_SIZE2(3, 4);
/* /*
* String_startsWith gives better performance if strlen(match) can be computed * String_startsWith gives better performance if strlen(match) can be computed
* at compile time (e.g. when they are immutable string literals). :) * at compile time (e.g. when they are immutable string literals). :)
*/ */
static inline bool String_startsWith(const char* s, const char* match) { static inline bool String_startsWith(const char *s, const char *match)
{
return strncmp(s, match, strlen(match)) == 0; return strncmp(s, match, strlen(match)) == 0;
} }
bool String_contains_i(const char* s1, const char* s2, bool multi); bool String_contains_i(const char *s1, const char *s2, bool multi);
static inline bool String_eq(const char* s1, const char* s2) { static inline bool String_eq(const char *s1, const char *s2)
{
return strcmp(s1, s2) == 0; return strcmp(s1, s2) == 0;
} }
char* String_cat(const char* s1, const char* s2) ATTR_MALLOC; char *String_cat(const char *s1, const char *s2) ATTR_MALLOC;
char* String_trim(const char* in) ATTR_MALLOC; char *String_trim(const char *in) ATTR_MALLOC;
char** String_split(const char* s, char sep, size_t* n); char **String_split(const char *s, char sep, size_t *n);
void String_freeArray(char** s); void String_freeArray(char **s);
char* String_readLine(FILE* fd) ATTR_MALLOC; char *String_readLine(FILE *fd) ATTR_MALLOC;
/* Always null-terminates dest. Caller must pass a strictly positive size. */ /* Always null-terminates dest. Caller must pass a strictly positive size. */
size_t String_safeStrncpy(char* restrict dest, const char* restrict src, size_t size); size_t String_safeStrncpy(char *restrict dest, const char *restrict src, size_t size);
ATTR_FORMAT(printf, 2, 3) ATTR_FORMAT(printf, 2, 3)
int xAsprintf(char** strp, const char* fmt, ...); int xAsprintf(char **strp, const char *fmt, ...);
ATTR_FORMAT(printf, 3, 4) ATTR_FORMAT(printf, 3, 4)
int xSnprintf(char* buf, size_t len, const char* fmt, ...); int xSnprintf(char *buf, size_t len, const char *fmt, ...);
char* xStrdup(const char* str) ATTR_NONNULL ATTR_MALLOC; char *xStrdup(const char *str) ATTR_NONNULL ATTR_MALLOC;
void free_and_xStrdup(char** ptr, const char* str); void free_and_xStrdup(char **ptr, const char *str);
char* xStrndup(const char* str, size_t len) ATTR_NONNULL ATTR_MALLOC; char *xStrndup(const char *str, size_t len) ATTR_NONNULL ATTR_MALLOC;
ssize_t xReadfile(const char* pathname, void* buffer, size_t count); ssize_t xReadfile(const char *pathname, void *buffer, size_t count);
ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count); ssize_t xReadfileat(openat_arg_t dirfd, const char *pathname, void *buffer, size_t count);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -34,10 +34,9 @@ in the source distribution for its full text.
/* GNU/Hurd does not have PATH_MAX in limits.h */ /* GNU/Hurd does not have PATH_MAX in limits.h */
#ifndef PATH_MAX #ifndef PATH_MAX
#define PATH_MAX 4096 #define PATH_MAX 4096
#endif #endif
extern const ScreenDefaults Platform_defaultScreens[]; extern const ScreenDefaults Platform_defaultScreens[];
extern const unsigned int Platform_numberOfDefaultScreens; extern const unsigned int Platform_numberOfDefaultScreens;
@ -46,90 +45,98 @@ extern const SignalItem Platform_signals[];
extern const unsigned int Platform_numberOfSignals; extern const unsigned int Platform_numberOfSignals;
extern const MeterClass* const Platform_meterTypes[]; extern const MeterClass *const Platform_meterTypes[];
bool Platform_init(void); bool Platform_init(void);
void Platform_done(void); void Platform_done(void);
extern bool Running_containerized; extern bool Running_containerized;
void Platform_setBindings(Htop_Action* keys); void Platform_setBindings(Htop_Action *keys);
int Platform_getUptime(void); int Platform_getUptime(void);
void Platform_getLoadAverage(double* one, double* five, double* fifteen); float Platform_getTemp(void);
float Platform_getFreq(void);
void Platform_getLoadAverage(double *one, double *five, double *fifteen);
int Platform_getMaxPid(void); int Platform_getMaxPid(void);
double Platform_setCPUValues(Meter* this, unsigned int cpu); double Platform_setCPUValues(Meter *this, unsigned int cpu);
void Platform_setMemoryValues(Meter* this); void Platform_setMemoryValues(Meter *this);
void Platform_setSwapValues(Meter* this); void Platform_setSwapValues(Meter *this);
void Platform_setZramValues(Meter* this); void Platform_setZramValues(Meter *this);
void Platform_setZfsArcValues(Meter* this); void Platform_setZfsArcValues(Meter *this);
void Platform_setZfsCompressedArcValues(Meter* this); void Platform_setZfsCompressedArcValues(Meter *this);
char* Platform_getProcessEnv(pid_t pid); char *Platform_getProcessEnv(pid_t pid);
char* Platform_getInodeFilename(pid_t pid, ino_t inode); char *Platform_getInodeFilename(pid_t pid, ino_t inode);
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); FileLocks_ProcessData *Platform_getProcessLocks(pid_t pid);
void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred); void Platform_getPressureStall(const char *file, bool some, double *ten, double *sixty, double *threehundred);
bool Platform_getDiskIO(DiskIOData* data); bool Platform_getDiskIO(DiskIOData *data);
bool Platform_getNetworkIO(NetworkIOData* data); bool Platform_getNetworkIO(NetworkIOData *data);
void Platform_getBattery(double* percent, ACPresence* isOnAC); void Platform_getBattery(double *percent, ACPresence *isOnAC);
static inline void Platform_getHostname(char* buffer, size_t size) { static inline void Platform_getHostname(char *buffer, size_t size)
{
Generic_hostname(buffer, size); Generic_hostname(buffer, size);
} }
static inline void Platform_getRelease(char** string) { static inline void Platform_getRelease(char **string)
{
*string = Generic_uname(); *string = Generic_uname();
} }
#ifdef HAVE_LIBCAP #ifdef HAVE_LIBCAP
#define PLATFORM_LONG_OPTIONS \ #define PLATFORM_LONG_OPTIONS \
{"drop-capabilities", optional_argument, 0, 160}, {"drop-capabilities", optional_argument, 0, 160},
#else #else
#define PLATFORM_LONG_OPTIONS #define PLATFORM_LONG_OPTIONS
#endif #endif
void Platform_longOptionsUsage(const char* name); void Platform_longOptionsUsage(const char *name);
CommandLineStatus Platform_getLongOption(int opt, int argc, char** argv); CommandLineStatus Platform_getLongOption(int opt, int argc, char **argv);
static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { static inline void Platform_gettime_realtime(struct timeval *tv, uint64_t *msec)
{
Generic_gettime_realtime(tv, msec); Generic_gettime_realtime(tv, msec);
} }
static inline void Platform_gettime_monotonic(uint64_t* msec) { static inline void Platform_gettime_monotonic(uint64_t *msec)
{
Generic_gettime_monotonic(msec); Generic_gettime_monotonic(msec);
} }
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; } static inline Hashtable *Platform_dynamicMeters(void) { return NULL; }
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { } static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable *table) {}
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter *meter) {}
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter *meter) {}
static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter *meter, ATTR_UNUSED RichString *out) {}
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; } static inline Hashtable *Platform_dynamicColumns(void) { return NULL; }
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { } static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable *table) {}
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; } static inline const char *Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; } static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process *proc, ATTR_UNUSED RichString *str, ATTR_UNUSED unsigned int key) { return false; }
#endif #endif