1
0

system.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. #include <unistd.h>
  2. #include <stdlib.h>
  3. #include <signal.h>
  4. #include <sys/wait.h>
  5. #include <spawn.h>
  6. #include <errno.h>
  7. #include "pthread_impl.h"
  8. extern char **__environ;
  9. int system(const char *cmd)
  10. {
  11. pid_t pid;
  12. sigset_t old, reset;
  13. struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit;
  14. int status = -1, ret;
  15. posix_spawnattr_t attr;
  16. pthread_testcancel();
  17. if (!cmd) return 1;
  18. sigaction(SIGINT, &sa, &oldint);
  19. sigaction(SIGQUIT, &sa, &oldquit);
  20. sigaddset(&sa.sa_mask, SIGCHLD);
  21. sigprocmask(SIG_BLOCK, &sa.sa_mask, &old);
  22. sigemptyset(&reset);
  23. if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT);
  24. if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT);
  25. posix_spawnattr_init(&attr);
  26. posix_spawnattr_setsigmask(&attr, &old);
  27. posix_spawnattr_setsigdefault(&attr, &reset);
  28. posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK);
  29. ret = posix_spawn(&pid, "/bin/sh", 0, &attr,
  30. (char *[]){"sh", "-c", (char *)cmd, 0}, __environ);
  31. posix_spawnattr_destroy(&attr);
  32. if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR);
  33. sigaction(SIGINT, &oldint, NULL);
  34. sigaction(SIGQUIT, &oldquit, NULL);
  35. sigprocmask(SIG_SETMASK, &old, NULL);
  36. if (ret) errno = ret;
  37. return status;
  38. }