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