예제 #1
0
파일: pipespawn.c 프로젝트: B-Rich/amanda
pid_t
pipespawnv_passwd(
    char *	prog,
    int		pipedef,
    int		need_root,
    int *	stdinfd,
    int *	stdoutfd,
    int *	stderrfd,
    char **	my_argv)
{
    pid_t pid;
    int i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2];
    char number[NUM_STR_SIZE];
    char **arg;
    char *e;
    char **env;
    char *cmdline;
    char **newenv;
    char *passwdvar = NULL;
    int  *passwdfd = NULL;
    GPtrArray *array = g_ptr_array_new();
    gchar **strings;

    /*
     * Log the command line and count the args.
     */
    if ((pipedef & PASSWD_PIPE) != 0) {
	passwdvar = *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));

    g_ptr_array_add(array, g_strdup(prog));

    for(arg = my_argv; *arg != NULL; arg++) {
        if (*arg == skip_argument)
            continue;
        g_ptr_array_add(array, quote_string(*arg));
    }

    g_ptr_array_add(array, NULL);

    strings = (gchar **)g_ptr_array_free(array, FALSE);
    cmdline = g_strjoinv(" ", strings);
    g_strfreev(strings);

    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));
	    /*NOTREACHED*/
	}
    }
    if ((pipedef & STDOUT_PIPE) != 0) {
	if(pipe(outpipe) == -1) {
	    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));
	    /*NOTREACHED*/
	}
    }
    if ((pipedef & PASSWD_PIPE) != 0) {
	if(pipe(passwdpipe) == -1) {
	    error(_("error [open pipe to %s: %s]"), prog, strerror(errno));
	    /*NOTREACHED*/
	}
    }

    /*
     * 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);
	/*NOTREACHED*/

    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 */
	debug_dup_stderr_to_debug();
	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) {
	    g_fprintf(stderr, "error [spawn %s: dup2 in: %s]", prog, strerror(errno));
	    exit(1);
	    /*NOTREACHED*/
	}
	if(dup2(outpipe[1], 1) == -1) {
	    g_fprintf(stderr, "error [spawn %s: dup2 out: %s]", prog, strerror(errno));
	    exit(1);
	    /*NOTREACHED*/
	}
	if(dup2(errpipe[1], 2) == -1) {
	    g_fprintf(stderr, "error [spawn %s: dup2 err: %s]", prog, strerror(errno));
	    exit(1);
	    /*NOTREACHED*/
	}

	/*
	 * 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++)
		(void)i; /* make lint happy and do nothing */	
	    newenv = (char **)g_malloc((i + 1 + 1) * sizeof(*newenv));
	    g_snprintf(number, sizeof(number), "%d", passwdpipe[0]);
	    newenv[0] = g_strjoin(NULL, passwdvar, "=", number, NULL);
	    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*/
    }
    amfree(cmdline);
    return pid;
}
예제 #2
0
파일: changer.c 프로젝트: pcmantz/amanda
static int
start_chg_glue(void)
{
    int stdin_pipe[2] = { -1, -1 };
    int stdout_pipe[2] = { -1, -1 };
    char *chg_glue = NULL;
    char **config_options = NULL;
    char *cmdline = NULL;

    /* is it already running? */
    if (tpchanger_pid != -1)
	return 1;

    if (pipe(stdin_pipe) == -1 || pipe(stdout_pipe) == -1) {
	changer_resultstr = vstrallocf(
			_("<error> could not make pipe: %s"), strerror(errno));
	goto error;
    }

    config_options = get_config_options(2);
    config_options[0] = g_strdup("chg-glue");
    config_options[1] = g_strdup(get_config_name());
    chg_glue = g_strdup_printf("%s/chg-glue", amlibexecdir);

    cmdline = g_strjoinv(" ", config_options);
    g_debug("invoking %s: %s", chg_glue, cmdline);
    amfree(cmdline);

    switch(tpchanger_pid = fork()) {
    case -1:
	changer_resultstr = vstrallocf(
			_("<error> could not fork: %s"), strerror(errno));
	goto error;

    case 0:
	debug_dup_stderr_to_debug();
	if(dup2(stdin_pipe[0], 0) == -1) {
	    changer_resultstr = vstrallocf(
			_("<error> could not dup2: %s\n"), strerror(errno));
	    goto child_err;
	}

	if(dup2(stdout_pipe[1], 1) == -1) {
	    changer_resultstr = vstrallocf(
			_("<error> could not dup2: %s\n"), strerror(errno));
	    goto child_err;
	}

	safe_fd(-1, 0);
	execv(chg_glue, config_options);
	changer_resultstr = vstrallocf(
			_("<error> could not exec \"%s\": %s\n"), chg_glue, strerror(errno));

child_err:
	(void)full_write(stdout_pipe[1], changer_resultstr, strlen(changer_resultstr));
	exit(1);

    default:
	aclose(stdin_pipe[0]);
	aclose(stdout_pipe[1]);

	g_strfreev(config_options);
	amfree(chg_glue);
	amfree(cmdline);

	tpchanger_stdout = stdout_pipe[0];
	tpchanger_stdin = stdin_pipe[1];

	return 1;
    }

error:
    amfree(chg_glue);
    amfree(cmdline);
    aclose(stdin_pipe[0]);
    aclose(stdin_pipe[1]);
    aclose(stdout_pipe[0]);
    aclose(stdout_pipe[1]);

    return 0;
}