X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=xfer-src%2Ffilter-process.c;h=aa23b0bdf4079e13f0e2448d0d2cd168e6874370;hb=4c9eba1feb11adf189bceb4001c425e641f0b56a;hp=8776ab7f7df8c3dc136f86598aeb07bbba646813;hpb=d5853102f67d85d8e169f9dbe973ad573306c215;p=debian%2Famanda diff --git a/xfer-src/filter-process.c b/xfer-src/filter-process.c index 8776ab7..aa23b0b 100644 --- a/xfer-src/filter-process.c +++ b/xfer-src/filter-process.c @@ -1,6 +1,6 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver - * Copyright (c) 2008,2009 Zmanda, Inc. All Rights Reserved. + * Copyright (c) 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -19,8 +19,8 @@ * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com */ -#include "amxfer.h" #include "amanda.h" +#include "amxfer.h" #include "event.h" #include "util.h" @@ -50,6 +50,7 @@ typedef struct XferFilterProcess { gchar **argv; gboolean need_root; + int pipe_err[2]; pid_t child_pid; GSource *child_watch; @@ -62,8 +63,9 @@ typedef struct XferFilterProcess { typedef struct { XferElementClass __parent__; -} XferFilterProcessClass; + int (*get_err_fd)(XferFilterProcess *elt); +} XferFilterProcessClass; /* * Implementation @@ -112,6 +114,13 @@ child_watch_callback( xfer_queue_message(XFER_ELEMENT(self)->xfer, xmsg_new(XFER_ELEMENT(self), XMSG_DONE, 0)); } +static int +get_err_fd_impl( + XferFilterProcess *xfp) +{ + return xfp->pipe_err[0]; +} + static gboolean start_impl( XferElement *elt) @@ -121,6 +130,7 @@ start_impl( char **argv; char *errmsg; char **env; + int rfd, wfd; /* first build up a log message of what we're going to do, properly shell quoted */ argv = self->argv; @@ -132,6 +142,9 @@ start_impl( } g_debug("%s spawning: %s", xfer_element_repr(elt), cmd_str); + rfd = xfer_element_swap_output_fd(elt->upstream, -1); + wfd = xfer_element_swap_input_fd(elt->downstream, -1); + /* now fork off the child and connect the pipes */ switch (self->child_pid = fork()) { case -1: @@ -139,10 +152,17 @@ start_impl( /* NOTREACHED */ case 0: /* child */ - /* set up stdin, stdout, and stderr */ - dup2(elt->upstream->output_fd, STDIN_FILENO); - dup2(elt->downstream->input_fd, STDOUT_FILENO); - debug_dup_stderr_to_debug(); + /* first, copy our fd's out of the stdio range */ + while (rfd <= STDERR_FILENO) + rfd = dup(rfd); + while (wfd <= STDERR_FILENO) + wfd = dup(wfd); + + /* set up stdin, stdout, and stderr, overwriting anything already open + * on those fd's */ + dup2(rfd, STDIN_FILENO); + dup2(wfd, STDOUT_FILENO); + dup2(self->pipe_err[1], STDERR_FILENO); /* and close everything else */ safe_fd(-1, 0); @@ -165,8 +185,9 @@ start_impl( g_free(cmd_str); /* close the pipe fd's */ - close(elt->upstream->output_fd); - close(elt->downstream->input_fd); + close(rfd); + close(wfd); + close(self->pipe_err[1]); /* watch for child death */ self->child_watch = new_child_watch_source(self->child_pid); @@ -251,8 +272,8 @@ class_init( XferElementClass *klass = XFER_ELEMENT_CLASS(selfc); GObjectClass *goc = (GObjectClass*) klass; static xfer_element_mech_pair_t mech_pairs[] = { - { XFER_MECH_READFD, XFER_MECH_WRITEFD, 1, 0}, - { XFER_MECH_NONE, XFER_MECH_NONE, 0, 0}, + { XFER_MECH_READFD, XFER_MECH_WRITEFD, XFER_NROPS(1), XFER_NTHREADS(0) }, + { XFER_MECH_NONE, XFER_MECH_NONE, XFER_NROPS(0), XFER_NTHREADS(0) }, }; klass->start = start_impl; @@ -260,6 +281,7 @@ class_init( klass->perl_class = "Amanda::Xfer::Filter::Process"; klass->mech_pairs = mech_pairs; + selfc->get_err_fd = get_err_fd_impl; goc->finalize = finalize_impl; @@ -305,6 +327,22 @@ xfer_filter_process( xfp->argv = argv; xfp->need_root = need_root; - + if (pipe(xfp->pipe_err) < 0) { + g_critical(_("Can't create pipe: %s"), strerror(errno)); + } return elt; } + +int get_err_fd(XferElement *elt); +int get_err_fd( + XferElement *elt) +{ + XferFilterProcessClass *klass; + g_assert(IS_XFER_FILTER_PROCESS(elt)); + + klass = XFER_FILTER_PROCESS_GET_CLASS(elt); + if (klass->get_err_fd) + return klass->get_err_fd(XFER_FILTER_PROCESS(elt)); + else + return 0; +}