1 /* Copyright (C) 1989, 1990, 1991, 1992 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 2, or (at your option) any later
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 along
17 with groff; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 -DWCOREFLAG=0200 (or whatever)
33 #include <sys/types.h>
45 extern char *strerror();
53 #else /* not _POSIX_VERSION */
55 /* traditional Unix */
57 #define WIFEXITED(s) (((s) & 0377) == 0)
58 #define WIFSTOPPED(s) (((s) & 0377) == 0177)
59 #define WIFSIGNALED(s) (((s) & 0377) != 0 && (((s) & 0377) != 0177))
60 #define WEXITSTATUS(s) (((s) >> 8) & 0377)
61 #define WTERMSIG(s) ((s) & 0177)
62 #define WSTOPSIG(s) (((s) >> 8) & 0377)
65 #define WCOREFLAG 0200
70 #endif /* not _POSIX_VERSION */
72 /* SVR4 uses WCOREFLG; Net 2 uses WCOREFLAG. */
75 #define WCOREFLAG WCOREFLG
77 #endif /* not WCOREFLAG */
81 #define WCOREDUMP(s) ((s) & WCOREFLAG)
82 #else /* not WCOREFLAG */
83 #define WCOREDUMP(s) (0)
84 #endif /* WCOREFLAG */
85 #endif /* not WCOREDUMP */
90 #define P(parms) parms
96 extern void error
P((char *, char *, char *, char *));
98 static void sys_fatal
P((char *));
99 static char *strsignal
P((int));
100 static char *itoa
P((int));
102 int run_pipeline(ncommands
, commands
)
108 PID_T pids
[MAX_COMMANDS
];
110 int proc_count
= ncommands
;
112 for (i
= 0; i
< ncommands
; i
++) {
115 if (i
!= ncommands
- 1) {
124 if (last_input
!= 0) {
127 if (dup(last_input
) < 0)
129 if (close(last_input
) < 0)
132 if (i
!= ncommands
- 1) {
135 if (dup(pdes
[1]) < 0)
137 if (close(pdes
[1]) < 0)
142 execvp(commands
[i
][0], commands
[i
]);
143 error("couldn't exec %1: %2", commands
[i
][0],
144 strerror(errno
), (char *)0);
145 fflush(stderr
); /* just in case error() doesn't */
146 _exit(EXEC_FAILED_EXIT_STATUS
);
149 if (last_input
!= 0) {
150 if (close(last_input
) < 0)
153 if (i
!= ncommands
- 1) {
154 if (close(pdes
[1]) < 0)
156 last_input
= pdes
[0];
160 while (proc_count
> 0) {
162 PID_T pid
= wait(&status
);
165 for (i
= 0; i
< ncommands
; i
++)
166 if (pids
[i
] == pid
) {
169 if (WIFSIGNALED(status
)) {
170 int sig
= WTERMSIG(status
);
172 if (sig
== SIGPIPE
) {
173 if (i
== ncommands
- 1) {
175 /* This works around a problem that occurred when using the
176 rerasterize action in gxditview. What seemed to be
177 happening (on SunOS 4.1.1) was that pclose() closed the
178 pipe and waited for groff, gtroff got a SIGPIPE, but
179 gpic blocked writing to gtroff, and so groff blocked
180 waiting for gpic and gxditview blocked waiting for
181 groff. I don't understand why gpic wasn't getting a
184 for (j
= 0; j
< ncommands
; j
++)
186 (void)kill(pids
[j
], SIGPIPE
);
195 WCOREDUMP(status
) ? " (core dumped)" : "");
199 else if (WIFEXITED(status
)) {
200 int exit_status
= WEXITSTATUS(status
);
201 if (exit_status
== EXEC_FAILED_EXIT_STATUS
)
203 else if (exit_status
!= 0)
207 error("unexpected status %1",
208 itoa(status
), (char *)0, (char *)0);
215 static void sys_fatal(s
)
218 c_fatal("%1: %2", s
, strerror(errno
), (char *)0);
225 sprintf(buf
, "%d", n
);
229 static char *strsignal(n
)
232 static char buf
[sizeof("Signal ") + 1 + sizeof(int)*3];
233 #ifdef HAVE_SYS_SIGLIST
234 extern char *sys_siglist
[];
235 if (n
>= 0 && n
< NSIG
&& sys_siglist
[n
] != 0)
236 return sys_siglist
[n
];
237 #endif /* HAVE_SYS_SIGLIST */
238 sprintf(buf
, "Signal %d", n
);