dlls/msvcrt: msvcrt-popen-1.1

Jaco Greeff jaco at puxedo.org
Fri Nov 1 07:16:58 CST 2002


This patch is to be applied over the "msvcrt-popen-1" patch released 
earlier today. This patch fixes the issue of only one "_popen" call 
allowed open at any point, i.e. multiple calls to _popen/_wpopen can be 
made without clsing the first _popen call first.

License:
LGPL

Changelog:
* dlls/msvcrt/msvcrt.h, dlls/msvcrt/main.c. dlls/msvcrt/process.c: Jaco 
Greeff <jaco at puxedo.org>
- Add the ability to have multiple open processes via the 
_popen/_wpopen/_pclose calls

----------------------------

diff -aurN msvcrt-popen.orig/dlls/msvcrt/main.c 
msvcrt-popen.new/dlls/msvcrt/main.c
--- msvcrt-popen.orig/dlls/msvcrt/main.c	Fri Nov  1 14:24:21 2002
+++ msvcrt-popen.new/dlls/msvcrt/main.c	Fri Nov  1 14:26:38 2002
@@ -58,6 +58,7 @@
      msvcrt_init_io();
      msvcrt_init_console();
      msvcrt_init_args();
+    msvcrt_init_process();
      MSVCRT_setlocale(0, "C");
      TRACE("finished process init\n");
      break;
diff -aurN msvcrt-popen.orig/dlls/msvcrt/msvcrt.h 
msvcrt-popen.new/dlls/msvcrt/msvcrt.h
--- msvcrt-popen.orig/dlls/msvcrt/msvcrt.h	Fri Nov  1 14:24:03 2002
+++ msvcrt-popen.new/dlls/msvcrt/msvcrt.h	Fri Nov  1 14:25:52 2002
@@ -76,6 +76,7 @@
  extern void msvcrt_init_args(void);
  extern void msvcrt_free_args(void);
  extern void msvcrt_init_vtables(void);
+extern void msvcrt_init_process(void);

  /* run-time error codes */
  #define _RT_STACK       0
diff -aurN msvcrt-popen.orig/dlls/msvcrt/process.c 
msvcrt-popen.new/dlls/msvcrt/process.c
--- msvcrt-popen.orig/dlls/msvcrt/process.c	Fri Nov  1 14:07:35 2002
+++ msvcrt-popen.new/dlls/msvcrt/process.c	Fri Nov  1 15:07:09 2002
@@ -50,7 +50,12 @@
  #define POPEN_FLAG_TEXT     0x0004
  #define POPEN_FLAG_BINARY   0x0008

+/* FIXME: Don't know what this value should be, 10 seems enough as
+ * the maximum number of simultaneous _popen'ed processes
+ */
  #define POPEN_MAX_FILES     10
+#define POPEN_FILE_IN_USE   0x0001
+
  #define POPEN_WCMD_EXEC     "wcmd /c "

  #define LPCWSTR_TO_LPSTR(wszIn, nIn, szOut, nOut) \
@@ -71,11 +76,7 @@
      int         fd;
  } POPEN_FILE;

-/* FIXME: we can only spawn one process at a time presently, this
- * needs to be extended to allow for any number. As a first pass,
- * this might be good enough...
- */
-static POPEN_FILE *pPOPEN_File = NULL;
+static POPEN_FILE POPEN_Files[POPEN_MAX_FILES];

  /* FIXME: Check file extensions for app to run */
  static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
@@ -83,6 +84,25 @@
  static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
  static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';

