Having to pull in the whole Encode just to get SvUTF8()
[p5sagit/p5-mst-13.2.git] / win32 / win32.c
index 6f96431..083e98e 100644 (file)
@@ -15,7 +15,8 @@
 #define Win32_Winsock
 #endif
 #include <windows.h>
-#ifndef __MINGW32__    /* GCC/Mingw32-2.95.2 forgot the WINAPI on CommandLineToArgvW() */
+/* GCC-2.95.2/Mingw32-1.1 forgot the WINAPI on CommandLineToArgvW() */
+#if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1)       
 #  include <shellapi.h>
 #else
    LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCommandLine, int * pNumArgs);
@@ -60,8 +61,8 @@
 int _CRT_glob = 0;
 #endif
 
-#if defined(__MINGW32__)
-/* Mingw32 is missing some prototypes */
+#if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1)       
+/* Mingw32-1.1 is missing some prototypes */
 FILE * _wfopen(LPCWSTR wszFileName, LPCWSTR wszMode);
 FILE * _wfdopen(int nFd, LPCWSTR wszMode);
 FILE * _freopen(LPCWSTR wszFileName, LPCWSTR wszMode, FILE * pOldStream);
@@ -85,15 +86,13 @@ int _fcloseall();
 #  define win32_get_sitelib g_win32_get_sitelib
 #  undef win32_get_vendorlib
 #  define win32_get_vendorlib g_win32_get_vendorlib
-#  undef do_spawn
-#  define do_spawn g_do_spawn
 #  undef getlogin
 #  define getlogin g_getlogin
 #endif
 
 static void            get_shell(void);
 static long            tokenize(const char *str, char **dest, char ***destv);
-       int             do_spawn2(char *cmd, int exectype);
+static int             do_spawn2(pTHX_ char *cmd, int exectype);
 static BOOL            has_shell_metachars(char *ptr);
 static long            filetime_to_clock(PFILETIME ft);
 static BOOL            filetime_from_time(PFILETIME ft, time_t t);
@@ -507,7 +506,7 @@ get_shell(void)
         *     for).
         */
        const char* defaultshell = (IsWinNT()
-                                   ? "cmd.exe /x/c" : "command.com /c");
+                                   ? "cmd.exe /x/d/c" : "command.com /c");
        const char *usershell = PerlEnv_getenv("PERL5SHELL");
        w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
                                       &w32_perlshell_tokens,
@@ -516,12 +515,8 @@ get_shell(void)
 }
 
 int
-do_aspawn(void *vreally, void **vmark, void **vsp)
+Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp)
 {
-    dTHX;
-    SV *really = (SV*)vreally;
-    SV **mark = (SV**)vmark;
-    SV **sp = (SV**)vsp;
     char **argv;
     char *str;
     int status;
@@ -607,10 +602,9 @@ find_next_space(const char *s)
     return (char*)s;
 }
 
-int
-do_spawn2(char *cmd, int exectype)
+static int
+do_spawn2(pTHX_ char *cmd, int exectype)
 {
-    dTHX;
     char **a;
     char *s;
     char **argv;
@@ -700,21 +694,21 @@ do_spawn2(char *cmd, int exectype)
 }
 
 int
-do_spawn(char *cmd)
+Perl_do_spawn(pTHX_ char *cmd)
 {
-    return do_spawn2(cmd, EXECF_SPAWN);
+    return do_spawn2(aTHX_ cmd, EXECF_SPAWN);
 }
 
 int
-do_spawn_nowait(char *cmd)
+Perl_do_spawn_nowait(pTHX_ char *cmd)
 {
-    return do_spawn2(cmd, EXECF_SPAWN_NOWAIT);
+    return do_spawn2(aTHX_ cmd, EXECF_SPAWN_NOWAIT);
 }
 
 bool
 Perl_do_exec(pTHX_ char *cmd)
 {
-    do_spawn2(cmd, EXECF_EXEC);
+    do_spawn2(aTHX_ cmd, EXECF_EXEC);
     return FALSE;
 }
 
@@ -1918,6 +1912,8 @@ win32_async_check(pTHX)
     return ours;
 }
 
