|
62 | 62 | # include <sys/syscall.h> |
63 | 63 | #endif |
64 | 64 |
|
| 65 | +/* XXX This should be removed obviously */ |
| 66 | +#define HAS_POSIX_SPAWN |
| 67 | + |
| 68 | +#ifdef HAS_POSIX_SPAWN |
| 69 | +#include <spawn.h> |
| 70 | +#endif |
| 71 | + |
65 | 72 | /* XXX Configure test needed. |
66 | 73 | h_errno might not be a simple 'int', especially for multi-threaded |
67 | 74 | applications, see "extern int errno in perl.h". Creating such |
@@ -4654,6 +4661,68 @@ PP_wrapped(pp_system, 0, 1) |
4654 | 4661 | sigset_t newset, oldset; |
4655 | 4662 | #endif |
4656 | 4663 |
|
| 4664 | +#ifdef HAS_POSIX_SPAWN |
| 4665 | + SV** mark = ORIGMARK; |
| 4666 | + |
| 4667 | + posix_spawnattr_t attrp; |
| 4668 | + posix_spawnattr_init(&attrp); |
| 4669 | + |
| 4670 | + sigemptyset(&newset); |
| 4671 | + sigaddset(&newset, SIGCHLD); |
| 4672 | + sigprocmask(SIG_BLOCK, &newset, &oldset); |
| 4673 | + posix_spawnattr_getsigmask(&attrp, &oldset); |
| 4674 | + |
| 4675 | + int success; |
| 4676 | + if (sp - mark > 1) { |
| 4677 | + const char **argv, **a; |
| 4678 | + Newx(argv, sp - mark + 1, const char*); |
| 4679 | + SAVEFREEPV(argv); |
| 4680 | + a = argv; |
| 4681 | + |
| 4682 | + while (++mark <= sp) { |
| 4683 | + if (*mark) { |
| 4684 | + char *arg = savepv(SvPV_nolen_const(*mark)); |
| 4685 | + SAVEFREEPV(arg); |
| 4686 | + *a++ = arg; |
| 4687 | + } else |
| 4688 | + *a++ = ""; |
| 4689 | + } |
| 4690 | + *a = NULL; |
| 4691 | + |
| 4692 | + success = posix_spawnp(&childpid, argv[0], NULL, &attrp, (char * const *)argv, environ); |
| 4693 | + } |
| 4694 | + else if(sp - mark == 1) { |
| 4695 | + const char* argv[] = { "/bin/sh", "-c", SvPV_nolen(*sp), NULL }; |
| 4696 | + success = posix_spawnp(&childpid, argv[0], NULL, &attrp, (char * const *)argv, environ); |
| 4697 | + } |
| 4698 | + else { |
| 4699 | + success = ENOEXEC; |
| 4700 | + } |
| 4701 | + SP = ORIGMARK; |
| 4702 | + if (success != 0) { |
| 4703 | + errno = success; |
| 4704 | + STATUS_NATIVE_CHILD_SET(255 << 8); |
| 4705 | + XPUSHi(255 << 8); |
| 4706 | + RETURN; |
| 4707 | + } |
| 4708 | + |
| 4709 | + Sigsave_t ihand,qhand; /* place to save signals during system() */ |
| 4710 | + rsignal_save(SIGINT, (Sighandler_t) SIG_IGN, &ihand); |
| 4711 | + rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qhand); |
| 4712 | + |
| 4713 | + int status; |
| 4714 | + do { |
| 4715 | + result = wait4pid(childpid, &status, 0); |
| 4716 | + } while (result == -1 && errno == EINTR); |
| 4717 | + |
| 4718 | + sigprocmask(SIG_SETMASK, &oldset, NULL); |
| 4719 | + (void)rsignal_restore(SIGINT, &ihand); |
| 4720 | + (void)rsignal_restore(SIGQUIT, &qhand); |
| 4721 | + |
| 4722 | + if (result) |
| 4723 | + STATUS_NATIVE_CHILD_SET(status); |
| 4724 | + XPUSHi(STATUS_CURRENT); |
| 4725 | +#else |
4657 | 4726 | if (PerlProc_pipe_cloexec(pp) >= 0) |
4658 | 4727 | did_pipes = 1; |
4659 | 4728 | #ifdef __amigaos4__ |
@@ -4760,6 +4829,7 @@ PP_wrapped(pp_system, 0, 1) |
4760 | 4829 | } |
4761 | 4830 | #endif /* __amigaos4__ */ |
4762 | 4831 | PerlProc__exit(-1); |
| 4832 | +#endif /* HAS_POSIX_SPAWN */ |
4763 | 4833 | } |
4764 | 4834 | #else /* ! FORK or VMS or OS/2 */ |
4765 | 4835 | PL_statusvalue = 0; |
|
0 commit comments