diff options
-rw-r--r-- | CPUMeter.c | 2 | ||||
-rw-r--r-- | LoadAverageMeter.c | 6 | ||||
-rw-r--r-- | MemoryMeter.c | 3 | ||||
-rw-r--r-- | Meter.c | 26 | ||||
-rw-r--r-- | Panel.c | 62 | ||||
-rw-r--r-- | Panel.h | 2 | ||||
-rw-r--r-- | Process.c | 26 | ||||
-rw-r--r-- | Process.h | 11 | ||||
-rw-r--r-- | ProcessList.c | 713 | ||||
-rw-r--r-- | ProcessList.h | 37 | ||||
-rw-r--r-- | RichString.c | 125 | ||||
-rw-r--r-- | RichString.h | 47 | ||||
-rw-r--r-- | SwapMeter.c | 3 | ||||
-rw-r--r-- | TasksMeter.c | 3 | ||||
-rw-r--r-- | htop.c | 19 |
15 files changed, 513 insertions, 572 deletions
@@ -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); @@ -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 @@ -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); @@ -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); @@ -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; @@ -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; |