chiark / gitweb /
ipif: "include" looks for the file in the directory where "include" appears
[userv-utils.git] / ipif / service-wrap
index 2916750b32b596606a2af4793f795c403946d3f2..8dca1c31bb1a7bcf455e832ed6399e340812d4e5 100755 (executable)
 #
 # Usage:
 #
-#   .../ipif1 <v1config> <real-service-program> -- <service-args>...
+#   .../ipif1 <v1config> <real-service-program> <v0config> -- <service-args>...
 #
-# Config file is a series of lines.
+# Config file is a series of lines, or a directory.  If a directory,
+# all files with names matching ^[-A-Za-z0-9_]+$ are processed.
 #
 #   permit <keyword>....
 #
 #              if a permit has no ifname at all, it is as if
 #              `ifname userv%d' was specified
 #
-#   include <other-config-file>
+#   include <other-config-file-or-directory>
 #
-#   v0config <v0configfile>
+# <v0config>
 #
-#     If none of the `permit' lines match, will read <v0configfile>
-#     in old format.  Must come after all `permit' lines.
+#     If none of the `permit' lines match, will process <v0config> in
+#     old format.  See service.c head comment.  <v0config> may be
+#     `' or `#' or `/dev/null' to process new-style config only.
 #
 #   <config> --
 
@@ -60,6 +62,7 @@ use strict;
 use POSIX;
 use Carp;
 use NetAddr::IP::Lite qw(:nofqdn :lower);
+use File::Basename;
 
 our $default_ifname = 'userv%d';
 
@@ -78,8 +81,8 @@ sub oneaddr ($) {
     $$ar = $x;
 }
 
-@ARGV == 5 or badusage "wrong number of arguments";
-our ($v1config, $realservice, $sep, $addrsarg, $rnets) = @ARGV;
+@ARGV == 6 or badusage "wrong number of arguments";
+our ($v1config, $realservice, $v0config, $sep, $addrsarg, $rnets) = @ARGV;
 
 $sep eq '--' or badusage "separator should be \`--'";
 my ($local_addr, $peer_addr, $mtu, $protocol, $ifname) =
@@ -103,13 +106,12 @@ our @rnets = ($rnets eq '-' ? () : split /\,/, $rnets);
 sub execreal ($) {
     my ($use_v0config) = @_;
     exec $realservice, $use_v0config, '--',
-       "$local_addr,$peer_addr,$mtu,$protocol",
+       (join ',', $local_addr->addr, $peer_addr->addr,
+                  $mtu, $protocol, $ifname),
        @rnets ? (join ",", map { "$_" } @rnets) : "-"
        or die "exec $realservice: $!\n";
 }
 
-our $v0config;
-
 our $cfgpath;
 
 sub badcfg ($) {
@@ -175,8 +177,21 @@ sub maybe_allow_addrs ($$) {
     }
 }
 
+sub readconfig ($);
 sub readconfig ($) {
     local ($cfgpath) = @_;
+
+    my $dirfh;
+    if (opendir $dirfh, $cfgpath) {
+       while ($!=0, my $ent = readdir $dirfh) {
+           next if $ent =~ m/[^-A-Za-z0-9_]/;
+           readconfig "$cfgpath/$ent";
+       }
+       die "$0: $cfgpath: $!\n" if $!;
+       return;
+    }
+    die "$0: $cfgpath: $!\n" unless $!==ENOENT || $!==ENOTDIR;
+
     my $cfgfh = new IO::File $cfgpath, "<";
     if (!$cfgfh) {
        die "$0: $cfgpath: $!\n" unless $!==ENOENT;
@@ -188,7 +203,6 @@ sub readconfig ($) {
        next if m/^\#/;
        next unless m/\S/;
        if (s{^permit\s+}{}) {
-           badcfg "v0config before permit" if defined $v0config;
            %need_allow = ();
            need_allow_singleton 'Caller', allowent 'caller';
            need_allow_singleton 'Local',
@@ -251,24 +265,33 @@ sub readconfig ($) {
                print "config $cfgpath:$.: mismatch: $_\n"
                    foreach @wrong;
            }
-       } elsif (m{^v0config\s+(\S+)$}) {
-           badcfg "repeated v0config" if defined $v0config;
-           $v0config = $1;
        } elsif (m{^include\s+(\S+)$}) {
-           readconfig $1;
+           my $include = $1;
+           $include =~ s{^(?!/)}{ dirname($cfgpath)."/" }e;
+           readconfig $include;
        } else {
            badcfg "unknown config directive or bad syntax";
        }
     }
     $cfgfh->error and die $!;
     close $cfgfh;
+}
 
-    if (defined $v0config) {
-       $v0config =~ s{^}{./} unless $v0config =~ m{^/};
-       print "trying v0 config $v0config...\n" if $protocol eq 'debug';
-       execreal $v0config;
+sub try_v0config() {
+    return unless $v0config;
+    return unless $v0config =~ m{^[^#]};
+    return if $v0config eq '/dev/null';
+    if ($v0config =~ m{^/}) {
+       if (!stat $v0config) {
+           die "v0 config $v0config: $!\n" unless $!==ENOENT;
+           return;
+       }
     }
-    die "permission denied\n";
+    print "trying v0 config $v0config...\n" if $protocol eq 'debug';
+    execreal $v0config;
 }
 
 readconfig $v1config;
+try_v0config();
+
+die "permission denied\n";