summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2010-11-22 12:40:20 +0000
committerHisham Muhammad <hisham@gobolinux.org>2010-11-22 12:40:20 +0000
commitd8e1480a27e1e26b8dfa97681bf8e7f90946d336 (patch)
treee32ebba1c4d7abba3dc8be6e0e0863e778e660ba
parent25551d44c1bc939e20fec7db81dfdb4198409b58 (diff)
Remove arbitrary limit from rich strings
Fix subtree hiding Fix reading of CPU values in hidden threads Fix hiding of zombie processes as kernel threads Remove "debug proc" code Code cleanup in processElements
-rw-r--r--CPUMeter.c2
-rw-r--r--LoadAverageMeter.c6
-rw-r--r--MemoryMeter.c3
-rw-r--r--Meter.c26
-rw-r--r--Panel.c62
-rw-r--r--Panel.h2
-rw-r--r--Process.c26
-rw-r--r--Process.h11
-rw-r--r--ProcessList.c713
-rw-r--r--ProcessList.h37
-rw-r--r--RichString.c125
-rw-r--r--RichString.h47
-rw-r--r--SwapMeter.c3
-rw-r--r--TasksMeter.c3
-rw-r--r--htop.c19
15 files changed, 513 insertions, 572 deletions
diff --git a/CPUMeter.c b/CPUMeter.c
index bed6266c..a1144ea9 100644
--- a/CPUMeter.c
+++ b/CPUMeter.c
@@ -75,7 +75,7 @@ static void CPUMeter_setValues(Meter* this, char* buffer, int size) {
static void CPUMeter_display(Object* cast, RichString* out) {
char buffer[50];
Meter* this = (Meter*)cast;
- RichString_init(out);
+ RichString_prune(out);
if (this->param > this->pl->cpuCount) {
RichString_append(out, CRT_colors[METER_TEXT], "absent");
return;
diff --git a/LoadAverageMeter.c b/LoadAverageMeter.c
index c8e38ff6..1109dab4 100644
--- a/LoadAverageMeter.c
+++ b/LoadAverageMeter.c
@@ -36,9 +36,8 @@ static void LoadAverageMeter_setValues(Meter* this, char* buffer, int size) {
static void LoadAverageMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast;
char buffer[20];
- RichString_init(out);
sprintf(buffer, "%.2f ", this->values[2]);
- RichString_append(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer);
+ RichString_write(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer);
sprintf(buffer, "%.2f ", this->values[1]);
RichString_append(out, CRT_colors[LOAD_AVERAGE_FIVE], buffer);
sprintf(buffer, "%.2f ", this->values[0]);
@@ -57,9 +56,8 @@ static void LoadMeter_setValues(Meter* this, char* buffer, int size) {
static void LoadMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast;
char buffer[20];
- RichString_init(out);
sprintf(buffer, "%.2f ", ((Meter*)this)->values[0]);
- RichString_append(out, CRT_colors[LOAD], buffer);
+ RichString_write(out, CRT_colors[LOAD], buffer);
}
MeterType LoadAverageMeter = {
diff --git a/MemoryMeter.c b/MemoryMeter.c
index 66c4fa5c..e3e18ec0 100644
--- a/MemoryMeter.c
+++ b/MemoryMeter.c
@@ -43,8 +43,7 @@ static void MemoryMeter_display(Object* cast, RichString* out) {
long int usedMem = this->values[0] / k;
long int buffersMem = this->values[1] / k;
long int cachedMem = this->values[2] / k;
- RichString_init(out);
- RichString_append(out, CRT_colors[METER_TEXT], ":");
+ RichString_write(out, CRT_colors[METER_TEXT], ":");
sprintf(buffer, format, totalMem);
RichString_append(out, CRT_colors[METER_VALUE], buffer);
sprintf(buffer, format, usedMem);
diff --git a/Meter.c b/Meter.c
index b65b0ee1..341be721 100644
--- a/Meter.c
+++ b/Meter.c
@@ -128,8 +128,6 @@ MeterType* Meter_types[] = {
NULL
};
-static RichString Meter_stringBuffer;
-
Meter* Meter_new(ProcessList* pl, int param, MeterType* type) {
Meter* this = calloc(sizeof(Meter), 1);
Object_setClass(this, METER_CLASS);
@@ -166,14 +164,13 @@ void Meter_setCaption(Meter* this, const char* caption) {
this->caption = strdup(caption);
}
-static inline void Meter_displayToStringBuffer(Meter* this, char* buffer) {
+static inline void Meter_displayBuffer(Meter* this, char* buffer, RichString* out) {
MeterType* type = this->type;
Object_Display display = ((Object*)this)->display;
if (display) {
- display((Object*)this, &Meter_stringBuffer);
+ display((Object*)this, out);
} else {
- RichString_initVal(Meter_stringBuffer);
- RichString_append(&Meter_stringBuffer, CRT_colors[type->attributes[0]], buffer);
+ RichString_write(out, CRT_colors[type->attributes[0]], buffer);
}
}
@@ -229,10 +226,12 @@ static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
int captionLen = strlen(this->caption);
w -= captionLen;
x += captionLen;
- Meter_displayToStringBuffer(this, buffer);
mvhline(y, x, ' ', CRT_colors[DEFAULT_COLOR]);
attrset(CRT_colors[RESET_COLOR]);
- RichString_printVal(Meter_stringBuffer, y, x);
+ RichString_begin(out);
+ Meter_displayBuffer(this, buffer, &out);
+ RichString_printVal(out, y, x);
+ RichString_end(out);
}
/* ---------- BarMeterMode ---------- */
@@ -378,14 +377,16 @@ static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
MeterType* type = this->type;
char buffer[METER_BUFFER_LEN];
type->setValues(this, buffer, METER_BUFFER_LEN - 1);
-
- Meter_displayToStringBuffer(this, buffer);
+
+ RichString_begin(out);
+ Meter_displayBuffer(this, buffer, &out);
attrset(CRT_colors[LED_COLOR]);
mvaddstr(y+2, x, this->caption);
int xx = x + strlen(this->caption);
- for (int i = 0; i < Meter_stringBuffer.len; i++) {
- char c = RichString_getCharVal(Meter_stringBuffer, i);
+ int len = RichString_sizeVal(out);
+ for (int i = 0; i < len; i++) {
+ char c = RichString_getCharVal(out, i);
if (c >= '0' && c <= '9') {
LEDMeterMode_drawDigit(xx, y, c-48);
xx += 4;
@@ -395,6 +396,7 @@ static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
}
}
attrset(CRT_colors[RESET_COLOR]);
+ RichString_end(out);
}
#endif
diff --git a/Panel.c b/Panel.c
index f4f286e5..c90a1674 100644
--- a/Panel.c
+++ b/Panel.c
@@ -98,7 +98,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner)
this->selected = 0;
this->oldSelected = 0;
this->needsRedraw = true;
- RichString_prune(&(this->header));
+ RichString_beginAllocated(this->header);
if (String_eq(CRT_termType, "linux"))
this->scrollHAmount = 20;
else
@@ -108,17 +108,19 @@ void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner)
void Panel_done(Panel* this) {
assert (this != NULL);
Vector_delete(this->items);
+ RichString_end(this->header);
}
-inline void Panel_setRichHeader(Panel* this, RichString header) {
+RichString* Panel_getHeader(Panel* this) {
assert (this != NULL);
- this->header = header;
this->needsRedraw = true;
+ return &(this->header);
}
inline void Panel_setHeader(Panel* this, const char* header) {
- Panel_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
+ RichString_write(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
+ this->needsRedraw = true;
}
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
@@ -136,7 +138,7 @@ void Panel_move(Panel* this, int x, int y) {
void Panel_resize(Panel* this, int w, int h) {
assert (this != NULL);
- if (this->header.len > 0)
+ if (RichString_sizeVal(this->header) > 0)
h--;
this->w = w;
this->h = h;
@@ -262,15 +264,16 @@ void Panel_draw(Panel* this, bool focus) {
assert(first >= 0);
assert(last <= itemCount);
- if (this->header.len > 0) {
+ int headerLen = RichString_sizeVal(this->header);
+ if (headerLen > 0) {
int attr = focus
? CRT_colors[PANEL_HEADER_FOCUS]
: CRT_colors[PANEL_HEADER_UNFOCUS];
attrset(attr);
mvhline(y, x, ' ', this->w);
- if (scrollH < this->header.len) {
+ if (scrollH < headerLen) {
RichString_printoffnVal(this->header, y, x, scrollH,
- MIN(this->header.len - scrollH, this->w));
+ MIN(headerLen - scrollH, this->w));
}
attrset(CRT_colors[RESET_COLOR]);
y++;
@@ -284,22 +287,23 @@ void Panel_draw(Panel* this, bool focus) {
for(int i = first, j = 0; j < this->h && i < last; i++, j++) {
Object* itemObj = Vector_get(this->items, i);
- RichString itemRef;
- RichString_initVal(itemRef);
- itemObj->display(itemObj, &itemRef);
- int amt = MIN(itemRef.len - scrollH, this->w);
+ RichString_begin(item);
+ itemObj->display(itemObj, &item);
+ int itemLen = RichString_sizeVal(item);
+ int amt = MIN(itemLen - scrollH, this->w);
if (i == this->selected) {
attrset(highlight);
- RichString_setAttr(&itemRef, highlight);
+ RichString_setAttr(&item, highlight);
mvhline(y + j, x+0, ' ', this->w);
if (amt > 0)
- RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
+ RichString_printoffnVal(item, y+j, x+0, scrollH, amt);
attrset(CRT_colors[RESET_COLOR]);
} else {
mvhline(y+j, x+0, ' ', this->w);
if (amt > 0)
- RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
+ RichString_printoffnVal(item, y+j, x+0, scrollH, amt);
}
+ RichString_end(item);
}
for (int i = y + (last - first); i < y + this->h; i++)
mvhline(i, x+0, ' ', this->w);
@@ -307,24 +311,26 @@ void Panel_draw(Panel* this, bool focus) {
} else {
Object* oldObj = Vector_get(this->items, this->oldSelected);
- RichString oldRef;
- RichString_initVal(oldRef);
- oldObj->display(oldObj, &oldRef);
+ RichString_begin(old);
+ oldObj->display(oldObj, &old);
+ int oldLen = RichString_sizeVal(old);
Object* newObj = Vector_get(this->items, this->selected);
- RichString newRef;
- RichString_initVal(newRef);
- newObj->display(newObj, &newRef);
+ RichString_begin(new);
+ newObj->display(newObj, &new);
+ int newLen = RichString_sizeVal(new);
mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
- if (scrollH < oldRef.len)
- RichString_printoffnVal(oldRef, y+this->oldSelected - this->scrollV, x,
- this->scrollH, MIN(oldRef.len - scrollH, this->w));
+ if (scrollH < oldLen)
+ RichString_printoffnVal(old, y+this->oldSelected - this->scrollV, x,
+ this->scrollH, MIN(oldLen - scrollH, this->w));
attrset(highlight);
mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
- RichString_setAttr(&newRef, highlight);
- if (scrollH < newRef.len)
- RichString_printoffnVal(newRef, y+this->selected - this->scrollV, x,
- this->scrollH, MIN(newRef.len - scrollH, this->w));
+ RichString_setAttr(&new, highlight);
+ if (scrollH < newLen)
+ RichString_printoffnVal(new, y+this->selected - this->scrollV, x,
+ this->scrollH, MIN(newLen - scrollH, this->w));
attrset(CRT_colors[RESET_COLOR]);
+ RichString_end(new);
+ RichString_end(old);
}
this->oldSelected = this->selected;
move(0, 0);
diff --git a/Panel.h b/Panel.h
index 66723251..c6f74336 100644
--- a/Panel.h
+++ b/Panel.h
@@ -78,7 +78,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner)
void Panel_done(Panel* this);
-extern void Panel_setRichHeader(Panel* this, RichString header);
+RichString* Panel_getHeader(Panel* this);
extern void Panel_setHeader(Panel* this, const char* header);
diff --git a/Process.c b/Process.c
index 30e243b1..0f2f1f58 100644
--- a/Process.c
+++ b/Process.c
@@ -40,12 +40,18 @@ in the source distribution for its full text.
#endif
#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
-#define PROCESS_COMM_LEN 300
-
/*{
+#ifndef Process_isKernelThread
+#define Process_isKernelThread(_process) (_process->pgrp == 0)
+#endif
+
+#ifndef Process_isUserlandThread
+#define Process_isUserlandThread(_process) (_process->pid != _process->tgid)
+#endif
+
#ifndef Process_isThread
-#define Process_isThread(_process) (_process->pid != _process->tgid || _process->m_size == 0)
+#define Process_isThread(_process) (Process_isUserlandThread(_process) || Process_isKernelThread(_process))
#endif
typedef enum ProcessField_ {
@@ -83,6 +89,7 @@ typedef struct Process_ {
char state;
bool tag;
bool showChildren;
+ bool show;
pid_t ppid;
unsigned int pgrp;
unsigned int session;
@@ -225,7 +232,7 @@ static int Process_getuid = -1;
#define ONE_M (ONE_K * ONE_K)
#define ONE_G (ONE_M * ONE_K)
-static void Process_printLargeNumber(Process* this, RichString *str, unsigned long number) {
+static void Process_printLargeNumber(Process* this, RichString* str, unsigned long number) {
char buffer[11];
int len;
if(number >= (10 * ONE_M)) {
@@ -279,10 +286,10 @@ static void Process_printTime(RichString* str, unsigned long t) {
}
static inline void Process_writeCommand(Process* this, int attr, int baseattr, RichString* str) {
- int start = str->len;
+ int start = RichString_size(str);
RichString_append(str, attr, this->comm);
if (this->pl->highlightBaseName) {
- int finish = str->len - 1;
+ int finish = RichString_size(str) - 1;
int space = RichString_findChar(str, ' ', start);
if (space != -1)
finish = space - 1;
@@ -312,10 +319,10 @@ static inline void Process_outputRate(Process* this, RichString* str, int attr,
}
static void Process_writeField(Process* this, RichString* str, ProcessField field) {
- char buffer[PROCESS_COMM_LEN];
+ char buffer[128]; buffer[127] = '\0';
int attr = CRT_colors[DEFAULT_COLOR];
int baseattr = CRT_colors[PROCESS_BASENAME];
- int n = PROCESS_COMM_LEN;
+ int n = sizeof(buffer) - 1;
switch (field) {
case PID: snprintf(buffer, n, "%5u ", this->pid); break;
@@ -457,7 +464,7 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel
static void Process_display(Object* cast, RichString* out) {
Process* this = (Process*) cast;
ProcessField* fields = this->pl->fields;
- RichString_init(out);
+ RichString_prune(out);
for (int i = 0; fields[i]; i++)
Process_writeField(this, out, fields[i]);
if (this->pl->shadowOtherUsers && (int)this->st_uid != Process_getuid)
@@ -486,6 +493,7 @@ Process* Process_new(struct ProcessList_ *pl) {
this->pl = pl;
this->tag = false;
this->showChildren = true;
+ this->show = true;
this->updated = false;
this->utime = 0;
this->stime = 0;
diff --git a/Process.h b/Process.h
index f7d1adf3..88e825e9 100644
--- a/Process.h
+++ b/Process.h
@@ -43,11 +43,17 @@ in the source distribution for its full text.
#endif
#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
-#define PROCESS_COMM_LEN 300
+#ifndef Process_isKernelThread
+#define Process_isKernelThread(_process) (_process->pgrp == 0)
+#endif
+
+#ifndef Process_isUserlandThread
+#define Process_isUserlandThread(_process) (_process->pid != _process->tgid)
+#endif
#ifndef Process_isThread
-#define Process_isThread(_process) (_process->pid != _process->tgid || _process->m_size == 0)
+#define Process_isThread(_process) (Process_isUserlandThread(_process) || Process_isKernelThread(_process))
#endif
typedef enum ProcessField_ {
@@ -85,6 +91,7 @@ typedef struct Process_ {
char state;
bool tag;
bool showChildren;
+ bool show;
pid_t ppid;
unsigned int pgrp;
unsigned int session;
diff --git a/ProcessList.c b/ProcessList.c
index cd265361..c37919ba 100644
--- a/ProcessList.c
+++ b/ProcessList.c
@@ -58,10 +58,6 @@ in the source distribution for its full text.
/*{
-#ifdef DEBUG_PROC
-typedef int(*vxscanf)(void*, const char*, va_list);
-#endif
-
typedef struct CPUData_ {
unsigned long long int totalTime;
unsigned long long int userTime;
@@ -126,77 +122,12 @@ typedef struct ProcessList_ {
bool highlightMegabytes;
bool highlightThreads;
bool detailedCPUTime;
- #ifdef DEBUG_PROC
- FILE* traceFile;
- #endif
} ProcessList;
}*/
static ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 };
-#ifdef DEBUG_PROC
-
-#define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ )
-#define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
-
-static FILE* ProcessList_fopen(ProcessList* this, const char* path, const char* mode) {
- fprintf(this->traceFile, "[%s]\n", path);
- return fopen(path, mode);
-}
-
-static inline int ProcessList_xread(ProcessList* this, vxscanf fn, void* buffer, char* format, ...) {
- va_list ap;
- va_start(ap, format);
- int num = fn(buffer, format, ap);
- va_end(format);
- va_start(ap, format);
- while (*format) {
- char ch = *format;
- char* c; int* d;
- long int* ld; unsigned long int* lu;
- long long int* lld; unsigned long long int* llu;
- char** s;
- if (ch != '%') {
- fprintf(this->traceFile, "%c", ch);
- format++;
- continue;
- }
- format++;
- switch(*format) {
- case 'c': c = va_arg(ap, char*); fprintf(this->traceFile, "%c", *c); break;
- case 'd': d = va_arg(ap, int*); fprintf(this->traceFile, "%d", *d); break;
- case 's': s = va_arg(ap, char**); fprintf(this->traceFile, "%s", *s); break;
- case 'l':
- format++;
- switch (*format) {
- case 'd': ld = va_arg(ap, long int*); fprintf(this->traceFile, "%ld", *ld); break;
- case 'u': lu = va_arg(ap, unsigned long int*); fprintf(this->traceFile, "%lu", *lu); break;
- case 'l':
- format++;
- switch (*format) {
- case 'd': lld = va_arg(ap, long long int*); fprintf(this->traceFile, "%lld", *lld); break;
- case 'u': llu = va_arg(ap, unsigned long long int*); fprintf(this->traceFile, "%llu", *llu); break;
- }
- }
- }
- format++;
- }
- fprintf(this->traceFile, "\n");
- va_end(format);
- return num;
-}
-
-#else
-
-#ifndef ProcessList_read
-#define ProcessList_fopen(this, path, mode) fopen(path, mode)
-#define ProcessList_read(this, buffer, format, ...) sscanf(buffer, format, ## __VA_ARGS__ )
-#define ProcessList_fread(this, file, format, ...) fscanf(file, format, ## __VA_ARGS__ )
-#endif
-
-#endif
-
ProcessList* ProcessList_new(UsersTable* usersTable) {
ProcessList* this;
this = malloc(sizeof(ProcessList));
@@ -208,19 +139,15 @@ ProcessList* ProcessList_new(UsersTable* usersTable) {
/* tree-view auxiliary buffers */
this->processes2 = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE, Process_compare);
- #ifdef DEBUG_PROC
- this->traceFile = fopen("/tmp/htop-proc-trace", "w");
- #endif
-
- FILE* status = fopen(PROCSTATFILE, "r");
- assert(status != NULL);
+ FILE* file = fopen(PROCSTATFILE, "r");
+ assert(file != NULL);
char buffer[256];
int cpus = -1;
do {
cpus++;
- fgets(buffer, 255, status);
+ fgets(buffer, 255, file);
} while (String_startsWith(buffer, "cpu"));
- fclose(status);
+ fclose(file);
this->cpuCount = cpus - 1;
this->cpus = calloc(sizeof(CPUData), cpus);
@@ -240,8 +167,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable) {
this->direction = 1;
this->hideThreads = false;
this->shadowOtherUsers = false;
- this->showThreadNames = true;
- this->showingThreadNames = true;
+ this->showThreadNames = false;
+ this->showingThreadNames = false;
this->hideKernelThreads = false;
this->hideUserlandThreads = false;
this->treeView = false;
@@ -256,13 +183,7 @@ void ProcessList_delete(ProcessList* this) {
Hashtable_delete(this->processTable);
Vector_delete(this->processes);
Vector_delete(this->processes2);
-
free(this->cpus);
-
- #ifdef DEBUG_PROC
- fclose(this->traceFile);
- #endif
-
free(this->fields);
free(this);
}
@@ -274,18 +195,16 @@ void ProcessList_invertSortOrder(ProcessList* this) {
this->direction = 1;
}
-RichString ProcessList_printHeader(ProcessList* this) {
- RichString out;
- RichString_initVal(out);
+void ProcessList_printHeader(ProcessList* this, RichString* header) {
+ RichString_prune(header);
ProcessField* fields = this->fields;
for (int i = 0; fields[i]; i++) {
const char* field = Process_fieldTitles[fields[i]];
if (this->sortKey == fields[i])
- RichString_append(&out, CRT_colors[PANEL_HIGHLIGHT_FOCUS], field);
+ RichString_append(header, CRT_colors[PANEL_HIGHLIGHT_FOCUS], field);
else
- RichString_append(&out, CRT_colors[PANEL_HEADER_FOCUS], field);
+ RichString_append(header, CRT_colors[PANEL_HEADER_FOCUS], field);
}
- return out;
}
static void ProcessList_add(ProcessList* this, Process* p) {
@@ -334,21 +253,18 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i
int size = Vector_size(children);
for (int i = 0; i < size; i++) {
Process* process = (Process*) (Vector_get(children, i));
- if (show) {
- int s = this->processes2->items;
- if (direction == 1)
- Vector_add(this->processes2, process);
- else
- Vector_insert(this->processes2, 0, process);
- assert(this->processes2->items == s+1); (void)s;
- int nextIndent = indent;
- if (i < size - 1)
- nextIndent = indent | (1 << level);
- ProcessList_buildTree(this, process->pid, level+1, nextIndent, direction, process->showChildren);
- process->indent = indent | (1 << level);
- } else {
- ProcessList_remove(this, process);
- }
+ if (!show)
+ process->show = false;
+ show = show ? process->showChildren : false;
+ int s = this->processes2->items;
+ if (direction == 1)
+ Vector_add(this->processes2, process);
+ else
+ Vector_insert(this->processes2, 0, process);
+ assert(this->processes2->items == s+1); (void)s;
+ int nextIndent = indent | (1 << level);
+ ProcessList_buildTree(this, process->pid, level+1, (i < size - 1) ? nextIndent : indent, direction, show);
+ process->indent = nextIndent;
}
Vector_delete(children);
}
@@ -393,364 +309,351 @@ void ProcessList_sort(ProcessList* this) {
}
}
-static int ProcessList_readStatFile(Process *proc, FILE *f, char *command) {
+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);
+ FILE* file = fopen(filename, "r");
+ if (!file)
+ return false;
+
static char buf[MAX_READ];
- unsigned long int zero;
- int size = fread(buf, 1, MAX_READ, f);
- if(!size) return 0;
+ int size = fread(buf, 1, MAX_READ, file);
+ if (!size) { fclose(file); return false; }
- assert(proc->pid == atoi(buf));
+ assert(process->pid == atoi(buf));
char *location = strchr(buf, ' ');
- if(!location) return 0;
+ if (!location) { fclose(file); return false; }
location += 2;
char *end = strrchr(location, ')');
- if(!end) return 0;
+ if (!end) { fclose(file); return false; }
int commsize = end - location;
memcpy(command, location, commsize);
command[commsize] = '\0';
location = end + 2;
-
- #ifdef DEBUG_PROC
- int num = ProcessList_read(this, location,
- "%c %u %u %u %u %d %lu %lu %lu %lu "
- "%lu %lu %lu %ld %ld %ld %ld %ld %ld "
- "%lu %lu %ld %lu %lu %lu %lu %lu "
- "%lu %lu %lu %lu %lu %lu %lu %lu "
- "%d %d",
- &proc->state, &proc->ppid, &proc->pgrp, &proc->session, &proc->tty_nr,
- &proc->tpgid, &proc->flags,
- &proc->minflt, &proc->cminflt, &proc->majflt, &proc->cmajflt,
- &proc->utime, &proc->stime, &proc->cutime, &proc->cstime,
- &proc->priority, &proc->nice, &proc->nlwp, &proc->itrealvalue,
- &zero, &proc->vsize, &proc->rss, &proc->rlim,
- &proc->startcode, &proc->endcode, &proc->startstack, &proc->kstkesp,
- &proc->kstkeip, &proc->signal, &proc->blocked, &proc->sigignore,
- &proc->sigcatch, &proc->wchan, &proc->nswap, &proc->cnswap,
- &proc->exit_signal, &proc->processor);
- #else
- long int uzero;
- int num = ProcessList_read(this, location,
- "%c %d %u %u %u %d %lu %lu %lu %lu "
- "%lu %lu %lu %ld %ld %ld %ld %ld %ld "
- "%lu %lu %ld %lu %lu %lu %lu %lu "
- "%lu %lu %lu %lu %lu %lu %lu %lu "
+
+ int num = sscanf(location,
+ "%c %d %u %u %u "
+ "%d %lu "
+ "%*u %*u %*u %*u "
+ "%lu %lu %ld %ld "
+ "%ld %ld %ld "
+ "%*d %*u %*u %*d %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u "
"%d %d",
- &proc->state, &proc->ppid, &proc->pgrp, &proc->session, &proc->tty_nr,
- &proc->tpgid, &proc->flags,
- &zero, &zero, &zero, &zero,
- &proc->utime, &proc->stime, &proc->cutime, &proc->cstime,
- &proc->priority, &proc->nice, &proc->nlwp, &uzero,
- &zero, &zero, &uzero, &zero,
- &zero, &zero, &zero, &zero,
- &zero, &zero, &zero, &zero,
- &zero, &zero, &zero, &zero,
- &proc->exit_signal, &proc->processor);
- #endif
-
- // This assert is always valid on 2.4, but reportedly not always valid on 2.6.
- // TODO: Check if the semantics of this field has changed.
- // assert(zero == 0);
-
- if(num != 37) return 0;
- return 1;
+ &process->state, &process->ppid, &process->pgrp, &process->session, &process->tty_nr,
+ &process->tpgid, &process->flags,
+ &process->utime, &process->stime, &process->cutime, &process->cstime,
+ &process->priority, &process->nice, &process->nlwp,
+ &process->exit_signal, &process->processor);
+ fclose(file);
+ return (num == 16);
}
-static bool ProcessList_readStatusFile(Process* proc, const char* dirname, char* name) {
- char statusfilename[MAX_NAME+1];
- statusfilename[MAX_NAME] = '\0';
+static bool ProcessList_statProcessDir(Process* process, const char* dirname, char* name) {
+ char filename[MAX_NAME+1];
+ filename[MAX_NAME] = '\0';
- snprintf(statusfilename, MAX_NAME, "%s/%s", dirname, name);
+ snprintf(filename, MAX_NAME, "%s/%s", dirname, name);
struct stat sstat;
- int statok = stat(statusfilename, &sstat);
+ int statok = stat(filename, &sstat);
if (statok == -1)
return false;
- proc->st_uid = sstat.st_uid;
+ process->st_uid = sstat.st_uid;
struct tm date;
time_t ctime = sstat.st_ctime;
- proc->starttime_ctime = ctime;
+ process->starttime_ctime = ctime;
(void) localtime_r((time_t*) &ctime, &date);
- strftime(proc->starttime_show, 7, ((ctime > time(NULL) - 86400) ? "%R " : "%b%d "), &date);
+ strftime(process->starttime_show, 7, ((ctime > time(NULL) - 86400) ? "%R " : "%b%d "), &date);
return true;
}
#ifdef HAVE_TASKSTATS
-static void ProcessList_readIoFile(Process* proc, const char* dirname, char* name) {
- char iofilename[MAX_NAME+1];
- iofilename[MAX_NAME] = '\0';
+static void ProcessList_readIoFile(Process* process, const char* dirname, char* name) {
+ char filename[MAX_NAME+1];
+ filename[MAX_NAME] = '\0';
- snprintf(iofilename, MAX_NAME, "%s/%s/io", dirname, name);
- FILE* io = ProcessList_fopen(this, iofilename, "r");
- if (io) {
- char buffer[256];
- buffer[255] = '\0';
- struct timeval tv;
- gettimeofday(&tv,NULL);
- unsigned long long now = tv.tv_sec*1000+tv.tv_usec/1000;
- unsigned long long last_read = proc->io_read_bytes;
- unsigned long long last_write = proc->io_write_bytes;
- while (fgets(buffer, 255, io)) {
- if (ProcessList_read(this, buffer, "rchar: %llu", &proc->io_rchar)) continue;
- if (ProcessList_read(this, buffer, "wchar: %llu", &proc->io_wchar)) continue;
- if (ProcessList_read(this, buffer, "syscr: %llu", &proc->io_syscr)) continue;
- if (ProcessList_read(this, buffer, "syscw: %llu", &proc->io_syscw)) continue;
- if (ProcessList_read(this, buffer, "read_bytes: %llu", &proc->io_read_bytes)) {
- proc->io_rate_read_bps =
- ((double)(proc->io_read_bytes - last_read))/(((double)(now - proc->io_rate_read_time))/1000);
- proc->io_rate_read_time = now;
- continue;
+ snprintf(filename, MAX_NAME, "%s/%s/io", dirname, name);
+ FILE* file = fopen(filename, "r");
+ if (!file)
+ return;
+
+ char buffer[256];
+ buffer[255] = '\0';
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ unsigned long long now = tv.tv_sec*1000+tv.tv_usec/1000;
+ unsigned long long last_read = process->io_read_bytes;
+ unsigned long long last_write = process->io_write_bytes;
+ while (fgets(buffer, 255, file)) {
+ if (sscanf(buffer, "rchar: %llu", &process->io_rchar)) continue;
+ if (sscanf(buffer, "wchar: %llu", &process->io_wchar)) continue;
+ if (sscanf(buffer, "syscr: %llu", &process->io_syscr)) continue;
+ if (sscanf(buffer, "syscw: %llu", &process->io_syscw)) continue;
+ if (sscanf(buffer, "read_bytes: %llu", &process->io_read_bytes)) {
+ 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;
+ continue;
+ }
+ if (sscanf(buffer, "write_bytes: %llu", &process->io_write_bytes)) {
+ 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;
+ continue;
+ }
+ sscanf(buffer, "cancelled_write_bytes: %llu", &process->io_cancelled_write_bytes);
+ }
+ fclose(file);
+}
+
+#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);
+ FILE* file = fopen(filename, "r");
+ if (!file)
+ return false;
+
+ int num = fscanf(file, "%d %d %d %d %d %d %d",
+ &process->m_size, &process->m_resident, &process->m_share,
+ &process->m_trs, &process->m_lrs, &process->m_drs,
+ &process->m_dt);
+ fclose(file);
+ return (num == 7);
+}
+
+#ifdef HAVE_OPENVZ
+
+static void ProcessList_readOpenVZData(Process* process, const char* dirname, const char* name) {
+ if (access("/proc/vz", R_OK) != 0) {
+ process->vpid = process->pid;
+ process->ctid = 0;
+ 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,
+ "%*u %*s %*c %*u %*u %*u %*u %*u %*u %*u "
+ "%*u %*u %*u %*u %*u %*u %*u %*u "
+ "%*u %*u %*u %*u %*u %*u %*u %*u "
+ "%*u %*u %*u %*u %*u %*u %*u %*u "
+ "%*u %*u %*u %*u %*u %*u %*u %*u "
+ "%*u %*u %*u %*u %*u %*u %*u "
+ "%*u %*u %u %u",
+ &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);
+ char** fields = String_split(trimmed, ':');
+ free(trimmed);
+
+ process->cgroup = strndup(fields[2] + 1, 10);
+ 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%d", &vxid);
+ if (ok >= 1) {
+ process->vxid = vxid;
}
- if (ProcessList_read(this, buffer, "write_bytes: %llu", &proc->io_write_bytes)) {
- proc->io_rate_write_bps =
- ((double)(proc->io_write_bytes - last_write))/(((double)(now - proc->io_rate_write_time))/1000);
- proc->io_rate_write_time = now;
- continue;
+ }
+ #if defined HAVE_ANCIENT_VSERVER
+ else if (String_startsWith(buffer, "s_context:")) {
+ int vxid;
+ int ok = sscanf(buffer, "s_context:\t%d", &vxid);
+ if (ok >= 1) {
+ process->vxid = vxid;
}
- ProcessList_read(this, buffer, "cancelled_write_bytes: %llu", &proc->io_cancelled_write_bytes);
}
- fclose(io);
+ #endif
}
+ fclose(file);
}
#endif
-static bool ProcessList_processEntries(ProcessList* this, const char* dirname, Process* parent, pid_t parentPid, float period) {
+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);
+ FILE* file = fopen(filename, "r");
+ if (!file)
+ return false;
+
+ char command[4096+1]; // max cmdline length on Linux
+ int amtRead = fread(command, 1, sizeof(command) - 1, file);
+ if (amtRead > 0) {
+ for (int i = 0; i < amtRead; i++)
+ if (command[i] == '\0' || command[i] == '\n') {
+ command[i] = ' ';
+ }
+ }
+ command[amtRead] = '\0';
+ fclose(file);
+ free(process->comm);
+ process->comm = String_copy(command);
+ return true;
+}
+
+
+static bool ProcessList_processEntries(ProcessList* this, const char* dirname, Process* parent, float period) {
DIR* dir;
struct dirent* entry;
dir = opendir(dirname);
if (!dir) return false;
int cpus = this->cpuCount;
- bool showUserlandThreads = !this->hideUserlandThreads;
+ bool hideKernelThreads = this->hideKernelThreads;
+ bool hideUserlandThreads = this->hideUserlandThreads;
while ((entry = readdir(dir)) != NULL) {
char* name = entry->d_name;
- int pid;
// filename is a number: process directory
- pid = atoi(name);
-
- if (pid == parentPid)
+ int pid = atoi(name);
+
+ if (parent && pid == parent->pid)
continue;
+ bool isThread = parent;
// The RedHat kernel hides threads with a dot.
// I believe this is non-standard.
- bool isThread = false;
if ((!this->hideThreads) && pid == 0 && name[0] == '.') {
char* tname = name + 1;
pid = atoi(tname);
- if (pid > 0)
- isThread = true;
+ isThread = true;
}
+ if (pid <= 0)
+ continue;
- if (pid > 0) {
-
- FILE* status;
- char statusfilename[MAX_NAME+1];
- char command[PROCESS_COMM_LEN + 1];
-
- 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 {
- if (parent && parent->pid == pid) {
- process = parent;
- } else {
- process = Process_new(this);
- assert(process->comm == NULL);
- process->pid = pid;
- }
- }
+ 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;
+ }
- if (showUserlandThreads && (!parent || pid != parent->pid)) {
- char subdirname[MAX_NAME+1];
- snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name);
-
- ProcessList_processEntries(this, subdirname, process, pid, period);
- }
+ char subdirname[MAX_NAME+1];
+ snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name);
+ ProcessList_processEntries(this, subdirname, process, period);
- #ifdef HAVE_TASKSTATS
- ProcessList_readIoFile(process, dirname, name);
- #endif
+ #ifdef HAVE_TASKSTATS
+ ProcessList_readIoFile(process, dirname, name);
+ #endif
- process->updated = true;
+ if (! ProcessList_readStatmFile(process, dirname, name))
+ goto errorReadingProcess;
- if (!existingProcess)
- if (! ProcessList_readStatusFile(process, dirname, name))
- goto errorReadingProcess;
+ isThread = Process_isThread(process);
+ process->show = ! ((hideKernelThreads && Process_isKernelThread(process)) || (hideUserlandThreads && Process_isUserlandThread(process)));
- snprintf(statusfilename, MAX_NAME, "%s/%s/statm", dirname, name);
- status = ProcessList_fopen(this, statusfilename, "r");
+ char command[MAX_NAME+1];
+ int lasttimes = (process->utime + process->stime);
+ if (! ProcessList_readStatFile(process, dirname, name, command))
+ goto errorReadingProcess;
+ int 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) / (float)(this->totalMem) * 100.0;
- if(!status) {
- goto errorReadingProcess;
- }
- int num = ProcessList_fread(this, status, "%d %d %d %d %d %d %d",
- &process->m_size, &process->m_resident, &process->m_share,
- &process->m_trs, &process->m_lrs, &process->m_drs,
- &process->m_dt);
-
- fclose(status);
- if(num != 7)
- goto errorReadingProcess;
+ if(!existingProcess) {
+ process->user = UsersTable_getRef(this->usersTable, process->st_uid);
- if (this->hideKernelThreads && process->m_size == 0)
+ if (! ProcessList_statProcessDir(process, dirname, name))
goto errorReadingProcess;
- int lasttimes = (process->utime + process->stime);
+ #ifdef HAVE_OPENVZ
+ ProcessList_readOpenVZData(process, dirname, name);
+ #endif
- snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
+ #ifdef HAVE_CGROUP
+ ProcessList_readCGroupFile(process, dirname, name);
+ #endif
- status = ProcessList_fopen(this, statusfilename, "r");
- if (status == NULL)
- goto errorReadingProcess;
-
- int success = ProcessList_readStatFile(process, status, command);
- fclose(status);
- if(!success) {
+ #ifdef HAVE_VSERVER
+ ProcessList_readVServerData(process, dirname, name);
+ #endif
+
+ if (! ProcessList_readCmdlineFile(process, dirname, name))
goto errorReadingProcess;
- }
- if(!existingProcess) {
- process->user = UsersTable_getRef(this->usersTable, process->st_uid);
-
- #ifdef HAVE_OPENVZ
- if (access("/proc/vz", R_OK) != 0) {
- process->vpid = process->pid;
- process->ctid = 0;
- } else {
- snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
- status = ProcessList_fopen(this, statusfilename, "r");
- if (status == NULL)
- goto errorReadingProcess;
- num = ProcessList_fread(this, status,
- "%*u %*s %*c %*u %*u %*u %*u %*u %*u %*u "
- "%*u %*u %*u %*u %*u %*u %*u %*u "
- "%*u %*u %*u %*u %*u %*u %*u %*u "
- "%*u %*u %*u %*u %*u %*u %*u %*u "
- "%*u %*u %*u %*u %*u %*u %*u %*u "
- "%*u %*u %*u %*u %*u %*u %*u "
- "%*u %*u %u %u",
- &process->vpid, &process->ctid);
- fclose(status);
- }
- #endif
-
- #ifdef HAVE_CGROUP
- snprintf(statusfilename, MAX_NAME, "%s/%s/cgroup", dirname, name);
- status = ProcessList_fopen(this, statusfilename, "r");
- if (status) {
- char buffer[256];
- char *ok = fgets(buffer, 255, status);
- if (ok) {
- char* trimmed = String_trim(buffer);
- char** fields = String_split(trimmed, ':');
- free(trimmed);
-
- process->cgroup = strndup(fields[2] + 1, 10);
- String_freeArray(fields);
- }
- fclose(status);
- } else {
- process->cgroup = strdup("");
- }
- #endif
-
- #ifdef HAVE_VSERVER
- snprintf(statusfilename, MAX_NAME, "%s/%s/status", dirname, name);
- status = ProcessList_fopen(this, statusfilename, "r");
- if (status == NULL)
- goto errorReadingProcess;
- else {
- char buffer[256];
- process->vxid = 0;
- while (fgets(buffer, 255, status)) {
-
- if (String_startsWith(buffer, "VxID:")) {
- int vxid;
- int ok = ProcessList_read(this, buffer, "VxID:\t%d", &vxid);
- if (ok >= 1) {
- process->vxid = vxid;
- }
- }
- #if defined HAVE_ANCIENT_VSERVER
- else if (String_startsWith(buffer, "s_context:")) {
- int vxid;
- int ok = ProcessList_read(this, buffer, "s_context:\t%d", &vxid);
- if (ok >= 1) {
- process->vxid = vxid;
- }
- }
- #endif
- }
- fclose(status);
- }
- #endif
- }
-
- if ( ((!existingProcess) && (!showUserlandThreads || pid == parentPid || !this->showThreadNames))
- || (this->showingThreadNames && !this->showThreadNames) ) {
+ ProcessList_add(this, process);
+ }
- snprintf(statusfilename, MAX_NAME, "%s/%s/cmdline", dirname, name);
- status = ProcessList_fopen(this, statusfilename, "r");
- if (!status) {
- goto errorReadingProcess;
- }
-
- int amtRead = fread(command, 1, PROCESS_COMM_LEN - 1, status);
- if (amtRead > 0) {
- for (int i = 0; i < amtRead; i++)
- if (command[i] == '\0' || command[i] == '\n')
- command[i] = ' ';
- command[amtRead] = '\0';
- }
- fclose(status);
- command[PROCESS_COMM_LEN] = '\0';
- free(process->comm);
- process->comm = String_copy(command);
- } else if (pid != parentPid && this->showThreadNames) {
+ if (isThread) {
+ if (this->showThreadNames || Process_isKernelThread(process) || process->state == 'Z') {
free(process->comm);
process->comm = String_copy(command);
+ } else if (this->showingThreadNames) {
+ if (! ProcessList_readCmdlineFile(process, dirname, name))
+ goto errorReadingProcess;
}
+ }
- int 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) /
- (float)(this->totalMem) *
- 100.0;
+ this->totalTasks++;
+ if (process->state == 'R')
+ this->runningTasks++;
+ process->updated = true;
- this->totalTasks++;
- if (process->state == 'R') {
- this->runningTasks++;
- }
+ continue;
- if (!existingProcess) {
- ProcessList_add(this, process);
- }
- continue;
-
- // Exception handler.
- errorReadingProcess: {
- if (process->comm) {
- free(process->comm);
- process->comm = NULL;
- }
- if (existingProcess)
- ProcessList_remove(this, process);
- else
- Process_delete((Object*)process);
+ // Exception handler.
+ errorReadingProcess: {
+ if (process->comm) {
+ free(process->comm);
+ process->comm = NULL;
}
+ if (existingProcess)
+ ProcessList_remove(this, process);
+ else
+ Process_delete((Object*)process);
}
}
closedir(dir);
@@ -761,36 +664,35 @@ void ProcessList_scan(ProcessList* this) {
unsigned long long int usertime, nicetime, systemtime, systemalltime, idlealltime, idletime, totaltime, virtalltime;
unsigned long long int swapFree = 0;
- FILE* status;
- status = ProcessList_fopen(this, PROCMEMINFOFILE, "r");
- assert(status != NULL);
+ FILE* file = fopen(PROCMEMINFOFILE, "r");
+ assert(file != NULL);
int cpus = this->cpuCount;
{
char buffer[128];
- while (fgets(buffer, 128, status)) {
+ while (fgets(buffer, 128, file)) {
switch (buffer[0]) {
case 'M':
if (String_startsWith(buffer, "MemTotal:"))
- ProcessList_read(this, buffer, "MemTotal: %llu kB", &this->totalMem);
+ sscanf(buffer, "MemTotal: %llu kB", &this->totalMem);
else if (String_startsWith(buffer, "MemFree:"))
- ProcessList_read(this, buffer, "MemFree: %llu kB", &this->freeMem);
+ sscanf(buffer, "MemFree: %llu kB", &this->freeMem);
else if (String_startsWith(buffer, "MemShared:"))
- ProcessList_read(this, buffer, "MemShared: %llu kB", &this->sharedMem);
+ sscanf(buffer, "MemShared: %llu kB", &this->sharedMem);
break;
case 'B':
if (String_startsWith(buffer, "Buffers:"))
- ProcessList_read(this, buffer, "Buffers: %llu kB", &this->buffersMem);
+ sscanf(buffer, "Buffers: %llu kB", &this->buffersMem);
break;
case 'C':
if (String_startsWith(buffer, "Cached:"))
- ProcessList_read(this, buffer, "Cached: %llu kB", &this->cachedMem);
+ sscanf(buffer, "Cached: %llu kB", &this->cachedMem);
break;
case 'S':
if (String_startsWith(buffer, "SwapTotal:"))
- ProcessList_read(this, buffer, "SwapTotal: %llu kB", &this->totalSwap);
+ sscanf(buffer, "SwapTotal: %llu kB", &this->totalSwap);
if (String_startsWith(buffer, "SwapFree:"))
- ProcessList_read(this, buffer, "SwapFree: %llu kB", &swapFree);
+ sscanf(buffer, "SwapFree: %llu kB", &swapFree);
break;
}
}
@@ -798,11 +700,10 @@ void ProcessList_scan(ProcessList* this) {
this->usedMem = this->totalMem - this->freeMem;
this->usedSwap = this->totalSwap - swapFree;
- fclose(status);
-
- status = ProcessList_fopen(this, PROCSTATFILE, "r");
+ fclose(file);
- assert(status != NULL);
+ file = fopen(PROCSTATFILE, "r");
+ assert(file != NULL);
for (int i = 0; i <= cpus; i++) {
char buffer[256];
int cpuid;
@@ -811,11 +712,11 @@ void ProcessList_scan(ProcessList* this) {
// Dependending on your kernel version,
// 5, 7 or 8 of these fields will be set.
// The rest will remain at zero.
- fgets(buffer, 255, status);
+ fgets(buffer, 255, file);
if (i == 0)
- ProcessList_read(this, buffer, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest);
+ sscanf(buffer, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest);
else {
- ProcessList_read(this, buffer, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest);
+ sscanf(buffer, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest);
assert(cpuid == i - 1);
}
// Fields existing on kernels >= 2.6
@@ -862,7 +763,7 @@ void ProcessList_scan(ProcessList* this) {
cpuData->guestTime = guest;
cpuData->totalTime = totaltime;
}
- float period = (float)this->cpus[0].totalPeriod / cpus; fclose(status);
+ float period = (float)this->cpus[0].totalPeriod / cpus; fclose(file);
// mark all process as "dirty"
for (int i = 0; i < Vector_size(this->processes); i++) {
@@ -873,7 +774,7 @@ void ProcessList_scan(ProcessList* this) {
this->totalTasks = 0;
this->runningTasks = 0;
- ProcessList_processEntries(this, PROCDIR, NULL, 0, period);
+ ProcessList_processEntries(this, PROCDIR, NULL, period);
this->showingThreadNames = this->showThreadNames;
diff --git a/ProcessList.h b/ProcessList.h
index 48456def..2442f351 100644
--- a/ProcessList.h
+++ b/ProcessList.h
@@ -58,10 +58,6 @@ in the source distribution for its full text.
-#ifdef DEBUG_PROC
-typedef int(*vxscanf)(void*, const char*, va_list);
-#endif
-
typedef struct CPUData_ {
unsigned long long int totalTime;
unsigned long long int userTime;
@@ -126,34 +122,16 @@ typedef struct ProcessList_ {
bool highlightMegabytes;
bool highlightThreads;
bool detailedCPUTime;
- #ifdef DEBUG_PROC
- FILE* traceFile;
- #endif
} ProcessList;
-#ifdef DEBUG_PROC
-
-#define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ )
-#define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
-
-#else
-
-#ifndef ProcessList_read
-#define ProcessList_fopen(this, path, mode) fopen(path, mode)
-#define ProcessList_read(this, buffer, format, ...) sscanf(buffer, format, ## __VA_ARGS__ )
-#define ProcessList_fread(this, file, format, ...) fscanf(file, format, ## __VA_ARGS__ )
-#endif
-
-#endif
-
ProcessList* ProcessList_new(UsersTable* usersTable);
void ProcessList_delete(ProcessList* this);
void ProcessList_invertSortOrder(ProcessList* this);
-RichString ProcessList_printHeader(ProcessList* this);
+void ProcessList_printHeader(ProcessList* this, RichString* header);
Process* ProcessList_get(ProcessList* this, int idx);
@@ -165,6 +143,19 @@ void ProcessList_sort(ProcessList* this);
#endif
+#ifdef HAVE_OPENVZ
+
+#endif
+
+#ifdef HAVE_CGROUP
+
+#endif
+
+#ifdef HAVE_VSERVER
+
+#endif
+
+
void ProcessList_scan(ProcessList* this);
ProcessField ProcessList_keyAt(ProcessList* this, int at);
diff --git a/RichString.c b/RichString.c
index a62a053a..6d87cd84 100644
--- a/RichString.c
+++ b/RichString.c
@@ -22,26 +22,31 @@
/*{
-#define RichString_init(this) (this)->len = 0
-#define RichString_initVal(this) (this).len = 0
+#define RichString_size(this) ((this)->chlen)
+#define RichString_sizeVal(this) ((this).chlen)
+
+#define RichString_begin(this) RichString (this); (this).chlen = 0; (this).chptr = (this).chstr;
+#define RichString_beginAllocated(this) (this).chlen = 0; (this).chptr = (this).chstr;
+#define RichString_end(this) RichString_prune(&(this));
#ifdef HAVE_LIBNCURSESW
-#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, this.chstr)
-#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, this.chstr + off, n)
-#define RichString_getCharVal(this, i) (this.chstr[i].chars[0] & 255)
+#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr)
+#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, (this).chptr + off, n)
+#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0] & 255)
+#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)].chars[0] = ch; } while(0)
+#define CharType cchar_t
#else
-#define RichString_printVal(this, y, x) mvaddchstr(y, x, this.chstr)
-#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, this.chstr + off, n)
-#define RichString_getCharVal(this, i) (this.chstr[i])
+#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr)
+#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + off, n)
+#define RichString_getCharVal(this, i) ((this).chptr[i])
+#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = ch; } while(0)
+#define CharType chtype
#endif
typedef struct RichString_ {
- int len;
-#ifdef HAVE_LIBNCURSESW
- cchar_t chstr[RICHSTRING_MAXLEN+1];
-#else
- chtype chstr[RICHSTRING_MAXLEN+1];
-#endif
+ int chlen;
+ CharType chstr[RICHSTRING_MAXLEN+1];
+ CharType* chptr;
} RichString;
}*/
@@ -50,35 +55,57 @@ typedef struct RichString_ {
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
+#define charBytes(n) (sizeof(CharType) * (n))
+
+static inline void RichString_setLen(RichString* this, int len) {
+ if (this->chlen <= RICHSTRING_MAXLEN) {
+ if (len > RICHSTRING_MAXLEN) {
+ this->chptr = malloc(charBytes(len+1));
+ memcpy(this->chptr, this->chstr, charBytes(this->chlen+1));
+ }
+ } else {
+ if (len <= RICHSTRING_MAXLEN) {
+ memcpy(this->chstr, this->chptr, charBytes(this->chlen));
+ free(this->chptr);
+ this->chptr = this->chstr;
+ } else {
+ this->chptr = realloc(this->chptr, charBytes(len+1));
+ }
+ }
+ RichString_setChar(this, len, 0);
+ this->chlen = len;
+}
+
#ifdef HAVE_LIBNCURSESW
inline void RichString_appendn(RichString* this, int attrs, const char* data_c, int len) {
- wchar_t data[RICHSTRING_MAXLEN];
- len = mbstowcs(data, data_c, RICHSTRING_MAXLEN);
+ wchar_t data[len+1];
+ len = mbstowcs(data, data_c, len);
if (len<0)
return;
- int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
- for (int i = this->len, j = 0; i < last; i++, j++) {
- memset(&this->chstr[i], 0, sizeof(this->chstr[i]));
- this->chstr[i].chars[0] = data[j];
- this->chstr[i].attr = attrs;
+ int oldLen = this->chlen;
+ int newLen = len + oldLen;
+ RichString_setLen(this, newLen);
+ for (int i = oldLen, j = 0; i < newLen; i++, j++) {
+ memset(&this->chptr[i], 0, sizeof(this->chptr[i]));
+ this->chptr[i].chars[0] = data[j];
+ this->chptr[i].attr = attrs;
}
- this->chstr[last].chars[0] = 0;
- this->len = last;
+ this->chptr[newLen].chars[0] = 0;
}
-inline void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
- cchar_t* ch = this->chstr + start;
+inline void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
+ cchar_t* ch = this->chptr + start;
for (int i = start; i <= finish; i++) {
ch->attr = attrs;
ch++;
}
}
-int RichString_findChar(RichString *this, char c, int start) {
+int RichString_findChar(RichString* this, char c, int start) {
wchar_t wc = btowc(c);
- cchar_t* ch = this->chstr + start;
- for (int i = start; i < this->len; i++) {
+ cchar_t* ch = this->chptr + start;
+ for (int i = start; i < this->chlen; i++) {
if (ch->chars[0] == wc)
return i;
ch++;
@@ -89,25 +116,25 @@ int RichString_findChar(RichString *this, char c, int start) {
#else
inline void RichString_appendn(RichString* this, int attrs, const char* data_c, int len) {
- int last = MIN(RICHSTRING_MAXLEN - 1, len + this->len);
- for (int i = this->len, j = 0; i < last; i++, j++)
- this->chstr[i] = (isprint(data_c[j]) ? data_c[j] : '?') | attrs;
-
- this->chstr[last] = 0;
- this->len = last;
+ int oldLen = this->chlen;
+ int newLen = len + oldLen;
+ RichString_setLen(this, newLen);
+ for (int i = oldLen, j = 0; i < newLen; i++, j++)
+ this->chptr[i] = (isprint(data_c[j]) ? data_c[j] : '?') | attrs;
+ this->chptr[newLen] = 0;
}
-void RichString_setAttrn(RichString *this, int attrs, int start, int finish) {
- chtype* ch = this->chstr + start;
+void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
+ chtype* ch = this->chptr + start;
for (int i = start; i <= finish; i++) {
*ch = (*ch & 0xff) | attrs;
ch++;
}
}
-int RichString_findChar(RichString *this, char c, int start) {
- chtype* ch = this->chstr + start;
- for (int i = start; i < this->len; i++) {
+int RichString_findChar(RichString* this, char c, int start) {
+ chtype* ch = this->chptr + start;
+ for (int i = start; i < this->chlen; i++) {
if ((*ch & 0xff) == (chtype) c)
return i;
ch++;
@@ -118,11 +145,14 @@ int RichString_findChar(RichString *this, char c, int start) {
#endif
void RichString_prune(RichString* this) {
- this->len = 0;
+ if (this->chlen > RICHSTRING_MAXLEN)
+ free(this->chptr);
+ this->chptr = this->chstr;
+ this->chlen = 0;
}
-void RichString_setAttr(RichString *this, int attrs) {
- RichString_setAttrn(this, attrs, 0, this->len - 1);
+void RichString_setAttr(RichString* this, int attrs) {
+ RichString_setAttrn(this, attrs, 0, this->chlen - 1);
}
inline void RichString_append(RichString* this, int attrs, const char* data) {
@@ -130,13 +160,6 @@ inline void RichString_append(RichString* this, int attrs, const char* data) {
}
void RichString_write(RichString* this, int attrs, const char* data) {
- RichString_init(this);
- RichString_append(this, attrs, data);
-}
-
-RichString RichString_quickString(int attrs, const char* data) {
- RichString str;
- RichString_initVal(str);
- RichString_write(&str, attrs, data);
- return str;
+ RichString_setLen(this, 0);
+ RichString_appendn(this, attrs, data, strlen(data));
}
diff --git a/RichString.h b/RichString.h
index 7b2de38e..b6622a13 100644
--- a/RichString.h
+++ b/RichString.h
@@ -24,26 +24,31 @@
#define RICHSTRING_MAXLEN 300
-#define RichString_init(this) (this)->len = 0
-#define RichString_initVal(this) (this).len = 0
+#define RichString_size(this) ((this)->chlen)
+#define RichString_sizeVal(this) ((this).chlen)
+
+#define RichString_begin(this) RichString (this); (this).chlen = 0; (this).chptr = (this).chstr;
+#define RichString_beginAllocated(this) (this).chlen = 0; (this).chptr = (this).chstr;
+#define RichString_end(this) RichString_prune(&(this));
#ifdef HAVE_LIBNCURSESW
-#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, this.chstr)
-#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, this.chstr + off, n)
-#define RichString_getCharVal(this, i) (this.chstr[i].chars[0] & 255)
+#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr)
+#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, (this).chptr + off, n)
+#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0] & 255)
+#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)].chars[0] = ch; } while(0)
+#define CharType cchar_t
#else
-#define RichString_printVal(this, y, x) mvaddchstr(y, x, this.chstr)
-#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, this.chstr + off, n)
-#define RichString_getCharVal(this, i) (this.chstr[i])
+#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr)
+#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + off, n)
+#define RichString_getCharVal(this, i) ((this).chptr[i])
+#define RichString_setChar(this, at, ch) do{ (this)->chptr[(at)] = ch; } while(0)
+#define CharType chtype
#endif
typedef struct RichString_ {
- int len;
-#ifdef HAVE_LIBNCURSESW
- cchar_t chstr[RICHSTRING_MAXLEN+1];
-#else
- chtype chstr[RICHSTRING_MAXLEN+1];
-#endif
+ int chlen;
+ CharType chstr[RICHSTRING_MAXLEN+1];
+ CharType* chptr;
} RichString;
@@ -51,32 +56,32 @@ typedef struct RichString_ {
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
+#define charBytes(n) (sizeof(CharType) * (n))
+
#ifdef HAVE_LIBNCURSESW
extern void RichString_appendn(RichString* this, int attrs, const char* data_c, int len);
-extern void RichString_setAttrn(RichString *this, int attrs, int start, int finish);
+extern void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
-int RichString_findChar(RichString *this, char c, int start);
+int RichString_findChar(RichString* this, char c, int start);
#else
extern void RichString_appendn(RichString* this, int attrs, const char* data_c, int len);
-void RichString_setAttrn(RichString *this, int attrs, int start, int finish);
+void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
-int RichString_findChar(RichString *this, char c, int start);
+int RichString_findChar(RichString* this, char c, int start);
#endif
void RichString_prune(RichString* this);
-void RichString_setAttr(RichString *this, int attrs);
+void RichString_setAttr(RichString* this, int attrs);
extern void RichString_append(RichString* this, int attrs, const char* data);
void RichString_write(RichString* this, int attrs, const char* data);
-RichString RichString_quickString(int attrs, const char* data);
-
#endif
diff --git a/SwapMeter.c b/SwapMeter.c
index 0f42e080..ecbd129a 100644
--- a/SwapMeter.c
+++ b/SwapMeter.c
@@ -34,8 +34,7 @@ static void SwapMeter_display(Object* cast, RichString* out) {
char buffer[50];
Meter* this = (Meter*)cast;
long int swap = (long int) this->values[0];
- RichString_init(out);
- RichString_append(out, CRT_colors[METER_TEXT], ":");
+ RichString_write(out, CRT_colors[METER_TEXT], ":");
sprintf(buffer, "%ldM ", (long int) this->total / 1024);
RichString_append(out, CRT_colors[METER_VALUE], buffer);
sprintf(buffer, "%ldk", swap);
diff --git a/TasksMeter.c b/TasksMeter.c
index e82f53c7..685489ab 100644
--- a/TasksMeter.c
+++ b/TasksMeter.c
@@ -26,10 +26,9 @@ static void TasksMeter_setValues(Meter* this, char* buffer, int len) {
static void TasksMeter_display(Object* cast, RichString* out) {
Meter* this = (Meter*)cast;
- RichString_init(out);
char buffer[20];
sprintf(buffer, "%d", (int)this->total);
- RichString_append(out, CRT_colors[METER_VALUE], buffer);
+ RichString_write(out, CRT_colors[METER_VALUE], buffer);
RichString_append(out, CRT_colors[METER_TEXT], " total, ");
sprintf(buffer, "%d", (int)this->values[0]);
RichString_append(out, CRT_colors[TASKS_RUNNING], buffer);
diff --git a/htop.c b/htop.c
index 79373894..0cc5eebc 100644
--- a/htop.c
+++ b/htop.c
@@ -241,7 +241,7 @@ static inline void setSortKey(ProcessList* pl, ProcessField sortKey, Panel* pane
pl->direction = 1;
pl->treeView = false;
settings->changed = true;
- Panel_setRichHeader(panel, ProcessList_printHeader(pl));
+ ProcessList_printHeader(pl, Panel_getHeader(panel));
}
int main(int argc, char** argv) {
@@ -352,7 +352,7 @@ int main(int argc, char** argv) {
pl->treeView = false;
pl->direction = 1;
}
- Panel_setRichHeader(panel, ProcessList_printHeader(pl));
+ ProcessList_printHeader(pl, Panel_getHeader(panel));
const char* searchFunctions[] = {"Next ", "Exit ", " Search: ", NULL};
const char* searchKeys[] = {"F3", "Esc", " "};
@@ -395,7 +395,7 @@ int main(int argc, char** argv) {
ProcessList_scan(pl);
doRecalculate = false;
}
- if (refreshTimeout == 0) {
+ if (refreshTimeout == 0 || pl->treeView) {
ProcessList_sort(pl);
refreshTimeout = 1;
}
@@ -404,7 +404,7 @@ int main(int argc, char** argv) {
int idx = 0;
for (int i = 0; i < size; i++) {
Process* p = ProcessList_get(pl, i);
- if (!userOnly || (p->st_uid == userId)) {
+ if (p->show && (!userOnly || (p->st_uid == userId))) {
Panel_set(panel, idx, (Object*)p);
if ((!follow && idx == currPos) || (follow && p->pid == currPid)) {
Panel_setSelected(panel, idx);
@@ -608,7 +608,7 @@ int main(int argc, char** argv) {
{
Setup_run(settings, headerHeight);
// TODO: shouldn't need this, colors should be dynamic
- Panel_setRichHeader(panel, ProcessList_printHeader(pl));
+ ProcessList_printHeader(pl, Panel_getHeader(panel));
headerHeight = Header_calculateHeight(header);
Panel_move(panel, 0, headerHeight);
Panel_resize(panel, COLS, LINES-headerHeight-1);
@@ -680,7 +680,7 @@ int main(int argc, char** argv) {
napms(500);
}
}
- Panel_setRichHeader(panel, ProcessList_printHeader(pl));
+ ProcessList_printHeader(pl, Panel_getHeader(panel));
refreshTimeout = 0;
break;
}
@@ -715,7 +715,7 @@ int main(int argc, char** argv) {
beep();
}
((Object*)affinityPanel)->delete((Object*)affinityPanel);
- Panel_setRichHeader(panel, ProcessList_printHeader(pl));
+ ProcessList_printHeader(pl, Panel_getHeader(panel));
refreshTimeout = 0;
break;
}
@@ -747,7 +747,7 @@ int main(int argc, char** argv) {
settings->changed = true;
setSortKey(pl, field->key, panel, settings);
} else {
- Panel_setRichHeader(panel, ProcessList_printHeader(pl));
+ ProcessList_printHeader(pl, Panel_getHeader(panel));
}
((Object*)sortPanel)->delete((Object*)sortPanel);
refreshTimeout = 0;
@@ -825,6 +825,9 @@ int main(int argc, char** argv) {
((Object*)killPanel)->delete((Object*)killPanel);
UsersTable_delete(ut);
Settings_delete(settings);
+#ifdef HAVE_PLPA
+ plpa_finalize();
+#endif
debug_done();
return 0;
}

© 2014-2024 Faster IT GmbH | imprint | privacy policy