From 5c8f70a17c2eea3e04f0b41a8ac59e4c60ccd8c3 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Fri, 27 Jan 2023 09:55:33 +0000 Subject: [PATCH] os: Use KERN_PROC_ARGS to determine client command on DragonFly and FreeBSD --- os/client.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/os/client.c b/os/client.c index 953431bd9..3295949a4 100644 --- a/os/client.c +++ b/os/client.c @@ -73,6 +73,11 @@ #include #endif +#if defined(__DragonFly__) || defined(__FreeBSD__) +#include +#include +#endif + #ifdef __APPLE__ #include #include @@ -136,7 +141,7 @@ DetermineClientPid(struct _Client * client) void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) { -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__FreeBSD__) char path[PATH_MAX + 1]; int totsize = 0; int fd = 0; @@ -248,6 +253,56 @@ DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) *cmdargs = strdup(args); } + free(procargs); + } +#elif defined(__DragonFly__) || defined(__FreeBSD__) + /* on DragonFly and FreeBSD use KERN_PROC_ARGS */ + { + int mib[] = { + CTL_KERN, + KERN_PROC, + KERN_PROC_ARGS, + pid, + }; + + /* Determine exact size instead of relying on kern.argmax */ + size_t len; + if (sysctl(mib, ARRAY_SIZE(mib), NULL, &len, NULL, 0) != 0) { + ErrorF("Failed to query KERN_PROC_ARGS length for PID %d: %s\n", pid, strerror(errno)); + return; + } + + /* Read KERN_PROC_ARGS contents. Similar to /proc/pid/cmdline + * the process name and each argument are separated by NUL byte. */ + char *const procargs = malloc(len); + if (sysctl(mib, ARRAY_SIZE(mib), procargs, &len, NULL, 0) != 0) { + ErrorF("Failed to get KERN_PROC_ARGS for PID %d: %s\n", pid, strerror(errno)); + free(procargs); + return; + } + + /* Construct the process name without arguments. */ + if (cmdname) { + *cmdname = strdup(procargs); + } + + /* Construct the arguments for client process. */ + if (cmdargs) { + size_t cmdsize = strlen(procargs) + 1; + size_t argsize = len - cmdsize; + char *args = NULL; + + if (argsize > 0) + args = procargs + cmdsize; + if (args) { + /* Replace NUL with space except terminating NUL */ + for (size_t i = 0; i < (argsize - 1); i++) { + if (args[i] == '\0') + args[i] = ' '; + } + *cmdargs = strdup(args); + } + } free(procargs); } #elif defined(__OpenBSD__)