diff --git a/src/processes.c b/src/processes.c
index e58076a3c83ad41d13b1d40dadaf3152c4d95606..66237dc376be56414b29d62000d8a39c6fd70e1b 100644 (file)
--- a/src/processes.c
+++ b/src/processes.c
char *fields[64];
char fields_len;
- int i;
+ int buffer_len;
- int name_len;
+ char *buffer_ptr;
+ size_t name_start_pos;
+ size_t name_end_pos;
+ size_t name_len;
derive_t cpu_user_counter;
derive_t cpu_system_counter;
ssnprintf (filename, sizeof (filename), "/proc/%i/stat", pid);
- i = read_file_contents (filename, buffer, sizeof(buffer) - 1);
- if (i <= 0)
+ buffer_len = read_file_contents (filename,
+ buffer, sizeof(buffer) - 1);
+ if (buffer_len <= 0)
return (-1);
- buffer[i] = 0;
-
- fields_len = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
- if (fields_len < 24)
+ buffer[buffer_len] = 0;
+
+ /* The name of the process is enclosed in parens. Since the name can
+ * contain parens itself, spaces, numbers and pretty much everything
+ * else, use these to determine the process name. We don't use
+ * strchr(3) and strrchr(3) to avoid pointer arithmetic which would
+ * otherwise be required to determine name_len. */
+ name_start_pos = 0;
+ while ((buffer[name_start_pos] != '(')
+ && (name_start_pos < buffer_len))
+ name_start_pos++;
+
+ name_end_pos = buffer_len;
+ while ((buffer[name_end_pos] != ')')
+ && (name_end_pos > 0))
+ name_end_pos--;
+
+ /* Either '(' or ')' is not found or they are in the wrong order.
+ * Anyway, something weird that shouldn't happen ever. */
+ if (name_start_pos >= name_end_pos)
{
- DEBUG ("processes plugin: ps_read_process (pid = %i):"
- " `%s' has only %i fields..",
- (int) pid, filename, fields_len);
+ ERROR ("processes plugin: name_start_pos = %zu >= name_end_pos = %zu",
+ name_start_pos, name_end_pos);
return (-1);
}
- /* copy the name, strip brackets in the process */
- name_len = strlen (fields[1]) - 2;
- if ((fields[1][0] != '(') || (fields[1][name_len + 1] != ')'))
+ name_len = (name_end_pos - name_start_pos) - 1;
+ if (name_len >= sizeof (ps->name))
+ name_len = sizeof (ps->name) - 1;
+
+ sstrncpy (ps->name, &buffer[name_start_pos + 1], name_len + 1);
+
+ if ((buffer_len - name_end_pos) < 2)
+ return (-1);
+ buffer_ptr = &buffer[name_end_pos + 2];
+
+ fields_len = strsplit (buffer_ptr, fields, STATIC_ARRAY_SIZE (fields));
+ if (fields_len < 22)
{
- DEBUG ("No brackets found in process name: `%s'", fields[1]);
+ DEBUG ("processes plugin: ps_read_process (pid = %i):"
+ " `%s' has only %i fields..",
+ (int) pid, filename, fields_len);
return (-1);
}
- fields[1] = fields[1] + 1;
- fields[1][name_len] = '\0';
- strncpy (ps->name, fields[1], PROCSTAT_NAME_LEN);
-
- *state = fields[2][0];
+ *state = fields[0][0];
if (*state == 'Z')
{
return (0);
}
- cpu_user_counter = atoll (fields[13]);
- cpu_system_counter = atoll (fields[14]);
- vmem_size = atoll (fields[22]);
- vmem_rss = atoll (fields[23]);
- ps->vmem_minflt_counter = atoll (fields[9]);
- ps->vmem_majflt_counter = atoll (fields[11]);
+ cpu_user_counter = atoll (fields[11]);
+ cpu_system_counter = atoll (fields[12]);
+ vmem_size = atoll (fields[20]);
+ vmem_rss = atoll (fields[21]);
+ ps->vmem_minflt_counter = atol (fields[7]);
+ ps->vmem_majflt_counter = atol (fields[9]);
{
- unsigned long long stack_start = atoll (fields[27]);
- unsigned long long stack_ptr = atoll (fields[28]);
+ unsigned long long stack_start = atoll (fields[25]);
+ unsigned long long stack_ptr = atoll (fields[26]);
stack_size = (stack_start > stack_ptr)
? stack_start - stack_ptr
kvm_t *kd;
char errbuf[1024];
struct kinfo_proc *procs; /* array of processes */
- char **argv;
+ struct kinfo_proc *proc_ptr = NULL;
int count; /* returns number of processes */
int i;
- struct kinfo_proc *proc_ptr = NULL;
-
procstat_t *ps_ptr;
procstat_entry_t pse;
errbuf);
return (0);
}
+
/* Get the list of processes. */
procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count);
if (procs == NULL)
* filter out threads (duplicate PID entries). */
if ((proc_ptr == NULL) || (proc_ptr->ki_pid != procs[i].ki_pid))
{
- char cmdline[ARG_MAX];
+ char cmdline[ARG_MAX] = "";
_Bool have_cmdline = 0;
- memset (cmdline, 0, sizeof (cmdline));
-
proc_ptr = &(procs[i]);
- /* not probe system processes and processes without arguments*/
+ /* Don't probe system processes and processes without arguments */
if (((procs[i].ki_flag & P_SYSTEM) == 0)
- && (procs[i].ki_args != NULL ))
+ && (procs[i].ki_args != NULL))
{
+ char **argv;
+ int argc;
+ int status;
+
/* retrieve the arguments */
argv = kvm_getargv (kd, proc_ptr, /* nchr = */ 0);
- if ( argv != NULL && *argv)
+ argc = 0;
+ if ((argv != NULL) && (argv[0] != NULL))
{
- int status;
- int argc;
-
- argc = 0;
while (argv[argc] != NULL)
argc++;
- status = strjoin (cmdline, sizeof (cmdline),
- argv, argc, " ");
-
+ status = strjoin (cmdline, sizeof (cmdline), argv, argc, " ");
if (status < 0)
WARNING ("processes plugin: Command line did not fit into buffer.");
else
have_cmdline = 1;
-
}
- }
+ } /* if (process has argument list) */
pse.id = procs[i].ki_pid;
pse.age = 0;
case SLOCK: blocked++; break;
case SZOMB: zombies++; break;
}
-
}
kvm_close(kd);
+
ps_submit_state ("running", running);
ps_submit_state ("sleeping", sleeping);
ps_submit_state ("zombies", zombies);
ps_submit_state ("blocked", blocked);
ps_submit_state ("idle", idle);
ps_submit_state ("wait", wait);
+
for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */