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