d6bfca668df06fadd91121db2fd5222077aaeec7
[scpubgit/System-Introspector.git] / lib / System / Introspector / Sudoers.pm
1 package System::Introspector::Sudoers;
2 use Moo;
3
4 has sudoers_file => (
5     is      => 'ro',
6     default => sub { '/etc/sudoers' },
7 );
8
9 has hostname => (
10     is      => 'ro',
11     default => sub { scalar `hostname` },
12 );
13
14 sub gather {
15     my ($self) = @_;
16     my %file = $self->_gather_files($self->sudoers_file);
17     return \%file;
18 }
19
20 sub _gather_files {
21     my ($self, $file) = @_;
22     open my $fh, '<', $file
23         or return $file => { error => "Unable to read: $!" };
24     my @lines = <$fh>;
25     my %file = ($file => { body => join '', @lines });
26     for my $line (@lines) {
27         chomp $line;
28         if ($line =~ m{^#include\s+(.+)$}) {
29             my $inc_file = $self->_insert_hostname($1);
30             %file = (%file, $self->_gather_files($inc_file));
31         }
32         elsif ($line =~ m{^#includedir\s+(.+)$}) {
33             my $inc_dir = $self->_insert_hostname($1);
34             %file = (%file, $self->_gather_from_dir($inc_dir));
35         }
36     }
37     return %file;
38 }
39
40 sub _gather_from_dir {
41     my ($self, $dir) = @_;
42     opendir(my $dh, $dir);
43     return $dir => { error => "Unable to read dir $dir: $!" }
44         unless $dh;
45     my %file;
46     while (my $file = readdir $dh) {
47         next if $file =~ m{\.} or $file =~ m{~$};
48         %file = (%file, $self->_gather_files("$dir/$file"));
49     }
50     return %file;
51 }
52
53 sub _insert_hostname {
54     my ($self, $value) = @_;
55     my $hostname = $self->hostname;
56     $value =~ s{\%h}{$hostname}g;
57     return $value;
58 }
59
60 1;