RFC: msvcrt _popen/_wpopen/_pclose

chrismorgan at rcn.com chrismorgan at rcn.com
Thu Oct 31 15:47:15 CST 2002


What is wrong with using wcmd and extending it if necessary?

Chris


> 
> From: "Jaco Greeff" <jaco at puxedo.org>
> Date: 2002/10/31 Thu PM 04:27:43 EST
> To: wine-devel at 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/_crt__popen.2c_._wpopen.asp
> 
> 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);
> }
> 
> 
> 
> 




More information about the wine-devel mailing list