Imported Upstream version 2.6.0
[debian/amanda] / common-src / pipespawn.c
index 8a8af5518f6b2a3cfe136cb002a1580288f48644..16fd67cdda4dfc916cd0e3dc71ec8bd8001049dc 100644 (file)
 #include "pipespawn.h"
 #include "arglist.h"
 #include "clock.h"
+#include "util.h"
 
 char skip_argument[1];
 
-#ifdef STDC_HEADERS
-int pipespawn(char *prog, int pipedef, int *stdinfd, int *stdoutfd,
-             int *stderrfd, ...)
-#else
-int pipespawn(prog, pipedef, stdinfd, stdoutfd, stderrfd, va_alist)
-char *prog;
-int pipedef;
-int *stdinfd, *stdoutfd, *stderrfd;
-va_dcl
-#endif
+pid_t pipespawnv_passwd(char *prog, int pipedef,
+                  int *stdinfd, int *stdoutfd, int *stderrfd,
+                  char **my_argv);
+
+
+/*
+ * this used to be a function in it's own write but became a wrapper around
+ * pipespawnv to eliminate redundancy...
+ */
+pid_t
+pipespawn(
+    char *     prog,
+    int                pipedef,
+    int *      stdinfd,
+    int *      stdoutfd,
+    int *      stderrfd,
+    ...)
 {
     va_list ap;
-    int argc;
+    int argc = 0, i;
+    pid_t pid;
     char **argv;
-    int pid, i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2];
-    char *passwdvar = NULL;
-    int *passwdfd = NULL;
-    char number[NUM_STR_SIZE];
-    char *arg;
-    char *e;
-    int ch;
-    char **env;
-    char **newenv;
 
-    /*
-     * Log the command line and count the args.
-     */
-    dbprintf(("%s: spawning %s in pipeline\n", debug_prefix_time(NULL), prog));
-    dbprintf(("%s: argument list:", debug_prefix(NULL)));
+    /* count args */
     arglist_start(ap, stderrfd);
