What is wrong with using wcmd and extending it if necessary?
Chris
From: "Jaco Greeff" jaco@puxedo.org Date: 2002/10/31 Thu PM 04:27:43 EST To: wine-devel@winehq.com Subject: RFC: msvcrt _popen/_wpopen/_pclose
Hi,
I want some comments on the possibility of a _popen/_wpopen/_pclose implementation in Wine. Reference available at:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/...
The open functions basically operate in the same way as the popen function in Linux, ie. it spawns a process with the command via the command interpreter. Now, unfortionately we don't have our won cmd.exe available, but should people really need this functionality it might not be too much to ask as to copy it from a working Windows installation.
In my mind, supporting the Win 95/98 command interpreters might be a nightmare - my gutt feel is that these two rely too much on DOS internals to be sucessfully launched via Wine. No, I haven't tried it, so I might be completely wrong. Either way, something like this might be better implemented via the Win NT/2000/XP cmd.exe. (I'll test my assumptions tomorrow, I don't have access to the command interpreters tonight.)
I've hacked (yes, it was quick) a potential implementation of the _popen family of functions. (Haven't compiled, haven't tested, this is just and RFC
- if it can work, I'll spend some real time on it.) Anyway, here it is,
comments appreciated:
--[ inline-ish RFC ]----
#include "config.h" #include "wine/port.h"
#include <stdio.h> #include <stdlib.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif
#include "winbase.h" #include "winnls.h" #include "wine/unicode.h" #include "msvcrt/stdio.h" #include "msvcrt/string.h"
#include "wine/debug.h"
#define POPEN_FLAG_READ 0x0001 #define POPEN_FLAG_WRITE 0x0002 #define POPEN_FLAG_TEXT 0x0004 #define POPEN_FLAG_BINARY 0x0008
inline CHAR *LPCWSTRToLPSTR(const LPCWSTR lpwstrIn, INT nIn) { INT nLen = WideCharToMultiByte(CP_ACP, 0, lpwszIn, nIn, NULL, 0, NULL, NULL); CHAR *szOut = (CHAR *)malloc((nLen+1)*sizeof(CHAR)); if (szOut) { WideCharToMultiByte(CP_ACP, 0, lpwszIn, nIn, szOut, nLen+1, NULL, NULL); szOut[nLen] = '\0'; } return szOut; }
INT POPEN_parseModeFlags(const CHAR *szMode) { INT nFlags = 0; while (szMode && *szMode) { switch (*szMode) { case 'r': { if (nFlags & POPEN_FLAG_WRITE) WARN(": _popen: Cannot set both read and write open flags, ignoring read flag\n"); else nFlags = nFlags & POPEN_FLAG_READ; break; } case 'w': { if (nFlags & POPEN_FLAG_READ) WARN(": _popen: Cannot set both read and write open flags, ignoring write flag\n"); else nFlags = nFlags & POPEN_FLAG_WRITE; break; } case 'b': case 't': { FIXME(": _popen: %c mode flag not implemented, ignoring\n", *szMode); break; } default: { WARN(": _popen: unknown mode flag %c, ignoring\n", *szMode); break; } } } return nFlags; }
MSVCRT_FILE *MSVCRT_popen(const CHAR *szCommand, const CHAR *szMode) { MSVCRT_FILE *fProcess = NULL;
if (!szCommand || !szMode) return NULL; INT nFlags = POPEN_parseModeFlags(szMode); if (!(nFlags & (POPEN_FLAG_READ|POPEN_FLAG_WRITE))) { ERR("No open mode flag r or w specified\n"); return NULL; } /* _popen/_wpopen executes the required command via the command * processor, either command.com (Win 95/98) or cmd.exe (Win NT/2000/XP). * Wine does not currently have it's own "cmd.exe" hence we cannot * really do anything more at this point. However, we try to lauch it * and hope for the best... */ CHAR *szExec = (CHAR *)malloc(strlen("wine -- C:/cmd.exe -C
")+strlen(szCommand)+1); if (szExec) { sprintf(szExec, "wine -- C:/cmd.exe -C %s", szCommand); fProcess = popen(szExec, (nFlags & POPEN_FLAG_READ) ? "r" : "w"); if (!fProcess) ERR("Execution of C:/cmd.exe via wine failed\n"); else WARN("Launch of %s succeeded, no guarentees of success made\n", debugstr_a(szExec)); free(szExec); }
return fProcess;
}
MSVCRT_FILE *MSVCRT_wpopen(const WCHAR *wszCommand, const WCHAR *wszMode) { MSVCRT_FILE *fProcess = NULL;
if (!wszCommand || !wszMode) return NULL; CHAR *szCommand = LPCWSTRToLPSTR(wszCommand, strlenW(wszCommand)); if (szCommand) { CHAR *szMode = LPCWSTRToLPSTR(wszMode, strlenW(wszMode)); if (szMode) { fProcess = _popen(szCommand, szMode); free(szMode); free(szCommand); } free(szCommand); } return fProcess;
}
int MSVCRT_pclose(MSVCRT_FILE *fProcess) { if (!fProcess) return -1; return pclose(fProcess); }
chrismorgan@rcn.com wrote:
What is wrong with using wcmd and extending it if necessary?
Nothing. I must admit that I have looked at the wcmd code, but if I remember correctly it lacks a "/C" switch. This I assume is the extending part you are speaking about. Then again, I'm not 100% sure that it will be needed, it might just do the job without touching anything. Come to think of it, it is actually the preferred approach, we don't want to rely on "other" executables.
I'll dig a bit...
Greetings, Jaco
Jaco Greeff wrote:
chrismorgan@rcn.com wrote:
What is wrong with using wcmd and extending it if necessary?
Nothing. I must admit that I have looked at the wcmd code, but if I remember correctly it lacks a "/C" switch.
Yes it lack a "/C" switch, but it has the "/c" switch :) I'm in the process testing and playing a bit, but it seems perfectly do-able.
Greetings, Jaco