? .cproject ? .project Index: clientserver.c =================================================================== RCS file: /cvsroot/rsync/clientserver.c,v retrieving revision 1.206 diff -u -r1.206 clientserver.c --- clientserver.c 23 Sep 2007 02:03:21 -0000 1.206 +++ clientserver.c 23 Sep 2007 04:20:22 -0000 @@ -309,10 +309,12 @@ return 0; } -static char *finish_pre_exec(pid_t pid, int fd, char *request, +static char *finish_pre_exec(pid_t pid, int fd, int err_fd, char *request, int argc, char *argv[]) { int j, status = -1; + int ret, outbuf_use = 0; + char *outbuf = NULL; if (!request) request = "(NONE)"; @@ -324,12 +326,36 @@ close(fd); + /* Retrieve data the command writes to stdout or stderr + * and pass it to the client. We're done when we get EOF. */ + for (;;) { + outbuf = realloc(outbuf, outbuf_use + 1024); + rprintf(FLOG, "Got here 1.1\n"); + ret = read(err_fd, outbuf + outbuf_use, 1023); + int errno1 = errno; + rprintf(FLOG, "Got here 1.2, ret %d, errno %d\n", ret, errno1); + if (ret == 0) + break; + else if (ret > 0) + outbuf_use += ret; + else if (errno != EINTR) { + rsyserr(FLOG, errno1, "read pre-xfer exec output failed"); + char *e; + if (asprintf(&e, "read pre-xfer exec output failed: %s (%d)\n", + strerror(errno1), errno1) < 0) + out_of_memory("finish_pre_exec"); + return e; + } + } + if (wait_process(pid, &status, 0) < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { char *e; - if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s\n", + outbuf[outbuf_use] = '\0'; + if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s%s%s\n", status, status < 0 ? ": " : "", - status < 0 ? strerror(errno) : "") < 0) + status < 0 ? strerror(errno) : "", + outbuf_use > 0 ? ": " : "", outbuf) < 0) out_of_memory("finish_pre_exec"); return e; } @@ -363,7 +389,7 @@ char *p, *err_msg = NULL; char *name = lp_name(i); int use_chroot = lp_use_chroot(i); - int ret, pre_exec_fd = -1; + int ret, pre_exec_fd = -1, pre_exec_err_fd = -1; pid_t pre_exec_pid = 0; char *request = NULL; @@ -536,10 +562,10 @@ * command, though it first waits for the parent process to * send us the user's request via a pipe. */ if (*lp_prexfer_exec(i)) { - int fds[2]; + int fds[2], fds_err[2]; if (asprintf(&p, "RSYNC_PID=%ld", (long)getpid()) > 0) putenv(p); - if (pipe(fds) < 0 || (pre_exec_pid = fork()) < 0) { + if (pipe(fds) < 0 || pipe(fds_err) < 0 || (pre_exec_pid = fork()) < 0) { rsyserr(FLOG, errno, "pre-xfer exec preparation failed"); io_printf(f_out, "@ERROR: pre-xfer exec preparation failed\n"); return -1; @@ -548,6 +574,7 @@ char buf[BIGPATHBUFLEN]; int j, len; close(fds[1]); + close(fds_err[0]); set_blocking(fds[0]); len = read_arg_from_pipe(fds[0], buf, BIGPATHBUFLEN); if (len <= 0) @@ -568,6 +595,10 @@ close(fds[0]); close(STDIN_FILENO); close(STDOUT_FILENO); + close(STDERR_FILENO); + dup2(fds_err[1], STDOUT_FILENO); + dup2(fds_err[1], STDERR_FILENO); + close(fds_err[1]); status = system(lp_prexfer_exec(i)); if (!WIFEXITED(status)) _exit(1); @@ -575,7 +606,9 @@ } close(fds[0]); set_blocking(fds[1]); + close(fds_err[1]); pre_exec_fd = fds[1]; + pre_exec_err_fd = fds_err[0]; } umask(0); } @@ -661,7 +694,7 @@ opt_cnt = read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request); if (pre_exec_pid) { - err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request, + err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, pre_exec_err_fd, request, opt_cnt, argv); }