master xplshn/aruu / cmd / posix / make / posix.c
  1#undef _POSIX_C_SOURCE
  2#define _POSIX_C_SOURCE 200809L
  3
  4#include <signal.h>
  5#include <sys/stat.h>
  6#include <sys/wait.h>
  7#include <unistd.h>
  8
  9#include <errno.h>
 10#include <stdio.h>
 11#include <string.h>
 12
 13#include "make.h"
 14
 15
 16static volatile pid_t pid;
 17
 18void
 19killchild(void)
 20{
 21	if (pid != 0)
 22		kill(pid, SIGTERM);
 23	pid = 0;
 24}
 25
 26int
 27is_dir(char *fname)
 28{
 29	struct stat st;
 30
 31	if (stat(fname, &st) < 0)
 32		return 0;
 33	return S_ISDIR(st.st_mode);
 34}
 35
 36void
 37exportvar(char *var, char *value)
 38{
 39	int n;
 40	char *buf;
 41
 42	n = snprintf(NULL, 0, "%s=%s", var, value);
 43	buf = emalloc(n+1);
 44	snprintf(buf, n+1, "%s=%s", var, value);
 45	putenv(buf);
 46}
 47
 48time_t
 49stamp(char *name)
 50{
 51	struct stat st;
 52
 53	if (stat(name, &st) < 0)
 54		return -1;
 55
 56	return st.st_mtime;
 57}
 58
 59int
 60launch(char *cmd, int ignore)
 61{
 62	int st;
 63	sigset_t new, old;
 64	char *name, *shell;
 65	char *args[] = {NULL, "-ec" , cmd, NULL};
 66	static int initsignals;
 67	extern char **environ;
 68	extern void sighandler(int);
 69
 70	if (!initsignals) {
 71		struct sigaction act = {
 72			.sa_handler = sighandler
 73		};
 74
 75		/* avoid BSD weirdness signal restart handling */
 76		sigaction(SIGINT, &act, NULL);
 77		sigaction(SIGHUP, &act, NULL);
 78		sigaction(SIGTERM, &act, NULL);
 79		sigaction(SIGQUIT, &act, NULL);
 80		initsignals = 1;
 81	}
 82
 83	sigfillset(&new);
 84	sigprocmask(SIG_BLOCK, &new, &old);
 85	if (stop)
 86		goto unblock;
 87
 88	switch (pid = fork()) {
 89	case -1:
 90		perror("make");
 91	unblock:
 92		sigprocmask(SIG_SETMASK, &old, NULL);
 93		return -1;
 94	case 0:
 95		signal(SIGINT, SIG_DFL);
 96		signal(SIGHUP, SIG_DFL);
 97		signal(SIGTERM, SIG_DFL);
 98		signal(SIGQUIT, SIG_DFL);
 99
100		sigprocmask(SIG_SETMASK, &old, NULL);
101
102		shell = getmacro("SHELL");
103
104		if (ignore)
105			args[1] = "-c";
106		if ((name = strrchr(shell, '/')) != NULL)
107			++name;
108		else
109			name = shell;
110		args[0] = name;
111		execve(shell, args, environ);
112		_exit(127);
113	default:
114		sigprocmask(SIG_SETMASK, &old, NULL);
115		wait(&st);
116
117		return st;
118	}
119}