ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Proc-FastSpawn/FastSpawn.xs
Revision: 1.7
Committed: Mon Jun 10 03:02:33 2013 UTC (10 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-1_2, HEAD
Changes since 1.6: +3 -3 lines
Log Message:
1.2

File Contents

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