void _popen_noshell_child_process(
        /* We need the pointer *arg_ptr only to free whatever we reference if exec() fails and we were fork()'ed (thus memory was copied),
         * not clone()'d */
        struct popen_noshell_clone_arg *arg_ptr, /* NULL if we were called by pure fork() (not because of Valgrind) */
        int pipefd_0, int pipefd_1, int read_pipe, int ignore_stderr, const char *file, const char * const *argv) {

        int closed_child_fd;
        int closed_pipe_fd;
        int dupped_child_fd;
        int pipefd[2] = {pipefd_0, pipefd_1};

        if (ignore_stderr) { /* ignore STDERR completely? */
                if (popen_noshell_reopen_fd_to_dev_null(STDERR_FILENO) != 0) _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", STDERR_FILENO);
        }

        if (read_pipe) {
                closed_child_fd = STDIN_FILENO;         /* re-open STDIN to /dev/null */
                closed_pipe_fd = 0;                     /* close read end of pipe */
                dupped_child_fd = STDOUT_FILENO;        /* dup the other pipe end to STDOUT */
        } else {
                closed_child_fd = STDOUT_FILENO;        /* ignore STDOUT completely */
                closed_pipe_fd = 1;                     /* close write end of pipe */
                dupped_child_fd = STDIN_FILENO;         /* dup the other pipe end to STDIN */
        }
        if (popen_noshell_reopen_fd_to_dev_null(closed_child_fd) != 0) {
                _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", closed_child_fd);
        }
        if (_popen_noshell_close_and_dup(pipefd, closed_pipe_fd, dupped_child_fd) != 0) {
                _ERR(255, "_popen_noshell_close_and_dup(%d ,%d)", closed_pipe_fd, dupped_child_fd);
        }

        execvp(file, (char * const *)argv);

        /* if we are here, exec() failed */

        warn("exec(\"%s\") inside the child", file);

#ifdef POPEN_NOSHELL_VALGRIND_DEBUG
        if (arg_ptr) { /* not NULL if we were called by clone() */
                /* but Valgrind does not support clone(), so we were actually called by fork(), thus memory was copied... */
                /* free this copied memory; if it was not Valgrind, this memory would have been shared and would belong to the parent! */
                _pclose_noshell_free_clone_arg_memory(arg_ptr);
        }
#endif

        if (fflush(stdout) != 0) _ERR(255, "fflush(stdout)");
        if (fflush(stderr) != 0) _ERR(255, "fflush(stderr)");
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);

        _exit(255); // call _exit() and not exit(), or you'll have troubles in C++
}
Esempio n. 2
0
static void popen_noshell_child_process(
	int pipefd_0, int pipefd_1,
	int read_pipe, int ignore_stderr,
	const char *file, const char * const *argv) {
	int closed_child_fd;
	int closed_pipe_fd;
	int dupped_child_fd;
	int pipefd[2] = {pipefd_0, pipefd_1};

	if (ignore_stderr) { /* ignore STDERR completely? */
		if (popen_noshell_reopen_fd_to_dev_null(STDERR_FILENO) != 0) _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", STDERR_FILENO);
	}

	if (read_pipe) {
		closed_child_fd = STDIN_FILENO;		/* re-open STDIN to /dev/null */
		closed_pipe_fd = 0;			/* close read end of pipe */
		dupped_child_fd = STDOUT_FILENO;	/* dup the other pipe end to STDOUT */
	} else {
		closed_child_fd = STDOUT_FILENO;	/* ignore STDOUT completely */
		closed_pipe_fd = 1;			/* close write end of pipe */
		dupped_child_fd = STDIN_FILENO;		/* dup the other pipe end to STDIN */
	}
	if (popen_noshell_reopen_fd_to_dev_null(closed_child_fd) != 0) {
		_ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", closed_child_fd);
	}
	if (popen_noshell_close_and_dup(pipefd, closed_pipe_fd, dupped_child_fd) != 0) {
		_ERR(255, "popen_noshell_close_and_dup(%d ,%d)", closed_pipe_fd, dupped_child_fd);
	}

	execvp(file, (char * const *)argv);

	/* if we are here, exec() failed */

	warn("exec(\"%s\") inside the child", file);

	if (fflush(stdout) != 0) _ERR(255, "fflush(stdout)");
	if (fflush(stderr) != 0) _ERR(255, "fflush(stderr)");
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);

	_exit(255); // call _exit() and not exit(), or you'll have troubles in C++
}