Commit a4a8afb4 authored by Andrew MacIntyre's avatar Andrew MacIntyre

OS/2 specific fixes related to SF bug # 1003471.

Also revise a related function to minimise file handle/pipe leakage
and improve reliability.
parent d0278ec9
...@@ -3248,86 +3248,85 @@ Open a pipe to/from a command returning a file object."); ...@@ -3248,86 +3248,85 @@ Open a pipe to/from a command returning a file object.");
static int static int
async_system(const char *command) async_system(const char *command)
{ {
char *p, errormsg[256], args[1024]; char errormsg[256], args[1024];
RESULTCODES rcodes; RESULTCODES rcodes;
APIRET rc; APIRET rc;
char *shell = getenv("COMSPEC");
if (!shell) char *shell = getenv("COMSPEC");
shell = "cmd"; if (!shell)
shell = "cmd";
strcpy(args, shell);
p = &args[ strlen(args)+1 ]; /* avoid overflowing the argument buffer */
strcpy(p, "/c "); if (strlen(shell) + 3 + strlen(command) >= 1024)
strcat(p, command); return ERROR_NOT_ENOUGH_MEMORY
p += strlen(p) + 1;
*p = '\0'; args[0] = '\0';
strcat(args, shell);
rc = DosExecPgm(errormsg, sizeof(errormsg), strcat(args, "/c ");
EXEC_ASYNC, /* Execute Async w/o Wait for Results */ strcat(args, command);
args,
NULL, /* Inherit Parent's Environment */ /* execute asynchronously, inheriting the environment */
&rcodes, shell); rc = DosExecPgm(errormsg,
return rc; sizeof(errormsg),
EXEC_ASYNC,
args,
NULL,
&rcodes,
shell);
return rc;
} }
static FILE * static FILE *
popen(const char *command, const char *mode, int pipesize, int *err) popen(const char *command, const char *mode, int pipesize, int *err)
{ {
HFILE rhan, whan; int oldfd, tgtfd;
FILE *retfd = NULL; HFILE pipeh[2];
APIRET rc = DosCreatePipe(&rhan, &whan, pipesize); APIRET rc;
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 */
DosEnterCritSec(); /* Stop Other Threads While Changing Handles */ /* mode determines which of stdin or stdout is reconnected to
close(0); /* Make STDIN Available for Reallocation */ * 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 */ /* setup the pipe
DosClose(rhan); /* Close Now-Unused Pipe Read Handle */ 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 */ /* reconnect stdio and execute child */
DosExitCritSec(); /* Now Allow Other Threads to Run */ oldfd = dup(tgtfd);
close(tgtfd);
if (dup2(pipeh[tgtfd], tgtfd) == 0) {
DosClose(pipeh[tgtfd]);
rc = async_system(command);
}
if (rc == NO_ERROR) /* restore stdio */
retfd = fdopen(whan, mode); /* And Return Pipe Write Handle */ dup2(oldfd, tgtfd);
close(oldfd);
close(oldfd); /* And Close Saved STDIN Handle */ /* allow other threads access to stdio */
return retfd; /* Return fd of Pipe or NULL if Error */ DosExitCritSec();
} else { /* if execution of child was successful return file stream */
*err = ERROR_INVALID_ACCESS; if (rc == NO_ERROR)
return NULL; /* ERROR - Invalid Mode (Neither Read nor Write) */ return fdopen(pipeh[1 - tgtfd], mode);
} else {
DosClose(pipeh[1 - tgtfd]);
*err = rc;
return NULL;
}
} }
static PyObject * static PyObject *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment