From 0145691112f14352ef15b49c1ea3079a8e80f6e8 Mon Sep 17 00:00:00 2001 From: William Jon McCann Date: Tue, 21 Aug 2007 11:27:04 -0400 Subject: more solaris support based on patch from Brian Cameron. --- src/ck-sysdeps-linux.c | 14 ++++++ src/ck-sysdeps-solaris.c | 109 ++++++++++++++++++++++++++++++++++++----------- src/ck-sysdeps-unix.c | 40 ++++++++++++----- src/ck-sysdeps.h | 2 + src/ck-vt-monitor.c | 14 +++--- 5 files changed, 136 insertions(+), 43 deletions(-) diff --git a/src/ck-sysdeps-linux.c b/src/ck-sysdeps-linux.c index 624bfc4..4b751d7 100644 --- a/src/ck-sysdeps-linux.c +++ b/src/ck-sysdeps-linux.c @@ -28,6 +28,10 @@ #include #include +#include +#include +#include + #ifdef HAVE_PATHS_H #include #endif /* HAVE_PATHS_H */ @@ -603,3 +607,13 @@ ck_unix_pid_get_ppid (pid_t pid) out: return ppid; } + +gboolean +ck_get_max_num_consoles (guint *num) +{ + if (num != NULL) { + *num = MAX_NR_CONSOLES; + } + + return TRUE; +} diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c index caea4c7..c1b1b64 100644 --- a/src/ck-sysdeps-solaris.c +++ b/src/ck-sysdeps-solaris.c @@ -224,38 +224,37 @@ ck_process_stat_free (CkProcessStat *stat) } GHashTable * -proc_pid_get_env_hash (pid_t pid) +ck_unix_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; - } + GHashTable *hash; + char *cmd; + char buf[BUFSIZ]; + FILE *fp; + int i; - hash = NULL; hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - pread (fd, env, 400, stat->penv); + cmd = g_strdup_printf ("pargs -e %d", pid); + fp = popen (cmd, "r"); + g_free (cmd); - i = 0; - while (env[i] != NULL && i < 400) { - char **vals; + while (fgets (buf, BUFSIZ, fp) != NULL) { + g_strchomp (buf); + if (g_str_has_prefix (buf, "envp[")) { + char *skip_prefix; - pread (fd, buf, BUFSIZ, env[i++]); + skip_prefix = strstr (buf, " "); - vals = g_strsplit (buf, "=", 2); - if (vals != NULL) { - g_hash_table_insert (hash, vals[0], vals[1]); + if (skip_prefix != NULL) { + char **vals; + vals = g_strsplit (buf, "=", 2); + if (vals != NULL) { + g_hash_table_insert (hash, vals[0], vals[1]); + } + } } } @@ -264,14 +263,20 @@ proc_pid_get_env_hash (pid_t pid) } char * -proc_pid_get_env (pid_t pid, - const char *var) +ck_unix_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); + /* + * Would probably be more efficient to just loop through the + * environment and return the value, avoiding building the hash + * table, but this works for now. + */ + hash = ck_unix_pid_get_env_hash (pid); + val = g_strdup (g_hash_table_lookup (hash, var)); + g_hash_table_destroy (hash); return val; } @@ -322,3 +327,55 @@ proc_pid_get_ppid (pid_t pid) out: return ppid; } + +gboolean +ck_get_max_num_consoles (guint *num) +{ + GError *error; + char *svcprop_stdout; + int status; + gboolean res; + gboolean ret; + + ret = FALSE; + + /* + * On Solaris, the default number of VT's is determined by + * resources and is stored in the vtdaemon SVC property + * options/vtnodecount. If the svcprop command fails, then it can + * be safely assumed that VT is not supported on this release of + * Solaris. + */ + + error = NULL; + svcprop_stdout = NULL; + status = 0; + res = g_spawn_command_line_sync ("/usr/bin/svcprop -p options/vtnodecount vtdaemon", + &svcprop_stdout, + NULL, + &status, + &error); + + if (res) { + if (error == NULL && svcprop_stdout != NULL) { + char *end; + + end = NULL; + errno = 0; + max_consoles = strtol (svcprop_stdout, &end, 0); + if (end == NULL || end == svcprop_stdout || errno != 0) { + max_consoles = 0; + } else { + ret = TRUE; + } + } + } + + if (num != NULL) { + *num = max_consoles; + } + + g_free (svcprop_stdout); + + return ret; +} diff --git a/src/ck-sysdeps-unix.c b/src/ck-sysdeps-unix.c index 4bad4b6..fa18dac 100644 --- a/src/ck-sysdeps-unix.c +++ b/src/ck-sysdeps-unix.c @@ -154,33 +154,51 @@ ck_get_a_console_fd (void) { int fd; + fd = -1; + +#ifdef __sun + /* On Solaris, first try Sun VT device. */ + fd = open_a_console ("/dev/vt/active"); + if (fd >= 0) { + goto done; + } + fd = open_a_console ("/dev/vt/0"); + if (fd >= 0) { + goto done; + } +#endif + #ifdef _PATH_TTY fd = open_a_console (_PATH_TTY); - if (fd >= 0) - return fd; + if (fd >= 0) { + goto done; + } #endif fd = open_a_console ("/dev/tty"); - if (fd >= 0) - return fd; + if (fd >= 0) { + goto done; + } #ifdef _PATH_CONSOLE fd = open_a_console (_PATH_CONSOLE); - if (fd >= 0) - return fd; + if (fd >= 0) { + goto done; + } #endif fd = open_a_console ("/dev/console"); - if (fd >= 0) - return fd; + if (fd >= 0) { + goto done; + } for (fd = 0; fd < 3; fd++) { if (ck_fd_is_a_console (fd)) { - return fd; + goto done; } } - - return -1; + done: + return fd; } gboolean diff --git a/src/ck-sysdeps.h b/src/ck-sysdeps.h index 86d4425..986018e 100644 --- a/src/ck-sysdeps.h +++ b/src/ck-sysdeps.h @@ -62,6 +62,8 @@ gboolean ck_fd_is_a_console (int fd); gboolean ck_is_root_user (void); +gboolean ck_get_max_num_consoles (guint *num); + G_END_DECLS #endif /* __CK_SYSDEPS_H */ diff --git a/src/ck-vt-monitor.c b/src/ck-vt-monitor.c index 4291bdd..5c37a64 100644 --- a/src/ck-vt-monitor.c +++ b/src/ck-vt-monitor.c @@ -29,11 +29,6 @@ #include #include -#if defined (__linux__) -#include -#include -#endif /* linux */ - #include #include #include @@ -358,6 +353,7 @@ vt_add_watch_unlocked (CkVtMonitor *vt_monitor, static void vt_add_watches (CkVtMonitor *vt_monitor) { + guint max_consoles; int i; gint32 current_num; @@ -365,7 +361,13 @@ vt_add_watches (CkVtMonitor *vt_monitor) current_num = vt_monitor->priv->active_num; - for (i = 1; i < MAX_NR_CONSOLES; i++) { + max_consoles = 1; + + if (! ck_get_max_num_consoles (&max_consoles)) { + /* FIXME: this can fail on solaris */ + } + + for (i = 1; i < max_consoles; i++) { gpointer id; /* don't wait on the active vc */ -- cgit