File Coverage

bin/app_dispatch
Criterion Covered Total %
statement 45 75 60.0
branch 16 38 42.1
condition 2 10 20.0
subroutine 8 9 88.8
pod 1 6 16.6
total 72 138 52.1


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2 1     1   637 use strict;
  1         2  
  1         33  
3 1     1   5 use warnings;
  1         2  
  1         1122  
4              
5             my @paths = (
6             "/etc/dispatch.conf",
7             "/etc/dispatch",
8             );
9              
10             push @paths => "$ENV{HOME}/.dispatch.conf"
11             unless $ENV{SUDO_USER} || $ENV{USER} eq 'root';
12              
13             App::Dispatch->new(@paths)->dispatch(@ARGV);
14              
15 1     1   37 BEGIN {
16              
17             package App::Dispatch;
18              
19 6     6 0 32 sub programs { shift->{programs} }
20 6     6 0 22 sub config { shift->{config} }
21              
22             sub new {
23 2     2 0 986 my $class = shift;
24              
25 2         8 my $self = bless {
26             config => {},
27             programs => {},
28             } => $class;
29              
30 2         9 $self->read_config($_) for @_;
31              
32 2         8 return $self;
33             }
34              
35             sub read_config {
36 6     6 0 9 my $self = shift;
37 6         7 my ($file) = @_;
38 6 100       83 unless ( -e $file ) {
39 4         13 $self->config->{$file} = "No such file or directory: '$file'.";
40 4         11 return;
41             }
42 2         4 $self->config->{$file} = 1;
43              
44 2 100       23 if ( -d $file ) {
45 1 50       38 opendir( my $dir, $file ) || die "Failed to open '$file': $!\n";
46 1         20 $self->read_config("$file/$_") for sort grep { $_ !~ m/^\./ } readdir($dir);
  3         17  
47 1         2 close($dir);
48 1         15 return;
49             }
50              
51 1 50       30 open( my $fh, '<', $file ) || die "Failed to open '$file': $!\n";
52              
53 1         2 my $program;
54 1         2 my $ln = 0;
55 1         21 while ( my $line = <$fh> ) {
56 9         8 $ln++;
57 9         10 chomp($line);
58 9 100       26 next unless $line;
59 7 100       21 next if $line =~ m/^#/;
60              
61 5 100       14 if ( $line =~ m/^\s*\[([a-zA-Z0-9_]+)\]\s*$/i ) {
62 1         2 $program = $1;
63 1   50     3 $self->programs->{$program} ||= {};
64 1         4 next;
65             }
66              
67 4 50       7 if ( !$program ) {
68 0         0 die "Error in '$file', line $ln: '$line'.\nItem is not under a program specification.\n";
69             }
70              
71 4 50       16 if ( $line =~ m/^\s*([a-zA-Z0-9_]+)\s*=\s*(\S+)\s*$/ ) {
72 4         7 $self->programs->{$program}->{$1} = $2;
73 4 50 33     18 next unless $1 eq 'SYSTEM' && $file ne '/etc/dispatch.conf';
74 0         0 die "SYSTEM alias can only be specified in /etc/dispatch.conf.\n";
75             }
76              
77 0         0 die "'$file' line $ln not valid: '$line'\n";
78             }
79              
80 1         12 close($fh);
81             }
82              
83             sub dispatch {
84 1     1 1 2 my $self = shift;
85 1         2 my ( $program, @argv ) = @_;
86              
87 1 50       30 die "No program specified\n" unless $program;
88              
89 0 0         return $self->debug if $program eq 'DEBUG';
90              
91 0           my @cascade;
92              
93 0   0       unshift @cascade => shift @argv while @argv && $argv[0] ne '--';
94 0           shift @argv;
95              
96 0 0         @cascade = ( 'DEFAULT', 'SYSTEM' ) unless @cascade;
97              
98 0   0       my $conf = $self->programs->{$program} || {};
99              
100 0           my $run;
101 0           for my $item (@cascade) {
102 0 0         if ( $item eq 'ENV' ) {
    0          
    0          
103 0           $run = $program;
104             }
105             elsif ( my $alias = $conf->{$item} ) {
106 0 0         next unless -x $alias;
107 0           $run = $alias;
108             }
109             elsif ( -x $item ) {
110 0           $run = $item;
111             }
112             }
113 0 0         exec( $run, @argv ) if $run;
114              
115 0           print STDERR "Could not find valid '$program' to run.\n";
116 0           print STDERR "Searched: " . join( ', ', @cascade ) . "\n";
117 0           print STDERR "'$program' config: ";
118 0 0         if ( keys %$conf ) {
119 0           print "\n";
120 0           for my $alias ( keys %$conf ) {
121 0           print STDERR " $alias = $conf->{$alias}\n";
122             }
123             }
124             else {
125 0           print STDERR "No config for '$program'\n";
126             }
127              
128 0           print STDERR "\n";
129 0           exit 1;
130             }
131              
132             sub debug {
133 0     0 0   my $self = shift;
134 0           require Data::Dumper;
135 0           print Data::Dumper::Dumper($self);
136             }
137             }