Commit | Line | Data |
---|---|---|
5db16f6a EF |
1 | /* |
2 | * Cygwin extras | |
3 | */ | |
4 | ||
6cc44f62 | 5 | #define PERLIO_NOT_STDIO 0 |
5db16f6a EF |
6 | #include "EXTERN.h" |
7 | #include "perl.h" | |
8 | #undef USE_DYNAMIC_LOADING | |
9 | #include "XSUB.h" | |
10 | ||
6b49d266 | 11 | #include <unistd.h> |
b4bcd662 | 12 | #include <process.h> |
49fd6edc | 13 | #include <sys/cygwin.h> |
803e389c | 14 | #include <cygwin/version.h> |
a25ce5f3 | 15 | #include <mntent.h> |
6d7e4387 | 16 | #include <alloca.h> |
9fb265f7 | 17 | #include <dlfcn.h> |
803e389c RU |
18 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
19 | #include <wchar.h> | |
20 | #endif | |
5db16f6a | 21 | |
2e75d796 KW |
22 | #define PATH_LEN_GUESS (260 + 1001) |
23 | ||
b4bcd662 GS |
24 | /* |
25 | * pp_system() implemented via spawn() | |
26 | * - more efficient and useful when embedding Perl in non-Cygwin apps | |
27 | * - code mostly borrowed from djgpp.c | |
28 | */ | |
29 | static int | |
30 | do_spawnvp (const char *path, const char * const *argv) | |
31 | { | |
acfe0abc | 32 | dTHX; |
b4bcd662 GS |
33 | Sigsave_t ihand,qhand; |
34 | int childpid, result, status; | |
35 | ||
ec1aec95 YST |
36 | rsignal_save(SIGINT, (Sighandler_t) SIG_IGN, &ihand); |
37 | rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qhand); | |
b4bcd662 GS |
38 | childpid = spawnvp(_P_NOWAIT,path,argv); |
39 | if (childpid < 0) { | |
1604cfb0 MS |
40 | status = -1; |
41 | if(ckWARN(WARN_EXEC)) | |
42 | Perl_warner(aTHX_ packWARN(WARN_EXEC),"Can't spawn \"%s\": %s", | |
43 | path,Strerror (errno)); | |
b4bcd662 | 44 | } else { |
1604cfb0 MS |
45 | do { |
46 | result = wait4pid(childpid, &status, 0); | |
47 | } while (result == -1 && errno == EINTR); | |
48 | if(result < 0) | |
49 | status = -1; | |
b4bcd662 GS |
50 | } |
51 | (void)rsignal_restore(SIGINT, &ihand); | |
52 | (void)rsignal_restore(SIGQUIT, &qhand); | |
53 | return status; | |
54 | } | |
55 | ||
56 | int | |
57 | do_aspawn (SV *really, void **mark, void **sp) | |
58 | { | |
acfe0abc | 59 | dTHX; |
b4bcd662 | 60 | int rc; |
a4ec4e68 JH |
61 | char const **a; |
62 | char *tmps,**argv; | |
63 | STRLEN n_a; | |
b4bcd662 GS |
64 | |
65 | if (sp<=mark) | |
66 | return -1; | |
a4ec4e68 JH |
67 | argv=(char**) alloca ((sp-mark+3)*sizeof (char*)); |
68 | a=(char const **)argv; | |
b4bcd662 GS |
69 | |
70 | while (++mark <= sp) | |
71 | if (*mark) | |
667e2948 | 72 | *a++ = SvPVx((SV *)*mark, n_a); |
b4bcd662 GS |
73 | else |
74 | *a++ = ""; | |
dfe169ee | 75 | *a = (char*)NULL; |
b4bcd662 GS |
76 | |
77 | if (argv[0][0] != '/' && argv[0][0] != '\\' | |
78 | && !(argv[0][0] && argv[0][1] == ':' | |
79 | && (argv[0][2] == '/' || argv[0][2] != '\\')) | |
80 | ) /* will swawnvp use PATH? */ | |
81 | TAINT_ENV(); /* testing IFS here is overkill, probably */ | |
82 | ||
83 | if (really && *(tmps = SvPV(really, n_a))) | |
84 | rc=do_spawnvp (tmps,(const char * const *)argv); | |
85 | else | |
86 | rc=do_spawnvp (argv[0],(const char *const *)argv); | |
87 | ||
88 | return rc; | |
89 | } | |
90 | ||
91 | int | |
92 | do_spawn (char *cmd) | |
93 | { | |
acfe0abc | 94 | dTHX; |
282fc0b3 | 95 | char const **argv, **a; |
a4ec4e68 JH |
96 | char *s; |
97 | char const *metachars = "$&*(){}[]'\";\\?>|<~`\n"; | |
b4bcd662 | 98 | const char *command[4]; |
282fc0b3 | 99 | int result; |
b4bcd662 | 100 | |
282fc0b3 | 101 | ENTER; |
b4bcd662 | 102 | while (*cmd && isSPACE(*cmd)) |
1604cfb0 | 103 | cmd++; |
b4bcd662 | 104 | |
f55ac4a4 | 105 | if (strBEGINs (cmd,"/bin/sh") && isSPACE (cmd[7])) |
b4bcd662 GS |
106 | cmd+=5; |
107 | ||
108 | /* save an extra exec if possible */ | |
109 | /* see if there are shell metacharacters in it */ | |
110 | if (strstr (cmd,"...")) | |
1604cfb0 | 111 | goto doshell; |
b4bcd662 | 112 | if (*cmd=='.' && isSPACE (cmd[1])) |
1604cfb0 | 113 | goto doshell; |
f55ac4a4 | 114 | if (strBEGINs (cmd,"exec") && isSPACE (cmd[4])) |
1604cfb0 | 115 | goto doshell; |
b4bcd662 | 116 | for (s=cmd; *s && isALPHA (*s); s++) ; /* catch VAR=val gizmo */ |
4e650215 KW |
117 | if (*s=='=') |
118 | goto doshell; | |
b4bcd662 GS |
119 | |
120 | for (s=cmd; *s; s++) | |
1604cfb0 MS |
121 | if (strchr (metachars,*s)) |
122 | { | |
123 | if (*s=='\n' && s[1]=='\0') | |
124 | { | |
125 | *s='\0'; | |
126 | break; | |
127 | } | |
128 | doshell: | |
129 | command[0] = "sh"; | |
130 | command[1] = "-c"; | |
131 | command[2] = cmd; | |
132 | command[3] = NULL; | |
133 | ||
134 | result = do_spawnvp("sh",command); | |
135 | goto leave; | |
136 | } | |
b4bcd662 | 137 | |
282fc0b3 Z |
138 | Newx (argv, (s-cmd)/2+2, const char*); |
139 | SAVEFREEPV(argv); | |
140 | cmd=savepvn (cmd,s-cmd); | |
141 | SAVEFREEPV(cmd); | |
142 | a=argv; | |
143 | for (s=cmd; *s;) { | |
1604cfb0 MS |
144 | while (*s && isSPACE (*s)) s++; |
145 | if (*s) | |
146 | *(a++)=s; | |
147 | while (*s && !isSPACE (*s)) s++; | |
148 | if (*s) | |
149 | *s++='\0'; | |
b4bcd662 | 150 | } |
dfe169ee | 151 | *a = (char*)NULL; |
282fc0b3 Z |
152 | if (!argv[0]) |
153 | result = -1; | |
154 | else | |
1604cfb0 | 155 | result = do_spawnvp(argv[0],(const char * const *)argv); |
282fc0b3 Z |
156 | leave: |
157 | LEAVE; | |
158 | return result; | |
b4bcd662 | 159 | } |
5db16f6a | 160 | |
803e389c RU |
161 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
162 | char* | |
c3be9bd4 | 163 | wide_to_utf8(const wchar_t *wsrc) |
803e389c | 164 | { |
5ee7770b | 165 | dTHX; |
c3be9bd4 | 166 | const Size_t wlen = (wcslen(wsrc) + 1) * sizeof(wchar_t); |
a0b53297 | 167 | |
a435da2b KW |
168 | /* Max expansion factor is 3/2 */ |
169 | Size_t blen = wlen * 3 / 2; | |
803e389c | 170 | |
a435da2b | 171 | char *buf = (char *) safemalloc(blen); |
803e389c | 172 | |
c3be9bd4 | 173 | utf16_to_utf8((U8 *) wsrc, buf, wlen, &blen); |
a0b53297 | 174 | |
803e389c RU |
175 | return buf; |
176 | } | |
177 | ||
178 | wchar_t* | |
a8a9fd0a | 179 | utf8_to_wide_extra_len(const char *buf, Size_t *extra_len) |
803e389c | 180 | { |
493e6288 | 181 | /* Return the conversion to UTF-16 of the UTF-8 string 'buf' |
a8a9fd0a KW |
182 | * (terminated by a NUL), making sure to have space for at least *extra_len |
183 | * extra (wide) characters in the result. The result must be freed by the | |
184 | * caller when no longer needed */ | |
185 | ||
5ee7770b | 186 | dTHX; |
a8a9fd0a | 187 | Size_t len = strlen(buf) + extra_len + 1; |
a0b53297 | 188 | |
5e4b76a1 KW |
189 | /* Max expansion factor is sizeof(wchar_t) */ |
190 | Size_t wlen = sizeof(wchar_t) * len; | |
a0b53297 | 191 | |
5e4b76a1 | 192 | wchar_t* wsrc = (wchar_t *) safemalloc(wlen); |
803e389c | 193 | |
5e4b76a1 | 194 | utf8_to_utf16(buf, (U8 *) wsrc, len, &wlen); |
803e389c | 195 | |
5e4b76a1 KW |
196 | return wsrc; |
197 | } | |
a0b53297 | 198 | |
a8a9fd0a KW |
199 | wchar_t* |
200 | utf8_to_wide(const char *buf) | |
201 | { | |
202 | Size_t extra_len = 0; | |
a0b53297 | 203 | |
a8a9fd0a | 204 | return utf8_to_wide_extra_len(buf, &extra_len); |
803e389c | 205 | } |
a8a9fd0a | 206 | |
803e389c RU |
207 | #endif /* cygwin 1.7 */ |
208 | ||
5db16f6a | 209 | /* see also Cwd.pm */ |
5db16f6a EF |
210 | XS(Cygwin_cwd) |
211 | { | |
212 | dXSARGS; | |
213 | char *cwd; | |
214 | ||
8034715d | 215 | /* See https://github.com/Perl/perl5/issues/8345 |
482150a7 JH |
216 | There is Cwd->cwd() usage in the wild, and previous versions didn't die. |
217 | */ | |
218 | if(items > 1) | |
1604cfb0 | 219 | Perl_croak(aTHX_ "Usage: Cwd::cwd()"); |
47dafe4d | 220 | if((cwd = getcwd(NULL, -1))) { |
1604cfb0 MS |
221 | ST(0) = sv_2mortal(newSVpv(cwd, 0)); |
222 | free(cwd); | |
223 | SvTAINTED_on(ST(0)); | |
224 | XSRETURN(1); | |
5db16f6a EF |
225 | } |
226 | XSRETURN_UNDEF; | |
227 | } | |
228 | ||
49fd6edc YST |
229 | XS(XS_Cygwin_pid_to_winpid) |
230 | { | |
231 | dXSARGS; | |
d2dc0126 YST |
232 | dXSTARG; |
233 | pid_t pid, RETVAL; | |
234 | ||
49fd6edc YST |
235 | if (items != 1) |
236 | Perl_croak(aTHX_ "Usage: Cygwin::pid_to_winpid(pid)"); | |
d2dc0126 YST |
237 | |
238 | pid = (pid_t)SvIV(ST(0)); | |
239 | ||
49fd6edc | 240 | if ((RETVAL = cygwin_internal(CW_CYGWIN_PID_TO_WINPID, pid)) > 0) { |
1604cfb0 | 241 | XSprePUSH; PUSHi((IV)RETVAL); |
49fd6edc YST |
242 | XSRETURN(1); |
243 | } | |
244 | XSRETURN_UNDEF; | |
245 | } | |
246 | ||
49fd6edc YST |
247 | XS(XS_Cygwin_winpid_to_pid) |
248 | { | |
249 | dXSARGS; | |
d2dc0126 YST |
250 | dXSTARG; |
251 | pid_t pid, RETVAL; | |
252 | ||
49fd6edc YST |
253 | if (items != 1) |
254 | Perl_croak(aTHX_ "Usage: Cygwin::winpid_to_pid(pid)"); | |
d2dc0126 YST |
255 | |
256 | pid = (pid_t)SvIV(ST(0)); | |
257 | ||
803e389c RU |
258 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
259 | RETVAL = cygwin_winpid_to_pid(pid); | |
260 | #else | |
261 | RETVAL = cygwin32_winpid_to_pid(pid); | |
262 | #endif | |
263 | if (RETVAL > 0) { | |
49fd6edc YST |
264 | XSprePUSH; PUSHi((IV)RETVAL); |
265 | XSRETURN(1); | |
266 | } | |
267 | XSRETURN_UNDEF; | |
268 | } | |
269 | ||
ea18e4f3 KW |
270 | /* The conversion between Posix and Windows paths is essentially the same in |
271 | * either direction, so a common function is used, with which direction passed | |
272 | * in. | |
273 | * | |
274 | * These numbers are chosen so can be or'd with absolute flag to get 0..3 */ | |
275 | typedef enum { | |
276 | to_posix = 0, | |
277 | to_win = 2 | |
278 | } direction_t; | |
279 | ||
280 | static void | |
281 | S_convert_path_common(pTHX_ const direction_t direction) | |
15414d2b RU |
282 | { |
283 | dXSARGS; | |
ea18e4f3 | 284 | bool absolute_flag = 0; |
15414d2b | 285 | STRLEN len; |
ba495c01 | 286 | int err = 0; |
803e389c | 287 | char *src_path; |
c3be9bd4 | 288 | char *converted_path; |
803e389c | 289 | int isutf8 = 0; |
15414d2b | 290 | |
ea18e4f3 KW |
291 | if (items < 1 || items > 2) { |
292 | char *name = (direction == to_posix) | |
293 | ? "win::win_to_posix_path" | |
294 | : "posix_to_win_path"; | |
295 | Perl_croak(aTHX_ "Usage: Cygwin::%s(pathname, [absolute])", name); | |
296 | } | |
15414d2b | 297 | |
bba8d7cf | 298 | src_path = SvPVx(ST(0), len); |
15414d2b | 299 | if (items == 2) |
1604cfb0 | 300 | absolute_flag = SvTRUE(ST(1)); |
15414d2b RU |
301 | |
302 | if (!len) | |
1604cfb0 | 303 | Perl_croak(aTHX_ "can't convert empty path"); |
803e389c | 304 | isutf8 = SvUTF8(ST(0)); |
15414d2b | 305 | |
803e389c RU |
306 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
307 | /* Check utf8 flag and use wide api then. | |
308 | Size calculation: On overflow let cygwin_conv_path calculate the final size. | |
309 | */ | |
310 | if (isutf8) { | |
ea18e4f3 KW |
311 | int what = ((absolute_flag) ? 0 : CCP_RELATIVE) |
312 | | ((direction == to_posix) | |
313 | ? CCP_WIN_W_TO_POSIX | |
314 | : CCP_POSIX_TO_WIN_W); | |
a8a9fd0a | 315 | STRLEN wlen; |
93425aaa KW |
316 | wchar_t *wsrc = NULL; /* The source, as a wchar_t */ |
317 | wchar_t *wconverted = NULL; /* wsrc, converted to the destination */ | |
a0b53297 | 318 | |
7dccff44 KW |
319 | /* ptr to either wsrc, or under BYTES, the src_path so can have common |
320 | * code below */ | |
321 | wchar_t *which_src = (wchar_t *) src_path; | |
322 | ||
93425aaa | 323 | if (LIKELY(! IN_BYTES)) { /* Normal case, convert UTF-8 to UTF-16 */ |
a8a9fd0a | 324 | wlen = PATH_LEN_GUESS; |
7dccff44 KW |
325 | wsrc = utf8_to_wide_extra_len(src_path, &wlen); |
326 | which_src = wsrc; | |
a8a9fd0a KW |
327 | } |
328 | else { /* use bytes; assume already UTF-16 encoded bytestream */ | |
329 | wlen = sizeof(wchar_t) * (len + PATH_LEN_GUESS); | |
7dccff44 KW |
330 | } |
331 | ||
332 | if (LIKELY(wlen > 0)) { /* Make sure didn't get an error */ | |
333 | wconverted = (wchar_t *) safemalloc(wlen); | |
334 | err = cygwin_conv_path(what, which_src, wconverted, wlen); | |
1604cfb0 | 335 | } |
ea18e4f3 | 336 | |
1604cfb0 | 337 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ |
7dccff44 KW |
338 | int newlen = cygwin_conv_path(what, which_src, wconverted, 0); |
339 | wconverted = (wchar_t *) realloc(&wconverted, newlen); | |
340 | err = cygwin_conv_path(what, which_src, wconverted, newlen); | |
1604cfb0 | 341 | } |
457ba501 | 342 | |
c3be9bd4 | 343 | converted_path = wide_to_utf8(wconverted); |
ac4290d0 | 344 | |
c3be9bd4 KW |
345 | safefree(wconverted); |
346 | safefree(wsrc); | |
803e389c | 347 | } else { |
ea18e4f3 KW |
348 | int what = ((absolute_flag) ? 0 : CCP_RELATIVE) |
349 | | ((direction == to_posix) | |
350 | ? CCP_WIN_A_TO_POSIX | |
351 | : CCP_POSIX_TO_WIN_A); | |
352 | ||
c3be9bd4 KW |
353 | converted_path = (char *) safemalloc (len + PATH_LEN_GUESS); |
354 | err = cygwin_conv_path(what, src_path, converted_path, len + PATH_LEN_GUESS); | |
1604cfb0 | 355 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ |
c3be9bd4 KW |
356 | int newlen = cygwin_conv_path(what, src_path, converted_path, 0); |
357 | converted_path = (char *) realloc(&converted_path, newlen); | |
358 | err = cygwin_conv_path(what, src_path, converted_path, newlen); | |
1604cfb0 | 359 | } |
803e389c | 360 | } |
ea18e4f3 | 361 | |
803e389c | 362 | #else |
c3be9bd4 | 363 | converted_path = (char *) safemalloc (len + PATH_LEN_GUESS); |
ea18e4f3 KW |
364 | |
365 | switch (absolute_flag | direction) { | |
366 | case (1|to_posix): | |
c3be9bd4 | 367 | err = cygwin_conv_to_full_posix_path(src_path, converted_path); |
ea18e4f3 KW |
368 | break; |
369 | case (0|to_posix): | |
c3be9bd4 | 370 | err = cygwin_conv_to_posix_path(src_path, converted_path); |
ea18e4f3 KW |
371 | break; |
372 | case (1|to_win): | |
373 | err = cygwin_conv_to_full_win32_path(src_path, converted_path); | |
374 | break; | |
375 | case (0|to_win): | |
376 | err = cygwin_conv_to_win32_path(src_path, converted_path); | |
377 | break; | |
378 | } | |
379 | ||
803e389c | 380 | #endif |
ea18e4f3 | 381 | |
15414d2b | 382 | if (!err) { |
1604cfb0 | 383 | EXTEND(SP, 1); |
c3be9bd4 | 384 | ST(0) = sv_2mortal(newSVpv(converted_path, 0)); |
1604cfb0 MS |
385 | if (isutf8) { /* src was utf-8, so result should also */ |
386 | /* TODO: convert ANSI (local windows encoding) to utf-8 on cygwin-1.5 */ | |
387 | SvUTF8_on(ST(0)); | |
388 | } | |
c3be9bd4 | 389 | safefree(converted_path); |
803e389c | 390 | XSRETURN(1); |
15414d2b | 391 | } else { |
c3be9bd4 | 392 | safefree(converted_path); |
1604cfb0 | 393 | XSRETURN_UNDEF; |
15414d2b RU |
394 | } |
395 | } | |
396 | ||
ea18e4f3 | 397 | XS(XS_Cygwin_win_to_posix_path) |
15414d2b | 398 | { |
ea18e4f3 KW |
399 | S_convert_path_common(aTHX_ to_posix); |
400 | } | |
457ba501 | 401 | |
ea18e4f3 KW |
402 | XS(XS_Cygwin_posix_to_win_path) |
403 | { | |
404 | S_convert_path_common(aTHX_ to_win); | |
15414d2b RU |
405 | } |
406 | ||
a25ce5f3 RU |
407 | XS(XS_Cygwin_mount_table) |
408 | { | |
409 | dXSARGS; | |
410 | struct mntent *mnt; | |
411 | ||
412 | if (items != 0) | |
413 | Perl_croak(aTHX_ "Usage: Cygwin::mount_table"); | |
414 | /* => array of [mnt_dir mnt_fsname mnt_type mnt_opts] */ | |
415 | ||
416 | setmntent (0, 0); | |
417 | while ((mnt = getmntent (0))) { | |
1604cfb0 MS |
418 | AV* av = newAV(); |
419 | av_push(av, newSVpvn(mnt->mnt_dir, strlen(mnt->mnt_dir))); | |
420 | av_push(av, newSVpvn(mnt->mnt_fsname, strlen(mnt->mnt_fsname))); | |
421 | av_push(av, newSVpvn(mnt->mnt_type, strlen(mnt->mnt_type))); | |
422 | av_push(av, newSVpvn(mnt->mnt_opts, strlen(mnt->mnt_opts))); | |
423 | XPUSHs(sv_2mortal(newRV_noinc((SV*)av))); | |
a25ce5f3 RU |
424 | } |
425 | endmntent (0); | |
426 | PUTBACK; | |
427 | } | |
428 | ||
429 | XS(XS_Cygwin_mount_flags) | |
430 | { | |
431 | dXSARGS; | |
432 | char *pathname; | |
803e389c RU |
433 | char flags[PATH_MAX]; |
434 | flags[0] = '\0'; | |
a25ce5f3 RU |
435 | |
436 | if (items != 1) | |
803e389c | 437 | Perl_croak(aTHX_ "Usage: Cygwin::mount_flags( mnt_dir | '/cygdrive' )"); |
a25ce5f3 RU |
438 | |
439 | pathname = SvPV_nolen(ST(0)); | |
74dc058d | 440 | |
083b2a61 | 441 | if (strEQ(pathname, "/cygdrive")) { |
1604cfb0 MS |
442 | char user[PATH_MAX]; |
443 | char system[PATH_MAX]; | |
444 | char user_flags[PATH_MAX]; | |
445 | char system_flags[PATH_MAX]; | |
74dc058d | 446 | |
1604cfb0 MS |
447 | cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, |
448 | user_flags, system_flags); | |
74dc058d JH |
449 | |
450 | if (strlen(user) > 0) { | |
451 | sprintf(flags, "%s,cygdrive,%s", user_flags, user); | |
452 | } else { | |
453 | sprintf(flags, "%s,cygdrive,%s", system_flags, system); | |
454 | } | |
455 | ||
1604cfb0 MS |
456 | ST(0) = sv_2mortal(newSVpv(flags, 0)); |
457 | XSRETURN(1); | |
74dc058d | 458 | |
a25ce5f3 | 459 | } else { |
1604cfb0 MS |
460 | struct mntent *mnt; |
461 | int found = 0; | |
462 | setmntent (0, 0); | |
463 | while ((mnt = getmntent (0))) { | |
464 | if (strEQ(pathname, mnt->mnt_dir)) { | |
465 | strcpy(flags, mnt->mnt_type); | |
466 | if (strlen(mnt->mnt_opts) > 0) { | |
467 | strcat(flags, ","); | |
468 | strcat(flags, mnt->mnt_opts); | |
469 | } | |
470 | found++; | |
471 | break; | |
472 | } | |
473 | } | |
474 | endmntent (0); | |
475 | ||
476 | /* Check if arg is the current volume moint point if not default, | |
477 | * and then use CW_GET_CYGDRIVE_INFO also. | |
478 | */ | |
479 | if (!found) { | |
480 | char user[PATH_MAX]; | |
481 | char system[PATH_MAX]; | |
482 | char user_flags[PATH_MAX]; | |
483 | char system_flags[PATH_MAX]; | |
484 | ||
485 | cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, | |
486 | user_flags, system_flags); | |
487 | ||
488 | if (strlen(user) > 0) { | |
489 | if (strNE(user,pathname)) { | |
490 | sprintf(flags, "%s,cygdrive,%s", user_flags, user); | |
491 | found++; | |
492 | } | |
493 | } else { | |
494 | if (strNE(user,pathname)) { | |
495 | sprintf(flags, "%s,cygdrive,%s", system_flags, system); | |
496 | found++; | |
497 | } | |
498 | } | |
499 | } | |
500 | if (found) { | |
501 | ST(0) = sv_2mortal(newSVpv(flags, 0)); | |
502 | XSRETURN(1); | |
503 | } else { | |
504 | XSRETURN_UNDEF; | |
505 | } | |
a25ce5f3 RU |
506 | } |
507 | } | |
508 | ||
15414d2b RU |
509 | XS(XS_Cygwin_is_binmount) |
510 | { | |
511 | dXSARGS; | |
512 | char *pathname; | |
513 | ||
514 | if (items != 1) | |
515 | Perl_croak(aTHX_ "Usage: Cygwin::is_binmount(pathname)"); | |
516 | ||
517 | pathname = SvPV_nolen(ST(0)); | |
518 | ||
519 | ST(0) = boolSV(cygwin_internal(CW_GET_BINMODE, pathname)); | |
520 | XSRETURN(1); | |
521 | } | |
522 | ||
286f8194 RU |
523 | XS(XS_Cygwin_sync_winenv){ cygwin_internal(CW_SYNC_WINENV); } |
524 | ||
5db16f6a EF |
525 | void |
526 | init_os_extras(void) | |
527 | { | |
5db16f6a | 528 | dTHX; |
a4ec4e68 | 529 | char const *file = __FILE__; |
9fb265f7 | 530 | void *handle; |
5db16f6a EF |
531 | |
532 | newXS("Cwd::cwd", Cygwin_cwd, file); | |
15414d2b RU |
533 | newXSproto("Cygwin::winpid_to_pid", XS_Cygwin_winpid_to_pid, file, "$"); |
534 | newXSproto("Cygwin::pid_to_winpid", XS_Cygwin_pid_to_winpid, file, "$"); | |
535 | newXSproto("Cygwin::win_to_posix_path", XS_Cygwin_win_to_posix_path, file, "$;$"); | |
536 | newXSproto("Cygwin::posix_to_win_path", XS_Cygwin_posix_to_win_path, file, "$;$"); | |
a25ce5f3 RU |
537 | newXSproto("Cygwin::mount_table", XS_Cygwin_mount_table, file, ""); |
538 | newXSproto("Cygwin::mount_flags", XS_Cygwin_mount_flags, file, "$"); | |
15414d2b | 539 | newXSproto("Cygwin::is_binmount", XS_Cygwin_is_binmount, file, "$"); |
286f8194 | 540 | newXS("Cygwin::sync_winenv", XS_Cygwin_sync_winenv, file); |
78ff2d7b | 541 | |
9fb265f7 JD |
542 | /* Initialize Win32CORE if it has been statically linked. */ |
543 | handle = dlopen(NULL, RTLD_LAZY); | |
544 | if (handle) { | |
545 | void (*pfn_init)(pTHX); | |
546 | pfn_init = (void (*)(pTHX))dlsym(handle, "init_Win32CORE"); | |
547 | if (pfn_init) | |
548 | pfn_init(aTHX); | |
549 | dlclose(handle); | |
78ff2d7b | 550 | } |
5db16f6a | 551 | } |