+/*********************************************************************
+ *      msvcrt_init_process (internal)
+ *
+ * Used to initialise the internal process tables
+ */
+void msvcrt_init_process(void)
+{
+    int i = 0;
+    for (i = 0; i < POPEN_MAX_FILES; i++)
+    {
+        /* clear everything that is used to hold the process
+         * file handles by setting it to zero.
+         */
+        POPEN_Files[i].fSysProcess = NULL;
+        POPEN_Files[i].fProcess = NULL;
+        POPEN_Files[i].fd = -1;
+    }
+}
+
  /* INTERNAL: Spawn a child process */
  static int msvcrt_spawn(int flags, const char* exe, char* cmdline, 
char* env)
  {
@@ -554,14 +574,49 @@
  }

  /*********************************************************************
+ *      POPEN_getOpenFileSlotPos (internal)
+ *
+ * Return the first available file slot for storing file data
+ */
+INT POPEN_getOpenFileSlotPos(VOID)
+{
+    INT i = 0;
+    for (i = 0; i < POPEN_MAX_FILES; i++)
+    {
+        if (!POPEN_Files[i].fProcess)
+        {
+            POPEN_Files[i].fProcess = (MSVCRT_FILE *)POPEN_FILE_IN_USE;
+            return i;
+        }
+    }
+    return -1;
+}
+
+/*********************************************************************
+ *      POPEN_findFileSlotPos (internal)
+ *
+ * Return the first available file slot for storing file data
+ */
+INT POPEN_findFileSlotPos(MSVCRT_FILE *fProcess)
+{
+    INT i = 0;
+    for (i = 0; i < POPEN_MAX_FILES; i++)
+    {
+        if (POPEN_Files[i].fProcess == fProcess)
+            return i;
+    }
+    return -1;
+}
+
+/*********************************************************************
   *      MSVCRT_popen (MSVCRT.@)
   */
  MSVCRT_FILE *MSVCRT_popen(const CHAR *szCommand, const CHAR *szMode)
  {
      MSVCRT_FILE *fProcess = NULL;
-    FILE *fIntl = NULL;
      INT nFlags = 0;
      CHAR *szExec = NULL;
+    INT nPos;

      TRACE("(szCommand == %s, szMode == %s)\n", debugstr_a(szCommand), 
debugstr_a(szMode));

@@ -582,42 +637,32 @@
      if ((szExec = (CHAR 
*)malloc(strlen(POPEN_WCMD_EXEC)+strlen(szCommand)+1)))
      {
          sprintf(szExec, "%s%s", POPEN_WCMD_EXEC, szCommand);
-
+
          /* convert from the specific FILE* to the MSVCRT_FILE*. We need
           * to make doubly sure that in the process we are not leaking
           * handles since we go from File -> fd -> MSVCRT_FILE. (The route
           * back in _pclose is even more interresting which means that we
           * need to keep track of the original FILE* so we can close it...)
-         *
-         * FIXME: We only have one available slot at present so we can only
-         * have one _popen command active at any time.
           */
-        if (!pPOPEN_File)
+        if ((nPos = POPEN_getOpenFileSlotPos()) != -1)
          {
-            FIXME("Allowance for multiple _popen streams to be made\n");
-
-            if ((pPOPEN_File = (POPEN_FILE 
*)MSVCRT_malloc(sizeof(POPEN_FILE))) &&
-                (fIntl = popen(szExec, (nFlags & POPEN_FLAG_READ) ? "r" 
: "w")))
+            if ((POPEN_Files[nPos].fSysProcess = popen(szExec, (nFlags 
& POPEN_FLAG_READ) ? "r" : "w")))
              {
-                int fd = fileno(fIntl);
-                fProcess = _fdopen(fd, (nFlags & POPEN_FLAG_READ) ? "r" 
: "w");
-
-                pPOPEN_File->fSysProcess = fIntl;
-                pPOPEN_File->fProcess = fProcess;
-                pPOPEN_File->fd = fd;
+                POPEN_Files[nPos].fd = 
fileno(POPEN_Files[nPos].fSysProcess);
+                POPEN_Files[nPos].fProcess = _fdopen(POPEN_Files[nPos].fd,
+                                                     (nFlags & 
POPEN_FLAG_READ) ? "r" : "w");
              }
              else
              {
-                if (pPOPEN_File)
-                {
-                    MSVCRT_free(pPOPEN_File);
-                    pPOPEN_File = NULL;
-                }
+                /* we've setup POPEN_Files[nPos].fProcess to 
POPEN_FILE_IN_USE,
+                 * reset it to available not that we won't be using it 
after all
+                 */
+                POPEN_Files[nPos].fProcess = NULL;
                  ERR("Execution of %s failed\n", debugstr_a(szExec));
              }
          }
          else
-            FIXME("Attempt to use multiple _popen streams, failing\n");
+            FIXME("Maxiumum number of process streams opened, failing\n");
          MSVCRT_free(szExec);
      }

@@ -660,23 +705,22 @@
  int MSVCRT_pclose(MSVCRT_FILE *fProcess)
  {
      int nRet = -1;
+    int nPos;

      TRACE("(fProcess == %p)\n", fProcess);

-    /* FIXME: single process time again, we must allow for multiple streams
-     * here and in the _popen function (read comments in _popen)
-     */
-    if (pPOPEN_File && fProcess && pPOPEN_File->fProcess == fProcess)
+    if ((nPos = POPEN_findFileSlotPos(fProcess)) != -1)
      {
-        nRet = pclose(pPOPEN_File->fSysProcess);
+        nRet = pclose(POPEN_Files[nPos].fSysProcess);

          /* FIXME: we need to make doubly sure that we are not leaking 
handles. Since
          * all references refer to the same file, we should be safe. We 
are closing
          * fProcess/pPOPEN_File->fProcess just to clean up the internal 
msvcrt stuff.
          */
          MSVCRT_fclose(fProcess);
-        MSVCRT_free(pPOPEN_File);
-        pPOPEN_File = NULL;
+        POPEN_Files[nPos].fSysProcess = NULL;
+        POPEN_Files[nPos].fProcess = NULL;
+        POPEN_Files[nPos].fd = -1;
      }
      else
          ERR("%p is not a valid process handle\n", fProcess);




More information about the wine-patches mailing list