|
|
|
@ -39,6 +39,48 @@ static inline void set_cloexec(int fd)
@@ -39,6 +39,48 @@ static inline void set_cloexec(int fd)
|
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure) |
|
|
|
|
{ |
|
|
|
|
int status, code = -1; |
|
|
|
|
pid_t waiting; |
|
|
|
|
int failed_errno = 0; |
|
|
|
|
|
|
|
|
|
while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR) |
|
|
|
|
; /* nothing */ |
|
|
|
|
|
|
|
|
|
if (waiting < 0) { |
|
|
|
|
failed_errno = errno; |
|
|
|
|
error("waitpid for %s failed: %s", argv0, strerror(errno)); |
|
|
|
|
} else if (waiting != pid) { |
|
|
|
|
error("waitpid is confused (%s)", argv0); |
|
|
|
|
} else if (WIFSIGNALED(status)) { |
|
|
|
|
code = WTERMSIG(status); |
|
|
|
|
error("%s died of signal %d", argv0, code); |
|
|
|
|
/* |
|
|
|
|
* This return value is chosen so that code & 0xff |
|
|
|
|
* mimics the exit code that a POSIX shell would report for |
|
|
|
|
* a program that died from this signal. |
|
|
|
|
*/ |
|
|
|
|
code -= 128; |
|
|
|
|
} else if (WIFEXITED(status)) { |
|
|
|
|
code = WEXITSTATUS(status); |
|
|
|
|
/* |
|
|
|
|
* Convert special exit code when execvp failed. |
|
|
|
|
*/ |
|
|
|
|
if (code == 127) { |
|
|
|
|
code = -1; |
|
|
|
|
failed_errno = ENOENT; |
|
|
|
|
if (!silent_exec_failure) |
|
|
|
|
error("cannot run %s: %s", argv0, |
|
|
|
|
strerror(ENOENT)); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
error("waitpid is confused (%s)", argv0); |
|
|
|
|
} |
|
|
|
|
errno = failed_errno; |
|
|
|
|
return code; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int start_command(struct child_process *cmd) |
|
|
|
|
{ |
|
|
|
|
int need_in, need_out, need_err; |
|
|
|
@ -272,48 +314,6 @@ fail_pipe:
@@ -272,48 +314,6 @@ fail_pipe:
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure) |
|
|
|
|
{ |
|
|
|
|
int status, code = -1; |
|
|
|
|
pid_t waiting; |
|
|
|
|
int failed_errno = 0; |
|
|
|
|
|
|
|
|
|
while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR) |
|
|
|
|
; /* nothing */ |
|
|
|
|
|
|
|
|
|
if (waiting < 0) { |
|
|
|
|
failed_errno = errno; |
|
|
|
|
error("waitpid for %s failed: %s", argv0, strerror(errno)); |
|
|
|
|
} else if (waiting != pid) { |
|
|
|
|
error("waitpid is confused (%s)", argv0); |
|
|
|
|
} else if (WIFSIGNALED(status)) { |
|
|
|
|
code = WTERMSIG(status); |
|
|
|
|
error("%s died of signal %d", argv0, code); |
|
|
|
|
/* |
|
|
|
|
* This return value is chosen so that code & 0xff |
|
|
|
|
* mimics the exit code that a POSIX shell would report for |
|
|
|
|
* a program that died from this signal. |
|
|
|
|
*/ |
|
|
|
|
code -= 128; |
|
|
|
|
} else if (WIFEXITED(status)) { |
|
|
|
|
code = WEXITSTATUS(status); |
|
|
|
|
/* |
|
|
|
|
* Convert special exit code when execvp failed. |
|
|
|
|
*/ |
|
|
|
|
if (code == 127) { |
|
|
|
|
code = -1; |
|
|
|
|
failed_errno = ENOENT; |
|
|
|
|
if (!silent_exec_failure) |
|
|
|
|
error("cannot run %s: %s", argv0, |
|
|
|
|
strerror(ENOENT)); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
error("waitpid is confused (%s)", argv0); |
|
|
|
|
} |
|
|
|
|
errno = failed_errno; |
|
|
|
|
return code; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int finish_command(struct child_process *cmd) |
|
|
|
|
{ |
|
|
|
|
return wait_or_whine(cmd->pid, cmd->argv[0], cmd->silent_exec_failure); |
|
|
|
|