ref: 21246a29a61afa8882a4a7f43d84fb4cce9f5a03
dir: /driver/posix/scc.c/
/* See LICENSE file for copyright and license details. */ #define _POSIX_SOURCE #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <errno.h> #include <limits.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../../inc/arg.h" #include "../../inc/cc.h" #define NARGS 64 enum { CC1, CC2, QBE, NR_TOOLS, }; static struct { char cmd[PATH_MAX]; char *args[NARGS]; int nargs; char bin[16]; char name[8]; int in, out; pid_t pid; } tools[NR_TOOLS] = { [CC1] = { .name = "cc1", }, [CC2] = { .name = "cc2", }, [QBE] = { .name = "qbe", .bin = "qbe", .cmd = "qbe", }, }; char *argv0; static char *arch; static int Eflag; static void terminate(void) { int i; for (i = 0; i < NR_TOOLS; ++i) { if (tools[i].pid) kill(tools[i].pid, SIGTERM); } } int settool(int tool, int pipeout) { int fds[2], n; static int fdin; switch (tool) { case CC1: case CC2: n = snprintf(tools[tool].bin, sizeof(tools[tool].bin), arch ? "%s-%s" : "%s", tools[tool].name, arch); if (n < 0 || n >= sizeof(tools[tool].bin)) die("scc: target tool name too long"); n = snprintf(tools[tool].cmd, sizeof(tools[tool].cmd), "%s/libexec/scc/%s", PREFIX, tools[tool].bin); if (n < 0 || n >= sizeof(tools[tool].cmd)) die("scc: target tool path too long"); break; default: break; } tools[tool].args[0] = tools[tool].bin; if (fdin) { tools[tool].in = fdin; fdin = 0; } if (pipeout) { if (pipe(fds)) die("scc: pipe: %s", strerror(errno)); tools[tool].out = fds[1]; fdin = fds[0]; } return tool; } void spawn(int tool) { switch (tools[tool].pid = fork()) { case -1: die("scc: %s: %s", tools[tool].name, strerror(errno)); case 0: if (tools[tool].out) dup2(tools[tool].out, 1); if (tools[tool].in) dup2(tools[tool].in, 0); execvp(tools[tool].cmd, tools[tool].args); fprintf(stderr, "scc: execv %s: %s\n", tools[tool].cmd, strerror(errno)); _exit(1); default: if (tools[tool].in) close(tools[tool].in); if (tools[tool].out) close(tools[tool].out); break; } } static void usage(void) { die("usage: %s [-m arch] input ..."); } int main(int argc, char *argv[]) { int st, i; pid_t pid; atexit(terminate); arch = getenv("ARCH"); ARGBEGIN { case 'E': Eflag = 1; tools[CC1].args[++tools[CC1].nargs] = "-E"; break; case 'm': arch = EARGF(usage()); break; case '-': fprintf(stderr, "scc: ignored parameter --%s\n", EARGF(usage())); break; default: usage(); } ARGEND if (!argc) die("scc: fatal error: no input files"); tools[CC1].args[++tools[CC1].nargs] = *argv; if (Eflag) { spawn(settool(CC1, 0)); } else { spawn(settool(CC1, 1)); if (!arch || strcmp(arch, "qbe")) { spawn(settool(CC2, 0)); } else { spawn(settool(CC2, 1)); spawn(settool(QBE, 0)); } } for (i = 0; i < NR_TOOLS; ++i) { if ((pid = wait(&st)) < 0) break; if (pid == tools[i].pid) tools[i].pid = 0; if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) exit(-1); } return 0; }