shithub: scc

ref: 3791d53a684fb8df4bbd7df4f834c1dc07595627
dir: /driver/posix/scc.c/

View raw version
/* 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 "../../arg.h"
#include "../../inc/cc.h"

char *argv0;

#define NARGS 64
static char cmd[FILENAME_MAX];
static char *argcc1[NARGS];
static char *argcc2[NARGS];

static pid_t pid_cc1, pid_cc2;
static char *arch;

static void
terminate(void)
{
	if (pid_cc1)
		kill(pid_cc1, SIGTERM);
	if (pid_cc2)
		kill(pid_cc2, SIGTERM);
}

void
cc1(int fd)
{
	pid_t pid;
	char *fmt;
	int r;

	switch (pid = fork()) {
	case -1:
		die("scc: cc1: %s", strerror(errno));
		exit(1);
	case 0:
		dup2(fd, 1);
		fmt = (arch) ? "%s/libexec/scc/cc1-%s" : "%s/libexec/scc/cc1";
		r = snprintf(cmd, sizeof(cmd), fmt, PREFIX, arch);
		if (r == sizeof(cmd)) {
			die("scc: incorrect prefix\n");
		}
		execv(cmd, argcc1);
		die("scc: execv cc1: %s", strerror(errno));
		abort();
	default:
		pid_cc1 = pid;
		close(fd);
		break;
	}
}

pid_t
cc2(int fd)
{
	pid_t pid;
	char *fmt;
	int r;

	switch (pid = fork()) {
	case -1:
		die("scc: cc2: %s", strerror(errno));
	case 0:
		dup2(fd, 0);
		fmt = (arch) ? "%s/libexec/scc/cc2-%s" : "%s/libexec/scc/cc2";
		r = snprintf(cmd, sizeof(cmd), fmt, PREFIX, arch);
		if (r == sizeof(cmd)) {
			die("scc: incorrect prefix");
		}
		execv(cmd, argcc2);
		fprintf(stderr, "scc: execv cc2: %s\n", strerror(errno));
		abort();
	default:
		pid_cc2 = pid;
		close(fd);
		break;
	}
}

static void
usage(void)
{
	die("usage: %s [-m arch] input ...");
}

int
main(int argc, char *argv[])
{
	int fds[2], st, i;
	char *p;
	pid_t pid;

	atexit(terminate);

	if (p = getenv("ARCH"))
		arch = p;

	ARGBEGIN {
	case 'm':
		arch = EARGF(usage());
		break;
	case '-':
		printf("scc: ignored parameter --%s\n", EARGF(usage()));
		break;
	default:
		usage();
	} ARGEND

	if (!argc)
		die("scc: fatal error: no input files");

	if (pipe(fds))
		die("scc: pipe: %s", strerror(errno));

	argcc1[0] = "cc1";
	argcc1[1] = *argv;
	argcc2[0] = "cc2";

	cc1(fds[1]);
	cc2(fds[0]);

	for (i = 0; i < 2; ++i) {
		pid = wait(&st);
		if (pid == pid_cc1)
			pid_cc1 = 0;
		else if (pid == pid_cc2)
			pid_cc2 = 0;
		if (!WIFEXITED(st) || WEXITSTATUS(st) != 0)
			exit(-1);
	}

	return 0;
}