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/proc-linux.c | 605 ------------------------------------------------------- 1 file changed, 605 deletions(-) delete mode 100644 src/proc-linux.c (limited to 'src/proc-linux.c') 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; -} -- cgit