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; | |
157 | char *oldlocale = setlocale(LC_CTYPE, NULL); | |
158 | setlocale(LC_CTYPE, "utf-8"); | |
159 | ||
c80e42f3 | 160 | /* uvchr_to_utf8(buf, chr) or Encoding::_bytes_to_utf8(sv, "UCS-2BE"); */ |
803e389c RU |
161 | wlen = wcsrtombs(NULL, (const wchar_t **)&wbuf, wlen, NULL); |
162 | buf = (char *) safemalloc(wlen+1); | |
163 | wcsrtombs(buf, (const wchar_t **)&wbuf, wlen, NULL); | |
164 | ||
165 | if (oldlocale) setlocale(LC_CTYPE, oldlocale); | |
166 | else setlocale(LC_CTYPE, "C"); | |
167 | return buf; | |
168 | } | |
169 | ||
170 | wchar_t* | |
171 | utf8_to_wide(const char *buf) | |
172 | { | |
173 | wchar_t *wbuf; | |
174 | mbstate_t mbs; | |
175 | char *oldlocale = setlocale(LC_CTYPE, NULL); | |
176 | int wlen = sizeof(wchar_t)*strlen(buf); | |
177 | ||
178 | setlocale(LC_CTYPE, "utf-8"); | |
179 | wbuf = (wchar_t *) safemalloc(wlen); | |
c80e42f3 | 180 | /* utf8_to_uvchr_buf(pathname, pathname + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */ |
803e389c RU |
181 | wlen = mbsrtowcs(wbuf, (const char**)&buf, wlen, &mbs); |
182 | ||
183 | if (oldlocale) setlocale(LC_CTYPE, oldlocale); | |
184 | else setlocale(LC_CTYPE, "C"); | |
185 | return wbuf; | |
186 | } | |
187 | #endif /* cygwin 1.7 */ | |
188 | ||
5db16f6a | 189 | /* see also Cwd.pm */ |
5db16f6a EF |
190 | XS(Cygwin_cwd) |
191 | { | |
192 | dXSARGS; | |
193 | char *cwd; | |
194 | ||
482150a7 JH |
195 | /* See http://rt.perl.org/rt3/Ticket/Display.html?id=38628 |
196 | There is Cwd->cwd() usage in the wild, and previous versions didn't die. | |
197 | */ | |
198 | if(items > 1) | |
5db16f6a | 199 | Perl_croak(aTHX_ "Usage: Cwd::cwd()"); |
47dafe4d | 200 | if((cwd = getcwd(NULL, -1))) { |
5db16f6a | 201 | ST(0) = sv_2mortal(newSVpv(cwd, 0)); |
a236cecb | 202 | free(cwd); |
6be3b590 | 203 | SvTAINTED_on(ST(0)); |
5db16f6a EF |
204 | XSRETURN(1); |
205 | } | |
206 | XSRETURN_UNDEF; | |
207 | } | |
208 | ||
49fd6edc YST |
209 | XS(XS_Cygwin_pid_to_winpid) |
210 | { | |
211 | dXSARGS; | |
d2dc0126 YST |
212 | dXSTARG; |
213 | pid_t pid, RETVAL; | |
214 | ||
49fd6edc YST |
215 | if (items != 1) |
216 | Perl_croak(aTHX_ "Usage: Cygwin::pid_to_winpid(pid)"); | |
d2dc0126 YST |
217 | |
218 | pid = (pid_t)SvIV(ST(0)); | |
219 | ||
49fd6edc YST |
220 | if ((RETVAL = cygwin_internal(CW_CYGWIN_PID_TO_WINPID, pid)) > 0) { |
221 | XSprePUSH; PUSHi((IV)RETVAL); | |
222 | XSRETURN(1); | |
223 | } | |
224 | XSRETURN_UNDEF; | |
225 | } | |
226 | ||
49fd6edc YST |
227 | XS(XS_Cygwin_winpid_to_pid) |
228 | { | |
229 | dXSARGS; | |
d2dc0126 YST |
230 | dXSTARG; |
231 | pid_t pid, RETVAL; | |
232 | ||
49fd6edc YST |
233 | if (items != 1) |
234 | Perl_croak(aTHX_ "Usage: Cygwin::winpid_to_pid(pid)"); | |
d2dc0126 YST |
235 | |
236 | pid = (pid_t)SvIV(ST(0)); | |
237 | ||
803e389c RU |
238 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
239 | RETVAL = cygwin_winpid_to_pid(pid); | |
240 | #else | |
241 | RETVAL = cygwin32_winpid_to_pid(pid); | |
242 | #endif | |
243 | if (RETVAL > 0) { | |
49fd6edc YST |
244 | XSprePUSH; PUSHi((IV)RETVAL); |
245 | XSRETURN(1); | |
246 | } | |
247 | XSRETURN_UNDEF; | |
248 | } | |
249 | ||
15414d2b | 250 | XS(XS_Cygwin_win_to_posix_path) |
803e389c | 251 | |
15414d2b RU |
252 | { |
253 | dXSARGS; | |
254 | int absolute_flag = 0; | |
255 | STRLEN len; | |
ba495c01 | 256 | int err = 0; |
803e389c RU |
257 | char *src_path; |
258 | char *posix_path; | |
259 | int isutf8 = 0; | |
15414d2b RU |
260 | |
261 | if (items < 1 || items > 2) | |
262 | Perl_croak(aTHX_ "Usage: Cygwin::win_to_posix_path(pathname, [absolute])"); | |
263 | ||
803e389c | 264 | src_path = SvPV(ST(0), len); |
15414d2b RU |
265 | if (items == 2) |
266 | absolute_flag = SvTRUE(ST(1)); | |
267 | ||
268 | if (!len) | |
269 | Perl_croak(aTHX_ "can't convert empty path"); | |
803e389c | 270 | isutf8 = SvUTF8(ST(0)); |
15414d2b | 271 | |
803e389c RU |
272 | #if (CYGWIN_VERSION_API_MINOR >= 181) |
273 | /* Check utf8 flag and use wide api then. | |
274 | Size calculation: On overflow let cygwin_conv_path calculate the final size. | |
275 | */ | |
276 | if (isutf8) { | |
277 | int what = absolute_flag ? CCP_WIN_W_TO_POSIX : CCP_WIN_W_TO_POSIX | CCP_RELATIVE; | |
278 | int wlen = sizeof(wchar_t)*(len + 260 + 1001); | |
279 | wchar_t *wpath = (wchar_t *) safemalloc(sizeof(wchar_t)*len); | |
280 | wchar_t *wbuf = (wchar_t *) safemalloc(wlen); | |
281 | if (!IN_BYTES) { | |
282 | mbstate_t mbs; | |
283 | char *oldlocale = setlocale(LC_CTYPE, NULL); | |
284 | setlocale(LC_CTYPE, "utf-8"); | |
c80e42f3 | 285 | /* utf8_to_uvchr_buf(src_path, src_path + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */ |
803e389c RU |
286 | wlen = mbsrtowcs(wpath, (const char**)&src_path, wlen, &mbs); |
287 | if (wlen > 0) | |
288 | err = cygwin_conv_path(what, wpath, wbuf, wlen); | |
289 | if (oldlocale) setlocale(LC_CTYPE, oldlocale); | |
290 | else setlocale(LC_CTYPE, "C"); | |
291 | } else { /* use bytes; assume already ucs-2 encoded bytestream */ | |
292 | err = cygwin_conv_path(what, src_path, wbuf, wlen); | |
293 | } | |
294 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ | |
295 | int newlen = cygwin_conv_path(what, wpath, wbuf, 0); | |
296 | wbuf = (wchar_t *) realloc(&wbuf, newlen); | |
297 | err = cygwin_conv_path(what, wpath, wbuf, newlen); | |
298 | wlen = newlen; | |
299 | } | |
300 | /* utf16_to_utf8(*p, *d, bytlen, *newlen) */ | |
301 | posix_path = (char *) safemalloc(wlen*3); | |
302 | Perl_utf16_to_utf8(aTHX_ (U8*)&wpath, (U8*)posix_path, (I32)wlen*2, (I32*)&len); | |
303 | /* | |
304 | wlen = wcsrtombs(NULL, (const wchar_t **)&wbuf, wlen, NULL); | |
305 | posix_path = (char *) safemalloc(wlen+1); | |
306 | wcsrtombs(posix_path, (const wchar_t **)&wbuf, wlen, NULL); | |
307 | */ | |
308 | } else { | |
309 | int what = absolute_flag ? CCP_WIN_A_TO_POSIX : CCP_WIN_A_TO_POSIX | CCP_RELATIVE; | |
310 | posix_path = (char *) safemalloc (len + 260 + 1001); | |
311 | err = cygwin_conv_path(what, src_path, posix_path, len + 260 + 1001); | |
312 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ | |
313 | int newlen = cygwin_conv_path(what, src_path, posix_path, 0); | |
314 | posix_path = (char *) realloc(&posix_path, newlen); | |
315 | err = cygwin_conv_path(what, src_path, posix_path, newlen); | |
316 | } | |
317 | } | |
318 | #else | |
319 | posix_path = (char *) safemalloc (len + 260 + 1001); | |
15414d2b | 320 | if (absolute_flag) |
803e389c | 321 | err = cygwin_conv_to_full_posix_path(src_path, posix_path); |
15414d2b | 322 | else |
803e389c RU |
323 | err = cygwin_conv_to_posix_path(src_path, posix_path); |
324 | #endif | |
15414d2b | 325 | if (!err) { |
803e389c RU |
326 | EXTEND(SP, 1); |
327 | ST(0) = sv_2mortal(newSVpv(posix_path, 0)); | |
328 | if (isutf8) { /* src was utf-8, so result should also */ | |
329 | /* TODO: convert ANSI (local windows encoding) to utf-8 on cygwin-1.5 */ | |
330 | SvUTF8_on(ST(0)); | |
331 | } | |
332 | safefree(posix_path); | |
333 | XSRETURN(1); | |
15414d2b | 334 | } else { |
803e389c | 335 | safefree(posix_path); |
15414d2b RU |
336 | XSRETURN_UNDEF; |
337 | } | |
338 | } | |
339 | ||
340 | XS(XS_Cygwin_posix_to_win_path) | |
341 | { | |
342 | dXSARGS; | |
343 | int absolute_flag = 0; | |
344 | STRLEN len; | |
ba495c01 | 345 | int err = 0; |
803e389c RU |
346 | char *src_path, *win_path; |
347 | int isutf8 = 0; | |
15414d2b RU |
348 | |
349 | if (items < 1 || items > 2) | |
350 | Perl_croak(aTHX_ "Usage: Cygwin::posix_to_win_path(pathname, [absolute])"); | |
351 | ||
803e389c | 352 | src_path = SvPVx(ST(0), len); |
15414d2b RU |
353 | if (items == 2) |
354 | absolute_flag = SvTRUE(ST(1)); | |
355 | ||
356 | if (!len) | |
357 | Perl_croak(aTHX_ "can't convert empty path"); | |
803e389c RU |
358 | isutf8 = SvUTF8(ST(0)); |
359 | #if (CYGWIN_VERSION_API_MINOR >= 181) | |
360 | /* Check utf8 flag and use wide api then. | |
361 | Size calculation: On overflow let cygwin_conv_path calculate the final size. | |
362 | */ | |
363 | if (isutf8) { | |
364 | int what = absolute_flag ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_W | CCP_RELATIVE; | |
365 | int wlen = sizeof(wchar_t)*(len + 260 + 1001); | |
366 | wchar_t *wpath = (wchar_t *) safemalloc(sizeof(wchar_t)*len); | |
367 | wchar_t *wbuf = (wchar_t *) safemalloc(wlen); | |
368 | char *oldlocale = setlocale(LC_CTYPE, NULL); | |
369 | setlocale(LC_CTYPE, "utf-8"); | |
370 | if (!IN_BYTES) { | |
371 | mbstate_t mbs; | |
c80e42f3 | 372 | /* utf8_to_uvchr_buf(src_path, src_path + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */ |
803e389c RU |
373 | wlen = mbsrtowcs(wpath, (const char**)&src_path, wlen, &mbs); |
374 | if (wlen > 0) | |
375 | err = cygwin_conv_path(what, wpath, wbuf, wlen); | |
376 | } else { /* use bytes; assume already ucs-2 encoded bytestream */ | |
377 | err = cygwin_conv_path(what, src_path, wbuf, wlen); | |
378 | } | |
379 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ | |
380 | int newlen = cygwin_conv_path(what, wpath, wbuf, 0); | |
381 | wbuf = (wchar_t *) realloc(&wbuf, newlen); | |
382 | err = cygwin_conv_path(what, wpath, wbuf, newlen); | |
383 | wlen = newlen; | |
384 | } | |
385 | /* also see utf8.c: Perl_utf16_to_utf8() or Encoding::_bytes_to_utf8(sv, "UCS-2BE"); */ | |
386 | wlen = wcsrtombs(NULL, (const wchar_t **)&wbuf, wlen, NULL); | |
387 | win_path = (char *) safemalloc(wlen+1); | |
388 | wcsrtombs(win_path, (const wchar_t **)&wbuf, wlen, NULL); | |
389 | if (oldlocale) setlocale(LC_CTYPE, oldlocale); | |
390 | else setlocale(LC_CTYPE, "C"); | |
391 | } else { | |
392 | int what = absolute_flag ? CCP_POSIX_TO_WIN_A : CCP_POSIX_TO_WIN_A | CCP_RELATIVE; | |
393 | win_path = (char *) safemalloc(len + 260 + 1001); | |
394 | err = cygwin_conv_path(what, src_path, win_path, len + 260 + 1001); | |
395 | if (err == ENOSPC) { /* our space assumption was wrong, not enough space */ | |
396 | int newlen = cygwin_conv_path(what, src_path, win_path, 0); | |
397 | win_path = (char *) realloc(&win_path, newlen); | |
398 | err = cygwin_conv_path(what, src_path, win_path, newlen); | |
399 | } | |
400 | } | |
401 | #else | |
402 | if (isutf8) | |
403 | Perl_warn(aTHX_ "can't convert utf8 path"); | |
404 | win_path = (char *) safemalloc(len + 260 + 1001); | |
15414d2b | 405 | if (absolute_flag) |
803e389c | 406 | err = cygwin_conv_to_full_win32_path(src_path, win_path); |
15414d2b | 407 | else |
803e389c RU |
408 | err = cygwin_conv_to_win32_path(src_path, win_path); |
409 | #endif | |
15414d2b | 410 | if (!err) { |
803e389c RU |
411 | EXTEND(SP, 1); |
412 | ST(0) = sv_2mortal(newSVpv(win_path, 0)); | |
413 | if (isutf8) { | |
414 | SvUTF8_on(ST(0)); | |
415 | } | |
416 | safefree(win_path); | |
417 | XSRETURN(1); | |
15414d2b | 418 | } else { |
803e389c | 419 | safefree(win_path); |
15414d2b RU |
420 | XSRETURN_UNDEF; |
421 | } | |
422 | } | |
423 | ||
a25ce5f3 RU |
424 | XS(XS_Cygwin_mount_table) |
425 | { | |
426 | dXSARGS; | |
427 | struct mntent *mnt; | |
428 | ||
429 | if (items != 0) | |
430 | Perl_croak(aTHX_ "Usage: Cygwin::mount_table"); | |
431 | /* => array of [mnt_dir mnt_fsname mnt_type mnt_opts] */ | |
432 | ||
433 | setmntent (0, 0); | |
434 | while ((mnt = getmntent (0))) { | |
435 | AV* av = newAV(); | |
436 | av_push(av, newSVpvn(mnt->mnt_dir, strlen(mnt->mnt_dir))); | |
437 | av_push(av, newSVpvn(mnt->mnt_fsname, strlen(mnt->mnt_fsname))); | |
438 | av_push(av, newSVpvn(mnt->mnt_type, strlen(mnt->mnt_type))); | |
439 | av_push(av, newSVpvn(mnt->mnt_opts, strlen(mnt->mnt_opts))); | |
440 | XPUSHs(sv_2mortal(newRV_noinc((SV*)av))); | |
441 | } | |
442 | endmntent (0); | |
443 | PUTBACK; | |
444 | } | |
445 | ||
446 | XS(XS_Cygwin_mount_flags) | |
447 | { | |
448 | dXSARGS; | |
449 | char *pathname; | |
803e389c RU |
450 | char flags[PATH_MAX]; |
451 | flags[0] = '\0'; | |
a25ce5f3 RU |
452 | |
453 | if (items != 1) | |
803e389c | 454 | Perl_croak(aTHX_ "Usage: Cygwin::mount_flags( mnt_dir | '/cygdrive' )"); |
a25ce5f3 RU |
455 | |
456 | pathname = SvPV_nolen(ST(0)); | |
74dc058d | 457 | |
a25ce5f3 | 458 | if (!strcmp(pathname, "/cygdrive")) { |
803e389c RU |
459 | char user[PATH_MAX]; |
460 | char system[PATH_MAX]; | |
461 | char user_flags[PATH_MAX]; | |
462 | char system_flags[PATH_MAX]; | |
74dc058d | 463 | |
803e389c RU |
464 | cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, |
465 | user_flags, system_flags); | |
74dc058d JH |
466 | |
467 | if (strlen(user) > 0) { | |
468 | sprintf(flags, "%s,cygdrive,%s", user_flags, user); | |
469 | } else { | |
470 | sprintf(flags, "%s,cygdrive,%s", system_flags, system); | |
471 | } | |
472 | ||
a25ce5f3 RU |
473 | ST(0) = sv_2mortal(newSVpv(flags, 0)); |
474 | XSRETURN(1); | |
74dc058d | 475 | |
a25ce5f3 RU |
476 | } else { |
477 | struct mntent *mnt; | |
803e389c | 478 | int found = 0; |
a25ce5f3 RU |
479 | setmntent (0, 0); |
480 | while ((mnt = getmntent (0))) { | |
481 | if (!strcmp(pathname, mnt->mnt_dir)) { | |
482 | strcpy(flags, mnt->mnt_type); | |
483 | if (strlen(mnt->mnt_opts) > 0) { | |
484 | strcat(flags, ","); | |
485 | strcat(flags, mnt->mnt_opts); | |
486 | } | |
803e389c | 487 | found++; |
a25ce5f3 RU |
488 | break; |
489 | } | |
490 | } | |
491 | endmntent (0); | |
803e389c RU |
492 | |
493 | /* Check if arg is the current volume moint point if not default, | |
494 | * and then use CW_GET_CYGDRIVE_INFO also. | |
495 | */ | |
496 | if (!found) { | |
497 | char user[PATH_MAX]; | |
498 | char system[PATH_MAX]; | |
499 | char user_flags[PATH_MAX]; | |
500 | char system_flags[PATH_MAX]; | |
501 | ||
502 | cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, | |
503 | user_flags, system_flags); | |
504 | ||
505 | if (strlen(user) > 0) { | |
506 | if (strcmp(user,pathname)) { | |
507 | sprintf(flags, "%s,cygdrive,%s", user_flags, user); | |
508 | found++; | |
509 | } | |
510 | } else { | |
511 | if (strcmp(user,pathname)) { | |
512 | sprintf(flags, "%s,cygdrive,%s", system_flags, system); | |
513 | found++; | |
514 | } | |
515 | } | |
516 | } | |
517 | if (found) { | |
518 | ST(0) = sv_2mortal(newSVpv(flags, 0)); | |
519 | XSRETURN(1); | |
520 | } else { | |
521 | XSRETURN_UNDEF; | |
522 | } | |
a25ce5f3 RU |
523 | } |
524 | } | |
525 | ||
15414d2b RU |
526 | XS(XS_Cygwin_is_binmount) |
527 | { | |
528 | dXSARGS; | |
529 | char *pathname; | |
530 | ||
531 | if (items != 1) | |
532 | Perl_croak(aTHX_ "Usage: Cygwin::is_binmount(pathname)"); | |
533 | ||
534 | pathname = SvPV_nolen(ST(0)); | |
535 | ||
536 | ST(0) = boolSV(cygwin_internal(CW_GET_BINMODE, pathname)); | |
537 | XSRETURN(1); | |
538 | } | |
539 | ||
286f8194 RU |
540 | XS(XS_Cygwin_sync_winenv){ cygwin_internal(CW_SYNC_WINENV); } |
541 | ||
5db16f6a EF |
542 | void |
543 | init_os_extras(void) | |
544 | { | |
5db16f6a | 545 | dTHX; |
a4ec4e68 | 546 | char const *file = __FILE__; |
9fb265f7 | 547 | void *handle; |
5db16f6a EF |
548 | |
549 | newXS("Cwd::cwd", Cygwin_cwd, file); | |
15414d2b RU |
550 | newXSproto("Cygwin::winpid_to_pid", XS_Cygwin_winpid_to_pid, file, "$"); |
551 | newXSproto("Cygwin::pid_to_winpid", XS_Cygwin_pid_to_winpid, file, "$"); | |
552 | newXSproto("Cygwin::win_to_posix_path", XS_Cygwin_win_to_posix_path, file, "$;$"); | |
553 | newXSproto("Cygwin::posix_to_win_path", XS_Cygwin_posix_to_win_path, file, "$;$"); | |
a25ce5f3 RU |
554 | newXSproto("Cygwin::mount_table", XS_Cygwin_mount_table, file, ""); |
555 | newXSproto("Cygwin::mount_flags", XS_Cygwin_mount_flags, file, "$"); | |
15414d2b | 556 | newXSproto("Cygwin::is_binmount", XS_Cygwin_is_binmount, file, "$"); |
286f8194 | 557 | newXS("Cygwin::sync_winenv", XS_Cygwin_sync_winenv, file); |
78ff2d7b | 558 | |
9fb265f7 JD |
559 | /* Initialize Win32CORE if it has been statically linked. */ |
560 | handle = dlopen(NULL, RTLD_LAZY); | |
561 | if (handle) { | |
562 | void (*pfn_init)(pTHX); | |
563 | pfn_init = (void (*)(pTHX))dlsym(handle, "init_Win32CORE"); | |
564 | if (pfn_init) | |
565 | pfn_init(aTHX); | |
566 | dlclose(handle); | |
78ff2d7b | 567 | } |
5db16f6a | 568 | } |