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