Oops. In the Perl code below, I wrote:
while (wait < 0) {}
it should read instead:
while (wait >= 0) {}
I was thinking of using an "until" construct, and changed mental gears
in mid-stream (how's that for a mixed metaphor? :^)
___________________________________________________________
Alan Stebbens <aks(_at_)sgi(_dot_)com> http://reality.sgi.com/aks
One of the greatest things about procmail is the ability to split a single
pipe input into many programs, or into files. For example, this construct:
:0c
| prog1
:0
| prog2
is very powerful. The only problem is that procmail seems to only deal with
mail-like input (as far as I can tell). Are there any other utilities that
anyone knows of that allows the splitting of the input in this way, but
doesn't
require its input to be in mail format?
Try Perl.
# writemany INPUT, OUTPUT1, OUTPUT2, ..
# Read all of INPUT, and write to the given output filehandles
# in parallel.
sub writemany {
my $input = shift; # input file-handle
my @output = @_; # output file-handles
my @input = (<$input>); # read all input at once
my $output;
foreach $output (@output) {
$output = ">$output" unless $output =~ /^[>|]/;
if (!fork) {
open(OUT,$output) ||
die "Can't open $output for output: $!\n";
print OUT @input;
exit;
}
}
while (wait < 0) {}; # wait for all the kids to come home
}
To use the subroutine:
writemany STDIN, "|prog1", "|prog2", "|prog3";
Strictly speaking, the procmail recipes above do not write their
outputs in parallel, but rather in serial fashion: one after the other.
The perl script above writes its input to one or more outputs in
parallel, each output stream being written by a different process.
There are advantages and disadvantages both ways.
If you only care to write output in parallel, which has less overhead
on the system, then the Perl subroutine looks like this:
sub writemany {
my $input = shift; # input file-handle
my @outputs = @_; # output file-handles
my @input = (<$input>); # read all input at once
my $output;
foreach $output (@outputs) {
$output = ">$output" unless $output =~ /^[>|]/;
open(OUT,$output) ||
die "Can't open $output for output: $!\n";
print OUT @input;
close OUT;
}
}
The procmail equivalent to the first Perl script is:
:0c
{ :0
|prog1
}
:0c
{ :0
|prog2
}
:0c
{ :0
|prog3
}
# ...
Procmail forks a child process when the "c" flag is given on
a nested block.
And, as far as I know, as long as you don't allow the input to be
delivered to a mailbox or piped to a mailer, then it can be arbitrary
data, especially using -m. Procmail will still try to parse it into
headers and a body, but if isn't parseable, procmail won't complain;
the input will just look like it has no headers.
However, Perl or another program is probably a better general
purpose tool for piping arbitrary data.
___________________________________________________________
Alan Stebbens <aks(_at_)sgi(_dot_)com> http://reality.sgi.com/aks