chiark / gitweb /
Add innduct-forall
[innduct.git] / innduct-forall
diff --git a/innduct-forall b/innduct-forall
new file mode 100755 (executable)
index 0000000..e26aab5
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/perl -w
+use strict qw(vars refs);
+use IO::Handle;
+our $self= 'innduct-forall';
+our $deftable= '/etc/news/ducts.table';
+
+our $usage=<<END;
+usage:
+   $self [<ducts-table>] <pattern>
+where <pattern> is a sh command and may contain
+   !site    site name
+   !fqdn    fqdn or empty string
+   !opts    innduct options
+   !duct    shorthand for !opts !site !fqdn
+   !!       single !
+default ducts-table is $deftable
+END
+
+
+die "$self: bad usage\n$usage" unless
+    @ARGV>=1 && @ARGV<=2 && $ARGV[0] !~ m/^\-/;
+
+our $table= (@ARGV>1 ? shift @ARGV : $deftable);
+our $pattern= shift @ARGV;
+
+our $maxexit= 0;
+
+open T, '<', $table or die "$self: $table: $!\n";
+while (<T>) {
+    s/^\s*//; s/\s+$//;
+    next unless m/^[^\#]/;
+    my @v= split /\s+/, $_, 3;
+    my %c;
+    foreach my $f (qw(site fqdn opts)) {
+       my $v= shift @v;
+       $v='' unless defined $v;
+       $c{$f}= $v;
+    }
+    $c{'fqdn'}= $c{'site'} if $c{'fqdn'} eq '=';
+    $c{'duct'}= "$c{opts} $c{site} $c{fqdn}";
+    $c{'!'}= '!';
+    $_= $pattern;
+    s/\!(\w+|\!)/ 
+        my $v= $c{$1};
+        die "$self: unknown substitution $1\n" unless defined $v;
+        $v;
+    /ge;
+    my $r= system $_;
+    die "$self: run command: $!\n" if $r<0;
+    warn "$self: $c{site}: wait status $r: $_\n" if $r>0;
+    $r |= 128 if $r>0 && $r<128;
+    $r>>=8 if $r>=256;
+    $maxexit=$r if $r>$maxexit;
+}
+die "$self: $table: read: $!\n" if T->error;
+close T or die "$self: table: close: $!\n";
+
+exit $maxexit;