Skip to content

Commit 186c522

Browse files
committed
Add posix_spawn support
1 parent ab79bb2 commit 186c522

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

pp_sys.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@
6262
# include <sys/syscall.h>
6363
#endif
6464

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+
6572
/* XXX Configure test needed.
6673
h_errno might not be a simple 'int', especially for multi-threaded
6774
applications, see "extern int errno in perl.h". Creating such
@@ -4654,6 +4661,68 @@ PP_wrapped(pp_system, 0, 1)
46544661
sigset_t newset, oldset;
46554662
#endif
46564663

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
46574726
if (PerlProc_pipe_cloexec(pp) >= 0)
46584727
did_pipes = 1;
46594728
#ifdef __amigaos4__
@@ -4760,6 +4829,7 @@ PP_wrapped(pp_system, 0, 1)
47604829
}
47614830
#endif /* __amigaos4__ */
47624831
PerlProc__exit(-1);
4832+
#endif /* HAS_POSIX_SPAWN */
47634833
}
47644834
#else /* ! FORK or VMS or OS/2 */
47654835
PL_statusvalue = 0;

0 commit comments

Comments
 (0)