summaryrefslogtreecommitdiff
path: root/src/roff/groff/pipeline.c
diff options
context:
space:
mode:
authorwlemb <wlemb>2004-02-29 00:07:06 +0000
committerwlemb <wlemb>2004-02-29 00:07:06 +0000
commitcf49e6d5f5c047f7c37c7fb09e3a06a5adbb696e (patch)
treea03f65f4af4967e7217a31a6ea3226f2a51582c2 /src/roff/groff/pipeline.c
parentcf22bfa85b2e85b72bc2de8dc3353f7cec1e3828 (diff)
downloadgroff-cf49e6d5f5c047f7c37c7fb09e3a06a5adbb696e.tar.gz
* src/include/nonposix.h (write, dup, dup2, close) [_MSC_VER]:
New macros. * src/roff/groff/pipeline.c: Declare strcasecmp. (run_pipeline) [_WIN32]: Use function name variants which don't start with `_'. Fix stream handling. * src/include/nonposix.h: Fix declaration of `system_shell_name'. Declare `spawnvp_wrapper' and macro definitions of spawnvp only for platforms which use the native Win32 runtime libraries. (FLUSH_INPUT_PIPE) [_UWIN]: Provide non-empty version. * src/libs/libgroff/quotearg.c (QUOTE_ARG_MALLOC_ERROR, QUOTE_ARG_REALLOC_ERROR): Fix string. * src/preproc/html/pre-html.cpp: Remove declaration of `spawnvp_wrapper'. Don't use __MINGW32__. s/DEBUG_FILE/DEBUG_FILE_DIR/. (DEBUG_TEXT, DEBUG_NAME, DEBUG_FILE) [DEBUGGING]: New macros. (OUTPUT_STREAM, PS_OUTPUT_STREAM, REGION_OUTPUT_STREAM): New macros. (char_buffer::run_output_filter) [MAY_FORK_CHILD_PROCESS]: Fix calls to `set_redirection' and `WAIT'. [MAY_SPAWN_ASYNCHRONOUS_CHILD]: Remove unused variable `i' and `j'. Fix calls to `set_redirection' and `save_and_redirect'. (char_buffer::do_html, char_buffer::do_image) [DEBUGGING]: Fix calls to `set_redirection' and `save_and_redirect'. (usage): Fix message. (makeTempFiles, main): Use `DEBUG_FILE'.
Diffstat (limited to 'src/roff/groff/pipeline.c')
-rw-r--r--src/roff/groff/pipeline.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/src/roff/groff/pipeline.c b/src/roff/groff/pipeline.c
index 2d7ba362..b51ed50e 100644
--- a/src/roff/groff/pipeline.c
+++ b/src/roff/groff/pipeline.c
@@ -102,6 +102,8 @@ static const char *sh = "sh";
static const char *cmd = "cmd";
static const char *command = "command";
+extern int strcasecmp(const char *, const char *);
+
char *sbasename(const char *path)
{
char *base;
@@ -189,13 +191,22 @@ int is_system_shell(const char *prog)
#ifdef _WIN32
-/* Windows 32 doesn't have fork() */
+/*
+ Windows 32 doesn't have fork(), so we need to start asynchronous child
+ processes with spawn() rather than exec(). If there is more than one
+ command, i.e., a pipeline, the parent must set up each child's I/O
+ redirection prior to the spawn. The original stdout must be restored
+ before spawning the last process in the pipeline, and the original
+ stdin must be restored in the parent after spawning the last process
+ and before waiting for any of the children.
+*/
int run_pipeline(int ncommands, char ***commands, int no_pipe)
{
- int save_stdin, save_stdout;
int i;
- int last_input = 0;
+ int last_input;
+ int save_stdin;
+ int save_stdout;
int ret = 0;
char err_str[BUFSIZ];
PID_T pids[MAX_COMMANDS];
@@ -209,18 +220,22 @@ int run_pipeline(int ncommands, char ***commands, int no_pipe)
if (ncommands > 1 && !no_pipe) {
/* last command doesn't need a new pipe */
if (i < ncommands - 1) {
- if (_pipe(pdes, BUFSIZ, _O_BINARY | _O_NOINHERIT) < 0) {
+ if (pipe(pdes) < 0) {
sprintf(err_str, "%s: pipe", commands[i][0]);
sys_fatal(err_str);
}
}
/* 1st command; writer */
if (i == 0) {
+ /* save stdin */
+ if ((save_stdin = dup(STDIN_FILENO)) < 0)
+ sys_fatal("dup stdin");
/* save stdout */
- if ((save_stdout = _dup(STDOUT_FILENO)) < 0)
+ if ((save_stdout = dup(STDOUT_FILENO)) < 0)
sys_fatal("dup stdout");
+
/* connect stdout to write end of pipe */
- if (_dup2(pdes[1], STDOUT_FILENO) < 0) {
+ if (dup2(pdes[1], STDOUT_FILENO) < 0) {
sprintf(err_str, "%s: dup2(stdout)", commands[i][0]);
sys_fatal(err_str);
}
@@ -228,17 +243,26 @@ int run_pipeline(int ncommands, char ***commands, int no_pipe)
sprintf(err_str, "%s: close(pipe[WRITE])", commands[i][0]);
sys_fatal(err_str);
}
+ /*
+ Save the read end of the pipe so that it can be connected to
+ stdin of the next program in the pipeline during the next
+ pass through the loop.
+ */
last_input = pdes[0];
}
/* reader and writer */
else if (i < ncommands - 1) {
/* connect stdin to read end of last pipe */
- if (_dup2(last_input, STDIN_FILENO) < 0) {
+ if (dup2(last_input, STDIN_FILENO) < 0) {
sprintf(err_str, " %s: dup2(stdin)", commands[i][0]);
sys_fatal(err_str);
}
+ if (close(last_input) < 0) {
+ sprintf(err_str, "%s: close(last_input)", commands[i][0]);
+ sys_fatal(err_str);
+ }
/* connect stdout to write end of new pipe */
- if (_dup2(pdes[1], STDOUT_FILENO) < 0) {
+ if (dup2(pdes[1], STDOUT_FILENO) < 0) {
sprintf(err_str, "%s: dup2(stdout)", commands[i][0]);
sys_fatal(err_str);
}
@@ -251,7 +275,7 @@ int run_pipeline(int ncommands, char ***commands, int no_pipe)
/* last command; reader */
else {
/* connect stdin to read end of last pipe */
- if (_dup2(last_input, STDIN_FILENO) < 0) {
+ if (dup2(last_input, STDIN_FILENO) < 0) {
sprintf(err_str, "%s: dup2(stdin)", commands[i][0]);
sys_fatal(err_str);
}
@@ -260,7 +284,7 @@ int run_pipeline(int ncommands, char ***commands, int no_pipe)
sys_fatal(err_str);
}
/* restore original stdout */
- if (_dup2(save_stdout, STDOUT_FILENO) < 0) {
+ if (dup2(save_stdout, STDOUT_FILENO) < 0) {
sprintf(err_str, "%s: dup2(save_stdout))", commands[i][0]);
sys_fatal(err_str);
}
@@ -271,7 +295,7 @@ int run_pipeline(int ncommands, char ***commands, int no_pipe)
}
}
}
- if ((pid = _spawnvp(_P_NOWAIT, commands[i][0], commands[i])) < 0) {
+ if ((pid = spawnvp(_P_NOWAIT, commands[i][0], commands[i])) < 0) {
error("couldn't exec %1: %2",
commands[i][0], strerror(errno), (char *)0);
fflush(stderr); /* just in case error() doesn't */
@@ -279,13 +303,27 @@ int run_pipeline(int ncommands, char ***commands, int no_pipe)
}
pids[i] = pid;
}
+
+ if (ncommands > 1 && !no_pipe) {
+ /* restore original stdin if it was redirected */
+ if (dup2(save_stdin, STDIN_FILENO) < 0) {
+ sprintf(err_str, "dup2(save_stdin))");
+ sys_fatal(err_str);
+ }
+ /* close stdin copy */
+ if (close(save_stdin) < 0) {
+ sprintf(err_str, "close(save_stdin)");
+ sys_fatal(err_str);
+ }
+ }
+
for (i = 0; i < ncommands; i++) {
int status;
- int pid;
+ PID_T pid;
pid = pids[i];
if ((pid = WAIT(&status, pid, _WAIT_CHILD)) < 0) {
- sprintf(err_str, "%s: cwait", commands[i][0]);
+ sprintf(err_str, "%s: wait", commands[i][0]);
sys_fatal(err_str);
}
else if (status != 0)