updated w32 code by tulloh
authorRoland McGrath <roland@redhat.com>
Fri, 19 Jul 1996 21:41:07 +0000 (21:41 +0000)
committerRoland McGrath <roland@redhat.com>
Fri, 19 Jul 1996 21:41:07 +0000 (21:41 +0000)
13 files changed:
ChangeLog
w32/compat/dirent.c
w32/include/dirent.h
w32/include/pathstuff.h
w32/include/sub_proc.h
w32/include/w32err.h
w32/pathstuff.c
w32/subproc/NMakefile
w32/subproc/build.bat
w32/subproc/misc.c
w32/subproc/proc.h
w32/subproc/sub_proc.c
w32/subproc/w32err.c

index d57aa7c..90f690c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Jul 19 16:57:27 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+       * GNUmakefile (win32files): New variable.
+       (distfiles): Add it.
+       * w32: Updated by Rob Tulloh.
+
+       * makefile.vms (LOADLIBES): Fix typo.
+
 Sun Jul 14 12:59:27 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
 
        * job.c (construct_command_argv_internal): Fix up #else, #endifs.
index f516eb9..25a7b74 100644 (file)
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include "dirent.h"
-
-
-DIR*
-opendir(const char* pDirName)
-{
-       struct stat sb;
-       DIR*    pDir;
-       char*   pEndDirName;
-       int     nBufferLen;
-
-       /* sanity checks */
-       if (!pDirName) {
-               errno = EINVAL;
-               return NULL;
-       }
-       if (stat(pDirName, &sb) != 0) {
-               errno = ENOENT;
-               return NULL;
-       }
-       if ((sb.st_mode & S_IFMT) != S_IFDIR) {
-               errno = ENOTDIR;
-               return NULL;
-       }
-
-       /* allocate a DIR structure to return */
-       pDir = (DIR *) malloc(sizeof (DIR));
-
-       if (!pDir)
-               return NULL;
-
-       /* input directory name length */
-       nBufferLen = strlen(pDirName);
-
-       /* copy input directory name to DIR buffer */
-       strcpy(pDir->dir_pDirectoryName, pDirName);
-
-       /* point to end of the copied directory name */
-       pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];
-
-       /* if directory name did not end in '/' or '\', add '/' */
-       if ((*pEndDirName != '/') && (*pEndDirName != '\\')) {
-               pEndDirName++;
-               *pEndDirName = '/';
-       }
-
-       /* now append the wildcard character to the buffer */
-       pEndDirName++;
-       *pEndDirName = '*';
-       pEndDirName++;
-       *pEndDirName = '\0';
-
-       /* other values defaulted */
-       pDir->dir_nNumFiles = 0;
-       pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;    
-       pDir->dir_ulCookie = __DIRENT_COOKIE;
-
-       return pDir;
-}
-
-void
-closedir(DIR *pDir)
-{
-       /* got a valid pointer? */
-       if (!pDir) {
-               errno = EINVAL;
-               return;
-       }
-
-       /* sanity check that this is a DIR pointer */
-       if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
-               errno = EINVAL;
-               return;
-       }
-
-       /* close the WIN32 directory handle */
-       if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
-               FindClose(pDir->dir_hDirHandle);
-
-       free(pDir);
-
-       return;
-}
-
-struct dirent *
-readdir(DIR* pDir)
-{
-       WIN32_FIND_DATA wfdFindData;
-
-       if (!pDir) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       /* sanity check that this is a DIR pointer */
-       if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (pDir->dir_nNumFiles == 0) {
-               pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);
-               if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)
-                       return NULL;
-       } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))
-                       return NULL;
-
-       /* bump count for next call to readdir() or telldir() */
-       pDir->dir_nNumFiles++;
-
-       /* fill in struct dirent values */
-       pDir->dir_sdReturn.d_ino = -1;
-       strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
-
-       return &pDir->dir_sdReturn;
-}
-
-void
-rewinddir(DIR* pDir)
-{
-       if (!pDir) {
-               errno = EINVAL;
-               return;
-       }
-
-       /* sanity check that this is a DIR pointer */
-       if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
-               errno = EINVAL;
-               return;
-       }
-
-       /* close the WIN32 directory handle */
-       if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
-               if (!FindClose(pDir->dir_hDirHandle))
-                       errno = EBADF;
-
-       /* reset members which control readdir() */
-       pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
-       pDir->dir_nNumFiles = 0;
-
-       return;
-}
-
-int
-telldir(DIR* pDir)
-{
-       if (!pDir) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       /* sanity check that this is a DIR pointer */
-       if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       /* return number of times readdir() called */
-       return pDir->dir_nNumFiles;
-}
-
-void
-seekdir(DIR* pDir, long nPosition)
-{
-       if (!pDir)
-               return;
-
-       /* sanity check that this is a DIR pointer */
-       if (pDir->dir_ulCookie != __DIRENT_COOKIE)
-               return;
-
-       /* go back to beginning of directory */
-       rewinddir(pDir);
-
-       /* loop until we have found position we care about */
-       for (--nPosition; nPosition && readdir(pDir); nPosition--);
-
-       /* flag invalid nPosition value */
-       if (nPosition)
-               errno = EINVAL;
-
-       return;
-}
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <errno.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "dirent.h"\r
+\r
+\r
+DIR*\r
+opendir(const char* pDirName)\r
+{\r
+       struct stat sb;\r
+       DIR*    pDir;\r
+       char*   pEndDirName;\r
+       int     nBufferLen;\r
+\r
+       /* sanity checks */\r
+       if (!pDirName) {\r
+               errno = EINVAL;\r
+               return NULL;\r
+       }\r
+       if (stat(pDirName, &sb) != 0) {\r
+               errno = ENOENT;\r
+               return NULL;\r
+       }\r
+       if ((sb.st_mode & S_IFMT) != S_IFDIR) {\r
+               errno = ENOTDIR;\r
+               return NULL;\r
+       }\r
+\r
+       /* allocate a DIR structure to return */\r
+       pDir = (DIR *) malloc(sizeof (DIR));\r
+\r
+       if (!pDir)\r
+               return NULL;\r
+\r
+       /* input directory name length */\r
+       nBufferLen = strlen(pDirName);\r
+\r
+       /* copy input directory name to DIR buffer */\r
+       strcpy(pDir->dir_pDirectoryName, pDirName);\r
+\r
+       /* point to end of the copied directory name */\r
+       pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];\r
+\r
+       /* if directory name did not end in '/' or '\', add '/' */\r
+       if ((*pEndDirName != '/') && (*pEndDirName != '\\')) {\r
+               pEndDirName++;\r
+               *pEndDirName = '/';\r
+       }\r
+\r
+       /* now append the wildcard character to the buffer */\r
+       pEndDirName++;\r
+       *pEndDirName = '*';\r
+       pEndDirName++;\r
+       *pEndDirName = '\0';\r
+\r
+       /* other values defaulted */\r
+       pDir->dir_nNumFiles = 0;\r
+       pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;    \r
+       pDir->dir_ulCookie = __DIRENT_COOKIE;\r
+\r
+       return pDir;\r
+}\r
+\r
+void\r
+closedir(DIR *pDir)\r
+{\r
+       /* got a valid pointer? */\r
+       if (!pDir) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+\r
+       /* sanity check that this is a DIR pointer */\r
+       if (pDir->dir_ulCookie != __DIRENT_COOKIE) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+\r
+       /* close the WIN32 directory handle */\r
+       if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)\r
+               FindClose(pDir->dir_hDirHandle);\r
+\r
+       free(pDir);\r
+\r
+       return;\r
+}\r
+\r
+struct dirent *\r
+readdir(DIR* pDir)\r
+{\r
+       WIN32_FIND_DATA wfdFindData;\r
+\r
+       if (!pDir) {\r
+               errno = EINVAL;\r
+               return NULL;\r
+       }\r
+\r
+       /* sanity check that this is a DIR pointer */\r
+       if (pDir->dir_ulCookie != __DIRENT_COOKIE) {\r
+               errno = EINVAL;\r
+               return NULL;\r
+       }\r
+\r
+       if (pDir->dir_nNumFiles == 0) {\r
+               pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);\r
+               if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)\r
+                       return NULL;\r
+       } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))\r
+                       return NULL;\r
+\r
+       /* bump count for next call to readdir() or telldir() */\r
+       pDir->dir_nNumFiles++;\r
+\r
+       /* fill in struct dirent values */\r
+       pDir->dir_sdReturn.d_ino = -1;\r
+       strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);\r
+\r
+       return &pDir->dir_sdReturn;\r
+}\r
+\r
+void\r
+rewinddir(DIR* pDir)\r
+{\r
+       if (!pDir) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+\r
+       /* sanity check that this is a DIR pointer */\r
+       if (pDir->dir_ulCookie != __DIRENT_COOKIE) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+\r
+       /* close the WIN32 directory handle */\r
+       if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)\r
+               if (!FindClose(pDir->dir_hDirHandle))\r
+                       errno = EBADF;\r
+\r
+       /* reset members which control readdir() */\r
+       pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;\r
+       pDir->dir_nNumFiles = 0;\r
+\r
+       return;\r
+}\r
+\r
+int\r
+telldir(DIR* pDir)\r
+{\r
+       if (!pDir) {\r
+               errno = EINVAL;\r
+               return -1;\r
+       }\r
+\r
+       /* sanity check that this is a DIR pointer */\r
+       if (pDir->dir_ulCookie != __DIRENT_COOKIE) {\r
+               errno = EINVAL;\r
+               return -1;\r
+       }\r
+\r
+       /* return number of times readdir() called */\r
+       return pDir->dir_nNumFiles;\r
+}\r
+\r
+void\r
+seekdir(DIR* pDir, long nPosition)\r
+{\r
+       if (!pDir)\r
+               return;\r
+\r
+       /* sanity check that this is a DIR pointer */\r
+       if (pDir->dir_ulCookie != __DIRENT_COOKIE)\r
+               return;\r
+\r
+       /* go back to beginning of directory */\r
+       rewinddir(pDir);\r
+\r
+       /* loop until we have found position we care about */\r
+       for (--nPosition; nPosition && readdir(pDir); nPosition--);\r
+\r
+       /* flag invalid nPosition value */\r
+       if (nPosition)\r
+               errno = EINVAL;\r
+\r
+       return;\r
+}\r
index 6bb7fbd..ccc1800 100644 (file)
@@ -1,37 +1,37 @@
-#ifndef _DIRENT_H
-#define _DIRENT_H
-
-#include <stdlib.h>
-#include <windows.h>
-#include <limits.h>
-#include <sys/types.h>
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-#define __DIRENT_COOKIE 0xfefeabab
-
-
-struct dirent
-{
-  ino_t d_ino;                         /* unused - no equivalent on WIN32 */
-  char d_name[NAME_MAX+1];
-};
-
-typedef struct dir_struct {
-       ULONG   dir_ulCookie;
-       HANDLE  dir_hDirHandle;
-       DWORD   dir_nNumFiles;
-       char    dir_pDirectoryName[NAME_MAX+1];
-       struct dirent dir_sdReturn;
-} DIR;
-
-DIR *opendir(const char *);
-struct dirent *readdir(DIR *);
-void rewinddir(DIR *);
-void closedir(DIR *);
-int telldir(DIR *);
-void seekdir(DIR *, long);
-
-#endif
+#ifndef _DIRENT_H\r
+#define _DIRENT_H\r
+\r
+#include <stdlib.h>\r
+#include <windows.h>\r
+#include <limits.h>\r
+#include <sys/types.h>\r
+\r
+#ifndef NAME_MAX\r
+#define NAME_MAX 255\r
+#endif\r
+\r
+#define __DIRENT_COOKIE 0xfefeabab\r
+\r
+\r
+struct dirent\r
+{\r
+  ino_t d_ino;                         /* unused - no equivalent on WIN32 */\r
+  char d_name[NAME_MAX+1];\r
+};\r
+\r
+typedef struct dir_struct {\r
+       ULONG   dir_ulCookie;\r
+       HANDLE  dir_hDirHandle;\r
+       DWORD   dir_nNumFiles;\r
+       char    dir_pDirectoryName[NAME_MAX+1];\r
+       struct dirent dir_sdReturn;\r
+} DIR;\r
+\r
+DIR *opendir(const char *);\r
+struct dirent *readdir(DIR *);\r
+void rewinddir(DIR *);\r
+void closedir(DIR *);\r
+int telldir(DIR *);\r
+void seekdir(DIR *, long);\r
+\r
+#endif\r
index 285ed04..63e7fb0 100644 (file)
@@ -1,10 +1,10 @@
-#ifndef _PATHSTUFF_H
-#define _PATHSTUFF_H
-
-extern char * convert_Path_to_win32(char *Path, char to_delim);
-extern char * w32ify(char *file, int resolve);
-extern char * getcwd_fs(char *buf, int len);
-
-#define convert_vpath_to_win32(vpath, delim) convert_Path_to_win32(vpath, delim)
-
-#endif
+#ifndef _PATHSTUFF_H\r
+#define _PATHSTUFF_H\r
+\r
+extern char * convert_Path_to_win32(char *Path, char to_delim);\r
+extern char * w32ify(char *file, int resolve);\r
+extern char * getcwd_fs(char *buf, int len);\r
+\r
+#define convert_vpath_to_win32(vpath, delim) convert_Path_to_win32(vpath, delim)\r
+\r
+#endif\r
index 12e9cf3..4f1f312 100644 (file)
@@ -1,54 +1,54 @@
-#ifndef SUB_PROC_H
-#define SUB_PROC_H
-
-/*
- * Component Name: 
- *
- * $Date$
- *
- * $Source$
- *
- * $Revision$
- *
- * Description: 
- *
- * (C) COPYRIGHT TIVOLI Systems, Inc. 1991-1994
- * Unpublished Work
- * All Rights Reserved
- * Licensed Material - Property of TIVOLI Systems, Inc.
- */
-
-/* $Id$ */
-
-#ifdef WIN32
-
-#define EXTERN_DECL(entry, args) extern entry args
-#define VOID_DECL void
-
-EXTERN_DECL(HANDLE process_init, (VOID_DECL));
-EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth,
-       HANDLE stderrh));
-EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp,
-       char *exec_path, char *as_user));
-EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data, 
-       int stdin_data_len));
-EXTERN_DECL(long process_file_io, (HANDLE proc));
-EXTERN_DECL(void process_cleanup, (HANDLE proc));
-EXTERN_DECL(HANDLE process_wait_for_any, (VOID_DECL));
-EXTERN_DECL(void process_register, (HANDLE proc));
-EXTERN_DECL(HANDLE process_easy, (char** argv, char** env));
-EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));
-
-/* support routines */
-EXTERN_DECL(long process_errno, (HANDLE proc));
-EXTERN_DECL(long process_last_err, (HANDLE proc));
-EXTERN_DECL(long process_exit_code, (HANDLE proc));
-EXTERN_DECL(long process_signal, (HANDLE proc));
-EXTERN_DECL(char * process_outbuf, (HANDLE proc));
-EXTERN_DECL(char * process_errbuf, (HANDLE proc));
-EXTERN_DECL(int process_outcnt, (HANDLE proc));
-EXTERN_DECL(int process_errcnt, (HANDLE proc));
-EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3]));
-
-#endif
-#endif
+#ifndef SUB_PROC_H\r
+#define SUB_PROC_H\r
+\r
+/*\r
+ * Component Name: \r
+ *\r
+ * $Date$\r
+ *\r
+ * $Source$\r
+ *\r
+ * $Revision$\r
+ *\r
+ * Description: \r
+ *\r
+ * (C) COPYRIGHT TIVOLI Systems, Inc. 1991-1994\r
+ * Unpublished Work\r
+ * All Rights Reserved\r
+ * Licensed Material - Property of TIVOLI Systems, Inc.\r
+ */\r
+\r
+/* $Id$ */\r
+\r
+#ifdef WIN32\r
+\r
+#define EXTERN_DECL(entry, args) extern entry args\r
+#define VOID_DECL void\r
+\r
+EXTERN_DECL(HANDLE process_init, (VOID_DECL));\r
+EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth,\r
+       HANDLE stderrh));\r
+EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp,\r
+       char *exec_path, char *as_user));\r
+EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data, \r
+       int stdin_data_len));\r
+EXTERN_DECL(long process_file_io, (HANDLE proc));\r
+EXTERN_DECL(void process_cleanup, (HANDLE proc));\r
+EXTERN_DECL(HANDLE process_wait_for_any, (VOID_DECL));\r
+EXTERN_DECL(void process_register, (HANDLE proc));\r
+EXTERN_DECL(HANDLE process_easy, (char** argv, char** env));\r
+EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));\r
+\r
+/* support routines */\r
+EXTERN_DECL(long process_errno, (HANDLE proc));\r
+EXTERN_DECL(long process_last_err, (HANDLE proc));\r
+EXTERN_DECL(long process_exit_code, (HANDLE proc));\r
+EXTERN_DECL(long process_signal, (HANDLE proc));\r
+EXTERN_DECL(char * process_outbuf, (HANDLE proc));\r
+EXTERN_DECL(char * process_errbuf, (HANDLE proc));\r
+EXTERN_DECL(int process_outcnt, (HANDLE proc));\r
+EXTERN_DECL(int process_errcnt, (HANDLE proc));\r
+EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3]));\r
+\r
+#endif\r
+#endif\r
index 7e9df78..b48dbbe 100644 (file)
@@ -1,10 +1,10 @@
-#ifndef _W32ERR_H_
-#define _W32ERR_H_
-
-#ifndef EXTERN_DECL
-#define EXTERN_DECL(entry, args) entry args
-#endif
-
-EXTERN_DECL(char * map_win32_error_to_string, (DWORD error));
-
-#endif /* !_W32ERR_H */
+#ifndef _W32ERR_H_\r
+#define _W32ERR_H_\r
+\r
+#ifndef EXTERN_DECL\r
+#define EXTERN_DECL(entry, args) entry args\r
+#endif\r
+\r
+EXTERN_DECL(char * map_win32_error_to_string, (DWORD error));\r
+\r
+#endif /* !_W32ERR_H */\r
index e5011f8..c6e8cfe 100644 (file)
-#include <string.h>
-#include <stdlib.h>
-#include "make.h"
-
-/*
- * Convert delimiter separated path to Canonical format. 
- */
-char *
-convert_Path_to_win32(char *Path, char to_delim)
-{
-    char *etok;            /* token separator for old Path */
-    char *p;            /* points to element of old Path */
-
-    /* is this a multi-element Path ? */
-    for (p = Path, etok = strpbrk(p, ":;");
-         etok; 
-         etok = strpbrk(p, ":;"))
-        if ((etok - p) == 1) {
-            if (*(etok - 1) == ';' ||
-                *(etok - 1) == ':') {
-               etok[-1] = to_delim;
-               etok[0] = to_delim;
-                p = ++etok;
-                continue;    /* ignore empty bucket */
-            } else if (etok = strpbrk(etok+1, ":;")) {
-                /* found one to count, handle drive letter */
-                *etok = to_delim;
-                p = ++etok;
-            } else
-                /* all finished, force abort */
-                p += strlen(p);    
-        } else {
-            /* found another one, no drive letter */
-            *etok = to_delim;
-            p = ++etok;
-       }
-
-#if 0
-    /* convert to backward slashes */
-    for (p = Path, p = strchr(p, '/'); p; p = strchr(p, '/'))
-       *p = '\\';
-#endif
-    return Path;
-} 
-
-/*
- * Convert to forward slashes. Resolve to full pathname optionally
- */
-char *
-w32ify(char *filename, int resolve)
-{
-    static char w32_path[FILENAME_MAX];
-    char *p;
-
-    if (resolve)
-        _fullpath(w32_path, filename, sizeof (w32_path));
-    else
-        strncpy(w32_path, filename, sizeof (w32_path));
-
-    for (p = w32_path; p && *p; p++)
-        if (*p == '\\')
-            *p = '/';
-
-    return w32_path;
-}
-
-char *
-getcwd_fs(char* buf, int len)
-{
-       char *p;
-
-       if (p = getcwd(buf, len)) {
-               char *q = w32ify(buf, 0);
-               strncpy(buf, q, len);
-       }
-
-       return p;
-}
-
-#ifdef unused
-/*
- * Convert delimiter separated pathnames (e.g. PATH) or single file pathname
- * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that 
- * _NutPathToNutc() fails to convert, just return the path we were handed 
- * and assume the caller will know what to do with it (It was probably 
- * a mistake to try and convert it anyway due to some of the bizarre things 
- * that might look like pathnames in makefiles).
- */
-char *
-convert_path_to_nutc(char *path)
-{
-    int  count;            /* count of path elements */
-    char *nutc_path;     /* new NutC path */
-    int  nutc_path_len;    /* length of buffer to allocate for new path */
-    char *pathp;        /* pointer to nutc_path used to build it */
-    char *etok;            /* token separator for old path */
-    char *p;            /* points to element of old path */
-    char sep;            /* what flavor of separator used in old path */
-    char *rval;
-
-    /* is this a multi-element path ? */
-    for (p = path, etok = strpbrk(p, ":;"), count = 0; 
-         etok; 
-         etok = strpbrk(p, ":;"))
-        if ((etok - p) == 1) {
-            if (*(etok - 1) == ';' ||
-                *(etok - 1) == ':') {
-                p = ++etok;
-                continue;    /* ignore empty bucket */
-            } else if (etok = strpbrk(etok+1, ":;"))
-                /* found one to count, handle drive letter */
-                p = ++etok, count++;
-            else
-                /* all finished, force abort */
-                p += strlen(p);    
-        } else 
-            /* found another one, no drive letter */
-            p = ++etok, count++;
-
-    if (count) {
-        count++;    /* x1;x2;x3 <- need to count x3 */
-
-        /* 
-         * Hazard a guess on how big the buffer needs to be.
-         * We have to convert things like c:/foo to /c=/foo.
-         */
-        nutc_path_len = strlen(path) + (count*2) + 1;
-        nutc_path = xmalloc(nutc_path_len);
-        pathp = nutc_path;
-        *pathp = '\0';
-
-        /*
-         * Loop through PATH and convert one elemnt of the path at at
-         * a time. Single file pathnames will fail this and fall
-         * to the logic below loop.
-         */
-        for (p = path, etok = strpbrk(p, ":;"); 
-             etok; 
-             etok = strpbrk(p, ":;")) {
-    
-            /* don't trip up on device specifiers or empty path slots */
-            if ((etok - p) == 1)
-                if (*(etok - 1) == ';' ||
-                    *(etok - 1) == ':') {
-                    p = ++etok;
-                    continue;
-                } else if ((etok = strpbrk(etok+1, ":;")) == NULL)
-                    break;    /* thing found was a WIN32 pathname */
-
-            /* save separator */
-            sep = *etok;
-
-            /* terminate the current path element -- temporarily */
-            *etok = '\0';
-    
-#ifdef __NUTC__
-            /* convert to NutC format */
-            if (_NutPathToNutc(p, pathp, 0) == FALSE) {
-                free(nutc_path);
-                rval = savestring(path, strlen(path));
-                return rval;
-            }
-#else
-            *pathp++ = '/';
-            *pathp++ = p[0];
-            *pathp++ = '=';
-            *pathp++ = '/';
-            strcpy(pathp, &p[2]);
-#endif
-            
-            pathp += strlen(pathp);
-            *pathp++ = ':';     /* use Unix style path separtor for new path */
-            *pathp   = '\0'; /* make sure we are null terminaed */
-    
-            /* restore path separator */
-            *etok = sep;
-    
-            /* point p to first char of next path element */
-            p = ++etok;
-
-        }
-    } else {
-        nutc_path_len = strlen(path) + 3; 
-        nutc_path = xmalloc(nutc_path_len);
-        pathp = nutc_path;
-        *pathp = '\0';
-        p = path;
-    }
-
-    /*
-      * OK, here we handle the last element in PATH (e.g. c of a;b;c)
-     * or the path was a single filename and will be converted
-     * here. Note, testing p here assures that we don't trip up
-     * on paths like a;b; which have trailing delimiter followed by 
-     * nothing.
-     */
-    if (*p != '\0') {
-#ifdef __NUTC__
-        if (_NutPathToNutc(p, pathp, 0) == FALSE) {
-            free(nutc_path);
-            rval = savestring(path, strlen(path));
-            return rval;
-        }
-#else
-        *pathp++ = '/';
-        *pathp++ = p[0];
-        *pathp++ = '=';
-        *pathp++ = '/';
-        strcpy(pathp, &p[2]);
-#endif
-    } else
-        *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */
-
-    rval = savestring(nutc_path, strlen(nutc_path));
-    free(nutc_path);
-    return rval;
-} 
-
-#endif
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "make.h"\r
+\r
+/*\r
+ * Convert delimiter separated path to Canonical format. \r
+ */\r
+char *\r
+convert_Path_to_win32(char *Path, char to_delim)\r
+{\r
+    char *etok;            /* token separator for old Path */\r
+    char *p;            /* points to element of old Path */\r
+\r
+    /* is this a multi-element Path ? */\r
+    for (p = Path, etok = strpbrk(p, ":;");\r
+         etok; \r
+         etok = strpbrk(p, ":;"))\r
+        if ((etok - p) == 1) {\r
+            if (*(etok - 1) == ';' ||\r
+                *(etok - 1) == ':') {\r
+               etok[-1] = to_delim;\r
+               etok[0] = to_delim;\r
+                p = ++etok;\r
+                continue;    /* ignore empty bucket */\r
+            } else if (etok = strpbrk(etok+1, ":;")) {\r
+                /* found one to count, handle drive letter */\r
+                *etok = to_delim;\r
+                p = ++etok;\r
+            } else\r
+                /* all finished, force abort */\r
+                p += strlen(p);    \r
+        } else {\r
+            /* found another one, no drive letter */\r
+            *etok = to_delim;\r
+            p = ++etok;\r
+       }\r
+\r
+#if 0\r
+    /* convert to backward slashes */\r
+    for (p = Path, p = strchr(p, '/'); p; p = strchr(p, '/'))\r
+       *p = '\\';\r
+#endif\r
+    return Path;\r
+} \r
+\r
+/*\r
+ * Convert to forward slashes. Resolve to full pathname optionally\r
+ */\r
+char *\r
+w32ify(char *filename, int resolve)\r
+{\r
+    static char w32_path[FILENAME_MAX];\r
+    char *p;\r
+\r
+    if (resolve)\r
+        _fullpath(w32_path, filename, sizeof (w32_path));\r
+    else\r
+        strncpy(w32_path, filename, sizeof (w32_path));\r
+\r
+    for (p = w32_path; p && *p; p++)\r
+        if (*p == '\\')\r
+            *p = '/';\r
+\r
+    return w32_path;\r
+}\r
+\r
+char *\r
+getcwd_fs(char* buf, int len)\r
+{\r
+       char *p;\r
+\r
+       if (p = getcwd(buf, len)) {\r
+               char *q = w32ify(buf, 0);\r
+               strncpy(buf, q, len);\r
+       }\r
+\r
+       return p;\r
+}\r
+\r
+#ifdef unused\r
+/*\r
+ * Convert delimiter separated pathnames (e.g. PATH) or single file pathname\r
+ * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that \r
+ * _NutPathToNutc() fails to convert, just return the path we were handed \r
+ * and assume the caller will know what to do with it (It was probably \r
+ * a mistake to try and convert it anyway due to some of the bizarre things \r
+ * that might look like pathnames in makefiles).\r
+ */\r
+char *\r
+convert_path_to_nutc(char *path)\r
+{\r
+    int  count;            /* count of path elements */\r
+    char *nutc_path;     /* new NutC path */\r
+    int  nutc_path_len;    /* length of buffer to allocate for new path */\r
+    char *pathp;        /* pointer to nutc_path used to build it */\r
+    char *etok;            /* token separator for old path */\r
+    char *p;            /* points to element of old path */\r
+    char sep;            /* what flavor of separator used in old path */\r
+    char *rval;\r
+\r
+    /* is this a multi-element path ? */\r
+    for (p = path, etok = strpbrk(p, ":;"), count = 0; \r
+         etok; \r
+         etok = strpbrk(p, ":;"))\r
+        if ((etok - p) == 1) {\r
+            if (*(etok - 1) == ';' ||\r
+                *(etok - 1) == ':') {\r
+                p = ++etok;\r
+                continue;    /* ignore empty bucket */\r
+            } else if (etok = strpbrk(etok+1, ":;"))\r
+                /* found one to count, handle drive letter */\r
+                p = ++etok, count++;\r
+            else\r
+                /* all finished, force abort */\r
+                p += strlen(p);    \r
+        } else \r
+            /* found another one, no drive letter */\r
+            p = ++etok, count++;\r
+\r
+    if (count) {\r
+        count++;    /* x1;x2;x3 <- need to count x3 */\r
+\r
+        /* \r
+         * Hazard a guess on how big the buffer needs to be.\r
+         * We have to convert things like c:/foo to /c=/foo.\r
+         */\r
+        nutc_path_len = strlen(path) + (count*2) + 1;\r
+        nutc_path = xmalloc(nutc_path_len);\r
+        pathp = nutc_path;\r
+        *pathp = '\0';\r
+\r
+        /*\r
+         * Loop through PATH and convert one elemnt of the path at at\r
+         * a time. Single file pathnames will fail this and fall\r
+         * to the logic below loop.\r
+         */\r
+        for (p = path, etok = strpbrk(p, ":;"); \r
+             etok; \r
+             etok = strpbrk(p, ":;")) {\r
+    \r
+            /* don't trip up on device specifiers or empty path slots */\r
+            if ((etok - p) == 1)\r
+                if (*(etok - 1) == ';' ||\r
+                    *(etok - 1) == ':') {\r
+                    p = ++etok;\r
+                    continue;\r
+                } else if ((etok = strpbrk(etok+1, ":;")) == NULL)\r
+                    break;    /* thing found was a WIN32 pathname */\r
+\r
+            /* save separator */\r
+            sep = *etok;\r
+\r
+            /* terminate the current path element -- temporarily */\r
+            *etok = '\0';\r
+    \r
+#ifdef __NUTC__\r
+            /* convert to NutC format */\r
+            if (_NutPathToNutc(p, pathp, 0) == FALSE) {\r
+                free(nutc_path);\r
+                rval = savestring(path, strlen(path));\r
+                return rval;\r
+            }\r
+#else\r
+            *pathp++ = '/';\r
+            *pathp++ = p[0];\r
+            *pathp++ = '=';\r
+            *pathp++ = '/';\r
+            strcpy(pathp, &p[2]);\r
+#endif\r
+            \r
+            pathp += strlen(pathp);\r
+            *pathp++ = ':';     /* use Unix style path separtor for new path */\r
+            *pathp   = '\0'; /* make sure we are null terminaed */\r
+    \r
+            /* restore path separator */\r
+            *etok = sep;\r
+    \r
+            /* point p to first char of next path element */\r
+            p = ++etok;\r
+\r
+        }\r
+    } else {\r
+        nutc_path_len = strlen(path) + 3; \r
+        nutc_path = xmalloc(nutc_path_len);\r
+        pathp = nutc_path;\r
+        *pathp = '\0';\r
+        p = path;\r
+    }\r
+\r
+    /*\r
+      * OK, here we handle the last element in PATH (e.g. c of a;b;c)\r
+     * or the path was a single filename and will be converted\r
+     * here. Note, testing p here assures that we don't trip up\r
+     * on paths like a;b; which have trailing delimiter followed by \r
+     * nothing.\r
+     */\r
+    if (*p != '\0') {\r
+#ifdef __NUTC__\r
+        if (_NutPathToNutc(p, pathp, 0) == FALSE) {\r
+            free(nutc_path);\r
+            rval = savestring(path, strlen(path));\r
+            return rval;\r
+        }\r
+#else\r
+        *pathp++ = '/';\r
+        *pathp++ = p[0];\r
+        *pathp++ = '=';\r
+        *pathp++ = '/';\r
+        strcpy(pathp, &p[2]);\r
+#endif\r
+    } else\r
+        *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */\r
+\r
+    rval = savestring(nutc_path, strlen(nutc_path));\r
+    free(nutc_path);\r
+    return rval;\r
+} \r
+\r
+#endif\r
index 3d44b82..0d2ca89 100644 (file)
@@ -1,59 +1,59 @@
-# NOTE: If you have no `make' program at all to process this makefile, run
-# `build.bat' instead.
-#
-# Copyright (C) 1988, 89, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc
-# This file is part of GNU Make.
-#
-# GNU Make is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU Make is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Make; see the file COPYING.  If not, write to
-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-#
-#       NMakefile for GNU Make (subproc library)
-#
-LIB = lib
-CC = cl
-
-OUTDIR=.
-MAKEFILE=NMakefile
-
-CFLAGS_any = /nologo /MT /W3 /GX /Z7 /YX /D WIN32 /D _WINDOWS  -I. -I../include
-CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/
-CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/
-
-all: Release Debug
-
-Release: 
-       $(MAKE) /f $(MAKEFILE) OUTDIR=WinRel CFLAGS="$(CFLAGS_release)" WinRel/subproc.lib
-Debug: 
-       $(MAKE) /f $(MAKEFILE) OUTDIR=WinDebug CFLAGS="$(CFLAGS_debug)" WinDebug/subproc.lib
-
-clean:
-       rmdir /s /q WinRel WinDebug
-
-$(OUTDIR):
-       if not exist .\$@\nul mkdir .\$@
-
-OBJS = $(OUTDIR)/misc.obj $(OUTDIR)/w32err.obj $(OUTDIR)/sub_proc.obj
-
-$(OUTDIR)/subproc.lib: $(OUTDIR) $(OBJS)
-       $(LIB) -out:$@ @<<
-               $(OBJS)
-<<
-
-.c{$(OUTDIR)}.obj:
-       $(CC) $(CFLAGS) /c $<
-       
-$(OUTDIR)/misc.obj: misc.c proc.h
-$(OUTDIR)/sub_proc.obj: sub_proc.c  ../include/sub_proc.h ../include/w32err.h proc.h
-$(OUTDIR)/w32err.obj: w32err.c ../include/w32err.h
+# NOTE: If you have no `make' program at all to process this makefile, run\r
+# `build.bat' instead.\r
+#\r
+# Copyright (C) 1988, 89, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc\r
+# This file is part of GNU Make.\r
+#\r
+# GNU Make is free software; you can redistribute it and/or modify\r
+# it under the terms of the GNU General Public License as published by\r
+# the Free Software Foundation; either version 2, or (at your option)\r
+# any later version.\r
+#\r
+# GNU Make is distributed in the hope that it will be useful,\r
+# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+# GNU General Public License for more details.\r
+#\r
+# You should have received a copy of the GNU General Public License\r
+# along with GNU Make; see the file COPYING.  If not, write to\r
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+\r
+#\r
+#       NMakefile for GNU Make (subproc library)\r
+#\r
+LIB = lib\r
+CC = cl\r
+\r
+OUTDIR=.\r
+MAKEFILE=NMakefile\r
+\r
+CFLAGS_any = /nologo /MT /W3 /GX /Z7 /YX /D WIN32 /D _WINDOWS  -I. -I../include\r
+CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/\r
+CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/\r
+\r
+all: Release Debug\r
+\r
+Release: \r
+       $(MAKE) /f $(MAKEFILE) OUTDIR=WinRel CFLAGS="$(CFLAGS_release)" WinRel/subproc.lib\r
+Debug: \r
+       $(MAKE) /f $(MAKEFILE) OUTDIR=WinDebug CFLAGS="$(CFLAGS_debug)" WinDebug/subproc.lib\r
+\r
+clean:\r
+       rmdir /s /q WinRel WinDebug\r
+\r
+$(OUTDIR):\r
+       if not exist .\$@\nul mkdir .\$@\r
+\r
+OBJS = $(OUTDIR)/misc.obj $(OUTDIR)/w32err.obj $(OUTDIR)/sub_proc.obj\r
+\r
+$(OUTDIR)/subproc.lib: $(OUTDIR) $(OBJS)\r
+       $(LIB) -out:$@ @<<\r
+               $(OBJS)\r
+<<\r
+\r
+.c{$(OUTDIR)}.obj:\r
+       $(CC) $(CFLAGS) /c $<\r
+       \r
+$(OUTDIR)/misc.obj: misc.c proc.h\r
+$(OUTDIR)/sub_proc.obj: sub_proc.c  ../include/sub_proc.h ../include/w32err.h proc.h\r
+$(OUTDIR)/w32err.obj: w32err.c ../include/w32err.h\r
index 45231bf..bb35615 100644 (file)
@@ -1,10 +1,10 @@
-if not exist .\WinDebug\nul mkdir .\WinDebug
-cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c
-cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c
-cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c w32err.c
-lib.exe /NOLOGO /OUT:.\WinDebug\subproc.lib  .\WinDebug/misc.obj  .\WinDebug/sub_proc.obj  .\WinDebug/w32err.obj
-if not exist .\WinRel\nul mkdir .\WinRel
-cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c misc.c
-cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c
-cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c
-lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib  .\WinRel/misc.obj  .\WinRel/sub_proc.obj  .\WinRel/w32err.obj
+if not exist .\WinDebug\nul mkdir .\WinDebug\r
+cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c\r
+cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c\r
+cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c w32err.c\r
+lib.exe /NOLOGO /OUT:.\WinDebug\subproc.lib  .\WinDebug/misc.obj  .\WinDebug/sub_proc.obj  .\WinDebug/w32err.obj\r
+if not exist .\WinRel\nul mkdir .\WinRel\r
+cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c misc.c\r
+cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c\r
+cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c\r
+lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib  .\WinRel/misc.obj  .\WinRel/sub_proc.obj  .\WinRel/w32err.obj\r
index 23b6124..2fd66ab 100644 (file)
@@ -1,63 +1,63 @@
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <windows.h>
-#include "proc.h"
-
-
-/*
- * Description:  Convert a NULL string terminated UNIX environment block to
- *             an environment block suitable for a win32 system call
- *
- * Returns:  TRUE= success, FALSE=fail
- *
- * Notes/Dependencies:  the environment block is sorted in case-insensitive
- *     order, is double-null terminated, and is a char *, not a char **
- */
-int _cdecl compare(const void *a1, const void *a2)
-{
-       return _stricoll(*((char**)a1),*((char**)a2));
-}
-bool_t
-arr2envblk(char **arr, char **envblk_out) 
-{
-       char **tmp;
-       int size_needed;
-       int arrcnt;
-       char *ptr;
-
-       arrcnt = 0;
-       while (arr[arrcnt]) {
-               arrcnt++;
-       }
-
-       tmp = (char**) calloc(arrcnt + 1, sizeof(char *));
-       if (!tmp) {
-               return FALSE;
-       }
-
-       arrcnt = 0;
-       size_needed = 0;
-       while (arr[arrcnt]) {
-               tmp[arrcnt] = arr[arrcnt];
-               size_needed += strlen(arr[arrcnt]) + 1;
-               arrcnt++;
-       }
-       size_needed++;
-
-       qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare);
-
-       ptr = *envblk_out = calloc(size_needed, 1);
-       if (!ptr) {
-               free(tmp);
-               return FALSE;
-       }
-
-       arrcnt = 0;
-       while (tmp[arrcnt]) {
-               strcpy(ptr, tmp[arrcnt]);
-               ptr += strlen(tmp[arrcnt]) + 1;
-               arrcnt++;
-       }
-       return TRUE;
-}
+#include <stddef.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <windows.h>\r
+#include "proc.h"\r
+\r
+\r
+/*\r
+ * Description:  Convert a NULL string terminated UNIX environment block to\r
+ *             an environment block suitable for a win32 system call\r
+ *\r
+ * Returns:  TRUE= success, FALSE=fail\r
+ *\r
+ * Notes/Dependencies:  the environment block is sorted in case-insensitive\r
+ *     order, is double-null terminated, and is a char *, not a char **\r
+ */\r
+int _cdecl compare(const void *a1, const void *a2)\r
+{\r
+       return _stricoll(*((char**)a1),*((char**)a2));\r
+}\r
+bool_t\r
+arr2envblk(char **arr, char **envblk_out) \r
+{\r
+       char **tmp;\r
+       int size_needed;\r
+       int arrcnt;\r
+       char *ptr;\r
+\r
+       arrcnt = 0;\r
+       while (arr[arrcnt]) {\r
+               arrcnt++;\r
+       }\r
+\r
+       tmp = (char**) calloc(arrcnt + 1, sizeof(char *));\r
+       if (!tmp) {\r
+               return FALSE;\r
+       }\r
+\r
+       arrcnt = 0;\r
+       size_needed = 0;\r
+       while (arr[arrcnt]) {\r
+               tmp[arrcnt] = arr[arrcnt];\r
+               size_needed += strlen(arr[arrcnt]) + 1;\r
+               arrcnt++;\r
+       }\r
+       size_needed++;\r
+\r
+       qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare);\r
+\r
+       ptr = *envblk_out = calloc(size_needed, 1);\r
+       if (!ptr) {\r
+               free(tmp);\r
+               return FALSE;\r
+       }\r
+\r
+       arrcnt = 0;\r
+       while (tmp[arrcnt]) {\r
+               strcpy(ptr, tmp[arrcnt]);\r
+               ptr += strlen(tmp[arrcnt]) + 1;\r
+               arrcnt++;\r
+       }\r
+       return TRUE;\r
+}\r
index ce7a14f..249ffd8 100644 (file)
@@ -1,13 +1,13 @@
-#ifndef  _PROC_H
-#define _PROC_H
-
-typedef int bool_t;
-
-#define E_SCALL                101
-#define E_IO           102
-#define E_NO_MEM       103
-#define E_FORK         104
-
-extern bool_t arr2envblk(char **arr, char **envblk_out);
-
-#endif
+#ifndef  _PROC_H\r
+#define _PROC_H\r
+\r
+typedef int bool_t;\r
+\r
+#define E_SCALL                101\r
+#define E_IO           102\r
+#define E_NO_MEM       103\r
+#define E_FORK         104\r
+\r
+extern bool_t arr2envblk(char **arr, char **envblk_out);\r
+\r
+#endif\r
index 52cd9d7..4f1ded9 100644 (file)
-#include <stdlib.h>
-#include <stdio.h>
-#include <process.h>  /* for msvc _beginthreadex, _endthreadex */
-#include <windows.h>
-
-#include "sub_proc.h"
-#include "proc.h"
-#include "w32err.h"
-
-static char *make_command_line( char *shell_name, char *exec_path, char **argv);
-
-typedef struct sub_process_t {
-       int sv_stdin[2];
-       int sv_stdout[2];
-       int sv_stderr[2];
-       int using_pipes;
-       char *inp;
-       DWORD incnt;
-       char * volatile outp;
-       volatile DWORD outcnt;
-       char * volatile errp;
-       volatile DWORD errcnt;
-       int pid;
-       int exit_code;
-       int signal;
-       long last_err;
-       long lerrno;
-} sub_process;
-
-/* keep track of children so we can implement a waitpid-like routine */
-static sub_process *proc_array[256];
-static int proc_index = 0;
-static int fake_exits_pending = 0;
-
-/*
- * When a process has been waited for, adjust the wait state
- * array so that we don't wait for it again
- */
-static void
-process_adjust_wait_state(sub_process* pproc)
-{
-       int i;
-
-       if (!proc_index)
-               return;
-
-       for (i = 0; i < proc_index; i++)
-               if (proc_array[i]->pid == pproc->pid)
-                       break;
-
-       if (i < proc_index) {
-               proc_index--;
-               if (i != proc_index)
-                       memmove(&proc_array[i], &proc_array[i+1], 
-                               (proc_index-i) * sizeof(sub_process*));
-               proc_array[proc_index] = NULL;
-       }
-}
-
-/*
- * Waits for any of the registered child processes to finish.
- */
-static sub_process *
-process_wait_for_any_private(void)
-{
-       HANDLE handles[256];
-       DWORD retval, which;
-       int i;
-
-       if (!proc_index)
-               return NULL;
-
-       /* build array of handles to wait for */
-       for (i = 0; i < proc_index; i++) {
-               handles[i] = (HANDLE) proc_array[i]->pid;
-
-               if (fake_exits_pending && proc_array[i]->exit_code)
-                       break;
-       }
-
-       /* wait for someone to exit */
-       if (!fake_exits_pending) {
-               retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
-               which = retval - WAIT_OBJECT_0;
-       } else {
-               fake_exits_pending--;
-               retval = !WAIT_FAILED;
-               which = i;
-       }
-
-       /* return pointer to process */
-       if (retval != WAIT_FAILED) {
-               sub_process* pproc = proc_array[which]; 
-               process_adjust_wait_state(pproc);
-               return pproc;
-       } else
-               return NULL;
-}
-
-/*
- * Terminate a process.
- */
-BOOL
-process_kill(HANDLE proc, int signal)
-{
-       sub_process* pproc = (sub_process*) proc;
-       pproc->signal = signal;
-       return (TerminateProcess((HANDLE) pproc->pid, signal));
-}
-
-/*
- * Use this function to register processes you wish to wait for by
- * calling process_file_io(NULL) or process_wait_any(). This must be done 
- * because it is possible for callers of this library to reuse the same 
- * handle for multiple processes launches :-(
- */
-void
-process_register(HANDLE proc)
-{
-       proc_array[proc_index++] = (sub_process *) proc;
-}
-
-/*
- * Public function which works kind of like waitpid(). Wait for any
- * of the children to die and return results. To call this function,
- * you must do 1 of things:
- *
- *     x = process_easy(...);
- *     
- * or
- *
- *     x = process_init_fd();
- *     process_register(x);
- *
- * or
- *
- *     x = process_init();
- *     process_register(x);
- *
- * You must NOT then call process_pipe_io() because this function is
- * not capable of handling automatic notification of any child
- * death.
- */
-
-HANDLE
-process_wait_for_any(void)
-{
-       sub_process* pproc = process_wait_for_any_private(); 
-
-       if (!pproc)
-               return NULL;
-       else {
-               /* 
-                * Ouch! can't tell caller if this fails directly. Caller 
-                * will have to use process_last_err() 
-                 */
-               (void) process_file_io(pproc);
-               return ((HANDLE) pproc);
-       }
-}
-
-long
-process_errno(HANDLE proc)
-{
-       return (((sub_process *)proc)->lerrno);
-}
-
-long
-process_signal(HANDLE proc)
-{
-       return (((sub_process *)proc)->signal);
-}
-
-       long
-process_last_err(HANDLE proc)
-{
-       return (((sub_process *)proc)->last_err);
-}
-
-       long
-process_exit_code(HANDLE proc)
-{
-       return (((sub_process *)proc)->exit_code);
-}
-
-       char *
-process_outbuf(HANDLE proc)
-{
-       return (((sub_process *)proc)->outp);
-}
-
-       char *
-process_errbuf(HANDLE proc)
-{
-       return (((sub_process *)proc)->errp);
-}
-
-       int
-process_outcnt(HANDLE proc)
-{
-       return (((sub_process *)proc)->outcnt);
-}
-
-       int
-process_errcnt(HANDLE proc)
-{
-       return (((sub_process *)proc)->errcnt);
-}
-
-       void
-process_pipes(HANDLE proc, int pipes[3])
-{
-       pipes[0] = ((sub_process *)proc)->sv_stdin[0];
-       pipes[1] = ((sub_process *)proc)->sv_stdout[0];
-       pipes[2] = ((sub_process *)proc)->sv_stderr[0];
-       return;
-}
-
-
-       HANDLE
-process_init()
-{
-       sub_process *pproc;
-       /*
-        * open file descriptors for attaching stdin/stdout/sterr
-        */
-       HANDLE stdin_pipes[2];
-       HANDLE stdout_pipes[2];
-       HANDLE stderr_pipes[2];
-       SECURITY_ATTRIBUTES inherit;
-       BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
-
-       pproc = malloc(sizeof(*pproc));
-       memset(pproc, 0, sizeof(*pproc));
-
-       /* We can't use NULL for lpSecurityDescriptor because that
-          uses the default security descriptor of the calling process.
-          Instead we use a security descriptor with no DACL.  This
-          allows nonrestricted access to the associated objects. */
-       
-       if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
-                                         SECURITY_DESCRIPTOR_REVISION)) {
-               pproc->last_err = GetLastError();
-               pproc->lerrno = E_SCALL;
-               return((HANDLE)pproc);
-       }
-
-       inherit.nLength = sizeof(inherit);
-       inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
-       inherit.bInheritHandle = TRUE;
-
-       // By convention, parent gets pipe[0], and child gets pipe[1]
-       // This means the READ side of stdin pipe goes into pipe[1]
-       // and the WRITE side of the stdout and stderr pipes go into pipe[1]
-       if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
-       CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
-       CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
-
-               pproc->last_err = GetLastError();
-               pproc->lerrno = E_SCALL;
-               return((HANDLE)pproc);
-       }
-
-       //
-       // Mark the parent sides of the pipes as non-inheritable
-       //
-       if (SetHandleInformation(stdin_pipes[0], 
-                               HANDLE_FLAG_INHERIT, 0) == FALSE ||
-               SetHandleInformation(stdout_pipes[0], 
-                               HANDLE_FLAG_INHERIT, 0) == FALSE ||
-               SetHandleInformation(stderr_pipes[0], 
-                               HANDLE_FLAG_INHERIT, 0) == FALSE) {
-
-               pproc->last_err = GetLastError();
-               pproc->lerrno = E_SCALL;
-               return((HANDLE)pproc);
-       }
-       pproc->sv_stdin[0]  = (int) stdin_pipes[0];
-       pproc->sv_stdin[1]  = (int) stdin_pipes[1];
-       pproc->sv_stdout[0] = (int) stdout_pipes[0];
-       pproc->sv_stdout[1] = (int) stdout_pipes[1];
-       pproc->sv_stderr[0] = (int) stderr_pipes[0];
-       pproc->sv_stderr[1] = (int) stderr_pipes[1];
-
-       pproc->using_pipes = 1;
-
-       pproc->lerrno = 0;
-
-       return((HANDLE)pproc);
-}
-
-
-       HANDLE
-process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
-{
-       sub_process *pproc;
-
-       pproc = malloc(sizeof(*pproc));
-       memset(pproc, 0, sizeof(*pproc));
-
-       /*
-        * Just pass the provided file handles to the 'child side' of the
-        * pipe, bypassing pipes altogether.
-        */
-       pproc->sv_stdin[1]  = (int) stdinh;
-       pproc->sv_stdout[1] = (int) stdouth;
-       pproc->sv_stderr[1] = (int) stderrh;
-
-       pproc->last_err = pproc->lerrno = 0;
-
-       return((HANDLE)pproc);
-}
-
-
-static HANDLE
-find_file(char *exec_path, LPOFSTRUCT file_info)
-{
-       HANDLE exec_handle;
-       char *fname;
-       char *ext;
-
-       if ((exec_handle = (HANDLE)OpenFile(exec_path, file_info,
-                       OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-               return(exec_handle);
-       }
-
-       fname = malloc(strlen(exec_path) + 5);
-       strcpy(fname, exec_path);
-       ext = fname + strlen(fname);
-       strcpy(ext, ".exe");
-       if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
-                       OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-               free(fname);
-               return(exec_handle);
-       }
-
-       strcpy(ext, ".bat");
-       if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
-                       OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-               free(fname);
-               return(exec_handle);
-       }
-
-       strcpy(ext, ".com");
-       if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
-                       OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
-               free(fname);
-               return(exec_handle);
-       }
-
-       free(fname);
-       return(exec_handle);
-}
-
-
-/*
- * Description:   Create the child process to be helped
- *
- * Returns: 
- *
- * Notes/Dependencies:  
- */
-long
-process_begin(
-       HANDLE proc,
-       char **argv,
-       char **envp,
-       char *exec_path,
-       char *as_user)
-{
-       sub_process *pproc = (sub_process *)proc;
-       char *shell_name = 0;
-       int file_not_found=0;
-       HANDLE exec_handle;
-       char buf[256];
-       DWORD bytes_returned;
-       DWORD flags;
-       char *command_line;
-       STARTUPINFO startInfo;
-       PROCESS_INFORMATION procInfo;
-       char *envblk=NULL;
-       OFSTRUCT file_info;
-
-
-       /*
-        *  Shell script detection...  if the exec_path starts with #! then
-        *  we want to exec shell-script-name exec-path, not just exec-path
-        *  NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl.  We do not
-        *  hard-code the path to the shell or perl or whatever:  Instead, we
-        *  assume it's in the path somewhere (generally, the NT tools
-        *  bin directory)
-        *  We use OpenFile here because it is capable of searching the Path.
-        */
-
-       exec_handle = find_file(exec_path, &file_info);
-
-       /*
-        * If we couldn't open the file, just assume that Win32 will be able
-        * to find and execute it.
-        */
-       if (exec_handle == (HANDLE)HFILE_ERROR) {
-               file_not_found++;
-       }
-       else {
-               /* Attempt to read the first line of the file */
-               if (ReadFile( exec_handle, 
-                               buf, sizeof(buf) - 1, /* leave room for trailing NULL */
-                               &bytes_returned, 0) == FALSE || bytes_returned < 2) {
-       
-                       pproc->last_err = GetLastError();
-                       pproc->lerrno = E_IO;
-                       CloseHandle(exec_handle);
-                       return(-1);
-               }
-               if (buf[0] == '#' && buf[1] == '!') {
-                       /*
-                        *  This is a shell script...  Change the command line from
-                        *      exec_path args to shell_name exec_path args
-                        */
-                       char *p;
-       
-                       /*  Make sure buf is NULL terminated */
-                       buf[bytes_returned] = 0;
-                       /*
-                        * Depending on the file system type, etc. the first line
-                        * of the shell script may end with newline or newline-carriage-return
-                        * Whatever it ends with, cut it off.
-                        */
-                       p= strchr(buf, '\n');
-                       if (p)
-                               *p = 0;
-                       p = strchr(buf, '\r');
-                       if (p)
-                               *p = 0;
-               
-                       /*
-                        *  Find base name of shell
-                        */
-                       shell_name = strrchr( buf, '/');
-                       if (shell_name) {
-                               shell_name++;
-                       } else {
-                               shell_name = &buf[2];/* skipping "#!" */
-                       }
-
-               } 
-               CloseHandle(exec_handle);
-       }
-
-       flags = 0;
-
-       if (file_not_found)
-               command_line = make_command_line( shell_name, exec_path, argv);
-       else
-               command_line = make_command_line( shell_name, file_info.szPathName,
-                                argv);
-
-       if ( command_line == NULL ) {
-               pproc->last_err = 0;
-               pproc->lerrno = E_NO_MEM;
-               return(-1);
-       }
-
-       if (envp) {
-               if (arr2envblk(envp, &envblk) ==FALSE) {
-                       pproc->last_err = 0;
-                       pproc->lerrno = E_NO_MEM;
-                       free( command_line );
-                       return(-1);
-               }
-       }
-
-       if ((shell_name) || (file_not_found)) {
-               exec_path = 0;  /* Search for the program in %Path% */
-       } else {
-               exec_path = file_info.szPathName;
-       }
-
-       /*
-        *  Set up inherited stdin, stdout, stderr for child
-        */
-       GetStartupInfo(&startInfo);
-       startInfo.dwFlags = STARTF_USESTDHANDLES;
-       startInfo.lpReserved = 0;
-       startInfo.cbReserved2 = 0;
-       startInfo.lpReserved2 = 0;
-       startInfo.lpTitle = shell_name ? shell_name : exec_path;
-       startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
-       startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
-       startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
-
-       /*
-        * See if we need to setuid to a different user.
-        */
-       if (as_user) {
-               return -1;
-       }
-
-       if (as_user) {
-               return -1;
-       } else {
-               if (CreateProcess(
-                       exec_path,
-                       command_line,
-                       NULL,
-                       0, /* default security attributes for thread */
-                       TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
-                       flags, 
-                       envblk,
-                       0, /* default starting directory */
-                       &startInfo,
-                       &procInfo) == FALSE) {
-               
-                       pproc->last_err = GetLastError();
-                       pproc->lerrno = E_FORK;
-                       fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path, command_line);
-                       free( command_line );
-                       return(-1);
-               }
-       }
-       
-       pproc->pid = (int)procInfo.hProcess;
-       /* Close the thread handle -- we'll just watch the process */
-       CloseHandle(procInfo.hThread);
-       
-       /* Close the halves of the pipes we don't need */
-       if (pproc->sv_stdin) {
-               CloseHandle((HANDLE)pproc->sv_stdin[1]);
-               (HANDLE)pproc->sv_stdin[1] = 0;
-       }
-       if (pproc->sv_stdout) {
-               CloseHandle((HANDLE)pproc->sv_stdout[1]);
-               (HANDLE)pproc->sv_stdout[1] = 0;
-       }
-       if (pproc->sv_stderr) {
-               CloseHandle((HANDLE)pproc->sv_stderr[1]);
-               (HANDLE)pproc->sv_stderr[1] = 0;
-       }
-
-       free( command_line );
-       pproc->lerrno=0;
-       return 0;
-}
-
-
-
-static DWORD 
-proc_stdin_thread(sub_process *pproc)
-{
-       DWORD in_done;
-       for (;;) {
-               if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
-                                        &in_done, NULL) == FALSE)
-                       _endthreadex(0);
-               // This if should never be true for anonymous pipes, but gives
-               // us a chance to change I/O mechanisms later
-               if (in_done < pproc->incnt) {
-                       pproc->incnt -= in_done;
-                       pproc->inp += in_done;
-               } else {
-                       _endthreadex(0);
-               }
-       }
-       return 0; // for compiler warnings only.. not reached
-}
-
-static DWORD
-proc_stdout_thread(sub_process *pproc)
-{
-       DWORD bufsize = 1024;
-       char c;
-       DWORD nread;
-       pproc->outp = malloc(bufsize);
-       if (pproc->outp == NULL)
-               _endthreadex(0);
-       pproc->outcnt = 0;
-
-       for (;;) {
-               if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL) 
-                                       == FALSE) {
-/*                     map_win32_error_to_string(GetLastError());*/
-                       _endthreadex(0);
-               }
-               if (nread == 0)
-                       _endthreadex(0);
-               if (pproc->outcnt + nread > bufsize) {
-                       bufsize += nread + 512; 
-                       pproc->outp = realloc(pproc->outp, bufsize);
-                       if (pproc->outp == NULL) {
-                               pproc->outcnt = 0;
-                               _endthreadex(0);
-                       }
-               }
-               pproc->outp[pproc->outcnt++] = c;
-       }
-       return 0;
-}
-
-static DWORD
-proc_stderr_thread(sub_process *pproc)
-{
-       DWORD bufsize = 1024;
-       char c;
-       DWORD nread;
-       pproc->errp = malloc(bufsize);
-       if (pproc->errp == NULL)
-               _endthreadex(0);
-       pproc->errcnt = 0;
-
-       for (;;) {
-               if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
-                       map_win32_error_to_string(GetLastError());
-                       _endthreadex(0);
-               }
-               if (nread == 0)
-                       _endthreadex(0);
-               if (pproc->errcnt + nread > bufsize) {
-                       bufsize += nread + 512; 
-                       pproc->errp = realloc(pproc->errp, bufsize);
-                       if (pproc->errp == NULL) {
-                               pproc->errcnt = 0;
-                               _endthreadex(0);
-                       }
-               }
-               pproc->errp[pproc->errcnt++] = c;
-       }
-       return 0;
-}
-
-
-/*
- * Purpose: collects output from child process and returns results
- *
- * Description:
- *
- * Returns: 
- *
- * Notes/Dependencies:
- */
-       long
-process_pipe_io(
-       HANDLE proc,
-       char *stdin_data, 
-       int stdin_data_len)
-{
-       sub_process *pproc = (sub_process *)proc;
-       bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
-       HANDLE childhand = (HANDLE) pproc->pid;
-       HANDLE tStdin, tStdout, tStderr;
-       DWORD dwStdin, dwStdout, dwStderr;
-       HANDLE wait_list[4];
-       DWORD wait_count;
-       DWORD wait_return;
-       HANDLE ready_hand;
-       bool_t child_dead = FALSE;
-
-
-       /*
-        *  Create stdin thread, if needed
-        */
-    pproc->inp = stdin_data;
-    pproc->incnt = stdin_data_len;
-       if (!pproc->inp) {
-               stdin_eof = TRUE;
-               CloseHandle((HANDLE)pproc->sv_stdin[0]);
-               (HANDLE)pproc->sv_stdin[0] = 0;
-       } else {
-               tStdin = (HANDLE) _beginthreadex( 0, 1024,
-                       (unsigned (__stdcall *) (void *))proc_stdin_thread, pproc, 0,
-                       (unsigned int *) &dwStdin);
-               if (tStdin == 0) {
-                       pproc->last_err = GetLastError();
-                       pproc->lerrno = E_SCALL;
-                       goto done;
-               }
-       }
-       
-       /*
-        *   Assume child will produce stdout and stderr
-        */ 
-       tStdout = (HANDLE) _beginthreadex( 0, 1024,
-               (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
-               (unsigned int *) &dwStdout);
-       tStderr = (HANDLE) _beginthreadex( 0, 1024,
-               (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
-               (unsigned int *) &dwStderr);
-       
-       if (tStdout == 0 || tStderr == 0) {
-       
-               pproc->last_err = GetLastError();
-               pproc->lerrno = E_SCALL;
-               goto done;
-       }
-
-
-       /*
-        *  Wait for all I/O to finish and for the child process to exit
-        */
-
-       while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
-               wait_count = 0;
-               if (!stdin_eof) {
-                       wait_list[wait_count++] = tStdin;
-               }
-               if (!stdout_eof) {
-                       wait_list[wait_count++] = tStdout;
-               }
-               if (!stderr_eof) {
-                       wait_list[wait_count++] = tStderr;
-               }
-               if (!child_dead) {
-                       wait_list[wait_count++] = childhand;
-               }
-               
-               wait_return = WaitForMultipleObjects(wait_count, wait_list,
-                        FALSE, /* don't wait for all: one ready will do */
-                        child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
-                               one second to collect all remaining output */
-               
-               if (wait_return == WAIT_FAILED) {
-/*                     map_win32_error_to_string(GetLastError());*/
-                       pproc->last_err = GetLastError();
-                       pproc->lerrno = E_SCALL;
-                       goto done;
-               }
-
-               ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
-               
-               if (ready_hand == tStdin) {
-                       CloseHandle((HANDLE)pproc->sv_stdin[0]);
-                       (HANDLE)pproc->sv_stdin[0] = 0;
-                       CloseHandle(tStdin);
-                       tStdin = 0;
-                       stdin_eof = TRUE;
-               
-               } else if (ready_hand == tStdout) {
-               
-                       CloseHandle((HANDLE)pproc->sv_stdout[0]);
-                       (HANDLE)pproc->sv_stdout[0] = 0;
-                       CloseHandle(tStdout);
-                       tStdout = 0;
-                       stdout_eof = TRUE;
-               
-               } else if (ready_hand == tStderr) {
-                       
-                       CloseHandle((HANDLE)pproc->sv_stderr[0]);
-                       (HANDLE)pproc->sv_stderr[0] = 0;
-                       CloseHandle(tStderr);
-                       tStderr = 0;
-                       stderr_eof = TRUE;
-               
-               } else if (ready_hand == childhand) {
-                       
-                       if (GetExitCodeProcess(childhand, &pproc->exit_code) == FALSE) {
-                               pproc->last_err = GetLastError();
-                               pproc->lerrno = E_SCALL;
-                               goto done;
-                       }
-                       child_dead = TRUE;
-       
-               } else {
-               
-                       /* ?? Got back a handle we didn't query ?? */
-                       pproc->last_err = 0;
-                       pproc->lerrno = E_FAIL;
-                       goto done;
-               }
-       }
- done:
-       if (tStdin != 0)
-               CloseHandle(tStdin);
-       if (tStdout != 0)
-               CloseHandle(tStdout);
-       if (tStderr != 0)
-               CloseHandle(tStderr);
-
-       if (pproc->lerrno)
-               return(-1);
-       else
-               return(0);
-
-}
-
-/*
- * Purpose: collects output from child process and returns results
- *
- * Description:
- *
- * Returns: 
- *
- * Notes/Dependencies:
- */
-       long
-process_file_io(
-       HANDLE proc)
-{
-       sub_process *pproc;
-       HANDLE childhand;
-       DWORD wait_return;
-
-       if (proc == NULL)
-               pproc = process_wait_for_any_private();
-       else
-               pproc = (sub_process *)proc;
-
-       /* some sort of internal error */
-       if (!pproc)
-               return -1;
-
-       childhand = (HANDLE) pproc->pid;
-
-       /*
-        * This function is poorly named, and could also be used just to wait
-        * for child death if you're doing your own pipe I/O.  If that is 
-        * the case, close the pipe handles here.
-        */
-       if (pproc->sv_stdin[0]) {
-               CloseHandle((HANDLE)pproc->sv_stdin[0]);
-               pproc->sv_stdin[0] = 0;
-       }
-       if (pproc->sv_stdout[0]) {
-               CloseHandle((HANDLE)pproc->sv_stdout[0]);
-               pproc->sv_stdout[0] = 0;
-       }
-       if (pproc->sv_stderr[0]) {
-               CloseHandle((HANDLE)pproc->sv_stderr[0]);
-               pproc->sv_stderr[0] = 0;
-       }
-
-       /*
-        *  Wait for the child process to exit
-        */
-
-       wait_return = WaitForSingleObject(childhand, INFINITE);
-               
-       if (wait_return != WAIT_OBJECT_0) {
-/*             map_win32_error_to_string(GetLastError());*/
-               pproc->last_err = GetLastError();
-               pproc->lerrno = E_SCALL;
-               goto done2;
-       }
-
-       if (GetExitCodeProcess(childhand, &pproc->exit_code) == FALSE) {
-               pproc->last_err = GetLastError();
-               pproc->lerrno = E_SCALL;
-       }
-       
-done2:
-       if (pproc->lerrno)
-               return(-1);
-       else
-               return(0);
-
-}
-
-/*
- * Description:  Clean up any leftover handles, etc.  It is up to the
- * caller to manage and free the input, ouput, and stderr buffers.
- */
-       void
-process_cleanup(
-       HANDLE proc)
-{
-       sub_process *pproc = (sub_process *)proc;
-       int i;
-
-       if (pproc->using_pipes) {
-               for (i= 0; i <= 1; i++) {
-                       if ((HANDLE)pproc->sv_stdin[i])
-                               CloseHandle((HANDLE)pproc->sv_stdin[i]);
-                       if ((HANDLE)pproc->sv_stdout[i])
-                               CloseHandle((HANDLE)pproc->sv_stdout[i]);
-                       if ((HANDLE)pproc->sv_stderr[i])
-                               CloseHandle((HANDLE)pproc->sv_stderr[i]);
-               }
-       }
-       if ((HANDLE)pproc->pid)
-               CloseHandle((HANDLE)pproc->pid);
-       
-       free(pproc);
-}
-
-
-/*
- * Try to protect against WIN32 argument munging. This function takes
- * an argv vector and outputs a 'protected' string as a return
- * value. The return code can be safely passed to CreateProcess().
- *
- * The caller should free the return value.
- */
-
-#define TRACE(x)
-static char *fix_command_line(char *args[])
-{
-       int i;
-       char *narg;
-       char *nargp;
-       char *p;
-       char *q;
-       int alloc_len = 0;
-
-       for (i = 0; args[i]; i++)
-               alloc_len += ((strlen(args[i]) * 2) + 1);
-       /* account for possible enclosing quotes and null termination */
-       alloc_len += 3;
-
-       nargp = narg = malloc(alloc_len);
-
-       for (i = 0; args[i]; i++) {
-               p = args[i];
-               TRACE(("original arg: %s\n", p));
-
-               if (*p == '\0') {
-                       *nargp++ = '"';
-                       *nargp++ = '"';
-                       *nargp = '\0';
-                       TRACE(("empty string arg: %s\n", nargp-2));
-               } else if (strpbrk(p, "\" \t")) {
-                       /* point to end of copy buffer */
-                       q = narg;
-                       q += (alloc_len-1);
-                       *q-- = '\0'; /* ensure null terminated string */
-                       *q-- = '"';  /* terminating quote of argument */
-
-                       /* point to end of the input string */
-                       p = args[i];
-                       p += strlen(args[i]);
-                       p--;
-
-                       /* 
-                        * Because arg is quoted, escape any backslashes 
-                        * that might occur at the end of the string which
-                        * proceed the closing quote.
-                        * Example:
-                        *      foo c:\
-                        * Becomes:
-                        *      "foo c:\\"
-                        */
-                       while (*p == '\\')
-                               *q-- = *p--, *q-- = '\\';
-
-                       /* copy the string in reverse */
-                       while (p >= args[i]) {
-                               /* copy the character */
-                               *q-- = *p--;
-
-                               /* 
-                                * Escape any double quote found. Also escape
-                                * each backslash preceding the double quote.
-                                */
-                               if (*(p+1) == '"') {
-                                       *q-- = '\\';
-                                       if (p >= args[i] && *p == '\\')
-                                               while (p >= args[i] && *p == '\\')
-                                                       *q-- = *p--, *q-- = '\\';
-                               }
-                       }
-
-                       /* finish quoting arg, q now points to complete arg */
-                       *q = '"';
-
-                       /* rejustify */
-                       memmove(nargp, q, strlen(q) + 1);
-                       TRACE(("arg with white space or doublequotes: %s\n", nargp));
-                       nargp += strlen(nargp);
-               } else {
-                       /* just copy the argument, no protection needed */
-                       strcpy(nargp, args[i]);
-                       TRACE(("plain arg: %s\n", nargp));
-                       nargp += strlen(nargp);
-               }
-
-               /* separate arguments with spaces (if more args to gather) */
-               if (args[i+1])
-                       *nargp++ = ' ';
-               *nargp   = '\0';
-       } /* end for */
-
-       /* NULL terminate the arg list */
-       *nargp = '\0';
-
-       return (narg);
-}
-#undef TRACE
-
-/*
- * Description: 
- *      Create a command line buffer to pass to CreateProcess
- *
- * Returns:  the buffer or NULL for failure
- *     Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...
- *  Otherwise:   argv[0] argv[1] argv[2] ...
- *
- * Notes/Dependencies: 
- *   CreateProcess does not take an argv, so this command creates a
- *   command line for the executable.  
- */
-
-static char *
-make_command_line( char *shell_name, char *exec_path, char **argv)
-{
-       char** nargv;
-       char*  buf;
-       int    i;
-       if (shell_name) {
-               for (i = 0; argv[i]; i++);
-               i += 2;
-               nargv = (char **) malloc(i * sizeof (char *));
-               nargv[0] = shell_name;
-               for (i = 1; argv[i-1]; i++)
-                       nargv[i] = argv[i-1];
-               nargv[i] = NULL;
-       } else
-               nargv = argv;
-
-       /* create string suitable for CreateProcess() */
-       buf = fix_command_line(nargv);
-
-       if (shell_name)
-               free(nargv);
-       
-       return buf;
-}
-
-/*
- * Description: Given an argv and optional envp, launch the process
- *              using the default stdin, stdout, and stderr handles.
- *              Also, register process so that process_wait_for_any_private()
- *             can be used via process_file_io(NULL) or 
- *             process_wait_for_any().
- *
- * Returns: 
- *
- * Notes/Dependencies:  
- */
-HANDLE
-process_easy(
-       char **argv,
-       char **envp)
-{
-  HANDLE hIn;
-  HANDLE hOut;
-  HANDLE hErr;
-  HANDLE hProcess;
-
-  if (DuplicateHandle(GetCurrentProcess(),
-                      GetStdHandle(STD_INPUT_HANDLE),
-                      GetCurrentProcess(),
-                      &hIn,
-                      0,
-                      TRUE,
-                      DUPLICATE_SAME_ACCESS) == FALSE) {
-    fprintf(stderr,
-            "process_easy: DuplicateHandle(In) failed (e=%d)\n",
-            GetLastError());
-    return INVALID_HANDLE_VALUE;
-  }
-  if (DuplicateHandle(GetCurrentProcess(),
-                      GetStdHandle(STD_OUTPUT_HANDLE),
-                      GetCurrentProcess(),
-                      &hOut,
-                      0,
-                      TRUE,
-                      DUPLICATE_SAME_ACCESS) == FALSE) {
-    fprintf(stderr,
-           "process_easy: DuplicateHandle(Out) failed (e=%d)\n",
-           GetLastError());
-    return INVALID_HANDLE_VALUE;
-  }
-  if (DuplicateHandle(GetCurrentProcess(),
-                      GetStdHandle(STD_ERROR_HANDLE),
-                      GetCurrentProcess(),
-                      &hErr,
-                      0,
-                      TRUE,
-                      DUPLICATE_SAME_ACCESS) == FALSE) {
-    fprintf(stderr,
-            "process_easy: DuplicateHandle(Err) failed (e=%d)\n",
-            GetLastError());
-    return INVALID_HANDLE_VALUE;
-  }
-
-  hProcess = process_init_fd(hIn, hOut, hErr);
-
-  if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
-    fake_exits_pending++;
-    ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
-
-    /* close up unused handles */
-    CloseHandle(hIn);
-    CloseHandle(hOut);
-    CloseHandle(hErr);
-  }
-
-  process_register(hProcess);
-
-  return hProcess;
-}
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <process.h>  /* for msvc _beginthreadex, _endthreadex */\r
+#include <windows.h>\r
+\r
+#include "sub_proc.h"\r
+#include "proc.h"\r
+#include "w32err.h"\r
+\r
+static char *make_command_line( char *shell_name, char *exec_path, char **argv);\r
+\r
+typedef struct sub_process_t {\r
+       int sv_stdin[2];\r
+       int sv_stdout[2];\r
+       int sv_stderr[2];\r
+       int using_pipes;\r
+       char *inp;\r
+       DWORD incnt;\r
+       char * volatile outp;\r
+       volatile DWORD outcnt;\r
+       char * volatile errp;\r
+       volatile DWORD errcnt;\r
+       int pid;\r
+       int exit_code;\r
+       int signal;\r
+       long last_err;\r
+       long lerrno;\r
+} sub_process;\r
+\r
+/* keep track of children so we can implement a waitpid-like routine */\r
+static sub_process *proc_array[256];\r
+static int proc_index = 0;\r
+static int fake_exits_pending = 0;\r
+\r
+/*\r
+ * When a process has been waited for, adjust the wait state\r
+ * array so that we don't wait for it again\r
+ */\r
+static void\r
+process_adjust_wait_state(sub_process* pproc)\r
+{\r
+       int i;\r
+\r
+       if (!proc_index)\r
+               return;\r
+\r
+       for (i = 0; i < proc_index; i++)\r
+               if (proc_array[i]->pid == pproc->pid)\r
+                       break;\r
+\r
+       if (i < proc_index) {\r
+               proc_index--;\r
+               if (i != proc_index)\r
+                       memmove(&proc_array[i], &proc_array[i+1], \r
+                               (proc_index-i) * sizeof(sub_process*));\r
+               proc_array[proc_index] = NULL;\r
+       }\r
+}\r
+\r
+/*\r
+ * Waits for any of the registered child processes to finish.\r
+ */\r
+static sub_process *\r
+process_wait_for_any_private(void)\r
+{\r
+       HANDLE handles[256];\r
+       DWORD retval, which;\r
+       int i;\r
+\r
+       if (!proc_index)\r
+               return NULL;\r
+\r
+       /* build array of handles to wait for */\r
+       for (i = 0; i < proc_index; i++) {\r
+               handles[i] = (HANDLE) proc_array[i]->pid;\r
+\r
+               if (fake_exits_pending && proc_array[i]->exit_code)\r
+                       break;\r
+       }\r
+\r
+       /* wait for someone to exit */\r
+       if (!fake_exits_pending) {\r
+               retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);\r
+               which = retval - WAIT_OBJECT_0;\r
+       } else {\r
+               fake_exits_pending--;\r
+               retval = !WAIT_FAILED;\r
+               which = i;\r
+       }\r
+\r
+       /* return pointer to process */\r
+       if (retval != WAIT_FAILED) {\r
+               sub_process* pproc = proc_array[which]; \r
+               process_adjust_wait_state(pproc);\r
+               return pproc;\r
+       } else\r
+               return NULL;\r
+}\r
+\r
+/*\r
+ * Terminate a process.\r
+ */\r
+BOOL\r
+process_kill(HANDLE proc, int signal)\r
+{\r
+       sub_process* pproc = (sub_process*) proc;\r
+       pproc->signal = signal;\r
+       return (TerminateProcess((HANDLE) pproc->pid, signal));\r
+}\r
+\r
+/*\r
+ * Use this function to register processes you wish to wait for by\r
+ * calling process_file_io(NULL) or process_wait_any(). This must be done \r
+ * because it is possible for callers of this library to reuse the same \r
+ * handle for multiple processes launches :-(\r
+ */\r
+void\r
+process_register(HANDLE proc)\r
+{\r
+       proc_array[proc_index++] = (sub_process *) proc;\r
+}\r
+\r
+/*\r
+ * Public function which works kind of like waitpid(). Wait for any\r
+ * of the children to die and return results. To call this function,\r
+ * you must do 1 of things:\r
+ *\r
+ *     x = process_easy(...);\r
+ *     \r
+ * or\r
+ *\r
+ *     x = process_init_fd();\r
+ *     process_register(x);\r
+ *\r
+ * or\r
+ *\r
+ *     x = process_init();\r
+ *     process_register(x);\r
+ *\r
+ * You must NOT then call process_pipe_io() because this function is\r
+ * not capable of handling automatic notification of any child\r
+ * death.\r
+ */\r
+\r
+HANDLE\r
+process_wait_for_any(void)\r
+{\r
+       sub_process* pproc = process_wait_for_any_private(); \r
+\r
+       if (!pproc)\r
+               return NULL;\r
+       else {\r
+               /* \r
+                * Ouch! can't tell caller if this fails directly. Caller \r
+                * will have to use process_last_err() \r
+                 */\r
+               (void) process_file_io(pproc);\r
+               return ((HANDLE) pproc);\r
+       }\r
+}\r
+\r
+long\r
+process_errno(HANDLE proc)\r
+{\r
+       return (((sub_process *)proc)->lerrno);\r
+}\r
+\r
+long\r
+process_signal(HANDLE proc)\r
+{\r
+       return (((sub_process *)proc)->signal);\r
+}\r
+\r
+       long\r
+process_last_err(HANDLE proc)\r
+{\r
+       return (((sub_process *)proc)->last_err);\r
+}\r
+\r
+       long\r
+process_exit_code(HANDLE proc)\r
+{\r
+       return (((sub_process *)proc)->exit_code);\r
+}\r
+\r
+       char *\r
+process_outbuf(HANDLE proc)\r
+{\r
+       return (((sub_process *)proc)->outp);\r
+}\r
+\r
+       char *\r
+process_errbuf(HANDLE proc)\r
+{\r
+       return (((sub_process *)proc)->errp);\r
+}\r
+\r
+       int\r
+process_outcnt(HANDLE proc)\r
+{\r
+       return (((sub_process *)proc)->outcnt);\r
+}\r
+\r
+       int\r
+process_errcnt(HANDLE proc)\r
+{\r
+       return (((sub_process *)proc)->errcnt);\r
+}\r
+\r
+       void\r
+process_pipes(HANDLE proc, int pipes[3])\r
+{\r
+       pipes[0] = ((sub_process *)proc)->sv_stdin[0];\r
+       pipes[1] = ((sub_process *)proc)->sv_stdout[0];\r
+       pipes[2] = ((sub_process *)proc)->sv_stderr[0];\r
+       return;\r
+}\r
+\r
+\r
+       HANDLE\r
+process_init()\r
+{\r
+       sub_process *pproc;\r
+       /*\r
+        * open file descriptors for attaching stdin/stdout/sterr\r
+        */\r
+       HANDLE stdin_pipes[2];\r
+       HANDLE stdout_pipes[2];\r
+       HANDLE stderr_pipes[2];\r
+       SECURITY_ATTRIBUTES inherit;\r
+       BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];\r
+\r
+       pproc = malloc(sizeof(*pproc));\r
+       memset(pproc, 0, sizeof(*pproc));\r
+\r
+       /* We can't use NULL for lpSecurityDescriptor because that\r
+          uses the default security descriptor of the calling process.\r
+          Instead we use a security descriptor with no DACL.  This\r
+          allows nonrestricted access to the associated objects. */\r
+       \r
+       if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),\r
+                                         SECURITY_DESCRIPTOR_REVISION)) {\r
+               pproc->last_err = GetLastError();\r
+               pproc->lerrno = E_SCALL;\r
+               return((HANDLE)pproc);\r
+       }\r
+\r
+       inherit.nLength = sizeof(inherit);\r
+       inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);\r
+       inherit.bInheritHandle = TRUE;\r
+\r
+       // By convention, parent gets pipe[0], and child gets pipe[1]\r
+       // This means the READ side of stdin pipe goes into pipe[1]\r
+       // and the WRITE side of the stdout and stderr pipes go into pipe[1]\r
+       if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||\r
+       CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||\r
+       CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {\r
+\r
+               pproc->last_err = GetLastError();\r
+               pproc->lerrno = E_SCALL;\r
+               return((HANDLE)pproc);\r
+       }\r
+\r
+       //\r
+       // Mark the parent sides of the pipes as non-inheritable\r
+       //\r
+       if (SetHandleInformation(stdin_pipes[0], \r
+                               HANDLE_FLAG_INHERIT, 0) == FALSE ||\r
+               SetHandleInformation(stdout_pipes[0], \r
+                               HANDLE_FLAG_INHERIT, 0) == FALSE ||\r
+               SetHandleInformation(stderr_pipes[0], \r
+                               HANDLE_FLAG_INHERIT, 0) == FALSE) {\r
+\r
+               pproc->last_err = GetLastError();\r
+               pproc->lerrno = E_SCALL;\r
+               return((HANDLE)pproc);\r
+       }\r
+       pproc->sv_stdin[0]  = (int) stdin_pipes[0];\r
+       pproc->sv_stdin[1]  = (int) stdin_pipes[1];\r
+       pproc->sv_stdout[0] = (int) stdout_pipes[0];\r
+       pproc->sv_stdout[1] = (int) stdout_pipes[1];\r
+       pproc->sv_stderr[0] = (int) stderr_pipes[0];\r
+       pproc->sv_stderr[1] = (int) stderr_pipes[1];\r
+\r
+       pproc->using_pipes = 1;\r
+\r
+       pproc->lerrno = 0;\r
+\r
+       return((HANDLE)pproc);\r
+}\r
+\r
+\r
+       HANDLE\r
+process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)\r
+{\r
+       sub_process *pproc;\r
+\r
+       pproc = malloc(sizeof(*pproc));\r
+       memset(pproc, 0, sizeof(*pproc));\r
+\r
+       /*\r
+        * Just pass the provided file handles to the 'child side' of the\r
+        * pipe, bypassing pipes altogether.\r
+        */\r
+       pproc->sv_stdin[1]  = (int) stdinh;\r
+       pproc->sv_stdout[1] = (int) stdouth;\r
+       pproc->sv_stderr[1] = (int) stderrh;\r
+\r
+       pproc->last_err = pproc->lerrno = 0;\r
+\r
+       return((HANDLE)pproc);\r
+}\r
+\r
+\r
+static HANDLE\r
+find_file(char *exec_path, LPOFSTRUCT file_info)\r
+{\r
+       HANDLE exec_handle;\r
+       char *fname;\r
+       char *ext;\r
+\r
+       if ((exec_handle = (HANDLE)OpenFile(exec_path, file_info,\r
+                       OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {\r
+               return(exec_handle);\r
+       }\r
+\r
+       fname = malloc(strlen(exec_path) + 5);\r
+       strcpy(fname, exec_path);\r
+       ext = fname + strlen(fname);\r
+       strcpy(ext, ".exe");\r
+       if ((exec_handle = (HANDLE)OpenFile(fname, file_info,\r
+                       OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {\r
+               free(fname);\r
+               return(exec_handle);\r
+       }\r
+\r
+       strcpy(ext, ".bat");\r
+       if ((exec_handle = (HANDLE)OpenFile(fname, file_info,\r
+                       OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {\r
+               free(fname);\r
+               return(exec_handle);\r
+       }\r
+\r
+       strcpy(ext, ".com");\r
+       if ((exec_handle = (HANDLE)OpenFile(fname, file_info,\r
+                       OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {\r
+               free(fname);\r
+               return(exec_handle);\r
+       }\r
+\r
+       free(fname);\r
+       return(exec_handle);\r
+}\r
+\r
+\r
+/*\r
+ * Description:   Create the child process to be helped\r
+ *\r
+ * Returns: \r
+ *\r
+ * Notes/Dependencies:  \r
+ */\r
+long\r
+process_begin(\r
+       HANDLE proc,\r
+       char **argv,\r
+       char **envp,\r
+       char *exec_path,\r
+       char *as_user)\r
+{\r
+       sub_process *pproc = (sub_process *)proc;\r
+       char *shell_name = 0;\r
+       int file_not_found=0;\r
+       HANDLE exec_handle;\r
+       char buf[256];\r
+       DWORD bytes_returned;\r
+       DWORD flags;\r
+       char *command_line;\r
+       STARTUPINFO startInfo;\r
+       PROCESS_INFORMATION procInfo;\r
+       char *envblk=NULL;\r
+       OFSTRUCT file_info;\r
+\r
+\r
+       /*\r
+        *  Shell script detection...  if the exec_path starts with #! then\r
+        *  we want to exec shell-script-name exec-path, not just exec-path\r
+        *  NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl.  We do not\r
+        *  hard-code the path to the shell or perl or whatever:  Instead, we\r
+        *  assume it's in the path somewhere (generally, the NT tools\r
+        *  bin directory)\r
+        *  We use OpenFile here because it is capable of searching the Path.\r
+        */\r
+\r
+       exec_handle = find_file(exec_path, &file_info);\r
+\r
+       /*\r
+        * If we couldn't open the file, just assume that Win32 will be able\r
+        * to find and execute it.\r
+        */\r
+       if (exec_handle == (HANDLE)HFILE_ERROR) {\r
+               file_not_found++;\r
+       }\r
+       else {\r
+               /* Attempt to read the first line of the file */\r
+               if (ReadFile( exec_handle, \r
+                               buf, sizeof(buf) - 1, /* leave room for trailing NULL */\r
+                               &bytes_returned, 0) == FALSE || bytes_returned < 2) {\r
+       \r
+                       pproc->last_err = GetLastError();\r
+                       pproc->lerrno = E_IO;\r
+                       CloseHandle(exec_handle);\r
+                       return(-1);\r
+               }\r
+               if (buf[0] == '#' && buf[1] == '!') {\r
+                       /*\r
+                        *  This is a shell script...  Change the command line from\r
+                        *      exec_path args to shell_name exec_path args\r
+                        */\r
+                       char *p;\r
+       \r
+                       /*  Make sure buf is NULL terminated */\r
+                       buf[bytes_returned] = 0;\r
+                       /*\r
+                        * Depending on the file system type, etc. the first line\r
+                        * of the shell script may end with newline or newline-carriage-return\r
+                        * Whatever it ends with, cut it off.\r
+                        */\r
+                       p= strchr(buf, '\n');\r
+                       if (p)\r
+                               *p = 0;\r
+                       p = strchr(buf, '\r');\r
+                       if (p)\r
+                               *p = 0;\r
+               \r
+                       /*\r
+                        *  Find base name of shell\r
+                        */\r
+                       shell_name = strrchr( buf, '/');\r
+                       if (shell_name) {\r
+                               shell_name++;\r
+                       } else {\r
+                               shell_name = &buf[2];/* skipping "#!" */\r
+                       }\r
+\r
+               } \r
+               CloseHandle(exec_handle);\r
+       }\r
+\r
+       flags = 0;\r
+\r
+       if (file_not_found)\r
+               command_line = make_command_line( shell_name, exec_path, argv);\r
+       else\r
+               command_line = make_command_line( shell_name, file_info.szPathName,\r
+                                argv);\r
+\r
+       if ( command_line == NULL ) {\r
+               pproc->last_err = 0;\r
+               pproc->lerrno = E_NO_MEM;\r
+               return(-1);\r
+       }\r
+\r
+       if (envp) {\r
+               if (arr2envblk(envp, &envblk) ==FALSE) {\r
+                       pproc->last_err = 0;\r
+                       pproc->lerrno = E_NO_MEM;\r
+                       free( command_line );\r
+                       return(-1);\r
+               }\r
+       }\r
+\r
+       if ((shell_name) || (file_not_found)) {\r
+               exec_path = 0;  /* Search for the program in %Path% */\r
+       } else {\r
+               exec_path = file_info.szPathName;\r
+       }\r
+\r
+       /*\r
+        *  Set up inherited stdin, stdout, stderr for child\r
+        */\r
+       GetStartupInfo(&startInfo);\r
+       startInfo.dwFlags = STARTF_USESTDHANDLES;\r
+       startInfo.lpReserved = 0;\r
+       startInfo.cbReserved2 = 0;\r
+       startInfo.lpReserved2 = 0;\r
+       startInfo.lpTitle = shell_name ? shell_name : exec_path;\r
+       startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];\r
+       startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];\r
+       startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];\r
+\r
+       /*\r
+        * See if we need to setuid to a different user.\r
+        */\r
+       if (as_user) {\r
+               return -1;\r
+       }\r
+\r
+       if (as_user) {\r
+               return -1;\r
+       } else {\r
+               if (CreateProcess(\r
+                       exec_path,\r
+                       command_line,\r
+                       NULL,\r
+                       0, /* default security attributes for thread */\r
+                       TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */\r
+                       flags, \r
+                       envblk,\r
+                       0, /* default starting directory */\r
+                       &startInfo,\r
+                       &procInfo) == FALSE) {\r
+               \r
+                       pproc->last_err = GetLastError();\r
+                       pproc->lerrno = E_FORK;\r
+                       fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path, command_line);\r
+                       free( command_line );\r
+                       return(-1);\r
+               }\r
+       }\r
+       \r
+       pproc->pid = (int)procInfo.hProcess;\r
+       /* Close the thread handle -- we'll just watch the process */\r
+       CloseHandle(procInfo.hThread);\r
+       \r
+       /* Close the halves of the pipes we don't need */\r
+       if (pproc->sv_stdin) {\r
+               CloseHandle((HANDLE)pproc->sv_stdin[1]);\r
+               (HANDLE)pproc->sv_stdin[1] = 0;\r
+       }\r
+       if (pproc->sv_stdout) {\r
+               CloseHandle((HANDLE)pproc->sv_stdout[1]);\r
+               (HANDLE)pproc->sv_stdout[1] = 0;\r
+       }\r
+       if (pproc->sv_stderr) {\r
+               CloseHandle((HANDLE)pproc->sv_stderr[1]);\r
+               (HANDLE)pproc->sv_stderr[1] = 0;\r
+       }\r
+\r
+       free( command_line );\r
+       pproc->lerrno=0;\r
+       return 0;\r
+}\r
+\r
+\r
+\r
+static DWORD \r
+proc_stdin_thread(sub_process *pproc)\r
+{\r
+       DWORD in_done;\r
+       for (;;) {\r
+               if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,\r
+                                        &in_done, NULL) == FALSE)\r
+                       _endthreadex(0);\r
+               // This if should never be true for anonymous pipes, but gives\r
+               // us a chance to change I/O mechanisms later\r
+               if (in_done < pproc->incnt) {\r
+                       pproc->incnt -= in_done;\r
+                       pproc->inp += in_done;\r
+               } else {\r
+                       _endthreadex(0);\r
+               }\r
+       }\r
+       return 0; // for compiler warnings only.. not reached\r
+}\r
+\r
+static DWORD\r
+proc_stdout_thread(sub_process *pproc)\r
+{\r
+       DWORD bufsize = 1024;\r
+       char c;\r
+       DWORD nread;\r
+       pproc->outp = malloc(bufsize);\r
+       if (pproc->outp == NULL)\r
+               _endthreadex(0);\r
+       pproc->outcnt = 0;\r
+\r
+       for (;;) {\r
+               if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL) \r
+                                       == FALSE) {\r
+/*                     map_win32_error_to_string(GetLastError());*/\r
+                       _endthreadex(0);\r
+               }\r
+               if (nread == 0)\r
+                       _endthreadex(0);\r
+               if (pproc->outcnt + nread > bufsize) {\r
+                       bufsize += nread + 512; \r
+                       pproc->outp = realloc(pproc->outp, bufsize);\r
+                       if (pproc->outp == NULL) {\r
+                               pproc->outcnt = 0;\r
+                               _endthreadex(0);\r
+                       }\r
+               }\r
+               pproc->outp[pproc->outcnt++] = c;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static DWORD\r
+proc_stderr_thread(sub_process *pproc)\r
+{\r
+       DWORD bufsize = 1024;\r
+       char c;\r
+       DWORD nread;\r
+       pproc->errp = malloc(bufsize);\r
+       if (pproc->errp == NULL)\r
+               _endthreadex(0);\r
+       pproc->errcnt = 0;\r
+\r
+       for (;;) {\r
+               if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {\r
+                       map_win32_error_to_string(GetLastError());\r
+                       _endthreadex(0);\r
+               }\r
+               if (nread == 0)\r
+                       _endthreadex(0);\r
+               if (pproc->errcnt + nread > bufsize) {\r
+                       bufsize += nread + 512; \r
+                       pproc->errp = realloc(pproc->errp, bufsize);\r
+                       if (pproc->errp == NULL) {\r
+                               pproc->errcnt = 0;\r
+                               _endthreadex(0);\r
+                       }\r
+               }\r
+               pproc->errp[pproc->errcnt++] = c;\r
+       }\r
+       return 0;\r
+}\r
+\r
+\r
+/*\r
+ * Purpose: collects output from child process and returns results\r
+ *\r
+ * Description:\r
+ *\r
+ * Returns: \r
+ *\r
+ * Notes/Dependencies:\r
+ */\r
+       long\r
+process_pipe_io(\r
+       HANDLE proc,\r
+       char *stdin_data, \r
+       int stdin_data_len)\r
+{\r
+       sub_process *pproc = (sub_process *)proc;\r
+       bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;\r
+       HANDLE childhand = (HANDLE) pproc->pid;\r
+       HANDLE tStdin, tStdout, tStderr;\r
+       DWORD dwStdin, dwStdout, dwStderr;\r
+       HANDLE wait_list[4];\r
+       DWORD wait_count;\r
+       DWORD wait_return;\r
+       HANDLE ready_hand;\r
+       bool_t child_dead = FALSE;\r
+\r
+\r
+       /*\r
+        *  Create stdin thread, if needed\r
+        */\r
+    pproc->inp = stdin_data;\r
+    pproc->incnt = stdin_data_len;\r
+       if (!pproc->inp) {\r
+               stdin_eof = TRUE;\r
+               CloseHandle((HANDLE)pproc->sv_stdin[0]);\r
+               (HANDLE)pproc->sv_stdin[0] = 0;\r
+       } else {\r
+               tStdin = (HANDLE) _beginthreadex( 0, 1024,\r
+                       (unsigned (__stdcall *) (void *))proc_stdin_thread, pproc, 0,\r
+                       (unsigned int *) &dwStdin);\r
+               if (tStdin == 0) {\r
+                       pproc->last_err = GetLastError();\r
+                       pproc->lerrno = E_SCALL;\r
+                       goto done;\r
+               }\r
+       }\r
+       \r
+       /*\r
+        *   Assume child will produce stdout and stderr\r
+        */ \r
+       tStdout = (HANDLE) _beginthreadex( 0, 1024,\r
+               (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,\r
+               (unsigned int *) &dwStdout);\r
+       tStderr = (HANDLE) _beginthreadex( 0, 1024,\r
+               (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,\r
+               (unsigned int *) &dwStderr);\r
+       \r
+       if (tStdout == 0 || tStderr == 0) {\r
+       \r
+               pproc->last_err = GetLastError();\r
+               pproc->lerrno = E_SCALL;\r
+               goto done;\r
+       }\r
+\r
+\r
+       /*\r
+        *  Wait for all I/O to finish and for the child process to exit\r
+        */\r
+\r
+       while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {\r
+               wait_count = 0;\r
+               if (!stdin_eof) {\r
+                       wait_list[wait_count++] = tStdin;\r
+               }\r
+               if (!stdout_eof) {\r
+                       wait_list[wait_count++] = tStdout;\r
+               }\r
+               if (!stderr_eof) {\r
+                       wait_list[wait_count++] = tStderr;\r
+               }\r
+               if (!child_dead) {\r
+                       wait_list[wait_count++] = childhand;\r
+               }\r
+               \r
+               wait_return = WaitForMultipleObjects(wait_count, wait_list,\r
+                        FALSE, /* don't wait for all: one ready will do */\r
+                        child_dead? 1000 :INFINITE); /* after the child dies, subthreads have\r
+                               one second to collect all remaining output */\r
+               \r
+               if (wait_return == WAIT_FAILED) {\r
+/*                     map_win32_error_to_string(GetLastError());*/\r
+                       pproc->last_err = GetLastError();\r
+                       pproc->lerrno = E_SCALL;\r
+                       goto done;\r
+               }\r
+\r
+               ready_hand = wait_list[wait_return - WAIT_OBJECT_0];\r
+               \r
+               if (ready_hand == tStdin) {\r
+                       CloseHandle((HANDLE)pproc->sv_stdin[0]);\r
+                       (HANDLE)pproc->sv_stdin[0] = 0;\r
+                       CloseHandle(tStdin);\r
+                       tStdin = 0;\r
+                       stdin_eof = TRUE;\r
+               \r
+               } else if (ready_hand == tStdout) {\r
+               \r
+                       CloseHandle((HANDLE)pproc->sv_stdout[0]);\r
+                       (HANDLE)pproc->sv_stdout[0] = 0;\r
+                       CloseHandle(tStdout);\r
+                       tStdout = 0;\r
+                       stdout_eof = TRUE;\r
+               \r
+               } else if (ready_hand == tStderr) {\r
+                       \r
+                       CloseHandle((HANDLE)pproc->sv_stderr[0]);\r
+                       (HANDLE)pproc->sv_stderr[0] = 0;\r
+                       CloseHandle(tStderr);\r
+                       tStderr = 0;\r
+                       stderr_eof = TRUE;\r
+               \r
+               } else if (ready_hand == childhand) {\r
+                       \r
+                       if (GetExitCodeProcess(childhand, &pproc->exit_code) == FALSE) {\r
+                               pproc->last_err = GetLastError();\r
+                               pproc->lerrno = E_SCALL;\r
+                               goto done;\r
+                       }\r
+                       child_dead = TRUE;\r
+       \r
+               } else {\r
+               \r
+                       /* ?? Got back a handle we didn't query ?? */\r
+                       pproc->last_err = 0;\r
+                       pproc->lerrno = E_FAIL;\r
+                       goto done;\r
+               }\r
+       }\r
\r
+ done:\r
+       if (tStdin != 0)\r
+               CloseHandle(tStdin);\r
+       if (tStdout != 0)\r
+               CloseHandle(tStdout);\r
+       if (tStderr != 0)\r
+               CloseHandle(tStderr);\r
+\r
+       if (pproc->lerrno)\r
+               return(-1);\r
+       else\r
+               return(0);\r
+\r
+}\r
+\r
+/*\r
+ * Purpose: collects output from child process and returns results\r
+ *\r
+ * Description:\r
+ *\r
+ * Returns: \r
+ *\r
+ * Notes/Dependencies:\r
+ */\r
+       long\r
+process_file_io(\r
+       HANDLE proc)\r
+{\r
+       sub_process *pproc;\r
+       HANDLE childhand;\r
+       DWORD wait_return;\r
+\r
+       if (proc == NULL)\r
+               pproc = process_wait_for_any_private();\r
+       else\r
+               pproc = (sub_process *)proc;\r
+\r
+       /* some sort of internal error */\r
+       if (!pproc)\r
+               return -1;\r
+\r
+       childhand = (HANDLE) pproc->pid;\r
+\r
+       /*\r
+        * This function is poorly named, and could also be used just to wait\r
+        * for child death if you're doing your own pipe I/O.  If that is \r
+        * the case, close the pipe handles here.\r
+        */\r
+       if (pproc->sv_stdin[0]) {\r
+               CloseHandle((HANDLE)pproc->sv_stdin[0]);\r
+               pproc->sv_stdin[0] = 0;\r
+       }\r
+       if (pproc->sv_stdout[0]) {\r
+               CloseHandle((HANDLE)pproc->sv_stdout[0]);\r
+               pproc->sv_stdout[0] = 0;\r
+       }\r
+       if (pproc->sv_stderr[0]) {\r
+               CloseHandle((HANDLE)pproc->sv_stderr[0]);\r
+               pproc->sv_stderr[0] = 0;\r
+       }\r
+\r
+       /*\r
+        *  Wait for the child process to exit\r
+        */\r
+\r
+       wait_return = WaitForSingleObject(childhand, INFINITE);\r
+               \r
+       if (wait_return != WAIT_OBJECT_0) {\r
+/*             map_win32_error_to_string(GetLastError());*/\r
+               pproc->last_err = GetLastError();\r
+               pproc->lerrno = E_SCALL;\r
+               goto done2;\r
+       }\r
+\r
+       if (GetExitCodeProcess(childhand, &pproc->exit_code) == FALSE) {\r
+               pproc->last_err = GetLastError();\r
+               pproc->lerrno = E_SCALL;\r
+       }\r
+       \r
+done2:\r
+       if (pproc->lerrno)\r
+               return(-1);\r
+       else\r
+               return(0);\r
+\r
+}\r
+\r
+/*\r
+ * Description:  Clean up any leftover handles, etc.  It is up to the\r
+ * caller to manage and free the input, ouput, and stderr buffers.\r
+ */\r
+       void\r
+process_cleanup(\r
+       HANDLE proc)\r
+{\r
+       sub_process *pproc = (sub_process *)proc;\r
+       int i;\r
+\r
+       if (pproc->using_pipes) {\r
+               for (i= 0; i <= 1; i++) {\r
+                       if ((HANDLE)pproc->sv_stdin[i])\r
+                               CloseHandle((HANDLE)pproc->sv_stdin[i]);\r
+                       if ((HANDLE)pproc->sv_stdout[i])\r
+                               CloseHandle((HANDLE)pproc->sv_stdout[i]);\r
+                       if ((HANDLE)pproc->sv_stderr[i])\r
+                               CloseHandle((HANDLE)pproc->sv_stderr[i]);\r
+               }\r
+       }\r
+       if ((HANDLE)pproc->pid)\r
+               CloseHandle((HANDLE)pproc->pid);\r
+       \r
+       free(pproc);\r
+}\r
+\r
+\r
+/*\r
+ * Try to protect against WIN32 argument munging. This function takes\r
+ * an argv vector and outputs a 'protected' string as a return\r
+ * value. The return code can be safely passed to CreateProcess().\r
+ *\r
+ * The caller should free the return value.\r
+ */\r
+\r
+#define TRACE(x)\r
+static char *fix_command_line(char *args[])\r
+{\r
+       int i;\r
+       char *narg;\r
+       char *nargp;\r
+       char *p;\r
+       char *q;\r
+       int alloc_len = 0;\r
+\r
+       for (i = 0; args[i]; i++)\r
+               alloc_len += ((strlen(args[i]) * 2) + 1);\r
+       /* account for possible enclosing quotes and null termination */\r
+       alloc_len += 3;\r
+\r
+       nargp = narg = malloc(alloc_len);\r
+\r
+       for (i = 0; args[i]; i++) {\r
+               p = args[i];\r
+               TRACE(("original arg: %s\n", p));\r
+\r
+               if (*p == '\0') {\r
+                       *nargp++ = '"';\r
+                       *nargp++ = '"';\r
+                       *nargp = '\0';\r
+                       TRACE(("empty string arg: %s\n", nargp-2));\r
+               } else if (strpbrk(p, "\" \t")) {\r
+                       /* point to end of copy buffer */\r
+                       q = narg;\r
+                       q += (alloc_len-1);\r
+                       *q-- = '\0'; /* ensure null terminated string */\r
+                       *q-- = '"';  /* terminating quote of argument */\r
+\r
+                       /* point to end of the input string */\r
+                       p = args[i];\r
+                       p += strlen(args[i]);\r
+                       p--;\r
+\r
+                       /* \r
+                        * Because arg is quoted, escape any backslashes \r
+                        * that might occur at the end of the string which\r
+                        * proceed the closing quote.\r
+                        * Example:\r
+                        *      foo c:\\r
+                        * Becomes:\r
+                        *      "foo c:\\"\r
+                        */\r
+                       while (*p == '\\')\r
+                               *q-- = *p--, *q-- = '\\';\r
+\r
+                       /* copy the string in reverse */\r
+                       while (p >= args[i]) {\r
+                               /* copy the character */\r
+                               *q-- = *p--;\r
+\r
+                               /* \r
+                                * Escape any double quote found. Also escape\r
+                                * each backslash preceding the double quote.\r
+                                */\r
+                               if (*(p+1) == '"') {\r
+                                       *q-- = '\\';\r
+                                       if (p >= args[i] && *p == '\\')\r
+                                               while (p >= args[i] && *p == '\\')\r
+                                                       *q-- = *p--, *q-- = '\\';\r
+                               }\r
+                       }\r
+\r
+                       /* finish quoting arg, q now points to complete arg */\r
+                       *q = '"';\r
+\r
+                       /* rejustify */\r
+                       memmove(nargp, q, strlen(q) + 1);\r
+                       TRACE(("arg with white space or doublequotes: %s\n", nargp));\r
+                       nargp += strlen(nargp);\r
+               } else {\r
+                       /* just copy the argument, no protection needed */\r
+                       strcpy(nargp, args[i]);\r
+                       TRACE(("plain arg: %s\n", nargp));\r
+                       nargp += strlen(nargp);\r
+               }\r
+\r
+               /* separate arguments with spaces (if more args to gather) */\r
+               if (args[i+1])\r
+                       *nargp++ = ' ';\r
+               *nargp   = '\0';\r
+       } /* end for */\r
+\r
+       /* NULL terminate the arg list */\r
+       *nargp = '\0';\r
+\r
+       return (narg);\r
+}\r
+#undef TRACE\r
+\r
+/*\r
+ * Description: \r
+ *      Create a command line buffer to pass to CreateProcess\r
+ *\r
+ * Returns:  the buffer or NULL for failure\r
+ *     Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...\r
+ *  Otherwise:   argv[0] argv[1] argv[2] ...\r
+ *\r
+ * Notes/Dependencies: \r
+ *   CreateProcess does not take an argv, so this command creates a\r
+ *   command line for the executable.  \r
+ */\r
+\r
+static char *\r
+make_command_line( char *shell_name, char *exec_path, char **argv)\r
+{\r
+       char** nargv;\r
+       char*  buf;\r
+       int    i;\r
\r
+       if (shell_name) {\r
+               for (i = 0; argv[i]; i++);\r
+               i += 2;\r
+               nargv = (char **) malloc(i * sizeof (char *));\r
+               nargv[0] = shell_name;\r
+               for (i = 1; argv[i-1]; i++)\r
+                       nargv[i] = argv[i-1];\r
+               nargv[i] = NULL;\r
+       } else\r
+               nargv = argv;\r
+\r
+       /* create string suitable for CreateProcess() */\r
+       buf = fix_command_line(nargv);\r
+\r
+       if (shell_name)\r
+               free(nargv);\r
+       \r
+       return buf;\r
+}\r
+\r
+/*\r
+ * Description: Given an argv and optional envp, launch the process\r
+ *              using the default stdin, stdout, and stderr handles.\r
+ *              Also, register process so that process_wait_for_any_private()\r
+ *             can be used via process_file_io(NULL) or \r
+ *             process_wait_for_any().\r
+ *\r
+ * Returns: \r
+ *\r
+ * Notes/Dependencies:  \r
+ */\r
+HANDLE\r
+process_easy(\r
+       char **argv,\r
+       char **envp)\r
+{\r
+  HANDLE hIn;\r
+  HANDLE hOut;\r
+  HANDLE hErr;\r
+  HANDLE hProcess;\r
+\r
+  if (DuplicateHandle(GetCurrentProcess(),\r
+                      GetStdHandle(STD_INPUT_HANDLE),\r
+                      GetCurrentProcess(),\r
+                      &hIn,\r
+                      0,\r
+                      TRUE,\r
+                      DUPLICATE_SAME_ACCESS) == FALSE) {\r
+    fprintf(stderr,\r
+            "process_easy: DuplicateHandle(In) failed (e=%d)\n",\r
+            GetLastError());\r
+    return INVALID_HANDLE_VALUE;\r
+  }\r
+  if (DuplicateHandle(GetCurrentProcess(),\r
+                      GetStdHandle(STD_OUTPUT_HANDLE),\r
+                      GetCurrentProcess(),\r
+                      &hOut,\r
+                      0,\r
+                      TRUE,\r
+                      DUPLICATE_SAME_ACCESS) == FALSE) {\r
+    fprintf(stderr,\r
+           "process_easy: DuplicateHandle(Out) failed (e=%d)\n",\r
+           GetLastError());\r
+    return INVALID_HANDLE_VALUE;\r
+  }\r
+  if (DuplicateHandle(GetCurrentProcess(),\r
+                      GetStdHandle(STD_ERROR_HANDLE),\r
+                      GetCurrentProcess(),\r
+                      &hErr,\r
+                      0,\r
+                      TRUE,\r
+                      DUPLICATE_SAME_ACCESS) == FALSE) {\r
+    fprintf(stderr,\r
+            "process_easy: DuplicateHandle(Err) failed (e=%d)\n",\r
+            GetLastError());\r
+    return INVALID_HANDLE_VALUE;\r
+  }\r
+\r
+  hProcess = process_init_fd(hIn, hOut, hErr);\r
+\r
+  if (process_begin(hProcess, argv, envp, argv[0], NULL)) {\r
+    fake_exits_pending++;\r
+    ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);\r
+\r
+    /* close up unused handles */\r
+    CloseHandle(hIn);\r
+    CloseHandle(hOut);\r
+    CloseHandle(hErr);\r
+  }\r
+\r
+  process_register(hProcess);\r
+\r
+  return hProcess;\r
+}\r
index e4e8835..8abd75b 100644 (file)
@@ -1,51 +1,51 @@
-#include <windows.h>
-#include "w32err.h"
-
-/*
- * Description: the win32 version of perror()
- *
- * Returns:  a pointer to a static error
- *
- * Notes/Dependencies:  I got this from 
- *      comp.os.ms-windows.programmer.win32
- */
-char * 
-map_win32_error_to_string (DWORD ercode) {
-/* __declspec (thread) necessary if you will use multiple threads */
-__declspec (thread) static char szMessageBuffer[128];
-       /* Fill message buffer with a default message in 
-        * case FormatMessage fails 
-        */
-    wsprintf (szMessageBuffer, "Error %ld", ercode);
-
-       /*
-        *  Special code for winsock error handling.
-        */
-       if (ercode > WSABASEERR) {
-               HMODULE hModule = GetModuleHandle("wsock32");
-               if (hModule != NULL) {
-                       FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
-                               hModule,
-                               ercode,
-                               LANG_NEUTRAL,
-                               szMessageBuffer,
-                               sizeof(szMessageBuffer),
-                               NULL);
-                       FreeLibrary(hModule);
-               } 
-       } else {
-               /*
-                *  Default system message handling
-                */
-       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
-                  NULL,
-                  ercode,
-                  LANG_NEUTRAL,
-                  szMessageBuffer,
-                  sizeof(szMessageBuffer),
-                  NULL);
-       }
-    return szMessageBuffer;
-}
+#include <windows.h>\r
+#include "w32err.h"\r
+\r
+/*\r
+ * Description: the win32 version of perror()\r
+ *\r
+ * Returns:  a pointer to a static error\r
+ *\r
+ * Notes/Dependencies:  I got this from \r
+ *      comp.os.ms-windows.programmer.win32\r
+ */\r
+char * \r
+map_win32_error_to_string (DWORD ercode) {\r
+/* __declspec (thread) necessary if you will use multiple threads */\r
+__declspec (thread) static char szMessageBuffer[128];\r
\r
+       /* Fill message buffer with a default message in \r
+        * case FormatMessage fails \r
+        */\r
+    wsprintf (szMessageBuffer, "Error %ld", ercode);\r
+\r
+       /*\r
+        *  Special code for winsock error handling.\r
+        */\r
+       if (ercode > WSABASEERR) {\r
+               HMODULE hModule = GetModuleHandle("wsock32");\r
+               if (hModule != NULL) {\r
+                       FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,\r
+                               hModule,\r
+                               ercode,\r
+                               LANG_NEUTRAL,\r
+                               szMessageBuffer,\r
+                               sizeof(szMessageBuffer),\r
+                               NULL);\r
+                       FreeLibrary(hModule);\r
+               } \r
+       } else {\r
+               /*\r
+                *  Default system message handling\r
+                */\r
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,\r
+                  NULL,\r
+                  ercode,\r
+                  LANG_NEUTRAL,\r
+                  szMessageBuffer,\r
+                  sizeof(szMessageBuffer),\r
+                  NULL);\r
+       }\r
+    return szMessageBuffer;\r
+}\r
\r