more explicit ipc to work around child-exec issues
[scpubgit/System-Introspector.git] / lib / System / Introspector / Util.pm
CommitLineData
f79a227c 1use strictures 1;
2
3package System::Introspector::Util;
4use Exporter 'import';
db5ba31f 5use IPC::Run qw( run );
9c3e454c 6use IPC::Open2;
7use File::Spec;
8use Scalar::Util qw( blessed );
f79a227c 9
10our @EXPORT_OK = qw(
11 handle_from_command
db5ba31f 12 handle_from_file
db5ba31f 13 output_from_command
14 output_from_file
91c60940 15 lines_from_command
16 files_from_dir
f79a227c 17 transform_exceptions
18);
19
c23ab973 20do {
65e569ee 21 package System::Introspector::_Exception;
c23ab973 22 use Moo;
23 has message => (is => 'ro');
24};
25
65e569ee 26sub fail { die System::Introspector::_Exception->new(message => shift) }
27sub is_report_exception { ref(shift) eq 'System::Introspector::_Exception' }
c23ab973 28
db5ba31f 29sub files_from_dir {
30 my ($dir) = @_;
31 my $dh;
32 opendir $dh, $dir
c23ab973 33 or fail "Unable to read directory $dir: $!";
db5ba31f 34 my @files;
35 while (defined( my $item = readdir $dh )) {
36 next if -d "$dir/$item";
37 push @files, $item;
38 }
39 return @files;
40}
41
f79a227c 42sub transform_exceptions (&) {
43 my ($code) = @_;
f79a227c 44 my $result = eval { $code->() };
c23ab973 45 if (my $error = $@) {
46 return { error => $error->message }
47 if is_report_exception $error;
48 die $@;
49 }
f79a227c 50 return $result;
51}
52
db5ba31f 53sub output_from_command {
54 my ($command, $in) = @_;
55 $in = ''
56 unless defined $in;
57 my ($out, $err) = ('', '');
58 my $ok = run($command, \$in, \$out, \$err);
59 return $out, $err, $ok
60 if wantarray;
61 $command = join ' ', @$command
62 if ref $command;
c23ab973 63 fail "Error running command ($command): $err"
db5ba31f 64 unless $ok;
65 return $out;
66}
67
91c60940 68sub lines_from_command {
69 my ($command) = @_;
70 my $output = output_from_command $command;
71 chomp $output;
72 return split m{\n}, $output;
73}
74
f79a227c 75sub handle_from_command {
76 my ($command) = @_;
9c3e454c 77 my $pipe;
78 local $@;
79 my $ok = eval {
80 my $out;
81 my $child_pid = open2($out, File::Spec->devnull, $command);
82 my @lines = <$out>;
83 waitpid $child_pid, 0;
84 my $content = join '', @lines;
85 my $status = $? >> 8;
86 open $pipe, '<', \$content;
87 1;
88 };
89 unless ($ok) {
90 my $err = $@;
91 die $err
92 if blessed($err) and $err->isa('System::Introspector::_Exception');
93 fail "Error from command '$command': $err";
94 }
f79a227c 95 return $pipe;
96}
97
db5ba31f 98sub handle_from_file {
99 my ($file) = @_;
100 open my $fh, '<', $file
c23ab973 101 or fail "Unable to read $file: $!";
db5ba31f 102 return $fh;
103}
104
105sub output_from_file {
106 my ($file) = @_;
107 my $fh = handle_from_file $file;
108 return <$fh>
109 if wantarray;
110 return do { local $/; <$fh> };
111}
112
f79a227c 1131;