This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
cygwin path conversions, take 4
[perl5.git] / cygwin / cygwin.c
CommitLineData
5db16f6a
FE
1/*
2 * Cygwin extras
3 */
4
5#include "EXTERN.h"
6#include "perl.h"
7#undef USE_DYNAMIC_LOADING
8#include "XSUB.h"
9
6b49d266 10#include <unistd.h>
b4bcd662 11#include <process.h>
49fd6edc 12#include <sys/cygwin.h>
6d7e4387 13#include <alloca.h>
9fb265f7 14#include <dlfcn.h>
5db16f6a 15
b4bcd662
GS
16/*
17 * pp_system() implemented via spawn()
18 * - more efficient and useful when embedding Perl in non-Cygwin apps
19 * - code mostly borrowed from djgpp.c
20 */
21static int
22do_spawnvp (const char *path, const char * const *argv)
23{
acfe0abc 24 dTHX;
b4bcd662
GS
25 Sigsave_t ihand,qhand;
26 int childpid, result, status;
27
ec1aec95
YST
28 rsignal_save(SIGINT, (Sighandler_t) SIG_IGN, &ihand);
29 rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qhand);
b4bcd662
GS
30 childpid = spawnvp(_P_NOWAIT,path,argv);
31 if (childpid < 0) {
32 status = -1;
411caa50 33 if(ckWARN(WARN_EXEC))
f98bc0c6 34 Perl_warner(aTHX_ packWARN(WARN_EXEC),"Can't spawn \"%s\": %s",
b4bcd662 35 path,Strerror (errno));
b4bcd662
GS
36 } else {
37 do {
38 result = wait4pid(childpid, &status, 0);
39 } while (result == -1 && errno == EINTR);
40 if(result < 0)
41 status = -1;
42 }
43 (void)rsignal_restore(SIGINT, &ihand);
44 (void)rsignal_restore(SIGQUIT, &qhand);
45 return status;
46}
47
48int
49do_aspawn (SV *really, void **mark, void **sp)
50{
acfe0abc 51 dTHX;
b4bcd662
GS
52 int rc;
53 char **a,*tmps,**argv;
54 STRLEN n_a;
55
56 if (sp<=mark)
57 return -1;
58 a=argv=(char**) alloca ((sp-mark+3)*sizeof (char*));
59
60 while (++mark <= sp)
61 if (*mark)
667e2948 62 *a++ = SvPVx((SV *)*mark, n_a);
b4bcd662
GS
63 else
64 *a++ = "";
65 *a = Nullch;
66
67 if (argv[0][0] != '/' && argv[0][0] != '\\'
68 && !(argv[0][0] && argv[0][1] == ':'
69 && (argv[0][2] == '/' || argv[0][2] != '\\'))
70 ) /* will swawnvp use PATH? */
71 TAINT_ENV(); /* testing IFS here is overkill, probably */
72
73 if (really && *(tmps = SvPV(really, n_a)))
74 rc=do_spawnvp (tmps,(const char * const *)argv);
75 else
76 rc=do_spawnvp (argv[0],(const char *const *)argv);
77
78 return rc;
79}
80
81int
82do_spawn (char *cmd)
83{
acfe0abc 84 dTHX;
b4bcd662
GS
85 char **a,*s,*metachars = "$&*(){}[]'\";\\?>|<~`\n";
86 const char *command[4];
87
88 while (*cmd && isSPACE(*cmd))
89 cmd++;
90
91 if (strnEQ (cmd,"/bin/sh",7) && isSPACE (cmd[7]))
92 cmd+=5;
93
94 /* save an extra exec if possible */
95 /* see if there are shell metacharacters in it */
96 if (strstr (cmd,"..."))
97 goto doshell;
98 if (*cmd=='.' && isSPACE (cmd[1]))
99 goto doshell;
100 if (strnEQ (cmd,"exec",4) && isSPACE (cmd[4]))
101 goto doshell;
102 for (s=cmd; *s && isALPHA (*s); s++) ; /* catch VAR=val gizmo */
103 if (*s=='=')
104 goto doshell;
105
106 for (s=cmd; *s; s++)
107 if (strchr (metachars,*s))
108 {
109 if (*s=='\n' && s[1]=='\0')
110 {
111 *s='\0';
112 break;
113 }
114 doshell:
115 command[0] = "sh";
116 command[1] = "-c";
117 command[2] = cmd;
118 command[3] = NULL;
119
120 return do_spawnvp("sh",command);
121 }
122
a02a5408 123 Newx (PL_Argv,(s-cmd)/2+2,char*);
b4bcd662
GS
124 PL_Cmd=savepvn (cmd,s-cmd);
125 a=PL_Argv;
126 for (s=PL_Cmd; *s;) {
127 while (*s && isSPACE (*s)) s++;
128 if (*s)
129 *(a++)=s;
130 while (*s && !isSPACE (*s)) s++;
131 if (*s)
132 *s++='\0';
133 }
134 *a=Nullch;
135 if (!PL_Argv[0])
136 return -1;
137
138 return do_spawnvp(PL_Argv[0],(const char * const *)PL_Argv);
139}
5db16f6a
FE
140
141/* see also Cwd.pm */
5db16f6a
FE
142XS(Cygwin_cwd)
143{
144 dXSARGS;
145 char *cwd;
146
147 if(items != 0)
148 Perl_croak(aTHX_ "Usage: Cwd::cwd()");
47dafe4d 149 if((cwd = getcwd(NULL, -1))) {
5db16f6a 150 ST(0) = sv_2mortal(newSVpv(cwd, 0));
a236cecb 151 free(cwd);
6be3b590
JH
152#ifndef INCOMPLETE_TAINTS
153 SvTAINTED_on(ST(0));
154#endif
5db16f6a
FE
155 XSRETURN(1);
156 }
157 XSRETURN_UNDEF;
158}
159
49fd6edc
YST
160XS(XS_Cygwin_pid_to_winpid)
161{
162 dXSARGS;
d2dc0126
YST
163 dXSTARG;
164 pid_t pid, RETVAL;
165
49fd6edc
YST
166 if (items != 1)
167 Perl_croak(aTHX_ "Usage: Cygwin::pid_to_winpid(pid)");
d2dc0126
YST
168
169 pid = (pid_t)SvIV(ST(0));
170
49fd6edc
YST
171 if ((RETVAL = cygwin_internal(CW_CYGWIN_PID_TO_WINPID, pid)) > 0) {
172 XSprePUSH; PUSHi((IV)RETVAL);
173 XSRETURN(1);
174 }
175 XSRETURN_UNDEF;
176}
177
49fd6edc
YST
178XS(XS_Cygwin_winpid_to_pid)
179{
180 dXSARGS;
d2dc0126
YST
181 dXSTARG;
182 pid_t pid, RETVAL;
183
49fd6edc
YST
184 if (items != 1)
185 Perl_croak(aTHX_ "Usage: Cygwin::winpid_to_pid(pid)");
d2dc0126
YST
186
187 pid = (pid_t)SvIV(ST(0));
188
49fd6edc
YST
189 if ((RETVAL = cygwin32_winpid_to_pid(pid)) > 0) {
190 XSprePUSH; PUSHi((IV)RETVAL);
191 XSRETURN(1);
192 }
193 XSRETURN_UNDEF;
194}
195
15414d2b
RU
196XS(XS_Cygwin_win_to_posix_path)
197{
198 dXSARGS;
199 int absolute_flag = 0;
200 STRLEN len;
201 int err;
202 char *pathname, *buf;
203
204 if (items < 1 || items > 2)
205 Perl_croak(aTHX_ "Usage: Cygwin::win_to_posix_path(pathname, [absolute])");
206
207 pathname = SvPV(ST(0), len);
208 if (items == 2)
209 absolute_flag = SvTRUE(ST(1));
210
211 if (!len)
212 Perl_croak(aTHX_ "can't convert empty path");
213 buf = (char *) safemalloc (len + 260 + 1001);
214
215 if (absolute_flag)
216 err = cygwin_conv_to_full_posix_path(pathname, buf);
217 else
218 err = cygwin_conv_to_posix_path(pathname, buf);
219 if (!err) {
220 ST(0) = sv_2mortal(newSVpv(buf, 0));
221 safefree(buf);
222 XSRETURN(1);
223 } else {
224 safefree(buf);
225 XSRETURN_UNDEF;
226 }
227}
228
229XS(XS_Cygwin_posix_to_win_path)
230{
231 dXSARGS;
232 int absolute_flag = 0;
233 STRLEN len;
234 int err;
235 char *pathname, *buf;
236
237 if (items < 1 || items > 2)
238 Perl_croak(aTHX_ "Usage: Cygwin::posix_to_win_path(pathname, [absolute])");
239
240 pathname = SvPV(ST(0), len);
241 if (items == 2)
242 absolute_flag = SvTRUE(ST(1));
243
244 if (!len)
245 Perl_croak(aTHX_ "can't convert empty path");
246 buf = (char *) safemalloc(len + 260 + 1001);
247
248 if (absolute_flag)
249 err = cygwin_conv_to_full_win32_path(pathname, buf);
250 else
251 err = cygwin_conv_to_win32_path(pathname, buf);
252 if (!err) {
253 ST(0) = sv_2mortal(newSVpv(buf, 0));
254 safefree(buf);
255 XSRETURN(1);
256 } else {
257 safefree(buf);
258 XSRETURN_UNDEF;
259 }
260}
261
262XS(XS_Cygwin_is_binmount)
263{
264 dXSARGS;
265 char *pathname;
266
267 if (items != 1)
268 Perl_croak(aTHX_ "Usage: Cygwin::is_binmount(pathname)");
269
270 pathname = SvPV_nolen(ST(0));
271
272 ST(0) = boolSV(cygwin_internal(CW_GET_BINMODE, pathname));
273 XSRETURN(1);
274}
275
276XS(XS_Cygwin_is_textmount)
277{
278 dXSARGS;
279 char *pathname;
280
281 if (items != 1)
282 Perl_croak(aTHX_ "Usage: Cygwin::is_textmount(pathname)");
283
284 pathname = SvPV_nolen(ST(0));
285
286 ST(0) = boolSV(!cygwin_internal(CW_GET_BINMODE, pathname));
287 XSRETURN(1);
288}
49fd6edc 289
5db16f6a
FE
290void
291init_os_extras(void)
292{
5db16f6a 293 dTHX;
9fb265f7
JD
294 char *file = __FILE__;
295 void *handle;
5db16f6a
FE
296
297 newXS("Cwd::cwd", Cygwin_cwd, file);
15414d2b
RU
298 newXSproto("Cygwin::winpid_to_pid", XS_Cygwin_winpid_to_pid, file, "$");
299 newXSproto("Cygwin::pid_to_winpid", XS_Cygwin_pid_to_winpid, file, "$");
300 newXSproto("Cygwin::win_to_posix_path", XS_Cygwin_win_to_posix_path, file, "$;$");
301 newXSproto("Cygwin::posix_to_win_path", XS_Cygwin_posix_to_win_path, file, "$;$");
302 newXSproto("Cygwin::is_binmount", XS_Cygwin_is_binmount, file, "$");
303 newXSproto("Cygwin::is_textmount", XS_Cygwin_is_textmount, file, "$");
78ff2d7b 304
9fb265f7
JD
305 /* Initialize Win32CORE if it has been statically linked. */
306 handle = dlopen(NULL, RTLD_LAZY);
307 if (handle) {
308 void (*pfn_init)(pTHX);
309 pfn_init = (void (*)(pTHX))dlsym(handle, "init_Win32CORE");
310 if (pfn_init)
311 pfn_init(aTHX);
312 dlclose(handle);
78ff2d7b 313 }
5db16f6a 314}