diff options
author | Andrew MacIntyre <andymac@bullseye.apana.org.au> | 2004-12-12 08:30:51 (GMT) |
---|---|---|
committer | Andrew MacIntyre <andymac@bullseye.apana.org.au> | 2004-12-12 08:30:51 (GMT) |
commit | a4a8afb4e1fe9a2a314f57d82310c28ac8e31132 (patch) | |
tree | cf7f2346262bb80d37a847d81fe376940324bac5 /Modules/posixmodule.c | |
parent | d0278ec97ffd252094cf56ea00e40b3c6f442a7a (diff) | |
download | cpython-a4a8afb4e1fe9a2a314f57d82310c28ac8e31132.zip cpython-a4a8afb4e1fe9a2a314f57d82310c28ac8e31132.tar.gz cpython-a4a8afb4e1fe9a2a314f57d82310c28ac8e31132.tar.bz2 |
OS/2 specific fixes related to SF bug # 1003471.
Also revise a related function to minimise file handle/pipe leakage
and improve reliability.
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r-- | Modules/posixmodule.c | 135 |
1 files changed, 67 insertions, 68 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 31d7c61..f605cca 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3248,86 +3248,85 @@ Open a pipe to/from a command returning a file object."); static int async_system(const char *command) { - char *p, errormsg[256], args[1024]; - RESULTCODES rcodes; - APIRET rc; - char *shell = getenv("COMSPEC"); - if (!shell) - shell = "cmd"; - - strcpy(args, shell); - p = &args[ strlen(args)+1 ]; - strcpy(p, "/c "); - strcat(p, command); - p += strlen(p) + 1; - *p = '\0'; - - rc = DosExecPgm(errormsg, sizeof(errormsg), - EXEC_ASYNC, /* Execute Async w/o Wait for Results */ - args, - NULL, /* Inherit Parent's Environment */ - &rcodes, shell); - return rc; + char errormsg[256], args[1024]; + RESULTCODES rcodes; + APIRET rc; + + char *shell = getenv("COMSPEC"); + if (!shell) + shell = "cmd"; + + /* avoid overflowing the argument buffer */ + if (strlen(shell) + 3 + strlen(command) >= 1024) + return ERROR_NOT_ENOUGH_MEMORY + + args[0] = '\0'; + strcat(args, shell); + strcat(args, "/c "); + strcat(args, command); + + /* execute asynchronously, inheriting the environment */ + rc = DosExecPgm(errormsg, + sizeof(errormsg), + EXEC_ASYNC, + args, + NULL, + &rcodes, + shell); + return rc; } static FILE * popen(const char *command, const char *mode, int pipesize, int *err) { - HFILE rhan, whan; - FILE *retfd = NULL; - APIRET rc = DosCreatePipe(&rhan, &whan, pipesize); - - if (rc != NO_ERROR) { - *err = rc; - return NULL; /* ERROR - Unable to Create Anon Pipe */ - } - - if (strchr(mode, 'r') != NULL) { /* Treat Command as a Data Source */ - int oldfd = dup(1); /* Save STDOUT Handle in Another Handle */ - - DosEnterCritSec(); /* Stop Other Threads While Changing Handles */ - close(1); /* Make STDOUT Available for Reallocation */ - - if (dup2(whan, 1) == 0) { /* Connect STDOUT to Pipe Write Side */ - DosClose(whan); /* Close Now-Unused Pipe Write Handle */ - - rc = async_system(command); - } - - dup2(oldfd, 1); /* Reconnect STDOUT to Original Handle */ - DosExitCritSec(); /* Now Allow Other Threads to Run */ - - if (rc == NO_ERROR) - retfd = fdopen(rhan, mode); /* And Return Pipe Read Handle */ - - close(oldfd); /* And Close Saved STDOUT Handle */ - return retfd; /* Return fd of Pipe or NULL if Error */ - - } else if (strchr(mode, 'w')) { /* Treat Command as a Data Sink */ - int oldfd = dup(0); /* Save STDIN Handle in Another Handle */ + int oldfd, tgtfd; + HFILE pipeh[2]; + APIRET rc; - DosEnterCritSec(); /* Stop Other Threads While Changing Handles */ - close(0); /* Make STDIN Available for Reallocation */ + /* mode determines which of stdin or stdout is reconnected to + * the pipe to the child + */ + if (strchr(mode, 'r') != NULL) { + tgt_fd = 1; /* stdout */ + } else if (strchr(mode, 'w')) { + tgt_fd = 0; /* stdin */ + } else { + *err = ERROR_INVALID_ACCESS; + return NULL; + } - if (dup2(rhan, 0) == 0) { /* Connect STDIN to Pipe Read Side */ - DosClose(rhan); /* Close Now-Unused Pipe Read Handle */ + /* setup the pipe + if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) { + *err = rc; + return NULL; + } - rc = async_system(command); - } + /* prevent other threads accessing stdio */ + DosEnterCritSec(); - dup2(oldfd, 0); /* Reconnect STDIN to Original Handle */ - DosExitCritSec(); /* Now Allow Other Threads to Run */ + /* reconnect stdio and execute child */ + oldfd = dup(tgtfd); + close(tgtfd); + if (dup2(pipeh[tgtfd], tgtfd) == 0) { + DosClose(pipeh[tgtfd]); + rc = async_system(command); + } - if (rc == NO_ERROR) - retfd = fdopen(whan, mode); /* And Return Pipe Write Handle */ + /* restore stdio */ + dup2(oldfd, tgtfd); + close(oldfd); - close(oldfd); /* And Close Saved STDIN Handle */ - return retfd; /* Return fd of Pipe or NULL if Error */ + /* allow other threads access to stdio */ + DosExitCritSec(); - } else { - *err = ERROR_INVALID_ACCESS; - return NULL; /* ERROR - Invalid Mode (Neither Read nor Write) */ - } + /* if execution of child was successful return file stream */ + if (rc == NO_ERROR) + return fdopen(pipeh[1 - tgtfd], mode); + else { + DosClose(pipeh[1 - tgtfd]); + *err = rc; + return NULL; + } } static PyObject * |