This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix cygwin build
[perl5.git] / cygwin / cygwin.c
index 0f5fe1d..bbb3e1a 100644 (file)
@@ -2,6 +2,7 @@
  * Cygwin extras
  */
 
+#define PERLIO_NOT_STDIO 0
 #include "EXTERN.h"
 #include "perl.h"
 #undef USE_DYNAMIC_LOADING
@@ -89,15 +90,17 @@ int
 do_spawn (char *cmd)
 {
     dTHX;
-    char const **a;
+    char const **argv, **a;
     char *s;
     char const *metachars = "$&*(){}[]'\";\\?>|<~`\n";
     const char *command[4];
+    int result;
 
+    ENTER;
     while (*cmd && isSPACE(*cmd))
        cmd++;
 
-    if (strnEQ (cmd,"/bin/sh",7) && isSPACE (cmd[7]))
+    if (strBEGINs (cmd,"/bin/sh") && isSPACE (cmd[7]))
         cmd+=5;
 
     /* save an extra exec if possible */
@@ -106,11 +109,11 @@ do_spawn (char *cmd)
        goto doshell;
     if (*cmd=='.' && isSPACE (cmd[1]))
        goto doshell;
-    if (strnEQ (cmd,"exec",4) && isSPACE (cmd[4]))
+    if (strBEGINs (cmd,"exec") && isSPACE (cmd[4]))
        goto doshell;
     for (s=cmd; *s && isALPHA (*s); s++) ;     /* catch VAR=val gizmo */
-       if (*s=='=')
-           goto doshell;
+    if (*s=='=')
+        goto doshell;
 
     for (s=cmd; *s; s++)
        if (strchr (metachars,*s))
@@ -126,13 +129,16 @@ do_spawn (char *cmd)
            command[2] = cmd;
            command[3] = NULL;
 
-           return do_spawnvp("sh",command);
+           result = do_spawnvp("sh",command);
+           goto leave;
        }
 
-    Newx (PL_Argv,(s-cmd)/2+2,char*);
-    PL_Cmd=savepvn (cmd,s-cmd);
-    a=PL_Argv;
-    for (s=PL_Cmd; *s;) {
+    Newx (argv, (s-cmd)/2+2, const char*);
+    SAVEFREEPV(argv);
+    cmd=savepvn (cmd,s-cmd);
+    SAVEFREEPV(cmd);
+    a=argv;
+    for (s=cmd; *s;) {
        while (*s && isSPACE (*s)) s++;
        if (*s)
            *(a++)=s;
@@ -141,10 +147,13 @@ do_spawn (char *cmd)
            *s++='\0';
     }
     *a = (char*)NULL;
-    if (!PL_Argv[0])
-        return -1;
-
-    return do_spawnvp(PL_Argv[0],(const char * const *)PL_Argv);
+    if (!argv[0])
+        result = -1;
+    else
+       result = do_spawnvp(argv[0],(const char * const *)argv);
+leave:
+    LEAVE;
+    return result;
 }
 
 #if (CYGWIN_VERSION_API_MINOR >= 181)
@@ -153,16 +162,26 @@ wide_to_utf8(const wchar_t *wbuf)
 {
     char *buf;
     int wlen = 0;
-    char *oldlocale = setlocale(LC_CTYPE, NULL);
+    char *oldlocale;
+
+    /* Here and elsewhere in this file, we have a critical section to prevent
+     * another thread from changing the locale out from under us.  XXX But why
+     * not just use uvchr_to_utf8? */
+    SETLOCALE_LOCK;
+
+    oldlocale = setlocale(LC_CTYPE, NULL);
     setlocale(LC_CTYPE, "utf-8");
 
-    /* uvuni_to_utf8(buf, chr) or Encoding::_bytes_to_utf8(sv, "UCS-2BE"); */
+    /* uvchr_to_utf8(buf, chr) or Encoding::_bytes_to_utf8(sv, "UCS-2BE"); */
     wlen = wcsrtombs(NULL, (const wchar_t **)&wbuf, wlen, NULL);
     buf = (char *) safemalloc(wlen+1);
     wcsrtombs(buf, (const wchar_t **)&wbuf, wlen, NULL);
 
     if (oldlocale) setlocale(LC_CTYPE, oldlocale);
     else setlocale(LC_CTYPE, "C");
+
+    SETLOCALE_UNLOCK;
+
     return buf;
 }
 
