diff options
Diffstat (limited to 'camel/camel-stream-process.c')
-rw-r--r-- | camel/camel-stream-process.c | 264 |
1 files changed, 0 insertions, 264 deletions
diff --git a/camel/camel-stream-process.c b/camel/camel-stream-process.c deleted file mode 100644 index 8dc5b33ea1..0000000000 --- a/camel/camel-stream-process.c +++ /dev/null @@ -1,264 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camel-stream-process.c : stream over piped process */ - -/* - * Copyright (C) 2003 Ximian Inc. - * - * Authors: David Woodhouse <dwmw2@infradead.org>, - * Jeffrey Stedfast <fejj@ximian.com> - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/wait.h> -#include <unistd.h> -#include <signal.h> -#include <fcntl.h> -#include <errno.h> - -#include "camel-stream-process.h" -#include "camel-file-utils.h" - -extern int camel_verbose_debug; - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_STREAM_PROCESS_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -/* dummy implementations, for a PROCESS stream */ -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_close (CamelStream *stream); -static int stream_flush (CamelStream *stream); - -static void -camel_stream_process_finalise (CamelObject *object) -{ - /* Ensure we clean up after ourselves -- kill - the child process and reap it. */ - stream_close (CAMEL_STREAM (object)); -} - -static void -camel_stream_process_class_init (CamelStreamProcessClass *camel_stream_process_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *) camel_stream_process_class; - - parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; -} - -static void -camel_stream_process_init (gpointer object, gpointer klass) -{ - CamelStreamProcess *stream = CAMEL_STREAM_PROCESS (object); - - stream->sockfd = -1; - stream->childpid = 0; -} - - -CamelType -camel_stream_process_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_stream_get_type (), - "CamelStreamProcess", - sizeof (CamelStreamProcess), - sizeof (CamelStreamProcessClass), - (CamelObjectClassInitFunc) camel_stream_process_class_init, - NULL, - (CamelObjectInitFunc) camel_stream_process_init, - (CamelObjectFinalizeFunc) camel_stream_process_finalise); - } - - return type; -} - -/** - * camel_stream_process_new: - * - * Returns a PROCESS stream. - * - * Return value: the stream - **/ -CamelStream * -camel_stream_process_new (void) -{ - return (CamelStream *) camel_object_new (camel_stream_process_get_type ()); -} - - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelStreamProcess *stream_process = CAMEL_STREAM_PROCESS (stream); - - return camel_read (stream_process->sockfd, buffer, n); -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelStreamProcess *stream_process = CAMEL_STREAM_PROCESS (stream); - - return camel_write (stream_process->sockfd, buffer, n); -} - -static int -stream_flush (CamelStream *stream) -{ - return 0; -} - -static int -stream_close (CamelStream *object) -{ - CamelStreamProcess *stream = CAMEL_STREAM_PROCESS (object); - - if (camel_verbose_debug) - fprintf (stderr, "Process stream close. sockfd %d, childpid %d\n", - stream->sockfd, stream->childpid); - - if (stream->sockfd != -1) { - close (stream->sockfd); - stream->sockfd = -1; - } - - if (stream->childpid) { - int ret, i; - for (i = 0; i < 4; i++) { - ret = waitpid (stream->childpid, NULL, WNOHANG); - if (camel_verbose_debug) - fprintf (stderr, "waitpid() for pid %d returned %d (errno %d)\n", - stream->childpid, ret, ret == -1 ? errno : 0); - if (ret == stream->childpid || errno == ECHILD) - break; - switch (i) { - case 0: - if (camel_verbose_debug) - fprintf (stderr, "Sending SIGTERM to pid %d\n", - stream->childpid); - kill (stream->childpid, SIGTERM); - break; - case 2: - if (camel_verbose_debug) - fprintf (stderr, "Sending SIGKILL to pid %d\n", - stream->childpid); - kill (stream->childpid, SIGKILL); - break; - case 1: - case 3: - sleep (1); - break; - } - } - - stream->childpid = 0; - } - - return 0; -} - -static void -do_exec_command (int fd, const char *command, char **env) -{ - int i, maxopen; - - /* Not a lot we can do if there's an error other than bail. */ - if (dup2 (fd, 0) == -1) - exit (1); - if (dup2 (fd, 1) == -1) - exit (1); - - /* What to do with stderr? Possibly put it through a separate pipe - and bring up a dialog box with its output if anything does get - spewed to it? It'd help the user understand what was going wrong - with their command, but it's hard to do cleanly. For now we just - leave it as it is. Perhaps we should close it and reopen /dev/null? */ - - maxopen = sysconf (_SC_OPEN_MAX); - for (i = 3; i < maxopen; i++) - fcntl (i, F_SETFD, FD_CLOEXEC); - - setsid (); -#ifdef TIOCNOTTY - /* Detach from the controlling tty if we have one. Otherwise, - SSH might do something stupid like trying to use it instead - of running $SSH_ASKPASS. Doh. */ - if ((fd = open ("/dev/tty", O_RDONLY)) != -1) { - ioctl (fd, TIOCNOTTY, NULL); - close (fd); - } -#endif /* TIOCNOTTY */ - - /* Set up child's environment. We _add_ to it, don't use execle, - because otherwise we'd destroy stuff like SSH_AUTH_SOCK etc. */ - for ( ; env && *env; env++) - putenv(*env); - - execl ("/bin/sh", "/bin/sh", "-c", command, NULL); - - if (camel_verbose_debug) - fprintf (stderr, "exec failed %d\n", errno); - - exit (1); -} - -int -camel_stream_process_connect (CamelStreamProcess *stream, const char *command, const char **env) -{ - int sockfds[2]; - - if (stream->sockfd != -1 || stream->childpid) - stream_close (CAMEL_STREAM (stream)); - - if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfds)) - return -1; - - stream->childpid = fork (); - if (!stream->childpid) { - do_exec_command (sockfds[1], command, (char **)env); - } else if (stream->childpid == -1) { - close (sockfds[0]); - close (sockfds[1]); - stream->sockfd = -1; - return -1; - } - - close (sockfds[1]); - stream->sockfd = sockfds[0]; - - return 0; -} |