Commit a166c7ed 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 3e6d0e9a
...@@ -3248,85 +3248,84 @@ Open a pipe to/from a command returning a file object."); ...@@ -3248,85 +3248,84 @@ 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"); char *shell = getenv("COMSPEC");
if (!shell) if (!shell)
shell = "cmd"; shell = "cmd";
strcpy(args, shell); /* avoid overflowing the argument buffer */
p = &args[ strlen(args)+1 ]; if (strlen(shell) + 3 + strlen(command) >= 1024)
strcpy(p, "/c "); return ERROR_NOT_ENOUGH_MEMORY
strcat(p, command);
p += strlen(p) + 1; args[0] = '\0';
*p = '\0'; strcat(args, shell);
strcat(args, "/c ");
strcat(args, command);
rc = DosExecPgm(errormsg, sizeof(errormsg), /* execute asynchronously, inheriting the environment */
EXEC_ASYNC, /* Execute Async w/o Wait for Results */ rc = DosExecPgm(errormsg,
sizeof(errormsg),
EXEC_ASYNC,
args, args,
NULL, /* Inherit Parent's Environment */ NULL,
&rcodes, shell); &rcodes,
shell);
return rc; 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) { /* mode determines which of stdin or stdout is reconnected to
*err = rc; * the pipe to the child
return NULL; /* ERROR - Unable to Create Anon Pipe */ */
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 (strchr(mode, 'r') != NULL) { /* Treat Command as a Data Source */ /* setup the pipe
int oldfd = dup(1); /* Save STDOUT Handle in Another Handle */ if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) {
*err = rc;
DosEnterCritSec(); /* Stop Other Threads While Changing Handles */ return NULL;
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 */ /* prevent other threads accessing stdio */
DosExitCritSec(); /* Now Allow Other Threads to Run */ DosEnterCritSec();
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 */
close(0); /* Make STDIN Available for Reallocation */
if (dup2(rhan, 0) == 0) { /* Connect STDIN to Pipe Read Side */
DosClose(rhan); /* Close Now-Unused Pipe Read Handle */
/* reconnect stdio and execute child */
oldfd = dup(tgtfd);
close(tgtfd);
if (dup2(pipeh[tgtfd], tgtfd) == 0) {
DosClose(pipeh[tgtfd]);
rc = async_system(command); rc = async_system(command);
} }
dup2(oldfd, 0); /* Reconnect STDIN to Original Handle */ /* restore stdio */
DosExitCritSec(); /* Now Allow Other Threads to Run */ dup2(oldfd, tgtfd);
close(oldfd);
if (rc == NO_ERROR) /* allow other threads access to stdio */
retfd = fdopen(whan, mode); /* And Return Pipe Write Handle */ DosExitCritSec();
close(oldfd); /* And Close Saved STDIN Handle */ /* if execution of child was successful return file stream */
return retfd; /* Return fd of Pipe or NULL if Error */ if (rc == NO_ERROR)
return fdopen(pipeh[1 - tgtfd], mode);
} else { else {
*err = ERROR_INVALID_ACCESS; DosClose(pipeh[1 - tgtfd]);
return NULL; /* ERROR - Invalid Mode (Neither Read nor Write) */ *err = rc;
return NULL;
} }
} }
......
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