diff options
author | Robey Pointer <robey@src.gnome.org> | 2000-07-10 23:18:54 +0000 |
---|---|---|
committer | Robey Pointer <robey@src.gnome.org> | 2000-07-10 23:18:54 +0000 |
commit | 5a7cda2daa8c72bd29ff89867f6d1736b7e80284 (patch) | |
tree | 87d6f7ad39e896c5d78cdb5ea74368c7aa85d1e6 /components | |
parent | c8113cdf81511498676126da502679b91d75c262 (diff) | |
download | nautilus-5a7cda2daa8c72bd29ff89867f6d1736b7e80284.tar.gz |
add baseline TrilobiteRootHelper object, to use eazel-helper to do root tasks
Diffstat (limited to 'components')
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_ */ |