#include "pipespawn.h"
#include "arglist.h"
#include "clock.h"
+#include "util.h"
char skip_argument[1];
+pid_t pipespawnv_passwd(char *prog, int pipedef, int need_root,
+ 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...
*/
-#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
+pipespawn(
+ char * prog,
+ int pipedef,
+ int need_root,
+ int * stdinfd,
+ int * stdoutfd,
+ int * stderrfd,
+ ...)
{
va_list ap;
- int argc = 0, pid, i;
+ int argc = 0, i;
+ pid_t pid;
char **argv;
/* count args */
* Create the argument vector.
*/
arglist_start(ap, stderrfd);
- argv = (char **)alloc((argc + 1) * sizeof(*argv));
+ argv = (char **)alloc((argc + 1) * SIZEOF(*argv));
i = 0;
while((argv[i] = arglist_val(ap, char *)) != NULL) {
if (argv[i] != skip_argument) {
}
arglist_end(ap);
- pid = pipespawnv_passwd(prog, pipedef, stdinfd, stdoutfd, stderrfd, NULL, NULL, argv);
+ pid = pipespawnv_passwd(prog, pipedef, need_root,
+ 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 need_root,
+ int * stdinfd,
+ int * stdoutfd,
+ int * stderrfd,
+ char ** my_argv)
{
- return pipespawnv_passwd(prog, pipedef, stdinfd, stdoutfd, stderrfd,
- NULL, NULL, my_argv);
+ return pipespawnv_passwd(prog, pipedef, need_root,
+ stdinfd, stdoutfd, stderrfd,
+ my_argv);
}
-int pipespawnv_passwd(prog, pipedef, stdinfd, stdoutfd, stderrfd, passwdvar, passwdfd, my_argv)
-char *prog;
-int pipedef;
-int *stdinfd, *stdoutfd, *stderrfd;
-char *passwdvar;
-int *passwdfd;
-char **my_argv;
+pid_t
+pipespawnv_passwd(
+ char * prog,
+ int pipedef,
+ int need_root,
+ int * stdinfd,
+ int * stdoutfd,
+ int * stderrfd,
+ char ** my_argv)
{
int argc;
- int pid, i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2];
+ 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*/
}
}
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 */
}
break;
case 0: /* child process */
+ debug_dup_stderr_to_debug();
if ((pipedef & STDIN_PIPE) != 0) {
aclose(inpipe[1]); /* close output side of pipe */
} else {
* 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));
+ g_fprintf(stderr, "error [spawn %s: dup2 in: %s]", prog, strerror(errno));
+ exit(1);
+ /*NOTREACHED*/
}
if(dup2(outpipe[1], 1) == -1) {
- error("error [spawn %s: dup2 out: %s]", prog, strerror(errno));
+ g_fprintf(stderr, "error [spawn %s: dup2 out: %s]", prog, strerror(errno));
+ exit(1);
+ /*NOTREACHED*/
}
if(dup2(errpipe[1], 2) == -1) {
- error("error [spawn %s: dup2 err: %s]", prog, strerror(errno));
+ g_fprintf(stderr, "error [spawn %s: dup2 err: %s]", prog, strerror(errno));
+ exit(1);
+ /*NOTREACHED*/
}
/*
*/
env = safe_env();
if ((pipedef & PASSWD_PIPE) != 0) {
- for(i = 0; env[i] != NULL; i++) {}
- newenv = (char **)alloc((i + 1 + 1) * sizeof(*newenv));
- 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);
+ }
+
+ if (need_root) {
+ become_root();
+ } else {
+ /* if our real userid is zero, the child shouldn't inherit
+ * that, so drop privs permanently */
+ if (getuid() == 0 && !set_root_privs(-1)) {
+ error(_("could not drop root privileges"));
+ }
}
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;
}