bonobo-process



Hi,

On 05 Jun 2001 08:17:04 +0200, Dietmar Maurer wrote:
> > Anyways, there are a couple of open issues (security, and how the
> > moniker should work), so I thought it would make a good addition to
> > bonobo-extras.
> 
> Well, everything sounds useful :-) Where can I find the sources?

Okay, here is a big patch against bonobo to supply bonobo-process,
bonobo-stream-fd, and bonobo-moniker-exec.

If this is okay I can get the bonobo-extra build stuff up and running if
you want.

Also, there is a smaller patch to bonobo-stream-client.c to handle
partial reads correctly, though I'm not sure if I'm breaking semantics
here.

The big question with the exec moniker is how to handle changing to
another user to execute a command, both for security, and handling
generic PAM authentication.

-Alex

--
 make: *** No rule to make target `sense'.  Stop.

Index: bonobo.h
===================================================================
RCS file: /cvs/gnome/bonobo/bonobo.h,v
retrieving revision 1.51
diff -u -r1.51 bonobo.h
--- bonobo.h	2001/04/23 20:47:11	1.51
+++ bonobo.h	2001/06/06 18:13:02
@@ -74,6 +74,8 @@
 #include <bonobo/bonobo-print.h>
 #include <bonobo/bonobo-print-client.h>
 
+#include <bonobo/bonobo-process.h>
+
 #ifdef __cplusplus
 }
 #endif
Index: bonobo/Makefile.am
===================================================================
RCS file: /cvs/gnome/bonobo/bonobo/Makefile.am,v
retrieving revision 1.171
diff -u -r1.171 Makefile.am
--- bonobo/Makefile.am	2001/04/16 23:25:54	1.171
+++ bonobo/Makefile.am	2001/06/06 18:13:02
@@ -39,6 +39,7 @@
 	$(top_srcdir)/idl/Bonobo_Moniker.idl		\
 	$(top_srcdir)/idl/Bonobo_Persist.idl		\
 	$(top_srcdir)/idl/Bonobo_Print.idl		\
+	$(top_srcdir)/idl/Bonobo_Process.idl		\
 	$(top_srcdir)/idl/Bonobo_Progressive.idl	\
 	$(top_srcdir)/idl/Bonobo_Property.idl		\
 	$(top_srcdir)/idl/Bonobo_Storage.idl		\
@@ -80,12 +81,14 @@
 	bonobo-persist-file.c		\
 	bonobo-persist-stream.c		\
 	bonobo-persist.c		\
+	bonobo-process.c		\
 	bonobo-progressive.c		\
 	bonobo-shlib-factory.c		\
 	bonobo-storage-plugin.c		\
 	bonobo-storage.c		\
 	bonobo-stream.c			\
 	bonobo-stream-client.c		\
+	bonobo-stream-fd.c		\
 	bonobo-stream-memory.c		\
 	bonobo-transient.c		\
 	bonobo-property.c		\
@@ -130,6 +133,7 @@
 	bonobo-persist-stream.h			\
 	bonobo-persist.h			\
 	bonobo-plug.h				\
+	bonobo-process.h			\
 	bonobo-progressive.h			\
 	bonobo-property-bag.h			\
 	bonobo-property-bag-client.h		\
@@ -143,6 +147,7 @@
 	bonobo-storage-plugin.h			\
 	bonobo-storage.h			\
 	bonobo-stream-client.h			\
+	bonobo-stream-fd.h			\
 	bonobo-stream-memory.h			\
 	bonobo-stream.h				\
 	bonobo-transient.h			\
Index: bonobo/bonobo-process.c
===================================================================
RCS file: bonobo-process.c
diff -N bonobo-process.c
--- /dev/null	Tue May  5 16:32:27 1998
+++ bonobo-process.c	Wed Jun  6 14:13:02 2001
@@ -0,0 +1,316 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * bonobo-process.c: Generic process interface for callbacks.
+ *
+ * Authors:
+ *	Alex Graveley (alex ximian com)
+ *
+ * Copyright (C) 2001, Ximian, Inc.
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <gtk/gtksignal.h>
+
+#include <bonobo/bonobo-event-source.h>
+#include <bonobo/bonobo-exception.h>
+#include <bonobo/bonobo-process.h>
+
+#define PARENT_TYPE BONOBO_X_OBJECT_TYPE
+
+static GtkObjectClass *bonobo_process_parent_class;
+
+struct _BonoboProcessPrivate {
+	pid_t  pid;
+	int    return_val;
+	guint  waitpid_tag;
+
+	Bonobo_Stream in_stream;
+	Bonobo_Stream out_stream;
+	Bonobo_Stream err_stream;
+};
+
+enum SIGNALS {
+	SIGNAL_SENT,
+	PROCESS_EXIT,
+	LAST_SIGNAL
+};
+static guint signals [LAST_SIGNAL] = { 0 };
+
+static gboolean bonobo_process_idle_waitpid (gpointer user_data);
+
+static void
+impl_Bonobo_Process_signal (PortableServer_Servant  servant, 
+			    CORBA_long              signum, 
+			    CORBA_Environment      *ev)
+{
+	BonoboProcess *process;
+	BonoboEventSource *source;
+
+	process = BONOBO_PROCESS (bonobo_object_from_servant (servant));
+
+	bonobo_return_if_fail (signum < 0, ev);
+
+	if (kill (process->priv->pid, signum) != 0) {
+		switch (errno) {
+		case EINVAL:
+			return;
+		case EPERM:
+			bonobo_exception_set (ev, 
+					      ex_Bonobo_Process_NoPermission);
+			return;
+		case ESRCH:
+			g_source_remove (process->priv->waitpid_tag);
+			bonobo_process_idle_waitpid (process); 
+			return;
+		}
+	}
+
+	gtk_signal_emit (GTK_OBJECT (process),
+			 signals [SIGNAL_SENT],
+			 signum, 
+			 ev);
+
+	source = BONOBO_EVENT_SOURCE (
+			bonobo_object_query_local_interface (
+				BONOBO_OBJECT (process),
+				"IDL:Bonobo/EventSource:1.0"));
+
+	if (source) {
+		BonoboArg arg;
+		arg._type = TC_CORBA_long;
+		arg._value = &signum;
+		bonobo_event_source_notify_listeners (source,
+						      "signal_sent",
+						      &arg,
+						      ev);
+		bonobo_object_unref (BONOBO_OBJECT (source));
+	}
+}
+
+static CORBA_boolean
+impl_Bonobo_Process_isRunning (PortableServer_Servant  servant, 
+			       CORBA_Environment      *ev)
+{
+	BonoboProcess *process;
+	process = BONOBO_PROCESS (bonobo_object_from_servant (servant));
+
+	if (process->priv->waitpid_tag == 0) 
+		return TRUE;
+	else if (kill (process->priv->pid, 0) != 0 && errno == ESRCH) 
+		return FALSE;
+
+	return TRUE;
+}
+
+static Bonobo_Stream
+impl_Bonobo_Process_getInputStream (PortableServer_Servant  servant, 
+				    CORBA_Environment      *ev)
+{
+	BonoboProcess *process;
+	process = BONOBO_PROCESS (bonobo_object_from_servant (servant));
+
+	if (!process->priv->in_stream)
+		bonobo_exception_set (ev, ex_Bonobo_Process_NoPermission);
+
+	return bonobo_object_dup_ref (process->priv->in_stream, ev);
+}
+
+static Bonobo_Stream
+impl_Bonobo_Process_getOutputStream (PortableServer_Servant  servant, 
+				     CORBA_Environment      *ev)
+{
+	BonoboProcess *process;
+	process = BONOBO_PROCESS (bonobo_object_from_servant (servant));
+
+	if (!process->priv->out_stream)
+		bonobo_exception_set (ev, ex_Bonobo_Process_NoPermission);
+
+	return bonobo_object_dup_ref (process->priv->out_stream, ev);
+}
+
+static Bonobo_Stream
+impl_Bonobo_Process_getErrorStream (PortableServer_Servant  servant, 
+				    CORBA_Environment      *ev)
+{
+	BonoboProcess *process;
+	process = BONOBO_PROCESS (bonobo_object_from_servant (servant));
+
+	if (!process->priv->err_stream)
+		bonobo_exception_set (ev, ex_Bonobo_Process_NoPermission);
+
+	return bonobo_object_dup_ref (process->priv->err_stream, ev);
+}
+
+static void
+bonobo_process_finalize (GtkObject *object)
+{
+	BonoboProcess *process;
+	BonoboProcessPrivate *pr;
+	CORBA_Environment ev;
+
+	process = BONOBO_PROCESS (object);
+	pr = process->priv;
+	
+	if (pr->waitpid_tag) g_source_remove (pr->waitpid_tag);
+
+	CORBA_exception_init (&ev);
+
+	if (pr->in_stream) bonobo_object_release_unref (pr->in_stream, &ev);
+	if (pr->out_stream) bonobo_object_release_unref (pr->out_stream, &ev);
+	if (pr->err_stream) bonobo_object_release_unref (pr->err_stream, &ev);
+
+	CORBA_exception_free (&ev);
+
+	g_free (pr);
+
+	bonobo_process_parent_class->finalize (object);
+}
+
+static void
+bonobo_process_class_init (BonoboProcessClass *klass)
+{
+	GtkObjectClass *oclass = (GtkObjectClass *)klass;
+	POA_Bonobo_Process__epv *epv = &klass->epv;
+
+	bonobo_process_parent_class = gtk_type_class (PARENT_TYPE);
+
+	oclass->finalize = bonobo_process_finalize;
+
+	signals [SIGNAL_SENT] = gtk_signal_new (
+		"signal_sent", GTK_RUN_LAST, oclass->type,
+		GTK_SIGNAL_OFFSET (BonoboProcessClass, signal_sent),
+		gtk_marshal_NONE__INT_POINTER, GTK_TYPE_NONE, 2,
+		GTK_TYPE_INT, GTK_TYPE_POINTER);
+
+	signals [PROCESS_EXIT] = gtk_signal_new (
+		"process_exit", GTK_RUN_LAST, oclass->type,
+		GTK_SIGNAL_OFFSET (BonoboProcessClass, process_exit),
+		gtk_marshal_NONE__INT_POINTER, GTK_TYPE_NONE, 2,
+		GTK_TYPE_INT, GTK_TYPE_POINTER);
+
+	gtk_object_class_add_signals (oclass, signals, LAST_SIGNAL);
+
+	epv->signal          = impl_Bonobo_Process_signal;
+	epv->isRunning       = impl_Bonobo_Process_isRunning;
+	epv->getInputStream  = impl_Bonobo_Process_getInputStream;
+	epv->getOutputStream = impl_Bonobo_Process_getOutputStream;
+	epv->getErrorStream  = impl_Bonobo_Process_getErrorStream;
+}
+
+static void
+bonobo_process_init (GtkObject *object)
+{
+	BonoboProcess *process;
+
+	process = BONOBO_PROCESS(object);
+	process->priv = g_new (BonoboProcessPrivate, 1);
+	process->priv->pid = 0;
+	process->priv->return_val = 0;
+	process->priv->waitpid_tag = 0;
+}
+
+BONOBO_X_TYPE_FUNC_FULL (BonoboProcess, 
+			 Bonobo_Process,
+			 PARENT_TYPE,
+			 bonobo_process);
+
+static gboolean 
+bonobo_process_idle_waitpid (gpointer user_data)
+{
+	BonoboProcess *process = user_data;
+	BonoboEventSource *source;
+	BonoboArg arg;
+	CORBA_Environment ev;
+
+	switch (waitpid (process->priv->pid, 
+			 &process->priv->return_val, 
+			 WNOHANG)) {
+	case 0:
+		return TRUE;
+	case -1:
+		process->priv->waitpid_tag = 0;
+		return FALSE;
+	default:
+		CORBA_exception_init (&ev);
+
+		gtk_signal_emit (GTK_OBJECT (process),
+				 signals [PROCESS_EXIT],
+				 process->priv->return_val, 
+				 ev);
+
+		source = BONOBO_EVENT_SOURCE (
+				bonobo_object_query_local_interface (
+					BONOBO_OBJECT (process),
+					"IDL:Bonobo/EventSource:1.0"));
+
+		if (source) {
+			arg._type = TC_CORBA_long;
+			arg._value = &process->priv->return_val;
+			bonobo_event_source_notify_listeners (source,
+							      "process_exit",
+							      &arg,
+							      &ev);
+			bonobo_object_unref (BONOBO_OBJECT (source));
+		}
+
+		CORBA_exception_free (&ev);
+
+		return FALSE;
+	}
+}
+
+BonoboProcess *
+bonobo_process_attach (pid_t pid)
+{
+	BonoboProcess *process;
+	BonoboEventSource *source;
+
+	if (kill (pid, 0) != 0 && errno == ESRCH) return NULL;
+
+	process = gtk_type_new (BONOBO_PROCESS_TYPE);
+
+	process->priv->pid = pid;
+	process->priv->waitpid_tag = g_idle_add (bonobo_process_idle_waitpid, 
+						 process);
+
+	source = bonobo_event_source_new ();
+
+	bonobo_object_add_interface (BONOBO_OBJECT (process), 
+				     BONOBO_OBJECT (source));
+
+	return process;
+}
+
+BonoboProcess *
+bonobo_process_attach_full (pid_t         pid,
+			    Bonobo_Stream in_stream,
+			    Bonobo_Stream out_stream,
+			    Bonobo_Stream err_stream)
+{
+	BonoboProcess *process;
+
+	process = bonobo_process_attach (pid);
+
+	if (process) {
+		CORBA_Environment ev;
+		CORBA_exception_init (&ev);
+
+		if (in_stream) 
+			process->priv->in_stream = 
+				bonobo_object_dup_ref (in_stream, &ev);
+		if (out_stream) 
+			process->priv->out_stream = 
+				bonobo_object_dup_ref (out_stream, &ev);
+		if (err_stream) 
+			process->priv->err_stream = 
+				bonobo_object_dup_ref (err_stream, &ev);
+
+		CORBA_exception_free (&ev);
+	}
+
+	return process;
+}
Index: bonobo/bonobo-process.h
===================================================================
RCS file: bonobo-process.h
diff -N bonobo-process.h
--- /dev/null	Tue May  5 16:32:27 1998
+++ bonobo-process.h	Wed Jun  6 14:13:02 2001
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * bonobo-process.h: Generic process interface for callbacks.
+ *
+ * Authors:
+ *	Alex Graveley (alex helixcode com)
+ *
+ * Copyright (C) 2000, Helix Code, Inc.
+ */
+
+#ifndef _BONOBO_PROCESS_H_
+#define _BONOBO_PROCESS_H_
+
+#include <sys/types.h>
+#include <bonobo/bonobo-arg.h>
+#include <bonobo/bonobo-xobject.h>
+
+BEGIN_GNOME_DECLS
+
+#define BONOBO_PROCESS_TYPE        (bonobo_process_get_type ())
+#define BONOBO_PROCESS(o)          (GTK_CHECK_CAST ((o), BONOBO_PROCESS_TYPE, BonoboProcess))
+#define BONOBO_PROCESS_CLASS(k)    (GTK_CHECK_CLASS_CAST((k), BONOBO_PROCESS_TYPE, BonoboProcessClass))
+#define BONOBO_IS_PROCESS(o)       (GTK_CHECK_TYPE ((o), BONOBO_PROCESS_TYPE))
+#define BONOBO_IS_PROCESS_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), BONOBO_PROCESS_TYPE))
+
+typedef struct _BonoboProcessPrivate BonoboProcessPrivate;
+
+typedef struct {
+        BonoboXObject          parent;
+
+	BonoboProcessPrivate  *priv;
+} BonoboProcess;
+
+typedef struct {
+	BonoboXObjectClass     parent_class;
+
+	POA_Bonobo_Process__epv epv;
+
+	/* Signals */
+	void (* signal_sent)  (BonoboProcess     *process, 
+			       CORBA_long         signal,
+			       CORBA_Environment *ev);
+
+	void (* process_exit) (BonoboProcess     *process, 
+			       CORBA_long         retval,
+			       CORBA_Environment *ev);
+} BonoboProcessClass;
+
+GtkType         bonobo_process_get_type    (void);
+
+BonoboProcess  *bonobo_process_attach      (pid_t pid);
+
+BonoboProcess  *bonobo_process_attach_full (pid_t         pid,
+					    Bonobo_Stream in_stream,
+					    Bonobo_Stream out_stream,
+					    Bonobo_Stream err_stream);
+
+END_GNOME_DECLS
+
+#endif /* _BONOBO_PROCESS_H_ */
+
Index: bonobo/bonobo-stream-fd.c
===================================================================
RCS file: bonobo-stream-fd.c
diff -N bonobo-stream-fd.c
--- /dev/null	Tue May  5 16:32:27 1998
+++ bonobo-stream-fd.c	Wed Jun  6 14:13:02 2001
@@ -0,0 +1,403 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/**
+ * bonobo-stream-fd.c: Unix file descriptor based stream
+ *
+ * Author:
+ *   Alex Graveley (alex ximian com)
+ *
+ * Copyright 2001, Ximian, Inc.
+ */
+
+#include <config.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-util.h>
+#include <bonobo/bonobo-exception.h>
+#include <bonobo/bonobo-stream-fd.h>
+
+static BonoboStreamClass *bonobo_stream_fd_parent_class;
+
+static Bonobo_StorageInfo*
+fd_get_info (BonoboStream                   *stream,
+	     const Bonobo_StorageInfoFields  mask,
+	     CORBA_Environment              *ev)
+{
+	Bonobo_StorageInfo *si;
+
+	si = Bonobo_StorageInfo__alloc ();
+
+	si->size = -1;
+	si->type = Bonobo_STORAGE_TYPE_REGULAR;
+	si->name = CORBA_string_dup ("");
+	si->content_type = CORBA_string_dup ("application/octet-stream");
+
+	return si;
+}
+
+static void
+fd_set_info (BonoboStream *stream,
+	     const Bonobo_StorageInfo *info,
+	     const Bonobo_StorageInfoFields mask,
+	     CORBA_Environment *ev)
+{
+	bonobo_exception_set (ev, ex_Bonobo_Stream_NotSupported);
+}
+
+static void
+fd_truncate (BonoboStream *stream,
+	     const CORBA_long new_size, 
+	     CORBA_Environment *ev)
+{
+	BonoboStreamFd *sfd = BONOBO_STREAM_FD (stream);
+	
+	if (!(sfd->mode & BONOBO_STREAM_FD_TRUNCATE)) {
+		bonobo_exception_set (ev, ex_Bonobo_Stream_NotSupported);
+		return;
+	}
+
+	if (ftruncate (sfd->fd, new_size) < 0)
+		bonobo_exception_set (ev, ex_Bonobo_Stream_NoPermission);
+}
+
+static void
+fd_write (BonoboStream *stream, 
+	  const Bonobo_Stream_iobuf *buffer,
+	  CORBA_Environment *ev)
+{
+	BonoboStreamFd *sfd = BONOBO_STREAM_FD (stream);
+	gint result = 0, total = 0;
+
+	if (!(sfd->mode & BONOBO_STREAM_FD_WRITE)) {
+		bonobo_exception_set (ev, ex_Bonobo_Stream_NotSupported);
+		return;
+	}
+
+	while (total < buffer->_length) {
+		result = write (sfd->fd, buffer->_buffer, buffer->_length);
+
+		if (result < 0) {
+			switch (errno) {
+			case EBADF:
+			case EINVAL:
+			case EISDIR:
+				bonobo_exception_set (
+				        ev, 
+					ex_Bonobo_Stream_NoPermission);
+			default:
+				bonobo_exception_set (
+				        ev, 
+					ex_Bonobo_Stream_IOError);
+			}
+			return;
+		}
+
+		total -= result;
+	}
+}
+
+static void
+fd_read (BonoboStream          *stream, 
+	 CORBA_long             count,
+	 Bonobo_Stream_iobuf  **buffer,
+	 CORBA_Environment     *ev)
+{
+	BonoboStreamFd *sfd = BONOBO_STREAM_FD (stream);
+	gint result = 0;
+
+	if (!(sfd->mode & BONOBO_STREAM_FD_READ)) {
+		bonobo_exception_set (ev, ex_Bonobo_Stream_NotSupported);
+		return;
+	}
+
+	*buffer = Bonobo_Stream_iobuf__alloc ();
+	CORBA_sequence_set_release (*buffer, TRUE);
+	(*buffer)->_buffer = CORBA_sequence_CORBA_octet_allocbuf (count);
+	(*buffer)->_length = count;
+
+	while (count) {
+		result = read (sfd->fd, (*buffer)->_buffer, count);
+
+		if (result < 0) {
+			switch (errno) {
+			case EBADF:
+			case EINVAL:
+			case EISDIR:
+				bonobo_exception_set (
+				        ev, 
+					ex_Bonobo_Stream_NoPermission);
+			default:
+				bonobo_exception_set (
+				        ev, 
+					ex_Bonobo_Stream_IOError);
+			}
+			return;
+		} else if (result == 0) {
+			(*buffer)->_length -= count;
+			break;
+		}
+
+		count -= result;
+	}
+}
+
+static CORBA_long
+fd_seek (BonoboStream *stream,
+	 CORBA_long offset, 
+	 Bonobo_Stream_SeekType whence,
+	 CORBA_Environment *ev)
+{
+	BonoboStreamFd *sfd = BONOBO_STREAM_FD (stream);
+	int pos = 0;
+
+	if (!(sfd->mode & BONOBO_STREAM_FD_SEEK)) {
+		bonobo_exception_set (ev, ex_Bonobo_Stream_NotSupported);
+		return pos;
+	}
+	
+	switch (whence){
+	case Bonobo_Stream_SEEK_SET:
+		whence = SEEK_SET;
+		break;
+
+	case Bonobo_Stream_SEEK_CUR:
+		whence = SEEK_CUR;
+		break;
+
+	case Bonobo_Stream_SEEK_END:
+		whence = SEEK_END;
+		break;
+	default:
+		g_warning ("Signal exception");
+	}
+
+	pos = lseek (sfd->fd, (off_t) offset, whence);
+
+	if (pos < 0) {
+		bonobo_exception_set (ev, ex_Bonobo_Stream_IOError);
+		return 0;
+	}
+
+	return pos;
+}
+
+#define COPY_TO_BLOCK_SIZE 8192
+
+static void
+fd_copy_to  (BonoboStream *stream,
+	     const CORBA_char *dest,
+	     const CORBA_long bytes,
+	     CORBA_long *read,
+	     CORBA_long *written,
+	     CORBA_Environment *ev)
+{
+	int dest_fd;
+
+	if (*dest == '\0' || (bytes < -1 || bytes == 0)) {
+		bonobo_exception_set (ev, ex_Bonobo_Stream_IOError);
+		return;
+	}
+
+	dest_fd = open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND);
+
+	if (dest_fd < 0) {
+		bonobo_exception_set (ev, ex_Bonobo_Stream_NoPermission);
+		return;
+	}
+
+	while (1) {
+		Bonobo_Stream_iobuf *buf;
+		int result;
+
+		fd_read (stream, COPY_TO_BLOCK_SIZE, &buf, ev);
+
+		if (buf->_length == 0 || BONOBO_EX (ev)) break;
+
+		*read += buf->_length;
+
+		result = write (dest_fd, buf->_buffer, buf->_length);
+
+		if (result < 0) {
+			switch (errno) {
+			case EBADF:
+			case EINVAL:
+			case EISDIR:
+				bonobo_exception_set (
+				        ev, 
+					ex_Bonobo_Stream_NoPermission);
+			default:
+				bonobo_exception_set (
+				        ev, 
+					ex_Bonobo_Stream_IOError);
+			}
+			break;
+		}
+
+		*written += result;
+	};
+}
+
+static void
+fd_commit (BonoboStream *stream, CORBA_Environment *ev)
+{
+	bonobo_exception_set (ev, ex_Bonobo_Stream_NotSupported);
+}
+
+static void
+fd_revert (BonoboStream *stream, CORBA_Environment *ev)
+{
+	bonobo_exception_set (ev, ex_Bonobo_Stream_NotSupported);
+}
+
+static void
+fd_destroy (GtkObject *object)
+{
+	BonoboStreamFd *sfd = BONOBO_STREAM_FD (object);
+
+	if (sfd->own_fd) close (sfd->fd);
+
+	GTK_OBJECT_CLASS (bonobo_stream_fd_parent_class)->destroy (object);
+}
+
+static int
+fd_get_unix_fd (BonoboStreamFd *stream_fd)
+{
+	g_return_val_if_fail (BONOBO_IS_STREAM_FD (stream_fd), -1);
+
+	return stream_fd->fd;
+}
+
+static void
+bonobo_stream_fd_class_init (BonoboStreamFdClass *klass)
+{
+	GtkObjectClass *object_class = (GtkObjectClass *) klass;
+	BonoboStreamClass *sclass = BONOBO_STREAM_CLASS (klass);
+	
+	bonobo_stream_fd_parent_class = gtk_type_class (bonobo_stream_get_type ());
+
+	object_class->destroy = fd_destroy;
+	
+	sclass->get_info   = fd_get_info;
+	sclass->set_info   = fd_set_info;
+	sclass->write      = fd_write;
+	sclass->read       = fd_read;
+	sclass->seek       = fd_seek;
+	sclass->truncate   = fd_truncate;
+	sclass->copy_to    = fd_copy_to;
+	sclass->commit     = fd_commit;
+	sclass->revert     = fd_revert;
+
+	klass->get_unix_fd = fd_get_unix_fd;
+}
+
+/**
+ * bonobo_stream_fd_get_type:
+ *
+ * Returns: the GtkType of the BonoboStreamFd class.
+ */
+GtkType
+bonobo_stream_fd_get_type (void)
+{
+	static GtkType type = 0;
+
+	if (!type){
+		GtkTypeInfo info = {
+			"BonoboStreamFd",
+			sizeof (BonoboStreamFd),
+			sizeof (BonoboStreamFdClass),
+			(GtkClassInitFunc) bonobo_stream_fd_class_init,
+			(GtkObjectInitFunc) NULL,
+			NULL, /* reserved 1 */
+			NULL, /* reserved 2 */
+			(GtkClassInitFunc) NULL
+		};
+
+		type = gtk_type_unique (bonobo_stream_get_type (), &info);
+	}
+
+	return type;
+}
+
+BonoboStreamFd *
+bonobo_stream_fd_construct (BonoboStreamFd  *stream_fd,
+			    Bonobo_Stream    corba_stream,
+			    int              fd,
+			    int              mode,
+			    gboolean         take_ownership)
+{
+	g_return_val_if_fail (corba_stream != CORBA_OBJECT_NIL, NULL);
+	g_return_val_if_fail (BONOBO_IS_STREAM_FD (stream_fd), NULL);
+
+	stream_fd->fd = fd;
+	stream_fd->mode = mode;
+	stream_fd->own_fd = take_ownership;
+
+	return BONOBO_STREAM_FD (
+		bonobo_object_construct (BONOBO_OBJECT (stream_fd),
+					 corba_stream));
+}
+
+/**
+ * bonobo_stream_fd_create:
+ * @buffer: The data for which a BonoboStreamFd object is to be created.
+ * @size: The size in bytes of @buffer.
+ * @read_only: Specifies whether or not the returned BonoboStreamFd
+ * object should allow write() operations.
+ * @resizable: Whether or not the buffer should be resized as needed.
+ *
+ * Creates a new BonoboStreamFd object.
+ *
+ * If @buffer is non-%NULL, @size bytes are copied from it into a new
+ * buffer. If @buffer is %NULL, a new buffer of size @size is created
+ * and filled with zero bytes.
+ *
+ * When data is read out of or (if @read_only is FALSE) written into
+ * the returned BonoboStream object, the read() and write() operations
+ * operate on the new buffer. If @resizable is TRUE, writing or seeking
+ * past the end of the buffer will cause the buffer to be expanded (with
+ * the new space zero-filled for a seek).
+ *
+ * Returns: the constructed BonoboStream object
+ **/
+BonoboStream *
+bonobo_stream_fd_create (int fd, int mode, gboolean take_ownership)
+{
+	BonoboStreamFd *stream_fd;
+	Bonobo_Stream corba_stream;
+
+	stream_fd = gtk_type_new (bonobo_stream_fd_get_type ());
+	if (stream_fd == NULL)
+		return NULL;
+
+	corba_stream = bonobo_stream_corba_object_create (
+		BONOBO_OBJECT (stream_fd));
+
+	if (corba_stream == CORBA_OBJECT_NIL) {
+		bonobo_object_unref (BONOBO_OBJECT (stream_fd));
+		return NULL;
+	}
+
+	return BONOBO_STREAM (bonobo_stream_fd_construct (stream_fd, 
+							  corba_stream, 
+							  fd, 
+							  mode, 
+							  take_ownership));
+}
+
+/**
+ * bonobo_stream_fd_get_unix_fd:
+ * @stream_fd: a BonoboStreamFd
+ *
+ * Returns the UNIX file descriptor associated with a BonoboStreamFd
+ *
+ * Return value: the fd.
+ **/
+int
+bonobo_stream_fd_get_unix_fd (BonoboStreamFd *stream_fd)
+{
+	return BONOBO_STREAM_FD_CLASS(
+		GTK_OBJECT(stream_fd)->klass)->get_unix_fd (stream_fd);
+}
Index: bonobo/bonobo-stream-fd.h
===================================================================
RCS file: bonobo-stream-fd.h
diff -N bonobo-stream-fd.h
--- /dev/null	Tue May  5 16:32:27 1998
+++ bonobo-stream-fd.h	Wed Jun  6 14:13:02 2001
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/**
+ * bonobo-stream-fd.h: Unix file descriptor based stream
+ *
+ * Author:
+ *   Alex Graveley (alex ximian com)
+ *
+ * Copyright 2001, Ximian, Inc.
+ */
+
+#ifndef _BONOBO_STREAM_FD_H_
+#define _BONOBO_STREAM_FD_H_
+
+#include <bonobo/bonobo-stream.h>
+
+BEGIN_GNOME_DECLS
+
+#define BONOBO_STREAM_FD_TYPE        (bonobo_stream_fd_get_type ())
+#define BONOBO_STREAM_FD(o)          (GTK_CHECK_CAST ((o), BONOBO_STREAM_FD_TYPE, BonoboStreamFd))
+#define BONOBO_STREAM_FD_CLASS(k)    (GTK_CHECK_CLASS_CAST((k), BONOBO_STREAM_FD_TYPE, BonoboStreamFdClass))
+#define BONOBO_IS_STREAM_FD(o)       (GTK_CHECK_TYPE ((o), BONOBO_STREAM_FD_TYPE))
+#define BONOBO_IS_STREAM_FD_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), BONOBO_STREAM_FD_TYPE))
+
+typedef enum {
+	BONOBO_STREAM_FD_READ      = (1 << 0),
+	BONOBO_STREAM_FD_WRITE     = (1 << 1),
+	BONOBO_STREAM_FD_SEEK      = (1 << 2),
+	BONOBO_STREAM_FD_TRUNCATE  = (1 << 3),
+
+	BONOBO_STREAM_FD_SOCKET    = (BONOBO_STREAM_FD_READ | 
+				      BONOBO_STREAM_FD_WRITE),
+
+	BONOBO_STREAM_FD_FILE      = (BONOBO_STREAM_FD_READ | 
+				      BONOBO_STREAM_FD_WRITE |
+				      BONOBO_STREAM_FD_SEEK | 
+				      BONOBO_STREAM_FD_TRUNCATE)
+} BonoboStreamFdMode;
+
+typedef struct _BonoboStreamFdPrivate BonoboStreamFdPrivate;
+
+typedef struct {
+	BonoboStream  stream;
+
+	int           fd;
+	int           mode;
+	gboolean      own_fd;
+
+	BonoboStreamFdPrivate *priv;
+} BonoboStreamFd;
+
+typedef struct {
+	BonoboStreamClass parent_class;
+	int             (*get_unix_fd) (BonoboStreamFd *stream_fd);
+} BonoboStreamFdClass;
+
+GtkType         bonobo_stream_fd_get_type    (void);
+BonoboStreamFd *bonobo_stream_fd_construct   (BonoboStreamFd *stream_fd,
+					      Bonobo_Stream   corba_stream,
+					      int             fd,
+					      int             mode,
+					      gboolean        take_ownership);
+
+BonoboStream   *bonobo_stream_fd_create      (int             fd,
+					      int             mode,
+					      gboolean        take_ownership);
+
+int             bonobo_stream_fd_get_unix_fd (BonoboStreamFd  *stream_fd);
+
+END_GNOME_DECLS
+
+#endif /* _BONOBO_STREAM_FD_H_ */
Index: idl/Bonobo.idl
===================================================================
RCS file: /cvs/gnome/bonobo/idl/Bonobo.idl,v
retrieving revision 1.44
diff -u -r1.44 Bonobo.idl
--- idl/Bonobo.idl	2001/01/25 20:01:15	1.44
+++ idl/Bonobo.idl	2001/06/06 18:13:02
@@ -45,6 +45,7 @@
 
 /* Misc. stuff. */
 #include <Bonobo_Desktop.idl>
+#include <Bonobo_Process.idl>
 
 #if !defined(__BONOBO_COMPILATION) && defined(__ORBIT_IDL__)
 #pragma inhibit pop
Index: idl/Bonobo_Process.idl
===================================================================
RCS file: Bonobo_Process.idl
diff -N Bonobo_Process.idl
--- /dev/null	Tue May  5 16:32:27 1998
+++ Bonobo_Process.idl	Wed Jun  6 14:13:02 2001
@@ -0,0 +1,40 @@
+/*
+ * bonobo-process.idl: UNIX Process manipulation.
+ *
+ * Copyright (C) 1999, 2000  Helix Code, Inc.
+ *
+ * Author:
+ *    Alex Graveley (alex ximian com)
+ *
+ * Terms:
+ *
+ *    Process:   This interface provides access to a currently running 
+ *               process, and allows signalling the process, and accessing 
+ *               the STDIN, STDOUT, and STDERR using Streams.
+ *
+ */
+
+#ifndef BONOBO_PROCESS_IDL
+#define BONOBO_PROCESS_IDL
+
+#include "Bonobo_Unknown.idl"
+
+module Bonobo {
+
+	interface Process : Unknown {
+		exception NoPermission {};
+
+		void signal (in long signum) raises (NoPermission);
+
+		boolean isRunning ();
+
+		Stream getInputStream () raises (NoPermission);
+
+		Stream getOutputStream () raises (NoPermission);
+
+		Stream getErrorStream () raises (NoPermission);
+	};
+
+};
+
+#endif /* BONOBO_PROCESS_IDL */
Index: monikers/Bonobo_Moniker_exec.oaf.in
===================================================================
RCS file: Bonobo_Moniker_exec.oaf.in
diff -N Bonobo_Moniker_exec.oaf.in
--- /dev/null	Tue May  5 16:32:27 1998
+++ Bonobo_Moniker_exec.oaf.in	Wed Jun  6 14:13:02 2001
@@ -0,0 +1,30 @@
+<oaf_info>
+
+<oaf_server iid="OAFIID:Bonobo_Moniker_exec_Factory" 
+	    type="exe"
+	    location="bonobo-moniker-exec">
+	<oaf_attribute name="repo_ids" type="stringv">
+		<item value="IDL:GNOME/GenericFactory:1.0"/>
+	</oaf_attribute>
+
+	<oaf_attribute name="name" 
+		       type="string" 
+		       _value="Process Execution Moniker factory"/>
+</oaf_server>
+
+<oaf_server iid="OAFIID:Bonobo_Moniker_exec" 
+	    type="factory"
+	    location="OAFIID:Bonobo_Moniker_exec_Factory">
+	<oaf_attribute name="repo_ids" type="stringv">
+		<item value="IDL:Bonobo/Moniker:1.0"/>
+		<item value="IDL:Bonobo/Unknown:1.0"/>
+	</oaf_attribute>
+	<oaf_attribute name="name" 
+		       type="string" 
+		       _value="Process Execution Moniker"/>
+	<oaf_attribute name="bonobo:moniker" type="stringv">
+		<item value="exec:"/>
+	</oaf_attribute>
+</oaf_server>
+
+</oaf_info>
Index: monikers/Bonobo_Moniker_std.oaf.in.in
===================================================================
RCS file: /cvs/gnome/bonobo/monikers/Bonobo_Moniker_std.oaf.in.in,v
retrieving revision 1.3
diff -u -r1.3 Bonobo_Moniker_std.oaf.in.in
--- monikers/Bonobo_Moniker_std.oaf.in.in	2001/01/25 09:26:21	1.3
+++ monikers/Bonobo_Moniker_std.oaf.in.in	2001/06/06 18:13:02
@@ -100,6 +100,7 @@
 		<item value="IDL:Bonobo/Unknown:1.0"/>
 	</oaf_attribute>
 	<oaf_attribute name="bonobo:moniker_extender" type="stringv">
+		<item value="exec:"/>
 		<item value="file:"/>
 		<item value="http:"/>
 		<item value="gunzip:"/>
Index: monikers/Makefile.am
===================================================================
RCS file: /cvs/gnome/bonobo/monikers/Makefile.am,v
retrieving revision 1.37
diff -u -r1.37 Makefile.am
--- monikers/Makefile.am	2001/05/05 22:57:34	1.37
+++ monikers/Makefile.am	2001/06/06 18:13:02
@@ -8,6 +8,7 @@
 	$(BONOBO_TEST_CFLAGS)
 
 OAF_FILES =					\
+	Bonobo_Moniker_exec.oaf.in		\
 	Bonobo_Moniker_gzip.oaf.in		\
 	Bonobo_Moniker_http.oaf.in
 
@@ -26,6 +27,7 @@
 moniker_LTLIBRARIES = libmoniker_std.la
 
 bin_PROGRAMS = 				\
+	bonobo-moniker-exec 		\
 	bonobo-moniker-gunzip 		\
 	bonobo-moniker-http		\
 	moniker-test
@@ -57,6 +59,12 @@
 	bonobo-moniker-std.c			
 
 libmoniker_std_la_LDFLAGS = -module
+
+bonobo_moniker_exec_SOURCES =		\
+	bonobo-moniker-exec.c
+
+bonobo_moniker_exec_LDADD =		\
+	$(moniker_ldadd)
 
 bonobo_moniker_gunzip_SOURCES =		\
 	bonobo-moniker-gunzip.c		\
Index: monikers/bonobo-moniker-exec.c
===================================================================
RCS file: bonobo-moniker-exec.c
diff -N bonobo-moniker-exec.c
--- /dev/null	Tue May  5 16:32:27 1998
+++ bonobo-moniker-exec.c	Wed Jun  6 14:13:02 2001
@@ -0,0 +1,321 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * bonobo-moniker-file.c: Process execution Moniker implementation
+ *
+ * Author:
+ *	Alex Graveley (alex ximian com)
+ *
+ * Copyright 2001, Ximian, Inc.
+ */
+
+#include <config.h>
+
+#include <bonobo/bonobo.h>
+#include <bonobo/bonobo-stream-fd.h>
+#include <bonobo/bonobo-moniker-extender.h>
+
+typedef struct {
+	gchar *path;
+	gchar *host;
+	gchar *user;
+	gchar *passwd;
+	gchar *rsh;
+} BonoboExecProcessInit;
+
+static BonoboExecProcessInit *
+bonobo_moniker_exec_parse_path (const gchar *path)
+{
+	BonoboExecProcessInit  *pi;
+	gchar                 **split, **split2;
+	gint                    x = 0;
+
+	split = g_strsplit (path, ";", 0);
+
+	if (!split || !split [0] || !split [0][0]) return NULL;
+
+	pi = g_new0 (BonoboExecProcessInit, 1);
+
+	while (split [x]) {
+		split2 = g_strsplit (split [x], "=", 0);
+
+		if (split2 [1]) {
+			g_strstrip (split2 [0]);
+			g_strstrip (split2 [1]);
+
+			if (!strcmp ("host", split2 [0]))
+				pi->host = g_strdup (split2 [1]);
+			else if (!strcmp ("user", split2 [0]))
+				pi->user = g_strdup (split2 [1]);
+			else if (!strcmp ("passwd", split2 [0]))
+				pi->passwd = g_strdup (split2 [1]);
+			else if (!strcmp ("rsh", split2 [0]))
+				pi->rsh = g_strdup (split2 [1]);
+			else g_warning ("Unknown option \"%s=%s\" "
+					"passed to Bonobo exec moniker", 
+					split2 [0], 
+					split2 [1]);
+		} else {
+			if (!pi->path) pi->path = g_strdup (split2 [0]);
+			else g_warning ("Two exec paths passed to "
+					"Bonobo exec moniker");
+		}
+
+		g_strfreev (split2);
+		x++;
+	}
+
+	g_strfreev (split);
+
+	return pi;
+}
+
+typedef struct {
+	Bonobo_Stream  in_stream;
+	Bonobo_Stream  out_stream;
+	Bonobo_Process process;
+} BonoboExecReader;
+
+static gboolean
+bonobo_moniker_exec_stdin_reader (BonoboExecReader *reader)
+{
+	CORBA_Environment  ev;
+	gchar             *buf;
+	gint               bytes_read;
+
+	CORBA_exception_init (&ev);
+
+	buf = bonobo_stream_client_read (reader->in_stream,
+					 4096,
+					 &bytes_read,
+					 &ev);
+
+	if (BONOBO_EX (&ev)) goto FINISHED_READ;
+	if (!bytes_read) return TRUE;
+
+	bonobo_stream_client_write (reader->out_stream,
+				    buf,
+				    bytes_read,
+				    &ev);
+
+
+	CORBA_exception_free (&ev);
+
+	return TRUE;
+
+ FINISHED_READ:
+	bonobo_object_release_unref (reader->in_stream, &ev);
+	bonobo_object_release_unref (reader->out_stream, &ev);
+	bonobo_object_release_unref (reader->process, &ev);
+	g_free (reader);
+
+	CORBA_exception_free (&ev);
+
+	return FALSE;
+}
+
+static Bonobo_Unknown
+bonobo_moniker_exec_resolve (BonoboMoniker               *moniker,
+			     const Bonobo_ResolveOptions *options,
+			     const CORBA_char            *requested_interface,
+			     CORBA_Environment           *ev)
+{
+	Bonobo_Unknown         retval = NULL;
+	Bonobo_Moniker         parent;
+	Bonobo_Stream          in_stream = NULL;
+	BonoboProcess         *process;
+	BonoboStream          *io_streams [3] = { NULL, NULL, NULL };
+	const char            *path;
+	BonoboExecProcessInit *pi;
+	BonoboExecReader      *read_state;
+	gint                   pair [3][2] = { {0,0}, {0,0}, {0,0} };
+	gint                   pid;
+
+	if (strcmp (requested_interface, "IDL:Bonobo/Process:1.0") || 
+	    strcmp (requested_interface, "IDL:Bonobo/Stream:1.0"))
+		return bonobo_moniker_use_extender (
+			"OAFIID:Bonobo_MonikerExtender_exec",
+			moniker, 
+			options, 
+			requested_interface, 
+			ev);
+
+	parent = bonobo_moniker_get_parent (moniker, ev);
+	if (BONOBO_EX (ev)) return NULL;
+
+	if (parent) {
+		in_stream = Bonobo_Moniker_resolve (parent, 
+						    options,
+						    "IDL:Bonobo/Stream:1.0", 
+						    ev);
+
+		if (BONOBO_EX (ev) || !in_stream) {
+			bonobo_object_release_unref (parent, ev);
+			return NULL;
+		}
+	}
+
+	path = bonobo_moniker_get_name (moniker);
+	pi = bonobo_moniker_exec_parse_path (path);
+
+	if (!pi) return NULL;
+	if (!pi->path) goto ERROR;
+
+	if (pipe (pair [0]) < 0) goto ERROR;
+	if (pipe (pair [1]) < 0) goto PIPE_ERROR;
+	if (pipe (pair [2]) < 0) goto PIPE_ERROR;
+
+	pid = fork ();
+
+	switch (pid) {
+	case -1:
+		goto PIPE_ERROR;
+	case 0:
+		dup2 (pair [0][0], STDIN_FILENO);
+		dup2 (pair [1][1], STDOUT_FILENO);
+		dup2 (pair [2][1], STDERR_FILENO);
+
+		/* FIXME: handle sending of password correctly. 
+		          fork twice and sniff stdout for something 
+			  resembling a password prompt. */
+		if (pi->user && pi->passwd) {
+			write (pair [0][1], 
+			       pi->passwd, 
+			       strlen (pi->passwd));
+			write (pair [0][1], "\n", 1);
+		}
+
+		close (pair [0][0]);
+		close (pair [0][1]);
+		close (pair [1][0]);
+		close (pair [1][1]);
+		close (pair [2][0]);
+		close (pair [2][1]);
+
+		if (pi->host) {
+			if (pi->user) 
+				execlp (pi->rsh ? pi->rsh : "rsh", 
+					pi->rsh ? pi->rsh : "rsh", 
+					"-l",
+					pi->user,
+					pi->host,
+					pi->path, 
+					NULL);
+			else 
+				execlp (pi->rsh ? pi->rsh : "rsh", 
+					pi->rsh ? pi->rsh : "rsh", 
+					pi->host,
+					pi->path, 
+					NULL);
+		} else if (pi->user) 
+			execlp ("su", 
+				"su", 
+				"-c", 
+				pi->path, 
+				pi->user, 
+				NULL);
+		else 
+			execlp ("sh", 
+				"sh", 
+				"-c", 
+				pi->path, 
+				NULL);
+	}
+
+	close (pair [0][0]); pair [0][0] = 0;
+	close (pair [1][1]); pair [1][1] = 0;
+	close (pair [2][1]); pair [2][1] = 0;
+
+	/* STDIN is created for writing by BonoboProcess clients */
+	io_streams [0] = 
+		bonobo_stream_fd_create (pair [0][1],
+					 BONOBO_STREAM_FD_WRITE,
+					 TRUE);
+
+	/* STDOUT and STDERR are created for reading by BonoboProcess clients */
+	io_streams [1] = 
+		bonobo_stream_fd_create (pair [1][0],
+					 BONOBO_STREAM_FD_READ,
+					 TRUE);
+	io_streams [2] = 
+		bonobo_stream_fd_create (pair [2][0],
+					 BONOBO_STREAM_FD_READ,
+					 TRUE);
+
+	process = bonobo_process_attach_full (pid,
+					      BONOBO_OBJREF (io_streams [0]),
+					      BONOBO_OBJREF (io_streams [1]),
+					      BONOBO_OBJREF (io_streams [2]));
+	if (!process) goto PROCESS_ERROR;
+
+	if (in_stream) {
+		read_state = g_new0 (BonoboExecReader, 1);
+		read_state->in_stream = in_stream;
+		read_state->out_stream = 
+			bonobo_object_dup_ref (BONOBO_OBJREF (io_streams [0]),
+					       ev);
+		read_state->process = 
+			bonobo_object_dup_ref (BONOBO_OBJREF (process),
+					       ev);
+
+		g_idle_add ((GSourceFunc) bonobo_moniker_exec_stdin_reader, 
+			    read_state);
+
+		bonobo_object_release_unref (parent, ev);
+	}
+
+	if (!strcmp (requested_interface, "IDL:Bonobo/Stream:1.0")) {
+		retval = BONOBO_OBJREF (io_streams [1]);
+		bonobo_object_unref (BONOBO_OBJECT (io_streams [0]));
+		bonobo_object_unref (BONOBO_OBJECT (io_streams [2]));
+	} else {
+		retval = BONOBO_OBJREF (process);
+		bonobo_object_unref (BONOBO_OBJECT (io_streams [0]));
+		bonobo_object_unref (BONOBO_OBJECT (io_streams [1]));
+		bonobo_object_unref (BONOBO_OBJECT (io_streams [2]));
+	}
+
+ ERROR:
+	g_free (pi->path);
+	g_free (pi->host);
+	g_free (pi->user);
+	g_free (pi->passwd);
+	g_free (pi->rsh);
+	g_free (pi);
+	
+	return retval;
+
+ PIPE_ERROR:
+	{
+		int x;
+		for (x = 0; x < 3; x++) {
+			if (pair [x][0]) close (pair [x][0]);
+			if (pair [x][1]) close (pair [x][1]);
+		}
+		goto ERROR;
+	}
+
+ PROCESS_ERROR:
+	{
+		int x;
+		for (x = 0; x < 3; x++)
+			if (io_streams [x]) 
+				bonobo_object_unref (
+					BONOBO_OBJECT (io_streams [x]));
+		goto ERROR;
+	}		
+}
+
+static BonoboObject *
+bonobo_moniker_exec_factory (BonoboGenericFactory *this, void *closure)
+{
+	BonoboMoniker *moniker;
+	moniker = bonobo_moniker_simple_new ("exec:", 
+					     bonobo_moniker_exec_resolve);
+	return BONOBO_OBJECT (moniker);
+}
+
+BONOBO_OAF_FACTORY ("OAFIID:Bonobo_Moniker_exec_Factory",
+		    "exec-moniker", VERSION,
+		    bonobo_moniker_exec_factory,
+		    NULL)
+
Index: monikers/moniker-test.c
===================================================================
RCS file: /cvs/gnome/bonobo/monikers/moniker-test.c,v
retrieving revision 1.10
diff -u -r1.10 moniker-test.c
--- monikers/moniker-test.c	2001/01/25 09:26:21	1.10
+++ monikers/moniker-test.c	2001/06/06 18:13:02
@@ -15,6 +15,7 @@
 
 #include <glib.h>
 #include <gnome.h>
+#include <unistd.h>
 #include <liboaf/liboaf.h>
 #include <bonobo.h>
 
@@ -23,6 +24,7 @@
 static void display_as_storage_file_list (const char *moniker, CORBA_Environment *ev);
 static void display_as_html (const char *moniker, CORBA_Environment *ev);
 static void display_as_control (const char *moniker, CORBA_Environment *ev);
+static void display_as_process (const char *moniker, CORBA_Environment *ev);
 
 typedef enum {
     AS_NONE = 0,
@@ -30,7 +32,8 @@
     AS_STREAM,
     AS_STORAGE_FILE_LIST,
     AS_HTML,
-    AS_CONTROL
+    AS_CONTROL,
+    AS_PROCESS
 } MonikerTestDisplayAs;
 
 typedef void (*MonikerDisplayFunction) (const char *moniker, CORBA_Environment *ev);
@@ -46,6 +49,7 @@
     {AS_STORAGE_FILE_LIST, display_as_storage_file_list},
     {AS_HTML, display_as_html},
     {AS_CONTROL, display_as_control},
+    {AS_PROCESS, display_as_process},
     {0}
 };
 
@@ -55,7 +59,7 @@
     MonikerTestDisplayAs display_as;
     gchar *moniker;
 
-    int ps, pr, pc, ph;
+    int ps, pr, pc, ph, pp;
 } MonikerTestOptions;
 
 MonikerTestOptions global_mto = { NULL };
@@ -66,6 +70,7 @@
     {"storage",   'r', POPT_ARG_NONE, &global_mto.pr, 'r', "request Bonobo/Storage", NULL },
     {"control",   'c', POPT_ARG_NONE, &global_mto.pc, 'c', "request Bonobo/Control", NULL },
     {"html",      'h', POPT_ARG_NONE, &global_mto.ph, 'h', "request Bonobo/Stream and display as HTML", NULL },
+    {"process",   'p', POPT_ARG_NONE, &global_mto.pp, 'p', "request Bonobo/Process and display process output", NULL },
     {NULL, 0, 0, NULL, 0, 0}
 };
 
@@ -223,6 +228,54 @@
 	gtk_main ();
 }
 
+static void
+display_as_process (const char *moniker, CORBA_Environment *ev)
+{
+	Bonobo_Process  process;
+	Bonobo_Stream   stdout;
+	gchar *buf = NULL;
+	gint len;
+
+	process = bonobo_get_object (moniker, "IDL:Bonobo/Process:1.0", ev);
+	if (BONOBO_EX (ev) || !process)
+		g_error ("Couldn't get Bonobo/Process interface");
+	
+	g_print ("Waiting for process to die...");
+	while (Bonobo_Process_isRunning (process, ev)) {
+		if (BONOBO_EX (ev)) 
+			g_error ("Exception in BonoboProcess::isRunning");
+
+		g_print (".");
+		usleep (500);
+	}
+	g_print ("dead.\n\n");
+
+	g_print ("Process output:\n");
+	g_print ("==========================================\n");
+
+	stdout = Bonobo_Process_getOutputStream (process, ev);
+	if (BONOBO_EX (ev) || !stdout) 
+		g_error ("Exception in BonoboProcess::getOutputStream.");
+
+	while (1) {
+		buf = bonobo_stream_client_read (stdout, 1024, &len, ev);
+		if (BONOBO_EX (ev)) 
+			g_error ("Exception while reading process output: %s",
+				 bonobo_exception_get_text (ev));
+
+		if (!buf || !len) break;
+
+		g_print ("%*s", len, buf);
+
+		g_free (buf);
+	}
+	
+	g_print ("==========================================\n");
+
+	bonobo_object_release_unref (stdout, ev);
+	bonobo_object_release_unref (process, ev);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -261,6 +314,8 @@
 		global_mto.display_as = AS_HTML;
 	else if (global_mto.pc)
 		global_mto.display_as = AS_CONTROL;
+	else if (global_mto.pp)
+		global_mto.display_as = AS_PROCESS;
 	else {
 		fprintf (stderr, "Usage: %s [-i interface] [-srch] <moniker>\n", argv [0]);
 		fprintf (stderr, "Run %s --help for more info\n", argv [0]);
@@ -295,6 +350,9 @@
 		break;
         case AS_CONTROL:
 		fprintf (stderr, "IDL:Bonobo/Control:1.0");
+		break;
+        case AS_PROCESS:
+		fprintf (stderr, "IDL:Bonobo/Process:1.0");
 		break;
         default:
 		fprintf (stderr, "???");
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/bonobo/ChangeLog,v
retrieving revision 1.1071
diff -u -r1.1071 ChangeLog
--- ChangeLog	2001/06/05 09:11:21	1.1071
+++ ChangeLog	2001/06/06 18:17:32
@@ -1,3 +1,8 @@
+2001-06-06  Alex Graveley  <alex ximian com>
+
+	* bonobo/bonobo-stream-client.c (bonobo_stream_client_read):
+	Handle partial reads correctly.
+
 2001-06-05  Dietmar Maurer  <dietmar ximian com>
 
 	* monikers/bonobo-stream-cache.c (impl_Bonobo_Stream_setInfo):
Index: bonobo/bonobo-stream-client.c
===================================================================
RCS file: /cvs/gnome/bonobo/bonobo/bonobo-stream-client.c,v
retrieving revision 1.17
diff -u -r1.17 bonobo-stream-client.c
--- bonobo/bonobo-stream-client.c	2001/02/22 22:54:40	1.17
+++ bonobo/bonobo-stream-client.c	2001/06/06 18:17:32
@@ -296,11 +296,16 @@
 		if (buf->_length > 0) {
 			memcpy (mem + pos, buf->_buffer, buf->_length);
 			pos += buf->_length;
-		} else {
-			g_warning ("Buffer length %d", buf->_length);
-			goto io_error;
 		}
+
+		len = buf->_length;
+
 		CORBA_free (buf);
+
+		if (!len) { 
+			*length_read = pos;
+			break;
+		}
 	}
 
 	return mem;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]