posix_spawn.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include <spawn.h>
  2. #include <unistd.h>
  3. #include <signal.h>
  4. #include <stdint.h>
  5. #include <fcntl.h>
  6. #include "syscall.h"
  7. #include "pthread_impl.h"
  8. #include "fdop.h"
  9. #include "libc.h"
  10. extern char **environ;
  11. static void dummy_0()
  12. {
  13. }
  14. weak_alias(dummy_0, __acquire_ptc);
  15. weak_alias(dummy_0, __release_ptc);
  16. pid_t __vfork(void);
  17. int __posix_spawnx(pid_t *restrict res, const char *restrict path,
  18. int (*exec)(const char *, char *const *, char *const *),
  19. const posix_spawn_file_actions_t *fa,
  20. const posix_spawnattr_t *restrict attr,
  21. char *const argv[restrict], char *const envp[restrict])
  22. {
  23. pid_t pid;
  24. sigset_t oldmask;
  25. int i;
  26. posix_spawnattr_t dummy_attr = { 0 };
  27. if (!attr) attr = &dummy_attr;
  28. sigprocmask(SIG_BLOCK, SIGALL_SET, &oldmask);
  29. __acquire_ptc();
  30. pid = __vfork();
  31. if (pid) {
  32. __release_ptc();
  33. sigprocmask(SIG_SETMASK, &oldmask, 0);
  34. if (pid < 0) return -pid;
  35. *res = pid;
  36. return 0;
  37. }
  38. for (i=1; i<=8*__SYSCALL_SSLEN; i++) {
  39. struct sigaction sa;
  40. __libc_sigaction(i, 0, &sa);
  41. if (sa.sa_handler!=SIG_DFL && (sa.sa_handler!=SIG_IGN ||
  42. ((attr->__flags & POSIX_SPAWN_SETSIGDEF)
  43. && sigismember(&attr->__def, i) ))) {
  44. sa.sa_handler = SIG_DFL;
  45. __libc_sigaction(i, &sa, 0);
  46. }
  47. }
  48. if ((attr->__flags&POSIX_SPAWN_SETPGROUP) && setpgid(0, attr->__pgrp))
  49. _exit(127);
  50. /* Use syscalls directly because pthread state is not consistent
  51. * for making calls to the library wrappers... */
  52. if ((attr->__flags&POSIX_SPAWN_RESETIDS) && (
  53. __syscall(SYS_setgid, __syscall(SYS_getgid)) ||
  54. __syscall(SYS_setuid, __syscall(SYS_getuid)) ))
  55. _exit(127);
  56. if (fa && fa->__actions) {
  57. struct fdop *op;
  58. int ret, fd;
  59. for (op = fa->__actions; op->next; op = op->next);
  60. for (; op; op = op->prev) {
  61. switch(op->cmd) {
  62. case FDOP_CLOSE:
  63. ret = __syscall(SYS_close, op->fd);
  64. break;
  65. case FDOP_DUP2:
  66. ret = __syscall(SYS_dup2, op->fd, op->newfd)<0;
  67. break;
  68. case FDOP_OPEN:
  69. fd = __syscall(SYS_open, op->path,
  70. op->oflag | O_LARGEFILE, op->mode);
  71. if (fd == op->fd) {
  72. ret = 0;
  73. } else {
  74. ret = __syscall(SYS_dup2, fd, op->fd)<0;
  75. __syscall(SYS_close, fd);
  76. }
  77. break;
  78. }
  79. if (ret) _exit(127);
  80. }
  81. }
  82. sigprocmask(SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK)
  83. ? &attr->__mask : &oldmask, 0);
  84. exec(path, argv, envp ? envp : environ);
  85. _exit(127);
  86. return 0;
  87. }
  88. int posix_spawn(pid_t *restrict res, const char *restrict path,
  89. const posix_spawn_file_actions_t *fa,
  90. const posix_spawnattr_t *restrict attr,
  91. char *const argv[restrict], char *const envp[restrict])
  92. {
  93. return __posix_spawnx(res, path, execve, fa, attr, argv, envp);
  94. }