summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorRobey Pointer <robey@src.gnome.org>2000-07-10 23:18:54 +0000
committerRobey Pointer <robey@src.gnome.org>2000-07-10 23:18:54 +0000
commit5a7cda2daa8c72bd29ff89867f6d1736b7e80284 (patch)
tree87d6f7ad39e896c5d78cdb5ea74368c7aa85d1e6 /components
parentc8113cdf81511498676126da502679b91d75c262 (diff)
downloadnautilus-5a7cda2daa8c72bd29ff89867f6d1736b7e80284.tar.gz
add baseline TrilobiteRootHelper object, to use eazel-helper to do root tasks
Diffstat (limited to 'components')
-rw-r--r--components/services/trilobite/libtrilobite/Makefile.am2
-rw-r--r--components/services/trilobite/libtrilobite/libtrilobite.h1
-rw-r--r--components/services/trilobite/libtrilobite/trilobite-core-utils.c71
-rw-r--r--components/services/trilobite/libtrilobite/trilobite-core-utils.h2
-rw-r--r--components/services/trilobite/libtrilobite/trilobite-root-helper.c442
-rw-r--r--components/services/trilobite/libtrilobite/trilobite-root-helper.h100
6 files changed, 618 insertions, 0 deletions
diff --git a/components/services/trilobite/libtrilobite/Makefile.am b/components/services/trilobite/libtrilobite/Makefile.am
index aadc2f33f..7ab01557b 100644
--- a/components/services/trilobite/libtrilobite/Makefile.am
+++ b/components/services/trilobite/libtrilobite/Makefile.am
@@ -46,6 +46,7 @@ libtrilobiteinclude_HEADERS = \
trilobite-core-security-manager.h \
trilobite-core-tests.h \
trilobite-core-utils.h \
+ trilobite-root-helper.h \
helixcode-utils.h \
$(NULL)
@@ -63,6 +64,7 @@ libtrilobite_la_SOURCES = \
trilobite-core-security-manager.c \
trilobite-core-tests.c \
trilobite-core-utils.c \
+ trilobite-root-helper.c \
helixcode-utils.c \
$(NULL)
diff --git a/components/services/trilobite/libtrilobite/libtrilobite.h b/components/services/trilobite/libtrilobite/libtrilobite.h
index a0174b93c..a566ce35c 100644
--- a/components/services/trilobite/libtrilobite/libtrilobite.h
+++ b/components/services/trilobite/libtrilobite/libtrilobite.h
@@ -40,6 +40,7 @@
#include <libtrilobite/trilobite-core-security-manager.h>
#include <libtrilobite/trilobite-core-metadata-manager.h>
#include <libtrilobite/trilobite-core-tests.h>
+#include <libtrilobite/trilobite-root-helper.h>
#include <libtrilobite/helixcode-utils.h>
#endif /* __LIBTRILOBITE_H__ */
diff --git a/components/services/trilobite/libtrilobite/trilobite-core-utils.c b/components/services/trilobite/libtrilobite/trilobite-core-utils.c
index 69e140c07..8d8ba4889 100644
--- a/components/services/trilobite/libtrilobite/trilobite-core-utils.c
+++ b/components/services/trilobite/libtrilobite/trilobite-core-utils.c
@@ -18,6 +18,7 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Authors: J Shane Culpepper <pepper@eazel.com>
+ * Robey Pointer <robey@eazel.com>
*
*/
@@ -27,3 +28,73 @@
*
*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "trilobite-core-utils.h"
+
+#ifdef OPEN_MAX
+#define LAST_FD OPEN_MAX
+#else
+#define LAST_FD 1024
+#endif
+
+/* better/safer replacement for popen (which doesn't exist on all platforms, anyway).
+ * forks and executes a specific program, with pipes carrying stdin/stdout/stderr back
+ * to you. this way, you can fork off a subprocess and control its environment. and
+ * it doesn't use system() like most evil popen implementations.
+ * for the future, it'd be nice to be able to clear out the subprocess's env vars.
+ */
+int
+trilobite_pexec (const char *path, char * const argv[], int *stdin_fd, int *stdout_fd, int *stderr_fd)
+{
+ pid_t child;
+ int pipe_in[2], pipe_out[2], pipe_err[2];
+ int i;
+
+ pipe_in[0] = pipe_in[1] = pipe_out[0] = pipe_out[1] = pipe_err[0] = pipe_err[1] = -1;
+ if ((pipe (pipe_in) != 0) || (pipe (pipe_out) != 0) || (pipe (pipe_err) != 0)) {
+ goto close_and_give_up;
+ }
+ child = fork ();
+ if (child < 0) {
+ goto close_and_give_up;
+ }
+
+ if (child == 0) {
+ /* make stdin/stdout/stderr use the pipes */
+ dup2 (pipe_in[0], 0);
+ dup2 (pipe_out[1], 1);
+ dup2 (pipe_err[1], 2);
+ /* close all open fd's */
+ for (i = 3; i < LAST_FD; i++) {
+ close(i);
+ }
+
+ /* FIXME: might we want to specify our own environment here? */
+ execv (path, argv);
+
+ /* if we get here, then somehow, exec failed */
+ exit (-1);
+ }
+
+ /* copy out all the in/out/err fd's */
+ close (pipe_in[0]);
+ close (pipe_out[1]);
+ close (pipe_err[1]);
+ *stdin_fd = pipe_in[1];
+ *stdout_fd = pipe_out[0];
+ *stderr_fd = pipe_err[0];
+
+ return 0;
+
+close_and_give_up:
+ close (pipe_in[0]);
+ close (pipe_in[1]);
+ close (pipe_out[0]);
+ close (pipe_out[1]);
+ close (pipe_err[0]);
+ close (pipe_err[1]);
+
+ return -1;
+}
diff --git a/components/services/trilobite/libtrilobite/trilobite-core-utils.h b/components/services/trilobite/libtrilobite/trilobite-core-utils.h
index d80c756dc..bb9c6473d 100644
--- a/components/services/trilobite/libtrilobite/trilobite-core-utils.h
+++ b/components/services/trilobite/libtrilobite/trilobite-core-utils.h
@@ -30,5 +30,7 @@
#ifndef TRILOBITE_CORE_UTILS_H
#define TRILOBITE_CORE_UTILS_H
+int trilobite_pexec (const char *path, char * const argv[], int *stdin_fd, int *stdout_fd, int *stderr_fd);
+
#endif /* TRILOBITE_CORE_UTILS_H */
diff --git a/components/services/trilobite/libtrilobite/trilobite-root-helper.c b/components/services/trilobite/libtrilobite/trilobite-root-helper.c
new file mode 100644
index 000000000..9f7d583d1
--- /dev/null
+++ b/components/services/trilobite/libtrilobite/trilobite-root-helper.c
@@ -0,0 +1,442 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * TrilobiteRootHelper is an object that allows a user process to ask for
+ * certain tasks to be handled by the superuser, using the usermode
+ * library (man userhelper) to run eazel-helper. A signal is emitted
+ * when the root password is needed, so the caller can ask for it in a
+ * special way.
+ *
+ * Copyright (C) 2000 Eazel, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library 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.
+ *
+ * Authors: Robey Pointer <robey@eazel.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/poll.h>
+#include <gtk/gtk.h>
+#include "trilobite-core-utils.h"
+#include "trilobite-root-helper.h"
+
+#define USERHELPER_PATH "/usr/sbin/userhelper"
+#define EAZEL_HELPER "eazel-helper"
+
+
+static GtkObject *parent_class;
+
+/* signals that a TrilobyteRootHelper can emit */
+/* LAST_SIGNAL is just a sentinel marking the end of the list */
+enum {
+ NEED_PASSWORD,
+ LAST_SIGNAL
+};
+static guint root_helper_signals[LAST_SIGNAL] = { 0 };
+
+
+/* have to make my own signal marshaller for STRING__NONE (grumble) */
+typedef gchar *(*GtkSignal_STRING__NONE) (GtkObject *object, gpointer user_data);
+static void
+gtk_marshal_STRING__NONE (GtkObject *object, GtkSignalFunc func, gpointer func_data, GtkArg *args)
+{
+ GtkSignal_STRING__NONE rfunc;
+ gchar **return_value;
+
+ return_value = GTK_RETLOC_STRING (args[0]);
+ rfunc = (GtkSignal_STRING__NONE)func;
+ *return_value = (*rfunc) (object, func_data);
+}
+
+
+/* destroy callback, and accessible from the outside world */
+void
+trilobite_root_helper_destroy (GtkObject *object)
+{
+ TrilobiteRootHelper *root_helper;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (TRILOBITE_IS_ROOT_HELPER (object));
+ g_message ("<-- trilobite_root_helper");
+
+ root_helper = TRILOBITE_ROOT_HELPER (object);
+
+ /* anything that needs to be freed? */
+
+ /* call parent destructor */
+ if (GTK_OBJECT_CLASS (parent_class)->destroy) {
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+ }
+}
+
+/* class initializer */
+static void
+trilobite_root_helper_class_initialize (TrilobiteRootHelperClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ parent_class = gtk_type_class (GTK_TYPE_OBJECT);
+
+ object_class = (GtkObjectClass *)klass;
+ object_class->destroy = trilobite_root_helper_destroy;
+
+ root_helper_signals[NEED_PASSWORD] =
+ gtk_signal_new ("need_password", 0, object_class->type,
+ GTK_SIGNAL_OFFSET (TrilobiteRootHelperClass, need_password),
+ gtk_marshal_STRING__NONE, GTK_TYPE_STRING, 0);
+ gtk_object_class_add_signals (object_class, root_helper_signals, LAST_SIGNAL);
+
+ klass->need_password = NULL;
+}
+
+/* object initializer */
+static void
+trilobite_root_helper_initialize (TrilobiteRootHelper *object)
+{
+ TrilobiteRootHelper *root_helper;
+
+ g_assert (object != NULL);
+ g_assert (TRILOBITE_IS_ROOT_HELPER (object));
+ g_message ("--> trilobite_root_helper");
+
+ root_helper = TRILOBITE_ROOT_HELPER (object);
+ root_helper->state = TRILOBITE_ROOT_HELPER_STATE_NEW;
+}
+
+/* generate the GtkType for TrilobyteRootHelper */
+GtkType
+trilobite_root_helper_get_type (void)
+{
+ static GtkType trilobite_root_helper_type = 0;
+
+ /* First time it's called ? */
+ if (! trilobite_root_helper_type) {
+ static const GtkTypeInfo root_helper_info = {
+ "TrilobiteRootHelper",
+ sizeof (TrilobiteRootHelper),
+ sizeof (TrilobiteRootHelperClass),
+ (GtkClassInitFunc) trilobite_root_helper_class_initialize,
+ (GtkObjectInitFunc) trilobite_root_helper_initialize,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ /* Get a unique GtkType */
+ trilobite_root_helper_type = gtk_type_unique (GTK_TYPE_OBJECT, &root_helper_info);
+ }
+
+ return trilobite_root_helper_type;
+}
+
+TrilobiteRootHelper *
+trilobite_root_helper_new (void)
+{
+ return TRILOBITE_ROOT_HELPER (gtk_object_new (TRILOBITE_TYPE_ROOT_HELPER, NULL));
+}
+
+
+/********** functions that actually implement the root helper **********/
+
+
+static int
+make_nonblocking (int fd)
+{
+ int flags;
+
+ flags = fcntl (fd, F_GETFL, 0);
+ fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+ return 0;
+}
+
+static int
+make_blocking (int fd)
+{
+ int flags;
+
+ flags = fcntl (fd, F_GETFL, 0);
+ fcntl (fd, F_SETFL, flags &~ O_NONBLOCK);
+ return 0;
+}
+
+
+/* wait for and read one character from the eazel-helper */
+static char
+eazel_helper_response (int pipe_stdout)
+{
+ struct pollfd pollfd;
+ char buffer[4];
+ int bytes;
+
+ /* wait for something to come in */
+ memset (&pollfd, 0, sizeof (pollfd));
+ pollfd.fd = pipe_stdout;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+ poll (&pollfd, 1, 3000);
+ bytes = read (pipe_stdout, buffer, 1);
+ if (bytes <= 0) {
+ return '\0';
+ } else {
+ return buffer[0];
+ }
+}
+
+/* /usr/sbin/userhelper
+ * userhelper
+ * -w
+ * eazel-helper
+ */
+static TrilobiteRootHelperStatus
+eazel_helper_start (int *pipe_stdin, int *pipe_stdout)
+{
+ char *pipe_argv[4];
+ int useless_stderr;
+ char buffer[256];
+ TrilobiteRootHelperStatus err;
+
+ pipe_argv[0] = "userhelper";
+ pipe_argv[1] = "-w";
+ pipe_argv[2] = EAZEL_HELPER;
+ pipe_argv[3] = NULL;
+ if (trilobite_pexec (USERHELPER_PATH, pipe_argv, pipe_stdin, pipe_stdout, &useless_stderr) != 0) {
+ return TRILOBITE_ROOT_HELPER_NO_USERHELPER;
+ }
+ close (useless_stderr);
+
+ make_nonblocking (*pipe_stdout);
+
+ /* if the first thing from the pipe is a "2", we need the root password */
+ buffer[0] = eazel_helper_response (*pipe_stdout);
+ if (buffer[0] == '\0') {
+ err = TRILOBITE_ROOT_HELPER_NO_USERHELPER;
+ goto give_up;
+ } else if (buffer[0] == '2') {
+ /* need root password. but first, clear the buffer of crap. */
+ read (*pipe_stdout, buffer, 256);
+ err = TRILOBITE_ROOT_HELPER_NEED_PASSWORD;
+ goto done;
+ } else if (buffer[0] == '*') {
+ /* the winner! */
+ read (*pipe_stdout, buffer, 256);
+ err = TRILOBITE_ROOT_HELPER_SUCCESS;
+ goto done;
+ } else {
+ /* ?! */
+ g_warning ("TrilobiteRootHelper: unknown userhelper result %02X", buffer[0]);
+ err = TRILOBITE_ROOT_HELPER_INTERNAL_ERROR;
+ goto give_up;
+ }
+
+give_up:
+ close (*pipe_stdin);
+ close (*pipe_stdout);
+
+done:
+ return err;
+}
+
+static TrilobiteRootHelperStatus
+eazel_helper_password (int pipe_stdin, int pipe_stdout, const char *password)
+{
+ char buffer[256];
+ int bytes;
+ TrilobiteRootHelperStatus err;
+
+ /* clear out anything lingering in the input buffer */
+ read (pipe_stdout, buffer, 256);
+
+ /* send password followed by linefeed */
+ memset (buffer, 0, 256);
+ strncpy (buffer, password, 200);
+ strcat (buffer, "\n");
+ bytes = write (pipe_stdin, buffer, strlen(buffer));
+
+ /* now check for response */
+ while (1) {
+ buffer[0] = eazel_helper_response (pipe_stdout);
+ if (buffer[0] == '\0') {
+ err = TRILOBITE_ROOT_HELPER_LOST_PIPE;
+ goto give_up;
+ } else if (buffer[0] == '2') {
+ err = TRILOBITE_ROOT_HELPER_BAD_PASSWORD;
+ goto give_up;
+ } else if (buffer[0] == '5') {
+ /* sometimes a leftover status message from the last stage */
+ /* read 2 chars, then continue */
+ eazel_helper_response (pipe_stdout);
+ eazel_helper_response (pipe_stdout);
+ continue;
+ } else if (buffer[0] == '*') {
+ /* clear buffer */
+ read (pipe_stdout, buffer, 256);
+ err = TRILOBITE_ROOT_HELPER_SUCCESS;
+ goto done;
+ } else {
+ /* ?! */
+ g_warning ("TrilobiteRootHelper: unknown userhelper 2nd result %02X", buffer[0]);
+ err = TRILOBITE_ROOT_HELPER_INTERNAL_ERROR;
+ goto give_up;
+ }
+ }
+
+give_up:
+ close (pipe_stdin);
+ close (pipe_stdout);
+
+done:
+ return err;
+}
+
+
+/********** actual API functions to make the root helper work **********/
+
+
+/* returns ROOT_HELPER_STATUS_SUCCESS (0) on success */
+TrilobiteRootHelperStatus
+trilobite_root_helper_start (TrilobiteRootHelper *root_helper)
+{
+ TrilobiteRootHelperStatus err;
+ char *password;
+
+ g_return_val_if_fail (root_helper != NULL, FALSE);
+ g_return_val_if_fail (TRILOBITE_IS_ROOT_HELPER (root_helper), FALSE);
+
+ password = NULL;
+
+ if (root_helper->state == TRILOBITE_ROOT_HELPER_STATE_CONNECTED) {
+ /* already connected, dude. */
+ return TRILOBITE_ROOT_HELPER_SUCCESS;
+ }
+
+ err = eazel_helper_start (&root_helper->pipe_stdin, &root_helper->pipe_stdout);
+ switch (err) {
+ case TRILOBITE_ROOT_HELPER_SUCCESS:
+ /* already done -- nice! */
+ goto connected;
+ case TRILOBITE_ROOT_HELPER_NEED_PASSWORD:
+ /* the expected case -- continue */
+ break;
+ default:
+ /* anything else is an error */
+ goto failed;
+ }
+
+ /* now emit a signal and get the password */
+ gtk_signal_emit (GTK_OBJECT (root_helper), root_helper_signals[NEED_PASSWORD], &password);
+ if (password == NULL) {
+ /* bummer. nobody caught the signal. */
+ err = TRILOBITE_ROOT_HELPER_NEED_PASSWORD;
+ goto failed;
+ }
+
+ err = eazel_helper_password (root_helper->pipe_stdin, root_helper->pipe_stdout, password);
+ switch (err) {
+ case TRILOBITE_ROOT_HELPER_SUCCESS:
+ /* yeah! set! */
+ goto connected;
+ default:
+ /* all else is error */
+ goto failed;
+ }
+
+connected:
+ g_free (password);
+ root_helper->state = TRILOBITE_ROOT_HELPER_STATE_CONNECTED;
+ return TRILOBITE_ROOT_HELPER_SUCCESS;
+
+failed:
+ g_free (password);
+ root_helper->state = TRILOBITE_ROOT_HELPER_STATE_NEW;
+ return err;
+}
+
+/* on an already-connected root helper, run rpm with the given arguments.
+ * argv is a GList of (char *) containing the arguments
+ * on success, returns an fd containing stdout/stderr from rpm.
+ * on failure, returns -1.
+ */
+static TrilobiteRootHelperStatus
+trilobite_root_helper_rpm (TrilobiteRootHelper *root_helper, GList *argv, int *fd)
+{
+ GList *item;
+ char *p, *out;
+ int len;
+
+ /* any argument containing an unprintable is an immediate error */
+ for (item = g_list_first (argv); item; item = g_list_next (item)) {
+ for (p = (char *)item->data; *p; p++) {
+ if ((*p < ' ') || (*p == 127)) {
+ g_warning ("TrilobiteRootHelper: RPM: argument %d contained an "
+ "unprintable character: %02X",
+ g_list_position (argv, item), *p);
+ return TRILOBITE_ROOT_HELPER_BAD_ARGS;
+ }
+ }
+ }
+
+ out = g_strdup_printf ("rpm %u\n", g_list_length (argv));
+ if (write (root_helper->pipe_stdin, out, strlen (out)) < strlen (out)) {
+ g_free (out);
+ goto bail;
+ }
+ g_free (out);
+
+ for (item = g_list_first (argv); item; item = g_list_next (item)) {
+ len = strlen ((char *)item->data);
+ if ((write (root_helper->pipe_stdin, (char *)item->data, len) < len) ||
+ (write (root_helper->pipe_stdin, "\n", 1) < 1)) {
+ goto bail;
+ }
+ }
+
+ /* the service will probably call fdopen on this fd, so the pipe needs to be made
+ * blocking, or else the buffered reads and writes will barf everywhere.
+ */
+ make_blocking (root_helper->pipe_stdout);
+ *fd = root_helper->pipe_stdout;
+ return TRILOBITE_ROOT_HELPER_SUCCESS;
+
+bail:
+ /* unable to write everything to the pipe */
+ close (root_helper->pipe_stdin);
+ close (root_helper->pipe_stdout);
+ root_helper->state = TRILOBITE_ROOT_HELPER_STATE_NEW;
+ return TRILOBITE_ROOT_HELPER_LOST_PIPE;
+}
+
+
+TrilobiteRootHelperStatus
+trilobite_root_helper_run (TrilobiteRootHelper *root_helper, TrilobiteRootHelperCommand command, GList *argv, int *fd)
+{
+ g_return_val_if_fail (root_helper != NULL, TRILOBITE_ROOT_HELPER_BAD_ARGS);
+ g_return_val_if_fail (argv != NULL, TRILOBITE_ROOT_HELPER_BAD_ARGS);
+ g_return_val_if_fail (TRILOBITE_IS_ROOT_HELPER (root_helper), TRILOBITE_ROOT_HELPER_BAD_ARGS);
+ g_return_val_if_fail (TRILOBITE_ROOT_HELPER_IS_CONNECTED (root_helper), TRILOBITE_ROOT_HELPER_BAD_ARGS);
+
+ switch (command) {
+ case TRILOBITE_ROOT_HELPER_RUN_RPM:
+ return trilobite_root_helper_rpm (root_helper, argv, fd);
+ default:
+ g_warning ("unknown TrilobiteRootHelper command: 0x%02X", command);
+ return TRILOBITE_ROOT_HELPER_BAD_COMMAND;
+ }
+}
+
diff --git a/components/services/trilobite/libtrilobite/trilobite-root-helper.h b/components/services/trilobite/libtrilobite/trilobite-root-helper.h
new file mode 100644
index 000000000..cb1951b36
--- /dev/null
+++ b/components/services/trilobite/libtrilobite/trilobite-root-helper.h
@@ -0,0 +1,100 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * GtkObject definition for TrilobiteRootHelper.
+ *
+ * Copyright (C) 2000 Eazel, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library 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.
+ *
+ * Authors: Robey Pointer <robey@eazel.com>
+ *
+ */
+
+#ifndef _TRILOBITE_ROOT_HELPER_H_
+#define _TRILOBITE_ROOT_HELPER_H_
+
+/* #include <libgnome/gnome-defs.h> */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define TRILOBITE_TYPE_ROOT_HELPER (trilobite_root_helper_get_type ())
+#define TRILOBITE_ROOT_HELPER(obj) (GTK_CHECK_CAST ((obj), TRILOBITE_TYPE_ROOT_HELPER, \
+ TrilobiteRootHelper))
+#define TRILOBITE_ROOT_HELPER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TRILOBITE_TYPE_ROOT_HELPER, \
+ TrilobiteRootHelperClass))
+#define TRILOBITE_IS_ROOT_HELPER(obj) (GTK_CHECK_TYPE ((obj), TRILOBITE_TYPE_ROOT_HELPER))
+#define TRILOBITE_IS_ROOT_HELPER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TRILOBITE_TYPE_ROOT_HELPER))
+
+typedef struct _TrilobiteRootHelper TrilobiteRootHelper;
+typedef struct _TrilobiteRootHelperClass TrilobiteRootHelperClass;
+
+/* used only internally */
+typedef enum {
+ TRILOBITE_ROOT_HELPER_STATE_NEW = 0,
+ TRILOBITE_ROOT_HELPER_STATE_CONNECTED
+} TrilobiteRootHelperState;
+
+typedef enum {
+ TRILOBITE_ROOT_HELPER_SUCCESS = 0,
+ TRILOBITE_ROOT_HELPER_NO_USERHELPER, /* couldn't fork/exec the "userhelper" utility */
+ TRILOBITE_ROOT_HELPER_NEED_PASSWORD, /* no signal handler supplied a root password */
+ TRILOBITE_ROOT_HELPER_BAD_PASSWORD, /* password was supplied, but it was wrong */
+ TRILOBITE_ROOT_HELPER_LOST_PIPE, /* "userhelper" pipe closed prematurely */
+ TRILOBITE_ROOT_HELPER_BAD_ARGS, /* arguments to trilobite_root_helper_run() were bad */
+ TRILOBITE_ROOT_HELPER_BAD_COMMAND, /* command unknown to TrilobiteRootHelper */
+ TRILOBITE_ROOT_HELPER_INTERNAL_ERROR /* something weird went wrong */
+} TrilobiteRootHelperStatus;
+
+/* commands that can be sent to the root helper, once it's running */
+typedef enum {
+ TRILOBITE_ROOT_HELPER_RUN_RPM
+} TrilobiteRootHelperCommand;
+
+struct _TrilobiteRootHelperClass
+{
+ GtkObjectClass parent_class;
+
+ gchar *(*need_password) (TrilobiteRootHelper *helper);
+};
+
+struct _TrilobiteRootHelper
+{
+ GtkObject parent;
+ TrilobiteRootHelperState state;
+ int pipe_stdin; /* pipe to/from the eazel-helper utility */
+ int pipe_stdout;
+};
+
+
+#define TRILOBITE_ROOT_HELPER_IS_CONNECTED(obj) (TRILOBITE_ROOT_HELPER (obj)->state == \
+ TRILOBITE_ROOT_HELPER_STATE_CONNECTED)
+
+
+GtkType trilobite_root_helper_get_type (void);
+TrilobiteRootHelper *trilobite_root_helper_new (void);
+void trilobite_root_helper_destroy (GtkObject *object);
+
+TrilobiteRootHelperStatus trilobite_root_helper_start (TrilobiteRootHelper *root_helper);
+TrilobiteRootHelperStatus trilobite_root_helper_run (TrilobiteRootHelper *root_helper,
+ TrilobiteRootHelperCommand command, GList *argv, int *fd);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* _TRILOBITE_ROOT_HELPER_H_ */