summaryrefslogtreecommitdiffstats
path: root/src/collectors/apps.plugin/apps_proc_pid_cmdline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/collectors/apps.plugin/apps_proc_pid_cmdline.c')
-rw-r--r--src/collectors/apps.plugin/apps_proc_pid_cmdline.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/collectors/apps.plugin/apps_proc_pid_cmdline.c b/src/collectors/apps.plugin/apps_proc_pid_cmdline.c
new file mode 100644
index 000000000..75a60fa3a
--- /dev/null
+++ b/src/collectors/apps.plugin/apps_proc_pid_cmdline.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "apps_plugin.h"
+
+#ifdef __APPLE__
+bool get_cmdline_per_os(struct pid_stat *p, char *cmdline, size_t maxBytes) {
+ int mib[3] = {CTL_KERN, KERN_PROCARGS2, p->pid};
+ static char *args = NULL;
+ static size_t size = 0;
+
+ size_t new_size;
+ if (sysctl(mib, 3, NULL, &new_size, NULL, 0) == -1) {
+ return false;
+ }
+
+ if (new_size > size) {
+ if (args)
+ freez(args);
+
+ args = (char *)mallocz(new_size);
+ size = new_size;
+ }
+
+ memset(cmdline, 0, new_size < maxBytes ? new_size : maxBytes);
+
+ size_t used_size = size;
+ if (sysctl(mib, 3, args, &used_size, NULL, 0) == -1)
+ return false;
+
+ int argc;
+ memcpy(&argc, args, sizeof(argc));
+ char *ptr = args + sizeof(argc);
+ used_size -= sizeof(argc);
+
+ // Skip the executable path
+ while (*ptr && used_size > 0) {
+ ptr++;
+ used_size--;
+ }
+
+ // Copy only the arguments to the cmdline buffer, skipping the environment variables
+ size_t i = 0, copied_args = 0;
+ bool inArg = false;
+ for (; used_size > 0 && i < maxBytes - 1 && copied_args < argc; --used_size, ++ptr) {
+ if (*ptr == '\0') {
+ if (inArg) {
+ cmdline[i++] = ' '; // Replace nulls between arguments with spaces
+ inArg = false;
+ copied_args++;
+ }
+ } else {
+ cmdline[i++] = *ptr;
+ inArg = true;
+ }
+ }
+
+ if (i > 0 && cmdline[i - 1] == ' ')
+ i--; // Remove the trailing space if present
+
+ cmdline[i] = '\0'; // Null-terminate the string
+
+ return true;
+}
+#endif // __APPLE__
+
+#if defined(__FreeBSD__)
+static inline bool get_cmdline_per_os(struct pid_stat *p, char *cmdline, size_t bytes) {
+ size_t i, b = bytes - 1;
+ int mib[4];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ARGS;
+ mib[3] = p->pid;
+ if (unlikely(sysctl(mib, 4, cmdline, &b, NULL, 0)))
+ return false;
+
+ cmdline[b] = '\0';
+ for(i = 0; i < b ; i++)
+ if(unlikely(!cmdline[i])) cmdline[i] = ' ';
+
+ return true;
+}
+#endif // __FreeBSD__
+
+#if !defined(__FreeBSD__) && !defined(__APPLE__)
+static inline bool get_cmdline_per_os(struct pid_stat *p, char *cmdline, size_t bytes) {
+ if(unlikely(!p->cmdline_filename)) {
+ char filename[FILENAME_MAX];
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", netdata_configured_host_prefix, p->pid);
+ p->cmdline_filename = strdupz(filename);
+ }
+
+ int fd = open(p->cmdline_filename, procfile_open_flags, 0666);
+ if(unlikely(fd == -1))
+ return false;
+
+ ssize_t i, b = read(fd, cmdline, bytes - 1);
+ close(fd);
+
+ if(unlikely(b < 0))
+ return false;
+
+ cmdline[b] = '\0';
+ for(i = 0; i < b ; i++)
+ if(unlikely(!cmdline[i])) cmdline[i] = ' ';
+
+ return true;
+}
+#endif // !__FreeBSD__ !__APPLE__
+
+int read_proc_pid_cmdline(struct pid_stat *p) {
+ static char cmdline[MAX_CMDLINE];
+
+ if(unlikely(!get_cmdline_per_os(p, cmdline, sizeof(cmdline))))
+ goto cleanup;
+
+ if(p->cmdline) freez(p->cmdline);
+ p->cmdline = strdupz(cmdline);
+
+ debug_log("Read file '%s' contents: %s", p->cmdline_filename, p->cmdline);
+
+ return 1;
+
+cleanup:
+ // copy the command to the command line
+ if(p->cmdline) freez(p->cmdline);
+ p->cmdline = strdupz(p->comm);
+ return 0;
+}