📄 pipeline.c
字号:
/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com)This file is part of groff.groff is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING. If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//*Compile options are:-DWCOREFLAG=0200 (or whatever)-DHAVE_VFORK_H-Dvfork=fork-DHAVE_SYS_SIGLIST-DHAVE_UNISTD_H*/#include <stdio.h>#include <signal.h>#include <errno.h>#include <sys/types.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_VFORK_H#include <vfork.h>#endif#ifndef errnoextern int errno;#endifextern char *strerror();#ifdef _POSIX_VERSION#include <sys/wait.h>#define PID_T pid_t#else /* not _POSIX_VERSION *//* traditional Unix */#define WIFEXITED(s) (((s) & 0377) == 0)#define WIFSTOPPED(s) (((s) & 0377) == 0177)#define WIFSIGNALED(s) (((s) & 0377) != 0 && (((s) & 0377) != 0177))#define WEXITSTATUS(s) (((s) >> 8) & 0377)#define WTERMSIG(s) ((s) & 0177)#define WSTOPSIG(s) (((s) >> 8) & 0377)#ifndef WCOREFLAG#define WCOREFLAG 0200#endif#define PID_T int#endif /* not _POSIX_VERSION *//* SVR4 uses WCOREFLG; Net 2 uses WCOREFLAG. */#ifndef WCOREFLAG#ifdef WCOREFLG#define WCOREFLAG WCOREFLG#endif /* WCOREFLG */#endif /* not WCOREFLAG */#ifndef WCOREDUMP#ifdef WCOREFLAG#define WCOREDUMP(s) ((s) & WCOREFLAG)#else /* not WCOREFLAG */#define WCOREDUMP(s) (0)#endif /* WCOREFLAG */#endif /* not WCOREDUMP */#include "pipeline.h"#ifdef __STDC__#define P(parms) parms#else#define P(parms) ()#endif#define error c_errorextern void error P((char *, char *, char *, char *));static void sys_fatal P((char *));static char *strsignal P((int));static char *itoa P((int));int run_pipeline(ncommands, commands) int ncommands; char ***commands;{ int i; int last_input = 0; PID_T pids[MAX_COMMANDS]; int ret = 0; int proc_count = ncommands; for (i = 0; i < ncommands; i++) { int pdes[2]; PID_T pid; if (i != ncommands - 1) { if (pipe(pdes) < 0) sys_fatal("pipe"); } pid = vfork(); if (pid < 0) sys_fatal("fork"); if (pid == 0) { /* child */ if (last_input != 0) { if (close(0) < 0) sys_fatal("close"); if (dup(last_input) < 0) sys_fatal("dup"); if (close(last_input) < 0) sys_fatal("close"); } if (i != ncommands - 1) { if (close(1) < 0) sys_fatal("close"); if (dup(pdes[1]) < 0) sys_fatal("dup"); if (close(pdes[1]) < 0) sys_fatal("close"); if (close(pdes[0])) sys_fatal("close"); } execvp(commands[i][0], commands[i]); error("couldn't exec %1: %2", commands[i][0], strerror(errno), (char *)0); fflush(stderr); /* just in case error() doesn't */ _exit(EXEC_FAILED_EXIT_STATUS); } /* in the parent */ if (last_input != 0) { if (close(last_input) < 0) sys_fatal("close"); } if (i != ncommands - 1) { if (close(pdes[1]) < 0) sys_fatal("close"); last_input = pdes[0]; } pids[i] = pid; } while (proc_count > 0) { int status; PID_T pid = wait(&status); if (pid < 0) sys_fatal("wait"); for (i = 0; i < ncommands; i++) if (pids[i] == pid) { pids[i] = -1; --proc_count; if (WIFSIGNALED(status)) { int sig = WTERMSIG(status);#ifdef SIGPIPE if (sig == SIGPIPE) { if (i == ncommands - 1) { /* This works around a problem that occurred when using the rerasterize action in gxditview. What seemed to be happening (on SunOS 4.1.1) was that pclose() closed the pipe and waited for groff, gtroff got a SIGPIPE, but gpic blocked writing to gtroff, and so groff blocked waiting for gpic and gxditview blocked waiting for groff. I don't understand why gpic wasn't getting a SIGPIPE. */ int j; for (j = 0; j < ncommands; j++) if (pids[j] > 0) (void)kill(pids[j], SIGPIPE); } } else#endif /* SIGPIPE */ { error("%1: %2%3", commands[i][0], strsignal(sig), WCOREDUMP(status) ? " (core dumped)" : ""); ret |= 2; } } else if (WIFEXITED(status)) { int exit_status = WEXITSTATUS(status); if (exit_status == EXEC_FAILED_EXIT_STATUS) ret |= 4; else if (exit_status != 0) ret |= 1; } else error("unexpected status %1", itoa(status), (char *)0, (char *)0); break; } } return ret;}static void sys_fatal(s) char *s;{ c_fatal("%1: %2", s, strerror(errno), (char *)0);}static char *itoa(n) int n;{ static char buf[12]; sprintf(buf, "%d", n); return buf;}static char *strsignal(n) int n;{ static char buf[sizeof("Signal ") + 1 + sizeof(int)*3];#ifdef HAVE_SYS_SIGLIST extern char *sys_siglist[]; if (n >= 0 && n < NSIG && sys_siglist[n] != 0) return sys_siglist[n];#endif /* HAVE_SYS_SIGLIST */ sprintf(buf, "Signal %d", n); return buf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -