diff options
author | Benny Baumann <BenBE@geshi.org> | 2021-04-10 13:31:39 +0200 |
---|---|---|
committer | BenBE <BenBE@geshi.org> | 2021-05-23 09:22:21 +0200 |
commit | bcb18ef82269c68d54a160290e5f8b2e939674ec (patch) | |
tree | e5967c038b2d11ed906b8fdda0babe114dab3c46 /linux | |
parent | c0d02024407411f75a4d7d5b63f26b74c727027b (diff) |
Move Process_makeCommandStr to global Process implementation
Diffstat (limited to 'linux')
-rw-r--r-- | linux/LinuxProcess.c | 356 | ||||
-rw-r--r-- | linux/LinuxProcess.h | 4 | ||||
-rw-r--r-- | linux/LinuxProcessList.c | 4 |
3 files changed, 4 insertions, 360 deletions
diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index 155bea86..7d32a6d3 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -172,358 +172,6 @@ static void LinuxProcess_printDelay(float delay_percent, char* buffer, int n) { } #endif -/* -TASK_COMM_LEN is defined to be 16 for /proc/[pid]/comm in man proc(5), but it is -not available in an userspace header - so define it. Note: when colorizing a -basename with the comm prefix, the entire basename (not just the comm prefix) is -colorized for better readability, and it is implicit that only upto -(TASK_COMM_LEN - 1) could be comm -*/ -#define TASK_COMM_LEN 16 - -static bool findCommInCmdline(const char *comm, const char *cmdline, int cmdlineBasenameStart, int *pCommStart, int *pCommEnd) { - /* Try to find procComm in tokenized cmdline - this might in rare cases - * mis-identify a string or fail, if comm or cmdline had been unsuitably - * modified by the process */ - const char *tokenBase; - size_t tokenLen; - const size_t commLen = strlen(comm); - - if (cmdlineBasenameStart < 0) - return false; - - for (const char *token = cmdline + cmdlineBasenameStart; *token;) { - for (tokenBase = token; *token && *token != '\n'; ++token) { - if (*token == '/') { - tokenBase = token + 1; - } - } - tokenLen = token - tokenBase; - - if ((tokenLen == commLen || (tokenLen > commLen && commLen == (TASK_COMM_LEN - 1))) && - strncmp(tokenBase, comm, commLen) == 0) { - *pCommStart = tokenBase - cmdline; - *pCommEnd = token - cmdline; - return true; - } - if (*token) { - do { - ++token; - } while (*token && '\n' == *token); - } - } - return false; -} - -static int matchCmdlinePrefixWithExeSuffix(const char *cmdline, int cmdlineBaseOffset, const char *exe, int exeBaseOffset, int exeBaseLen) { - int matchLen; /* matching length to be returned */ - char delim; /* delimiter following basename */ - - /* cmdline prefix is an absolute path: it must match whole exe. */ - if (cmdline[0] == '/') { - matchLen = exeBaseLen + exeBaseOffset; - if (strncmp(cmdline, exe, matchLen) == 0) { - delim = cmdline[matchLen]; - if (delim == 0 || delim == '\n' || delim == ' ') { - return matchLen; - } - } - return 0; - } - - /* cmdline prefix is a relative path: We need to first match the basename at - * cmdlineBaseOffset and then reverse match the cmdline prefix with the exe - * suffix. But there is a catch: Some processes modify their cmdline in ways - * that make htop's identification of the basename in cmdline unreliable. - * For e.g. /usr/libexec/gdm-session-worker modifies its cmdline to - * "gdm-session-worker [pam/gdm-autologin]" and htop ends up with - * proccmdlineBasenameEnd at "gdm-autologin]". This issue could arise with - * chrome as well as it stores in cmdline its concatenated argument vector, - * without NUL delimiter between the arguments (which may contain a '/') - * - * So if needed, we adjust cmdlineBaseOffset to the previous (if any) - * component of the cmdline relative path, and retry the procedure. */ - bool delimFound; /* if valid basename delimiter found */ - do { - /* match basename */ - matchLen = exeBaseLen + cmdlineBaseOffset; - if (cmdlineBaseOffset < exeBaseOffset && - strncmp(cmdline + cmdlineBaseOffset, exe + exeBaseOffset, exeBaseLen) == 0) { - delim = cmdline[matchLen]; - if (delim == 0 || delim == '\n' || delim == ' ') { - int i, j; - /* reverse match the cmdline prefix and exe suffix */ - for (i = cmdlineBaseOffset - 1, j = exeBaseOffset - 1; - i >= 0 && j >= 0 && cmdline[i] == exe[j]; --i, --j) - ; - /* full match, with exe suffix being a valid relative path */ - if (i < 0 && j >= 0 && exe[j] == '/') { - return matchLen; - } - } - } - - /* Try to find the previous potential cmdlineBaseOffset - it would be - * preceded by '/' or nothing, and delimited by ' ' or '\n' */ - for (delimFound = false, cmdlineBaseOffset -= 2; cmdlineBaseOffset > 0; --cmdlineBaseOffset) { - if (delimFound) { - if (cmdline[cmdlineBaseOffset - 1] == '/') { - break; - } - } else if (cmdline[cmdlineBaseOffset] == ' ' || cmdline[cmdlineBaseOffset] == '\n') { - delimFound = true; - } - } - } while (delimFound); - - return 0; -} - -/* stpcpy, but also converts newlines to spaces */ -static inline char *stpcpyWithNewlineConversion(char *dstStr, const char *srcStr) { - for (; *srcStr; ++srcStr) { - *dstStr++ = (*srcStr == '\n') ? ' ' : *srcStr; - } - *dstStr = 0; - return dstStr; -} - -/* -This function makes the merged Command string. It also stores the offsets of the -basename, comm w.r.t the merged Command string - these offsets will be used by -LinuxProcess_writeCommand() for coloring. The merged Command string is also -returned by LinuxProcess_getCommandStr() for searching, sorting and filtering. -*/ -void LinuxProcess_makeCommandStr(Process* this) { - ProcessMergedCommand *mc = &this->mergedCommand; - const Settings* settings = this->settings; - - bool showMergedCommand = settings->showMergedCommand; - bool showProgramPath = settings->showProgramPath; - bool searchCommInCmdline = settings->findCommInCmdline; - bool stripExeFromCmdline = settings->stripExeFromCmdline; - - /* lp->mergedCommand.str needs updating only if its state or contents changed. - * Its content is based on the fields cmdline, comm, and exe. */ - if ( - mc->prevMergeSet == showMergedCommand && - mc->prevPathSet == showProgramPath && - mc->prevCommSet == searchCommInCmdline && - mc->prevCmdlineSet == stripExeFromCmdline && - !mc->cmdlineChanged && - !mc->commChanged && - !mc->exeChanged - ) { - return; - } - - /* The field separtor "│" has been chosen such that it will not match any - * valid string used for searching or filtering */ - const char *SEPARATOR = CRT_treeStr[TREE_STR_VERT]; - const int SEPARATOR_LEN = strlen(SEPARATOR); - - /* Check for any changed fields since we last built this string */ - if (mc->cmdlineChanged || mc->commChanged || mc->exeChanged) { - free(mc->str); - /* Accommodate the column text, two field separators and terminating NUL */ - mc->str = xCalloc(1, mc->maxLen + 2*SEPARATOR_LEN + 1); - } - - /* Preserve the settings used in this run */ - mc->prevMergeSet = showMergedCommand; - mc->prevPathSet = showProgramPath; - mc->prevCommSet = searchCommInCmdline; - mc->prevCmdlineSet = stripExeFromCmdline; - - /* Mark everything as unchanged */ - mc->cmdlineChanged = false; - mc->commChanged = false; - mc->exeChanged = false; - - /* Reset all locations that need extra handling when actually displaying */ - mc->highlightCount = 0; - memset(mc->highlights, 0, sizeof(mc->highlights)); - - size_t mbMismatch = 0; - #define WRITE_HIGHLIGHT(_offset, _length, _attr, _flags) \ - do { \ - /* Check if we still have capacity */ \ - assert(mc->highlightCount < ARRAYSIZE(mc->highlights)); \ - if (mc->highlightCount >= ARRAYSIZE(mc->highlights)) \ - continue; \ - \ - mc->highlights[mc->highlightCount].offset = str - strStart + _offset - mbMismatch; \ - mc->highlights[mc->highlightCount].length = _length; \ - mc->highlights[mc->highlightCount].attr = _attr; \ - mc->highlights[mc->highlightCount].flags = _flags; \ - mc->highlightCount++; \ - } while (0) - - #define WRITE_SEPARATOR \ - do { \ - WRITE_HIGHLIGHT(0, 1, CRT_colors[FAILED_READ], CMDLINE_HIGHLIGHT_FLAG_SEPARATOR); \ - mbMismatch += SEPARATOR_LEN - 1; \ - str = stpcpy(str, SEPARATOR); \ - } while (0) - - const int baseAttr = Process_isThread(this) ? CRT_colors[PROCESS_THREAD_BASENAME] : CRT_colors[PROCESS_BASENAME]; - const int commAttr = Process_isThread(this) ? CRT_colors[PROCESS_THREAD_COMM] : CRT_colors[PROCESS_COMM]; - const int delAttr = CRT_colors[FAILED_READ]; - - /* Establish some shortcuts to data we need */ - const char *cmdline = this->cmdline; - const char *procComm = this->procComm; - const char *procExe = this->procExe; - - char *strStart = mc->str; - char *str = strStart; - - int cmdlineBasenameStart = this->cmdlineBasenameStart; - int cmdlineBasenameEnd = this->cmdlineBasenameEnd; - - if (!cmdline) { - cmdlineBasenameStart = 0; - cmdlineBasenameEnd = 0; - cmdline = "(zombie)"; - } - - assert(cmdlineBasenameStart >= 0); - assert(cmdlineBasenameStart <= (int)strlen(cmdline)); - - if (!showMergedCommand || !procExe || !procComm) { /* fall back to cmdline */ - if (showMergedCommand && !procExe && procComm && strlen(procComm)) { /* Prefix column with comm */ - if (strncmp(cmdline + cmdlineBasenameStart, procComm, MINIMUM(TASK_COMM_LEN - 1, strlen(procComm))) != 0) { - WRITE_HIGHLIGHT(0, strlen(procComm), commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); - str = stpcpy(str, procComm); - - WRITE_SEPARATOR; - } - } - - if (showProgramPath) { - WRITE_HIGHLIGHT(cmdlineBasenameStart, cmdlineBasenameEnd - cmdlineBasenameStart, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME); - (void)stpcpyWithNewlineConversion(str, cmdline); - } else { - WRITE_HIGHLIGHT(0, cmdlineBasenameEnd - cmdlineBasenameStart, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME); - (void)stpcpyWithNewlineConversion(str, cmdline + cmdlineBasenameStart); - } - - return; - } - - int exeLen = strlen(this->procExe); - int exeBasenameOffset = this->procExeBasenameOffset; - int exeBasenameLen = exeLen - exeBasenameOffset; - - assert(exeBasenameOffset >= 0); - assert(exeBasenameOffset <= (int)strlen(procExe)); - - bool haveCommInExe = false; - if (procExe && procComm) { - haveCommInExe = strncmp(procExe + exeBasenameOffset, procComm, TASK_COMM_LEN - 1) == 0; - } - - /* Start with copying exe */ - if (showProgramPath) { - if (haveCommInExe) - WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); - WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME); - if (this->procExeDeleted) - WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, delAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED); - str = stpcpy(str, procExe); - } else { - if (haveCommInExe) - WRITE_HIGHLIGHT(0, exeBasenameLen, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); - WRITE_HIGHLIGHT(0, exeBasenameLen, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME); - if (this->procExeDeleted) - WRITE_HIGHLIGHT(0, exeBasenameLen, delAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED); - str = stpcpy(str, procExe + exeBasenameOffset); - } - - bool haveCommInCmdline = false; - int commStart = 0; - int commEnd = 0; - - /* Try to match procComm with procExe's basename: This is reliable (predictable) */ - if (searchCommInCmdline) { - /* commStart/commEnd will be adjusted later along with cmdline */ - haveCommInCmdline = findCommInCmdline(procComm, cmdline, cmdlineBasenameStart, &commStart, &commEnd); - } - - int matchLen = matchCmdlinePrefixWithExeSuffix(cmdline, cmdlineBasenameStart, procExe, exeBasenameOffset, exeBasenameLen); - - bool haveCommField = false; - - if (!haveCommInExe && !haveCommInCmdline && procComm) { - WRITE_SEPARATOR; - WRITE_HIGHLIGHT(0, strlen(procComm), commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); - str = stpcpy(str, procComm); - haveCommField = true; - } - - if (matchLen) { - /* strip the matched exe prefix */ - cmdline += matchLen; - - commStart -= matchLen; - commEnd -= matchLen; - } - - if (!matchLen || (haveCommField && *cmdline)) { - /* cmdline will be a separate field */ - WRITE_SEPARATOR; - } - - if (!haveCommInExe && haveCommInCmdline && !haveCommField) - WRITE_HIGHLIGHT(commStart, commEnd - commStart, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); - - /* Display cmdline if it hasn't been consumed by procExe */ - if (*cmdline) { - (void) stpcpyWithNewlineConversion(str, cmdline); - } - - #undef WRITE_SEPARATOR - #undef WRITE_HIGHLIGHT -} - -static void LinuxProcess_writeCommand(const Process* this, int attr, int baseAttr, RichString* str) { - (void)baseAttr; - - const ProcessMergedCommand *mc = &this->mergedCommand; - - int strStart = RichString_size(str); - -// int commAttr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM]; - - const bool highlightBaseName = this->settings->highlightBaseName; - const bool highlightSeparator = true; - const bool highlightDeleted = true; - - RichString_appendWide(str, attr, this->mergedCommand.str); - - for (size_t i = 0, hlCount = CLAMP(mc->highlightCount, 0, ARRAYSIZE(mc->highlights)); i < hlCount; i++) - { - const ProcessCmdlineHighlight* hl = &mc->highlights[i]; - - if (!hl->length) - continue; - - if (hl->flags & CMDLINE_HIGHLIGHT_FLAG_SEPARATOR) - if (!highlightSeparator) - continue; - - if (hl->flags & CMDLINE_HIGHLIGHT_FLAG_BASENAME) - if (!highlightBaseName) - continue; - - if (hl->flags & CMDLINE_HIGHLIGHT_FLAG_DELETED) - if (!highlightDeleted) - continue; - - RichString_setAttrn(str, hl->attr, strStart + hl->offset, hl->length); - } -} - static void LinuxProcess_writeCommandField(const Process *this, RichString *str, char *buffer, int n, int attr) { /* This code is from Process_writeField for COMM, but we invoke * LinuxProcess_writeCommand to display @@ -534,7 +182,7 @@ static void LinuxProcess_writeCommandField(const Process *this, RichString *str, baseattr = CRT_colors[PROCESS_THREAD_BASENAME]; } if (!this->settings->treeView || this->indent == 0) { - LinuxProcess_writeCommand(this, attr, baseattr, str); + Process_writeCommand(this, attr, baseattr, str); } else { char* buf = buffer; int maxIndent = 0; @@ -566,7 +214,7 @@ static void LinuxProcess_writeCommandField(const Process *this, RichString *str, const char* draw = CRT_treeStr[lastItem ? TREE_STR_BEND : TREE_STR_RTEE]; xSnprintf(buf, n, "%s%s ", draw, this->showChildren ? CRT_treeStr[TREE_STR_SHUT] : CRT_treeStr[TREE_STR_OPEN] ); RichString_appendWide(str, CRT_colors[PROCESS_TREE], buffer); - LinuxProcess_writeCommand(this, attr, baseattr, str); + Process_writeCommand(this, attr, baseattr, str); } } diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index 90ce7c50..fe9d88e2 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -119,10 +119,6 @@ IOPriority LinuxProcess_updateIOPriority(LinuxProcess* this); bool LinuxProcess_setIOPriority(Process* this, Arg ioprio); -/* This function constructs the string that is displayed by - * LinuxProcess_writeCommand and also returned by LinuxProcess_getCommandStr */ -void LinuxProcess_makeCommandStr(Process *this); - bool Process_isThread(const Process* this); #endif diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 020fc0a5..ca2f2b80 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -1028,7 +1028,7 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t proc for (int i = 0; i < amtRead; i++) { /* newline used as delimiter - when forming the mergedCommand, newline is - * converted to space by LinuxProcess_makeCommandStr */ + * converted to space by Process_makeCommandStr */ if (command[i] == '\0') { command[i] = '\n'; } else { @@ -1432,7 +1432,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ if (!Process_isKernelThread(proc) && (proc->state != 'Z' || proc->mergedCommand.str) && (!Process_isUserlandThread(proc) || !settings->showThreadNames)) { - LinuxProcess_makeCommandStr(proc); + Process_makeCommandStr(proc); } #ifdef HAVE_DELAYACCT |