in ExecUtil.cpp [67:210]
int Cmd::Start() {
if (_pid > 0) {
return -EBUSY;
}
cleanup();
int sigpipe[2];
int inpipe[2] = {-1, -1};
int outpipe[2] = {-1, -1};
int errpipe[2] = {-1, -1};
int ret = 0;
ret = pipe2(sigpipe, O_CLOEXEC);
if (ret != 0) {
_fail_reason = FAILED_PIPE2;
_errno = errno;
return -errno;
}
if (STDIN_FLAGS(_flags) == PIPE_STDIN) {
ret = pipe(inpipe);
if (ret != 0) {
_fail_reason = FAILED_PIPE;
_errno = errno;
return -errno;
}
}
if (STDOUT_FLAGS(_flags) & PIPE_STDOUT) {
ret = pipe(outpipe);
if (ret != 0) {
_fail_reason = FAILED_PIPE;
_errno = errno;
return -errno;
}
}
if (STDERR_FLAGS(_flags) == PIPE_STDERR) {
ret = pipe(errpipe);
if (ret != 0) {
_fail_reason = FAILED_PIPE;
_errno = errno;
return -errno;
}
}
if ((_flags & COMBINE_OUTPUT) == COMBINE_OUTPUT) {
errpipe[0] = outpipe[0];
errpipe[1] = outpipe[1];
}
auto pid = fork();
if (pid < 0) {
_fail_reason = FAILED_FORK;
_errno = errno;
return -errno;
}
if (pid == 0) {
close(sigpipe[_PIPE_READ]);
char *args[_args.size()+2];
args[0] = new char[_path.size()+1];
_path.copy(args[0], _path.size());
args[0][_path.size()] = 0;
int idx = 1;
for(auto& arg: _args) {
args[idx] = new char[arg.size()+1];
arg.copy(args[idx], arg.size());
args[idx][arg.size()] = 0;
idx++;
}
args[idx] = nullptr;
if (inpipe[_PIPE_READ] != -1) {
ret = dup2(inpipe[_PIPE_READ], 0);
if (ret != 0) {
write_error(FAILED_DUP2, errno, sigpipe[_PIPE_WRITE]);
exit(1);
}
} else if (STDIN_FLAGS(_flags) == NULL_STDIN) {
int in = open("/dev/null", O_RDONLY);
if (in < 0) {
write_error(FAILED_OPEN, errno, sigpipe[_PIPE_WRITE]);
exit(1);
}
ret = dup2(in, 0);
if (ret != 0) {
write_error(FAILED_DUP2, errno, sigpipe[_PIPE_WRITE]);
exit(1);
}
}
if (outpipe[_PIPE_WRITE] != -1) {
ret = dup2(outpipe[_PIPE_WRITE], 1);
if (ret != 1) {
write_error(FAILED_DUP2, errno, sigpipe[_PIPE_WRITE]);
exit(1);
}
}
if (errpipe[_PIPE_WRITE] != -1) {
ret = dup2(errpipe[_PIPE_WRITE], 2);
if (ret != 2) {
write_error(FAILED_DUP2, errno, sigpipe[_PIPE_WRITE]);
exit(1);
}
}
::execve(_path.c_str(), args, environ);
write_error(FAILED_EXECVE, errno, sigpipe[_PIPE_WRITE]);
exit(1);
} else {
_pid = pid;
close(sigpipe[_PIPE_WRITE]);
_stdin = inpipe[_PIPE_WRITE];
_stdout = outpipe[_PIPE_READ];
_stderr = errpipe[_PIPE_READ];
if (inpipe[_PIPE_READ] != -1) {
close(inpipe[_PIPE_READ]);
}
if (outpipe[_PIPE_WRITE] != -1) {
close(outpipe[_PIPE_WRITE]);
}
if (errpipe[_PIPE_WRITE] != -1) {
close(errpipe[_PIPE_WRITE]);
}
uint32_t code;
// The return code is unimportant, the read will return once the child process exits or execs
auto nr = read(sigpipe[_PIPE_READ], &code, sizeof(code));
if (nr == sizeof(code)) {
_fail_reason = static_cast<int>(code>>16);
_errno = static_cast<int>(code&0xFFFF);
} else {
_fail_reason = 0;
_errno = 0;
}
close(sigpipe[_PIPE_READ]);
return (-_errno);
}
}