+/* This function will not return until the timeout has elapsed, or until
+ * one of the handles is ready. */
 DllExport DWORD
 win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD resultp)
 {
@@ -1942,10 +1938,7 @@ win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD result
         }
        if (result == WAIT_OBJECT_0 + count) {
            /* Message has arrived - check it */
-           if (win32_async_check(aTHX)) {
-               /* was one of ours */
-               break;
-           }
+           (void)win32_async_check(aTHX);
        }
        else {
           /* Not timeout or message - one of handles is ready */
@@ -2622,8 +2615,8 @@ win32_rewind(FILE *pf)
     return;
 }
 
-DllExport FILE*
-win32_tmpfile(void)
+DllExport int
+win32_tmpfd(void)
 {
     dTHX;
     char prefix[MAX_PATH+1];
@@ -2647,11 +2640,20 @@ win32_tmpfile(void)
 #endif
                    DEBUG_p(PerlIO_printf(Perl_debug_log,
                                          "Created tmpfile=%s\n",filename));
-                   return fdopen(fd, "w+b");
+                   return fd;
                }
            }
        }
     }
+    return -1;
+}
+
+DllExport FILE*
+win32_tmpfile(void)
+{
+    int fd = win32_tmpfd();
+    if (fd >= 0)
+       return win32_fdopen(fd, "w+b");
     return NULL;
 }
 
@@ -2756,6 +2758,12 @@ win32_popen(const char *command, const char *mode)
     if ((oldfd = win32_dup(stdfd)) == -1)
         goto cleanup;
 
+    /* save the old std handle (this needs to happen before the
+     * dup2(), since that might call SetStdHandle() too) */
+    OP_REFCNT_LOCK;
+    lock_held = 1;
+    old_h = GetStdHandle(nhandle);
+
     /* make stdfd go to child end of pipe (implicitly closes stdfd) */
     /* stdfd will be inherited by the child */
     if (win32_dup2(p[child], stdfd) == -1)
@@ -2764,10 +2772,7 @@ win32_popen(const char *command, const char *mode)
     /* close the child end in parent */
     win32_close(p[child]);
 
-    /* save the old std handle, and set the std handle */
-    OP_REFCNT_LOCK;
-    lock_held = 1;
-    old_h = GetStdHandle(nhandle);
+    /* set the new std handle (in case dup2() above didn't) */
     SetStdHandle(nhandle, (HANDLE)_get_osfhandle(stdfd));
 
     /* start the child */
@@ -2776,17 +2781,18 @@ win32_popen(const char *command, const char *mode)
        if ((childpid = do_spawn_nowait((char*)command)) == -1)
            goto cleanup;
 
-       /* restore the old std handle */
+       /* revert stdfd to whatever it was before */
+       if (win32_dup2(oldfd, stdfd) == -1)
+           goto cleanup;
+
+       /* restore the old std handle (this needs to happen after the
+        * dup2(), since that might call SetStdHandle() too */
        if (lock_held) {
            SetStdHandle(nhandle, old_h);
            OP_REFCNT_UNLOCK;
            lock_held = 0;
        }
 
-       /* revert stdfd to whatever it was before */
-       if (win32_dup2(oldfd, stdfd) == -1)
-           goto cleanup;
-
        /* close saved handle */
        win32_close(oldfd);
 
@@ -3079,6 +3085,55 @@ win32_setmode(int fd, int mode)
     return setmode(fd, mode);
 }
 
