From 3ba695293c981af034d243605a30dac6cb55f880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Sat, 4 Dec 2021 19:57:47 +0100 Subject: Linux: dynamically adjust the SECATTR column width SELinux contexts can be quite long; adjust the column width dynamically at each cycle to the longest value. Also with the recent addition of multiple screens, over-long columns can be moved into their own screen. --- Process.c | 20 ++++++++++++++++++++ Process.h | 7 +++++++ ProcessList.c | 7 +++++++ linux/LinuxProcess.c | 4 ++-- linux/LinuxProcessList.c | 3 +++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Process.c b/Process.c index 34c66bec..4e4f2c52 100644 --- a/Process.c +++ b/Process.c @@ -1252,3 +1252,23 @@ void Process_updateExe(Process* this, const char* exe) { } this->mergedCommand.exeChanged = true; } + +uint8_t Process_fieldWidths[LAST_PROCESSFIELD] = { 0 }; + +void Process_resetFieldWidths() { + for (size_t i = 0; i < LAST_PROCESSFIELD; i++) { + if (!Process_fields[i].autoWidth) + continue; + + size_t len = strlen(Process_fields[i].title); + assert(len <= UINT8_MAX); + Process_fieldWidths[i] = (uint8_t)len; + } +} + +void Process_updateFieldWidth(ProcessField key, size_t width) { + if (width > UINT8_MAX) + Process_fieldWidths[key] = UINT8_MAX; + else if (width > Process_fieldWidths[key]) + Process_fieldWidths[key] = (uint8_t)width; +} diff --git a/Process.h b/Process.h index 70892e57..d02c5d5f 100644 --- a/Process.h +++ b/Process.h @@ -279,6 +279,9 @@ typedef struct ProcessFieldData_ { /* Whether the column should be sorted in descending order by default */ bool defaultSortDesc; + + /* Whether the column width is dynamically adjusted (the minimum width is determined by the title length) */ + bool autoWidth; } ProcessFieldData; // Implemented in platform-specific code: @@ -286,6 +289,7 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field int Process_compare(const void* v1, const void* v2); void Process_delete(Object* cast); extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; +extern uint8_t Process_fieldWidths[LAST_PROCESSFIELD]; #define PROCESS_MIN_PID_DIGITS 5 #define PROCESS_MAX_PID_DIGITS 19 #define PROCESS_MIN_UID_DIGITS 5 @@ -406,4 +410,7 @@ void Process_makeCommandStr(Process* this); void Process_writeCommand(const Process* this, int attr, int baseAttr, RichString* str); +void Process_resetFieldWidths(void); +void Process_updateFieldWidth(ProcessField key, size_t width); + #endif diff --git a/ProcessList.c b/ProcessList.c index f6ba63fd..f3e184e8 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -114,6 +114,12 @@ static const char* alignedProcessFieldTitle(const ProcessList* this, ProcessFiel return titleBuffer; } + if (Process_fields[field].autoWidth) { + static char titleBuffer[UINT8_MAX + 1]; + xSnprintf(titleBuffer, sizeof(titleBuffer), "%-*.*s ", Process_fieldWidths[field], Process_fieldWidths[field], title); + return titleBuffer; + } + return title; } @@ -453,6 +459,7 @@ void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) { this->kernelThreads = 0; this->runningTasks = 0; + Process_resetFieldWidths(); // set scan timestamp static bool firstScanDone = false; diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index ba2dbd46..f6d2d0e8 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -94,7 +94,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { [M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, [M_PSSWP] = { .name = "M_PSSWP", .title = " PSSWP ", .description = "shows proportional swap share of this mapping, unlike \"Swap\", this does not take into account swapped out page of underlying shmem objects", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, [CTXT] = { .name = "CTXT", .title = " CTXT ", .description = "Context switches (incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches)", .flags = PROCESS_FLAG_LINUX_CTXT, .defaultSortDesc = true, }, - [SECATTR] = { .name = "SECATTR", .title = "Security Attribute ", .description = "Security attribute of the process (e.g. SELinux or AppArmor)", .flags = PROCESS_FLAG_LINUX_SECATTR, }, + [SECATTR] = { .name = "SECATTR", .title = "Security Attribute", .description = "Security attribute of the process (e.g. SELinux or AppArmor)", .flags = PROCESS_FLAG_LINUX_SECATTR, .autoWidth = true, }, [PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process from /proc/[pid]/comm", .flags = 0, }, [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process from /proc/[pid]/exe", .flags = 0, }, [CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, }, @@ -280,7 +280,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces } xSnprintf(buffer, n, "%5lu ", lp->ctxt_diff); break; - case SECATTR: snprintf(buffer, n, "%-30.30s ", lp->secattr ? lp->secattr : "?"); break; + case SECATTR: snprintf(buffer, n, "%-*.*s ", Process_fieldWidths[SECATTR], Process_fieldWidths[SECATTR], lp->secattr ? lp->secattr : "N/A"); break; case AUTOGROUP_ID: if (lp->autogroup_id != -1) { xSnprintf(buffer, n, "%4ld ", lp->autogroup_id); diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 492887d8..9be97681 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -1029,6 +1029,9 @@ static void LinuxProcessList_readSecattrData(LinuxProcess* process, openat_arg_t if (newline) { *newline = '\0'; } + + Process_updateFieldWidth(SECATTR, strlen(buffer)); + if (process->secattr && String_eq(process->secattr, buffer)) { return; } -- cgit v1.2.3