From d18e9a4895599a479df264a6c7380b8805abb434 Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Wed, 2 Dec 2015 22:15:46 +0100 Subject: [PATCH 01/29] 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. --- Process.c | 17 +++++++++++------ TraceScreen.c | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Process.c b/Process.c index 4999bfcb..a1c2079c 100644 --- a/Process.c +++ b/Process.c @@ -513,12 +513,16 @@ void Process_toggleTag(Process* this) { } bool Process_setPriority(Process* this, int priority) { - int old_prio = getpriority(PRIO_PROCESS, this->pid); - int err = setpriority(PRIO_PROCESS, this->pid, priority); - if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) { - this->nice = priority; + if ( Process_getuid == 0 || Process_getuid == (int) this->st_uid ) { + int old_prio = getpriority(PRIO_PROCESS, this->pid); + int err = setpriority(PRIO_PROCESS, this->pid, priority); + if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) { + this->nice = priority; + } + return (err == 0); } - return (err == 0); + else + return false; } bool Process_changePriorityBy(Process* this, size_t delta) { @@ -526,7 +530,8 @@ bool Process_changePriorityBy(Process* this, size_t delta) { } void Process_sendSignal(Process* this, size_t sgn) { - kill(this->pid, (int) sgn); + if ( Process_getuid == 0 || Process_getuid == (int) this->st_uid ) + kill(this->pid, (int) sgn); } long Process_pidCompare(const void* v1, const void* v2) { diff --git a/TraceScreen.c b/TraceScreen.c index ecd0c0ab..3a62eb63 100644 --- a/TraceScreen.c +++ b/TraceScreen.c @@ -86,6 +86,7 @@ void TraceScreen_run(TraceScreen* this) { int child = fork(); if (child == -1) return; if (child == 0) { + seteuid(getuid()); dup2(fdpair[1], STDERR_FILENO); int ok = fcntl(fdpair[1], F_SETFL, O_NONBLOCK); if (ok != -1) { From 42b08f223395eb8cfcd0d36389803f329ea493f7 Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Wed, 2 Dec 2015 23:42:10 +0100 Subject: [PATCH 02/29] drop privileges during Settings_read()/Settings_write() --- Settings.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Settings.c b/Settings.c index 65e49bfc..6a674549 100644 --- a/Settings.c +++ b/Settings.c @@ -154,7 +154,12 @@ static void readFields(ProcessField* fields, int* flags, const char* line) { } static bool Settings_read(Settings* this, const char* fileName) { - FILE* fd = fopen(fileName, "r"); + FILE* fd; + uid_t euid = geteuid(); + + seteuid(getuid()); + fd = fopen(fileName, "w"); + seteuid(euid); if (!fd) return false; @@ -260,7 +265,11 @@ static void writeMeterModes(Settings* this, FILE* fd, int column) { bool Settings_write(Settings* this) { FILE* fd; + uid_t euid = geteuid(); + + seteuid(getuid()); fd = fopen(this->filename, "w"); + seteuid(euid); if (fd == NULL) { return false; } @@ -345,6 +354,8 @@ Settings* Settings_new(int cpuCount) { htopDir = String_cat(home, "/.config/htop"); } legacyDotfile = String_cat(home, "/.htoprc"); + uid_t euid = geteuid(); + seteuid(getuid()); (void) mkdir(configDir, 0700); (void) mkdir(htopDir, 0700); free(htopDir); @@ -357,6 +368,7 @@ Settings* Settings_new(int cpuCount) { free(legacyDotfile); legacyDotfile = NULL; } + seteuid(euid); } this->colorScheme = 0; this->changed = false; From c23770245e21eaac8b1d34fd4463e265f714b63f Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Sun, 6 Dec 2015 19:06:23 -0200 Subject: [PATCH 03/29] If ncurses*-config script is present, use it in configure when testing for ncurses library. See #198. --- configure.ac | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 80180486..7fead7af 100644 --- a/configure.ac +++ b/configure.ac @@ -147,15 +147,22 @@ fi # HTOP_CHECK_NCURSES_LIBRARY(LIBNAME, FUNCTION, DEFINE, CONFIG_SCRIPT, ELSE_PART) m4_define([HTOP_CHECK_NCURSES_LIBRARY], [ + config_script=$([$4] --libs 2> /dev/null) + save_LDFLAGS="$LDFLAGS" + if test ! "x$config_script" = x; then + LDFLAGS="$config_script $LDFLAGS" + fi AC_CHECK_LIB([$1], [$2], [ AC_DEFINE([$3], 1, [The library is present.]) - config_script=$([$4] --libs 2> /dev/null) if test ! "x$config_script" = x; then LIBS="$config_script $LIBS " else LIBS="-l[$1] $LIBS " fi - ], [$5]) + LDFLAGS="$save_LDFLAGS" + ], [ + LDFLAGS="$save_LDFLAGS" + $5]) ]) AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="yes") From ab3a7c2fa826932c9c297885b0ea33f1d880cc01 Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Mon, 7 Dec 2015 20:10:09 +0100 Subject: [PATCH 04/29] drop privileges before changing process priority or sending signals - replaces uid check from d18e9a4895599a479df264a6c7380b8805abb434 --- Process.c | 23 ++++++++++++----------- Process.h | 2 ++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Process.c b/Process.c index a1c2079c..8046daf1 100644 --- a/Process.c +++ b/Process.c @@ -513,16 +513,15 @@ void Process_toggleTag(Process* this) { } bool Process_setPriority(Process* this, int priority) { - if ( Process_getuid == 0 || Process_getuid == (int) this->st_uid ) { - int old_prio = getpriority(PRIO_PROCESS, this->pid); - int err = setpriority(PRIO_PROCESS, this->pid, priority); - if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) { - this->nice = priority; - } - return (err == 0); + uid_t euid = geteuid(); + seteuid(getuid()); + int old_prio = getpriority(PRIO_PROCESS, this->pid); + int err = setpriority(PRIO_PROCESS, this->pid, priority); + seteuid(euid); + if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) { + this->nice = priority; } - else - return false; + return (err == 0); } bool Process_changePriorityBy(Process* this, size_t delta) { @@ -530,8 +529,10 @@ bool Process_changePriorityBy(Process* this, size_t delta) { } void Process_sendSignal(Process* this, size_t sgn) { - if ( Process_getuid == 0 || Process_getuid == (int) this->st_uid ) - kill(this->pid, (int) sgn); + uid_t euid = geteuid(); + seteuid(getuid()); + kill(this->pid, (int) sgn); + seteuid(euid); } long Process_pidCompare(const void* v1, const void* v2) { diff --git a/Process.h b/Process.h index 841b1291..d856c035 100644 --- a/Process.h +++ b/Process.h @@ -158,6 +158,8 @@ typedef struct ProcessClass_ { #define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K) #define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K) +extern char Process_pidFormat[20]; + void Process_setupColumnWidths(); void Process_humanNumber(RichString* str, unsigned long number, bool coloring); From db6828617d3e56dd3f1f7f5d028170c58863039e Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Wed, 9 Dec 2015 17:17:30 -0200 Subject: [PATCH 05/29] More thorough checks for ncurses*-config scripts. See #198. --- configure.ac | 68 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/configure.ac b/configure.ac index 7fead7af..752e8e94 100644 --- a/configure.ac +++ b/configure.ac @@ -144,47 +144,59 @@ if test "x$enable_taskstats" = xyes; then AC_DEFINE(HAVE_TASKSTATS, 1, [Define if taskstats support enabled.]) fi -# HTOP_CHECK_NCURSES_LIBRARY(LIBNAME, FUNCTION, DEFINE, CONFIG_SCRIPT, ELSE_PART) -m4_define([HTOP_CHECK_NCURSES_LIBRARY], +# HTOP_CHECK_SCRIPT(LIBNAME, FUNCTION, DEFINE, CONFIG_SCRIPT, ELSE_PART) +m4_define([HTOP_CHECK_SCRIPT], [ - config_script=$([$4] --libs 2> /dev/null) - save_LDFLAGS="$LDFLAGS" - if test ! "x$config_script" = x; then - LDFLAGS="$config_script $LDFLAGS" + htop_config_script=$([$4] --libs 2> /dev/null) + htop_script_success=no + htop_save_LDFLAGS="$LDFLAGS" + if test ! "x$htop_config_script" = x; then + LDFLAGS="$htop_config_script $LDFLAGS" + AC_CHECK_LIB([$1], [$2], [ + AC_DEFINE([$3], 1, [The library is present.]) + LIBS="$htop_config_script $LIBS " + htop_script_success=yes + ], []) + LDFLAGS="$save_LDFLAGS" fi + if test "x$htop_script_success" = no; then + [$5] + fi +]) + +# HTOP_CHECK_LIB(LIBNAME, FUNCTION, DEFINE, ELSE_PART) +m4_define([HTOP_CHECK_LIB], +[ AC_CHECK_LIB([$1], [$2], [ AC_DEFINE([$3], 1, [The library is present.]) - if test ! "x$config_script" = x; then - LIBS="$config_script $LIBS " - else - LIBS="-l[$1] $LIBS " - fi - LDFLAGS="$save_LDFLAGS" - ], [ - LDFLAGS="$save_LDFLAGS" - $5]) + LIBS="-l[$1] $LIBS " + ], [$4]) ]) AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="yes") if test "x$enable_unicode" = xyes; then - HTOP_CHECK_NCURSES_LIBRARY([ncursesw6], [addnwstr], [HAVE_LIBNCURSESW], "ncursesw6-config", [ - HTOP_CHECK_NCURSES_LIBRARY([ncursesw], [addnwstr], [HAVE_LIBNCURSESW], "ncursesw5-config", [ - HTOP_CHECK_NCURSES_LIBRARY([ncurses], [addnwstr], [HAVE_LIBNCURSES], "ncurses5-config", [ - missing_libraries="$missing_libraries libncursesw" - AC_MSG_ERROR([You may want to use --disable-unicode or install libncursesw.]) - ]) - ]) - ]) + HTOP_CHECK_SCRIPT([ncursesw6], [addnwstr], [HAVE_LIBNCURSESW], "ncursesw6-config", + HTOP_CHECK_SCRIPT([ncursesw], [addnwstr], [HAVE_LIBNCURSESW], "ncursesw5-config", + HTOP_CHECK_SCRIPT([ncurses], [addnwstr], [HAVE_LIBNCURSESW], "ncurses5-config", + HTOP_CHECK_LIB([ncursesw6], [addnwstr], [HAVE_LIBNCURSESW], + HTOP_CHECK_LIB([ncursesw], [addnwstr], [HAVE_LIBNCURSESW], + HTOP_CHECK_LIB([ncurses], [addnwstr], [HAVE_LIBNCURSESW], + missing_libraries="$missing_libraries libncursesw" + AC_MSG_ERROR([You may want to use --disable-unicode or install libncursesw.]) + )))))) + AC_CHECK_HEADERS([ncursesw/curses.h],[:], [AC_CHECK_HEADERS([ncurses/ncurses.h],[:], [AC_CHECK_HEADERS([ncurses/curses.h],[:], [AC_CHECK_HEADERS([ncurses.h],[:],[missing_headers="$missing_headers $ac_header"])])])]) else - HTOP_CHECK_NCURSES_LIBRARY([ncurses6], [refresh], [HAVE_LIBNCURSES], "ncurses6-config", [ - HTOP_CHECK_NCURSES_LIBRARY([ncurses], [refresh], [HAVE_LIBNCURSES], "ncurses5-config", [ - missing_libraries="$missing_libraries libncurses" - ]) - ]) + HTOP_CHECK_SCRIPT([ncurses6], [refresh], [HAVE_LIBNCURSES], "ncurses6-config", + HTOP_CHECK_SCRIPT([ncurses], [refresh], [HAVE_LIBNCURSES], "ncurses5-config", + HTOP_CHECK_LIB([ncurses6], [refresh], [HAVE_LIBNCURSES], + HTOP_CHECK_LIB([ncurses], [refresh], [HAVE_LIBNCURSES], + missing_libraries="$missing_libraries libncurses" + )))) + AC_CHECK_HEADERS([curses.h],[:], [AC_CHECK_HEADERS([ncurses/curses.h],[:], [AC_CHECK_HEADERS([ncurses/ncurses.h],[:], From 84783bd6f0b9da40d3ce92d0a81e56d276d24eca Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Wed, 9 Dec 2015 20:34:11 +0100 Subject: [PATCH 06/29] Fix fopen mode in Settings_read() --- Settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Settings.c b/Settings.c index 6a674549..8eb5bbd7 100644 --- a/Settings.c +++ b/Settings.c @@ -158,7 +158,7 @@ static bool Settings_read(Settings* this, const char* fileName) { uid_t euid = geteuid(); seteuid(getuid()); - fd = fopen(fileName, "w"); + fd = fopen(fileName, "r"); seteuid(euid); if (!fd) return false; From cccc18dd2f820c3eba3a495eb2265d682c77d718 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Wed, 9 Dec 2015 17:34:57 -0200 Subject: [PATCH 07/29] Oops! --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 752e8e94..709b69b7 100644 --- a/configure.ac +++ b/configure.ac @@ -159,7 +159,7 @@ m4_define([HTOP_CHECK_SCRIPT], ], []) LDFLAGS="$save_LDFLAGS" fi - if test "x$htop_script_success" = no; then + if test "x$htop_script_success" = xno; then [$5] fi ]) From 065aab5247012498f3c00fb5edf7712672c0a40e Mon Sep 17 00:00:00 2001 From: Antoine Catton Date: Wed, 9 Dec 2015 23:42:56 -0700 Subject: [PATCH 08/29] 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. --- IncSet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/IncSet.c b/IncSet.c index 2b1ad392..93be6b3a 100644 --- a/IncSet.c +++ b/IncSet.c @@ -169,6 +169,8 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue IncMode_reset(mode); } } + } else if (ch == KEY_RESIZE) { + Panel_resize(panel, COLS, LINES-panel->y-1); } else { if (mode->isFilter) { filterChanged = true; From bc84920b91f916532cdffd2fae5e31fdd37a017e Mon Sep 17 00:00:00 2001 From: "Martin \"eto\" Misuth" Date: Fri, 11 Dec 2015 11:01:24 +0100 Subject: [PATCH 09/29] added support for effective UID/username change detection --- freebsd/FreeBSDProcessList.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index f1b7a191..ee84753c 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -224,6 +224,10 @@ void ProcessList_goThroughEntries(ProcessList* this) { free(fp->jname); fp->jname = FreeBSDProcessList_readJailName(kproc); } + if(proc->st_uid != kproc->ki_uid) { + proc->st_uid = kproc->ki_uid; + proc->user = UsersTable_getRef(this->usersTable, proc->st_uid); + } if (settings->updateProcessNames) { free(proc->comm); proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset); From c2769985ccea4894a6fb9fbfa9588ef520e907db Mon Sep 17 00:00:00 2001 From: "Martin \"eto\" Misuth" Date: Sun, 13 Dec 2015 00:21:02 +0100 Subject: [PATCH 10/29] added cpu monitoring for both single core and smp systems, some notes in process monitor --- freebsd/FreeBSDProcessList.c | 173 +++++++++++++++++++++++++++++++---- freebsd/Platform.c | 36 +++++++- 2 files changed, 188 insertions(+), 21 deletions(-) diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index ee84753c..a8e1af09 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -23,13 +23,20 @@ in the source distribution for its full text. #include #include #include +#include #define JAIL_ERRMSGLEN 1024 char jail_errmsg[JAIL_ERRMSGLEN]; typedef struct CPUData_ { - unsigned long long int totalTime; - unsigned long long int totalPeriod; + + double userPercent; + double nicePercent; + double systemPercent; + double irqPercent; + double idlePercent; + double systemAllPercent; + } CPUData; typedef struct FreeBSDProcessList_ { @@ -38,6 +45,12 @@ typedef struct FreeBSDProcessList_ { CPUData* cpus; + unsigned long *cp_time_o; + unsigned long *cp_time_n; + + unsigned long *cp_times_o; + unsigned long *cp_times_n; + } FreeBSDProcessList; }*/ @@ -46,25 +59,17 @@ static int MIB_vm_stats_vm_v_wire_count[4]; static int MIB_vm_stats_vm_v_cache_count[4]; static int MIB_hw_physmem[2]; +static int MIB_kern_cp_time[2]; +static int MIB_kern_cp_times[2]; + static int pageSizeKb; + ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { FreeBSDProcessList* fpl = calloc(1, sizeof(FreeBSDProcessList)); ProcessList* pl = (ProcessList*) fpl; ProcessList_init(pl, Class(FreeBSDProcess), usersTable, pidWhiteList, userId); - int cpus = 1; - size_t sizeof_cpus = sizeof(cpus); - int err = sysctlbyname("hw.ncpu", &cpus, &sizeof_cpus, NULL, 0); - if (err) cpus = 1; - pl->cpuCount = MAX(cpus, 1); - fpl->cpus = realloc(fpl->cpus, cpus * sizeof(CPUData)); - - for (int i = 0; i < cpus; i++) { - fpl->cpus[i].totalTime = 1; - fpl->cpus[i].totalPeriod = 1; - } - size_t len; len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len); len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len); @@ -74,6 +79,50 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui fpl->kd = kvm_open(NULL, "/dev/null", NULL, 0, NULL); assert(fpl->kd); + int smp = 0; + size_t sizeof_smp = sizeof(smp); + + if (sysctlbyname("kern.smp.active", &smp, &sizeof_smp, NULL, 0) != 0 || sizeof_smp != sizeof(smp)) { + smp = 0; + } + + int cpus = 1; + size_t sizeof_cpus = sizeof(cpus); + + if (smp) { + int err = sysctlbyname("kern.smp.cpus", &cpus, &sizeof_cpus, NULL, 0); + if (err) cpus = 1; + } else { + cpus = 1; + } + + size_t sizeof_cp_time_array = sizeof(unsigned long) * CPUSTATES; + len = 2; sysctlnametomib("kern.cp_time", MIB_kern_cp_time, &len); + fpl->cp_time_o = calloc(cpus, sizeof_cp_time_array); + fpl->cp_time_n = calloc(cpus, sizeof_cp_time_array); + len = sizeof_cp_time_array; + + // fetch intial single (or average) CPU clicks from kernel + sysctl(MIB_kern_cp_time, 2, fpl->cp_time_o, &len, NULL, 0); + + // on smp box, fetch rest of intial CPU's clicks + if (cpus > 1) { + len = 2; sysctlnametomib("kern.cp_times", MIB_kern_cp_times, &len); + fpl->cp_times_o = calloc(cpus, sizeof_cp_time_array); + fpl->cp_times_n = calloc(cpus, sizeof_cp_time_array); + len = cpus * sizeof_cp_time_array; + sysctl(MIB_kern_cp_times, 2, fpl->cp_times_o, &len, NULL, 0); + } + + pl->cpuCount = MAX(cpus, 1); + + if (cpus == 1 ) { + fpl->cpus = realloc(fpl->cpus, sizeof(CPUData)); + } else { + // on smp we need CPUs + 1 to store averages too (as kernel kindly provides that as well) + fpl->cpus = realloc(fpl->cpus, (pl->cpuCount + 1) * sizeof(CPUData)); + } + return pl; } @@ -81,10 +130,95 @@ void ProcessList_delete(ProcessList* this) { const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this; if (fpl->kd) kvm_close(fpl->kd); + if (fpl->cp_time_o != NULL) free(fpl->cp_time_o); + if (fpl->cp_time_n != NULL) free(fpl->cp_time_n); + if (fpl->cp_times_o != NULL) free(fpl->cp_times_o); + if (fpl->cp_times_n != NULL) free(fpl->cp_times_n); + ProcessList_done(this); free(this); } +static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) { + const FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; + + int cpus = pl->cpuCount; // actual CPU count + int maxcpu = cpus; // max iteration (in case we have average + smp) + int cp_times_offset; + + assert(cpus > 0); + + size_t sizeof_cp_time_array; + + unsigned long *cp_time_n; // old clicks state + unsigned long *cp_time_o; // current clicks state + + unsigned long long total_o = 0; + unsigned long long total_n = 0; + unsigned long long total_d = 0; + unsigned long cp_time_d[CPUSTATES]; + double cp_time_p[CPUSTATES]; + + // get averages or single CPU clicks + sizeof_cp_time_array = sizeof(unsigned long) * CPUSTATES; + sysctl(MIB_kern_cp_time, 2, fpl->cp_time_n, &sizeof_cp_time_array, NULL, 0); + + // get rest of CPUs + if (cpus > 1) { + // on smp systems FreeBSD kernel concats all CPU states into one long array in + // kern.cp_times sysctl OID + // we store averages in fpl->cpus[0], and actual cores after that + maxcpu = cpus + 1; + sizeof_cp_time_array = cpus * sizeof(unsigned long) * CPUSTATES; + sysctl(MIB_kern_cp_times, 2, fpl->cp_times_n, &sizeof_cp_time_array, NULL, 0); + } + + for (int i = 0; i < maxcpu; i++) { + if (cpus == 1) { + // single CPU box + cp_time_n = fpl->cp_time_n; + cp_time_o = fpl->cp_time_o; + } else { + if (i == 0 ) { + // average + cp_time_n = fpl->cp_time_n; + cp_time_o = fpl->cp_time_o; + } else { + // specific smp cores + cp_times_offset = i - 1; + cp_time_n = fpl->cp_times_n + (cp_times_offset * CPUSTATES); + cp_time_o = fpl->cp_times_o + (cp_times_offset * CPUSTATES); + } + } + + // diff old vs new + for (int s = 0; s < CPUSTATES; s++) { + cp_time_d[s] = cp_time_n[s] - cp_time_o[s]; + total_o += cp_time_o[s]; + total_n += cp_time_n[s]; + } + + // totals + total_d = total_n - total_o; + if (total_d < 1 ) total_d = 1; + + // save current state as old and calc percentages + for (int s = 0; s < CPUSTATES; ++s) { + cp_time_o[s] = cp_time_n[s]; + cp_time_p[s] = ((double)cp_time_d[s]) / ((double)total_d) * 100; + } + + CPUData* cpuData = &(fpl->cpus[i]); + cpuData->userPercent = cp_time_p[CP_USER]; + cpuData->nicePercent = cp_time_p[CP_NICE]; + cpuData->systemPercent = cp_time_p[CP_SYS]; + cpuData->irqPercent = cp_time_p[CP_INTR]; + cpuData->systemAllPercent = cp_time_p[CP_SYS] + cp_time_p[CP_INTR]; + // this one is not really used, but we store it anyway + cpuData->idlePercent = cp_time_p[CP_IDLE]; + } +} + static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { const FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; @@ -186,6 +320,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { bool hideUserlandThreads = settings->hideUserlandThreads; FreeBSDProcessList_scanMemoryInfo(this); + FreeBSDProcessList_scanCPUTime(this); int count = 0; struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_ALL, 0, &count); @@ -199,7 +334,6 @@ void ProcessList_goThroughEntries(ProcessList* this) { proc->show = ! ((hideKernelThreads && Process_isKernelThread(fp)) || (hideUserlandThreads && Process_isUserlandThread(proc))); - if (!preExisting) { fp->jid = kproc->ki_jid; proc->pid = kproc->ki_pid; @@ -220,11 +354,17 @@ void ProcessList_goThroughEntries(ProcessList* this) { fp->jname = FreeBSDProcessList_readJailName(kproc); } else { if(fp->jid != kproc->ki_jid) { + // proces can enter jail anytime fp->jid = kproc->ki_jid; free(fp->jname); fp->jname = FreeBSDProcessList_readJailName(kproc); } + if (proc->ppid != kproc->ki_ppid) { + // if there are reapers in the system, proces can get reparented anytime + proc->ppid = kproc->ki_ppid; + } if(proc->st_uid != kproc->ki_uid) { + // some proceses change users (eg. to lower privs) proc->st_uid = kproc->ki_uid; proc->user = UsersTable_getRef(this->usersTable, proc->st_uid); } @@ -234,8 +374,6 @@ void ProcessList_goThroughEntries(ProcessList* this) { } } - proc->ppid = kproc->ki_ppid; - proc->m_size = kproc->ki_size / pageSizeKb / 1000; proc->m_resident = kproc->ki_rssize; // * pageSizeKb; proc->nlwp = kproc->ki_numthreads; @@ -253,7 +391,6 @@ void ProcessList_goThroughEntries(ProcessList* this) { proc->nice = PRIO_MAX + 1 + kproc->ki_pri.pri_level - PRI_MIN_IDLE; } - switch (kproc->ki_stat) { case SIDL: proc->state = 'I'; break; case SRUN: proc->state = 'R'; break; diff --git a/freebsd/Platform.c b/freebsd/Platform.c index b1703291..60b7586c 100644 --- a/freebsd/Platform.c +++ b/freebsd/Platform.c @@ -16,6 +16,7 @@ in the source distribution for its full text. #include "ClockMeter.h" #include "HostnameMeter.h" #include "FreeBSDProcess.h" +#include "FreeBSDProcessList.h" #include #include @@ -105,7 +106,7 @@ int Platform_getUptime() { struct timeval bootTime, currTime; int mib[2] = { CTL_KERN, KERN_BOOTTIME }; size_t size = sizeof(bootTime); - + int err = sysctl(mib, 2, &bootTime, &size, NULL, 0); if (err) { return -1; @@ -119,7 +120,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) { struct loadavg loadAverage; int mib[2] = { CTL_VM, VM_LOADAVG }; size_t size = sizeof(loadAverage); - + int err = sysctl(mib, 2, &loadAverage, &size, NULL, 0); if (err) { *one = 0; @@ -143,7 +144,36 @@ int Platform_getMaxPid() { } double Platform_setCPUValues(Meter* this, int cpu) { - // TODO + FreeBSDProcessList* fpl = (FreeBSDProcessList*) this->pl; + int cpus = this->pl->cpuCount; + CPUData* cpuData; + + if (cpus == 1) { + // single CPU box has everything in fpl->cpus[0] + cpuData = &(fpl->cpus[0]); + } else { + cpuData = &(fpl->cpus[cpu]); + } + + double percent; + double* v = this->values; + + v[CPU_METER_NICE] = cpuData->nicePercent; + v[CPU_METER_NORMAL] = cpuData->userPercent; + if (this->pl->settings->detailedCPUTime) { + v[CPU_METER_KERNEL] = cpuData->systemPercent; + v[CPU_METER_IRQ] = cpuData->irqPercent; + Meter_setItems(this, 4); + percent = v[0]+v[1]+v[2]+v[3]; + } else { + v[2] = cpuData->systemAllPercent; + Meter_setItems(this, 3); + percent = v[0]+v[1]+v[2]; + } + + percent = MIN(100.0, MAX(0.0, percent)); + if (isnan(percent)) percent = 0.0; + return percent; } void Platform_setMemoryValues(Meter* this) { From 80f594f3145eea6345657be1a86d208b9401341b Mon Sep 17 00:00:00 2001 From: "Martin \"eto\" Misuth" Date: Sun, 13 Dec 2015 01:39:54 +0100 Subject: [PATCH 11/29] added CPU% for processes in process list --- freebsd/FreeBSDProcessList.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index a8e1af09..4531a7b1 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -63,7 +63,7 @@ static int MIB_kern_cp_time[2]; static int MIB_kern_cp_times[2]; static int pageSizeKb; - +static int kernelFScale; ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { FreeBSDProcessList* fpl = calloc(1, sizeof(FreeBSDProcessList)); @@ -79,6 +79,12 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui fpl->kd = kvm_open(NULL, "/dev/null", NULL, 0, NULL); assert(fpl->kd); + size_t sizeof_kernelFScale = sizeof(kernelFScale); + if (sysctlbyname("kern.fscale", &kernelFScale, &sizeof_kernelFScale, NULL, 0) == -1) { + //sane default on x86 machines, in case this sysctl call failed + kernelFScale = 2048; + } + int smp = 0; size_t sizeof_smp = sizeof(smp); @@ -322,6 +328,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { FreeBSDProcessList_scanMemoryInfo(this); FreeBSDProcessList_scanCPUTime(this); + int cpus = this->cpuCount; int count = 0; struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_ALL, 0, &count); @@ -379,6 +386,15 @@ void ProcessList_goThroughEntries(ProcessList* this) { proc->nlwp = kproc->ki_numthreads; proc->time = (kproc->ki_runtime + 5000) / 10000; + proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)kernelFScale); + if (cpus > 1 ) { + proc->percent_cpu = proc->percent_cpu / (double) cpus; + } + if (proc->percent_cpu >= 99.8) { + // don't break formatting + proc->percent_cpu = 99.8; + } + proc->priority = kproc->ki_pri.pri_level - PZERO; if (strcmp("intr", kproc->ki_comm) == 0 && kproc->ki_flag & P_SYSTEM) { From 9d55c56f268d8c08423ccdcb19c0fd9049eca3c0 Mon Sep 17 00:00:00 2001 From: "Martin \"eto\" Misuth" Date: Sun, 13 Dec 2015 04:11:35 +0100 Subject: [PATCH 12/29] added Support for memory meter, and slightly adjusted process monitor logic --- freebsd/FreeBSDProcessList.c | 162 ++++++++++++++++++++++++++++------- freebsd/Platform.c | 6 ++ 2 files changed, 137 insertions(+), 31 deletions(-) diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 4531a7b1..9ace433a 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -43,6 +43,15 @@ typedef struct FreeBSDProcessList_ { ProcessList super; kvm_t* kd; + int zfsArcEnabled; + + unsigned long long int memWire; + unsigned long long int memActive; + unsigned long long int memInactive; + unsigned long long int memFree; + unsigned long long int memZfsArc; + + CPUData* cpus; unsigned long *cp_time_o; @@ -55,48 +64,81 @@ typedef struct FreeBSDProcessList_ { }*/ -static int MIB_vm_stats_vm_v_wire_count[4]; -static int MIB_vm_stats_vm_v_cache_count[4]; + static int MIB_hw_physmem[2]; +static int MIB_vm_stats_vm_v_page_count[4]; +static int pageSize; +static int pageSizeKb; + +static int MIB_vm_stats_vm_v_wire_count[4]; +static int MIB_vm_stats_vm_v_active_count[4]; +static int MIB_vm_stats_vm_v_cache_count[4]; +static int MIB_vm_stats_vm_v_inactive_count[4]; +static int MIB_vm_stats_vm_v_free_count[4]; + +static int MIB_vfs_bufspace[2]; + +static int MIB_kstat_zfs_misc_arcstats_size[5]; static int MIB_kern_cp_time[2]; static int MIB_kern_cp_times[2]; - -static int pageSizeKb; static int kernelFScale; + ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { FreeBSDProcessList* fpl = calloc(1, sizeof(FreeBSDProcessList)); ProcessList* pl = (ProcessList*) fpl; ProcessList_init(pl, Class(FreeBSDProcess), usersTable, pidWhiteList, userId); size_t len; - len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len); - len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len); - len = 2; sysctlnametomib("hw.physmem", MIB_hw_physmem, &len); - pageSizeKb = PAGE_SIZE_KB; - fpl->kd = kvm_open(NULL, "/dev/null", NULL, 0, NULL); - assert(fpl->kd); + // physical memory in system: hw.physmem + // physical page size: hw.pagesize + // usable pagesize : vm.stats.vm.v_page_size + len = 2; sysctlnametomib("hw.physmem", MIB_hw_physmem, &len); - size_t sizeof_kernelFScale = sizeof(kernelFScale); - if (sysctlbyname("kern.fscale", &kernelFScale, &sizeof_kernelFScale, NULL, 0) == -1) { - //sane default on x86 machines, in case this sysctl call failed - kernelFScale = 2048; + len = sizeof(pageSize); + if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) { + pageSize = PAGE_SIZE; + pageSizeKb = PAGE_SIZE_KB; + } else { + pageSizeKb = pageSize / ONE_K; } - int smp = 0; - size_t sizeof_smp = sizeof(smp); + // usable page count vm.stats.vm.v_page_count + // actually usable memory : vm.stats.vm.v_page_count * vm.stats.vm.v_page_size + len = 4; sysctlnametomib("vm.stats.vm.v_page_count", MIB_vm_stats_vm_v_page_count, &len); - if (sysctlbyname("kern.smp.active", &smp, &sizeof_smp, NULL, 0) != 0 || sizeof_smp != sizeof(smp)) { + len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_active_count", MIB_vm_stats_vm_v_active_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_inactive_count", MIB_vm_stats_vm_v_inactive_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_free_count", MIB_vm_stats_vm_v_free_count, &len); + + len = 2; sysctlnametomib("vfs.bufspace", MIB_vfs_bufspace, &len); + + len = sizeof(fpl->memZfsArc); + if (sysctlbyname("kstat.zfs.misc.arcstats.size", &fpl->memZfsArc, &len, + NULL, 0) == 0 && fpl->memZfsArc != 0) { + sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); + fpl->zfsArcEnabled = 1; + } else { + fpl->zfsArcEnabled = 0; + } + + + int smp = 0; + len = sizeof(smp); + + if (sysctlbyname("kern.smp.active", &smp, &len, NULL, 0) != 0 || len != sizeof(smp)) { smp = 0; } int cpus = 1; - size_t sizeof_cpus = sizeof(cpus); + len = sizeof(cpus); if (smp) { - int err = sysctlbyname("kern.smp.cpus", &cpus, &sizeof_cpus, NULL, 0); + int err = sysctlbyname("kern.smp.cpus", &cpus, &len, NULL, 0); if (err) cpus = 1; } else { cpus = 1; @@ -129,6 +171,16 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui fpl->cpus = realloc(fpl->cpus, (pl->cpuCount + 1) * sizeof(CPUData)); } + + len = sizeof(kernelFScale); + if (sysctlbyname("kern.fscale", &kernelFScale, &len, NULL, 0) == -1) { + //sane default for kernel provded CPU precentage scaling, at least on x86 machines, in case this sysctl call failed + kernelFScale = 2048; + } + + fpl->kd = kvm_open(NULL, "/dev/null", NULL, 0, NULL); + assert(fpl->kd); + return pl; } @@ -226,17 +278,59 @@ static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) { } static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { - const FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; + FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; + // @etosan: + // memory counter relationships seem to be these: + // total = active + wired + inactive + cache + free + // htop_used (unavail to anybody) = active + wired + // htop_cache (for cache meter) = buffers + cache + // user_free (avail to procs) = buffers + inactive + cache + free + // + // with ZFS ARC situation becomes bit muddled, as ARC behaves like "user_free" + // and belongs into cache, but is reported as wired by kernel + // + // htop_used = active + (wired - arc) + // htop_cache = buffers + cache + arc size_t len = sizeof(pl->totalMem); + + //disabled for now, as it is always smaller than phycal amount of memory... + //...to avoid "where is my memory?" questions + //sysctl(MIB_vm_stats_vm_v_page_count, 4, &(pl->totalMem), &len, NULL, 0); + //pl->totalMem *= pageSizeKb; sysctl(MIB_hw_physmem, 2, &(pl->totalMem), &len, NULL, 0); pl->totalMem /= 1024; - sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(pl->usedMem), &len, NULL, 0); - pl->usedMem *= pageSizeKb; - pl->freeMem = pl->totalMem - pl->usedMem; + + sysctl(MIB_vm_stats_vm_v_active_count, 4, &(fpl->memActive), &len, NULL, 0); + fpl->memActive *= pageSizeKb; + + sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(fpl->memWire), &len, NULL, 0); + fpl->memWire *= pageSizeKb; + + sysctl(MIB_vfs_bufspace, 2, &(pl->buffersMem), &len, NULL, 0); + pl->buffersMem /= 1024; + sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(pl->cachedMem), &len, NULL, 0); pl->cachedMem *= pageSizeKb; + if (fpl->zfsArcEnabled) { + len = sizeof(fpl->memZfsArc); + sysctl(MIB_kstat_zfs_misc_arcstats_size, 5, &(fpl->memZfsArc), &len , NULL, 0); + fpl->memZfsArc /= 1024; + fpl->memWire -= fpl->memZfsArc; + pl->cachedMem += fpl->memZfsArc; + // maybe when we learn how to make custom memory meter + // we could do custom arc breakdown? + } + + pl->usedMem = fpl->memActive + fpl->memWire; + + //currently unused, same as with arc, custom meter perhaps + //sysctl(MIB_vm_stats_vm_v_inactive_count, 4, &(fpl->memInactive), &len, NULL, 0); + //sysctl(MIB_vm_stats_vm_v_free_count, 4, &(fpl->memFree), &len, NULL, 0); + //pl->freeMem = fpl->memInactive + fpl->memFree; + //pl->freeMem *= pageSizeKb; + struct kvm_swap swap[16]; int nswap = kvm_getswapinfo(fpl->kd, swap, sizeof(swap)/sizeof(swap[0]), 0); pl->totalSwap = 0; @@ -249,7 +343,6 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { pl->usedSwap *= pageSizeKb; pl->sharedMem = 0; // currently unused - pl->buffersMem = 0; // not exposed to userspace } char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd) { @@ -334,8 +427,8 @@ void ProcessList_goThroughEntries(ProcessList* this) { for (int i = 0; i < count; i++) { struct kinfo_proc* kproc = &kprocs[i]; - bool preExisting = false; + bool isIdleProcess = false; Process* proc = ProcessList_getProcess(this, kproc->ki_pid, &preExisting, (Process_New) FreeBSDProcess_new); FreeBSDProcess* fp = (FreeBSDProcess*) proc; @@ -381,16 +474,23 @@ void ProcessList_goThroughEntries(ProcessList* this) { } } - proc->m_size = kproc->ki_size / pageSizeKb / 1000; - proc->m_resident = kproc->ki_rssize; // * pageSizeKb; + // from FreeBSD source /src/usr.bin/top/machine.c + proc->m_size = kproc->ki_size / 1024; + proc->m_resident = kproc->ki_rssize * pageSizeKb; proc->nlwp = kproc->ki_numthreads; proc->time = (kproc->ki_runtime + 5000) / 10000; proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)kernelFScale); - if (cpus > 1 ) { - proc->percent_cpu = proc->percent_cpu / (double) cpus; + if (proc->percent_cpu > 0.1) { + // system idle process should own all CPU time left regardless of CPU count + if ( strcmp("idle", kproc->ki_comm) == 0 ) { + isIdleProcess = true; + } else { + if (cpus > 1) + proc->percent_cpu = proc->percent_cpu / (double) cpus; + } } - if (proc->percent_cpu >= 99.8) { + if (isIdleProcess == false && proc->percent_cpu >= 99.8) { // don't break formatting proc->percent_cpu = 99.8; } @@ -398,7 +498,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { proc->priority = kproc->ki_pri.pri_level - PZERO; if (strcmp("intr", kproc->ki_comm) == 0 && kproc->ki_flag & P_SYSTEM) { - proc->nice = 0; //@etosan: freebsd intr kernel process (not thread) has weird nice value + proc->nice = 0; //@etosan: intr kernel process (not thread) has weird nice value } else if (kproc->ki_pri.pri_class == PRI_TIMESHARE) { proc->nice = kproc->ki_nice - NZERO; } else if (PRI_IS_REALTIME(kproc->ki_pri.pri_class)) { diff --git a/freebsd/Platform.c b/freebsd/Platform.c index 60b7586c..2dd15766 100644 --- a/freebsd/Platform.c +++ b/freebsd/Platform.c @@ -178,6 +178,12 @@ double Platform_setCPUValues(Meter* this, int cpu) { void Platform_setMemoryValues(Meter* this) { // TODO + ProcessList* pl = (ProcessList*) this->pl; + + this->total = pl->totalMem; + this->values[0] = pl->usedMem; + this->values[1] = pl->buffersMem; + this->values[2] = pl->cachedMem; } void Platform_setSwapValues(Meter* this) { From e0b6e2eef2f9a401419d06273681e4486d1b4484 Mon Sep 17 00:00:00 2001 From: "Martin \"eto\" Misuth" Date: Sun, 13 Dec 2015 04:16:06 +0100 Subject: [PATCH 13/29] enabled swap meter --- freebsd/Platform.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/freebsd/Platform.c b/freebsd/Platform.c index 2dd15766..a51b12bb 100644 --- a/freebsd/Platform.c +++ b/freebsd/Platform.c @@ -187,7 +187,9 @@ void Platform_setMemoryValues(Meter* this) { } void Platform_setSwapValues(Meter* this) { - // TODO + ProcessList* pl = (ProcessList*) this->pl; + this->total = pl->totalSwap; + this->values[0] = pl->usedSwap; } void Platform_setTasksValues(Meter* this) { From 802e216870efb740069583b208fa4bac970653e0 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Mon, 14 Dec 2015 13:27:11 -0200 Subject: [PATCH 14/29] 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 --- Process.h | 2 ++ linux/LinuxProcessList.c | 32 ++++++++++++++++++-------------- linux/LinuxProcessList.h | 4 ++++ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Process.h b/Process.h index 841b1291..d856c035 100644 --- a/Process.h +++ b/Process.h @@ -158,6 +158,8 @@ typedef struct ProcessClass_ { #define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K) #define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K) +extern char Process_pidFormat[20]; + void Process_setupColumnWidths(); void Process_humanNumber(RichString* str, unsigned long number, bool coloring); diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index e939b4a9..9387dbd4 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -78,6 +78,10 @@ typedef struct LinuxProcessList_ { #define PROCMEMINFOFILE PROCDIR "/meminfo" #endif +#ifndef PROC_LINE_LENGTH +#define PROC_LINE_LENGTH 512 +#endif + }*/ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { @@ -90,11 +94,11 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui if (file == NULL) { CRT_fatalError("Cannot open " PROCSTATFILE); } - char buffer[256]; + char buffer[PROC_LINE_LENGTH + 1]; int cpus = -1; do { cpus++; - char * s = fgets(buffer, 255, file); + char * s = fgets(buffer, PROC_LINE_LENGTH, file); (void) s; } while (String_startsWith(buffer, "cpu")); fclose(file); @@ -306,8 +310,8 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, const char* di int fd = open(filename, O_RDONLY); if (fd == -1) return false; - char buf[256]; - ssize_t rres = xread(fd, buf, 255); + char buf[PROC_LINE_LENGTH + 1]; + ssize_t rres = xread(fd, buf, PROC_LINE_LENGTH); close(fd); if (rres < 1) return false; @@ -361,13 +365,13 @@ static void LinuxProcessList_readCGroupFile(LinuxProcess* process, const char* d process->cgroup = strdup(""); return; } - char output[256]; + char output[PROC_LINE_LENGTH + 1]; output[0] = '\0'; char* at = output; - int left = 255; + int left = PROC_LINE_LENGTH; while (!feof(file) && left > 0) { - char buffer[256]; - char *ok = fgets(buffer, 255, file); + char buffer[PROC_LINE_LENGTH + 1]; + char *ok = fgets(buffer, PROC_LINE_LENGTH, file); if (!ok) break; char* group = strchr(buffer, ':'); if (!group) break; @@ -394,9 +398,9 @@ static void LinuxProcessList_readVServerData(LinuxProcess* process, const char* FILE* file = fopen(filename, "r"); if (!file) return; - char buffer[256]; + char buffer[PROC_LINE_LENGTH + 1]; process->vxid = 0; - while (fgets(buffer, 255, file)) { + while (fgets(buffer, PROC_LINE_LENGTH, file)) { if (String_startsWith(buffer, "VxID:")) { int vxid; int ok = sscanf(buffer, "VxID:\t%32d", &vxid); @@ -425,8 +429,8 @@ static void LinuxProcessList_readOomData(LinuxProcess* process, const char* dirn FILE* file = fopen(filename, "r"); if (!file) return; - char buffer[256]; - if (fgets(buffer, 255, file)) { + char buffer[PROC_LINE_LENGTH + 1]; + if (fgets(buffer, PROC_LINE_LENGTH, file)) { unsigned int oom; int ok = sscanf(buffer, "%32u", &oom); if (ok >= 1) { @@ -677,14 +681,14 @@ static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) { int cpus = this->super.cpuCount; assert(cpus > 0); for (int i = 0; i <= cpus; i++) { - char buffer[256]; + char buffer[PROC_LINE_LENGTH + 1]; unsigned long long int usertime, nicetime, systemtime, idletime; unsigned long long int ioWait, irq, softIrq, steal, guest, guestnice; ioWait = irq = softIrq = steal = guest = guestnice = 0; // Depending on your kernel version, // 5, 7, 8 or 9 of these fields will be set. // The rest will remain at zero. - char* ok = fgets(buffer, 255, file); + char* ok = fgets(buffer, PROC_LINE_LENGTH, file); if (!ok) buffer[0] = '\0'; if (i == 0) sscanf(buffer, "cpu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice); diff --git a/linux/LinuxProcessList.h b/linux/LinuxProcessList.h index 538d98cb..2a4abff9 100644 --- a/linux/LinuxProcessList.h +++ b/linux/LinuxProcessList.h @@ -59,6 +59,10 @@ typedef struct LinuxProcessList_ { #define PROCMEMINFOFILE PROCDIR "/meminfo" #endif +#ifndef PROC_LINE_LENGTH +#define PROC_LINE_LENGTH 512 +#endif + ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId); From c67e482c67b4e4a99adb95fe35945204037a0c77 Mon Sep 17 00:00:00 2001 From: "Martin \"eto\" Misuth" Date: Thu, 17 Dec 2015 08:48:53 +0100 Subject: [PATCH 15/29] 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 --- freebsd/FreeBSDProcessList.c | 1 + 1 file changed, 1 insertion(+) diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 9ace433a..e8d6f137 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -441,6 +441,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { fp->kernel = 1; else fp->kernel = 0; + proc->ppid = kproc->ki_ppid; proc->tpgid = kproc->ki_tpgid; proc->tgid = kproc->ki_pid; proc->session = kproc->ki_sid; From 71ad9b304db9aa4ece7c7b5aa75d1d8fade9d00a Mon Sep 17 00:00:00 2001 From: Explorer09 Date: Tue, 22 Dec 2015 17:43:31 +0800 Subject: [PATCH 16/29] 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 --- MetersPanel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MetersPanel.c b/MetersPanel.c index db910fb9..bdbe83ee 100644 --- a/MetersPanel.c +++ b/MetersPanel.c @@ -36,7 +36,7 @@ static const char* MetersKeys[] = {"Space", "Enter", "Del", "Esc"}; static int MetersEvents[] = {' ', 13, KEY_DC, 27}; static const char* MetersMovingFunctions[] = {"Up ", "Down ", "Left ", "Right ", "Confirm", "Delete", "Done ", NULL}; -static const char* MetersMovingKeys[] = {"Up", "Dn", "Lt", "Rt", "Arrows", "Enter", "Del", "Esc"}; +static const char* MetersMovingKeys[] = {"Up", "Dn", "Lt", "Rt", "Enter", "Del", "Esc"}; static int MetersMovingEvents[] = {KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, 13, KEY_DC, 27}; static FunctionBar* Meters_movingBar = NULL; From 22cfda6332bcfe89e143ed9475032bec7222bfa3 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 2 Jan 2016 11:57:53 -0500 Subject: [PATCH 17/29] 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. --- openbsd/OpenBSDProcessList.c | 54 +++++++++++++++++------------------- openbsd/Platform.h | 1 + 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index 210328aa..eb4cd2e7 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -12,6 +12,7 @@ in the source distribution for its full text. #include #include +#include #include #include #include @@ -59,7 +60,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui size = sizeof(fscale); if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) - CRT_fatalError("fscale sysctl call failed"); + errx(1, "fscale sysctl call failed"); for (i = 0; i < pl->cpuCount; i++) { fpl->cpus[i].totalTime = 1; @@ -89,7 +90,7 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { size_t size = sizeof(uvmexp); if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0) { - CRT_fatalError("uvmexp sysctl call failed"); + errx(1, "uvmexp sysctl call failed"); } //kb_pagesize = uvmexp.pagesize / 1024; @@ -125,34 +126,31 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { } char *OpenBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd) { - char *str, *buf, **argv; - size_t cpsz; - size_t len = 500; + char *s, *buf, **arg; + size_t cpsz, len = 0, n; + int i; - argv = kvm_getargv(kd, kproc, 500); - - if (argv == NULL) - CRT_fatalError("kvm call failed"); - - str = buf = malloc(len+1); - if (str == NULL) - CRT_fatalError("out of memory"); - - while (*argv != NULL) { - cpsz = MIN(len, strlen(*argv)); - strncpy(buf, *argv, cpsz); - buf += cpsz; - len -= cpsz; - argv++; - if (len > 0) { - *buf = ' '; - buf++; - len--; - } + arg = kvm_getargv(kd, kproc, 500); + if (arg == NULL) { + return "[zombie]"; + // the FreeBSD port uses ki_comm, but we don't have it + //return strndup(kproc->ki_comm); } - - *buf = '\0'; - return str; + for (i = 0; arg[i] != NULL; i++) { + len += strlen(arg[i]) + 1; + } + buf = s = malloc(len); + for (i = 0; arg[i] != NULL; i++) { + n = strlcpy(buf, arg[i], (s + len) - buf); + buf += n; + if (i == 0) { + *basenameEnd = n; + } + buf++; + *buf = ' '; + } + *(buf - 1) = '\0'; + return s; } /* diff --git a/openbsd/Platform.h b/openbsd/Platform.h index a59d2ef5..d8dea1b1 100644 --- a/openbsd/Platform.h +++ b/openbsd/Platform.h @@ -11,6 +11,7 @@ in the source distribution for its full text. */ #include "Action.h" +#include "SignalsPanel.h" #include "BatteryMeter.h" extern ProcessFieldData Process_fields[]; From 71703827063770d78438ec0051e70f579faafbf4 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 2 Jan 2016 12:11:26 -0500 Subject: [PATCH 18/29] Fix spelling of "maintainer" --- darwin/DarwinCRT.c | 2 +- freebsd/FreeBSDCRT.c | 2 +- linux/LinuxCRT.c | 2 +- openbsd/OpenBSDCRT.c | 2 +- unsupported/UnsupportedCRT.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/darwin/DarwinCRT.c b/darwin/DarwinCRT.c index 3efb18a7..51725984 100644 --- a/darwin/DarwinCRT.c +++ b/darwin/DarwinCRT.c @@ -28,7 +28,7 @@ void CRT_handleSIGSEGV(int sgn) { #endif #else fprintf(stderr, "\nUnfortunately, you seem to be using an unsupported platform!"); - fprintf(stderr, "\nPlease contact your platform package mantainer!\n\n"); + fprintf(stderr, "\nPlease contact your platform package maintainer!\n\n"); #endif abort(); } diff --git a/freebsd/FreeBSDCRT.c b/freebsd/FreeBSDCRT.c index c4e65eeb..5c3a9de4 100644 --- a/freebsd/FreeBSDCRT.c +++ b/freebsd/FreeBSDCRT.c @@ -15,7 +15,7 @@ void CRT_handleSIGSEGV(int sgn) { CRT_done(); fprintf(stderr, "\n\nhtop " VERSION " aborting.\n"); fprintf(stderr, "\nUnfortunately, you seem to be using an unsupported platform!"); - fprintf(stderr, "\nPlease contact your platform package mantainer!\n\n"); + fprintf(stderr, "\nPlease contact your platform package maintainer!\n\n"); abort(); } diff --git a/linux/LinuxCRT.c b/linux/LinuxCRT.c index e0a12821..5b2a21fd 100644 --- a/linux/LinuxCRT.c +++ b/linux/LinuxCRT.c @@ -30,7 +30,7 @@ void CRT_handleSIGSEGV(int sgn) { #endif #else fprintf(stderr, "\nUnfortunately, you seem to be using an unsupported platform!"); - fprintf(stderr, "\nPlease contact your platform package mantainer!\n\n"); + fprintf(stderr, "\nPlease contact your platform package maintainer!\n\n"); #endif abort(); } diff --git a/openbsd/OpenBSDCRT.c b/openbsd/OpenBSDCRT.c index 552ca30d..c5dcec4a 100644 --- a/openbsd/OpenBSDCRT.c +++ b/openbsd/OpenBSDCRT.c @@ -16,7 +16,7 @@ void CRT_handleSIGSEGV(int sgn) { CRT_done(); fprintf(stderr, "\n\nhtop " VERSION " aborting.\n"); fprintf(stderr, "\nUnfortunately, you seem to be using an unsupported platform!"); - fprintf(stderr, "\nPlease contact your platform package mantainer!\n\n"); + fprintf(stderr, "\nPlease contact your platform package maintainer!\n\n"); abort(); } diff --git a/unsupported/UnsupportedCRT.c b/unsupported/UnsupportedCRT.c index c4e65eeb..5c3a9de4 100644 --- a/unsupported/UnsupportedCRT.c +++ b/unsupported/UnsupportedCRT.c @@ -15,7 +15,7 @@ void CRT_handleSIGSEGV(int sgn) { CRT_done(); fprintf(stderr, "\n\nhtop " VERSION " aborting.\n"); fprintf(stderr, "\nUnfortunately, you seem to be using an unsupported platform!"); - fprintf(stderr, "\nPlease contact your platform package mantainer!\n\n"); + fprintf(stderr, "\nPlease contact your platform package maintainer!\n\n"); abort(); } From ae5c01f4859e3296292bd34b2efc5a7720368d98 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 2 Jan 2016 12:17:35 -0500 Subject: [PATCH 19/29] Use err() rather then errx() for sysctl() So that we can see errno. Pointed out by Michael Reed. --- openbsd/OpenBSDProcessList.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index eb4cd2e7..aa765a15 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -60,7 +60,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui size = sizeof(fscale); if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) - errx(1, "fscale sysctl call failed"); + err(1, "fscale sysctl call failed"); for (i = 0; i < pl->cpuCount; i++) { fpl->cpus[i].totalTime = 1; @@ -90,7 +90,7 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { size_t size = sizeof(uvmexp); if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0) { - errx(1, "uvmexp sysctl call failed"); + err(1, "uvmexp sysctl call failed"); } //kb_pagesize = uvmexp.pagesize / 1024; From c1b32892190ee0b605cac5087fb000f6cefc4b1e Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 2 Jan 2016 12:20:40 -0500 Subject: [PATCH 20/29] Check for allocation failure Pointed out by Michael Reed. --- openbsd/OpenBSDProcessList.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index aa765a15..d6420853 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -139,7 +139,8 @@ char *OpenBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in for (i = 0; arg[i] != NULL; i++) { len += strlen(arg[i]) + 1; } - buf = s = malloc(len); + if ((buf = s = malloc(len)) == NULL) + err(1, NULL); for (i = 0; arg[i] != NULL; i++) { n = strlcpy(buf, arg[i], (s + len) - buf); buf += n; From 3da36bbc61dbd27f717188a0a742bb637ca4f5bc Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 2 Jan 2016 17:11:23 -0500 Subject: [PATCH 21/29] Use dynamically allocated memory for process names Even when they're constant, as is the case for zombie processes. --- openbsd/OpenBSDProcessList.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index d6420853..cbb90c91 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -132,9 +132,12 @@ char *OpenBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in arg = kvm_getargv(kd, kproc, 500); if (arg == NULL) { - return "[zombie]"; // the FreeBSD port uses ki_comm, but we don't have it //return strndup(kproc->ki_comm); + if ((s = strdup("[zombie]")) == NULL) { + err(1, NULL); + } + return s; } for (i = 0; arg[i] != NULL; i++) { len += strlen(arg[i]) + 1; From 918cfd54d6ea3794f412ab891acd40bb6e555127 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 2 Jan 2016 22:05:20 -0500 Subject: [PATCH 22/29] 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. --- openbsd/OpenBSDProcessList.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index cbb90c91..25f63349 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -130,28 +130,34 @@ char *OpenBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in size_t cpsz, len = 0, n; int i; + /* + * We attempt to fall back to just the command name (argv[0]) if we + * fail to construct the full command at any point. + */ arg = kvm_getargv(kd, kproc, 500); if (arg == NULL) { - // the FreeBSD port uses ki_comm, but we don't have it - //return strndup(kproc->ki_comm); - if ((s = strdup("[zombie]")) == NULL) { - err(1, NULL); + if ((s = strdup(kproc->p_comm)) == NULL) { + err(1, NULL); } return s; } for (i = 0; arg[i] != NULL; i++) { len += strlen(arg[i]) + 1; } - if ((buf = s = malloc(len)) == NULL) - err(1, NULL); + if ((buf = s = malloc(len)) == NULL) { + if ((s = strdup(kproc->p_comm)) == NULL) { + err(1, NULL); + } + return s; + } for (i = 0; arg[i] != NULL; i++) { n = strlcpy(buf, arg[i], (s + len) - buf); buf += n; if (i == 0) { - *basenameEnd = n; + *basenameEnd = n; } - buf++; *buf = ' '; + buf++; } *(buf - 1) = '\0'; return s; From 70cd5c2b88ca6b2f9966a5e9b3e8be19a938b7f7 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Sun, 3 Jan 2016 16:31:44 -0200 Subject: [PATCH 23/29] Check range when accessing keys table. Should fix #321. --- MainPanel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainPanel.c b/MainPanel.c index 2e91a3c5..336cfa46 100644 --- a/MainPanel.c +++ b/MainPanel.c @@ -91,7 +91,7 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) { result = HANDLED; } else if (ch == 27) { return HANDLED; - } else if (ch != ERR && this->keys[ch]) { + } else if (ch != ERR && ch > 0 && ch < KEY_MAX && this->keys[ch]) { reaction |= (this->keys[ch])(this->state); result = HANDLED; } else if (isdigit(ch)) { From 198592a0f1d688f75820111be64ba9e2da4ac679 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sun, 3 Jan 2016 16:56:33 -0500 Subject: [PATCH 24/29] Plug mem leak, improve CPU enumeration logic I think this leak may still exist in the FreeBSD port. --- openbsd/OpenBSDProcessList.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index 25f63349..9757ef91 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -48,19 +48,21 @@ static long fscale; ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { int mib[] = { CTL_HW, HW_NCPU }; int fmib[] = { CTL_KERN, KERN_FSCALE }; - int i; + int i, e; OpenBSDProcessList* fpl = calloc(1, sizeof(OpenBSDProcessList)); ProcessList* pl = (ProcessList*) fpl; size_t size = sizeof(pl->cpuCount); ProcessList_init(pl, Class(OpenBSDProcess), usersTable, pidWhiteList, userId); - pl->cpuCount = 1; // default to 1 on sysctl() error - (void)sysctl(mib, 2, &pl->cpuCount, &size, NULL, 0); + e = sysctl(mib, 2, &pl->cpuCount, &size, NULL, 0); + if (e == -1 || pl->cpuCount < 1) { + pl->cpuCount = 1; + } fpl->cpus = realloc(fpl->cpus, pl->cpuCount * sizeof(CPUData)); size = sizeof(fscale); if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) - err(1, "fscale sysctl call failed"); + err(1, "fscale sysctl call failed"); for (i = 0; i < pl->cpuCount; i++) { fpl->cpus[i].totalTime = 1; @@ -80,6 +82,8 @@ void ProcessList_delete(ProcessList* this) { const OpenBSDProcessList* fpl = (OpenBSDProcessList*) this; if (fpl->kd) kvm_close(fpl->kd); + free(fpl->cpus); + ProcessList_done(this); free(this); } From 61f2d674b03b6c4c538be5b42684e209ecc18504 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sun, 3 Jan 2016 16:59:44 -0500 Subject: [PATCH 25/29] Remove NULL-checks before free() These are never necessary when using the standard library. --- freebsd/FreeBSDProcessList.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index e8d6f137..133a3bbb 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -188,10 +188,10 @@ void ProcessList_delete(ProcessList* this) { const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this; if (fpl->kd) kvm_close(fpl->kd); - if (fpl->cp_time_o != NULL) free(fpl->cp_time_o); - if (fpl->cp_time_n != NULL) free(fpl->cp_time_n); - if (fpl->cp_times_o != NULL) free(fpl->cp_times_o); - if (fpl->cp_times_n != NULL) free(fpl->cp_times_n); + free(fpl->cp_time_o); + free(fpl->cp_time_n); + free(fpl->cp_times_o); + free(fpl->cp_times_n); ProcessList_done(this); free(this); From 9ca646acbb32e8f5172ade2ed40fb549c359ea9b Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Mon, 4 Jan 2016 16:02:29 +0100 Subject: [PATCH 26/29] align help output --- htop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htop.c b/htop.c index f5fe6db2..e8cdc75b 100644 --- a/htop.c +++ b/htop.c @@ -44,7 +44,7 @@ static void printHelpFlag() { "-s --sort-key=COLUMN Sort by COLUMN (try --sort-key=help for a list)\n" "-u --user=USERNAME Show only processes of a given user\n" "-p --pid=PID,[,PID,PID...] Show only the given PIDs\n" - "-v --version Print version info\n" + "-v --version Print version info\n" "\n" "Long options may be passed with a single dash.\n\n" "Press F1 inside htop for online help.\n" From c5b9045f1863b1ad86c95320b87858b9ac2018fd Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Mon, 4 Jan 2016 18:04:50 -0200 Subject: [PATCH 27/29] Plug leak in FreeBSD backend, as noted by @mmcco in #334. --- freebsd/FreeBSDProcessList.c | 1 + 1 file changed, 1 insertion(+) diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index e8d6f137..6eec1a03 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -192,6 +192,7 @@ void ProcessList_delete(ProcessList* this) { if (fpl->cp_time_n != NULL) free(fpl->cp_time_n); if (fpl->cp_times_o != NULL) free(fpl->cp_times_o); if (fpl->cp_times_n != NULL) free(fpl->cp_times_n); + free(fpl->cpus); ProcessList_done(this); free(this); From e595f6865e5d58cc6996124dac9df8384519ce20 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Mon, 4 Jan 2016 16:20:51 -0500 Subject: [PATCH 28/29] Rename variable for consistency Suggested by Hisham. --- openbsd/OpenBSDProcessList.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index 9757ef91..6da38efc 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -49,8 +49,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui int mib[] = { CTL_HW, HW_NCPU }; int fmib[] = { CTL_KERN, KERN_FSCALE }; int i, e; - OpenBSDProcessList* fpl = calloc(1, sizeof(OpenBSDProcessList)); - ProcessList* pl = (ProcessList*) fpl; + OpenBSDProcessList* opl = calloc(1, sizeof(OpenBSDProcessList)); + ProcessList* pl = (ProcessList*) opl; size_t size = sizeof(pl->cpuCount); ProcessList_init(pl, Class(OpenBSDProcess), usersTable, pidWhiteList, userId); @@ -58,31 +58,31 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui if (e == -1 || pl->cpuCount < 1) { pl->cpuCount = 1; } - fpl->cpus = realloc(fpl->cpus, pl->cpuCount * sizeof(CPUData)); + opl->cpus = realloc(opl->cpus, pl->cpuCount * sizeof(CPUData)); size = sizeof(fscale); if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) err(1, "fscale sysctl call failed"); for (i = 0; i < pl->cpuCount; i++) { - fpl->cpus[i].totalTime = 1; - fpl->cpus[i].totalPeriod = 1; + opl->cpus[i].totalTime = 1; + opl->cpus[i].totalPeriod = 1; } pageSizeKb = PAGE_SIZE_KB; // XXX: last arg should eventually be an errbuf - fpl->kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); - assert(fpl->kd); + opl->kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); + assert(opl->kd); return pl; } void ProcessList_delete(ProcessList* this) { - const OpenBSDProcessList* fpl = (OpenBSDProcessList*) this; - if (fpl->kd) kvm_close(fpl->kd); + const OpenBSDProcessList* opl = (OpenBSDProcessList*) this; + if (opl->kd) kvm_close(opl->kd); - free(fpl->cpus); + free(opl->cpus); ProcessList_done(this); free(this); @@ -102,7 +102,7 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { pl->totalMem = uvmexp.npages * pageSizeKb; /* - const OpenBSDProcessList* fpl = (OpenBSDProcessList*) pl; + const OpenBSDProcessList* opl = (OpenBSDProcessList*) pl; size_t len = sizeof(pl->totalMem); sysctl(MIB_hw_physmem, 2, &(pl->totalMem), &len, NULL, 0); @@ -114,7 +114,7 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { pl->cachedMem *= pageSizeKb; struct kvm_swap swap[16]; - int nswap = kvm_getswapinfo(fpl->kd, swap, sizeof(swap)/sizeof(swap[0]), 0); + int nswap = kvm_getswapinfo(opl->kd, swap, sizeof(swap)/sizeof(swap[0]), 0); pl->totalSwap = 0; pl->usedSwap = 0; for (int i = 0; i < nswap; i++) { @@ -180,7 +180,7 @@ double getpcpu(const struct kinfo_proc *kp) { } void ProcessList_goThroughEntries(ProcessList* this) { - OpenBSDProcessList* fpl = (OpenBSDProcessList*) this; + OpenBSDProcessList* opl = (OpenBSDProcessList*) this; Settings* settings = this->settings; bool hideKernelThreads = settings->hideKernelThreads; bool hideUserlandThreads = settings->hideUserlandThreads; @@ -194,7 +194,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { OpenBSDProcessList_scanMemoryInfo(this); // use KERN_PROC_KTHREAD to also include kernel threads - struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count); + struct kinfo_proc* kprocs = kvm_getprocs(opl->kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count); //struct kinfo_proc* kprocs = getprocs(KERN_PROC_ALL, 0, &count); for (i = 0; i < count; i++) { @@ -218,11 +218,11 @@ void ProcessList_goThroughEntries(ProcessList* this) { proc->starttime_ctime = kproc->p_ustart_sec; proc->user = UsersTable_getRef(this->usersTable, proc->st_uid); ProcessList_add((ProcessList*)this, proc); - proc->comm = OpenBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset); + proc->comm = OpenBSDProcessList_readProcessName(opl->kd, kproc, &proc->basenameOffset); } else { if (settings->updateProcessNames) { free(proc->comm); - proc->comm = OpenBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset); + proc->comm = OpenBSDProcessList_readProcessName(opl->kd, kproc, &proc->basenameOffset); } } From 4c23a81d725da49e3142e6de3655ef2cfb47da41 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 5 Jan 2016 10:23:08 +0100 Subject: [PATCH 29/29] use AC_HELP_STRING for proc dir --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 709b69b7..424e80ce 100644 --- a/configure.ac +++ b/configure.ac @@ -103,7 +103,7 @@ if test "x$enable_proc" = xyes; then AC_DEFINE(HAVE_PROC, 1, [Define if using a Linux-compatible proc filesystem.]) fi -AC_ARG_WITH(proc, [ --with-proc=DIR Location of a Linux-compatible proc filesystem (default=/proc).], +AC_ARG_WITH(proc, [AC_HELP_STRING([--with-proc=DIR], [Location of a Linux-compatible proc filesystem (default=/proc).])], if test -n "$withval"; then AC_DEFINE_UNQUOTED(PROCDIR, "$withval", [Path of proc filesystem])