9 pid_t pipespawnv_passwd(char *prog, int pipedef, int need_root,
10 int *stdinfd, int *stdoutfd, int *stderrfd,
15 * this used to be a function in it's own write but became a wrapper around
16 * pipespawnv to eliminate redundancy...
34 arglist_start(ap, stderrfd);
35 while(arglist_val(ap, char *) != NULL) {
41 * Create the argument vector.
43 arglist_start(ap, stderrfd);
44 argv = (char **)alloc((argc + 1) * SIZEOF(*argv));
46 while((argv[i] = arglist_val(ap, char *)) != NULL) {
47 if (argv[i] != skip_argument) {
53 pid = pipespawnv_passwd(prog, pipedef, need_root,
54 stdinfd, stdoutfd, stderrfd, argv);
69 return pipespawnv_passwd(prog, pipedef, need_root,
70 stdinfd, stdoutfd, stderrfd,
85 int i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2];
86 char number[NUM_STR_SIZE];
93 char *passwdvar = NULL;
97 * Log the command line and count the args.
99 if ((pipedef & PASSWD_PIPE) != 0) {
100 passwdvar = *my_argv++;
101 passwdfd = (int *)*my_argv++;
103 memset(inpipe, -1, SIZEOF(inpipe));
104 memset(outpipe, -1, SIZEOF(outpipe));
105 memset(errpipe, -1, SIZEOF(errpipe));
106 memset(passwdpipe, -1, SIZEOF(passwdpipe));
108 cmdline = stralloc(prog);
109 for(arg = my_argv; *arg != NULL; arg++) {
110 if (*arg != skip_argument) {
111 quoted = quote_string(*arg);
112 cmdline = vstrextend(&cmdline, " ", quoted, NULL);
116 dbprintf(_("Spawning \"%s\" in pipeline\n"), cmdline);
121 if ((pipedef & STDIN_PIPE) != 0) {
122 if(pipe(inpipe) == -1) {
123 error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
127 if ((pipedef & STDOUT_PIPE) != 0) {
128 if(pipe(outpipe) == -1) {
129 error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
133 if ((pipedef & STDERR_PIPE) != 0) {
134 if(pipe(errpipe) == -1) {
135 error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
139 if ((pipedef & PASSWD_PIPE) != 0) {
140 if(pipe(passwdpipe) == -1) {
141 error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
147 * Fork and set up the return or run the program.
149 switch(pid = fork()) {
152 error(_("error [fork %s: %s]"), prog, e);
155 default: /* parent process */
156 if ((pipedef & STDIN_PIPE) != 0) {
157 aclose(inpipe[0]); /* close input side of pipe */
158 *stdinfd = inpipe[1];
160 if ((pipedef & STDOUT_PIPE) != 0) {
161 aclose(outpipe[1]); /* close output side of pipe */
162 *stdoutfd = outpipe[0];
164 if ((pipedef & STDERR_PIPE) != 0) {
165 aclose(errpipe[1]); /* close output side of pipe */
166 *stderrfd = errpipe[0];
168 if ((pipedef & PASSWD_PIPE) != 0) {
169 aclose(passwdpipe[0]); /* close input side of pipe */
170 *passwdfd = passwdpipe[1];
173 case 0: /* child process */
174 debug_dup_stderr_to_debug();
175 if ((pipedef & STDIN_PIPE) != 0) {
176 aclose(inpipe[1]); /* close output side of pipe */
178 inpipe[0] = *stdinfd;
180 if ((pipedef & STDOUT_PIPE) != 0) {
181 aclose(outpipe[0]); /* close input side of pipe */
183 outpipe[1] = *stdoutfd;
185 if ((pipedef & STDERR_PIPE) != 0) {
186 aclose(errpipe[0]); /* close input side of pipe */
188 errpipe[1] = *stderrfd;
190 if ((pipedef & PASSWD_PIPE) != 0) {
191 aclose(passwdpipe[1]); /* close output side of pipe */
195 * Shift the pipes to the standard file descriptors as requested.
197 if(dup2(inpipe[0], 0) == -1) {
198 g_fprintf(stderr, "error [spawn %s: dup2 in: %s]", prog, strerror(errno));
202 if(dup2(outpipe[1], 1) == -1) {
203 g_fprintf(stderr, "error [spawn %s: dup2 out: %s]", prog, strerror(errno));
207 if(dup2(errpipe[1], 2) == -1) {
208 g_fprintf(stderr, "error [spawn %s: dup2 err: %s]", prog, strerror(errno));
214 * Get the "safe" environment. If we are sending a password to
215 * the child via a pipe, add the environment variable for that.
218 if ((pipedef & PASSWD_PIPE) != 0) {
219 for (i = 0; env[i] != NULL; i++)
220 (void)i; /* make lint happy and do nothing */
221 newenv = (char **)alloc((i + 1 + 1) * SIZEOF(*newenv));
222 g_snprintf(number, SIZEOF(number), "%d", passwdpipe[0]);
223 newenv[0] = vstralloc(passwdvar, "=", number, NULL);
224 for(i = 0; env[i] != NULL; i++)
225 newenv[i + 1] = env[i];
226 newenv[i + 1] = NULL;
229 safe_fd(passwdpipe[0], 1);
237 /* if our real userid is zero, the child shouldn't inherit
238 * that, so drop privs permanently */
239 if (getuid() == 0 && !set_root_privs(-1)) {
240 error(_("could not drop root privileges"));
244 execve(prog, my_argv, env);
246 error(_("error [exec %s: %s]"), prog, e);