+
+static int read_fork_rate ()
+{
+ FILE *proc_stat;
+ char buffer[1024];
+ value_t value;
+ _Bool value_valid = 0;
+
+ proc_stat = fopen ("/proc/stat", "r");
+ if (proc_stat == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("processes plugin: fopen (/proc/stat) failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ while (fgets (buffer, sizeof (buffer), proc_stat) != NULL)
+ {
+ int status;
+ char *fields[3];
+ int fields_num;
+
+ fields_num = strsplit (buffer, fields,
+ STATIC_ARRAY_SIZE (fields));
+ if (fields_num != 2)
+ continue;
+
+ if (strcmp ("processes", fields[0]) != 0)
+ continue;
+
+ status = parse_value (fields[1], &value, DS_TYPE_DERIVE);
+ if (status == 0)
+ value_valid = 1;
+
+ break;
+ }
+ fclose(proc_stat);
+
+ if (!value_valid)
+ return (-1);
+
+ ps_submit_fork_rate (value.derive);
+ return (0);
+}
+#endif /*KERNEL_LINUX */
+
+#if KERNEL_SOLARIS
+static const char *ps_get_cmdline (pid_t pid, /* {{{ */
+ char *buffer, size_t buffer_size)
+{
+ char path[PATH_MAX];
+ psinfo_t info;
+ int status;
+
+ snprintf(path, sizeof (path), "/proc/%i/psinfo", pid);
+
+ status = read_file_contents (path, (void *) &info, sizeof (info));
+ if (status != ((int) buffer_size))
+ {
+ ERROR ("processes plugin: Unexpected return value "
+ "while reading \"%s\": "
+ "Returned %i but expected %zu.",
+ path, status, buffer_size);
+ return (NULL);
+ }
+
+ info.pr_psargs[sizeof (info.pr_psargs) - 1] = 0;
+ sstrncpy (buffer, info.pr_psargs, buffer_size);
+
+ return (buffer);
+} /* }}} int ps_get_cmdline */
+
+/*
+ * Reads process information on the Solaris OS. The information comes mainly from
+ * /proc/PID/status, /proc/PID/psinfo and /proc/PID/usage
+ * The values for input and ouput chars are calculated "by hand"
+ * Added a few "solaris" specific process states as well
+ */
+static int ps_read_process(int pid, procstat_t *ps, char *state)
+{
+ char filename[64];
+ char f_psinfo[64], f_usage[64];
+ char *buffer;
+
+ pstatus_t *myStatus;
+ psinfo_t *myInfo;
+ prusage_t *myUsage;
+
+ snprintf(filename, sizeof (filename), "/proc/%i/status", pid);
+ snprintf(f_psinfo, sizeof (f_psinfo), "/proc/%i/psinfo", pid);
+ snprintf(f_usage, sizeof (f_usage), "/proc/%i/usage", pid);
+
+
+ buffer = malloc(sizeof (pstatus_t));
+ memset(buffer, 0, sizeof (pstatus_t));
+ read_file_contents(filename, buffer, sizeof (pstatus_t));
+ myStatus = (pstatus_t *) buffer;
+
+ buffer = malloc(sizeof (psinfo_t));
+ memset(buffer, 0, sizeof(psinfo_t));
+ read_file_contents(f_psinfo, buffer, sizeof (psinfo_t));
+ myInfo = (psinfo_t *) buffer;
+
+ buffer = malloc(sizeof (prusage_t));
+ memset(buffer, 0, sizeof(prusage_t));
+ read_file_contents(f_usage, buffer, sizeof (prusage_t));
+ myUsage = (prusage_t *) buffer;
+
+ sstrncpy(ps->name, myInfo->pr_fname, sizeof (myInfo->pr_fname));
+ ps->num_lwp = myStatus->pr_nlwp;
+ if (myInfo->pr_wstat != 0) {
+ ps->num_proc = 0;
+ ps->num_lwp = 0;
+ *state = (char) 'Z';
+ return (0);
+ } else {
+ ps->num_proc = 1;
+ ps->num_lwp = myInfo->pr_nlwp;
+ }
+
+ /*
+ * Convert system time and user time from nanoseconds to microseconds
+ * for compatibility with the linux module
+ */
+ ps->cpu_system_counter = myStatus -> pr_stime.tv_nsec / 1000;
+ ps->cpu_user_counter = myStatus -> pr_utime.tv_nsec / 1000;
+
+ /*
+ * Convert rssize from KB to bytes to be consistent w/ the linux module
+ */
+ ps->vmem_rss = myInfo->pr_rssize * 1024;
+ ps->vmem_size = myInfo->pr_size * 1024;
+ ps->vmem_minflt_counter = myUsage->pr_minf;
+ ps->vmem_majflt_counter = myUsage->pr_majf;
+
+ /*
+ * TODO: Data and code segment calculations for Solaris
+ */
+
+ ps->vmem_data = -1;
+ ps->vmem_code = -1;
+ ps->stack_size = myStatus->pr_stksize;
+
+ /*
+ * Calculating input/ouput chars
+ * Formula used is total chars / total blocks => chars/block
+ * then convert input/output blocks to chars
+ */
+ ulong_t tot_chars = myUsage->pr_ioch;
+ ulong_t tot_blocks = myUsage->pr_inblk + myUsage->pr_oublk;
+ ulong_t chars_per_block = 1;
+ if (tot_blocks != 0)
+ chars_per_block = tot_chars / tot_blocks;
+ ps->io_rchar = myUsage->pr_inblk * chars_per_block;
+ ps->io_wchar = myUsage->pr_oublk * chars_per_block;
+ ps->io_syscr = myUsage->pr_sysc;
+ ps->io_syscw = myUsage->pr_sysc;
+
+
+ /*
+ * TODO: Find way of setting BLOCKED and PAGING status
+ */
+
+ *state = (char) 'R';
+ if (myStatus->pr_flags & PR_ASLEEP)
+ *state = (char) 'S';
+ else if (myStatus->pr_flags & PR_STOPPED)
+ *state = (char) 'T';
+ else if (myStatus->pr_flags & PR_DETACH)
+ *state = (char) 'E';
+ else if (myStatus->pr_flags & PR_DAEMON)
+ *state = (char) 'A';
+ else if (myStatus->pr_flags & PR_ISSYS)
+ *state = (char) 'Y';
+ else if (myStatus->pr_flags & PR_ORPHAN)
+ *state = (char) 'O';
+
+ sfree(myStatus);
+ sfree(myInfo);
+ sfree(myUsage);
+
+ return (0);
+}
+
+/*
+ * Reads the number of threads created since the last reboot. On Solaris these
+ * are retrieved from kstat (module cpu, name sys, class misc, stat nthreads).
+ * The result is the sum for all the threads created on each cpu
+ */
+static int read_fork_rate()
+{
+ extern kstat_ctl_t *kc;
+ kstat_t *ksp_chain = NULL;
+ derive_t result = 0;
+
+ if (kc == NULL)
+ return (-1);
+
+ for (ksp_chain = kc->kc_chain;
+ ksp_chain != NULL;
+ ksp_chain = ksp_chain->ks_next)
+ {
+ if ((strcmp (ksp_chain->ks_module, "cpu") == 0)
+ && (strcmp (ksp_chain->ks_name, "sys") == 0)
+ && (strcmp (ksp_chain->ks_class, "misc") == 0))
+ {
+ long long tmp;
+
+ kstat_read (kc, ksp_chain, NULL);
+
+ tmp = get_kstat_value(ksp_chain, "nthreads");
+ if (tmp != -1LL)
+ result += tmp;
+ }
+ }
+
+ ps_submit_fork_rate (result);
+ return (0);
+}
+#endif /* KERNEL_SOLARIS */