From fe848403149dd8e452281ec8eb16a8401112b0f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Thu, 26 Nov 2020 17:51:54 +0100 Subject: Add Linux cwd process column --- linux/LinuxProcess.c | 15 +++++++++++++++ linux/LinuxProcess.h | 5 ++++- linux/LinuxProcessList.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index 23b08be2..5cff5703 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -115,6 +115,7 @@ ProcessFieldData Process_fields[] = { [SECATTR] = { .name = "SECATTR", .title = " Security Attribute ", .description = "Security attribute of the process (e.g. SELinux or AppArmor)", .flags = PROCESS_FLAG_LINUX_SECATTR, }, [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_LINUX_CWD, }, [LAST_PROCESSFIELD] = { .name = "*** report bug! ***", .title = NULL, .description = NULL, .flags = 0, }, }; @@ -156,6 +157,7 @@ void Process_delete(Object* cast) { #ifdef HAVE_OPENVZ free(this->ctid); #endif + free(this->cwd); free(this->secattr); free(this->ttyDevice); free(this->procExe); @@ -739,6 +741,17 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces } break; } + case CWD: + if (!lp->cwd) { + xSnprintf(buffer, n, "%-25s ", "N/A"); + attr = CRT_colors[PROCESS_SHADOW]; + } else if (String_startsWith(lp->cwd, "/proc/") && strstr(lp->cwd, " (deleted)") != NULL) { + xSnprintf(buffer, n, "%-25s ", "main thread terminated"); + attr = CRT_colors[PROCESS_SHADOW]; + } else { + xSnprintf(buffer, n, "%-25.25s ", lp->cwd); + } + break; default: Process_writeField(this, str, field); return; @@ -841,6 +854,8 @@ static long LinuxProcess_compare(const void* v1, const void* v2) { const char *exe2 = p2->procExe ? (p2->procExe + p2->procExeBasenameOffset) : (Process_isKernelThread(p2) ? kthreadID : ""); return strcmp(exe1, exe2); } + case CWD: + return SPACESHIP_NULLSTR(p1->cwd, p2->cwd); default: return Process_compare(v1, v2); } diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index e665502c..41127113 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -28,6 +28,7 @@ in the source distribution for its full text. #define PROCESS_FLAG_LINUX_CTXT 0x00004000 #define PROCESS_FLAG_LINUX_SECATTR 0x00008000 #define PROCESS_FLAG_LINUX_LRS_FIX 0x00010000 +#define PROCESS_FLAG_LINUX_CWD 0x00020000 typedef enum UnsupportedProcessFields { FLAGS = 9, @@ -94,7 +95,8 @@ typedef enum LinuxProcessFields { SECATTR = 123, PROC_COMM = 124, PROC_EXE = 125, - LAST_PROCESSFIELD = 126, + CWD = 126, + LAST_PROCESSFIELD = 127, } LinuxProcessField; /* LinuxProcessMergedCommand is populated by LinuxProcess_makeCommandStr: It @@ -181,6 +183,7 @@ typedef struct LinuxProcess_ { unsigned long ctxt_diff; char* secattr; unsigned long long int last_mlrs_calctime; + char* cwd; } LinuxProcess; #define Process_isKernelThread(_process) (((const LinuxProcess*)(_process))->isKernelThread) diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 5d9ec87b..46850e1a 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -882,6 +882,31 @@ static void LinuxProcessList_readSecattrData(LinuxProcess* process, openat_arg_t process->secattr = xStrdup(buffer); } +static void LinuxProcessList_readCwd(LinuxProcess* process, openat_arg_t procFd) { + char pathBuffer[PATH_MAX + 1]; + +#if defined(HAVE_READLINKAT) && defined(HAVE_OPENAT) + ssize_t r = readlinkat(procFd, "cwd", pathBuffer, sizeof(pathBuffer) - 1); +#else + char filename[MAX_NAME + 1]; + xSnprintf(filename, sizeof(filename), "%s/cwd", procFd); + ssize_t r = readlink(filename, pathBuffer, sizeof(pathBuffer) - 1); +#endif + if (r < 0) { + free(process->cwd); + process->cwd = NULL; + return; + } + + pathBuffer[r] = '\0'; + + if (process->cwd && String_eq(process->cwd, pathBuffer)) + return; + + free(process->cwd); + process->cwd = xStrdup(pathBuffer); +} + #ifdef HAVE_DELAYACCT static int handleNetlinkMsg(struct nl_msg* nlmsg, void* linuxProcess) { @@ -1404,6 +1429,10 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ LinuxProcessList_readSecattrData(lp, procFd); } + if (settings->flags & PROCESS_FLAG_LINUX_CWD) { + LinuxProcessList_readCwd(lp, procFd); + } + if (proc->state == 'Z' && (proc->basenameOffset == 0)) { proc->basenameOffset = -1; setCommand(proc, command, commLen); -- cgit v1.2.3