-    if ((pipedef & PASSWD_PIPE) != 0) {
-       passwdvar = arglist_val(ap, char *);
-       passwdfd = arglist_val(ap, int *);
-    }
-    argc = 0;
-    while((arg = arglist_val(ap, char *)) != NULL) {
-       if (arg == skip_argument) {
-           continue;
-       }
+    while(arglist_val(ap, char *) != NULL) {
        argc++;
-       dbprintf((" "));
-       for(i = 0; (ch = arg[i]) != '\0' && isprint(ch) && ch != ' '; i++) {}
-       if(ch != '\0' || i == 0) {
-           dbprintf(("\""));
-       }
-       dbprintf(("%s", arg));
-       if(ch != '\0' || i == 0) {
-           dbprintf(("\""));
-       }
     }
     arglist_end(ap);
-    dbprintf(("\n"));
 
     /*
-     * Create the pipes
+     * Create the argument vector.
      */
-    if ((pipedef & STDIN_PIPE) != 0) {
-       if(pipe(inpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
-       }
-    }
-    if ((pipedef & STDOUT_PIPE) != 0) {
-       if(pipe(outpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
-       }
-    }
-    if ((pipedef & STDERR_PIPE) != 0) {
-       if(pipe(errpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
-       }
-    }
-    if ((pipedef & PASSWD_PIPE) != 0) {
-       if(pipe(passwdpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
-       }
+    arglist_start(ap, stderrfd);
+    argv = (char **)alloc((argc + 1) * SIZEOF(*argv));
+    i = 0;
+    while((argv[i] = arglist_val(ap, char *)) != NULL) {
+        if (argv[i] != skip_argument) {
+           i++;
+        }
     }
+    arglist_end(ap);
 
-    /*
-     * Fork and set up the return or run the program.
-     */
-    switch(pid = fork()) {
-    case -1:
-       e = strerror(errno);
-       error("error [fork %s: %s]", prog, e);
-    default:   /* parent process */
-       if ((pipedef & STDIN_PIPE) != 0) {
-           aclose(inpipe[0]);          /* close input side of pipe */
-           *stdinfd = inpipe[1];
-       }
-       if ((pipedef & STDOUT_PIPE) != 0) {
-           aclose(outpipe[1]);         /* close output side of pipe */
-           *stdoutfd = outpipe[0];
-       }
-       if ((pipedef & STDERR_PIPE) != 0) {
-           aclose(errpipe[1]);         /* close output side of pipe */
-           *stderrfd = errpipe[0];
-       }
-       if ((pipedef & PASSWD_PIPE) != 0) {
-           aclose(passwdpipe[0]);      /* close input side of pipe */
-           *passwdfd = passwdpipe[1];
-       }
-       break;
-    case 0:            /* child process */
-       if ((pipedef & STDIN_PIPE) != 0) {
-           aclose(inpipe[1]);          /* close output side of pipe */
-       } else {
-           inpipe[0] = *stdinfd;
-       }
-       if ((pipedef & STDOUT_PIPE) != 0) {
-           aclose(outpipe[0]);         /* close input side of pipe */
-       } else {
-           outpipe[1] = *stdoutfd;
-       }
-       if ((pipedef & STDERR_PIPE) != 0) {
-           aclose(errpipe[0]);         /* close input side of pipe */
-       } else {
-           errpipe[1] = *stderrfd;
-       }
-       if ((pipedef & PASSWD_PIPE) != 0) {
-           aclose(passwdpipe[1]);      /* close output side of pipe */
-       }
-
-       /*
-        * Shift the pipes to the standard file descriptors as requested.
-        */
-       if(dup2(inpipe[0], 0) == -1) {
-           error("error [spawn %s: dup2 in: %s]", prog, strerror(errno));
-       }
-       if(dup2(outpipe[1], 1) == -1) {
-           error("error [spawn %s: dup2 out: %s]", prog, strerror(errno));
-       }
-       if(dup2(errpipe[1], 2) == -1) {
-           error("error [spawn %s: dup2 err: %s]", prog, strerror(errno));
-       }
-
-       /*
-        * Create the argument vector.
-        */
-       arglist_start(ap, stderrfd);
-       if ((pipedef & PASSWD_PIPE) != 0) {
-           passwdvar = arglist_val(ap, char *);
-           passwdfd = arglist_val(ap, int *);
-       }
-       argv = (char **)alloc((argc + 1) * sizeof(*argv));
-       i = 0;
-       while((argv[i] = arglist_val(ap, char *)) != NULL) {
-           if (argv[i] != skip_argument) {
-               i++;
-           }
-       }
-       arglist_end(ap);
-
-       /*
-        * Get the "safe" environment.  If we are sending a password to
-        * the child via a pipe, add the environment variable for that.
-        */
-       env = safe_env();
-       if ((pipedef & PASSWD_PIPE) != 0) {
-           for(i = 0; env[i] != NULL; i++) {}
-           newenv = (char **)alloc((i + 1 + 1) * sizeof(*newenv));
-           ap_snprintf(number, sizeof(number), "%d", passwdpipe[0]);
-           newenv[0] = vstralloc(passwdvar, "=", number, NULL);
-           for(i = 0; (newenv[i + 1] = env[i]) != NULL; i++) {}
-           env = newenv;
-       }
-
-       execve(prog, argv, env);
-       e = strerror(errno);
-       error("error [exec %s: %s]", prog, e);
-       /* NOTREACHED */
-    }
+    pid = pipespawnv_passwd(prog, pipedef, stdinfd, stdoutfd, stderrfd, argv);
+    amfree(argv);
     return pid;
 }
 
-int pipespawnv(prog, pipedef, stdinfd, stdoutfd, stderrfd, my_argv)
-char *prog;
-int pipedef;
-int *stdinfd, *stdoutfd, *stderrfd;
-char **my_argv;
+pid_t
+pipespawnv(
+    char *     prog,
+    int                pipedef,
+    int *      stdinfd,
+    int *      stdoutfd,
+    int *      stderrfd,
+    char **    my_argv)
+{
+    return pipespawnv_passwd(prog, pipedef, stdinfd, stdoutfd, stderrfd,
+       my_argv);
+}
+
+pid_t
+pipespawnv_passwd(
+    char *     prog,
+    int                pipedef,
+    int *      stdinfd,
+    int *      stdoutfd,
+    int *      stderrfd,
+    char **    my_argv)
 {
     int argc;
-    int pid, i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2];
-    char *passwdvar = NULL;
-    int *passwdfd = NULL;
+    pid_t pid;
+    int i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2];
     char number[NUM_STR_SIZE];
     char **arg;
     char *e;
-    int ch;
     char **env;
+    char *cmdline;
+    char *quoted;
     char **newenv;
+    char *passwdvar = NULL;
+    int  *passwdfd = NULL;
 
     /*
      * Log the command line and count the args.
      */
-    dbprintf(("%s: spawning %s in pipeline\n", debug_prefix_time(NULL), prog));
-    dbprintf(("%s: argument list:", debug_prefix(NULL)));
     if ((pipedef & PASSWD_PIPE) != 0) {
        passwdvar = *my_argv++;
-       passwdfd = (int *)*my_argv++;
+       passwdfd  = (int *)*my_argv++;
     }
+    memset(inpipe, -1, SIZEOF(inpipe));
+    memset(outpipe, -1, SIZEOF(outpipe));
+    memset(errpipe, -1, SIZEOF(errpipe));
+    memset(passwdpipe, -1, SIZEOF(passwdpipe));
     argc = 0;
+
+    cmdline = stralloc(prog);
     for(arg = my_argv; *arg != NULL; arg++) {
-       if (*arg == skip_argument) {
-           continue;
-       }
-       argc++;
-       dbprintf((" "));
-       for(i = 0; (ch = (*arg)[i]) != '\0' && isprint(ch) && ch != ' '; i++) {}
-       if(ch != '\0' || i == 0) {
-           dbprintf(("\""));
-       }
-       dbprintf(("%s", *arg));
-       if(ch != '\0' || i == 0) {
-           dbprintf(("\""));
+       if (*arg != skip_argument) {
+           argc++;
+           quoted = quote_string(*arg);
+           cmdline = vstrextend(&cmdline, " ", quoted, NULL);
+           amfree(quoted);
        }
     }
-    dbprintf(("\n"));
+    dbprintf(_("Spawning \"%s\" in pipeline\n"), cmdline);
 
     /*
      * Create the pipes
      */
     if ((pipedef & STDIN_PIPE) != 0) {
        if(pipe(inpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
+           error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
+           /*NOTREACHED*/
        }
     }
     if ((pipedef & STDOUT_PIPE) != 0) {
        if(pipe(outpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
+           error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
+           /*NOTREACHED*/
        }
     }
     if ((pipedef & STDERR_PIPE) != 0) {
        if(pipe(errpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
+           error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
+           /*NOTREACHED*/
        }
     }
     if ((pipedef & PASSWD_PIPE) != 0) {
        if(pipe(passwdpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
+           error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
+           /*NOTREACHED*/
        }
     }
 
@@ -253,7 +147,9 @@ char **my_argv;
     switch(pid = fork()) {
     case -1:
        e = strerror(errno);
-       error("error [fork %s: %s]", prog, e);
+       error(_("error [fork %s: %s]"), prog, e);
+       /*NOTREACHED*/
+
     default:   /* parent process */
        if ((pipedef & STDIN_PIPE) != 0) {
            aclose(inpipe[0]);          /* close input side of pipe */
@@ -288,18 +184,24 @@ char **my_argv;
        } else {
            errpipe[1] = *stderrfd;
        }
+        if ((pipedef & PASSWD_PIPE) != 0) { 
+            aclose(passwdpipe[1]);      /* close output side of pipe */
+        }
 
        /*
         * Shift the pipes to the standard file descriptors as requested.
         */
        if(dup2(inpipe[0], 0) == -1) {
-           error("error [spawn %s: dup2 in: %s]", prog, strerror(errno));
+           error(_("error [spawn %s: dup2 in: %s]"), prog, strerror(errno));
+           /*NOTREACHED*/
        }
        if(dup2(outpipe[1], 1) == -1) {
-           error("error [spawn %s: dup2 out: %s]", prog, strerror(errno));
+           error(_("error [spawn %s: dup2 out: %s]"), prog, strerror(errno));
+           /*NOTREACHED*/
        }
        if(dup2(errpipe[1], 2) == -1) {
-           error("error [spawn %s: dup2 err: %s]", prog, strerror(errno));
+           error(_("error [spawn %s: dup2 err: %s]"), prog, strerror(errno));
+           /*NOTREACHED*/
        }
 
        /*
@@ -308,18 +210,26 @@ char **my_argv;
         */
        env = safe_env();
        if ((pipedef & PASSWD_PIPE) != 0) {
-           for(i = 0; env[i] != NULL; i++) {}
-           newenv = (char **)alloc((i + 1 + 1) * sizeof(*newenv));
-           ap_snprintf(number, sizeof(number), "%d", passwdpipe[0]);
+           for (i = 0; env[i] != NULL; i++)
+               (void)i; /* make lint happy and do nothing */   
+           newenv = (char **)alloc((i + 1 + 1) * SIZEOF(*newenv));
+           g_snprintf(number, SIZEOF(number), "%d", passwdpipe[0]);
            newenv[0] = vstralloc(passwdvar, "=", number, NULL);
-           for(i = 0; (newenv[i + 1] = env[i]) != NULL; i++) {}
+           for(i = 0; env[i] != NULL; i++)
+               newenv[i + 1] = env[i];
+           newenv[i + 1] = NULL;
+           amfree(env);
            env = newenv;
+           safe_fd(passwdpipe[0], 1);
+       } else {
+           safe_fd(-1, 0);
        }
 
        execve(prog, my_argv, env);
        e = strerror(errno);
-       error("error [exec %s: %s]", prog, e);
-       /* NOTREACHED */
+       error(_("error [exec %s: %s]"), prog, e);
+       /*NOTREACHED*/
     }
+    amfree(cmdline);
     return pid;
 }