1 // SPDX-License-Identifier: GPL-2.0 2 #include <unistd.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <ctype.h> 6 #include <fcntl.h> 7 #include <string.h> 8 #include <linux/compiler.h> 9 #include <linux/string.h> 10 #include <errno.h> 11 #include <sys/wait.h> 12 #include "subcmd-util.h" 13 #include "run-command.h" 14 #include "exec-cmd.h" 15 16 #define STRERR_BUFSIZE 128 17 18 static inline void close_pair(int fd[2]) 19 { 20 close(fd[0]); 21 close(fd[1]); 22 } 23 24 static inline void dup_devnull(int to) 25 { 26 int fd = open("/dev/null", O_RDWR); 27 dup2(fd, to); 28 close(fd); 29 } 30 31 int start_command(struct child_process *cmd) 32 { 33 int need_in, need_out, need_err; 34 int fdin[2], fdout[2], fderr[2]; 35 char sbuf[STRERR_BUFSIZE]; 36 37 /* 38 * In case of errors we must keep the promise to close FDs 39 * that have been passed in via ->in and ->out. 40 */ 41 42 need_in = !cmd->no_stdin && cmd->in < 0; 43 if (need_in) { 44 if (pipe(fdin) < 0) { 45 if (cmd->out > 0) 46 close(cmd->out); 47 return -ERR_RUN_COMMAND_PIPE; 48 } 49 cmd->in = fdin[1]; 50 } 51 52 need_out = !cmd->no_stdout 53 && !cmd->stdout_to_stderr 54 && cmd->out < 0; 55 if (need_out) { 56 if (pipe(fdout) < 0) { 57 if (need_in) 58 close_pair(fdin); 59 else if (cmd->in) 60 close(cmd->in); 61 return -ERR_RUN_COMMAND_PIPE; 62 } 63 cmd->out = fdout[0]; 64 } 65 66 need_err = !cmd->no_stderr && cmd->err < 0; 67 if (need_err) { 68 if (pipe(fderr) < 0) { 69 if (need_in) 70 close_pair(fdin); 71 else if (cmd->in) 72 close(cmd->in); 73 if (need_out) 74 close_pair(fdout); 75 else if (cmd->out) 76 close(cmd->out); 77 return -ERR_RUN_COMMAND_PIPE; 78 } 79 cmd->err = fderr[0]; 80 } 81 82 fflush(NULL); 83 cmd->pid = fork(); 84 if (!cmd->pid) { 85 if (cmd->no_stdin) 86 dup_devnull(0); 87 else if (need_in) { 88 dup2(fdin[0], 0); 89 close_pair(fdin); 90 } else if (cmd->in) { 91 dup2(cmd->in, 0); 92 close(cmd->in); 93 } 94 95 if (cmd->no_stderr) 96 dup_devnull(2); 97 else if (need_err) { 98 dup2(fderr[1], 2); 99 close_pair(fderr); 100 } 101 102 if (cmd->no_stdout) 103 dup_devnull(1); 104 else if (cmd->stdout_to_stderr) 105 dup2(2, 1); 106 else if (need_out) { 107 dup2(fdout[1], 1); 108 close_pair(fdout); 109 } else if (cmd->out > 1) { 110 dup2(cmd->out, 1); 111 close(cmd->out); 112 } 113 114 if (cmd->dir && chdir(cmd->dir)) 115 die("exec %s: cd to %s failed (%s)", cmd->argv[0], 116 cmd->dir, str_error_r(errno, sbuf, sizeof(sbuf))); 117 if (cmd->env) { 118 for (; *cmd->env; cmd->env++) { 119 if (strchr(*cmd->env, '=')) 120 putenv((char*)*cmd->env); 121 else 122 unsetenv(*cmd->env); 123 } 124 } 125 if (cmd->preexec_cb) 126 cmd->preexec_cb(); 127 if (cmd->no_exec_cmd) 128 exit(cmd->no_exec_cmd(cmd)); 129 if (cmd->exec_cmd) { 130 execv_cmd(cmd->argv); 131 } else { 132 execvp(cmd->argv[0], (char *const*) cmd->argv); 133 } 134 exit(127); 135 } 136 137 if (cmd->pid < 0) { 138 int err = errno; 139 if (need_in) 140 close_pair(fdin); 141 else if (cmd->in) 142 close(cmd->in); 143 if (need_out) 144 close_pair(fdout); 145 else if (cmd->out) 146 close(cmd->out); 147 if (need_err) 148 close_pair(fderr); 149 return err == ENOENT ? 150 -ERR_RUN_COMMAND_EXEC : 151 -ERR_RUN_COMMAND_FORK; 152 } 153 154 if (need_in) 155 close(fdin[0]); 156 else if (cmd->in) 157 close(cmd->in); 158 159 if (need_out) 160 close(fdout[1]); 161 else if (cmd->out) 162 close(cmd->out); 163 164 if (need_err) 165 close(fderr[1]); 166 167 return 0; 168 } 169 170 static int wait_or_whine(struct child_process *cmd, bool block) 171 { 172 bool finished; 173 int result; 174 175 if (cmd->pid <= 0) { 176 cmd->finished = 1; 177 if (cmd->pid < 0 && cmd->finish_result == 0) 178 cmd->finish_result = -ERR_RUN_COMMAND_FORK; 179 return cmd->finish_result; 180 } 181 182 finished = cmd->finished; 183 result = cmd->finish_result; 184 185 while (!finished) { 186 int status, code; 187 pid_t waiting = waitpid(cmd->pid, &status, block ? 0 : WNOHANG); 188 189 if (!block && waiting == 0) 190 break; 191 192 if (waiting < 0 && errno == EINTR) 193 continue; 194 195 finished = true; 196 if (waiting < 0) { 197 char sbuf[STRERR_BUFSIZE]; 198 199 fprintf(stderr, " Error: waitpid failed (%s)", 200 str_error_r(errno, sbuf, sizeof(sbuf))); 201 result = -ERR_RUN_COMMAND_WAITPID; 202 } else if (waiting != cmd->pid) { 203 result = -ERR_RUN_COMMAND_WAITPID_WRONG_PID; 204 } else if (WIFSIGNALED(status)) { 205 result = -ERR_RUN_COMMAND_WAITPID_SIGNAL; 206 } else if (!WIFEXITED(status)) { 207 result = -ERR_RUN_COMMAND_WAITPID_NOEXIT; 208 } else { 209 code = WEXITSTATUS(status); 210 switch (code) { 211 case 127: 212 result = -ERR_RUN_COMMAND_EXEC; 213 break; 214 case 0: 215 result = 0; 216 break; 217 default: 218 result = -code; 219 break; 220 } 221 } 222 } 223 if (finished) { 224 cmd->finished = 1; 225 cmd->finish_result = result; 226 } 227 return result; 228 } 229 230 /* 231 * Conservative estimate of number of characaters needed to hold an a decoded 232 * integer, assume each 3 bits needs a character byte and plus a possible sign 233 * character. 234 */ 235 #ifndef is_signed_type 236 #define is_signed_type(type) (((type)(-1)) < (type)1) 237 #endif 238 #define MAX_STRLEN_TYPE(type) (sizeof(type) * 8 / 3 + (is_signed_type(type) ? 1 : 0)) 239 240 int check_if_command_finished(struct child_process *cmd) 241 { 242 #ifdef __linux__ 243 char filename[6 + MAX_STRLEN_TYPE(typeof(cmd->pid)) + 7 + 1]; 244 char status_line[256]; 245 FILE *status_file; 246 #endif 247 248 if (cmd->finished) 249 return 1; 250 if (cmd->pid <= 0) { 251 cmd->finished = 1; 252 if (cmd->pid < 0 && cmd->finish_result == 0) 253 cmd->finish_result = -ERR_RUN_COMMAND_FORK; 254 return 1; 255 } 256 257 #ifdef __linux__ 258 /* 259 * Check by reading /proc/<pid>/status as calling waitpid causes 260 * stdout/stderr to be closed and data lost. 261 */ 262 sprintf(filename, "/proc/%u/status", cmd->pid); 263 status_file = fopen(filename, "r"); 264 if (status_file == NULL) { 265 int status; 266 pid_t waiting; 267 268 /* 269 * fopen() can fail with ENOENT if the process has been reaped. 270 * It can also fail with EMFILE/ENFILE if RLIMIT_NOFILE is reached. 271 * In those cases, use waitpid(..., WNOHANG) to robustly check 272 * and reap the process if it has exited. 273 */ 274 if (errno == ENOENT) 275 return 1; 276 277 waiting = waitpid(cmd->pid, &status, WNOHANG); 278 if (waiting == cmd->pid) { 279 int result; 280 int code; 281 282 cmd->finished = 1; 283 if (WIFSIGNALED(status)) { 284 result = -ERR_RUN_COMMAND_WAITPID_SIGNAL; 285 } else if (!WIFEXITED(status)) { 286 result = -ERR_RUN_COMMAND_WAITPID_NOEXIT; 287 } else { 288 code = WEXITSTATUS(status); 289 switch (code) { 290 case 127: 291 result = -ERR_RUN_COMMAND_EXEC; 292 break; 293 case 0: 294 result = 0; 295 break; 296 default: 297 result = -code; 298 break; 299 } 300 } 301 cmd->finish_result = result; 302 return 1; 303 } 304 if (waiting < 0 && (errno == ECHILD || errno == ESRCH)) 305 return 1; 306 return 0; 307 } 308 while (fgets(status_line, sizeof(status_line), status_file) != NULL) { 309 char *p; 310 311 if (strncmp(status_line, "State:", 6)) 312 continue; 313 314 fclose(status_file); 315 p = status_line + 6; 316 while (isspace(*p)) 317 p++; 318 return *p == 'Z' ? 1 : 0; 319 } 320 /* Read failed assume finish_command was called. */ 321 fclose(status_file); 322 return 1; 323 #else 324 wait_or_whine(cmd, /*block=*/false); 325 return cmd->finished; 326 #endif 327 } 328 329 int finish_command(struct child_process *cmd) 330 { 331 return wait_or_whine(cmd, /*block=*/true); 332 } 333 334 int run_command(struct child_process *cmd) 335 { 336 int code = start_command(cmd); 337 if (code) 338 return code; 339 return finish_command(cmd); 340 } 341 342 static void prepare_run_command_v_opt(struct child_process *cmd, 343 const char **argv, 344 int opt) 345 { 346 memset(cmd, 0, sizeof(*cmd)); 347 cmd->argv = argv; 348 cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0; 349 cmd->exec_cmd = opt & RUN_EXEC_CMD ? 1 : 0; 350 cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0; 351 } 352 353 int run_command_v_opt(const char **argv, int opt) 354 { 355 struct child_process cmd; 356 prepare_run_command_v_opt(&cmd, argv, opt); 357 return run_command(&cmd); 358 } 359