~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to PC/w9xpopen.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
22
const 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
 
 
27
int 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
}