1 /* Copyright (C) 1989-2014 Free Software Foundation, Inc.
2 Written by James Clark (jjc@jclark.com)
4 This file is part of groff.
6 groff is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include <sys/types.h>
34 extern char *strerror();
42 #else /* not _POSIX_VERSION */
44 /* traditional Unix */
46 #define WIFEXITED(s) (((s) & 0377) == 0)
47 #define WIFSTOPPED(s) (((s) & 0377) == 0177)
48 #define WIFSIGNALED(s) (((s) & 0377) != 0 && (((s) & 0377) != 0177))
49 #define WEXITSTATUS(s) (((s) >> 8) & 0377)
50 #define WTERMSIG(s) ((s) & 0177)
51 #define WSTOPSIG(s) (((s) >> 8) & 0377)
54 #define WCOREFLAG 0200
59 #endif /* not _POSIX_VERSION */
61 /* SVR4 uses WCOREFLG; Net 2 uses WCOREFLAG. */
64 #define WCOREFLAG WCOREFLG
66 #endif /* not WCOREFLAG */
70 #define WCOREDUMP(s) ((s) & WCOREFLAG)
71 #else /* not WCOREFLAG */
72 #define WCOREDUMP(s) (0)
73 #endif /* WCOREFLAG */
74 #endif /* not WCOREDUMP */
84 extern void error(const char *, const char *, const char *, const char *);
85 extern void c_fatal(const char *, const char *, const char *, const char *);
86 extern const char *i_to_a(int); /* from libgroff */
92 static void sys_fatal(const char *);
93 static const char *xstrsignal(int);
96 #if defined(__MSDOS__) \
97 || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \
105 #include "nonposix.h"
107 static const char *sh = "sh";
108 static const char *cmd = "cmd";
109 static const char *command = "command";
111 extern int strcasecmp(const char *, const char *);
113 char *sbasename(const char *path)
119 if ((p2 = strrchr(p1, '\\'))
120 || (p2 = strrchr(p1, '/'))
121 || (p2 = strrchr(p1, ':')))
123 if ((p2 = strrchr(p1, '.'))
124 && ((strcasecmp(p2, ".exe") == 0)
125 || (strcasecmp(p2, ".com") == 0)))
128 p2 = p1 + strlen(p1);
130 base = malloc((size_t)(p2 - p1));
131 strncpy(base, p1, p2 - p1);
132 *(base + (p2 - p1)) = '\0';
137 /* Get the name of the system shell */
138 char *system_shell_name(void)
140 const char *shell_name;
143 Use a Unixy shell if it's installed. Use SHELL if set; otherwise,
144 let spawnlp try to find sh; if that fails, use COMSPEC if set; if
145 not, try cmd.exe; if that fails, default to command.com.
148 if ((shell_name = getenv("SHELL")) != NULL)
150 else if (spawnlp(_P_WAIT, sh, sh, "-c", ":", NULL) == 0)
152 else if ((shell_name = getenv("COMSPEC")) != NULL)
154 else if (spawnlp(_P_WAIT, cmd, cmd, "/c", ";", NULL) == 0)
157 shell_name = command;
159 return sbasename(shell_name);
162 const char *system_shell_dash_c(void)
167 shell_name = system_shell_name();
169 /* Assume that if the shell name ends in `sh', it's Unixy */
170 if (strcasecmp(shell_name + strlen(shell_name) - strlen("sh"), "sh") == 0)
179 int is_system_shell(const char *prog)
182 char *this_prog, *system_shell;
184 if (!prog) /* paranoia */
187 this_prog = sbasename(prog);
188 system_shell = system_shell_name();
190 result = strcasecmp(this_prog, system_shell) == 0;
201 Windows 32 doesn't have fork(), so we need to start asynchronous child
202 processes with spawn() rather than exec(). If there is more than one
203 command, i.e., a pipeline, the parent must set up each child's I/O
204 redirection prior to the spawn. The original stdout must be restored
205 before spawning the last process in the pipeline, and the original
206 stdin must be restored in the parent after spawning the last process
207 and before waiting for any of the children.
210 int run_pipeline(int ncommands, char ***commands, int no_pipe)
213 int last_input = 0; /* pacify some compilers */
217 char err_str[BUFSIZ];
218 PID_T pids[MAX_COMMANDS];
220 for (i = 0; i < ncommands; i++) {
224 /* If no_pipe is set, just run the commands in sequence
225 to show the version numbers */
226 if (ncommands > 1 && !no_pipe) {
227 /* last command doesn't need a new pipe */
228 if (i < ncommands - 1) {
229 if (pipe(pdes) < 0) {
230 sprintf(err_str, "%s: pipe", commands[i][0]);
234 /* 1st command; writer */
237 if ((save_stdin = dup(STDIN_FILENO)) < 0)
238 sys_fatal("dup stdin");
240 if ((save_stdout = dup(STDOUT_FILENO)) < 0)
241 sys_fatal("dup stdout");
243 /* connect stdout to write end of pipe */
244 if (dup2(pdes[1], STDOUT_FILENO) < 0) {
245 sprintf(err_str, "%s: dup2(stdout)", commands[i][0]);
248 if (close(pdes[1]) < 0) {
249 sprintf(err_str, "%s: close(pipe[WRITE])", commands[i][0]);
253 Save the read end of the pipe so that it can be connected to
254 stdin of the next program in the pipeline during the next
255 pass through the loop.
257 last_input = pdes[0];
259 /* reader and writer */
260 else if (i < ncommands - 1) {
261 /* connect stdin to read end of last pipe */
262 if (dup2(last_input, STDIN_FILENO) < 0) {
263 sprintf(err_str, " %s: dup2(stdin)", commands[i][0]);
266 if (close(last_input) < 0) {
267 sprintf(err_str, "%s: close(last_input)", commands[i][0]);
270 /* connect stdout to write end of new pipe */
271 if (dup2(pdes[1], STDOUT_FILENO) < 0) {
272 sprintf(err_str, "%s: dup2(stdout)", commands[i][0]);
275 if (close(pdes[1]) < 0) {
276 sprintf(err_str, "%s: close(pipe[WRITE])", commands[i][0]);
279 last_input = pdes[0];
281 /* last command; reader */
283 /* connect stdin to read end of last pipe */
284 if (dup2(last_input, STDIN_FILENO) < 0) {
285 sprintf(err_str, "%s: dup2(stdin)", commands[i][0]);
288 if (close(last_input) < 0) {
289 sprintf(err_str, "%s: close(last_input)", commands[i][0]);
292 /* restore original stdout */
293 if (dup2(save_stdout, STDOUT_FILENO) < 0) {
294 sprintf(err_str, "%s: dup2(save_stdout))", commands[i][0]);
297 /* close stdout copy */
298 if (close(save_stdout) < 0) {
299 sprintf(err_str, "%s: close(save_stdout)", commands[i][0]);
304 if ((pid = spawnvp(_P_NOWAIT, commands[i][0], commands[i])) < 0) {
305 error("couldn't exec %1: %2",
306 commands[i][0], strerror(errno), (char *)0);
307 fflush(stderr); /* just in case error() doesn't */
308 _exit(EXEC_FAILED_EXIT_STATUS);
313 if (ncommands > 1 && !no_pipe) {
314 /* restore original stdin if it was redirected */
315 if (dup2(save_stdin, STDIN_FILENO) < 0) {
316 sprintf(err_str, "dup2(save_stdin))");
319 /* close stdin copy */
320 if (close(save_stdin) < 0) {
321 sprintf(err_str, "close(save_stdin)");
326 for (i = 0; i < ncommands; i++) {
331 if ((pid = WAIT(&status, pid, _WAIT_CHILD)) < 0) {
332 sprintf(err_str, "%s: wait", commands[i][0]);
335 else if (status != 0)
341 #else /* not _WIN32 */
343 /* MSDOS doesn't have `fork', so we need to simulate the pipe by running
344 the programs in sequence with standard streams redirected to and
345 from temporary files.
349 /* A signal handler that just records that a signal has happened. */
350 static int child_interrupted;
352 static RETSIGTYPE signal_catcher(int signo)
357 int run_pipeline(int ncommands, char ***commands, int no_pipe)
359 int save_stdin = dup(0);
360 int save_stdout = dup(1);
366 /* Choose names for a pair of temporary files to implement the pipeline.
367 Microsoft's `tempnam' uses the directory specified by `getenv("TMP")'
368 if it exists; in case it doesn't, try the GROFF alternatives, or
369 `getenv("TEMP")' as last resort -- at least one of these had better
370 be set, since Microsoft's default has a high probability of failure. */
372 if ((tmpdir = getenv("GROFF_TMPDIR")) == NULL
373 && (tmpdir = getenv("TMPDIR")) == NULL)
374 tmpdir = getenv("TEMP");
376 /* Don't use `tmpnam' here: Microsoft's implementation yields unusable
377 file names if current directory is on network share with read-only
379 tmpfiles[0] = tempnam(tmpdir, NULL);
380 tmpfiles[1] = tempnam(tmpdir, NULL);
382 for (i = 0; i < ncommands; i++) {
384 RETSIGTYPE (*prev_handler)(int);
387 /* redirect stdin from temp file */
388 f = open(tmpfiles[infile], O_RDONLY|O_BINARY, 0666);
390 sys_fatal("open stdin");
392 sys_fatal("dup2 stdin");
394 sys_fatal("close stdin");
396 if ((i < ncommands - 1) && !no_pipe) {
397 /* redirect stdout to temp file */
398 f = open(tmpfiles[outfile], O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
400 sys_fatal("open stdout");
402 sys_fatal("dup2 stdout");
404 sys_fatal("close stdout");
406 else if (dup2(save_stdout, 1) < 0)
407 sys_fatal("restore stdout");
409 /* run the program */
410 child_interrupted = 0;
411 prev_handler = signal(SIGINT, signal_catcher);
412 exit_status = spawnvp(P_WAIT, commands[i][0], commands[i]);
413 signal(SIGINT, prev_handler);
414 if (child_interrupted) {
415 error("%1: Interrupted", commands[i][0], (char *)0, (char *)0);
418 else if (exit_status < 0) {
419 error("couldn't exec %1: %2",
420 commands[i][0], strerror(errno), (char *)0);
421 fflush(stderr); /* just in case error() doesn't */
424 if (exit_status != 0)
426 /* There's no sense to continue with the pipe if one of the
427 programs has ended abnormally, is there? */
430 /* swap temp files: make output of this program be input for the next */
432 outfile = 1 - outfile;
434 if (dup2(save_stdin, 0) < 0)
435 sys_fatal("restore stdin");
441 #endif /* not _WIN32 */
443 #else /* not __MSDOS__, not _WIN32 */
445 int run_pipeline(int ncommands, char ***commands, int no_pipe)
449 PID_T pids[MAX_COMMANDS];
451 int proc_count = ncommands;
453 for (i = 0; i < ncommands; i++) {
457 if ((i != ncommands - 1) && !no_pipe) {
466 if (last_input != 0) {
469 if (dup(last_input) < 0)
471 if (close(last_input) < 0)
474 if ((i != ncommands - 1) && !no_pipe) {
477 if (dup(pdes[1]) < 0)
479 if (close(pdes[1]) < 0)
484 execvp(commands[i][0], commands[i]);
485 error("couldn't exec %1: %2",
486 commands[i][0], strerror(errno), (char *)0);
487 fflush(stderr); /* just in case error() doesn't */
488 _exit(EXEC_FAILED_EXIT_STATUS);
491 if (last_input != 0) {
492 if (close(last_input) < 0)
495 if ((i != ncommands - 1) && !no_pipe) {
496 if (close(pdes[1]) < 0)
498 last_input = pdes[0];
502 while (proc_count > 0) {
504 PID_T pid = wait(&status);
508 for (i = 0; i < ncommands; i++)
509 if (pids[i] == pid) {
512 if (WIFSIGNALED(status)) {
513 int sig = WTERMSIG(status);
515 if (sig == SIGPIPE) {
516 if (i == ncommands - 1) {
517 /* This works around a problem that occurred when using the
518 rerasterize action in gxditview. What seemed to be
519 happening (on SunOS 4.1.1) was that pclose() closed the
520 pipe and waited for groff, gtroff got a SIGPIPE, but
521 gpic blocked writing to gtroff, and so groff blocked
522 waiting for gpic and gxditview blocked waiting for
523 groff. I don't understand why gpic wasn't getting a
527 for (j = 0; j < ncommands; j++)
529 (void)kill(pids[j], SIGPIPE);
538 WCOREDUMP(status) ? " (core dumped)" : "");
542 else if (WIFEXITED(status)) {
543 int exit_status = WEXITSTATUS(status);
545 if (exit_status == EXEC_FAILED_EXIT_STATUS)
547 else if (exit_status != 0)
551 error("unexpected status %1", i_to_a(status), (char *)0, (char *)0);
558 #endif /* not __MSDOS__, not _WIN32 */
560 static void sys_fatal(const char *s)
562 c_fatal("%1: %2", s, strerror(errno), (char *)0);
565 static const char *xstrsignal(int n)
567 static char buf[sizeof("Signal ") + 1 + sizeof(int) * 3];
570 #if HAVE_DECL_SYS_SIGLIST
571 if (n >= 0 && n < NSIG && sys_siglist[n] != 0)
572 return sys_siglist[n];
573 #endif /* HAVE_DECL_SYS_SIGLIST */
575 sprintf(buf, "Signal %d", n);