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