From fcb0f32632f74950c361a0a23128ebca05efdca0 Mon Sep 17 00:00:00 2001 From: William Jon McCann Date: Thu, 16 Aug 2007 22:29:18 -0400 Subject: move all proc stuff into ck-sysdeps --- src/Makefile.am | 23 +- src/ck-manager.c | 52 ++-- src/ck-sysdeps-linux.c | 605 ++++++++++++++++++++++++++++++++++++++ src/ck-sysdeps-solaris.c | 324 ++++++++++++++++++++ src/ck-sysdeps.h | 49 +++ src/proc-linux.c | 605 -------------------------------------- src/proc-solaris.c | 324 -------------------- src/proc.h | 48 --- tools/Makefile.am | 6 +- tools/ck-collect-session-info.c | 36 +-- tools/ck-get-x11-display-device.c | 18 +- 11 files changed, 1046 insertions(+), 1044 deletions(-) create mode 100644 src/ck-sysdeps-linux.c create mode 100644 src/ck-sysdeps-solaris.c create mode 100644 src/ck-sysdeps.h delete mode 100644 src/proc-linux.c delete mode 100644 src/proc-solaris.c delete mode 100644 src/proc.h diff --git a/src/Makefile.am b/src/Makefile.am index c63abf3..948b247 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,27 +24,27 @@ INCLUDES = \ $(NULL) noinst_LTLIBRARIES = \ - libckproc.la \ + libck.la \ $(NULL) -libckproc_la_SOURCES = \ - proc.h \ +libck_la_SOURCES = \ + ck-sysdeps.h \ $(NULL) if CK_COMPILE_LINUX -libckproc_la_SOURCES += \ - proc-linux.c \ +libck_la_SOURCES += \ + ck-sysdeps-linux.c \ $(NULL) endif if CK_COMPILE_SOLARIS -libckproc_la_SOURCES += \ - proc-solaris.c \ +libck_la_SOURCES += \ + ck-sysdeps-solaris.c \ $(NULL) endif -EXTRA_libckproc_la_SOURCES = \ - proc-linux.c \ - proc-solaris.c \ +EXTRA_libck_la_SOURCES = \ + ck-sysdeps-linux.c \ + ck-sysdeps-solaris.c \ $(NULL) sbin_PROGRAMS = \ @@ -91,7 +91,6 @@ console_kit_daemon_SOURCES = \ ck-log.h \ ck-log.c \ getfd.c \ - proc.h \ $(BUILT_SOURCES) \ $(NULL) @@ -110,7 +109,7 @@ EXTRA_console_kit_daemon_SOURCES = \ console_kit_daemon_LDADD = \ $(CONSOLE_KIT_LIBS) \ - libckproc.la \ + libck.la \ $(NULL) noinst_PROGRAMS = \ diff --git a/src/ck-manager.c b/src/ck-manager.c index 3007437..506249b 100644 --- a/src/ck-manager.c +++ b/src/ck-manager.c @@ -43,7 +43,7 @@ #include "ck-job.h" #include "ck-marshal.h" -#include "proc.h" +#include "ck-sysdeps.h" #define CK_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_MANAGER, CkManagerPrivate)) @@ -933,15 +933,15 @@ ck_manager_get_session_for_cookie (CkManager *manager, const char *cookie, DBusGMethodInvocation *context) { - gboolean res; - char *sender; - uid_t calling_uid; - pid_t calling_pid; - proc_stat_t *stat; - char *ssid; - CkSession *session; - LeaderInfo *leader_info; - GError *local_error; + gboolean res; + char *sender; + uid_t calling_uid; + pid_t calling_pid; + CkProcessStat *stat; + char *ssid; + CkSession *session; + LeaderInfo *leader_info; + GError *local_error; ssid = NULL; @@ -964,7 +964,7 @@ ck_manager_get_session_for_cookie (CkManager *manager, } local_error = NULL; - res = proc_stat_new_for_pid (calling_pid, &stat, &local_error); + res = ck_process_stat_new_for_unix_pid (calling_pid, &stat, &local_error); if (! res) { GError *error; error = g_error_new (CK_MANAGER_ERROR, @@ -982,7 +982,7 @@ ck_manager_get_session_for_cookie (CkManager *manager, } /* FIXME: should we restrict this by uid? */ - proc_stat_free (stat); + ck_process_stat_free (stat); leader_info = g_hash_table_lookup (manager->priv->leaders, cookie); if (leader_info == NULL) { @@ -1023,7 +1023,7 @@ get_cookie_for_pid (CkManager *manager, /* FIXME: need a better way to get the cookie */ - cookie = proc_pid_get_env (pid, "XDG_SESSION_COOKIE"); + cookie = ck_unix_pid_get_env (pid, "XDG_SESSION_COOKIE"); return cookie; } @@ -1040,13 +1040,13 @@ ck_manager_get_session_for_unix_process (CkManager *manager, guint pid, DBusGMethodInvocation *context) { - gboolean res; - char *sender; - uid_t calling_uid; - pid_t calling_pid; - proc_stat_t *stat; - char *cookie; - GError *error; + gboolean res; + char *sender; + uid_t calling_uid; + pid_t calling_pid; + CkProcessStat *stat; + char *cookie; + GError *error; sender = dbus_g_method_get_sender (context); @@ -1067,7 +1067,7 @@ ck_manager_get_session_for_unix_process (CkManager *manager, } error = NULL; - res = proc_stat_new_for_pid (calling_pid, &stat, &error); + res = ck_process_stat_new_for_unix_pid (calling_pid, &stat, &error); if (! res) { GError *error; g_debug ("stat on pid %d failed", calling_pid); @@ -1082,7 +1082,7 @@ ck_manager_get_session_for_unix_process (CkManager *manager, /* FIXME: check stuff? */ - proc_stat_free (stat); + ck_process_stat_free (stat); cookie = get_cookie_for_pid (manager, pid); if (cookie == NULL) { @@ -1572,9 +1572,9 @@ add_seat_for_file (CkManager *manager, static gboolean load_seats_from_dir (CkManager *manager) { - GDir *d; - GError *error; - char *file; + GDir *d; + GError *error; + const char *file; error = NULL; d = g_dir_open (CK_SEAT_DIR, @@ -1594,6 +1594,8 @@ load_seats_from_dir (CkManager *manager) } g_dir_close (d); + + return TRUE; } static void diff --git a/src/ck-sysdeps-linux.c b/src/ck-sysdeps-linux.c new file mode 100644 index 0000000..624bfc4 --- /dev/null +++ b/src/ck-sysdeps-linux.c @@ -0,0 +1,605 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2006 William Jon McCann + * + * 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 +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_PATHS_H +#include +#endif /* HAVE_PATHS_H */ + +#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 */ +}; + +/* adapted from procps */ +#define MAJOR_OF(d) ( ((unsigned)(d)>>8u) & 0xfffu ) +#define MINOR_OF(d) ( ((unsigned)(d)&0xffu) | (((unsigned)(d)&0xfff00000u)>>12u) ) + +typedef struct tty_map_node { + struct tty_map_node *next; + guint major_number; + guint minor_first; + guint minor_last; + char name[16]; + char devfs_type; +} tty_map_node; + +static tty_map_node *tty_map = NULL; + +/* adapted from procps */ +/* Load /proc/tty/drivers for device name mapping use. */ +static void +load_drivers (void) +{ + char buf[10000]; + char *p; + int fd; + int bytes; + + fd = open ("/proc/tty/drivers", O_RDONLY); + if (fd == -1) { + goto fail; + } + + bytes = read (fd, buf, sizeof (buf) - 1); + if (bytes == -1) { + goto fail; + } + + buf[bytes] = '\0'; + p = buf; + while ((p = strstr (p, " " _PATH_DEV))) { + tty_map_node *tmn; + int len; + char *end; + + p += 6; + end = strchr (p, ' '); + if (! end) { + continue; + } + len = end - p; + tmn = calloc (1, sizeof (tty_map_node)); + tmn->next = tty_map; + tty_map = tmn; + /* if we have a devfs type name such as /dev/tts/%d then strip the %d but + keep a flag. */ + if (len >= 3 && !strncmp (end - 2, "%d", 2)) { + len -= 2; + tmn->devfs_type = 1; + } + strncpy (tmn->name, p, len); + p = end; /* set p to point past the %d as well if there is one */ + while (*p == ' ') { + p++; + } + + tmn->major_number = atoi (p); + p += strspn (p, "0123456789"); + while (*p == ' ') { + p++; + } + switch (sscanf (p, "%u-%u", &tmn->minor_first, &tmn->minor_last)) { + default: + /* Can't finish parsing this line so we remove it from the list */ + tty_map = tty_map->next; + free (tmn); + break; + case 1: + tmn->minor_last = tmn->minor_first; + break; + case 2: + break; + } + } + fail: + if (fd != -1) { + close (fd); + } + if(! tty_map) { + tty_map = (tty_map_node *)-1; + } +} + +/* adapted from procps */ +/* Try to guess the device name from /proc/tty/drivers info. */ +static char * +driver_name (guint maj, + guint min) +{ + struct stat sbuf; + tty_map_node *tmn; + char *tty; + + if (! tty_map) { + load_drivers (); + } + if (tty_map == (tty_map_node *) - 1) { + return 0; + } + + tmn = tty_map; + for (;;) { + if (! tmn) { + return 0; + } + if (tmn->major_number == maj && tmn->minor_first <= min && tmn->minor_last >= min) { + break; + } + tmn = tmn->next; + } + + tty = g_strdup_printf (_PATH_DEV "%s%d", tmn->name, min); /* like "/dev/ttyZZ255" */ + if (stat (tty, &sbuf) < 0){ + g_free (tty); + + if (tmn->devfs_type) { + return NULL; + } + + tty = g_strdup_printf (_PATH_DEV "%s", tmn->name); /* like "/dev/ttyZZ255" */ + + if (stat (tty, &sbuf) < 0) { + g_free (tty); + return NULL; + } + } + + if (min != MINOR_OF (sbuf.st_rdev)) { + g_free (tty); + return NULL; + } + + if (maj != MAJOR_OF (sbuf.st_rdev)) { + g_free (tty); + return NULL; + } + + return tty; +} + +/* adapted from procps */ +static char * +link_name (guint maj, + guint min, + int pid, + const char *name) +{ + struct stat sbuf; + char *path; + char *tty; + + path = g_strdup_printf ("/proc/%d/%s", pid, name); + tty = g_file_read_link (path, NULL); + g_free (path); + + if (tty == NULL) { + goto out; + } + + if (stat (tty, &sbuf) < 0) { + g_free (tty); + tty = NULL; + goto out; + } + + if (min != MINOR_OF (sbuf.st_rdev)) { + g_free (tty); + tty = NULL; + goto out; + + } + if (maj != MAJOR_OF (sbuf.st_rdev)) { + g_free (tty); + tty = NULL; + goto out; + } + + out: + return tty; +} + +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); + + pid = stat->pid; + dev = stat->tty; + + if (dev == 0u) { + return NULL; + } + + dev_maj = MAJOR_OF (dev); + dev_min = MINOR_OF (dev); + + tty = link_name (dev_maj, dev_min, pid, "tty"); + if (tty != NULL) { + goto out; + } + + tty = driver_name (dev_maj, dev_min); + if (tty != NULL) { + goto out; + } + + tty = link_name (dev_maj, dev_min, pid, "fd/2"); + if (tty != NULL) { + goto out; + } + + tty = link_name (dev_maj, dev_min, pid, "fd/255"); + if (tty != NULL) { + goto out; + } + + out: + + return tty; +} + +#define KLF "l" +/* adapted from procps */ +static void +stat2proc (const char *S, + CkProcessStat *P) +{ + unsigned num; + char * tmp; + + /* fill in default values for older kernels */ + P->processor = 0; + P->rtprio = -1; + P->sched = -1; + P->nlwp = 0; + + S = strchr (S, '(') + 1; + tmp = strrchr (S, ')'); + num = tmp - S; + if (G_UNLIKELY (num >= sizeof P->cmd)) { + num = sizeof P->cmd - 1; + } + + memcpy (P->cmd, S, num); + P->cmd[num] = '\0'; + S = tmp + 2; /* skip ") " */ + + num = sscanf (S, + "%c " + "%d %d %d %d %d " + "%lu %lu %lu %lu %lu " + "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ + "%ld %ld " + "%d " + "%ld " + "%Lu " /* start_time */ + "%lu " + "%ld " + "%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u " + "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ + "%"KLF"u %*lu %*lu " + "%d %d " + "%lu %lu", + &P->state, + &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, + &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, + &P->utime, &P->stime, &P->cutime, &P->cstime, + &P->priority, &P->nice, + &P->nlwp, + &P->alarm, + &P->start_time, + &P->vsize, + &P->rss, + &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip, + /* P->signal, P->blocked, P->sigignore, P->sigcatch, */ /* can't use */ + &P->wchan, /* &P->nswap, &P->cnswap, */ /* nswap and cnswap dead for 2.4.xx and up */ + /* -- Linux 2.0.35 ends here -- */ + &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */ + /* -- Linux 2.2.8 to 2.5.17 end here -- */ + &P->rtprio, &P->sched /* both added to 2.5.18 */ + ); + + if (!P->nlwp){ + P->nlwp = 1; + } +} + +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; + } + + path = g_strdup_printf ("/proc/%d/stat", pid); + + contents = NULL; + local_error = NULL; + res = g_file_get_contents (path, + &contents, + &length, + &local_error); + if (res) { + proc = g_new0 (CkProcessStat, 1); + proc->pid = pid; + stat2proc (contents, proc); + *stat = proc; + } else { + g_propagate_error (error, local_error); + *stat = NULL; + } + + g_free (contents); + g_free (path); + + return res; +} + +void +ck_process_stat_free (CkProcessStat *stat) +{ + g_free (stat); +} + +GHashTable * +ck_unix_pid_get_env_hash (pid_t pid) +{ + char *path; + gboolean res; + char *contents; + gsize length; + GError *error; + GHashTable *hash; + int i; + gboolean last_was_null; + + g_return_val_if_fail (pid > 1, NULL); + + contents = NULL; + hash = NULL; + + path = g_strdup_printf ("/proc/%u/environ", (guint)pid); + + error = NULL; + res = g_file_get_contents (path, + &contents, + &length, + &error); + if (! res) { + g_warning ("Couldn't read %s: %s", path, error->message); + g_error_free (error); + goto out; + } + + hash = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + + last_was_null = TRUE; + for (i = 0; i < length; i++) { + if (contents[i] == '\0') { + last_was_null = TRUE; + continue; + } + if (last_was_null) { + char **vals; + vals = g_strsplit (contents + i, "=", 2); + if (vals != NULL) { + g_hash_table_insert (hash, vals[0], vals[1]); + } + } + last_was_null = FALSE; + } + + out: + g_free (contents); + g_free (path); + + return hash; +} + +char * +ck_unix_pid_get_env (pid_t pid, + const char *var) +{ + char *path; + gboolean res; + char *contents; + char *val; + gsize length; + GError *error; + int i; + char *prefix; + int prefix_len; + gboolean last_was_null; + + g_return_val_if_fail (pid > 1, NULL); + + val = NULL; + contents = NULL; + prefix = NULL; + + path = g_strdup_printf ("/proc/%u/environ", (guint)pid); + + error = NULL; + res = g_file_get_contents (path, + &contents, + &length, + &error); + if (! res) { + g_warning ("Couldn't read %s: %s", path, error->message); + g_error_free (error); + goto out; + } + + + prefix = g_strdup_printf ("%s=", var); + prefix_len = strlen (prefix); + + /* FIXME: make more robust */ + last_was_null = TRUE; + for (i = 0; i < length; i++) { + if (contents[i] == '\0') { + last_was_null = TRUE; + continue; + } + if (last_was_null && g_str_has_prefix (contents + i, prefix)) { + val = g_strdup (contents + i + prefix_len); + break; + } + last_was_null = FALSE; + } + + out: + g_free (prefix); + g_free (contents); + g_free (path); + + return val; +} + +uid_t +ck_unix_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 +ck_unix_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; +} 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 + * + * 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 +#include +#include +#include +#include +#include +#include + +#define DEV_ENCODE(M,m) ( \ + ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ +) + +#include +#include +#define _STRUCTURED_PROC 1 +#include +#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; +} diff --git a/src/ck-sysdeps.h b/src/ck-sysdeps.h new file mode 100644 index 0000000..7a5f768 --- /dev/null +++ b/src/ck-sysdeps.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2006 William Jon McCann + * + * 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. + * + */ + +#ifndef __CK_SYSDEPS_H +#define __CK_SYSDEPS_H + +#include + +G_BEGIN_DECLS + +typedef struct _CkProcessStat CkProcessStat; + +gboolean ck_process_stat_new_for_unix_pid (pid_t pid, + CkProcessStat **stat, + GError **error); +pid_t ck_process_stat_get_ppid (CkProcessStat *stat); +char *ck_process_stat_get_tty (CkProcessStat *stat); +char *ck_process_stat_get_cmd (CkProcessStat *stat); +void ck_process_stat_free (CkProcessStat *stat); + + +char *ck_unix_pid_get_env (pid_t pid, + const char *var); + +GHashTable *ck_unix_pid_get_env_hash (pid_t pid); + +pid_t ck_unix_pid_get_ppid (pid_t pid); +uid_t ck_unix_pid_get_uid (pid_t pid); + +G_END_DECLS + +#endif /* __CK_SYSDEPS_H */ diff --git a/src/proc-linux.c b/src/proc-linux.c deleted file mode 100644 index d704e18..0000000 --- a/src/proc-linux.c +++ /dev/null @@ -1,605 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2006 William Jon McCann - * - * 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 -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_PATHS_H -#include -#endif /* HAVE_PATHS_H */ - -#include "proc.h" - -/* adapted from procps */ -struct _proc_stat_t -{ - 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 */ -}; - -/* adapted from procps */ -#define MAJOR_OF(d) ( ((unsigned)(d)>>8u) & 0xfffu ) -#define MINOR_OF(d) ( ((unsigned)(d)&0xffu) | (((unsigned)(d)&0xfff00000u)>>12u) ) - -typedef struct tty_map_node { - struct tty_map_node *next; - guint major_number; - guint minor_first; - guint minor_last; - char name[16]; - char devfs_type; -} tty_map_node; - -static tty_map_node *tty_map = NULL; - -/* adapted from procps */ -/* Load /proc/tty/drivers for device name mapping use. */ -static void -load_drivers (void) -{ - char buf[10000]; - char *p; - int fd; - int bytes; - - fd = open ("/proc/tty/drivers", O_RDONLY); - if (fd == -1) { - goto fail; - } - - bytes = read (fd, buf, sizeof (buf) - 1); - if (bytes == -1) { - goto fail; - } - - buf[bytes] = '\0'; - p = buf; - while ((p = strstr (p, " " _PATH_DEV))){ - tty_map_node *tmn; - int len; - char *end; - - p += 6; - end = strchr (p, ' '); - if (! end) { - continue; - } - len = end - p; - tmn = calloc (1, sizeof (tty_map_node)); - tmn->next = tty_map; - tty_map = tmn; - /* if we have a devfs type name such as /dev/tts/%d then strip the %d but - keep a flag. */ - if (len >= 3 && !strncmp (end - 2, "%d", 2)) { - len -= 2; - tmn->devfs_type = 1; - } - strncpy (tmn->name, p, len); - p = end; /* set p to point past the %d as well if there is one */ - while (*p == ' ') { - p++; - } - - tmn->major_number = atoi (p); - p += strspn (p, "0123456789"); - while (*p == ' ') { - p++; - } - switch (sscanf (p, "%u-%u", &tmn->minor_first, &tmn->minor_last)) { - default: - /* Can't finish parsing this line so we remove it from the list */ - tty_map = tty_map->next; - free (tmn); - break; - case 1: - tmn->minor_last = tmn->minor_first; - break; - case 2: - break; - } - } - fail: - if (fd != -1) { - close (fd); - } - if(! tty_map) { - tty_map = (tty_map_node *)-1; - } -} - -/* adapted from procps */ -/* Try to guess the device name from /proc/tty/drivers info. */ -static char * -driver_name (guint maj, - guint min) -{ - struct stat sbuf; - tty_map_node *tmn; - char *tty; - - if (! tty_map) { - load_drivers (); - } - if (tty_map == (tty_map_node *) - 1) { - return 0; - } - - tmn = tty_map; - for (;;) { - if (! tmn) { - return 0; - } - if (tmn->major_number == maj && tmn->minor_first <= min && tmn->minor_last >= min) { - break; - } - tmn = tmn->next; - } - - tty = g_strdup_printf (_PATH_DEV "%s%d", tmn->name, min); /* like "/dev/ttyZZ255" */ - if (stat (tty, &sbuf) < 0){ - g_free (tty); - - if (tmn->devfs_type) { - return NULL; - } - - tty = g_strdup_printf (_PATH_DEV "%s", tmn->name); /* like "/dev/ttyZZ255" */ - - if (stat (tty, &sbuf) < 0) { - g_free (tty); - return NULL; - } - } - - if (min != MINOR_OF (sbuf.st_rdev)) { - g_free (tty); - return NULL; - } - - if (maj != MAJOR_OF (sbuf.st_rdev)) { - g_free (tty); - return NULL; - } - - return tty; -} - -/* adapted from procps */ -static char * -link_name (guint maj, - guint min, - int pid, - const char *name) -{ - struct stat sbuf; - char *path; - char *tty; - - path = g_strdup_printf ("/proc/%d/%s", pid, name); - tty = g_file_read_link (path, NULL); - g_free (path); - - if (tty == NULL) { - goto out; - } - - if (stat (tty, &sbuf) < 0) { - g_free (tty); - tty = NULL; - goto out; - } - - if (min != MINOR_OF (sbuf.st_rdev)) { - g_free (tty); - tty = NULL; - goto out; - - } - if (maj != MAJOR_OF (sbuf.st_rdev)) { - g_free (tty); - tty = NULL; - goto out; - } - - out: - return tty; -} - -pid_t -proc_stat_get_ppid (proc_stat_t *stat) -{ - g_return_val_if_fail (stat != NULL, -1); - - return stat->ppid; -} - -char * -proc_stat_get_cmd (proc_stat_t *stat) -{ - g_return_val_if_fail (stat != NULL, NULL); - - return g_strdup (stat->cmd); -} - -/* adapted from procps */ -char * -proc_stat_get_tty (proc_stat_t *stat) -{ - guint dev; - char *tty; - guint dev_maj; - guint dev_min; - pid_t pid; - - g_return_val_if_fail (stat != NULL, NULL); - - pid = stat->pid; - dev = stat->tty; - - if (dev == 0u) { - return NULL; - } - - dev_maj = MAJOR_OF (dev); - dev_min = MINOR_OF (dev); - - tty = link_name (dev_maj, dev_min, pid, "tty"); - if (tty != NULL) { - goto out; - } - - tty = driver_name (dev_maj, dev_min); - if (tty != NULL) { - goto out; - } - - tty = link_name (dev_maj, dev_min, pid, "fd/2"); - if (tty != NULL) { - goto out; - } - - tty = link_name (dev_maj, dev_min, pid, "fd/255"); - if (tty != NULL) { - goto out; - } - - out: - - return tty; -} - -#define KLF "l" -/* adapted from procps */ -static void -stat2proc (const char *S, - proc_stat_t *P) -{ - unsigned num; - char * tmp; - - /* fill in default values for older kernels */ - P->processor = 0; - P->rtprio = -1; - P->sched = -1; - P->nlwp = 0; - - S = strchr (S, '(') + 1; - tmp = strrchr (S, ')'); - num = tmp - S; - if (G_UNLIKELY (num >= sizeof P->cmd)) { - num = sizeof P->cmd - 1; - } - - memcpy (P->cmd, S, num); - P->cmd[num] = '\0'; - S = tmp + 2; /* skip ") " */ - - num = sscanf (S, - "%c " - "%d %d %d %d %d " - "%lu %lu %lu %lu %lu " - "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ - "%ld %ld " - "%d " - "%ld " - "%Lu " /* start_time */ - "%lu " - "%ld " - "%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u " - "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ - "%"KLF"u %*lu %*lu " - "%d %d " - "%lu %lu", - &P->state, - &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, - &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, - &P->utime, &P->stime, &P->cutime, &P->cstime, - &P->priority, &P->nice, - &P->nlwp, - &P->alarm, - &P->start_time, - &P->vsize, - &P->rss, - &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip, - /* P->signal, P->blocked, P->sigignore, P->sigcatch, */ /* can't use */ - &P->wchan, /* &P->nswap, &P->cnswap, */ /* nswap and cnswap dead for 2.4.xx and up */ - /* -- Linux 2.0.35 ends here -- */ - &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */ - /* -- Linux 2.2.8 to 2.5.17 end here -- */ - &P->rtprio, &P->sched /* both added to 2.5.18 */ - ); - - if (!P->nlwp){ - P->nlwp = 1; - } -} - -gboolean -proc_stat_new_for_pid (pid_t pid, - proc_stat_t **stat, - GError **error) -{ - char *path; - char *contents; - gsize length; - gboolean res; - GError *local_error; - proc_stat_t *proc; - - g_return_val_if_fail (pid > 1, FALSE); - - if (stat == NULL) { - return FALSE; - } - - path = g_strdup_printf ("/proc/%d/stat", pid); - - contents = NULL; - local_error = NULL; - res = g_file_get_contents (path, - &contents, - &length, - &local_error); - if (res) { - proc = g_new0 (proc_stat_t, 1); - proc->pid = pid; - stat2proc (contents, proc); - *stat = proc; - } else { - g_propagate_error (error, local_error); - *stat = NULL; - } - - g_free (contents); - g_free (path); - - return res; -} - -void -proc_stat_free (proc_stat_t *stat) -{ - g_free (stat); -} - -GHashTable * -proc_pid_get_env_hash (pid_t pid) -{ - char *path; - gboolean res; - char *contents; - gsize length; - GError *error; - GHashTable *hash; - int i; - gboolean last_was_null; - - g_return_val_if_fail (pid > 1, NULL); - - contents = NULL; - hash = NULL; - - path = g_strdup_printf ("/proc/%u/environ", (guint)pid); - - error = NULL; - res = g_file_get_contents (path, - &contents, - &length, - &error); - if (! res) { - g_warning ("Couldn't read %s: %s", path, error->message); - g_error_free (error); - goto out; - } - - hash = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); - - last_was_null = TRUE; - for (i = 0; i < length; i++) { - if (contents[i] == '\0') { - last_was_null = TRUE; - continue; - } - if (last_was_null) { - char **vals; - vals = g_strsplit (contents + i, "=", 2); - if (vals != NULL) { - g_hash_table_insert (hash, vals[0], vals[1]); - } - } - last_was_null = FALSE; - } - - out: - g_free (contents); - g_free (path); - - return hash; -} - -char * -proc_pid_get_env (pid_t pid, - const char *var) -{ - char *path; - gboolean res; - char *contents; - char *val; - gsize length; - GError *error; - int i; - char *prefix; - int prefix_len; - gboolean last_was_null; - - g_return_val_if_fail (pid > 1, NULL); - - val = NULL; - contents = NULL; - prefix = NULL; - - path = g_strdup_printf ("/proc/%u/environ", (guint)pid); - - error = NULL; - res = g_file_get_contents (path, - &contents, - &length, - &error); - if (! res) { - g_warning ("Couldn't read %s: %s", path, error->message); - g_error_free (error); - goto out; - } - - - prefix = g_strdup_printf ("%s=", var); - prefix_len = strlen (prefix); - - /* FIXME: make more robust */ - last_was_null = TRUE; - for (i = 0; i < length; i++) { - if (contents[i] == '\0') { - last_was_null = TRUE; - continue; - } - if (last_was_null && g_str_has_prefix (contents + i, prefix)) { - val = g_strdup (contents + i + prefix_len); - break; - } - last_was_null = FALSE; - } - - out: - g_free (prefix); - g_free (contents); - g_free (path); - - 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; - proc_stat_t *stat; - - g_return_val_if_fail (pid > 1, 0); - - ppid = -1; - - res = proc_stat_new_for_pid (pid, &stat, NULL); - if (! res) { - goto out; - } - - ppid = proc_stat_get_ppid (stat); - - proc_stat_free (stat); - - out: - return ppid; -} diff --git a/src/proc-solaris.c b/src/proc-solaris.c deleted file mode 100644 index f95c042..0000000 --- a/src/proc-solaris.c +++ /dev/null @@ -1,324 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2006 William Jon McCann - * - * 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 -#include -#include -#include -#include -#include -#include - -#define DEV_ENCODE(M,m) ( \ - ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ -) - -#include -#include -#define _STRUCTURED_PROC 1 -#include -#define NO_TTY_VALUE DEV_ENCODE(-1,-1) - -#include "proc.h" - -/* adapted from procps */ -struct _proc_stat_t -{ - 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 -proc_stat_get_ppid (proc_stat_t *stat) -{ - g_return_val_if_fail (stat != NULL, -1); - - return stat->ppid; -} - -char * -proc_stat_get_cmd (proc_stat_t *stat) -{ - g_return_val_if_fail (stat != NULL, NULL); - - return g_strdup (stat->cmd); -} - -/* adapted from procps */ -char * -proc_stat_get_tty (proc_stat_t *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, - proc_stat_t *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 -proc_stat_new_for_pid (pid_t pid, - proc_stat_t **stat, - GError **error) -{ - char *path; - char *contents; - gsize length; - gboolean res; - GError *local_error; - proc_stat_t *proc; - - g_return_val_if_fail (pid > 1, FALSE); - - if (stat == NULL) { - return FALSE; - } - - proc = g_new0 (proc_stat_t, 1); - proc->pid = pid; - res = stat2proc (pid, proc); - if (res) { - *stat = proc; - } else { - g_propagate_error (error, local_error); - *stat = NULL; - } - - return res; -} - -void -proc_stat_free (proc_stat_t *stat) -{ - g_free (stat); -} - -GHashTable * -proc_pid_get_env_hash (pid_t pid) -{ - GHashTable *hash; - gboolean res; - proc_stat_t *stat; - char *env[400]; - char buf[BUFSIZ]; - int fd; - int i; - - res = proc_stat_new_for_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; - proc_stat_t *stat; - - g_return_val_if_fail (pid > 1, 0); - - ppid = -1; - - res = proc_stat_new_for_pid (pid, &stat, NULL); - if (! res) { - goto out; - } - - ppid = proc_stat_get_ppid (stat); - - proc_stat_free (stat); - - out: - return ppid; -} diff --git a/src/proc.h b/src/proc.h deleted file mode 100644 index 8c3fc64..0000000 --- a/src/proc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2006 William Jon McCann - * - * 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. - * - */ - -#ifndef __PROC_H -#define __PROC_H - -#include - -G_BEGIN_DECLS - -typedef struct _proc_stat_t proc_stat_t; - -gboolean proc_stat_new_for_pid (pid_t pid, - proc_stat_t **stat, - GError **error); -pid_t proc_stat_get_ppid (proc_stat_t *stat); -char *proc_stat_get_tty (proc_stat_t *stat); -char *proc_stat_get_cmd (proc_stat_t *stat); -void proc_stat_free (proc_stat_t *stat); - -char *proc_pid_get_env (pid_t pid, - const char *var); - -GHashTable *proc_pid_get_env_hash (pid_t pid); - -pid_t proc_pid_get_ppid (pid_t pid); -uid_t proc_pid_get_uid (pid_t pid); - -G_END_DECLS - -#endif /* __PROC_H */ diff --git a/tools/Makefile.am b/tools/Makefile.am index 98783eb..5283e18 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -56,7 +56,7 @@ ck_collect_session_info_SOURCES = \ ck_collect_session_info_LDADD = \ $(TOOLS_LIBS) \ - $(top_builddir)/src/libckproc.la\ + $(top_builddir)/src/libck.la \ $(NULL) ck_get_x11_server_pid_SOURCES = \ @@ -65,7 +65,7 @@ ck_get_x11_server_pid_SOURCES = \ ck_get_x11_server_pid_LDADD = \ $(TOOLS_LIBS) \ - $(top_builddir)/src/libckproc.la\ + $(top_builddir)/src/libck.la \ $(NULL) ck_get_x11_display_device_SOURCES = \ @@ -74,7 +74,7 @@ ck_get_x11_display_device_SOURCES = \ ck_get_x11_display_device_LDADD = \ $(TOOLS_LIBS) \ - $(top_builddir)/src/libckproc.la\ + $(top_builddir)/src/libck.la \ $(NULL) diff --git a/tools/ck-collect-session-info.c b/tools/ck-collect-session-info.c index 5e8e07d..45abb07 100644 --- a/tools/ck-collect-session-info.c +++ b/tools/ck-collect-session-info.c @@ -32,7 +32,7 @@ #include -#include "proc.h" +#include "ck-sysdeps.h" typedef struct { uid_t uid; @@ -108,7 +108,7 @@ get_filtered_environment (pid_t pid) g_ptr_array_add (env, g_strdup ("PATH=/bin:/usr/bin")); - hash = proc_pid_get_env_hash (pid); + hash = ck_unix_pid_get_env_hash (pid); for (i = 0; i < G_N_ELEMENTS (allowed_env_vars); i++) { const char *var; @@ -221,14 +221,14 @@ get_x11_server_pid (SessionInfo *si, static void fill_x11_info (SessionInfo *si) { - guint xorg_pid; - gboolean can_connect; - gboolean res; - proc_stat_t *xorg_stat; - GError *error; + guint xorg_pid; + gboolean can_connect; + gboolean res; + CkProcessStat *xorg_stat; + GError *error; /* assume this is true then check it */ - si->x11_display = proc_pid_get_env (si->pid, "DISPLAY"); + si->x11_display = ck_unix_pid_get_env (si->pid, "DISPLAY"); if (si->x11_display == NULL) { /* no point continuing */ @@ -261,7 +261,7 @@ fill_x11_info (SessionInfo *si) } error = NULL; - res = proc_stat_new_for_pid (xorg_pid, &xorg_stat, &error); + res = ck_process_stat_new_for_unix_pid (xorg_pid, &xorg_stat, &error); if (! res) { if (error != NULL) { g_warning ("stat on pid %d failed: %s", xorg_pid, error->message); @@ -271,8 +271,8 @@ fill_x11_info (SessionInfo *si) return; } - si->x11_display_device = proc_stat_get_tty (xorg_stat); - proc_stat_free (xorg_stat); + si->x11_display_device = ck_process_stat_get_tty (xorg_stat); + ck_process_stat_free (xorg_stat); si->is_local = TRUE; si->is_local_is_set = TRUE; @@ -284,12 +284,12 @@ fill_x11_info (SessionInfo *si) static gboolean fill_session_info (SessionInfo *si) { - proc_stat_t *stat; - GError *error; - gboolean res; + CkProcessStat *stat; + GError *error; + gboolean res; error = NULL; - res = proc_stat_new_for_pid (si->pid, &stat, &error); + res = ck_process_stat_new_for_unix_pid (si->pid, &stat, &error); if (! res) { if (error != NULL) { g_warning ("stat on pid %d failed: %s", si->pid, error->message); @@ -299,9 +299,9 @@ fill_session_info (SessionInfo *si) return FALSE; } - si->display_device = proc_stat_get_tty (stat); - si->session_type = proc_stat_get_cmd (stat); - proc_stat_free (stat); + si->display_device = ck_process_stat_get_tty (stat); + si->session_type = ck_process_stat_get_cmd (stat); + ck_process_stat_free (stat); fill_x11_info (si); diff --git a/tools/ck-get-x11-display-device.c b/tools/ck-get-x11-display-device.c index 2d414c6..92a7936 100644 --- a/tools/ck-get-x11-display-device.c +++ b/tools/ck-get-x11-display-device.c @@ -32,18 +32,18 @@ #include #include -#include "proc.h" +#include "ck-sysdeps.h" static char * get_tty_for_pid (int pid) { - GError *error; - char *device; - gboolean res; - proc_stat_t *xorg_stat; + GError *error; + char *device; + gboolean res; + CkProcessStat *xorg_stat; error = NULL; - res = proc_stat_new_for_pid (pid, &xorg_stat, &error); + res = ck_process_stat_new_for_unix_pid (pid, &xorg_stat, &error); if (! res) { if (error != NULL) { g_warning ("stat on pid %d failed: %s", pid, error->message); @@ -53,8 +53,8 @@ get_tty_for_pid (int pid) return NULL; } - device = proc_stat_get_tty (xorg_stat); - proc_stat_free (xorg_stat); + device = ck_process_stat_get_tty (xorg_stat); + ck_process_stat_free (xorg_stat); return device; } @@ -84,7 +84,7 @@ get_peer_pid (int fd) } static Display * -display_init (char *display_name) +display_init (const char *display_name) { Display *xdisplay; -- cgit