diff --git a/CRT.c b/CRT.c index f0f69767..487f8b0c 100644 --- a/CRT.c +++ b/CRT.c @@ -112,6 +112,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), + [PROCESS_NEW] = ColorPair(Black,Green), + [PROCESS_TOMB] = ColorPair(Black,Red), [PROCESS_THREAD] = ColorPair(Green, Black), [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Black), [BAR_BORDER] = A_BOLD, @@ -191,6 +193,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [PROCESS_D_STATE] = A_BOLD, [PROCESS_HIGH_PRIORITY] = A_BOLD, [PROCESS_LOW_PRIORITY] = A_DIM, + [PROCESS_NEW] = A_BOLD, + [PROCESS_TOMB] = A_DIM, [PROCESS_THREAD] = A_BOLD, [PROCESS_THREAD_BASENAME] = A_REVERSE, [BAR_BORDER] = A_BOLD, @@ -270,6 +274,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, White), [PROCESS_HIGH_PRIORITY] = ColorPair(Red, White), [PROCESS_LOW_PRIORITY] = ColorPair(Green, White), + [PROCESS_NEW] = ColorPair(White,Green), + [PROCESS_TOMB] = ColorPair(White,Red), [PROCESS_THREAD] = ColorPair(Blue, White), [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, White), [BAR_BORDER] = ColorPair(Blue, White), @@ -349,6 +355,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), + [PROCESS_NEW] = ColorPair(Black,Green), + [PROCESS_TOMB] = ColorPair(Black,Red), [PROCESS_THREAD] = ColorPair(Blue, Black), [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black), [BAR_BORDER] = ColorPair(Blue, Black), @@ -428,6 +436,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Blue), [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Blue), [PROCESS_LOW_PRIORITY] = ColorPair(Green, Blue), + [PROCESS_NEW] = ColorPair(Blue,Green), + [PROCESS_TOMB] = ColorPair(Blue,Red), [PROCESS_THREAD] = ColorPair(Green, Blue), [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Blue), [BAR_BORDER] = A_BOLD | ColorPair(Yellow, Blue), @@ -509,6 +519,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), + [PROCESS_NEW] = ColorPair(Black,Green), + [PROCESS_TOMB] = ColorPair(Black,Red), [BAR_BORDER] = A_BOLD | ColorPair(Green, Black), [BAR_SHADOW] = ColorPair(Cyan, Black), [SWAP] = ColorPair(Red, Black), diff --git a/CRT.h b/CRT.h index ed9cbf42..00fa0657 100644 --- a/CRT.h +++ b/CRT.h @@ -73,6 +73,8 @@ typedef enum ColorElements_ { PROCESS_BASENAME, PROCESS_HIGH_PRIORITY, PROCESS_LOW_PRIORITY, + PROCESS_NEW, + PROCESS_TOMB, PROCESS_THREAD, PROCESS_THREAD_BASENAME, BAR_BORDER, diff --git a/DisplayOptionsPanel.c b/DisplayOptionsPanel.c index 64fd303c..e539906c 100644 --- a/DisplayOptionsPanel.c +++ b/DisplayOptionsPanel.c @@ -93,6 +93,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU percentage numerically"), &(settings->showCPUUsage))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU frequency"), &(settings->showCPUFrequency))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable the mouse"), &(settings->enableMouse))); + Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Highlight new and old processes"), &(settings->highlightChanges))); #ifdef HAVE_LIBHWLOC Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Show topology when selecting affinity by default"), &(settings->topologyAffinity))); #endif diff --git a/Panel.c b/Panel.c index 870f89cc..fd9de2b1 100644 --- a/Panel.c +++ b/Panel.c @@ -273,16 +273,18 @@ void Panel_draw(Panel* this, bool focus) { Object_display(itemObj, &item); int itemLen = RichString_sizeVal(item); int amt = MINIMUM(itemLen - scrollH, this->w); - bool selected = (i == this->selected); - if (selected) { - attrset(selectionColor); - RichString_setAttr(&item, selectionColor); + if (i == this->selected) { + item.highlightAttr = selectionColor; + } + if (item.highlightAttr) { + attrset(item.highlightAttr); + RichString_setAttr(&item, item.highlightAttr); this->selectedLen = itemLen; } mvhline(y + line, x, ' ', this->w); if (amt > 0) RichString_printoffnVal(item, y + line, x, scrollH, amt); - if (selected) + if (item.highlightAttr) attrset(CRT_colors[RESET_COLOR]); RichString_end(item); line++; diff --git a/Process.c b/Process.c index 6ca383fe..28cc0307 100644 --- a/Process.c +++ b/Process.c @@ -76,7 +76,7 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori RichString_appendn(str, processColor, buffer, len); } else if (number < 100000) { //2 digit MB, 3 digit KB - len = snprintf(buffer, 10, "%2llu", number / 1000); + len = snprintf(buffer, 10, "%2llu", number/1000); RichString_appendn(str, processMegabytesColor, buffer, len); number %= 1000; len = snprintf(buffer, 10, "%03llu ", number); @@ -89,7 +89,7 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori } else if (number < 10000 * ONE_K) { //1 digit GB, 3 digit MB number /= ONE_K; - len = snprintf(buffer, 10, "%1llu", number / 1000); + len = snprintf(buffer, 10, "%1llu", number/1000); RichString_appendn(str, processGigabytesColor, buffer, len); number %= 1000; len = snprintf(buffer, 10, "%03lluM ", number); @@ -97,7 +97,7 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori } else if (number < 100000 * ONE_K) { //2 digit GB, 1 digit MB number /= 100 * ONE_K; - len = snprintf(buffer, 10, "%2llu", number / 10); + len = snprintf(buffer, 10, "%2llu", number/10); RichString_appendn(str, processGigabytesColor, buffer, len); number %= 10; len = snprintf(buffer, 10, ".%1lluG ", number); @@ -110,14 +110,14 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori } else if (number < 10000ULL * ONE_M) { //1 digit TB, 3 digit GB number /= ONE_M; - len = snprintf(buffer, 10, "%1llu", number / 1000); + len = snprintf(buffer, 10, "%1llu", number/1000); RichString_appendn(str, largeNumberColor, buffer, len); number %= 1000; len = snprintf(buffer, 10, "%03lluG ", number); RichString_appendn(str, processGigabytesColor, buffer, len); } else { //2 digit TB and above - len = snprintf(buffer, 10, "%4.1lfT ", (double)number / ONE_G); + len = snprintf(buffer, 10, "%4.1lfT ", (double)number/ONE_G); RichString_appendn(str, largeNumberColor, buffer, len); } } @@ -144,18 +144,18 @@ void Process_colorNumber(RichString* str, unsigned long long number, bool colori } else if (number >= 100LL * ONE_DECIMAL_T) { xSnprintf(buffer, 13, "%11llu ", number / ONE_DECIMAL_M); RichString_appendn(str, largeNumberColor, buffer, 8); - RichString_appendn(str, processMegabytesColor, buffer + 8, 4); + RichString_appendn(str, processMegabytesColor, buffer+8, 4); } else if (number >= 10LL * ONE_DECIMAL_G) { xSnprintf(buffer, 13, "%11llu ", number / ONE_DECIMAL_K); RichString_appendn(str, largeNumberColor, buffer, 5); - RichString_appendn(str, processMegabytesColor, buffer + 5, 3); - RichString_appendn(str, processColor, buffer + 8, 4); + RichString_appendn(str, processMegabytesColor, buffer+5, 3); + RichString_appendn(str, processColor, buffer+8, 4); } else { xSnprintf(buffer, 13, "%11llu ", number); RichString_appendn(str, largeNumberColor, buffer, 2); - RichString_appendn(str, processMegabytesColor, buffer + 2, 3); - RichString_appendn(str, processColor, buffer + 5, 3); - RichString_appendn(str, processShadowColor, buffer + 8, 4); + RichString_appendn(str, processMegabytesColor, buffer+2, 3); + RichString_appendn(str, processColor, buffer+5, 3); + RichString_appendn(str, processShadowColor, buffer+8, 4); } } @@ -291,11 +291,11 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field for (int i = 0; i < 32; i++) { if (indent & (1U << i)) { - maxIndent = i + 1; + maxIndent = i+1; } } - for (int i = 0; i < maxIndent - 1; i++) { + for (int i = 0; i < maxIndent - 1; i++) { int written, ret; if (indent & (1 << i)) { ret = snprintf(buf, n, "%s ", CRT_treeStr[TREE_STR_VERT]); @@ -333,7 +333,7 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field case PID: xSnprintf(buffer, n, Process_pidFormat, this->pid); break; case PPID: xSnprintf(buffer, n, Process_pidFormat, this->ppid); break; case PRIORITY: { - if (this->priority <= -100) + if(this->priority <= -100) xSnprintf(buffer, n, " RT "); else xSnprintf(buffer, n, "%3ld ", this->priority); @@ -394,6 +394,14 @@ void Process_display(const Object* cast, RichString* out) { RichString_setAttr(out, CRT_colors[PROCESS_TAG]); } + if (this->settings->highlightChanges) { + if (Process_isTomb(this)) { + out->highlightAttr = CRT_colors[PROCESS_TOMB]; + } else if (Process_isNew(this)) { + out->highlightAttr = CRT_colors[PROCESS_NEW]; + } + } + assert(out->chlen > 0); } @@ -429,6 +437,18 @@ void Process_toggleTag(Process* this) { this->tag = this->tag == true ? false : true; } +bool Process_isNew(const Process* this) { + assert(this->processList); + if (this->processList->scanTs >= this->seenTs) { + return this->processList->scanTs - this->seenTs <= this->processList->settings->highlightDelaySecs; + } + return false; +} + +bool Process_isTomb(const Process* this) { + return this->tombTs > 0; +} + bool Process_setPriority(Process* this, int priority) { CRT_dropPrivileges(); int old_prio = getpriority(PRIO_PROCESS, this->pid); diff --git a/Process.h b/Process.h index 465fed68..c75ee501 100644 --- a/Process.h +++ b/Process.h @@ -9,18 +9,19 @@ in the source distribution for its full text. */ #include +#include #include #include "Object.h" #include "RichString.h" - #ifdef __ANDROID__ #define SYS_ioprio_get __NR_ioprio_get #define SYS_ioprio_set __NR_ioprio_set #endif #define PROCESS_FLAG_IO 0x0001 +#define DEFAULT_HIGHLIGHT_SECS 5 typedef enum ProcessFields { NULL_PROCESSFIELD = 0, @@ -59,6 +60,7 @@ struct Settings_; typedef struct Process_ { Object super; + const struct ProcessList_* processList; const struct Settings_* settings; unsigned long long int time; @@ -76,6 +78,7 @@ typedef struct Process_ { bool tag; bool showChildren; bool show; + bool wasShown; unsigned int pgrp; unsigned int session; unsigned int tty_nr; @@ -99,6 +102,9 @@ typedef struct Process_ { int exit_signal; + time_t seenTs; + time_t tombTs; + unsigned long int minflt; unsigned long int majflt; } Process; @@ -119,7 +125,7 @@ extern ProcessFieldData Process_fields[]; extern ProcessPidColumn Process_pidColumns[]; extern char Process_pidFormat[20]; -typedef Process* (* Process_New)(const struct Settings_*); +typedef Process*(*Process_New)(const struct Settings_*); typedef void (*Process_WriteField)(const Process*, RichString*, ProcessField); typedef struct ProcessClass_ { @@ -172,6 +178,10 @@ void Process_init(Process* this, const struct Settings_* settings); void Process_toggleTag(Process* this); +bool Process_isNew(const Process* this); + +bool Process_isTomb(const Process* this); + bool Process_setPriority(Process* this, int priority); bool Process_changePriorityBy(Process* this, Arg delta); diff --git a/ProcessList.c b/ProcessList.c index 457761a2..a88c1e7b 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -9,6 +9,7 @@ in the source distribution for its full text. #include #include +#include #include "CRT.h" #include "XUtils.h" @@ -27,6 +28,9 @@ ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, Users // set later by platform-specific code this->cpuCount = 0; + this->scanTs = 0; + this->firstScanTs = 0; + #ifdef HAVE_LIBHWLOC this->topologyOk = false; if (hwloc_topology_init(&this->topology) == 0) { @@ -85,6 +89,14 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) { void ProcessList_add(ProcessList* this, Process* p) { assert(Vector_indexOf(this->processes, p, Process_pidCompare) == -1); assert(Hashtable_get(this->processTable, p->pid) == NULL); + p->processList = this; + + if (this->scanTs == this->firstScanTs) { + // prevent highlighting processes found in first scan + p->seenTs = this->firstScanTs - this->settings->highlightDelaySecs - 1; + } else { + p->seenTs = this->scanTs; + } Vector_add(this->processes, p); Hashtable_put(this->processTable, p->pid, p); @@ -145,10 +157,10 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i Vector_insert(this->processes2, 0, process); } - assert(Vector_size(this->processes2) == s + 1); (void)s; + assert(Vector_size(this->processes2) == s+1); (void)s; int nextIndent = indent | (1 << level); - ProcessList_buildTree(this, process->pid, level + 1, (i < size - 1) ? nextIndent : indent, direction, show ? process->showChildren : false); + ProcessList_buildTree(this, process->pid, level+1, (i < size - 1) ? nextIndent : indent, direction, show ? process->showChildren : false); if (i == size - 1) { process->indent = -nextIndent; @@ -160,8 +172,8 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i } static long ProcessList_treeProcessCompare(const void* v1, const void* v2) { - const Process* p1 = (const Process*)v1; - const Process* p2 = (const Process*)v2; + const Process *p1 = (const Process*)v1; + const Process *p2 = (const Process*)v2; return p1->pid - p2->pid; } @@ -304,6 +316,7 @@ Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting, } void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) { + struct timespec now; // in pause mode only gather global data for meters (CPU/memory/...) if (pauseProcessUpdate) { @@ -315,6 +328,7 @@ void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) { for (int i = 0; i < Vector_size(this->processes); i++) { Process* p = (Process*) Vector_get(this->processes, i); p->updated = false; + p->wasShown = p->show; p->show = true; } @@ -323,12 +337,33 @@ void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) { this->kernelThreads = 0; this->runningTasks = 0; + + // set scanTs + if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) { + if (this->firstScanTs == 0) { + this->firstScanTs = now.tv_sec; + } + this->scanTs = now.tv_sec; + } + ProcessList_goThroughEntries(this, false); for (int i = Vector_size(this->processes) - 1; i >= 0; i--) { Process* p = (Process*) Vector_get(this->processes, i); - if (p->updated == false) { + if (p->tombTs > 0) { + // remove tombed process + if (this->scanTs >= p->tombTs) { ProcessList_remove(this, p); + } + } else if (p->updated == false) { + // process no longer exists + if (this->settings->highlightChanges && p->wasShown) { + // mark tombed + p->tombTs = this->scanTs + this->settings->highlightDelaySecs; + } else { + // immediately remove + ProcessList_remove(this, p); + } } else { p->updated = false; } diff --git a/ProcessList.h b/ProcessList.h index 737fffb3..db288104 100644 --- a/ProcessList.h +++ b/ProcessList.h @@ -70,6 +70,8 @@ typedef struct ProcessList_ { int cpuCount; + time_t scanTs; + time_t firstScanTs; } ProcessList; ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId); diff --git a/RichString.h b/RichString.h index fdf6ba35..12b09540 100644 --- a/RichString.h +++ b/RichString.h @@ -39,6 +39,7 @@ typedef struct RichString_ { int chlen; CharType* chptr; CharType chstr[RICHSTRING_MAXLEN + 1]; + int highlightAttr; } RichString; void RichString_setAttrn(RichString* this, int attrs, int start, int finish); diff --git a/ScreenManager.c b/ScreenManager.c index b8e1713a..28f289db 100644 --- a/ScreenManager.c +++ b/ScreenManager.c @@ -102,6 +102,7 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi struct timeval tv; gettimeofday(&tv, NULL); double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000); + *timedOut = (newTime - *oldTime > this->settings->delay); *rescan |= *timedOut; diff --git a/Settings.c b/Settings.c index ea32ebbe..15826471 100644 --- a/Settings.c +++ b/Settings.c @@ -157,6 +157,10 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo this->highlightMegabytes = atoi(option[1]); } else if (String_eq(option[0], "highlight_threads")) { this->highlightThreads = atoi(option[1]); + } else if (String_eq(option[0], "highlight_changes")) { + this->highlightChanges = atoi(option[1]); + } else if (String_eq(option[0], "highlight_changes_delay_secs")) { + this->highlightDelaySecs = atoi(option[1]); } else if (String_eq(option[0], "header_margin")) { this->headerMargin = atoi(option[1]); } else if (String_eq(option[0], "expand_system_time")) { @@ -265,6 +269,8 @@ bool Settings_write(Settings* this) { fprintf(fd, "highlight_base_name=%d\n", (int) this->highlightBaseName); fprintf(fd, "highlight_megabytes=%d\n", (int) this->highlightMegabytes); fprintf(fd, "highlight_threads=%d\n", (int) this->highlightThreads); + fprintf(fd, "highlight_changes=%d\n", (int) this->highlightChanges); + fprintf(fd, "highlight_changes_delay_secs=%d\n", (int) this->highlightDelaySecs); fprintf(fd, "tree_view=%d\n", (int) this->treeView); fprintf(fd, "header_margin=%d\n", (int) this->headerMargin); fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime); @@ -306,6 +312,8 @@ Settings* Settings_new(int initialCpuCount) { this->updateProcessNames = false; this->showProgramPath = true; this->highlightThreads = true; + this->highlightChanges = false; + this->highlightDelaySecs = DEFAULT_HIGHLIGHT_SECS; #ifdef HAVE_LIBHWLOC this->topologyAffinity = false; #endif diff --git a/Settings.h b/Settings.h index 3d8e0581..93b98bd8 100644 --- a/Settings.h +++ b/Settings.h @@ -47,6 +47,8 @@ typedef struct Settings_ { bool highlightBaseName; bool highlightMegabytes; bool highlightThreads; + bool highlightChanges; + int highlightDelaySecs; bool updateProcessNames; bool accountGuestInCPUMeter; bool headerMargin; diff --git a/htop.1.in b/htop.1.in index cf337b09..6048449d 100644 --- a/htop.1.in +++ b/htop.1.in @@ -4,7 +4,7 @@ htop \- interactive process viewer .SH "SYNOPSIS" .LP .B htop -.RB [ \-dCFhpustv ] +.RB [ \-dCFhpustvH ] .SH "DESCRIPTION" .LP .B htop @@ -62,6 +62,9 @@ Output version information and exit .TP \fB\-t \-\-tree Show processes in tree view +.TP +\fB\-H \-\-highlight-changes=DELAY\fR +Highlight new and old processes .SH "INTERACTIVE COMMANDS" .LP The following commands are supported while in diff --git a/htop.c b/htop.c index 7fbc04c9..b36bd4b0 100644 --- a/htop.c +++ b/htop.c @@ -50,8 +50,9 @@ static void printHelpFlag(void) { "-d --delay=DELAY Set the delay between updates, in tenths of seconds\n" "-F --filter=FILTER Show only the commands matching the given filter\n" "-h --help Print this help screen\n" + "-H --highlight-changes[=DELAY] Highlight new and old processes\n" "-M --no-mouse Disable the mouse\n" - "-p --pid=PID,[,PID,PID...] Show only the given PIDs\n" + "-p --pid=PID[,PID,PID...] Show only the given PIDs\n" "-s --sort-key=COLUMN Sort by COLUMN (try --sort-key=help for a list)\n" "-t --tree Show the tree view by default\n" "-u --user[=USERNAME] Show only processes for a given user (or $USER)\n" @@ -76,6 +77,8 @@ typedef struct CommandLineSettings_ { bool enableMouse; bool treeView; bool allowUnicode; + bool highlightChanges; + int highlightDelaySecs; } CommandLineSettings; static CommandLineSettings parseArguments(int argc, char** argv) { @@ -90,6 +93,8 @@ static CommandLineSettings parseArguments(int argc, char** argv) { .enableMouse = true, .treeView = false, .allowUnicode = true, + .highlightChanges = false, + .highlightDelaySecs = -1, }; static struct option long_opts[] = @@ -106,12 +111,13 @@ static CommandLineSettings parseArguments(int argc, char** argv) { {"tree", no_argument, 0, 't'}, {"pid", required_argument, 0, 'p'}, {"filter", required_argument, 0, 'F'}, - {0, 0, 0, 0} + {"highlight-changes", optional_argument, 0, 'H'}, + {0,0,0,0} }; - int opt, opti = 0; + int opt, opti=0; /* Parse arguments */ - while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:", long_opts, &opti))) { + while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:H::", long_opts, &opti))) { if (opt == EOF) break; switch (opt) { case 'h': @@ -186,11 +192,11 @@ static CommandLineSettings parseArguments(int argc, char** argv) { char* saveptr; char* pid = strtok_r(argCopy, ",", &saveptr); - if (!flags.pidMatchList) { + if(!flags.pidMatchList) { flags.pidMatchList = Hashtable_new(8, false); } - while (pid) { + while(pid) { unsigned int num_pid = atoi(pid); // deepcode ignore CastIntegerToAddress: we just want a non-NUll pointer here Hashtable_put(flags.pidMatchList, num_pid, (void *) 1); @@ -206,6 +212,24 @@ static CommandLineSettings parseArguments(int argc, char** argv) { break; } + case 'H': { + const char *delay = optarg; + if (!delay && optind < argc && argv[optind] != NULL && + (argv[optind][0] != '\0' && argv[optind][0] != '-')) { + delay = argv[optind++]; + } + if (delay) { + if (sscanf(delay, "%16d", &(flags.highlightDelaySecs)) == 1) { + if (flags.highlightDelaySecs < 1) + flags.highlightDelaySecs = 1; + } else { + fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay); + exit(1); + } + } + flags.highlightChanges = true; + break; + } default: exit(1); } @@ -218,7 +242,7 @@ static void millisleep(unsigned long millisec) { .tv_sec = 0, .tv_nsec = millisec * 1000000L }; - while (nanosleep(&req, &req) == -1) { + while(nanosleep(&req,&req)==-1) { continue; } } @@ -242,7 +266,7 @@ static void setCommFilter(State* state, char** commFilter) { int main(int argc, char** argv) { - char* lc_ctype = getenv("LC_CTYPE"); + char *lc_ctype = getenv("LC_CTYPE"); if (lc_ctype != NULL) { setlocale(LC_CTYPE, lc_ctype); } else if ((lc_ctype = getenv("LC_ALL"))) { @@ -284,6 +308,12 @@ int main(int argc, char** argv) { if (flags.treeView) { settings->treeView = true; } + if (flags.highlightChanges) { + settings->highlightChanges = true; + } + if (flags.highlightDelaySecs != -1) { + settings->highlightDelaySecs = flags.highlightDelaySecs; + } CRT_init(settings->delay, settings->colorScheme, flags.allowUnicode); @@ -323,7 +353,7 @@ int main(int argc, char** argv) { ScreenManager_run(scr, NULL, NULL); attron(CRT_colors[RESET_COLOR]); - mvhline(LINES - 1, 0, ' ', COLS); + mvhline(LINES-1, 0, ' ', COLS); attroff(CRT_colors[RESET_COLOR]); refresh(); @@ -339,7 +369,7 @@ int main(int argc, char** argv) { UsersTable_delete(ut); Settings_delete(settings); - if (flags.pidMatchList) { + if(flags.pidMatchList) { Hashtable_delete(flags.pidMatchList); } return 0;