d988a8c9a086e2d2fac36cd6b819f7d11d350641
[platform/upstream/groff.git] / src / roff / groff / pipeline.c
1 /* Copyright (C) 1989-2014  Free Software Foundation, Inc.
2      Written by James Clark (jjc@jclark.com)
3
4 This file is part of groff.
5
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.
10
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
14 for more details.
15
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/>. */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <signal.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30
31 #ifdef HAVE_STRERROR
32 #include <string.h>
33 #else
34 extern char *strerror();
35 #endif
36
37 #ifdef _POSIX_VERSION
38
39 #include <sys/wait.h>
40 #define PID_T pid_t
41
42 #else /* not _POSIX_VERSION */
43
44 /* traditional Unix */
45
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)
52
53 #ifndef WCOREFLAG
54 #define WCOREFLAG 0200
55 #endif
56
57 #define PID_T int
58
59 #endif /* not _POSIX_VERSION */
60
61 /* SVR4 uses WCOREFLG; Net 2 uses WCOREFLAG. */
62 #ifndef WCOREFLAG
63 #ifdef WCOREFLG
64 #define WCOREFLAG WCOREFLG
65 #endif /* WCOREFLG */
66 #endif /* not WCOREFLAG */
67
68 #ifndef WCOREDUMP
69 #ifdef WCOREFLAG
70 #define WCOREDUMP(s) ((s) & WCOREFLAG)
71 #else /* not WCOREFLAG */
72 #define WCOREDUMP(s) (0)
73 #endif /* WCOREFLAG */
74 #endif /* not WCOREDUMP */
75
76 #include "pipeline.h"
77
78 #define error c_error
79
80 #ifdef __cplusplus
81 extern "C" {
82 #endif
83
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 */
87
88 #ifdef __cplusplus
89 }
90 #endif
91
92 static void sys_fatal(const char *);
93 static const char *xstrsignal(int);
94
95
96 #if defined(__MSDOS__) \
97     || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \
98     || defined(__EMX__)
99
100 #include <process.h>
101 #include <fcntl.h>
102 #include <string.h>
103 #include <stdlib.h>
104
105 #include "nonposix.h"
106
107 static const char *sh = "sh";
108 static const char *cmd = "cmd";
109 static const char *command = "command";
110
111 extern int strcasecmp(const char *, const char *);
112
113 char *sbasename(const char *path)
114 {
115   char *base;
116   const char *p1, *p2;
117
118   p1 = path;
119   if ((p2 = strrchr(p1, '\\'))
120       || (p2 = strrchr(p1, '/'))
121       || (p2 = strrchr(p1, ':')))
122     p1 = p2 + 1;
123   if ((p2 = strrchr(p1, '.'))
124       && ((strcasecmp(p2, ".exe") == 0)
125           || (strcasecmp(p2, ".com") == 0)))
126     ;
127   else
128     p2 = p1 + strlen(p1);
129
130   base = malloc((size_t)(p2 - p1));
131   strncpy(base, p1, p2 - p1);
132   *(base + (p2 - p1)) = '\0';
133
134   return(base);
135 }
136
137 /* Get the name of the system shell */
138 char *system_shell_name(void)
139 {
140   const char *shell_name;
141
142   /*
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.
146    */
147
148   if ((shell_name = getenv("SHELL")) != NULL)
149     ;
150   else if (spawnlp(_P_WAIT, sh, sh, "-c", ":", NULL) == 0)
151     shell_name = sh;
152   else if ((shell_name = getenv("COMSPEC")) != NULL)
153     ;
154   else if (spawnlp(_P_WAIT, cmd, cmd, "/c", ";", NULL) == 0)
155     shell_name = cmd;
156   else
157     shell_name = command;
158
159   return sbasename(shell_name);
160 }
161
162 const char *system_shell_dash_c(void)
163 {
164   char *shell_name;
165   const char *dash_c;
166
167   shell_name = system_shell_name();
168
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)
171     dash_c = "-c";
172   else
173     dash_c = "/c";
174
175   free(shell_name);
176   return dash_c;
177 }
178
179 int is_system_shell(const char *prog)
180 {
181   int result;
182   char *this_prog, *system_shell;
183
184   if (!prog)    /* paranoia */
185     return 0;
186
187   this_prog = sbasename(prog);
188   system_shell = system_shell_name();
189
190   result = strcasecmp(this_prog, system_shell) == 0;
191
192   free(this_prog);
193   free(system_shell);
194
195   return result;
196 }
197
198 #ifdef _WIN32
199
200 /*
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.
208 */
209
210 int run_pipeline(int ncommands, char ***commands, int no_pipe)
211 {
212   int i;
213   int last_input = 0;   /* pacify some compilers */
214   int save_stdin = 0;
215   int save_stdout = 0;
216   int ret = 0;
217   char err_str[BUFSIZ];
218   PID_T pids[MAX_COMMANDS];
219
220   for (i = 0; i < ncommands; i++) {
221     int pdes[2];
222     PID_T pid;
223
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]);
231           sys_fatal(err_str);
232         }
233       }
234       /* 1st command; writer */
235       if (i == 0) {
236         /* save stdin */
237         if ((save_stdin = dup(STDIN_FILENO)) < 0)
238           sys_fatal("dup stdin");
239         /* save stdout */
240         if ((save_stdout = dup(STDOUT_FILENO)) < 0)
241           sys_fatal("dup stdout");
242
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]);
246           sys_fatal(err_str);
247         }
248         if (close(pdes[1]) < 0) {
249           sprintf(err_str, "%s: close(pipe[WRITE])", commands[i][0]);
250           sys_fatal(err_str);
251         }
252         /*
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.
256         */
257         last_input = pdes[0];
258       }
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]);
264           sys_fatal(err_str);
265         }
266         if (close(last_input) < 0) {
267           sprintf(err_str, "%s: close(last_input)", commands[i][0]);
268           sys_fatal(err_str);
269         }
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]);
273           sys_fatal(err_str);
274         }
275         if (close(pdes[1]) < 0) {
276           sprintf(err_str, "%s: close(pipe[WRITE])", commands[i][0]);
277           sys_fatal(err_str);
278         }
279         last_input = pdes[0];
280       }
281       /* last command; reader */
282       else {
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]);
286           sys_fatal(err_str);
287         }
288         if (close(last_input) < 0) {
289           sprintf(err_str, "%s: close(last_input)", commands[i][0]);
290           sys_fatal(err_str);
291         }
292         /* restore original stdout */
293         if (dup2(save_stdout, STDOUT_FILENO) < 0) {
294           sprintf(err_str, "%s: dup2(save_stdout))", commands[i][0]);
295           sys_fatal(err_str);
296         }
297         /* close stdout copy */
298         if (close(save_stdout) < 0) {
299           sprintf(err_str, "%s: close(save_stdout)", commands[i][0]);
300           sys_fatal(err_str);
301         }
302       }
303     }
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);
309     }
310     pids[i] = pid;
311   }
312
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))");
317       sys_fatal(err_str);
318     }
319     /* close stdin copy */
320     if (close(save_stdin) < 0) {
321       sprintf(err_str, "close(save_stdin)");
322       sys_fatal(err_str);
323     }
324   }
325
326   for (i = 0; i < ncommands; i++) {
327     int status;
328     PID_T pid;
329
330     pid = pids[i];
331     if ((pid = WAIT(&status, pid, _WAIT_CHILD)) < 0) {
332       sprintf(err_str, "%s: wait", commands[i][0]);
333       sys_fatal(err_str);
334     }
335     else if (status != 0)
336       ret |= 1;
337   }
338   return ret;
339 }
340
341 #else  /* not _WIN32 */
342
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.
346 */
347
348
349 /* A signal handler that just records that a signal has happened.  */
350 static int child_interrupted;
351
352 static RETSIGTYPE signal_catcher(int signo)
353 {
354   child_interrupted++;
355 }
356
357 int run_pipeline(int ncommands, char ***commands, int no_pipe)
358 {
359   int save_stdin = dup(0);
360   int save_stdout = dup(1);
361   char *tmpfiles[2];
362   int infile  = 0;
363   int outfile = 1;
364   int i, f, ret = 0;
365
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. */
371   char *tmpdir;
372   if ((tmpdir = getenv("GROFF_TMPDIR")) == NULL
373       && (tmpdir = getenv("TMPDIR")) == NULL)
374     tmpdir = getenv("TEMP");
375
376   /* Don't use `tmpnam' here: Microsoft's implementation yields unusable
377      file names if current directory is on network share with read-only
378      root. */
379   tmpfiles[0] = tempnam(tmpdir, NULL);
380   tmpfiles[1] = tempnam(tmpdir, NULL);
381
382   for (i = 0; i < ncommands; i++) {
383     int exit_status;
384     RETSIGTYPE (*prev_handler)(int);
385
386     if (i && !no_pipe) {
387       /* redirect stdin from temp file */
388       f = open(tmpfiles[infile], O_RDONLY|O_BINARY, 0666);
389       if (f < 0)
390         sys_fatal("open stdin");
391       if (dup2(f, 0) < 0)
392         sys_fatal("dup2 stdin"); 
393       if (close(f) < 0)
394         sys_fatal("close stdin");
395     }
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);
399       if (f < 0)
400         sys_fatal("open stdout");
401       if (dup2(f, 1) < 0)
402         sys_fatal("dup2 stdout");
403       if (close(f) < 0)
404         sys_fatal("close stdout");
405     }
406     else if (dup2(save_stdout, 1) < 0)
407       sys_fatal("restore stdout");
408
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);
416       ret |= 2;
417     }
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 */
422       ret |= 4;
423     }
424     if (exit_status != 0)
425       ret |= 1;
426     /* There's no sense to continue with the pipe if one of the
427        programs has ended abnormally, is there? */
428     if (ret != 0)
429       break;
430     /* swap temp files: make output of this program be input for the next */
431     infile = 1 - infile;
432     outfile = 1 - outfile;
433   }
434   if (dup2(save_stdin, 0) < 0)
435     sys_fatal("restore stdin");
436   unlink(tmpfiles[0]);
437   unlink(tmpfiles[1]);
438   return ret;
439 }
440
441 #endif /* not _WIN32 */
442
443 #else /* not __MSDOS__, not _WIN32 */
444
445 int run_pipeline(int ncommands, char ***commands, int no_pipe)
446 {
447   int i;
448   int last_input = 0;
449   PID_T pids[MAX_COMMANDS];
450   int ret = 0;
451   int proc_count = ncommands;
452
453   for (i = 0; i < ncommands; i++) {
454     int pdes[2];
455     PID_T pid;
456
457     if ((i != ncommands - 1) && !no_pipe) {
458       if (pipe(pdes) < 0)
459         sys_fatal("pipe");
460     }
461     pid = fork();
462     if (pid < 0)
463       sys_fatal("fork");
464     if (pid == 0) {
465       /* child */
466       if (last_input != 0) {
467         if (close(0) < 0)
468           sys_fatal("close");
469         if (dup(last_input) < 0)
470           sys_fatal("dup");
471         if (close(last_input) < 0)
472           sys_fatal("close");
473       }
474       if ((i != ncommands - 1) && !no_pipe) {
475         if (close(1) < 0)
476           sys_fatal("close");
477         if (dup(pdes[1]) < 0)
478           sys_fatal("dup");
479         if (close(pdes[1]) < 0)
480           sys_fatal("close");
481         if (close(pdes[0]))
482           sys_fatal("close");
483       }
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);
489     }
490     /* in the parent */
491     if (last_input != 0) {
492       if (close(last_input) < 0)
493         sys_fatal("close");
494     }
495     if ((i != ncommands - 1) && !no_pipe) {
496       if (close(pdes[1]) < 0)
497         sys_fatal("close");
498       last_input = pdes[0];
499     }
500     pids[i] = pid;
501   }
502   while (proc_count > 0) {
503     int status;
504     PID_T pid = wait(&status);
505
506     if (pid < 0)
507       sys_fatal("wait");
508     for (i = 0; i < ncommands; i++)
509       if (pids[i] == pid) {
510         pids[i] = -1;
511         --proc_count;
512         if (WIFSIGNALED(status)) {
513           int sig = WTERMSIG(status);
514 #ifdef SIGPIPE
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
524                  SIGPIPE. */
525               int j;
526
527               for (j = 0; j < ncommands; j++)
528                 if (pids[j] > 0)
529                   (void)kill(pids[j], SIGPIPE);
530             }
531           }
532           else
533 #endif /* SIGPIPE */
534           {
535             error("%1: %2%3",
536                   commands[i][0],
537                   xstrsignal(sig),
538                   WCOREDUMP(status) ? " (core dumped)" : "");
539             ret |= 2;
540           }
541         }
542         else if (WIFEXITED(status)) {
543           int exit_status = WEXITSTATUS(status);
544
545           if (exit_status == EXEC_FAILED_EXIT_STATUS)
546             ret |= 4;
547           else if (exit_status != 0)
548             ret |= 1;
549         }
550         else
551           error("unexpected status %1", i_to_a(status), (char *)0, (char *)0);
552         break;
553       }
554   }
555   return ret;
556 }
557
558 #endif /* not __MSDOS__, not _WIN32 */
559
560 static void sys_fatal(const char *s)
561 {
562   c_fatal("%1: %2", s, strerror(errno), (char *)0);
563 }
564
565 static const char *xstrsignal(int n)
566 {
567   static char buf[sizeof("Signal ") + 1 + sizeof(int) * 3];
568
569 #ifdef NSIG
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 */
574 #endif /* NSIG */
575   sprintf(buf, "Signal %d", n);
576   return buf;
577 }