diff options
| author | William Jon McCann <mccann@jhu.edu> | 2007-08-14 11:50:54 -0400 | 
|---|---|---|
| committer | William Jon McCann <mccann@jhu.edu> | 2007-08-14 11:50:54 -0400 | 
| commit | 383ea823871bf3768e85d1a3ca061e775c6aedf1 (patch) | |
| tree | 3d5970d160777fecf4dc6a30998e3d8e13ad1793 /src | |
| parent | e054c0f8b86f27f94d9316bac065a94081f4be32 (diff) | |
add some solaris support
Based on a patch from Brian Cameron.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 9 | ||||
| -rw-r--r-- | src/getfd.c | 20 | ||||
| -rw-r--r-- | src/proc-solaris.c | 324 | 
3 files changed, 350 insertions, 3 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0977591..136d88a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,9 +49,16 @@ ck-marshal.c: ck-marshal.list  ck-marshal.h: ck-marshal.list  	@GLIB_GENMARSHAL@ $< --prefix=ck_marshal --header > $@ +if CK_COMPILE_LINUX  PLATFORM_SOURCES =		\  	proc-linux.c		\  	$(NULL) +endif +if CK_COMPILE_SOLARIS +PLATFORM_SOURCES =		\ +	proc-solaris.c		\ +	$(NULL) +endif  console_kit_daemon_SOURCES =	\  	main.c			\ @@ -87,6 +94,8 @@ console_kit_daemon_SOURCES += $(FILE_MONITOR_BACKEND)  EXTRA_console_kit_daemon_SOURCES = 	\  	ck-file-monitor-inotify.c	\  	ck-file-monitor-dummy.c		\ +	proc-linux.c			\ +	proc-solaris.c			\  	$(NULL)  console_kit_daemon_LDADD =	\ diff --git a/src/getfd.c b/src/getfd.c index 56c7dd7..8aa46ca 100644 --- a/src/getfd.c +++ b/src/getfd.c @@ -9,7 +9,10 @@  #include <stdio.h>  #include <fcntl.h>  #include <errno.h> +#include <unistd.h> +#ifdef __linux__  #include <linux/kd.h> +#endif  #include <sys/ioctl.h>  #ifdef HAVE_PATHS_H @@ -28,11 +31,18 @@ static int  is_a_console (int fd)  {      char arg; +    int  kb_ok;      arg = 0; -    return (isatty (fd) -            && ioctl (fd, KDGKBTYPE, &arg) == 0 -	    && ((arg == KB_101) || (arg == KB_84))); + +#ifdef __linux__ +    kb_ok = (ioctl (fd, KDGKBTYPE, &arg) == 0 +             && ((arg == KB_101) || (arg == KB_84))); +#else +    kb_ok = 1; +#endif + +    return (isatty (fd) && kb_ok);  }  static int @@ -59,17 +69,21 @@ int getfd (void)  {      int fd; +#ifdef _PATH_TTY      fd = open_a_console (_PATH_TTY);      if (fd >= 0)        return fd; +#endif      fd = open_a_console ("/dev/tty");      if (fd >= 0)        return fd; +#ifdef _PATH_CONSOLE      fd = open_a_console (_PATH_CONSOLE);      if (fd >= 0)        return fd; +#endif      fd = open_a_console ("/dev/console");      if (fd >= 0) diff --git a/src/proc-solaris.c b/src/proc-solaris.c new file mode 100644 index 0000000..f95c042 --- /dev/null +++ b/src/proc-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 "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; +}  | 
