+ assert(unused == NULL);
+ errstr = newstralloc(errstr, _("data timeout"));
+ dump_result = 2;
+ stop_dump();
+}
+
+/*
+ * This is called when everything needs to shut down so event_loop()
+ * will exit.
+ */
+static void
+stop_dump(void)
+{
+ int i;
+ struct cmdargs *cmdargs = NULL;
+
+ /* Check if I have a pending ABORT command */
+ cmdargs = get_pending_cmd();
+ if (cmdargs) {
+ if (cmdargs->cmd != ABORT) {
+ error(_("beurk %d"), cmdargs->cmd);
+ }
+ amfree(errstr);
+ errstr = stralloc(cmdargs->argv[1]);
+ free_cmdargs(cmdargs);
+ }
+
+ for (i = 0; i < NSTREAMS; i++) {
+ if (streams[i].fd != NULL) {
+ security_stream_close(streams[i].fd);
+ streams[i].fd = NULL;
+ }
+ }
+ aclose(indexout);
+ aclose(g_databuf->fd);
+ timeout(0);
+}
+
+
+/*
+ * Runs compress with the first arg as its stdout. Returns
+ * 0 on success or negative if error, and it's pid via the second
+ * argument. The outfd arg is dup2'd to the pipe to the compress
+ * process.
+ */
+static int
+runcompress(
+ int outfd,
+ pid_t * pid,
+ comp_t comptype,
+ char *name)
+{
+ int outpipe[2], rval;
+ int errpipe[2];
+ filter_t *filter;
+
+ assert(outfd >= 0);
+ assert(pid != NULL);
+
+ /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
+ if (pipe(outpipe) < 0) {
+ errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
+ return (-1);
+ }
+
+ /* errpipe[0] is pipe's output, outpipe[1] is input. */
+ if (pipe(errpipe) < 0) {
+ errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
+ return (-1);
+ }
+
+ if (comptype != COMP_SERVER_CUST) {
+ g_debug("execute: %s %s", COMPRESS_PATH,
+ comptype == COMP_BEST ? COMPRESS_BEST_OPT : COMPRESS_FAST_OPT);
+ } else {
+ g_debug("execute: %s", srvcompprog);
+ }
+ switch (*pid = fork()) {
+ case -1:
+ errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno));
+ aclose(outpipe[0]);
+ aclose(outpipe[1]);
+ aclose(errpipe[0]);
+ aclose(errpipe[1]);
+ return (-1);
+ default:
+ rval = dup2(outpipe[1], outfd);
+ if (rval < 0)
+ errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno));
+ aclose(outpipe[1]);
+ aclose(outpipe[0]);
+ aclose(errpipe[1]);
+ filter = g_new0(filter_t, 1);
+ filter->fd = errpipe[0];
+ filter->name = name;
+ filter->buffer = NULL;
+ filter->size = 0;
+ filter->allocated_size = 0;
+ filter->event = event_register((event_id_t)filter->fd, EV_READFD,
+ handle_filter_stderr, filter);
+ return (rval);
+ case 0:
+ close(outpipe[1]);
+ close(errpipe[0]);
+ if (dup2(outpipe[0], 0) < 0) {
+ error(_("err dup2 in: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+ if (dup2(outfd, 1) == -1) {
+ error(_("err dup2 out: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+ if (dup2(errpipe[1], 2) == -1) {
+ error(_("err dup2 err: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+ if (comptype != COMP_SERVER_CUST) {
+ char *base = stralloc(COMPRESS_PATH);
+ log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
+ amfree(base);
+ safe_fd(-1, 0);
+ set_root_privs(-1);
+ execlp(COMPRESS_PATH, COMPRESS_PATH, ( comptype == COMP_BEST ?
+ COMPRESS_BEST_OPT : COMPRESS_FAST_OPT), (char *)NULL);
+ error(_("error: couldn't exec %s: %s"), COMPRESS_PATH, strerror(errno));
+ /*NOTREACHED*/
+ } else if (*srvcompprog) {
+ char *base = stralloc(srvcompprog);
+ log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
+ amfree(base);
+ safe_fd(-1, 0);
+ set_root_privs(-1);
+ execlp(srvcompprog, srvcompprog, (char *)0);
+ error(_("error: couldn't exec server custom compression '%s'.\n"), srvcompprog);
+ /*NOTREACHED*/
+ }
+ }
+ /*NOTREACHED*/
+ return (-1);
+}
+
+/*
+ * Runs encrypt with the first arg as its stdout. Returns
+ * 0 on success or negative if error, and it's pid via the second
+ * argument. The outfd arg is dup2'd to the pipe to the encrypt
+ * process.
+ */
+static int
+runencrypt(
+ int outfd,
+ pid_t * pid,
+ encrypt_t encrypttype)
+{
+ int outpipe[2], rval;
+ int errpipe[2];
+ filter_t *filter;
+
+ assert(outfd >= 0);
+ assert(pid != NULL);
+
+ /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
+ if (pipe(outpipe) < 0) {
+ errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
+ return (-1);
+ }
+
+ /* errpipe[0] is pipe's output, outpipe[1] is input. */
+ if (pipe(errpipe) < 0) {
+ errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
+ return (-1);
+ }
+
+ g_debug("execute: %s", srv_encrypt);
+ switch (*pid = fork()) {
+ case -1:
+ errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno));
+ aclose(outpipe[0]);
+ aclose(outpipe[1]);
+ aclose(errpipe[0]);
+ aclose(errpipe[1]);
+ return (-1);
+ default: {
+ char *base;
+ rval = dup2(outpipe[1], outfd);
+ if (rval < 0)
+ errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno));
+ aclose(outpipe[1]);
+ aclose(outpipe[0]);
+ aclose(errpipe[1]);
+ filter = g_new0(filter_t, 1);
+ filter->fd = errpipe[0];
+ base = g_strdup(srv_encrypt);
+ filter->name = g_strdup(basename(base));
+ amfree(base);
+ filter->buffer = NULL;
+ filter->size = 0;
+ filter->allocated_size = 0;
+ filter->event = event_register((event_id_t)filter->fd, EV_READFD,
+ handle_filter_stderr, filter);
+ return (rval);
+ }
+ case 0: {
+ char *base;
+ if (dup2(outpipe[0], 0) < 0) {
+ error(_("err dup2 in: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+ if (dup2(outfd, 1) < 0 ) {
+ error(_("err dup2 out: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+ if (dup2(errpipe[1], 2) == -1) {
+ error(_("err dup2 err: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+ close(errpipe[0]);
+ base = stralloc(srv_encrypt);
+ log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
+ amfree(base);
+ safe_fd(-1, 0);
+ if ((encrypttype == ENCRYPT_SERV_CUST) && *srv_encrypt) {
+ set_root_privs(-1);
+ execlp(srv_encrypt, srv_encrypt, (char *)0);
+ error(_("error: couldn't exec server custom encryption '%s'.\n"), srv_encrypt);
+ /*NOTREACHED*/
+ }
+ }
+ }
+ /*NOTREACHED*/
+ return (-1);
+}
+
+
+/* -------------------- */
+
+static void
+sendbackup_response(
+ void * datap,
+ pkt_t * pkt,
+ security_handle_t * sech)
+{
+ int ports[NSTREAMS], *response_error = datap, i;
+ char *p;
+ char *tok;
+ char *extra;
+
+ assert(response_error != NULL);
+ assert(sech != NULL);
+
+ security_close_connection(sech, hostname);
+
+ if (pkt == NULL) {
+ errstr = newvstrallocf(errstr, _("[request failed: %s]"),
+ security_geterror(sech));
+ *response_error = 1;