| git.druid.rocks | index | druid520 | q | src/ | runsh.c |
src/runsh.c
#include "config.h"
#ifdef OS_NETBSD_C
#define _NETBSD_SOURCE 1
#endif
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "q.h"
/* run a recipe's command. the child shell sources /etc/q.cfg (the same
* general-purpose config q itself reads its prefix/db/pkgs from) before
* exec'ing "$shell -e recipe cmd" -- so a config can set PATH, build
* flags, proxies, or anything else a recipe's get/add/del/upd needs. the
* -e keeps q's "fail loud, not silent" rule: a failing command inside a
* recipe aborts the whole operation. q's own Q_PREFIX/Q_DB/Q_PKGS are
* exported too, so a recipe knows where to install without the config
* having to export them itself. */
int
runrecipe(const struct qcfg* c, const char* recipe, const char* cmd)
{
pid_t pid;
int status;
pid = fork();
if(pid < 0)
{
die("fork failed");
return 1;
}
if(pid == 0)
{
setenv("Q_PREFIX", c->prefix, 1);
setenv("Q_DB", c->db, 1);
setenv("Q_PKGS", c->pkgs, 1);
setenv("Q_CONF_PATH", c->conf, 1);
execlp(c->shell, c->shell, "-e", "-c",
"[ -f \"$Q_CONF_PATH\" ] && . \"$Q_CONF_PATH\"; "
"exec \"$1\" -e \"$2\" \"$3\"",
c->shell, c->shell, recipe, cmd, (char*)NULL);
_exit(127);
}
if(waitpid(pid, &status, 0) < 0)
{
die("waitpid failed");
return 1;
}
if(!WIFEXITED(status) || WEXITSTATUS(status) != 0)
{
return 1;
}
return 0;
}