@@ -171,16 +190,23 @@ utf8_to_wide(const char *buf)
 {
     wchar_t *wbuf;
     mbstate_t mbs;
-    char *oldlocale = setlocale(LC_CTYPE, NULL);
+    char *oldlocale;
     int wlen = sizeof(wchar_t)*strlen(buf);
 
+    SETLOCALE_LOCK;
+
+    oldlocale = setlocale(LC_CTYPE, NULL);
+
     setlocale(LC_CTYPE, "utf-8");
     wbuf = (wchar_t *) safemalloc(wlen);
-    /* utf8_to_uvuni(pathname, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */
+    /* utf8_to_uvchr_buf(pathname, pathname + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */
     wlen = mbsrtowcs(wbuf, (const char**)&buf, wlen, &mbs);
 
     if (oldlocale) setlocale(LC_CTYPE, oldlocale);
     else setlocale(LC_CTYPE, "C");
+
+    SETLOCALE_UNLOCK;
+
     return wbuf;
 }
 #endif /* cygwin 1.7 */
@@ -191,7 +217,7 @@ XS(Cygwin_cwd)
     dXSARGS;
     char *cwd;
 
-    /* See http://rt.perl.org/rt3/Ticket/Display.html?id=38628 
+    /* See https://github.com/Perl/perl5/issues/8345
        There is Cwd->cwd() usage in the wild, and previous versions didn't die.
      */
     if(items > 1)
@@ -199,9 +225,7 @@ XS(Cygwin_cwd)
     if((cwd = getcwd(NULL, -1))) {
        ST(0) = sv_2mortal(newSVpv(cwd, 0));
        free(cwd);
-#ifndef INCOMPLETE_TAINTS
        SvTAINTED_on(ST(0));
-#endif
        XSRETURN(1);
     }
     XSRETURN_UNDEF;
@@ -254,7 +278,7 @@ XS(XS_Cygwin_win_to_posix_path)
     dXSARGS;
     int absolute_flag = 0;
     STRLEN len;
-    int err;
+    int err = 0;
     char *src_path;
     char *posix_path;
     int isutf8 = 0;
@@ -276,19 +300,25 @@ XS(XS_Cygwin_win_to_posix_path)
      */
     if (isutf8) {
        int what = absolute_flag ? CCP_WIN_W_TO_POSIX : CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
-       int wlen = sizeof(wchar_t)*(len + 260 + 1001);
+       STRLEN wlen = sizeof(wchar_t)*(len + 260 + 1001);
        wchar_t *wpath = (wchar_t *) safemalloc(sizeof(wchar_t)*len);
        wchar_t *wbuf = (wchar_t *) safemalloc(wlen);
        if (!IN_BYTES) {
            mbstate_t mbs;
-            char *oldlocale = setlocale(LC_CTYPE, NULL);
+            char *oldlocale;
+
+            SETLOCALE_LOCK;
+
+            oldlocale = setlocale(LC_CTYPE, NULL);
             setlocale(LC_CTYPE, "utf-8");
-           /* utf8_to_uvuni(src_path, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */
+           /* utf8_to_uvchr_buf(src_path, src_path + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */
            wlen = mbsrtowcs(wpath, (const char**)&src_path, wlen, &mbs);
            if (wlen > 0)
                err = cygwin_conv_path(what, wpath, wbuf, wlen);
             if (oldlocale) setlocale(LC_CTYPE, oldlocale);
             else setlocale(LC_CTYPE, "C");
+
+            SETLOCALE_UNLOCK;
        } else { /* use bytes; assume already ucs-2 encoded bytestream */
            err = cygwin_conv_path(what, src_path, wbuf, wlen);
        }
@@ -300,7 +330,7 @@ XS(XS_Cygwin_win_to_posix_path)
        }
        /* utf16_to_utf8(*p, *d, bytlen, *newlen) */
        posix_path = (char *) safemalloc(wlen*3);
