static const char **prepare_shell_cmd(struct argv_array *out, const char **argv)
{
if (!argv[0])
- die("BUG: shell command is empty");
+ BUG("shell command is empty");
if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
#ifndef GIT_WINDOWS_NATIVE
set_error_routine(old_errfn);
}
-static void prepare_cmd(struct argv_array *out, const struct child_process *cmd)
+static int prepare_cmd(struct argv_array *out, const struct child_process *cmd)
{
if (!cmd->argv[0])
- die("BUG: command is empty");
+ BUG("command is empty");
/*
* Add SHELL_PATH so in the event exec fails with ENOEXEC we can
/*
* If there are no '/' characters in the command then perform a path
* lookup and use the resolved path as the command to exec. If there
- * are no '/' characters or if the command wasn't found in the path,
- * have exec attempt to invoke the command directly.
+ * are '/' characters, we have exec attempt to invoke the command
+ * directly.
*/
if (!strchr(out->argv[1], '/')) {
char *program = locate_in_PATH(out->argv[1]);
if (program) {
free((char *)out->argv[1]);
out->argv[1] = program;
+ } else {
+ argv_array_clear(out);
+ errno = ENOENT;
+ return -1;
}
}
+
+ return 0;
}
static char **prep_childenv(const char *const *deltaenv)
sigset_t old;
};
-#ifndef NO_PTHREADS
-static void bug_die(int err, const char *msg)
-{
- if (err) {
- errno = err;
- die_errno("BUG: %s", msg);
- }
-}
-#endif
+#define CHECK_BUG(err, msg) \
+ do { \
+ int e = (err); \
+ if (e) \
+ BUG("%s: %s", msg, strerror(e)); \
+ } while(0)
static void atfork_prepare(struct atfork_state *as)
{
if (sigprocmask(SIG_SETMASK, &all, &as->old))
die_errno("sigprocmask");
#else
- bug_die(pthread_sigmask(SIG_SETMASK, &all, &as->old),
+ CHECK_BUG(pthread_sigmask(SIG_SETMASK, &all, &as->old),
"blocking all signals");
- bug_die(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &as->cs),
+ CHECK_BUG(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &as->cs),
"disabling cancellation");
#endif
}
if (sigprocmask(SIG_SETMASK, &as->old, NULL))
die_errno("sigprocmask");
#else
- bug_die(pthread_setcancelstate(as->cs, NULL),
+ CHECK_BUG(pthread_setcancelstate(as->cs, NULL),
"re-enabling cancellation");
- bug_die(pthread_sigmask(SIG_SETMASK, &as->old, NULL),
+ CHECK_BUG(pthread_sigmask(SIG_SETMASK, &as->old, NULL),
"restoring signal mask");
#endif
}
struct child_err cerr;
struct atfork_state as;
+ if (prepare_cmd(&argv, cmd) < 0) {
+ failed_errno = errno;
+ cmd->pid = -1;
+ goto end_of_spawn;
+ }
+
if (pipe(notify_pipe))
notify_pipe[0] = notify_pipe[1] = -1;
set_cloexec(null_fd);
}
- prepare_cmd(&argv, cmd);
childenv = prep_childenv(cmd->env);
atfork_prepare(&as);
argv_array_clear(&argv);
free(childenv);
}
+end_of_spawn:
+
#else
{
int fhin = 0, fhout = 1, fherr = 2;
int code;
if (cmd->out < 0 || cmd->err < 0)
- die("BUG: run_command with a pipe can cause deadlock");
+ BUG("run_command with a pipe can cause deadlock");
code = start_command(cmd);
if (code)
pp->data = data;
if (!get_next_task)
- die("BUG: you need to specify a get_next_task function");
+ BUG("you need to specify a get_next_task function");
pp->get_next_task = get_next_task;
pp->start_failure = start_failure ? start_failure : default_start_failure;
if (pp->children[i].state == GIT_CP_FREE)
break;
if (i == pp->max_processes)
- die("BUG: bookkeeping is hard");
+ BUG("bookkeeping is hard");
code = pp->get_next_task(&pp->children[i].process,
&pp->children[i].err,