+++ /dev/null
-# -*- perl -*-
-# Pipeline -- library of process spawn functions that do not invoke a shell
-
-# Copyright (C) 1998 Richard Braakman
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, you can find it on the World Wide
-# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
-# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
-# MA 02110-1301, USA.
-
-package Pipeline;
-use strict;
-
-use Exporter;
-our @ISA = qw(Exporter);
-our @EXPORT = qw(spawn pipeline pipeline_open pipeline_pure);
-
-use Fcntl;
-
-
-# This is used to avoid END blocks and such, when exiting from
-# children that have not execed.
-use POSIX;
-sub immediate_exit { POSIX::_exit($_[0] + 0); }
-
-# The pipeline function takes a list of coderefs, which are forked off
-# as processes. The stdout of each is connected to the stdin of the
-# next.
-
-# The coderefs will usually be 'exec' calls. If the code does return,
-# the process will exit with the return value of that code. That way
-# you don't have to check if the exec succeeded.
-#
-# Use an explicit exit statement if you don't want this.
-
-# The first list element may be a filename instead of a coderef, in which
-# case it will be opened as stdin for the first process.
-# The last list element may also be a filename instead of a coderef, in
-# which case it will be opened as stdout for the last process.
-
-# pipeline() returns the exit value of the last process in the pipe,
-# or 255 if the exec failed.
-
-sub pipeline {
- my $i;
- my $pid = fork();
- defined $pid or return 255;
-
- if (not $pid) { # child
- sysopen(STDIN, shift, O_RDONLY)
- or fail("$$: cannot redirect input: $!")
- unless ref($_[0]) eq "CODE";
- sysopen(STDOUT, pop, O_WRONLY|O_CREAT|O_TRUNC)
- or fail("$$: cannot redirect output: $!")
- unless ref($_[$#_]) eq "CODE";
-
- # Perhaps I should submit this to the obfuscated perl contest.
- $i = @_ or immediate_exit 0;
- $pid = open(STDIN, "-|") while $pid == 0 and --$i;
- defined $pid or fail("cannot fork: $!");
- immediate_exit int(&{$_[$i]});
- } else { # parent
- waitpid($pid, 0);
- return $?;
- }
-}
-
-# pipeline_open is just like pipeline, except that it takes a filehandle
-# as its first argument, and cannot take both an input filename and
-# an output filename. It connects the filehandle to stdout of the
-# last process if no output filename is given, and connects it to
-# stdin of the first process otherwise. (Be sure to handle SIGPIPE
-# if you do the latter).
-# pipeline_open() returns the pid of the child process, or undef if it failed.
-
-sub pipeline_open (*@) {
- my ($i, $pid);
- if (ref($_[$#_]) eq "CODE") {
- $pid = open(shift, "-|");
- } else {
- $pid = open(shift, "|-");
- }
- defined $pid or return undef;
-
- if (not $pid) { # child
- sysopen(STDIN, shift, O_RDONLY)
- or fail("$$: cannot redirect input: $!")
- unless ref($_[0]) eq "CODE";
- sysopen(STDOUT, pop, O_WRONLY|O_CREAT|O_TRUNC)
- or fail("$$: cannot redirect output: $!")
- unless ref($_[$#_]) eq "CODE";
-
- $i = @_ or immediate_exit 0;
- $pid = open(STDIN, "-|") while $pid == 0 and --$i;
- defined $pid or fail("cannot fork: $!");
- immediate_exit int(&{$_[$i]});
- }
- # parent does nothing
- return $pid;
-}
-
-# Fork off a single process that immediately execs. It has a simpler
-# calling syntax than pipeline() with only one argument.
-
-# It returns the exit code of the execed process, or 255 if the
-# fork or exec failed.
-
-sub spawn {
- my $pid = fork();
- defined $pid or return 255;
-
- if (not $pid) { # child
- exec @_ or immediate_exit 255;
- } else {
- waitpid($pid, 0);
- return $?;
- }
-}
-
-# This is just an experiment to see if the loop alone is useful.
-# It looks like it isn't.
-#sub pipeline_pure {
-# my $pid = 0;
-# my $i = @_ or return;
-# $pid = open(STDIN, "-|") while $pid == 0 and --$i;
-# defined $pid or fail("cannot fork: $!");
-# &{$_[$i]};
-# close(STDIN) or fail("child process failed: $?") if $pid;
-# immediate_exit 0 unless $i == $#_;
-#}
-
-1;