-       Perl_utf16_to_utf8(aTHX_ (U8*)&wpath, (U8*)posix_path, (I32)wlen*2, (I32*)&len);
+       Perl_utf16_to_utf8(aTHX_ (U8*)&wpath, (U8*)posix_path, wlen*2, &len);
        /*
        wlen = wcsrtombs(NULL, (const wchar_t **)&wbuf, wlen, NULL);
        posix_path = (char *) safemalloc(wlen+1);
@@ -343,7 +373,7 @@ XS(XS_Cygwin_posix_to_win_path)
     dXSARGS;
     int absolute_flag = 0;
     STRLEN len;
-    int err;
+    int err = 0;
     char *src_path, *win_path;
     int isutf8 = 0;
 
@@ -366,11 +396,15 @@ XS(XS_Cygwin_posix_to_win_path)
        int wlen = sizeof(wchar_t)*(len + 260 + 1001);
        wchar_t *wpath = (wchar_t *) safemalloc(sizeof(wchar_t)*len);
        wchar_t *wbuf = (wchar_t *) safemalloc(wlen);
-       char *oldlocale = setlocale(LC_CTYPE, NULL);
+       char *oldlocale;
+
+        SETLOCALE_LOCK;
+
+       oldlocale = setlocale(LC_CTYPE, NULL);
        setlocale(LC_CTYPE, "utf-8");
        if (!IN_BYTES) {
            mbstate_t mbs;
-           /* utf8_to_uvuni(src_path, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */
+           /* utf8_to_uvchr_buf(src_path, src_path + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */
            wlen = mbsrtowcs(wpath, (const char**)&src_path, wlen, &mbs);
            if (wlen > 0)
                err = cygwin_conv_path(what, wpath, wbuf, wlen);
@@ -389,6 +423,8 @@ XS(XS_Cygwin_posix_to_win_path)
        wcsrtombs(win_path, (const wchar_t **)&wbuf, wlen, NULL);
        if (oldlocale) setlocale(LC_CTYPE, oldlocale);
        else setlocale(LC_CTYPE, "C");
+
+        SETLOCALE_UNLOCK;
     } else {
        int what = absolute_flag ? CCP_POSIX_TO_WIN_A : CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
        win_path = (char *) safemalloc(len + 260 + 1001);
@@ -456,7 +492,7 @@ XS(XS_Cygwin_mount_flags)
 
     pathname = SvPV_nolen(ST(0));
 
-    if (!strcmp(pathname, "/cygdrive")) {
+    if (strEQ(pathname, "/cygdrive")) {
        char user[PATH_MAX];
        char system[PATH_MAX];
        char user_flags[PATH_MAX];
@@ -479,7 +515,7 @@ XS(XS_Cygwin_mount_flags)
        int found = 0;
        setmntent (0, 0);
        while ((mnt = getmntent (0))) {
-           if (!strcmp(pathname, mnt->mnt_dir)) {
+           if (strEQ(pathname, mnt->mnt_dir)) {
                strcpy(flags, mnt->mnt_type);
                if (strlen(mnt->mnt_opts) > 0) {
                    strcat(flags, ",");
@@ -504,12 +540,12 @@ XS(XS_Cygwin_mount_flags)
                             user_flags, system_flags);
 
            if (strlen(user) > 0) {
-               if (strcmp(user,pathname)) {
+               if (strNE(user,pathname)) {
                    sprintf(flags, "%s,cygdrive,%s", user_flags, user);
                    found++;
                }
            } else {
-               if (strcmp(user,pathname)) {
+               if (strNE(user,pathname)) {
                    sprintf(flags, "%s,cygdrive,%s", system_flags, system);
                    found++;
                }
@@ -538,6 +574,8 @@ XS(XS_Cygwin_is_binmount)
     XSRETURN(1);
 }
 
+XS(XS_Cygwin_sync_winenv){ cygwin_internal(CW_SYNC_WINENV); }
+
 void
 init_os_extras(void)
 {
@@ -553,6 +591,7 @@ init_os_extras(void)
     newXSproto("Cygwin::mount_table", XS_Cygwin_mount_table, file, "");
     newXSproto("Cygwin::mount_flags", XS_Cygwin_mount_flags, file, "$");
     newXSproto("Cygwin::is_binmount", XS_Cygwin_is_binmount, file, "$");
+    newXS("Cygwin::sync_winenv", XS_Cygwin_sync_winenv, file);
 
     /* Initialize Win32CORE if it has been statically linked. */
     handle = dlopen(NULL, RTLD_LAZY);