+DllExport int
+win32_chsize(int fd, Off_t size)
+{
+#if defined(WIN64) || defined(USE_LARGE_FILES)
+    int retval = 0;
+    Off_t cur, end, extend;
+
+    cur = win32_tell(fd);
+    if (cur < 0)
+       return -1;
+    end = win32_lseek(fd, 0, SEEK_END);
+    if (end < 0)
+       return -1;
+    extend = size - end;
+    if (extend == 0) {
+       /* do nothing */
+    }
+    else if (extend > 0) {
+       /* must grow the file, padding with nulls */
+       char b[4096];
+       int oldmode = win32_setmode(fd, O_BINARY);
+       size_t count;
+       memset(b, '\0', sizeof(b));
+       do {
+           count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend;
+           count = win32_write(fd, b, count);
+           if (count < 0) {
+               retval = -1;
+               break;
+           }
+       } while ((extend -= count) > 0);
+       win32_setmode(fd, oldmode);
+    }
+    else {
+       /* shrink the file */
+       win32_lseek(fd, size, SEEK_SET);
+       if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) {
+           errno = EACCES;
+           retval = -1;
+       }
+    }
+finish:
+    win32_lseek(fd, cur, SEEK_SET);
+    return retval;
+#else
+    return chsize(fd, size);
+#endif
+}
+
 DllExport Off_t
 win32_lseek(int fd, Off_t offset, int origin)
 {
@@ -3553,7 +3608,9 @@ create_command_line(char *cname, STRLEN clen, const char * const *args)
 
        if (!extra_quotes
            && cmd_shell
-           && (stricmp(arg, "/x/c") == 0 || stricmp(arg, "/c") == 0))
+           && curlen >= 2
+           && *arg  == '/'     /* see if arg is "/c", "/x/c", "/x/d/c" etc. */
+           && stricmp(arg+curlen-2, "/c") == 0)
        {
            /* is there a next argument? */
            if (args[index+1]) {
@@ -3925,7 +3982,7 @@ win32_execvp(const char *cmdname, const char *const *argv)
     /* if this is a pseudo-forked child, we just want to spawn
      * the new program, and return */
     if (w32_pseudo_id) {
-       int status = win32_spawnvp(P_WAIT, cmdname, (char *const *)argv);
+       int status = win32_spawnvp(P_WAIT, cmdname, (const char *const *)argv);
        if (status != -1) {
            my_exit(status);
            return 0;
@@ -4383,11 +4440,11 @@ XS(w32_DomainName)
        /* NERR_Success *is* 0*/
        if (0 == pfnNetWkstaGetInfo(NULL, 100, &pwi)) {
            if (pwi->wki100_langroup && *(pwi->wki100_langroup)) {
-               WideCharToMultiByte(CP_ACP, NULL, pwi->wki100_langroup,
+               WideCharToMultiByte(CP_ACP, 0, pwi->wki100_langroup,
                                    -1, (LPSTR)dname, dnamelen, NULL, NULL);
            }
            else {
-               WideCharToMultiByte(CP_ACP, NULL, pwi->wki100_computername,
+               WideCharToMultiByte(CP_ACP, 0, pwi->wki100_computername,
                                    -1, (LPSTR)dname, dnamelen, NULL, NULL);
            }
            pfnNetApiBufferFree(pwi);
@@ -4601,6 +4658,7 @@ XS(w32_GetShortPathName)
     } while (len >= SvLEN(shortpath) && sv_grow(shortpath,len+1));
     if (len) {
        SvCUR_set(shortpath,len);
+       *SvEND(shortpath) = '\0';
        ST(0) = shortpath;
        XSRETURN(1);
     }
@@ -4634,11 +4692,17 @@ XS(w32_GetFullPathName)
     if (len) {
        if (GIMME_V == G_ARRAY) {
            EXTEND(SP,1);
-           XST_mPV(1,filepart);
-           len = filepart - SvPVX(fullpath);
+           if (filepart) {
+               XST_mPV(1,filepart);
+               len = filepart - SvPVX(fullpath);
+           }
+           else {
+               XST_mPVN(1,"",0);
+           }
            items = 2;
        }
        SvCUR_set(fullpath,len);
+       *SvEND(fullpath) = '\0';
        ST(0) = fullpath;
        XSRETURN(items);
     }
@@ -4757,12 +4821,8 @@ win32_signal_context(void)
     }
     return my_perl;
 #else
-#ifdef USE_5005THREADS
-    return aTHX;
-#else
     return PL_curinterp;
 #endif
-#endif
 }
 
 
@@ -4774,10 +4834,6 @@ win32_ctrlhandler(DWORD dwCtrlType)
 
     if (!my_perl)
        return FALSE;
-#else
-#ifdef USE_5005THREADS
-    dTHX;
-#endif
 #endif
 
     switch(dwCtrlType) {
@@ -4839,6 +4895,13 @@ Perl_win32_init(int *argcp, char ***argvp)
 }
 
 void
+Perl_win32_term(void)
+{
+    OP_REFCNT_TERM;
+    MALLOC_TERM;
+}
+
+void
 win32_get_child_IO(child_IO_table* ptbl)
 {
     ptbl->childStdIn   = GetStdHandle(STD_INPUT_HANDLE);