PageRenderTime 355ms CodeModel.GetById 151ms app.highlight 6ms RepoModel.GetById 196ms app.codeStats 0ms

/PC/w9xpopen.c

http://unladen-swallow.googlecode.com/
C | 112 lines | 76 code | 4 blank | 32 comment | 10 complexity | f8e123978233bbfc00f4ad6a728416d2 MD5 | raw file
  1/*
  2 * w9xpopen.c
  3 *
  4 * Serves as an intermediate stub Win32 console application to
  5 * avoid a hanging pipe when redirecting 16-bit console based
  6 * programs (including MS-DOS console based programs and batch
  7 * files) on Window 95 and Windows 98.
  8 *
  9 * This program is to be launched with redirected standard
 10 * handles. It will launch the command line specified 16-bit
 11 * console based application in the same console, forwarding
 12 * its own redirected standard handles to the 16-bit child.
 13
 14 * AKA solution to the problem described in KB: Q150956.
 15 */    
 16
 17#define WIN32_LEAN_AND_MEAN
 18#include <windows.h>
 19#include <stdio.h>
 20#include <stdlib.h>  /* for malloc and its friends */
 21
 22const char *usage =
 23"This program is used by Python's os.popen function\n"
 24"to work around a limitation in Windows 95/98.  It is\n"
 25"not designed to be used as a stand-alone program.";
 26
 27int main(int argc, char *argv[])
 28{
 29    BOOL bRet;
 30    STARTUPINFO si;
 31    PROCESS_INFORMATION pi;
 32    DWORD exit_code=0;
 33    size_t cmdlen = 0;
 34    int i;
 35    char *cmdline, *cmdlinefill;
 36
 37    if (argc < 2) {
 38        if (GetFileType(GetStdHandle(STD_INPUT_HANDLE))==FILE_TYPE_CHAR)
 39            /* Attached to a console, and therefore not executed by Python
 40               Display a message box for the inquisitive user
 41            */
 42            MessageBox(NULL, usage, argv[0], MB_OK);
 43        else {
 44            /* Eeek - executed by Python, but args are screwed!
 45               Write an error message to stdout so there is at
 46               least some clue for the end user when it appears
 47               in their output.
 48               A message box would be hidden and blocks the app.
 49             */
 50            fprintf(stdout, "Internal popen error - no args specified\n%s\n", usage);
 51        }
 52        return 1;
 53    }
 54    /* Build up the command-line from the args.
 55       Args with a space are quoted, existing quotes are escaped.
 56       To keep things simple calculating the buffer size, we assume
 57       every character is a quote - ie, we allocate double what we need
 58       in the worst case.  As this is only double the command line passed
 59       to us, there is a good chance this is reasonably small, so the total 
 60       allocation will almost always be < 512 bytes.
 61    */
 62    for (i=1;i<argc;i++)
 63        cmdlen += strlen(argv[i])*2 + 3; /* one space, maybe 2 quotes */
 64    cmdline = cmdlinefill = (char *)malloc(cmdlen+1);
 65    if (cmdline == NULL)
 66        return -1;
 67    for (i=1;i<argc;i++) {
 68        const char *arglook;
 69        int bQuote = strchr(argv[i], ' ') != NULL;
 70        if (bQuote)
 71            *cmdlinefill++ = '"';
 72        /* escape quotes */
 73        for (arglook=argv[i];*arglook;arglook++) {
 74            if (*arglook=='"')
 75                *cmdlinefill++ = '\\';
 76            *cmdlinefill++ = *arglook;
 77        }
 78        if (bQuote)
 79            *cmdlinefill++ = '"';
 80        *cmdlinefill++ = ' ';
 81    }
 82    *cmdlinefill = '\0';
 83
 84    /* Make child process use this app's standard files. */
 85    ZeroMemory(&si, sizeof si);
 86    si.cb = sizeof si;
 87    si.dwFlags = STARTF_USESTDHANDLES;
 88    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
 89    si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 90    si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
 91
 92    bRet = CreateProcess(
 93        NULL, cmdline,
 94        NULL, NULL,
 95        TRUE, 0,
 96        NULL, NULL,
 97        &si, &pi
 98        );
 99
100    free(cmdline);
101
102    if (bRet) {
103        if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) {
104	    GetExitCodeProcess(pi.hProcess, &exit_code);
105	}
106        CloseHandle(pi.hProcess);
107        CloseHandle(pi.hThread);
108        return exit_code;
109    }
110
111    return 1;
112}