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 | |
b4bcd662 GS |
22 | /* |
23 | * pp_system() implemented via spawn() | |
24 | * - more efficient and useful when embedding Perl in non-Cygwin apps | |
25 | * - code mostly borrowed from djgpp.c | |
26 | */ | |
27 | static int | |
28 | do_spawnvp (const char *path, const char * const *argv) | |
29 | { | |
acfe0abc | 30 | dTHX; |
b4bcd662 GS |
31 | Sigsave_t ihand,qhand; |
32 | int childpid, result, status; | |
33 | ||
ec1aec95 YST |
34 | rsignal_save(SIGINT, (Sighandler_t) SIG_IGN, &ihand); |
35 | rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qhand); | |
b4bcd662 GS |
36 | childpid = spawnvp(_P_NOWAIT,path,argv); |
37 | if (childpid < 0) { | |
38 | status = -1; | |
411caa50 | 39 | if(ckWARN(WARN_EXEC)) |
f98bc0c6 | 40 | Perl_warner(aTHX_ packWARN(WARN_EXEC),"Can't spawn \"%s\": %s", |
b4bcd662 | 41 | path,Strerror (errno)); |
b4bcd662 GS |
42 | } else { |
43 | do { | |
44 | result = wait4pid(childpid, &status, 0); | |
45 | } while (result == -1 && errno == EINTR); | |
46 | if(result < 0) | |
47 | status = -1; | |
48 | } | |
49 | (void)rsignal_restore(SIGINT, &ihand); | |
50 | (void)rsignal_restore(SIGQUIT, &qhand); | |
51 | return status; | |
52 | } | |
53 | ||
54 | int | |
55 | do_aspawn (SV *really, void **mark, void **sp) | |
56 | { | |
acfe0abc | 57 | dTHX; |
b4bcd662 | 58 | int rc; |
a4ec4e68 JH |
59 | char const **a; |
60 | char *tmps,**argv; | |
61 | STRLEN n_a; | |
b4bcd662 GS |
62 | |
63 | if (sp<=mark) | |
64 | return -1; | |
a4ec4e68 JH |
65 | argv=(char**) alloca ((sp-mark+3)*sizeof (char*)); |
66 | a=(char const **)argv; | |
b4bcd662 GS |
67 | |
68 | while (++mark <= sp) | |
69 | if (*mark) | |
667e2948 | 70 | *a++ = SvPVx((SV *)*mark, n_a); |
b4bcd662 GS |
71 | else |
72 | *a++ = ""; | |
dfe169ee | 73 | *a = (char*)NULL; |
b4bcd662 GS |
74 | |
75 | if (argv[0][0] != '/' && argv[0][0] != '\\' | |
76 | && !(argv[0][0] && argv[0][1] == ':' | |
77 | && (argv[0][2] == '/' || argv[0][2] != '\\')) | |
78 | ) /* will swawnvp use PATH? */ | |
79 | TAINT_ENV(); /* testing IFS here is overkill, probably */ | |
80 | ||
81 | if (really && *(tmps = SvPV(really, n_a))) | |
82 | rc=do_spawnvp (tmps,(const char * const *)argv); | |
83 | else | |
84 | rc=do_spawnvp (argv[0],(const char *const *)argv); | |
85 | ||
86 | return rc; | |
87 | } | |
88 | ||
89 | int | |
90 | do_spawn (char *cmd) | |
91 | { | |
acfe0abc | 92 | dTHX; |
3f5211dd | 93 | char const **a; |
a4ec4e68 JH |
94 | char *s; |
95 | char const *metachars = "$&*(){}[]'\";\\?>|<~`\n"; | |
b4bcd662 GS |
96 | const char *command[4]; |
97 | ||
98 | while (*cmd && isSPACE(*cmd)) | |
99 | cmd++; | |
100 | ||
101 | if (strnEQ (cmd,"/bin/sh",7) && isSPACE (cmd[7])) | |
102 | cmd+=5; | |
103 | ||
104 | /* save an extra exec if possible */ | |
105 | /* see if there are shell metacharacters in it */ | |
106 | if (strstr (cmd,"...")) | |
107 | goto doshell; | |
108 | if (*cmd=='.' && isSPACE (cmd[1])) | |
109 | goto doshell; | |
110 | if (strnEQ (cmd,"exec",4) && isSPACE (cmd[4])) | |
111 | goto doshell; | |
112 | for (s=cmd; *s && isALPHA (*s); s++) ; /* catch VAR=val gizmo */ | |
113 | if (*s=='=') | |
114 | goto doshell; | |
115 | ||
116 | for (s=cmd; *s; s++) | |
117 | if (strchr (metachars,*s)) | |
118 | { | |
119 | if (*s=='\n' && s[1]=='\0') | |
120 | { | |
121 | *s='\0'; | |
122 | break; | |
123 | } | |
124 | doshell: | |
125 | command[0] = "sh"; | |
126 | command[1] = "-c"; | |
127 | command[2] = cmd; | |
128 | command[3] = NULL; | |
129 | ||
130 | return do_spawnvp("sh",command); | |
131 | } | |
132 | ||
ba495c01 | 133 | Newx (PL_Argv, (s-cmd)/2+2, const char*); |
b4bcd662 GS |
134 | PL_Cmd=savepvn (cmd,s-cmd); |
135 | a=PL_Argv; | |
136 | for (s=PL_Cmd; *s;) { | |
137 | while (*s && isSPACE (*s)) s++; | |
138 | if (*s) | |
139 | *(a++)=s; | |
140 | while (*s && !isSPACE (*s)) s++; | |
141 | if (*s) | |
142 | *s++='\0'; | |
143 | } | |
dfe169ee | 144 | *a = (char*)NULL; |
b4bcd662 GS |
145 | if (!PL_Argv[0]) |
146 | return -1; | |
147 | ||
148 | return do_spawnvp(PL_Argv[0],(const char * const *)PL_Argv); | |
149 | } | |
5db16f6a | 150 | |
803e389c RU |
151 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
152 | char* | |
153 | wide_to_utf8(const wchar_t *wbuf) | |
154 | { | |
155 | char *buf; | |
156 | int wlen = 0; | |
a0b53297 KW |
157 | char *oldlocale; |
158 | dVAR; | |
159 | ||
160 | /* Here and elsewhere in this file, we have a critical section to prevent | |
161 | * another thread from changing the locale out from under us. XXX But why | |
162 | * not just use uvchr_to_utf8? */ | |
163 | LOCALE_LOCK; | |
164 | ||
165 | oldlocale = setlocale(LC_CTYPE, NULL); | |
803e389c RU |
166 | setlocale(LC_CTYPE, "utf-8"); |
167 | ||
c80e42f3 | 168 | /* uvchr_to_utf8(buf, chr) or Encoding::_bytes_to_utf8(sv, "UCS-2BE"); */ |
803e389c RU |
169 | wlen = wcsrtombs(NULL, (const wchar_t **)&wbuf, wlen, NULL); |
170 | buf = (char *) safemalloc(wlen+1); | |
171 | wcsrtombs(buf, (const wchar_t **)&wbuf, wlen, NULL); | |
172 | ||
173 | if (oldlocale) setlocale(LC_CTYPE, oldlocale); | |
174 | else setlocale(LC_CTYPE, "C"); | |
a0b53297 KW |
175 | |
176 | LOCALE_UNLOCK; | |
177 | ||
803e389c RU |
178 | return buf; |
179 | } | |
180 | ||
181 | wchar_t* | |
182 | utf8_to_wide(const char *buf) | |
183 | { | |
184 | wchar_t *wbuf; | |
185 | mbstate_t mbs; | |
a0b53297 | 186 | char *oldlocale; |
803e389c | 187 | int wlen = sizeof(wchar_t)*strlen(buf); |
a0b53297 KW |
188 | dVAR; |
189 | ||
190 | LOCALE_LOCK; | |
191 | ||
192 | oldlocale = setlocale(LC_CTYPE, NULL); | |
803e389c RU |
193 | |
194 | setlocale(LC_CTYPE, "utf-8"); | |
195 | wbuf = (wchar_t *) safemalloc(wlen); | |
c80e42f3 | 196 | /* utf8_to_uvchr_buf(pathname, pathname + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */ |
803e389c RU |
197 | wlen = mbsrtowcs(wbuf, (const char**)&buf, wlen, &mbs); |
198 | ||
199 | if (oldlocale) setlocale(LC_CTYPE, oldlocale); | |
200 | else setlocale(LC_CTYPE, "C"); | |
a0b53297 KW |
201 | |
202 | LOCALE_UNLOCK; | |
203 | ||
803e389c RU |
204 | return wbuf; |
205 | } | |
206 | #endif /* cygwin 1.7 */ | |
207 | ||
5db16f6a | 208 | /* see also Cwd.pm */ |
5db16f6a EF |
209 | XS(Cygwin_cwd) |
210 | { | |
211 | dXSARGS; | |
212 | char *cwd; | |
213 | ||
482150a7 JH |
214 | /* See http://rt.perl.org/rt3/Ticket/Display.html?id=38628 |
215 | There is Cwd->cwd() usage in the wild, and previous versions didn't die. | |
216 | */ | |
217 | if(items > 1) | |
5db16f6a | 218 | Perl_croak(aTHX_ "Usage: Cwd::cwd()"); |
47dafe4d | 219 | if((cwd = getcwd(NULL, -1))) { |
5db16f6a | 220 | ST(0) = sv_2mortal(newSVpv(cwd, 0)); |
a236cecb | 221 | free(cwd); |
6be3b590 | 222 | SvTAINTED_on(ST(0)); |
5db16f6a EF |
223 | XSRETURN(1); |
224 | } | |
225 | XSRETURN_UNDEF; | |
226 | } | |
227 | ||
49fd6edc YST |
228 | XS(XS_Cygwin_pid_to_winpid) |
229 | { | |
230 | dXSARGS; | |
d2dc0126 YST |
231 | dXSTARG; |
232 | pid_t pid, RETVAL; | |
233 | ||
49fd6edc YST |
234 | if (items != 1) |
235 | Perl_croak(aTHX_ "Usage: Cygwin::pid_to_winpid(pid)"); | |
d2dc0126 YST |
236 | |
237 | pid = (pid_t)SvIV(ST(0)); | |
238 | ||
49fd6edc YST |
239 | if ((RETVAL = cygwin_internal(CW_CYGWIN_PID_TO_WINPID, pid)) > 0) { |
240 | XSprePUSH; PUSHi((IV)RETVAL); | |
241 | XSRETURN(1); | |
242 | } | |
243 | XSRETURN_UNDEF; | |
244 | } | |
245 | ||
49fd6edc YST |
246 | XS(XS_Cygwin_winpid_to_pid) |
247 | { | |
248 | dXSARGS; | |
d2dc0126 YST |
249 | dXSTARG; |
250 | pid_t pid, RETVAL; | |
251 | ||
49fd6edc YST |
252 | if (items != 1) |
253 | Perl_croak(aTHX_ "Usage: Cygwin::winpid_to_pid(pid)"); | |
d2dc0126 YST |
254 | |
255 | pid = (pid_t)SvIV(ST(0)); | |
256 | ||
803e389c RU |
257 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
258 | RETVAL = cygwin_winpid_to_pid(pid); | |
259 | #else | |
260 | RETVAL = cygwin32_winpid_to_pid(pid); | |
261 | #endif | |
262 | if (RETVAL > 0) { | |
49fd6edc YST |
263 | XSprePUSH; PUSHi((IV)RETVAL); |
264 | XSRETURN(1); | |
265 | } | |
266 | XSRETURN_UNDEF; | |
267 | } | |
268 | ||
15414d2b | 269 | XS(XS_Cygwin_win_to_posix_path) |
803e389c | 270 | |
15414d2b RU |
271 | { |
272 | dXSARGS; | |
273 | int absolute_flag = 0; | |
274 | STRLEN len; | |
ba495c01 | 275 | int err = 0; |
803e389c RU |
276 | char *src_path; |
277 | char *posix_path; | |
278 | int isutf8 = 0; | |
15414d2b RU |
279 | |
280 | if (items < 1 || items > 2) | |
281 | Perl_croak(aTHX_ "Usage: Cygwin::win_to_posix_path(pathname, [absolute])"); | |
282 | ||
803e389c | 283 | src_path = SvPV(ST(0), len); |
15414d2b RU |
284 | if (items == 2) |
285 | absolute_flag = SvTRUE(ST(1)); | |
286 | ||
287 | if (!len) | |
288 | Perl_croak(aTHX_ "can't convert empty path"); | |
803e389c | 289 | isutf8 = SvUTF8(ST(0)); |
15414d2b | 290 | |
803e389c RU |
291 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
292 | /* Check utf8 flag and use wide api then. | |
293 | Size calculation: On overflow let cygwin_conv_path calculate the final size. | |
294 | */ | |
295 | if (isutf8) { | |
296 | int what = absolute_flag ? CCP_WIN_W_TO_POSIX : CCP_WIN_W_TO_POSIX | CCP_RELATIVE; | |
297 | int wlen = sizeof(wchar_t)*(len + 260 + 1001); | |
298 | wchar_t *wpath = (wchar_t *) safemalloc(sizeof(wchar_t)*len); | |
299 | wchar_t *wbuf = (wchar_t *) safemalloc(wlen); | |
300 | if (!IN_BYTES) { | |
301 | mbstate_t mbs; | |
a0b53297 KW |
302 | char *oldlocale; |
303 | dVAR; | |
304 | ||
305 | LOCALE_LOCK; | |
306 | ||
307 | oldlocale = setlocale(LC_CTYPE, NULL); | |
803e389c | 308 | setlocale(LC_CTYPE, "utf-8"); |
c80e42f3 | 309 | /* utf8_to_uvchr_buf(src_path, src_path + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */ |
803e389c RU |
310 | wlen = mbsrtowcs(wpath, (const char**)&src_path, wlen, &mbs); |
311 | if (wlen > 0) | |
312 | err = cygwin_conv_path(what, wpath, wbuf, wlen); | |
313 | if (oldlocale) setlocale(LC_CTYPE, oldlocale); | |
314 | else setlocale(LC_CTYPE, "C"); | |
a0b53297 KW |
315 | |
316 | LOCALE_UNLOCK; | |
803e389c RU |
317 | } else { /* use bytes; assume already ucs-2 encoded bytestream */ |
318 | err = cygwin_conv_path(what, src_path, wbuf, wlen); | |
319 | } | |
320 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ | |
321 | int newlen = cygwin_conv_path(what, wpath, wbuf, 0); | |
322 | wbuf = (wchar_t *) realloc(&wbuf, newlen); | |
323 | err = cygwin_conv_path(what, wpath, wbuf, newlen); | |
324 | wlen = newlen; | |
325 | } | |
326 | /* utf16_to_utf8(*p, *d, bytlen, *newlen) */ | |
327 | posix_path = (char *) safemalloc(wlen*3); | |
328 | Perl_utf16_to_utf8(aTHX_ (U8*)&wpath, (U8*)posix_path, (I32)wlen*2, (I32*)&len); | |
329 | /* | |
330 | wlen = wcsrtombs(NULL, (const wchar_t **)&wbuf, wlen, NULL); | |
331 | posix_path = (char *) safemalloc(wlen+1); | |
332 | wcsrtombs(posix_path, (const wchar_t **)&wbuf, wlen, NULL); | |
333 | */ | |
334 | } else { | |
335 | int what = absolute_flag ? CCP_WIN_A_TO_POSIX : CCP_WIN_A_TO_POSIX | CCP_RELATIVE; | |
336 | posix_path = (char *) safemalloc (len + 260 + 1001); | |
337 | err = cygwin_conv_path(what, src_path, posix_path, len + 260 + 1001); | |
338 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ | |
339 | int newlen = cygwin_conv_path(what, src_path, posix_path, 0); | |
340 | posix_path = (char *) realloc(&posix_path, newlen); | |
341 | err = cygwin_conv_path(what, src_path, posix_path, newlen); | |
342 | } | |
343 | } | |
344 | #else | |
345 | posix_path = (char *) safemalloc (len + 260 + 1001); | |
15414d2b | 346 | if (absolute_flag) |
803e389c | 347 | err = cygwin_conv_to_full_posix_path(src_path, posix_path); |
15414d2b | 348 | else |
803e389c RU |
349 | err = cygwin_conv_to_posix_path(src_path, posix_path); |
350 | #endif | |
15414d2b | 351 | if (!err) { |
803e389c RU |
352 | EXTEND(SP, 1); |
353 | ST(0) = sv_2mortal(newSVpv(posix_path, 0)); | |
354 | if (isutf8) { /* src was utf-8, so result should also */ | |
355 | /* TODO: convert ANSI (local windows encoding) to utf-8 on cygwin-1.5 */ | |
356 | SvUTF8_on(ST(0)); | |
357 | } | |
358 | safefree(posix_path); | |
359 | XSRETURN(1); | |
15414d2b | 360 | } else { |
803e389c | 361 | safefree(posix_path); |
15414d2b RU |
362 | XSRETURN_UNDEF; |
363 | } | |
364 | } | |
365 | ||
366 | XS(XS_Cygwin_posix_to_win_path) | |
367 | { | |
368 | dXSARGS; | |
369 | int absolute_flag = 0; | |
370 | STRLEN len; | |
ba495c01 | 371 | int err = 0; |
803e389c RU |
372 | char *src_path, *win_path; |
373 | int isutf8 = 0; | |
15414d2b RU |
374 | |
375 | if (items < 1 || items > 2) | |
376 | Perl_croak(aTHX_ "Usage: Cygwin::posix_to_win_path(pathname, [absolute])"); | |
377 | ||
803e389c | 378 | src_path = SvPVx(ST(0), len); |
15414d2b RU |
379 | if (items == 2) |
380 | absolute_flag = SvTRUE(ST(1)); | |
381 | ||
382 | if (!len) | |
383 | Perl_croak(aTHX_ "can't convert empty path"); | |
803e389c RU |
384 | isutf8 = SvUTF8(ST(0)); |
385 | #if (CYGWIN_VERSION_API_MINOR >= 181) | |
386 | /* Check utf8 flag and use wide api then. | |
387 | Size calculation: On overflow let cygwin_conv_path calculate the final size. | |
388 | */ | |
389 | if (isutf8) { | |
390 | int what = absolute_flag ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_W | CCP_RELATIVE; | |
391 | int wlen = sizeof(wchar_t)*(len + 260 + 1001); | |
392 | wchar_t *wpath = (wchar_t *) safemalloc(sizeof(wchar_t)*len); | |
393 | wchar_t *wbuf = (wchar_t *) safemalloc(wlen); | |
a0b53297 KW |
394 | char *oldlocale; |
395 | dVAR; | |
396 | ||
397 | LOCALE_LOCK; | |
398 | ||
399 | oldlocale = setlocale(LC_CTYPE, NULL); | |
803e389c RU |
400 | setlocale(LC_CTYPE, "utf-8"); |
401 | if (!IN_BYTES) { | |
402 | mbstate_t mbs; | |
c80e42f3 | 403 | /* utf8_to_uvchr_buf(src_path, src_path + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */ |
803e389c RU |
404 | wlen = mbsrtowcs(wpath, (const char**)&src_path, wlen, &mbs); |
405 | if (wlen > 0) | |
406 | err = cygwin_conv_path(what, wpath, wbuf, wlen); | |
407 | } else { /* use bytes; assume already ucs-2 encoded bytestream */ | |
408 | err = cygwin_conv_path(what, src_path, wbuf, wlen); | |
409 | } | |
410 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ | |
411 | int newlen = cygwin_conv_path(what, wpath, wbuf, 0); | |
412 | wbuf = (wchar_t *) realloc(&wbuf, newlen); | |
413 | err = cygwin_conv_path(what, wpath, wbuf, newlen); | |
414 | wlen = newlen; | |
415 | } | |
416 | /* also see utf8.c: Perl_utf16_to_utf8() or Encoding::_bytes_to_utf8(sv, "UCS-2BE"); */ | |
417 | wlen = wcsrtombs(NULL, (const wchar_t **)&wbuf, wlen, NULL); | |
418 | win_path = (char *) safemalloc(wlen+1); | |
419 | wcsrtombs(win_path, (const wchar_t **)&wbuf, wlen, NULL); | |
420 | if (oldlocale) setlocale(LC_CTYPE, oldlocale); | |
421 | else setlocale(LC_CTYPE, "C"); | |
a0b53297 KW |
422 | |
423 | LOCALE_UNLOCK; | |
803e389c RU |
424 | } else { |
425 | int what = absolute_flag ? CCP_POSIX_TO_WIN_A : CCP_POSIX_TO_WIN_A | CCP_RELATIVE; | |
426 | win_path = (char *) safemalloc(len + 260 + 1001); | |
427 | err = cygwin_conv_path(what, src_path, win_path, len + 260 + 1001); | |
428 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ | |
429 | int newlen = cygwin_conv_path(what, src_path, win_path, 0); | |
430 | win_path = (char *) realloc(&win_path, newlen); | |
431 | err = cygwin_conv_path(what, src_path, win_path, newlen); | |
432 | } | |
433 | } | |
434 | #else | |
435 | if (isutf8) | |
436 | Perl_warn(aTHX_ "can't convert utf8 path"); | |
437 | win_path = (char *) safemalloc(len + 260 + 1001); | |
15414d2b | 438 | if (absolute_flag) |
803e389c | 439 | err = cygwin_conv_to_full_win32_path(src_path, win_path); |
15414d2b | 440 | else |
803e389c RU |
441 | err = cygwin_conv_to_win32_path(src_path, win_path); |
442 | #endif | |
15414d2b | 443 | if (!err) { |
803e389c RU |
444 | EXTEND(SP, 1); |
445 | ST(0) = sv_2mortal(newSVpv(win_path, 0)); | |
446 | if (isutf8) { | |
447 | SvUTF8_on(ST(0)); | |
448 | } | |
449 | safefree(win_path); | |
450 | XSRETURN(1); | |
15414d2b | 451 | } else { |
803e389c | 452 | safefree(win_path); |
15414d2b RU |
453 | XSRETURN_UNDEF; |
454 | } | |
455 | } | |
456 | ||
a25ce5f3 RU |
457 | XS(XS_Cygwin_mount_table) |
458 | { | |
459 | dXSARGS; | |
460 | struct mntent *mnt; | |
461 | ||
462 | if (items != 0) | |
463 | Perl_croak(aTHX_ "Usage: Cygwin::mount_table"); | |
464 | /* => array of [mnt_dir mnt_fsname mnt_type mnt_opts] */ | |
465 | ||
466 | setmntent (0, 0); | |
467 | while ((mnt = getmntent (0))) { | |
468 | AV* av = newAV(); | |
469 | av_push(av, newSVpvn(mnt->mnt_dir, strlen(mnt->mnt_dir))); | |
470 | av_push(av, newSVpvn(mnt->mnt_fsname, strlen(mnt->mnt_fsname))); | |
471 | av_push(av, newSVpvn(mnt->mnt_type, strlen(mnt->mnt_type))); | |
472 | av_push(av, newSVpvn(mnt->mnt_opts, strlen(mnt->mnt_opts))); | |
473 | XPUSHs(sv_2mortal(newRV_noinc((SV*)av))); | |
474 | } | |
475 | endmntent (0); | |
476 | PUTBACK; | |
477 | } | |
478 | ||
479 | XS(XS_Cygwin_mount_flags) | |
480 | { | |
481 | dXSARGS; | |
482 | char *pathname; | |
803e389c RU |
483 | char flags[PATH_MAX]; |
484 | flags[0] = '\0'; | |
a25ce5f3 RU |
485 | |
486 | if (items != 1) | |
803e389c | 487 | Perl_croak(aTHX_ "Usage: Cygwin::mount_flags( mnt_dir | '/cygdrive' )"); |
a25ce5f3 RU |
488 | |
489 | pathname = SvPV_nolen(ST(0)); | |
74dc058d | 490 | |
a25ce5f3 | 491 | if (!strcmp(pathname, "/cygdrive")) { |
803e389c RU |
492 | char user[PATH_MAX]; |
493 | char system[PATH_MAX]; | |
494 | char user_flags[PATH_MAX]; | |
495 | char system_flags[PATH_MAX]; | |
74dc058d | 496 | |
803e389c RU |
497 | cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, |
498 | user_flags, system_flags); | |
74dc058d JH |
499 | |
500 | if (strlen(user) > 0) { | |
501 | sprintf(flags, "%s,cygdrive,%s", user_flags, user); | |
502 | } else { | |
503 | sprintf(flags, "%s,cygdrive,%s", system_flags, system); | |
504 | } | |
505 | ||
a25ce5f3 RU |
506 | ST(0) = sv_2mortal(newSVpv(flags, 0)); |
507 | XSRETURN(1); | |
74dc058d | 508 | |
a25ce5f3 RU |
509 | } else { |
510 | struct mntent *mnt; | |
803e389c | 511 | int found = 0; |
a25ce5f3 RU |
512 | setmntent (0, 0); |
513 | while ((mnt = getmntent (0))) { | |
514 | if (!strcmp(pathname, mnt->mnt_dir)) { | |
515 | strcpy(flags, mnt->mnt_type); | |
516 | if (strlen(mnt->mnt_opts) > 0) { | |
517 | strcat(flags, ","); | |
518 | strcat(flags, mnt->mnt_opts); | |
519 | } | |
803e389c | 520 | found++; |
a25ce5f3 RU |
521 | break; |
522 | } | |
523 | } | |
524 | endmntent (0); | |
803e389c RU |
525 | |
526 | /* Check if arg is the current volume moint point if not default, | |
527 | * and then use CW_GET_CYGDRIVE_INFO also. | |
528 | */ | |
529 | if (!found) { | |
530 | char user[PATH_MAX]; | |
531 | char system[PATH_MAX]; | |
532 | char user_flags[PATH_MAX]; | |
533 | char system_flags[PATH_MAX]; | |
534 | ||
535 | cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, | |
536 | user_flags, system_flags); | |
537 | ||
538 | if (strlen(user) > 0) { | |
539 | if (strcmp(user,pathname)) { | |
540 | sprintf(flags, "%s,cygdrive,%s", user_flags, user); | |
541 | found++; | |
542 | } | |
543 | } else { | |
544 | if (strcmp(user,pathname)) { | |
545 | sprintf(flags, "%s,cygdrive,%s", system_flags, system); | |
546 | found++; | |
547 | } | |
548 | } | |
549 | } | |
550 | if (found) { | |
551 | ST(0) = sv_2mortal(newSVpv(flags, 0)); | |
552 | XSRETURN(1); | |
553 | } else { | |
554 | XSRETURN_UNDEF; | |
555 | } | |
a25ce5f3 RU |
556 | } |
557 | } | |
558 | ||
15414d2b RU |
559 | XS(XS_Cygwin_is_binmount) |
560 | { | |
561 | dXSARGS; | |
562 | char *pathname; | |
563 | ||
564 | if (items != 1) | |
565 | Perl_croak(aTHX_ "Usage: Cygwin::is_binmount(pathname)"); | |
566 | ||
567 | pathname = SvPV_nolen(ST(0)); | |
568 | ||
569 | ST(0) = boolSV(cygwin_internal(CW_GET_BINMODE, pathname)); | |
570 | XSRETURN(1); | |
571 | } | |
572 | ||
286f8194 RU |
573 | XS(XS_Cygwin_sync_winenv){ cygwin_internal(CW_SYNC_WINENV); } |
574 | ||
5db16f6a EF |
575 | void |
576 | init_os_extras(void) | |
577 | { | |
5db16f6a | 578 | dTHX; |
a4ec4e68 | 579 | char const *file = __FILE__; |
9fb265f7 | 580 | void *handle; |
5db16f6a EF |
581 | |
582 | newXS("Cwd::cwd", Cygwin_cwd, file); | |
15414d2b RU |
583 | newXSproto("Cygwin::winpid_to_pid", XS_Cygwin_winpid_to_pid, file, "$"); |
584 | newXSproto("Cygwin::pid_to_winpid", XS_Cygwin_pid_to_winpid, file, "$"); | |
585 | newXSproto("Cygwin::win_to_posix_path", XS_Cygwin_win_to_posix_path, file, "$;$"); | |
586 | newXSproto("Cygwin::posix_to_win_path", XS_Cygwin_posix_to_win_path, file, "$;$"); | |
a25ce5f3 RU |
587 | newXSproto("Cygwin::mount_table", XS_Cygwin_mount_table, file, ""); |
588 | newXSproto("Cygwin::mount_flags", XS_Cygwin_mount_flags, file, "$"); | |
15414d2b | 589 | newXSproto("Cygwin::is_binmount", XS_Cygwin_is_binmount, file, "$"); |
286f8194 | 590 | newXS("Cygwin::sync_winenv", XS_Cygwin_sync_winenv, file); |
78ff2d7b | 591 | |
9fb265f7 JD |
592 | /* Initialize Win32CORE if it has been statically linked. */ |
593 | handle = dlopen(NULL, RTLD_LAZY); | |
594 | if (handle) { | |
595 | void (*pfn_init)(pTHX); | |
596 | pfn_init = (void (*)(pTHX))dlsym(handle, "init_Win32CORE"); | |
597 | if (pfn_init) | |
598 | pfn_init(aTHX); | |
599 | dlclose(handle); | |
78ff2d7b | 600 | } |
5db16f6a | 601 | } |