|
58 | 58 | # endif |
59 | 59 | #endif |
60 | 60 |
|
| 61 | +/* XXX This should be removed obviously */ |
| 62 | +#define HAS_POSIX_SPAWN |
| 63 | + |
| 64 | +#ifdef HAS_POSIX_SPAWN |
| 65 | +#include <spawn.h> |
| 66 | +#endif |
| 67 | + |
61 | 68 | /* XXX Configure test needed. |
62 | 69 | h_errno might not be a simple 'int', especially for multi-threaded |
63 | 70 | applications, see "extern int errno in perl.h". Creating such |
@@ -4406,6 +4413,67 @@ PP(pp_system) |
4406 | 4413 | sigset_t newset, oldset; |
4407 | 4414 | #endif |
4408 | 4415 |
|
| 4416 | +#ifdef HAS_POSIX_SPAWN |
| 4417 | + SV** mark = ORIGMARK; |
| 4418 | + |
| 4419 | + posix_spawnattr_t attrp; |
| 4420 | + posix_spawnattr_init(&attrp); |
| 4421 | + |
| 4422 | + sigemptyset(&newset); |
| 4423 | + sigaddset(&newset, SIGCHLD); |
| 4424 | + sigprocmask(SIG_BLOCK, &newset, &oldset); |
| 4425 | + posix_spawnattr_getsigmask(&attrp, &oldset); |
| 4426 | + |
| 4427 | + int success; |
| 4428 | + if (sp - mark > 1) { |
| 4429 | + const char **argv, **a; |
| 4430 | + Newx(argv, sp - mark + 1, const char*); |
| 4431 | + SAVEFREEPV(argv); |
| 4432 | + a = argv; |
| 4433 | + |
| 4434 | + while (++mark <= sp) { |
| 4435 | + if (*mark) { |
| 4436 | + char *arg = savepv(SvPV_nolen_const(*mark)); |
| 4437 | + SAVEFREEPV(arg); |
| 4438 | + *a++ = arg; |
| 4439 | + } else |
| 4440 | + *a++ = ""; |
| 4441 | + } |
| 4442 | + *a = NULL; |
| 4443 | + |
| 4444 | + success = posix_spawnp(&childpid, argv[0], NULL, &attrp, (char * const *)argv, environ); |
| 4445 | + } |
| 4446 | + else if(sp - mark == 1) { |
| 4447 | + const char* argv[] = { "/bin/sh", "-c", SvPV_nolen(*sp), NULL }; |
| 4448 | + success = posix_spawnp(&childpid, argv[0], NULL, &attrp, (char * const *)argv, environ); |
| 4449 | + } |
| 4450 | + else { |
| 4451 | + success = ENOEXEC; |
| 4452 | + } |
| 4453 | + SP = ORIGMARK; |
| 4454 | + if (success != 0) { |
| 4455 | + STATUS_NATIVE_CHILD_SET(255 << 8); |
| 4456 | + XPUSHi(255 << 8); |
| 4457 | + RETURN; |
| 4458 | + } |
| 4459 | + |
| 4460 | + Sigsave_t ihand,qhand; /* place to save signals during system() */ |
| 4461 | + rsignal_save(SIGINT, (Sighandler_t) SIG_IGN, &ihand); |
| 4462 | + rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qhand); |
| 4463 | + |
| 4464 | + int status; |
| 4465 | + do { |
| 4466 | + result = wait4pid(childpid, &status, 0); |
| 4467 | + } while (result == -1 && errno == EINTR); |
| 4468 | + |
| 4469 | + sigprocmask(SIG_SETMASK, &oldset, NULL); |
| 4470 | + (void)rsignal_restore(SIGINT, &ihand); |
| 4471 | + (void)rsignal_restore(SIGQUIT, &qhand); |
| 4472 | + |
| 4473 | + if (result) |
| 4474 | + STATUS_NATIVE_CHILD_SET(status); |
| 4475 | + XPUSHi(STATUS_CURRENT); |
| 4476 | +#else |
4409 | 4477 | if (PerlProc_pipe_cloexec(pp) >= 0) |
4410 | 4478 | did_pipes = 1; |
4411 | 4479 | #ifdef __amigaos4__ |
@@ -4516,6 +4584,7 @@ PP(pp_system) |
4516 | 4584 | } |
4517 | 4585 | #endif /* __amigaos4__ */ |
4518 | 4586 | PerlProc__exit(-1); |
| 4587 | +#endif /* HAS_POSIX_SPAWN */ |
4519 | 4588 | } |
4520 | 4589 | #else /* ! FORK or VMS or OS/2 */ |
4521 | 4590 | PL_statusvalue = 0; |
|
0 commit comments