summaryrefslogtreecommitdiffstats
path: root/src/proc-linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/proc-linux.c')
-rw-r--r--src/proc-linux.c605
1 files changed, 0 insertions, 605 deletions
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 <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>
-
-#ifdef HAVE_PATHS_H
-#include <paths.h>
-#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;
-}