ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Proc-FastSpawn/FastSpawn.xs
Revision: 1.1
Committed: Fri Mar 29 22:15:52 2013 UTC (11 years, 2 months ago) by root
Branch: MAIN
CVS Tags: rel-0_1
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <stdio.h>
6
7 #ifdef WIN32
8
9 #include <windows.h>
10
11 #else
12
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16
17 /* openbsd seems to have a buggy vfork (what would you expect), */
18 /* while others might implement vfork as fork in older versions, which is fine */
19 #if __linux || __FreeBSD__ || __NetBSD__ || __sun
20 #define USE_VFORK 1
21 #endif
22
23 #if !USE_VFORK
24 #if _POSIX_SPAWN >= 200809L
25 #define USE_SPAWN 1
26 #include <spawn.h>
27 #else
28 #define vfork() fork()
29 #endif
30 #endif
31
32 #endif
33
34 static char *const *
35 array_to_cvec (SV *sv)
36 {
37 AV *av;
38 int n, i;
39 char **cvec;
40
41 if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
42 croak ("expected a reference to an array of argument/environment strings");
43
44 av = (AV *)SvRV (sv);
45 n = av_len (av) + 1;
46 cvec = (char **)SvPVX (sv_2mortal (NEWSV (0, sizeof (char *) * n + 1)));
47
48 for (i = 0; i < n; ++i)
49 cvec [i] = SvPVbyte_nolen (*av_fetch (av, i, 11));
50
51 cvec [n] = 0;
52
53 return cvec;
54 }
55
56 MODULE = Proc::FastSpawn PACKAGE = Proc::FastSpawn
57
58 PROTOTYPES: ENABLE
59
60 BOOT:
61 #ifndef WIN32
62 cv_undef (get_cv ("Proc::FastSpawn::_quote", 0));
63 #endif
64
65 long
66 spawn (const char *path, SV *argv, SV *envp = &PL_sv_undef)
67 INIT:
68 {
69 #ifdef WIN32
70 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS)
71 {
72 errno = EAGAIN;
73 XSRETURN_UNDEF;
74 }
75
76 argv = sv_2mortal (newSVsv (argv));
77 PUSHMARK (SP);
78 XPUSHs (argv);
79 PUTBACK;
80 call_pv ("Proc::FastSpawn::_quote", G_VOID | G_DISCARD);
81 SPAGAIN;
82 #endif
83 }
84 CODE:
85 {
86 extern char **environ;
87 char *const *cargv = array_to_cvec (argv);
88 char *const *cenvp = SvOK (envp) ? array_to_cvec (envp) : environ;
89 intptr_t pid;
90
91 fflush (0);
92 #ifdef WIN32
93 pid = _spawnve (_P_NOWAIT, path, cargv, cenvp);
94
95 if (pid == -1)
96 XSRETURN_UNDEF;
97
98 /* do it like perl, dadadoop dadadoop */
99 w32_child_handles [w32_num_children] = (HANDLE)pid;
100 pid = GetProcessId ((HANDLE)pid); /* get the real pid */
101 w32_child_pids [w32_num_children] = pid;
102 ++w32_num_children;
103 #elif USE_SPAWN
104 {
105 pid_t xpid;
106
107 errno = posix_spawn (&xpid, path, 0, 0, cargv, cenvp);
108
109 if (errno)
110 XSRETURN_UNDEF;
111
112 pid = xpid;
113 }
114 #else
115 pid = vfork ();
116
117 if (pid < 0)
118 XSRETURN_UNDEF;
119
120 if (pid == 0)
121 {
122 execve (path, cargv, cenvp);
123 _exit (127);
124 }
125 #endif
126
127 RETVAL = pid;
128 }
129 OUTPUT: RETVAL
130
131 void
132 fd_inherit (int fd, int on = 1)
133 CODE:
134 #ifdef WIN32
135 SetHandleInformation ((HANDLE)_get_osfhandle (fd), HANDLE_FLAG_INHERIT, on ? HANDLE_FLAG_INHERIT : 0);
136 #else
137 fcntl (fd, F_SETFD, on ? 0 : FD_CLOEXEC);
138 #endif