1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "cache.h"
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "run-command.h"
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "exec_cmd.h"
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline void close_pair(int fd[2])
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	close(fd[0]);
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	close(fd[1]);
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline void dup_devnull(int to)
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int fd = open("/dev/null", O_RDWR);
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	dup2(fd, to);
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	close(fd);
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint start_command(struct child_process *cmd)
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int need_in, need_out, need_err;
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int fdin[2], fdout[2], fderr[2];
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/*
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * In case of errors we must keep the promise to close FDs
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * that have been passed in via ->in and ->out.
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 */
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	need_in = !cmd->no_stdin && cmd->in < 0;
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (need_in) {
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pipe(fdin) < 0) {
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (cmd->out > 0)
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				close(cmd->out);
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ERR_RUN_COMMAND_PIPE;
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		cmd->in = fdin[1];
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	need_out = !cmd->no_stdout
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		&& !cmd->stdout_to_stderr
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		&& cmd->out < 0;
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (need_out) {
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pipe(fdout) < 0) {
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (need_in)
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				close_pair(fdin);
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			else if (cmd->in)
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				close(cmd->in);
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ERR_RUN_COMMAND_PIPE;
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		cmd->out = fdout[0];
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	need_err = !cmd->no_stderr && cmd->err < 0;
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (need_err) {
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pipe(fderr) < 0) {
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (need_in)
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				close_pair(fdin);
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			else if (cmd->in)
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				close(cmd->in);
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (need_out)
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				close_pair(fdout);
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			else if (cmd->out)
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				close(cmd->out);
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ERR_RUN_COMMAND_PIPE;
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		cmd->err = fderr[0];
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fflush(NULL);
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	cmd->pid = fork();
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!cmd->pid) {
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (cmd->no_stdin)
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup_devnull(0);
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (need_in) {
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup2(fdin[0], 0);
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close_pair(fdin);
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else if (cmd->in) {
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup2(cmd->in, 0);
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close(cmd->in);
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (cmd->no_stderr)
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup_devnull(2);
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (need_err) {
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup2(fderr[1], 2);
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close_pair(fderr);
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (cmd->no_stdout)
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup_devnull(1);
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (cmd->stdout_to_stderr)
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup2(2, 1);
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (need_out) {
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup2(fdout[1], 1);
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close_pair(fdout);
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else if (cmd->out > 1) {
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			dup2(cmd->out, 1);
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close(cmd->out);
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (cmd->dir && chdir(cmd->dir))
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			die("exec %s: cd to %s failed (%s)", cmd->argv[0],
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			    cmd->dir, strerror(errno));
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (cmd->env) {
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			for (; *cmd->env; cmd->env++) {
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				if (strchr(*cmd->env, '='))
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					putenv((char*)*cmd->env);
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				else
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					unsetenv(*cmd->env);
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (cmd->preexec_cb)
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			cmd->preexec_cb();
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (cmd->perf_cmd) {
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			execv_perf_cmd(cmd->argv);
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else {
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			execvp(cmd->argv[0], (char *const*) cmd->argv);
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		exit(127);
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (cmd->pid < 0) {
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int err = errno;
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (need_in)
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close_pair(fdin);
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (cmd->in)
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close(cmd->in);
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (need_out)
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close_pair(fdout);
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (cmd->out)
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close(cmd->out);
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (need_err)
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close_pair(fderr);
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return err == ENOENT ?
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			-ERR_RUN_COMMAND_EXEC :
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			-ERR_RUN_COMMAND_FORK;
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (need_in)
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		close(fdin[0]);
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else if (cmd->in)
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		close(cmd->in);
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (need_out)
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		close(fdout[1]);
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else if (cmd->out)
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		close(cmd->out);
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (need_err)
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		close(fderr[1]);
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int wait_or_whine(pid_t pid)
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (;;) {
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int status, code;
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pid_t waiting = waitpid(pid, &status, 0);
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (waiting < 0) {
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (errno == EINTR)
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				continue;
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			error("waitpid failed (%s)", strerror(errno));
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ERR_RUN_COMMAND_WAITPID;
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (waiting != pid)
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (WIFSIGNALED(status))
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!WIFEXITED(status))
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		code = WEXITSTATUS(status);
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		switch (code) {
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case 127:
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ERR_RUN_COMMAND_EXEC;
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case 0:
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return 0;
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		default:
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -code;
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint finish_command(struct child_process *cmd)
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return wait_or_whine(cmd->pid);
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint run_command(struct child_process *cmd)
191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int code = start_command(cmd);
193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (code)
194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return code;
195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return finish_command(cmd);
196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void prepare_run_command_v_opt(struct child_process *cmd,
199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				      const char **argv,
200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				      int opt)
201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	memset(cmd, 0, sizeof(*cmd));
203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	cmd->argv = argv;
204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	cmd->perf_cmd = opt & RUN_PERF_CMD ? 1 : 0;
206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint run_command_v_opt(const char **argv, int opt)
210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct child_process cmd;
212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	prepare_run_command_v_opt(&cmd, argv, opt);
213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return run_command(&cmd);
214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
215