summaryrefslogtreecommitdiffstats
path: root/src/ck-sysdeps-solaris.c
diff options
context:
space:
mode:
authorWilliam Jon McCann <mccann@jhu.edu>2007-08-16 22:29:18 -0400
committerWilliam Jon McCann <mccann@jhu.edu>2007-08-16 22:29:18 -0400
commitfcb0f32632f74950c361a0a23128ebca05efdca0 (patch)
tree4e496846ea2b4327e4f8e3dbf4aee74b4321ddc3 /src/ck-sysdeps-solaris.c
parente56a95f64c9c9f57adebf6cb3e6c88790cec40e4 (diff)
move all proc stuff into ck-sysdeps
Diffstat (limited to 'src/ck-sysdeps-solaris.c')
-rw-r--r--src/ck-sysdeps-solaris.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c
new file mode 100644
index 0000000..caea4c7
--- /dev/null
+++ b/src/ck-sysdeps-solaris.c
@@ -0,0 +1,324 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define DEV_ENCODE(M,m) ( \
+ ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \
+)
+
+#include <sys/int_types.h>
+#include <sys/mkdev.h>
+#define _STRUCTURED_PROC 1
+#include <sys/procfs.h>
+#define NO_TTY_VALUE DEV_ENCODE(-1,-1)
+
+#include "ck-sysdeps.h"
+
+/* adapted from procps */
+struct _CkProcessStat
+{
+ int pid;
+ int ppid; /* stat,status pid of parent process */
+ char state; /* stat,status single-char code for process state (S=sleeping) */
+ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */
+ unsigned long long utime; /* stat user-mode CPU time accumulated by process */
+ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */
+ unsigned long long cutime; /* stat cumulative utime of process and reaped children */
+ unsigned long long cstime; /* stat cumulative stime of process and reaped children */
+ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */
+ unsigned long start_code; /* stat address of beginning of code segment */
+ unsigned long end_code; /* stat address of end of code segment */
+ unsigned long start_stack; /* stat address of the bottom of stack for the process */
+ unsigned long kstk_esp; /* stat kernel stack pointer */
+ unsigned long kstk_eip; /* stat kernel instruction pointer */
+ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */
+ long priority; /* stat kernel scheduling priority */
+ long nice; /* stat standard unix nice level of process */
+ long rss; /* stat resident set size from /proc/#/stat (pages) */
+ long alarm; /* stat ? */
+ unsigned long rtprio; /* stat real-time priority */
+ unsigned long sched; /* stat scheduling class */
+ unsigned long vsize; /* stat number of pages of virtual memory ... */
+ unsigned long rss_rlim; /* stat resident set size limit? */
+ unsigned long flags; /* stat kernel flags for the process */
+ unsigned long min_flt; /* stat number of minor page faults since process start */
+ unsigned long maj_flt; /* stat number of major page faults since process start */
+ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */
+ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */
+ int pgrp; /* stat process group id */
+ int session; /* stat session id */
+ int nlwp; /* stat number of threads, or 0 if no clue */
+ int tty; /* stat full device number of controlling terminal */
+ int tpgid; /* stat terminal process group id */
+ int exit_signal; /* stat might not be SIGCHLD */
+ int processor; /* stat current (or most recent?) CPU */
+ uintptr_t penv; /* stat address of initial environment vector */
+ char tty_text[16]; /* stat device name */
+
+};
+
+pid_t
+ck_process_stat_get_ppid (CkProcessStat *stat)
+{
+ g_return_val_if_fail (stat != NULL, -1);
+
+ return stat->ppid;
+}
+
+char *
+ck_process_stat_get_cmd (CkProcessStat *stat)
+{
+ g_return_val_if_fail (stat != NULL, NULL);
+
+ return g_strdup (stat->cmd);
+}
+
+/* adapted from procps */
+char *
+ck_process_stat_get_tty (CkProcessStat *stat)
+{
+ guint dev;
+ char *tty;
+ guint dev_maj;
+ guint dev_min;
+ pid_t pid;
+
+ g_return_val_if_fail (stat != NULL, NULL);
+
+ return stat->tty_text;
+}
+
+/* return 1 if it works, or 0 for failure */
+static gboolean
+stat2proc (pid_t pid,
+ CkProcessStat *P)
+{
+ struct psinfo p;
+ char buf[32];
+ int num;
+ int fd;
+ int tty_maj;
+ int tty_min;
+
+ snprintf (buf, sizeof buf, "/proc/%d/psinfo", pid);
+
+ if ((fd = open (buf, O_RDONLY, 0) ) == -1 ) {
+ return FALSE;
+ }
+
+ num = read (fd, &p, sizeof p);
+ close (fd);
+
+ if (num != sizeof p) {
+ return FALSE;
+ }
+
+ num = PRFNSZ;
+ if (num >= sizeof P->cmd) {
+ num = sizeof P->cmd - 1;
+ }
+
+ memcpy (P->cmd, p.pr_fname, num); /* p.pr_fname or p.pr_lwp.pr_name */
+
+ P->cmd[num] = '\0';
+ P->pid = p.pr_pid;
+ P->ppid = p.pr_ppid;
+ P->pgrp = p.pr_pgid;
+ P->session = p.pr_sid;
+ P->rss = p.pr_rssize;
+ P->vsize = p.pr_size;
+ P->start_time = p.pr_start.tv_sec;
+ P->wchan = p.pr_lwp.pr_wchan;
+ P->state = p.pr_lwp.pr_sname;
+ P->nice = p.pr_lwp.pr_nice;
+ P->priority = p.pr_lwp.pr_pri; /* or pr_oldpri */
+ P->penv = p.pr_envp;
+
+ /* we like it Linux-encoded :-) */
+ tty_maj = major (p.pr_ttydev);
+ tty_min = minor (p.pr_ttydev);
+ P->tty = DEV_ENCODE (tty_maj,tty_min);
+
+ snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min);
+
+ if (tty_maj == 24) {
+ snprintf (P->tty_text, sizeof P->tty_text, "pts/%-3u", tty_min);
+ }
+
+ if (P->tty == NO_TTY_VALUE) {
+ memcpy (P->tty_text, " ? ", 8);
+ }
+
+ if (P->tty == DEV_ENCODE(0,0)) {
+ memcpy (P->tty_text, "console", 8);
+ }
+
+ if (P->pid != pid) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_process_stat_new_for_unix_pid (pid_t pid,
+ CkProcessStat **stat,
+ GError **error)
+{
+ char *path;
+ char *contents;
+ gsize length;
+ gboolean res;
+ GError *local_error;
+ CkProcessStat *proc;
+
+ g_return_val_if_fail (pid > 1, FALSE);
+
+ if (stat == NULL) {
+ return FALSE;
+ }
+
+ proc = g_new0 (CkProcessStat, 1);
+ proc->pid = pid;
+ res = stat2proc (pid, proc);
+ if (res) {
+ *stat = proc;
+ } else {
+ g_propagate_error (error, local_error);
+ *stat = NULL;
+ }
+
+ return res;
+}
+
+void
+ck_process_stat_free (CkProcessStat *stat)
+{
+ g_free (stat);
+}
+
+GHashTable *
+proc_pid_get_env_hash (pid_t pid)
+{
+ GHashTable *hash;
+ gboolean res;
+ CkProcessStat *stat;
+ char *env[400];
+ char buf[BUFSIZ];
+ int fd;
+ int i;
+
+ res = ck_process_stat_new_for_unix_pid (pid, &stat, NULL);
+ if (! res) {
+ goto out;
+ }
+
+ hash = NULL;
+ hash = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_free);
+
+ pread (fd, env, 400, stat->penv);
+
+ i = 0;
+ while (env[i] != NULL && i < 400) {
+ char **vals;
+
+ pread (fd, buf, BUFSIZ, env[i++]);
+
+ vals = g_strsplit (buf, "=", 2);
+ if (vals != NULL) {
+ g_hash_table_insert (hash, vals[0], vals[1]);
+ }
+ }
+
+ out:
+ return hash;
+}
+
+char *
+proc_pid_get_env (pid_t pid,
+ const char *var)
+{
+ GHashTable *hash;
+ char *val;
+
+ hash = proc_pid_get_env_hash (pid);
+ val = g_hash_table_lookup (hash, var);
+
+ return val;
+}
+
+uid_t
+proc_pid_get_uid (pid_t pid)
+{
+ struct stat st;
+ char *path;
+ int uid;
+ int res;
+
+ g_return_val_if_fail (pid > 1, 0);
+
+ uid = -1;
+
+ path = g_strdup_printf ("/proc/%u", (guint)pid);
+ res = stat (path, &st);
+ g_free (path);
+
+ if (res == 0) {
+ uid = st.st_uid;
+ }
+
+ return uid;
+}
+
+pid_t
+proc_pid_get_ppid (pid_t pid)
+{
+ int ppid;
+ gboolean res;
+ CkProcessStat *stat;
+
+ g_return_val_if_fail (pid > 1, 0);
+
+ ppid = -1;
+
+ res = ck_process_stat_new_for_unix_pid (pid, &stat, NULL);
+ if (! res) {
+ goto out;
+ }
+
+ ppid = ck_process_stat_get_ppid (stat);
+
+ ck_process_stat_free (stat);
+
+ out:
+ return ppid;
+}