Op zaterdag 19-09-2009 om 11:30 uur [tijdzone +0530], schreef Harry
Simons:
> Hello,
> 
> I have a C program that builds and runs fine on my Fedora 11 box. This 
> program uses popen as follows:
> 
>      FILE *pipe = popen("perl - ", "w");
>      if(pipe) {
>        int i = 0;
> 
>        // Send a Perl script to the STDIN of 'pipe'.
>        for( ; i<  sizeof(perlScript) / sizeof(perlScript[0]); ++i) {
>          fprintf(pipe, "%c", perlScript[i]);
>        }
> 
>        pclose(pipe);
>      }
> 
> I would like to know if MinGW can help me:
>    1. cross-compile the above C program (on my Fedora 11 for the Windows 
> platform),
>    2. without having to replace the above call to popen by less than ideal
>        Windows counterparts like _popen (which pops up an ugly CMD console 
> window!),
>        or CreatePipe, or CreateNamedPipe, etc.
> 
> Regards,
> /HS

Hi Harry,

For one of my own projects I've used this piece of code as a replacement
for popen on Win32. It uses the Win32 API functions CreatePipe and
CreateProcess and it doesn't show an ugly CMD console window:

-------

#ifdef WIN32
#include <windows.h>
#include <io.h>

#define popen pt_popen
#define pclose pt_pclose

HANDLE my_pipein[2], my_pipeout[2], my_pipeerr[2];
char   my_popenmode = ' ';

static int
my_pipe(HANDLE *readwrite)
{
    SECURITY_ATTRIBUTES sa;

    sa.nLength = sizeof(sa);
    sa.bInheritHandle = 1;
    sa.lpSecurityDescriptor = NULL;

    if (!CreatePipe (&readwrite[0],&readwrite[1],&sa,1 << 13)) {
        errno = EMFILE;
        return -1;
    }

    return 0;
}

static FILE *
pt_popen(const char *cmd, const char *mode)
{
    FILE *fptr = (FILE *)0;
    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
    int success, catch_stderr;

    my_pipein[0]   = INVALID_HANDLE_VALUE;
    my_pipein[1]   = INVALID_HANDLE_VALUE;
    my_pipeout[0]  = INVALID_HANDLE_VALUE;
    my_pipeout[1]  = INVALID_HANDLE_VALUE;
    my_pipeerr[0]  = INVALID_HANDLE_VALUE;
    my_pipeerr[1]  = INVALID_HANDLE_VALUE;

    if (!mode || !*mode)
        goto finito;

    my_popenmode = *mode;
    if (my_popenmode != 'r' && my_popenmode != 'w')
        goto finito;

    catch_stderr = strstr((char *) cmd, "2>&1") != NULL;
    if (catch_stderr) {
        char *ptr = strstr((char*) cmd, "2>&1");
        *ptr = '\0';
    }

    if (my_pipe(my_pipein)  == -1 || my_pipe(my_pipeout) == -1)
        goto finito;
    if (!catch_stderr && my_pipe(my_pipeerr) == -1)
      goto finito;

    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
    siStartInfo.cb             = sizeof(STARTUPINFO);
    siStartInfo.hStdInput      = my_pipein[0];
    siStartInfo.hStdOutput     = my_pipeout[1];
    if (catch_stderr)
        siStartInfo.hStdError  = my_pipeout[1];
    else
        siStartInfo.hStdError  = my_pipeerr[1];
    siStartInfo.dwFlags        = STARTF_USESTDHANDLES;

    success = CreateProcess(NULL,
       (LPTSTR)cmd,       // command line
       NULL,              // process security attributes
       NULL,              // primary thread security attributes
       TRUE,              // handles are inherited
       DETACHED_PROCESS,  // creation flags
       NULL,              // use parent's environment
       NULL,              // use parent's current directory
       &siStartInfo,      // STARTUPINFO pointer
       &piProcInfo);      // receives PROCESS_INFORMATION

    if (!success)
        goto finito;

    CloseHandle(my_pipein[0]);  my_pipein[0]  = INVALID_HANDLE_VALUE;
    CloseHandle(my_pipeout[1]); my_pipeout[1] = INVALID_HANDLE_VALUE;
    CloseHandle(my_pipeerr[1]); my_pipeerr[1] = INVALID_HANDLE_VALUE;

    if (my_popenmode == 'r')
        fptr = _fdopen(_open_osfhandle((long)my_pipeout[0],_O_BINARY),"r");
    else
        fptr = _fdopen(_open_osfhandle((long)my_pipein[1],_O_BINARY),"w");

finito:
    if (!fptr) {
        if (my_pipein[0]  != INVALID_HANDLE_VALUE)
            CloseHandle(my_pipein[0]);
        if (my_pipein[1]  != INVALID_HANDLE_VALUE)
            CloseHandle(my_pipein[1]);
        if (my_pipeout[0] != INVALID_HANDLE_VALUE)
            CloseHandle(my_pipeout[0]);
        if (my_pipeout[1] != INVALID_HANDLE_VALUE)
            CloseHandle(my_pipeout[1]);
        if (my_pipeerr[0] != INVALID_HANDLE_VALUE)
            CloseHandle(my_pipeerr[0]);
        if (my_pipeerr[1] != INVALID_HANDLE_VALUE)
            CloseHandle(my_pipeerr[1]);
    }

    return fptr;
}

static int
pt_pclose(FILE *file)
{
    if (!file) {
        return -1;
    }

    fclose(file);

    CloseHandle(my_pipeerr[0]);
    if (my_popenmode == 'r')
        CloseHandle(my_pipein[1]);
    else
       CloseHandle(my_pipeout[0]);

    return 0;
}
#endif

----

Note that this piece of code only supports one open file descriptor at the same 
time (because of the global variables which are used).
It may need some further adjustment to fit in your particular case.

Regards,

Erik van Pienbroek


_______________________________________________
fedora-mingw mailing list
[email protected]
https://admin.fedoraproject.org/mailman/listinfo/fedora-mingw

Reply via email to