📄 filter.c
字号:
fc_next_simple_command_init(fcp);}/***************************************************************** functions to add new args to current simple command****************************************************************//* * fc_add_arg -- add one argument */voidfc_add_arg(fcp, arg)register FCP fcp;char *arg;{ if (fcp->fc_i >= fcp->fc_max) { fc_grow(fcp); } fcp->fc_argv[fcp->fc_nf][fcp->fc_i++] = strsave(arg);}/* * fc_add_args_l -- add 0 terminated list of arguments to * current simple command *//*VARARGS1*/voidfc_add_args_l(fcp, va_alist)register FCP fcp;va_dcl{ va_list ap; register char *str; va_start(ap); while (str = va_arg(ap, char *)) { if (fcp->fc_i >= fcp->fc_max) { fc_grow(fcp); } fcp->fc_argv[fcp->fc_nf][fcp->fc_i++] = strsave(str); } va_end(ap);}/* * fc_add_args_v -- add a vector of arguments to current simple command */voidfc_add_args_v(fcp, argv)register FCP fcp;char **argv;{ while (*argv) { if (fcp->fc_i >= fcp->fc_max) { fc_grow(fcp); } fcp->fc_argv[fcp->fc_nf][fcp->fc_i++] = strsave(*argv++); }}/* * fc_add_args_va -- add va_list of arguments to current simple command */voidfc_add_args_va(fcp, ap)register FCP fcp;va_list ap;{ register char *str; while (str = va_arg(ap, char *)) { if (fcp->fc_i >= fcp->fc_max) { fc_grow(fcp); } fcp->fc_argv[fcp->fc_nf][fcp->fc_i++] = strsave(str); }}/***************************************************************** functions to fire up the filters****************************************************************//* * fc_run -- run a filter * * Description: * This does the business after any necessary plumbing (pipes) * to the file descriptors 0, 1 & 2 has been done by fc_plumb_and_run() */static voidfc_run(fcp, fork_action)register FCP fcp;int fork_action; /* argument to dofork() */{ register int nf; /* counter for pipe building loop */ extern char **environ; if (fcp->fc_mon_start) /* Start progress monitor */ (*fcp->fc_mon_start)(fcp); if (fcp->fc_nf == 0) { /* no filters: straight copy */ register int n; char buf[BUFSIZ]; dlog(0, "fc_run: straight copy"); while ((n = read(fcp->fc_fds[FC_STDIN], buf, BUFSIZ)) > 0) { if (write(fcp->fc_fds[FC_STDOUT], buf, n) != n) { fcp->fc_status.w_retcode = 1; break; } } if (fcp->fc_mon_stop) /* Stop progress monitor */ (*fcp->fc_mon_stop)(); fcp->fc_state = fc_done; return; } if (DB > 0) { /* DEBUGGING: print log message */ int i; log("fc_run: "); for (i = 0; i < fcp->fc_nf; ) { printv(fcp->fc_argv[i]); fprintf(stderr, (++i < fcp->fc_nf) ? "| " : "\n"); } } /* * Many actions in the pipe building loop * are conditional on the following macros which * determine whether the particular simple command * is first or last in the pipeline and therefore * needs to be plumbed to the outside world. */#define first_in_pipeline (nf == 0)#define last_in_pipeline (nf == (fcp->fc_nf-1)) for (nf = 0; nf < fcp->fc_nf; nf++) { int pipe_fd[2]; /* pipe file descriptors */ int i; /* index for handling vector of fd's */ if (!last_in_pipeline) pipe(pipe_fd); if ((fcp->fc_pid[nf] = dofork(fork_action)) == 0) { /* child */ if (!last_in_pipeline) { fcp->fc_fds[FC_STDOUT] = pipe_fd[1]; close(pipe_fd[0]); } /* * deal with file descriptors 0, 1 & 2 */ for (i = 0; i < 3; i++) { if (fcp->fc_fds[i] >= 0) { if (fcp->fc_fds[i] != i) (void)dup2(fcp->fc_fds[i], i); } else { (void) close(i); } } /* close rest of file descriptors */ for (i = 3; i < NOFILE; i++) (void) close(i); /* set up new PATH in environment */ if (PATH_STRING && !(environ = chenv(environ, PATH_STRING))) { log("No PATH in inherited environment"); exit(3); } execvp(fcp->fc_argv[nf][0], fcp->fc_argv[nf]); log("filter %s: not found\n", fcp->fc_argv[nf][0]); exit(2); } else if (fcp->fc_pid[nf] > 0) { /* parent */ dlog(0, "fc_run: filter %d, pid %d", nf, fcp->fc_pid[nf]); if (!first_in_pipeline) { (void) close(fcp->fc_fds[FC_STDIN]); } if (!last_in_pipeline) { (void) close(pipe_fd[1]); fcp->fc_fds[FC_STDIN] = pipe_fd[0]; } fcp->fc_state = fc_running; } else { /* dofork() failed */ if (!last_in_pipeline) { (void) close(pipe_fd[0]); (void) close(pipe_fd[1]); } fcp->fc_status.w_retcode = 1; /* force a retry */ fcp->fc_state = fc_done; break; } } return;}/* * fc_plumb_and_run -- Exported function to run a filter * * Description: * We build any pipes requested and then call fc_run * Note that the ends of the pipes of interest to * the children are passed via the array in the filter struct. * The ends of the pipe which interest the parent are copied * in by this function before it returns. */extern voidfc_plumb_and_run(fcp, fork_action, fd_in, fd_out, fd_err)register FCP fcp;int fork_action;int fd_in;int fd_out;int fd_err;{ int pipe_fd[2]; int parent_fds[3]; int pipe_unwanted_fds[3]; register int i; fcp->fc_fds[FC_STDIN] = fd_in; fcp->fc_fds[FC_STDOUT] = fd_out; fcp->fc_fds[FC_STDERR] = fd_err; for (i=0; i < 3; i++) { if (fcp->fc_fds[i] == FC_MAKEPIPE) { fcp->fc_is_pipe |= (1<<i); parent_fds[i] = fcp->fc_fds[i]; } } /* * If we have any pipes at all then it must not be * a null filter */ if (fcp->fc_is_pipe && fcp->fc_nf == 0) { /* This shouldn't happen, indicates coding error */ dlog(0,"fc_plumb_and_run: Can't pipe to empty filter"); fcp->fc_is_pipe = 0; fcp->fc_state = fc_done; } if (fcp->fc_is_pipe & (1<<FC_STDIN)) { pipe(pipe_fd); pipe_unwanted_fds[FC_STDIN] = fcp->fc_fds[FC_STDIN] = pipe_fd[0]; parent_fds[FC_STDIN] = pipe_fd[1]; } if (fcp->fc_is_pipe & (1<<FC_STDOUT)) { pipe(pipe_fd); pipe_unwanted_fds[FC_STDOUT] = fcp->fc_fds[FC_STDOUT] = pipe_fd[1]; parent_fds[FC_STDOUT] = pipe_fd[0]; } if (fcp->fc_is_pipe & (1<<FC_STDERR)) { pipe(pipe_fd); pipe_unwanted_fds[FC_STDERR] = fcp->fc_fds[FC_STDERR] = pipe_fd[1]; parent_fds[FC_STDERR] = pipe_fd[0]; } fc_run(fcp, fork_action); for (i=0; i < 3; i++) { if (fcp->fc_is_pipe & (1<<i)) { fcp->fc_fds[i] = parent_fds[i]; (void) close(pipe_unwanted_fds[i]); } else { fcp->fc_fds[i] = FC_FD_CLOSED; } }}/* * fc_wait wait for termination of filter and return exit status */union waitfc_wait(fcp)FCP fcp;{ register int pid = -1; register int last_pid; if (fcp->fc_state == fc_running && fcp->fc_nf > 0) { last_pid = fcp->fc_pid[fcp->fc_nf - 1]; dlog(0, "fc_wait: filter %d %s", last_pid, ((kill(last_pid, 0) < 0) ? "has exited" : "is still running")); for (pid = 0; pid >= 0 && pid != last_pid; ) { fcp->fc_status.w_status = 0; pid = wait(&fcp->fc_status); if (pid > 0) dlog(0, "fc_wait: Found process %d", pid); } if (fcp->fc_mon_stop) /* Stop progress monitor */ (*fcp->fc_mon_stop)(); fcp->fc_state = fc_done; if (pid != last_pid) { dlog(0, "fc_wait: Couldn't find process %d", last_pid); } else if (DB > 0){ if (WIFEXITED(fcp->fc_status)) { log("Process %d exited status %d", pid, fcp->fc_status.w_retcode); } else if (WIFSIGNALED(fcp->fc_status)) { log("Process %d killed by signal %d%s", pid, fcp->fc_status.w_termsig, ((fcp->fc_status.w_coredump) ? " with core dump" : "")); } } } /* This recursive call is to clean up lpserrof */ if (fcp->fc_next) (void)fc_wait(fcp->fc_next); return fcp->fc_status;}/***************************************************************** functions relating to process control of filters run* with a pipe to their standard input****************************************************************//* * fc_stop -- stop output filter with ^Y^A, then wash hands */intfc_stop(fcp)FCP fcp;{ int pid; if (!(fcp->fc_is_pipe && (1 <<0))) { dlog(0, "fc_stop: no input pipe"); return -1; } switch (fcp->fc_state) { default: /* not in suitable state: error */ break; case fc_stopped: /* already stopped, nothing to do */ break; case fc_running: /* ok to stop */ write(fcp->fc_fds[0], "\031\1", 2); while ((pid=wait3(&fcp->fc_status, WUNTRACED, 0)) > 0 && pid != fcp->fc_pid[0]) {} fcp->fc_state = ((WIFEXITED(fcp->fc_status)) ? fc_done : fc_stopped); break; } return ((fcp->fc_state == fc_stopped) ? 0 : -1); /* ok if stopped, else error */}/* * fc_start -- restart output filter with SIGCONT */intfc_start(fcp)FCP fcp;{ int pid; if (!(fcp->fc_is_pipe && (1 <<0))) { dlog(0, "fc_start: no input pipe"); return -1; } switch (fcp->fc_state) { default: /* not in suitable state: error */ break; case fc_running: /* already running, nothing to do */ break; case fc_stopped: /* ok to restart */ if (kill(fcp->fc_pid[0], SIGCONT) < 0) { dlog(0, "fc_start: process %d died",fcp->fc_pid[0]); fcp->fc_state = fc_done; } else { fcp->fc_state = fc_running; } break; } return ((fcp->fc_state == fc_running) ? 0 : -1); /* ok if running, else error */}/* * fc_pout_kill -- kill output filter by closing stdin * restart first if necessary */void fc_pout_kill(fcp)FCP fcp;{ register int pid; if (fc_start(fcp) == 0) { (void) close(fcp->fc_fds[0]); fcp->fc_fds[0] = FC_FD_CLOSED; } else { dlog(0, "fc_pout_kill: error: filter in state %s", "ready\0runng\0done\0\0stopped"[6*(int)fcp->fc_state]); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -