Description: Add support for GNU/Hurd Currently consolekit fails to build on GNU/Hurd mainly because there's no sysdeps backend for the GNU OS implemented. The attached patch proposes a sysdeps-gnu backend, which implements the process management using Hurd's libps, the *ttyent API for the part of the console implementation and the rest using similar (valid) approaches of other backends. Author: Pino Toscano Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=552393 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=24738 Last-Update: 2010-09-20 Index: consolekit/configure.ac =================================================================== --- consolekit.orig/configure.ac 2010-09-20 03:07:20.969097019 +0200 +++ consolekit/configure.ac 2010-09-20 03:07:22.189095438 +0200 @@ -190,6 +190,9 @@ *-*-solaris*) CK_BACKEND="solaris" ;; + *-*-gnu*) + CK_BACKEND="gnu" + ;; *) AC_MSG_ERROR([No sysdeps back-end implemented for host $host]) ;; @@ -200,6 +203,7 @@ AM_CONDITIONAL(CK_COMPILE_LINUX, test x$CK_BACKEND = xlinux, [Compiling for Linux]) AM_CONDITIONAL(CK_COMPILE_FREEBSD, test x$CK_BACKEND = xfreebsd, [Compiling for FreeBSD]) AM_CONDITIONAL(CK_COMPILE_SOLARIS, test x$CK_BACKEND = xsolaris, [Compiling for Solaris]) +AM_CONDITIONAL(CK_COMPILE_GNU, test x$CK_BACKEND = xgnu, [Compiling for GNU]) AC_SUBST(CK_BACKEND) dnl --------------------------------------------------------------------------- Index: consolekit/src/Makefile.am =================================================================== --- consolekit.orig/src/Makefile.am 2010-09-20 03:07:09.397095424 +0200 +++ consolekit/src/Makefile.am 2010-09-20 03:07:22.189095438 +0200 @@ -57,11 +57,18 @@ $(NULL) libck_la_LIBADD = $(KVM_LIBS) endif +if CK_COMPILE_GNU +libck_la_SOURCES += \ + ck-sysdeps-gnu.c \ + $(NULL) +libck_la_LIBADD = -lps +endif EXTRA_libck_la_SOURCES = \ ck-sysdeps-linux.c \ ck-sysdeps-solaris.c \ ck-sysdeps-freebsd.c \ + ck-sysdeps-gnu.c \ $(NULL) sbin_PROGRAMS = \ Index: consolekit/src/ck-sysdeps-gnu.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ consolekit/src/ck-sysdeps-gnu.c 2010-09-20 03:07:22.189095438 +0200 @@ -0,0 +1,402 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2009 Pino Toscano + * + * 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 +#include +#include + +#ifdef HAVE_PATHS_H +#include +#endif /* HAVE_PATHS_H */ + +#include "ck-sysdeps.h" + +struct _CkProcessStat +{ + struct proc_stat *ps; /* the statistics of a process */ +}; + +static struct ps_context *pc = NULL; + +static gboolean +get_proc_stat_from_pid (pid_t pid, + ps_flags_t flags, + struct proc_stat **res_ps) +{ + error_t err; + struct proc_stat *ps; + + g_assert (pid >= 0); + g_assert (res_ps != NULL); + + if (pc == NULL) { + err = ps_context_create (getproc (), &pc); + if (err) { + return FALSE; + } + } + + err = _proc_stat_create (pid, pc, &ps); + if (err) { + return FALSE; + } + + err = proc_stat_set_flags (ps, PSTAT_PID | flags); + if (err) { + return FALSE; + } + + *res_ps = ps; + return TRUE; +} + + +pid_t +ck_process_stat_get_ppid (CkProcessStat *stat) +{ + g_return_val_if_fail (stat != NULL, -1); + + return proc_stat_pid (stat->ps); +} + +char * +ck_process_stat_get_cmd (CkProcessStat *stat) +{ + g_return_val_if_fail (stat != NULL, NULL); + + return g_strdup (proc_stat_args (stat->ps)); +} + +char * +ck_process_stat_get_tty (CkProcessStat *stat) +{ + struct ps_tty *tty; + + g_return_val_if_fail (stat != NULL, NULL); + + tty = proc_stat_tty (stat->ps); + + return tty ? g_strdup (ps_tty_name (tty)) : NULL; +} + +gboolean +ck_process_stat_new_for_unix_pid (pid_t pid, + CkProcessStat **stat, + GError **error) +{ + gboolean res; + struct proc_stat *ps; + CkProcessStat *proc; + + g_return_val_if_fail (pid > 1, FALSE); + + if (stat == NULL) { + return FALSE; + } + + *stat = NULL; + + res = get_proc_stat_from_pid (pid, PSTAT_ARGS | PSTAT_TTY, &ps); + if (!res) { + return FALSE; + } + + proc = g_new0 (CkProcessStat, 1); + proc->ps = ps; + *stat = proc; + + return TRUE; +} + +void +ck_process_stat_free (CkProcessStat *stat) +{ + _proc_stat_free (stat->ps); + + g_free (stat); +} + +GHashTable * +ck_unix_pid_get_env_hash (pid_t pid) +{ + struct proc_stat *ps; + char *env_p; + size_t env_index; + size_t env_l; + gboolean res; + GHashTable *hash; + + g_return_val_if_fail (pid > 1, NULL); + + res = get_proc_stat_from_pid (pid, PSTAT_ENV, &ps); + if (!res) { + return NULL; + } + + hash = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + + env_index = 0; + env_l = 0; + env_p = proc_stat_env (ps); + while (env_index < proc_stat_env_len (ps)) { + env_l = strlen (env_p); + env_index += env_l + 1; + if (env_l) { + char **vals; + vals = g_strsplit (env_p, "=", 2); + if (vals != NULL) { + g_hash_table_insert (hash, + g_strdup (vals[0]), + g_strdup (vals[1])); + g_strfreev (vals); + } + } + env_p = env_p + env_l + 1; + } + + _proc_stat_free (ps); + + return hash; +} + +char * +ck_unix_pid_get_env (pid_t pid, + const char *var) +{ + struct proc_stat *ps; + char *env_p; + size_t env_index; + size_t env_l; + char *prefix; + int prefix_len; + char *val; + gboolean res; + + g_return_val_if_fail (pid > 1, NULL); + + val = NULL; + + res = get_proc_stat_from_pid (pid, PSTAT_ENV, &ps); + if (!res) { + return NULL; + } + + prefix = g_strdup_printf ("%s=", var); + prefix_len = strlen (prefix); + + env_index = 0; + env_l = 0; + env_p = proc_stat_env (ps); + while (env_index < proc_stat_env_len (ps)) { + env_l = strlen (env_p); + env_index += env_l + 1; + if (env_l && g_str_has_prefix (env_p, prefix)) { + val = g_strdup (env_p + prefix_len); + break; + } + env_p = env_p + env_l + 1; + } + + g_free (prefix); + + _proc_stat_free (ps); + + return val; +} + +uid_t +ck_unix_pid_get_uid (pid_t pid) +{ + struct proc_stat *ps; + gboolean res; + uid_t uid; + + g_return_val_if_fail (pid > 1, 0); + + res = get_proc_stat_from_pid (pid, PSTAT_OWNER_UID, &ps); + if (!res) { + return 0; + } + + uid = proc_stat_owner_uid (ps); + + _proc_stat_free (ps); + + return uid; +} + +pid_t +ck_unix_pid_get_ppid (pid_t pid) +{ + struct proc_stat *ps; + gboolean res; + pid_t ppid; + + g_return_val_if_fail (pid > 1, 0); + + res = get_proc_stat_from_pid (pid, PSTAT_PROC_INFO, &ps); + if (!res) { + return 0; + } + + ppid = proc_stat_proc_info (ps)->ppid; + + _proc_stat_free (ps); + + return ppid; +} + +gboolean +ck_unix_pid_get_login_session_id (pid_t pid, + char **idp) +{ + g_return_val_if_fail (pid > 1, FALSE); + + return FALSE; +} + +gboolean +ck_get_max_num_consoles (guint *num) +{ + int max_consoles; + int res; + gboolean ret; + struct ttyent *t; + + ret = FALSE; + max_consoles = 0; + + res = setttyent (); + if (res == 0) { + goto done; + } + + while ((t = getttyent ()) != NULL) { + if (t->ty_status & TTY_ON && strncmp (t->ty_name, "tty", 3) == 0) + max_consoles++; + } + + /* Increment one more so that all consoles are properly counted + * this is arguable a bug in vt_add_watches(). + */ + max_consoles++; + + ret = TRUE; + + endttyent (); + +done: + if (num != NULL) { + *num = max_consoles; + } + + return ret; +} + +gboolean +ck_supports_activatable_consoles (void) +{ + return TRUE; +} + +char * +ck_get_console_device_for_num (guint num) +{ + char *device; + + device = g_strdup_printf (_PATH_TTY "%u", num); + + return device; +} + +gboolean +ck_get_console_num_from_device (const char *device, + guint *num) +{ + guint n; + gboolean ret; + + n = 0; + ret = FALSE; + + if (device == NULL) { + return FALSE; + } + + if (sscanf (device, _PATH_TTY "%u", &n) == 1) { + ret = TRUE; + } + + if (num != NULL) { + *num = n; + } + + return ret; +} + +gboolean +ck_get_active_console_num (int console_fd, + guint *num) +{ + gboolean ret; + int res; + long cur_active; + char buf[30]; + guint active; + + g_assert (console_fd != -1); + + active = 0; + ret = FALSE; + + res = readlink ("/dev/cons/vcs", buf, sizeof (buf)); + if (res > 0) { + /* the resolved path is like "/dev/vcs/$number", so skip + the non-number part at the start */ + const char *p = buf; + while ((*p) && ((*p < '0') || (*p > '9'))) { + ++p; + } + if (*p) { + cur_active = strtol (p, NULL, 10); + g_debug ("Current VT: tty%ld", cur_active); + active = cur_active; + ret = TRUE; + } + } + + if (num != NULL) { + *num = active; + } + + return ret; +}