diff --git a/Action.c b/Action.c new file mode 100644 index 00000000..23f0c840 --- /dev/null +++ b/Action.c @@ -0,0 +1,59 @@ +/* +htop - Action.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Process.h" +#include "Panel.h" +#include "Action.h" + +/*{ + +#include "IncSet.h" +#include "Settings.h" +#include "UsersTable.h" + +typedef enum { + HTOP_OK = 0x00, + HTOP_REFRESH = 0x01, + HTOP_RECALCULATE = 0x03, // implies HTOP_REFRESH + HTOP_SAVE_SETTINGS = 0x04, + HTOP_KEEP_FOLLOWING = 0x08, + HTOP_QUIT = 0x10, + HTOP_REDRAW_BAR = 0x20, + HTOP_UPDATE_PANELHDR = 0x41, // implies HTOP_REFRESH +} Htop_Reaction; + +typedef Htop_Reaction (*Htop_Action)(); + +typedef struct State_ { + IncSet* inc; + Settings* settings; + UsersTable* ut; +} State; + +typedef bool(*Action_ForeachProcessFn)(Process*, size_t); + +}*/ + +bool Action_foreachProcess(Panel* panel, Action_ForeachProcessFn fn, int arg, bool* wasAnyTagged) { + bool ok = true; + bool anyTagged = false; + for (int i = 0; i < Panel_size(panel); i++) { + Process* p = (Process*) Panel_get(panel, i); + if (p->tag) { + ok = fn(p, arg) && ok; + anyTagged = true; + } + } + if (!anyTagged) { + Process* p = (Process*) Panel_getSelected(panel); + if (p) ok = fn(p, arg) && ok; + } + if (wasAnyTagged) + *wasAnyTagged = anyTagged; + return ok; +} + diff --git a/Action.h b/Action.h new file mode 100644 index 00000000..5a2ce1ce --- /dev/null +++ b/Action.h @@ -0,0 +1,42 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_Action +#define HEADER_Action +/* +htop - Action.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + + +#include "IncSet.h" +#include "Settings.h" +#include "UsersTable.h" + +typedef enum { + HTOP_OK = 0x00, + HTOP_REFRESH = 0x01, + HTOP_RECALCULATE = 0x03, // implies HTOP_REFRESH + HTOP_SAVE_SETTINGS = 0x04, + HTOP_KEEP_FOLLOWING = 0x08, + HTOP_QUIT = 0x10, + HTOP_REDRAW_BAR = 0x20, + HTOP_UPDATE_PANELHDR = 0x41, // implies HTOP_REFRESH +} Htop_Reaction; + +typedef Htop_Reaction (*Htop_Action)(); + +typedef struct State_ { + IncSet* inc; + Settings* settings; + UsersTable* ut; +} State; + +typedef bool(*Action_ForeachProcessFn)(Process*, size_t); + + +bool Action_foreachProcess(Panel* panel, Action_ForeachProcessFn fn, int arg, bool* wasAnyTagged); + + +#endif diff --git a/CRT.c b/CRT.c index 14a30d0f..c06c3caf 100644 --- a/CRT.c +++ b/CRT.c @@ -7,7 +7,6 @@ in the source distribution for its full text. #include "CRT.h" -#include "config.h" #include "String.h" #include "RichString.h" @@ -16,9 +15,6 @@ in the source distribution for its full text. #include #include #include -#ifdef HAVE_EXECINFO_H -#include -#endif #define ColorPair(i,j) COLOR_PAIR((7-i)*8+j) @@ -112,6 +108,8 @@ typedef enum ColorElements_ { void CRT_fatalError(const char* note) __attribute__ ((noreturn)); +void CRT_handleSIGSEGV(int sgn); + }*/ // TODO: centralize these in Settings. @@ -134,27 +132,6 @@ char* CRT_termType; void *backtraceArray[128]; -static void CRT_handleSIGSEGV(int sgn) { - (void) sgn; - CRT_done(); - #if __linux - fprintf(stderr, "\n\nhtop " VERSION " aborting. Please report bug at http://hisham.hm/htop\n"); - #ifdef HAVE_EXECINFO_H - size_t size = backtrace(backtraceArray, sizeof(backtraceArray) / sizeof(void *)); - fprintf(stderr, "\n Please include in your report the following backtrace: \n"); - backtrace_symbols_fd(backtraceArray, size, 2); - fprintf(stderr, "\nAdditionally, in order to make the above backtrace useful,"); - fprintf(stderr, "\nplease also run the following command to generate a disassembly of your binary:"); - fprintf(stderr, "\n\n objdump -d `which htop` > ~/htop.objdump"); - fprintf(stderr, "\n\nand then attach the file ~/htop.objdump to your bug report."); - fprintf(stderr, "\n\nThank you for helping to improve htop!\n\n"); - #endif - #else - fprintf(stderr, "\n\nhtop " VERSION " aborting. Unsupported platform.\n"); - #endif - abort(); -} - static void CRT_handleSIGTERM(int sgn) { (void) sgn; CRT_done(); diff --git a/CRT.h b/CRT.h index 260d0874..b77a83a7 100644 --- a/CRT.h +++ b/CRT.h @@ -9,9 +9,6 @@ Released under the GNU GPL, see the COPYING file in the source distribution for its full text. */ -#ifdef HAVE_EXECINFO_H -#endif - #define ColorPair(i,j) COLOR_PAIR((7-i)*8+j) #define COLORSCHEME_DEFAULT 0 @@ -103,6 +100,8 @@ typedef enum ColorElements_ { void CRT_fatalError(const char* note) __attribute__ ((noreturn)); +void CRT_handleSIGSEGV(int sgn); + // TODO: centralize these in Settings. diff --git a/Makefile.am b/Makefile.am index 820e2e54..9eb31a79 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,9 @@ ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = subdir-objects bin_PROGRAMS = htop + dist_man_MANS = htop.1 EXTRA_DIST = $(dist_man_MANS) htop.desktop htop.png scripts/MakeHeader.py \ install-sh autogen.sh missing @@ -10,7 +12,7 @@ applications_DATA = htop.desktop pixmapdir = $(datadir)/pixmaps pixmap_DATA = htop.png -htop_CFLAGS = -pedantic -Wall -Wextra -std=c99 -rdynamic -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR=\"$(sysconfdir)\" +htop_CFLAGS = -pedantic -Wall -Wextra -std=c99 -rdynamic -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR=\"$(sysconfdir)\" -I"$(my_htop_platform)" AM_CPPFLAGS = -DNDEBUG myhtopsources = AvailableMetersPanel.c CategoriesPanel.c CheckItem.c \ @@ -18,23 +20,42 @@ ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c \ DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \ LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \ BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \ -IOPriorityPanel.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \ +SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \ UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \ -HostnameMeter.c OpenFilesScreen.c Affinity.c IOPriority.c IncSet.c +HostnameMeter.c OpenFilesScreen.c Affinity.c IncSet.c Action.c myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \ CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \ -IOPriorityPanel.h CPUMeter.h CRT.h DisplayOptionsPanel.h FunctionBar.h \ +CPUMeter.h CRT.h DisplayOptionsPanel.h FunctionBar.h \ Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \ BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \ ScreenManager.h Settings.h SignalsPanel.h String.h SwapMeter.h TasksMeter.h \ TraceScreen.h UptimeMeter.h UsersTable.h Vector.h Process.h AffinityPanel.h \ -HostnameMeter.h OpenFilesScreen.h Affinity.h IOPriority.h IncSet.h +HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h + +if HTOP_LINUX +myhtopplatsources = linux/Platform.c linux/IOPriorityPanel.c linux/IOPriority.c \ +linux/LinuxProcessList.c linux/LinuxCRT.c + +myhtopplatheaders = linux/Platform.h linux/IOPriorityPanel.h linux/IOPriority.h \ +linux/LinuxProcessList.h linux/LinuxCRT.h +endif + +if HTOP_UNSUPPORTED +myhtopplatsources = unsupported/Platform.c unsupported/UnsupportedProcessList.c \ +unsupported/UnsupportedCRT.c + +myhtopplatheaders = unsupported/Platform.h unsupported/UnsupportedProcessList.h \ +unsupported/UnsupportedCRT.h +endif SUFFIXES = .h -BUILT_SOURCES = $(myhtopheaders) -htop_SOURCES = $(myhtopheaders) $(myhtopsources) config.h +BUILT_SOURCES = $(myhtopheaders) $(myhtopplatheaders) +htop_SOURCES = $(myhtopheaders) $(myhtopplatheaders) $(myhtopsources) $(myhtopplatsources) config.h + +target: + echo $(htop_SOURCES) profile: $(MAKE) all CFLAGS="-pg" AM_CPPFLAGS="-pg -O2 -DNDEBUG" @@ -47,3 +68,4 @@ debug: cppcheck: cppcheck -q -v . --enable=all -DHAVE_CGROUP -DHAVE_OPENVZ -DHAVE_TASKSTATS + diff --git a/Process.c b/Process.c index 5501b3e9..dd08521b 100644 --- a/Process.c +++ b/Process.c @@ -1,6 +1,6 @@ /* htop - Process.c -(C) 2004-2011 Hisham H. Muhammad +(C) 2004-2014 Hisham H. Muhammad Released under the GNU GPL, see the COPYING file in the source distribution for its full text. */ @@ -32,7 +32,7 @@ in the source distribution for its full text. #include #endif -// This works only with glibc 2.1+. On earlier versions +// On Linux, this works only with glibc 2.1+. On earlier versions // the behavior is similar to have a hardcoded page size. #ifndef PAGE_SIZE #define PAGE_SIZE ( sysconf(_SC_PAGESIZE) ) @@ -42,7 +42,7 @@ in the source distribution for its full text. /*{ #include "Object.h" #include "Affinity.h" -#include "IOPriority.h" + #include #define PROCESS_FLAG_IO 1 @@ -122,7 +122,6 @@ typedef struct Process_ { long int priority; long int nice; long int nlwp; - IOPriority ioPriority; char starttime_show[8]; time_t starttime_ctime; @@ -628,24 +627,6 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel #ifdef HAVE_OOM case OOM: snprintf(buffer, n, Process_pidFormat, this->oom); break; #endif - case IO_PRIORITY: { - int klass = IOPriority_class(this->ioPriority); - if (klass == IOPRIO_CLASS_NONE) { - // see note [1] above - snprintf(buffer, n, "B%1d ", (int) (this->nice + 20) / 5); - } else if (klass == IOPRIO_CLASS_BE) { - snprintf(buffer, n, "B%1d ", IOPriority_data(this->ioPriority)); - } else if (klass == IOPRIO_CLASS_RT) { - attr = CRT_colors[PROCESS_HIGH_PRIORITY]; - snprintf(buffer, n, "R%1d ", IOPriority_data(this->ioPriority)); - } else if (this->ioPriority == IOPriority_Idle) { - attr = CRT_colors[PROCESS_LOW_PRIORITY]; - snprintf(buffer, n, "id "); - } else { - snprintf(buffer, n, "?? "); - } - break; - } default: snprintf(buffer, n, "- "); } @@ -720,27 +701,6 @@ bool Process_changePriorityBy(Process* this, size_t delta) { return Process_setPriority(this, this->nice + delta); } -IOPriority Process_updateIOPriority(Process* this) { - IOPriority ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, this->pid); - this->ioPriority = ioprio; - return ioprio; -} - -bool Process_setIOPriority(Process* this, IOPriority ioprio) { - syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, this->pid, ioprio); - return (Process_updateIOPriority(this) == ioprio); -} - -/* -[1] Note that before kernel 2.6.26 a process that has not asked for -an io priority formally uses "none" as scheduling class, but the -io scheduler will treat such processes as if it were in the best -effort class. The priority within the best effort class will be -dynamically derived from the cpu nice level of the process: -io_priority = (cpu_nice + 20) / 5. -- From ionice(1) man page -*/ -#define Process_effectiveIOPriority(p_) (IOPriority_class(p_->ioPriority) == IOPRIO_CLASS_NONE ? IOPriority_tuple(IOPRIO_CLASS_BE, (p_->nice + 20) / 5) : p_->ioPriority) - #ifdef HAVE_LIBHWLOC Affinity* Process_getAffinity(Process* this) { @@ -902,8 +862,6 @@ long Process_compare(const void* v1, const void* v2) { case OOM: return (p1->oom - p2->oom); #endif - case IO_PRIORITY: - return Process_effectiveIOPriority(p1) - Process_effectiveIOPriority(p2); default: return (p1->pid - p2->pid); } diff --git a/Process.h b/Process.h index 87196eee..c4ef808d 100644 --- a/Process.h +++ b/Process.h @@ -4,7 +4,7 @@ #define HEADER_Process /* htop - Process.h -(C) 2004-2011 Hisham H. Muhammad +(C) 2004-2014 Hisham H. Muhammad Released under the GNU GPL, see the COPYING file in the source distribution for its full text. */ @@ -12,7 +12,7 @@ in the source distribution for its full text. #ifdef HAVE_LIBHWLOC #endif -// This works only with glibc 2.1+. On earlier versions +// On Linux, this works only with glibc 2.1+. On earlier versions // the behavior is similar to have a hardcoded page size. #ifndef PAGE_SIZE #define PAGE_SIZE ( sysconf(_SC_PAGESIZE) ) @@ -21,7 +21,7 @@ in the source distribution for its full text. #include "Object.h" #include "Affinity.h" -#include "IOPriority.h" + #include #define PROCESS_FLAG_IO 1 @@ -101,7 +101,6 @@ typedef struct Process_ { long int priority; long int nice; long int nlwp; - IOPriority ioPriority; char starttime_show[8]; time_t starttime_ctime; @@ -202,20 +201,6 @@ bool Process_setPriority(Process* this, int priority); bool Process_changePriorityBy(Process* this, size_t delta); -IOPriority Process_updateIOPriority(Process* this); - -bool Process_setIOPriority(Process* this, IOPriority ioprio); - -/* -[1] Note that before kernel 2.6.26 a process that has not asked for -an io priority formally uses "none" as scheduling class, but the -io scheduler will treat such processes as if it were in the best -effort class. The priority within the best effort class will be -dynamically derived from the cpu nice level of the process: -extern io_priority; -*/ -#define Process_effectiveIOPriority(p_) (IOPriority_class(p_->ioPriority) == IOPRIO_CLASS_NONE ? IOPriority_tuple(IOPRIO_CLASS_BE, (p_->nice + 20) / 5) : p_->ioPriority) - #ifdef HAVE_LIBHWLOC Affinity* Process_getAffinity(Process* this); diff --git a/ProcessList.c b/ProcessList.c index 7841e0a3..16a52a59 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -35,18 +35,6 @@ in the source distribution for its full text. #include "Panel.h" #include "Process.h" -#ifndef PROCDIR -#define PROCDIR "/proc" -#endif - -#ifndef PROCSTATFILE -#define PROCSTATFILE PROCDIR "/stat" -#endif - -#ifndef PROCMEMINFOFILE -#define PROCMEMINFOFILE PROCDIR "/meminfo" -#endif - #ifndef MAX_NAME #define MAX_NAME 128 #endif @@ -155,6 +143,9 @@ typedef struct ProcessList_ { } ProcessList; +ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidWhiteList); +void ProcessList_scan(ProcessList* pl); + }*/ static ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; @@ -179,45 +170,18 @@ const char *ProcessList_treeStrUtf8[TREE_STR_COUNT] = { "\xe2\x94\x80", // TREE_STR_SHUT ─ }; -static ssize_t xread(int fd, void *buf, size_t count) { - // Read some bytes. Retry on EINTR and when we don't get as many bytes as we requested. - size_t alreadyRead = 0; - for(;;) { - ssize_t res = read(fd, buf, count); - if (res == -1 && errno == EINTR) continue; - if (res > 0) { - buf = ((char*)buf)+res; - count -= res; - alreadyRead += res; - } - if (res == -1) return -1; - if (count == 0 || res == 0) return alreadyRead; - } -} - -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList) { - ProcessList* this; - this = calloc(1, sizeof(ProcessList)); +ProcessList* ProcessList_init(ProcessList* this, UsersTable* usersTable, Hashtable* pidWhiteList) { this->processes = Vector_new(Class(Process), true, DEFAULT_SIZE); this->processTable = Hashtable_new(140, false); this->usersTable = usersTable; this->pidWhiteList = pidWhiteList; - /* tree-view auxiliary buffers */ + // tree-view auxiliary buffers this->processes2 = Vector_new(Class(Process), true, DEFAULT_SIZE); - FILE* file = fopen(PROCSTATFILE, "r"); - if (file == NULL) { - CRT_fatalError("Cannot open " PROCSTATFILE); - } - char buffer[256]; - int cpus = -1; - do { - cpus++; - fgets(buffer, 255, file); - } while (String_startsWith(buffer, "cpu")); - fclose(file); - this->cpuCount = MAX(cpus - 1, 1); + // set later by platform-specific code + this->cpuCount = 0; + this->cpus = NULL; #ifdef HAVE_LIBHWLOC this->topologyOk = false; @@ -229,12 +193,6 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList) { this->topologyOk = true; } #endif - this->cpus = calloc(cpus, sizeof(CPUData)); - - for (int i = 0; i < cpus; i++) { - this->cpus[i].totalTime = 1; - this->cpus[i].totalPeriod = 1; - } this->fields = calloc(LAST_PROCESSFIELD+1, sizeof(ProcessField)); // TODO: turn 'fields' into a Vector, @@ -245,10 +203,6 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList) { this->flags |= Process_fieldFlags[defaultHeaders[i]]; } - #ifdef HAVE_OPENVZ - this->flags |= PROCESS_FLAG_OPENVZ; - #endif - this->sortKey = PERCENT_CPU; this->direction = 1; this->hideThreads = false; @@ -304,7 +258,7 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) { } } -static void ProcessList_add(ProcessList* this, Process* p) { +void ProcessList_add(ProcessList* this, Process* p) { assert(Vector_indexOf(this->processes, p, Process_pidCompare) == -1); assert(Hashtable_get(this->processTable, p->pid) == NULL); @@ -316,7 +270,7 @@ static void ProcessList_add(ProcessList* this, Process* p) { assert(Hashtable_count(this->processTable) == Vector_count(this->processes)); } -static void ProcessList_remove(ProcessList* this, Process* p) { +void ProcessList_remove(ProcessList* this, Process* p) { assert(Vector_indexOf(this->processes, p, Process_pidCompare) != -1); assert(Hashtable_get(this->processTable, p->pid) != NULL); Process* pp = Hashtable_remove(this->processTable, p->pid); @@ -385,6 +339,7 @@ void ProcessList_sort(ProcessList* this) { // Take PID 1 as root and add to the new listing int vsize = Vector_size(this->processes); Process* init = (Process*) (Vector_take(this->processes, 0)); + if (!init) return; // This assertion crashes on hardened kernels. // I wonder how well tree view works on those systems. // assert(init->pid == 1); @@ -408,622 +363,6 @@ void ProcessList_sort(ProcessList* this) { } } -static bool ProcessList_readStatFile(Process *process, const char* dirname, const char* name, char* command) { - char filename[MAX_NAME+1]; - snprintf(filename, MAX_NAME, "%s/%s/stat", dirname, name); - int fd = open(filename, O_RDONLY); - if (fd == -1) - return false; - - static char buf[MAX_READ+1]; - - int size = xread(fd, buf, MAX_READ); - close(fd); - if (size <= 0) return false; - buf[size] = '\0'; - - assert(process->pid == atoi(buf)); - char *location = strchr(buf, ' '); - if (!location) return false; - - location += 2; - char *end = strrchr(location, ')'); - if (!end) return false; - - int commsize = end - location; - memcpy(command, location, commsize); - command[commsize] = '\0'; - location = end + 2; - - process->state = location[0]; - location += 2; - process->ppid = strtol(location, &location, 10); - location += 1; - process->pgrp = strtoul(location, &location, 10); - location += 1; - process->session = strtoul(location, &location, 10); - location += 1; - process->tty_nr = strtoul(location, &location, 10); - location += 1; - process->tpgid = strtol(location, &location, 10); - location += 1; - process->flags = strtoul(location, &location, 10); - location += 1; - process->minflt = strtoull(location, &location, 10); - location += 1; - process->cminflt = strtoull(location, &location, 10); - location += 1; - process->majflt = strtoull(location, &location, 10); - location += 1; - process->cmajflt = strtoull(location, &location, 10); - location += 1; - process->utime = strtoull(location, &location, 10); - location += 1; - process->stime = strtoull(location, &location, 10); - location += 1; - process->cutime = strtoull(location, &location, 10); - location += 1; - process->cstime = strtoull(location, &location, 10); - location += 1; - process->priority = strtol(location, &location, 10); - location += 1; - process->nice = strtol(location, &location, 10); - location += 1; - process->nlwp = strtol(location, &location, 10); - location += 1; - for (int i=0; i<17; i++) location = strchr(location, ' ')+1; - process->exit_signal = strtol(location, &location, 10); - location += 1; - assert(location != NULL); - process->processor = strtol(location, &location, 10); - assert(location == NULL); - - return true; -} - -static bool ProcessList_statProcessDir(Process* process, const char* dirname, char* name, time_t curTime) { - char filename[MAX_NAME+1]; - filename[MAX_NAME] = '\0'; - - snprintf(filename, MAX_NAME, "%s/%s", dirname, name); - struct stat sstat; - int statok = stat(filename, &sstat); - if (statok == -1) - return false; - process->st_uid = sstat.st_uid; - - struct tm date; - time_t ctime = sstat.st_ctime; - process->starttime_ctime = ctime; - (void) localtime_r((time_t*) &ctime, &date); - strftime(process->starttime_show, 7, ((ctime > curTime - 86400) ? "%R " : "%b%d "), &date); - - return true; -} - -#ifdef HAVE_TASKSTATS - -static void ProcessList_readIoFile(Process* process, const char* dirname, char* name, unsigned long long now) { - char filename[MAX_NAME+1]; - filename[MAX_NAME] = '\0'; - - snprintf(filename, MAX_NAME, "%s/%s/io", dirname, name); - int fd = open(filename, O_RDONLY); - if (fd == -1) - return; - - char buffer[1024]; - ssize_t buflen = xread(fd, buffer, 1023); - close(fd); - if (buflen < 1) return; - buffer[buflen] = '\0'; - unsigned long long last_read = process->io_read_bytes; - unsigned long long last_write = process->io_write_bytes; - char *buf = buffer; - char *line = NULL; - while ((line = strsep(&buf, "\n")) != NULL) { - switch (line[0]) { - case 'r': - if (line[1] == 'c' && strncmp(line+2, "har: ", 5) == 0) - process->io_rchar = strtoull(line+7, NULL, 10); - else if (strncmp(line+1, "ead_bytes: ", 11) == 0) { - process->io_read_bytes = strtoull(line+12, NULL, 10); - process->io_rate_read_bps = - ((double)(process->io_read_bytes - last_read))/(((double)(now - process->io_rate_read_time))/1000); - process->io_rate_read_time = now; - } - break; - case 'w': - if (line[1] == 'c' && strncmp(line+2, "har: ", 5) == 0) - process->io_wchar = strtoull(line+7, NULL, 10); - else if (strncmp(line+1, "rite_bytes: ", 12) == 0) { - process->io_write_bytes = strtoull(line+13, NULL, 10); - process->io_rate_write_bps = - ((double)(process->io_write_bytes - last_write))/(((double)(now - process->io_rate_write_time))/1000); - process->io_rate_write_time = now; - } - break; - case 's': - if (line[5] == 'r' && strncmp(line+1, "yscr: ", 6) == 0) - process->io_syscr = strtoull(line+7, NULL, 10); - else if (strncmp(line+1, "yscw: ", 6) == 0) - sscanf(line, "syscw: %32llu", &process->io_syscw); - process->io_syscw = strtoull(line+7, NULL, 10); - break; - case 'c': - if (strncmp(line+1, "ancelled_write_bytes: ", 22) == 0) - process->io_cancelled_write_bytes = strtoull(line+23, NULL, 10); - } - } -} - -#endif - -static bool ProcessList_readStatmFile(Process* process, const char* dirname, const char* name) { - char filename[MAX_NAME+1]; - snprintf(filename, MAX_NAME, "%s/%s/statm", dirname, name); - int fd = open(filename, O_RDONLY); - if (fd == -1) - return false; - char buf[256]; - ssize_t rres = xread(fd, buf, 255); - close(fd); - if (rres < 1) return false; - - char *p = buf; - errno = 0; - process->m_size = strtol(p, &p, 10); if (*p == ' ') p++; - process->m_resident = strtol(p, &p, 10); if (*p == ' ') p++; - process->m_share = strtol(p, &p, 10); if (*p == ' ') p++; - process->m_trs = strtol(p, &p, 10); if (*p == ' ') p++; - process->m_lrs = strtol(p, &p, 10); if (*p == ' ') p++; - process->m_drs = strtol(p, &p, 10); if (*p == ' ') p++; - process->m_dt = strtol(p, &p, 10); - return (errno == 0); -} - -#ifdef HAVE_OPENVZ - -static void ProcessList_readOpenVZData(ProcessList* this, Process* process, const char* dirname, const char* name) { - if ( (!(this->flags & PROCESS_FLAG_OPENVZ)) || (access("/proc/vz", R_OK) != 0)) { - process->vpid = process->pid; - process->ctid = 0; - this->flags |= ~PROCESS_FLAG_OPENVZ; - return; - } - char filename[MAX_NAME+1]; - snprintf(filename, MAX_NAME, "%s/%s/stat", dirname, name); - FILE* file = fopen(filename, "r"); - if (!file) - return; - fscanf(file, - "%*32u %*32s %*1c %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %32u %32u", - &process->vpid, &process->ctid); - fclose(file); -} - -#endif - -#ifdef HAVE_CGROUP - -static void ProcessList_readCGroupFile(Process* process, const char* dirname, const char* name) { - char filename[MAX_NAME+1]; - snprintf(filename, MAX_NAME, "%s/%s/cgroup", dirname, name); - FILE* file = fopen(filename, "r"); - if (!file) { - process->cgroup = strdup(""); - return; - } - char buffer[256]; - char *ok = fgets(buffer, 255, file); - if (ok) { - char* trimmed = String_trim(buffer); - int nFields; - char** fields = String_split(trimmed, ':', &nFields); - free(trimmed); - if (nFields >= 3) { - process->cgroup = strndup(fields[2] + 1, 10); - } else { - process->cgroup = strdup(""); - } - String_freeArray(fields); - } - fclose(file); -} - -#endif - -#ifdef HAVE_VSERVER - -static void ProcessList_readVServerData(Process* process, const char* dirname, const char* name) { - char filename[MAX_NAME+1]; - snprintf(filename, MAX_NAME, "%s/%s/status", dirname, name); - FILE* file = fopen(filename, "r"); - if (!file) - return; - char buffer[256]; - process->vxid = 0; - while (fgets(buffer, 255, file)) { - if (String_startsWith(buffer, "VxID:")) { - int vxid; - int ok = sscanf(buffer, "VxID:\t%32d", &vxid); - if (ok >= 1) { - process->vxid = vxid; - } - } - #if defined HAVE_ANCIENT_VSERVER - else if (String_startsWith(buffer, "s_context:")) { - int vxid; - int ok = sscanf(buffer, "s_context:\t%32d", &vxid); - if (ok >= 1) { - process->vxid = vxid; - } - } - #endif - } - fclose(file); -} - -#endif - -#ifdef HAVE_OOM - -static void ProcessList_readOomData(Process* process, const char* dirname, const char* name) { - char filename[MAX_NAME+1]; - snprintf(filename, MAX_NAME, "%s/%s/oom_score", dirname, name); - FILE* file = fopen(filename, "r"); - if (!file) - return; - char buffer[256]; - if (fgets(buffer, 255, file)) { - unsigned int oom; - int ok = sscanf(buffer, "%32u", &oom); - if (ok >= 1) { - process->oom = oom; - } - } - fclose(file); -} - -#endif - -static bool ProcessList_readCmdlineFile(Process* process, const char* dirname, const char* name) { - if (Process_isKernelThread(process)) - return true; - - char filename[MAX_NAME+1]; - snprintf(filename, MAX_NAME, "%s/%s/cmdline", dirname, name); - int fd = open(filename, O_RDONLY); - if (fd == -1) - return false; - - char command[4096+1]; // max cmdline length on Linux - int amtRead = xread(fd, command, sizeof(command) - 1); - close(fd); - int tokenEnd = 0; - if (amtRead > 0) { - for (int i = 0; i < amtRead; i++) - if (command[i] == '\0' || command[i] == '\n') { - if (tokenEnd == 0) { - tokenEnd = i; - } - command[i] = ' '; - } - } - if (tokenEnd == 0) { - tokenEnd = amtRead; - } - command[amtRead] = '\0'; - free(process->comm); - process->comm = strdup(command); - process->basenameOffset = tokenEnd; - - return true; -} - - -static bool ProcessList_processEntries(ProcessList* this, const char* dirname, Process* parent, double period, struct timeval tv) { - DIR* dir; - struct dirent* entry; - - time_t curTime = tv.tv_sec; - #ifdef HAVE_TASKSTATS - unsigned long long now = tv.tv_sec*1000LL+tv.tv_usec/1000LL; - #endif - - dir = opendir(dirname); - if (!dir) return false; - int cpus = this->cpuCount; - bool hideKernelThreads = this->hideKernelThreads; - bool hideUserlandThreads = this->hideUserlandThreads; - while ((entry = readdir(dir)) != NULL) { - char* name = entry->d_name; - - // The RedHat kernel hides threads with a dot. - // I believe this is non-standard. - if ((!this->hideThreads) && name[0] == '.') { - name++; - } - - // Just skip all non-number directories. - if (name[0] < '0' || name[0] > '9') { - continue; - } - - // filename is a number: process directory - int pid = atoi(name); - - if (parent && pid == parent->pid) - continue; - - if (pid <= 0) - continue; - - Process* process = NULL; - Process* existingProcess = (Process*) Hashtable_get(this->processTable, pid); - - if (existingProcess) { - assert(Vector_indexOf(this->processes, existingProcess, Process_pidCompare) != -1); - process = existingProcess; - assert(process->pid == pid); - } else { - process = Process_new(this); - assert(process->comm == NULL); - process->pid = pid; - process->tgid = parent ? parent->pid : pid; - } - - char subdirname[MAX_NAME+1]; - snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name); - ProcessList_processEntries(this, subdirname, process, period, tv); - - #ifdef HAVE_TASKSTATS - if (this->flags & PROCESS_FLAG_IO) - ProcessList_readIoFile(process, dirname, name, now); - #endif - - if (! ProcessList_readStatmFile(process, dirname, name)) - goto errorReadingProcess; - - process->show = ! ((hideKernelThreads && Process_isKernelThread(process)) || (hideUserlandThreads && Process_isUserlandThread(process))); - - char command[MAX_NAME+1]; - unsigned long long int lasttimes = (process->utime + process->stime); - if (! ProcessList_readStatFile(process, dirname, name, command)) - goto errorReadingProcess; - if (this->flags & PROCESS_FLAG_IOPRIO) - Process_updateIOPriority(process); - float percent_cpu = (process->utime + process->stime - lasttimes) / period * 100.0; - process->percent_cpu = MAX(MIN(percent_cpu, cpus*100.0), 0.0); - if (isnan(process->percent_cpu)) process->percent_cpu = 0.0; - process->percent_mem = (process->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem) * 100.0; - - if(!existingProcess) { - - if (! ProcessList_statProcessDir(process, dirname, name, curTime)) - goto errorReadingProcess; - - process->user = UsersTable_getRef(this->usersTable, process->st_uid); - - #ifdef HAVE_OPENVZ - ProcessList_readOpenVZData(this, process, dirname, name); - #endif - - #ifdef HAVE_VSERVER - if (this->flags & PROCESS_FLAG_VSERVER) - ProcessList_readVServerData(process, dirname, name); - #endif - - if (! ProcessList_readCmdlineFile(process, dirname, name)) - goto errorReadingProcess; - - ProcessList_add(this, process); - } else { - if (this->updateProcessNames) { - if (! ProcessList_readCmdlineFile(process, dirname, name)) - goto errorReadingProcess; - } - } - - #ifdef HAVE_CGROUP - if (this->flags & PROCESS_FLAG_CGROUP) - ProcessList_readCGroupFile(process, dirname, name); - #endif - - #ifdef HAVE_OOM - ProcessList_readOomData(process, dirname, name); - #endif - - if (process->state == 'Z') { - free(process->comm); - process->basenameOffset = -1; - process->comm = strdup(command); - } else if (Process_isThread(process)) { - if (this->showThreadNames || Process_isKernelThread(process) || process->state == 'Z') { - free(process->comm); - process->basenameOffset = -1; - process->comm = strdup(command); - } else if (this->showingThreadNames) { - if (! ProcessList_readCmdlineFile(process, dirname, name)) - goto errorReadingProcess; - } - if (Process_isKernelThread(process)) { - this->kernelThreads++; - } else { - this->userlandThreads++; - } - } - - this->totalTasks++; - if (process->state == 'R') - this->runningTasks++; - process->updated = true; - - continue; - - // Exception handler. - errorReadingProcess: { - if (process->comm) { - free(process->comm); - process->basenameOffset = -1; - process->comm = NULL; - } - if (existingProcess) - ProcessList_remove(this, process); - else - Process_delete((Object*)process); - } - } - closedir(dir); - return true; -} - -void ProcessList_scan(ProcessList* this) { - unsigned long long int usertime, nicetime, systemtime, idletime; - unsigned long long int swapFree = 0; - - FILE* file = fopen(PROCMEMINFOFILE, "r"); - if (file == NULL) { - CRT_fatalError("Cannot open " PROCMEMINFOFILE); - } - int cpus = this->cpuCount; - assert(cpus > 0); - { - char buffer[128]; - while (fgets(buffer, 128, file)) { - - switch (buffer[0]) { - case 'M': - if (String_startsWith(buffer, "MemTotal:")) - sscanf(buffer, "MemTotal: %32llu kB", &this->totalMem); - else if (String_startsWith(buffer, "MemFree:")) - sscanf(buffer, "MemFree: %32llu kB", &this->freeMem); - else if (String_startsWith(buffer, "MemShared:")) - sscanf(buffer, "MemShared: %32llu kB", &this->sharedMem); - break; - case 'B': - if (String_startsWith(buffer, "Buffers:")) - sscanf(buffer, "Buffers: %32llu kB", &this->buffersMem); - break; - case 'C': - if (String_startsWith(buffer, "Cached:")) - sscanf(buffer, "Cached: %32llu kB", &this->cachedMem); - break; - case 'S': - if (String_startsWith(buffer, "SwapTotal:")) - sscanf(buffer, "SwapTotal: %32llu kB", &this->totalSwap); - if (String_startsWith(buffer, "SwapFree:")) - sscanf(buffer, "SwapFree: %32llu kB", &swapFree); - break; - } - } - } - - this->usedMem = this->totalMem - this->freeMem; - this->usedSwap = this->totalSwap - swapFree; - fclose(file); - - file = fopen(PROCSTATFILE, "r"); - if (file == NULL) { - CRT_fatalError("Cannot open " PROCSTATFILE); - } - for (int i = 0; i <= cpus; i++) { - char buffer[256]; - int cpuid; - unsigned long long int ioWait, irq, softIrq, steal, guest, guestnice; - unsigned long long int systemalltime, idlealltime, totaltime, virtalltime; - ioWait = irq = softIrq = steal = guest = guestnice = 0; - // Dependending on your kernel version, - // 5, 7, 8 or 9 of these fields will be set. - // The rest will remain at zero. - fgets(buffer, 255, file); - 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); - else { - sscanf(buffer, "cpu%4d %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice); - assert(cpuid == i - 1); - } - // Guest time is already accounted in usertime - usertime = usertime - guest; - nicetime = nicetime - guestnice; - // Fields existing on kernels >= 2.6 - // (and RHEL's patched kernel 2.4...) - idlealltime = idletime + ioWait; - systemalltime = systemtime + irq + softIrq; - virtalltime = guest + guestnice; - totaltime = usertime + nicetime + systemalltime + idlealltime + steal + virtalltime; - CPUData* cpuData = &(this->cpus[i]); - assert (usertime >= cpuData->userTime); - assert (nicetime >= cpuData->niceTime); - assert (systemtime >= cpuData->systemTime); - assert (idletime >= cpuData->idleTime); - assert (totaltime >= cpuData->totalTime); - assert (systemalltime >= cpuData->systemAllTime); - assert (idlealltime >= cpuData->idleAllTime); - assert (ioWait >= cpuData->ioWaitTime); - assert (irq >= cpuData->irqTime); - assert (softIrq >= cpuData->softIrqTime); - assert (steal >= cpuData->stealTime); - assert (virtalltime >= cpuData->guestTime); - cpuData->userPeriod = usertime - cpuData->userTime; - cpuData->nicePeriod = nicetime - cpuData->niceTime; - cpuData->systemPeriod = systemtime - cpuData->systemTime; - cpuData->systemAllPeriod = systemalltime - cpuData->systemAllTime; - cpuData->idleAllPeriod = idlealltime - cpuData->idleAllTime; - cpuData->idlePeriod = idletime - cpuData->idleTime; - cpuData->ioWaitPeriod = ioWait - cpuData->ioWaitTime; - cpuData->irqPeriod = irq - cpuData->irqTime; - cpuData->softIrqPeriod = softIrq - cpuData->softIrqTime; - cpuData->stealPeriod = steal - cpuData->stealTime; - cpuData->guestPeriod = virtalltime - cpuData->guestTime; - cpuData->totalPeriod = totaltime - cpuData->totalTime; - cpuData->userTime = usertime; - cpuData->niceTime = nicetime; - cpuData->systemTime = systemtime; - cpuData->systemAllTime = systemalltime; - cpuData->idleAllTime = idlealltime; - cpuData->idleTime = idletime; - cpuData->ioWaitTime = ioWait; - cpuData->irqTime = irq; - cpuData->softIrqTime = softIrq; - cpuData->stealTime = steal; - cpuData->guestTime = virtalltime; - cpuData->totalTime = totaltime; - } - double period = (double)this->cpus[0].totalPeriod / cpus; fclose(file); - - // mark all process as "dirty" - for (int i = 0; i < Vector_size(this->processes); i++) { - Process* p = (Process*) Vector_get(this->processes, i); - p->updated = false; - } - - this->totalTasks = 0; - this->userlandThreads = 0; - this->kernelThreads = 0; - this->runningTasks = 0; - - struct timeval tv; - gettimeofday(&tv, NULL); - ProcessList_processEntries(this, PROCDIR, NULL, period, tv); - - this->showingThreadNames = this->showThreadNames; - - for (int i = Vector_size(this->processes) - 1; i >= 0; i--) { - Process* p = (Process*) Vector_get(this->processes, i); - if (p->updated == false) - ProcessList_remove(this, p); - else - p->updated = false; - } - -} ProcessField ProcessList_keyAt(ProcessList* this, int at) { int x = 0; @@ -1083,3 +422,4 @@ void ProcessList_rebuildPanel(ProcessList* this, bool flags, int following, cons } } } + diff --git a/ProcessList.h b/ProcessList.h index fce7d03f..2bd5788a 100644 --- a/ProcessList.h +++ b/ProcessList.h @@ -15,18 +15,6 @@ in the source distribution for its full text. #include "Panel.h" #include "Process.h" -#ifndef PROCDIR -#define PROCDIR "/proc" -#endif - -#ifndef PROCSTATFILE -#define PROCSTATFILE PROCDIR "/stat" -#endif - -#ifndef PROCMEMINFOFILE -#define PROCMEMINFOFILE PROCDIR "/meminfo" -#endif - #ifndef MAX_NAME #define MAX_NAME 128 #endif @@ -135,12 +123,15 @@ typedef struct ProcessList_ { } ProcessList; +ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidWhiteList); +void ProcessList_scan(ProcessList* pl); + extern const char *ProcessList_treeStrAscii[TREE_STR_COUNT]; extern const char *ProcessList_treeStrUtf8[TREE_STR_COUNT]; -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList); +ProcessList* ProcessList_init(ProcessList* this, UsersTable* usersTable, Hashtable* pidWhiteList); void ProcessList_delete(ProcessList* this); @@ -150,39 +141,21 @@ void ProcessList_invertSortOrder(ProcessList* this); void ProcessList_printHeader(ProcessList* this, RichString* header); +void ProcessList_add(ProcessList* this, Process* p); + +void ProcessList_remove(ProcessList* this, Process* p); + Process* ProcessList_get(ProcessList* this, int idx); int ProcessList_size(ProcessList* this); void ProcessList_sort(ProcessList* this); -#ifdef HAVE_TASKSTATS - -#endif - -#ifdef HAVE_OPENVZ - -#endif - -#ifdef HAVE_CGROUP - -#endif - -#ifdef HAVE_VSERVER - -#endif - -#ifdef HAVE_OOM - -#endif - - -void ProcessList_scan(ProcessList* this); - ProcessField ProcessList_keyAt(ProcessList* this, int at); void ProcessList_expandTree(ProcessList* this); void ProcessList_rebuildPanel(ProcessList* this, bool flags, int following, const char* incFilter); + #endif diff --git a/RichString.c b/RichString.c index fb2f2578..51914b08 100644 --- a/RichString.c +++ b/RichString.c @@ -174,4 +174,4 @@ void RichString_appendn(RichString* this, int attrs, const char* data, int len) void RichString_write(RichString* this, int attrs, const char* data) { RichString_writeFrom(this, attrs, data, 0, strlen(data)); -} \ No newline at end of file +} diff --git a/configure.ac b/configure.ac index 63d34842..45279181 100644 --- a/configure.ac +++ b/configure.ac @@ -22,6 +22,19 @@ AC_DISABLE_SHARED AC_ENABLE_STATIC AC_PROG_LIBTOOL +# Checks for platform. +# ---------------------------------------------------------------------- +case "$target" in +*linux*) + my_htop_platform=linux + ;; +*) + my_htop_platform=unsupported + ;; +esac +AM_CONDITIONAL([HTOP_LINUX], [test "$my_htop_platform" = linux]) +AM_CONDITIONAL([HTOP_UNSUPPORTED], [test "$my_htop_platform" = unsupported]) + # Checks for libraries. # ---------------------------------------------------------------------- AC_CHECK_LIB([m], [ceil], [], [missing_libraries="$missing_libraries libm"]) @@ -60,17 +73,25 @@ CFLAGS="$save_cflags" # Checks for features and flags. # ---------------------------------------------------------------------- PROCDIR=/proc + +AC_ARG_ENABLE(proc, [AC_HELP_STRING([--enable-proc], [use Linux-compatible proc filesystem])], enable_proc="yes", enable_proc="no") +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).], - if test -n "$withval"; then - AC_DEFINE_UNQUOTED(PROCDIR, "$withval", [Path of proc filesystem]) - PROCDIR="$withval" - fi, - AC_DEFINE(PROCDIR, "/proc", [Path of proc filesystem])) +if test -n "$withval"; then + AC_DEFINE_UNQUOTED(PROCDIR, "$withval", [Path of proc filesystem]) + PROCDIR="$withval" +fi, +AC_DEFINE(PROCDIR, "/proc", [Path of proc filesystem])) if test "x$cross_compiling" = xno; then -AC_CHECK_FILE($PROCDIR/stat,,AC_MSG_ERROR(Cannot find /proc/stat. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.)) -AC_CHECK_FILE($PROCDIR/meminfo,,AC_MSG_ERROR(Cannot find /proc/meminfo. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.)) + if test "x$enable_proc" = xyes; then + AC_CHECK_FILE($PROCDIR/stat,,AC_MSG_ERROR(Cannot find $PROCDIR/stat. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.)) + AC_CHECK_FILE($PROCDIR/meminfo,,AC_MSG_ERROR(Cannot find $PROCDIR/meminfo. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.)) + fi fi AC_ARG_ENABLE(openvz, [AC_HELP_STRING([--enable-openvz], [enable OpenVZ support])], ,enable_openvz="no") @@ -161,5 +182,6 @@ fi # We're done, let's go! # ---------------------------------------------------------------------- +AC_SUBST(my_htop_platform) AC_CONFIG_FILES([Makefile htop.1]) AC_OUTPUT diff --git a/htop.c b/htop.c index 01393e61..e4b4ddf2 100644 --- a/htop.c +++ b/htop.c @@ -22,8 +22,9 @@ in the source distribution for its full text. #include "TraceScreen.h" #include "OpenFilesScreen.h" #include "AffinityPanel.h" -#include "IOPriorityPanel.h" +#include "Platform.h" #include "IncSet.h" +#include "Action.h" #include "htop.h" #include @@ -43,31 +44,6 @@ in the source distribution for its full text. #define COPYRIGHT "(C) 2004-2014 Hisham Muhammad" -/*{ - -typedef enum { - HTOP_OK = 0x00, - HTOP_REFRESH = 0x01, - HTOP_RECALCULATE = 0x03, // implies HTOP_REFRESH - HTOP_SAVE_SETTINGS = 0x04, - HTOP_KEEP_FOLLOWING = 0x08, - HTOP_QUIT = 0x10, - HTOP_REDRAW_BAR = 0x20, - HTOP_UPDATE_PANELHDR = 0x41, // implies HTOP_REFRESH -} Htop_Reaction; - -typedef Htop_Reaction (*Htop_Action)(); - -typedef struct State_ { - IncSet* inc; - Settings* settings; - UsersTable* ut; -} State; - -typedef bool(*ForeachProcessFn)(Process*, size_t); - -}*/ - static void printVersionFlag() { fputs("htop " VERSION " - " COPYRIGHT "\n" "Released under the GNU GPL.\n\n", @@ -211,28 +187,9 @@ static void Setup_run(Settings* settings, const Header* header) { ScreenManager_delete(scr); } -static bool foreachProcess(Panel* panel, ForeachProcessFn fn, int arg, bool* wasAnyTagged) { - bool ok = true; - bool anyTagged = false; - for (int i = 0; i < Panel_size(panel); i++) { - Process* p = (Process*) Panel_get(panel, i); - if (p->tag) { - ok = fn(p, arg) && ok; - anyTagged = true; - } - } - if (!anyTagged) { - Process* p = (Process*) Panel_getSelected(panel); - if (p) ok = fn(p, arg) && ok; - } - if (wasAnyTagged) - *wasAnyTagged = anyTagged; - return ok; -} - static bool changePriority(Panel* panel, int delta) { bool anyTagged; - bool ok = foreachProcess(panel, (ForeachProcessFn) Process_changePriorityBy, delta, &anyTagged); + bool ok = Action_foreachProcess(panel, (Action_ForeachProcessFn) Process_changePriorityBy, delta, &anyTagged); if (!ok) beep(); return anyTagged; @@ -429,24 +386,6 @@ static Htop_Reaction actionInvertSortOrder(Panel* panel, ProcessList* pl) { return HTOP_REFRESH | HTOP_SAVE_SETTINGS; } -static Htop_Reaction actionSetIOPriority(Panel* panel, ProcessList* pl, Header* header) { - (void) panel, (void) pl; - Process* p = (Process*) Panel_getSelected(panel); - if (!p) return HTOP_OK; - IOPriority ioprio = p->ioPriority; - Panel* ioprioPanel = IOPriorityPanel_new(ioprio); - const char* fuFunctions[] = {"Set ", "Cancel ", NULL}; - void* set = pickFromVector(panel, ioprioPanel, 21, fuFunctions, header); - if (set) { - IOPriority ioprio = IOPriorityPanel_getIOPriority(ioprioPanel); - bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setIOPriority, (size_t) ioprio, NULL); - if (!ok) - beep(); - } - Panel_delete((Object*)ioprioPanel); - return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; -} - static Htop_Reaction actionSetSortColumn(Panel* panel, ProcessList* pl, Header* header) { return sortBy(panel, pl, header); } @@ -479,11 +418,14 @@ static Htop_Reaction actionSetAffinity(Panel* panel, ProcessList* pl, Header* he void* set = pickFromVector(panel, affinityPanel, 15, fuFunctions, header); if (set) { Affinity* affinity = AffinityPanel_getAffinity(affinityPanel); - bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setAffinity, (size_t) affinity, NULL); + bool ok = Action_foreachProcess(panel, (Action_ForeachProcessFn) Process_setAffinity, (size_t) affinity, NULL); if (!ok) beep(); Affinity_delete(affinity); } Panel_delete((Object*)affinityPanel); +#else + (void) panel; + (void) header; #endif return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; } @@ -498,7 +440,7 @@ static Htop_Reaction actionKill(Panel* panel, ProcessList* pl, Header* header) { Panel_setHeader(panel, "Sending..."); Panel_draw(panel, true); refresh(); - foreachProcess(panel, (ForeachProcessFn) Process_sendSignal, (size_t) sgn->key, NULL); + Action_foreachProcess(panel, (Action_ForeachProcessFn) Process_sendSignal, (size_t) sgn->key, NULL); napms(500); } } @@ -596,7 +538,7 @@ static Htop_Reaction actionTagAllChildren(Panel* panel) { return HTOP_OK; } -void setBindings(Htop_Action* keys) { +static void setBindings(Htop_Action* keys) { keys[KEY_RESIZE] = actionResize; keys['M'] = actionSortByMemory; keys['T'] = actionSortByTime; @@ -615,7 +557,6 @@ void setBindings(Htop_Action* keys) { keys['['] = actionLowerPriority; keys[KEY_F(8)] = actionLowerPriority; keys['I'] = actionInvertSortOrder; - keys['i'] = actionSetIOPriority; keys[KEY_F(6)] = actionExpandCollapseOrSortColumn; keys[KEY_F(18)] = actionExpandCollapseOrSortColumn; keys['<'] = actionSetSortColumn; @@ -761,17 +702,7 @@ int main(int argc, char** argv) { fprintf(stderr, "Error: could not read procfs (compiled to look in %s).\n", PROCDIR); exit(1); } - - bool quit = false; - int sortTimeout = 0; - int resetSortTimeout = 5; - bool doRefresh = true; - bool forceRecalculate = false; - Settings* settings; - ProcessList* pl = NULL; - UsersTable* ut = UsersTable_new(); - #ifdef HAVE_LIBNCURSESW char *locale = setlocale(LC_ALL, NULL); if (locale == NULL || locale[0] == '\0') @@ -786,13 +717,14 @@ int main(int argc, char** argv) { CRT_utf8 = false; #endif - pl = ProcessList_new(ut, pidWhiteList); + UsersTable* ut = UsersTable_new(); + ProcessList* pl = ProcessList_new(ut, pidWhiteList); pl->userOnly = userOnly; pl->userId = userId; Process_getMaxPid(); Header* header = Header_new(pl); - settings = Settings_new(pl, header, pl->cpuCount); + Settings* settings = Settings_new(pl, header, pl->cpuCount); int headerHeight = Header_calculateHeight(header); // FIXME: move delay code to settings @@ -839,12 +771,19 @@ int main(int argc, char** argv) { Htop_Action keys[KEY_MAX] = { NULL }; setBindings(keys); + Platform_setBindings(keys); State state = { .inc = inc, .settings = settings, .ut = ut, }; + + bool quit = false; + int sortTimeout = 0; + int resetSortTimeout = 5; + bool doRefresh = true; + bool forceRecalculate = false; while (!quit) { gettimeofday(&tv, NULL); diff --git a/htop.h b/htop.h index a1369431..77f6e2e8 100644 --- a/htop.h +++ b/htop.h @@ -13,33 +13,8 @@ in the source distribution for its full text. #define COPYRIGHT "(C) 2004-2014 Hisham Muhammad" - -typedef enum { - HTOP_OK = 0x00, - HTOP_REFRESH = 0x01, - HTOP_RECALCULATE = 0x03, // implies HTOP_REFRESH - HTOP_SAVE_SETTINGS = 0x04, - HTOP_KEEP_FOLLOWING = 0x08, - HTOP_QUIT = 0x10, - HTOP_REDRAW_BAR = 0x20, - HTOP_UPDATE_PANELHDR = 0x41, // implies HTOP_REFRESH -} Htop_Reaction; - -typedef Htop_Reaction (*Htop_Action)(); - -typedef struct State_ { - IncSet* inc; - Settings* settings; - UsersTable* ut; -} State; - -typedef bool(*ForeachProcessFn)(Process*, size_t); - - // ---------------------------------------- -void setBindings(Htop_Action* keys); - // ---------------------------------------- int main(int argc, char** argv);