scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

posix.c (1881B)


      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 
     16 static volatile pid_t pid;
     17 
     18 void
     19 killchild(void)
     20 {
     21 	if (pid != 0)
     22 		kill(pid, SIGTERM);
     23 	pid = 0;
     24 }
     25 
     26 int
     27 is_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 
     36 void
     37 exportvar(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 
     48 time_t
     49 stamp(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 
     59 int
     60 launch(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 }