File Coverage

blib/lib/Proc/Find.pm
Criterion Covered Total %
statement 88 106 83.0
branch 56 80 70.0
condition 16 26 61.5
subroutine 10 13 76.9
pod 4 4 100.0
total 174 229 75.9


line stmt bran cond sub pod time code
1             package Proc::Find;
2              
3             our $DATE = '2015-01-03'; # DATE
4             our $VERSION = '0.04'; # VERSION
5              
6 1     1   719 use 5.010001;
  1         4  
  1         48  
7 1     1   6 use strict;
  1         2  
  1         39  
8 1     1   5 use warnings;
  1         2  
  1         37  
9              
10 1     1   6 use List::Util qw(first);
  1         2  
  1         1605  
11              
12             require Exporter;
13             our @ISA = qw(Exporter);
14             our @EXPORT_OK = qw(
15             find_proc
16             find_any_proc
17             find_all_proc
18             proc_exists
19             );
20              
21             our $CACHE = 0;
22              
23             my $_table_res;
24             sub _table {
25 0     0   0 state $pt = do {
26 0         0 require Proc::ProcessTable;
27 0         0 Proc::ProcessTable->new;
28             };
29 0 0 0     0 if (!$CACHE || !$_table_res) {
30 0         0 $_table_res = $pt->table;
31             }
32 0         0 $_table_res;
33             }
34              
35             sub find_proc {
36 30     30 1 725 my %args = @_;
37              
38 30         63 my @unknown_args = grep {!/\A(
  63         251  
39             pid|name|cmndline|exec|
40             user|uid|euser|euid|
41             table|detail|
42             result_max
43             )\z/x} keys %args;
44 30 50       71 die "Unknown arguments to find_proc(): ".join(", ", @unknown_args)
45             if @unknown_args;
46              
47 30   33     66 my $table = $args{table} // _table();
48              
49 30         28 my ($arg_uid, $arg_euid);
50              
51 0         0 my @res;
52 30         51 for my $p (@$table) {
53             # create extra fields
54 118         181 $p->{name} = $p->{cmndline};
55 118         294 $p->{name} =~ s/\s.*//;
56 118         202 $p->{name} =~ s!.+/!!;
57              
58 118         99 my $cond = 0;
59             COND:
60             {
61 118 100       93 if (defined $args{pid}) {
  118         191  
62 8 100       19 last COND unless $p->{pid} == $args{pid};
63             }
64 111 100       279 if (defined $args{name}) {
65 12 100       22 if (ref($args{name}) eq 'Regexp') {
66 4 100       39 last COND unless $p->{name} =~ $args{name};
67             } else {
68 8 100       18 last COND unless $p->{name} eq $args{name};
69             }
70             }
71 101 100       145 if (defined $args{cmndline}) {
72 12 100       18 if (ref($args{cmndline}) eq 'Regexp') {
73 4 100       14 last COND unless $p->{cmndline} =~ $args{cmndline};
74             } else {
75 8 100       21 last COND unless $p->{cmndline} eq $args{cmndline};
76             }
77             }
78 91 100       149 if (defined $args{exec}) {
79 28   100     82 my $exec = $p->{exec} // '';
80 28 100       65 unless ($args{exec} =~ m!/!) {
81 20         63 $exec =~ s!.+/!!;
82             }
83 28 100       67 last COND unless $exec eq $args{exec};
84             }
85 68 100 100     214 if (defined($args{user}) || defined($args{uid})) {
86 22   66     45 my $val = $args{user} // $args{uid};
87 22         17 my $uid;
88 22 50       58 if ($val =~ /\A\d+\z/) {
89 22         22 $uid = $val;
90             } else {
91 0 0       0 if (!defined($arg_uid)) {
92 0         0 my @pw = getpwnam($val);
93 0 0       0 $arg_uid = @pw ? $pw[2] : -1;
94             }
95 0         0 $uid = $arg_uid;
96             }
97 22 100       571 last COND unless $p->{uid} == $uid;
98             }
99 53 100 100     162 if (defined($args{euser}) || defined($args{euid})) {
100 28   100     68 my $val = $args{euser} // $args{euid};
101 28         24 my $euid;
102 28 50       81 if ($val =~ /\A\d+\z/) {
103 28         25 $euid = $val;
104             } else {
105 0 0       0 if (!defined($arg_euid)) {
106 0         0 my @pw = getpwnam($val);
107 0 0       0 $arg_euid = @pw ? $pw[2] : -1;
108             }
109 0         0 $euid = $arg_euid;
110             }
111 28 100       68 last COND unless $p->{euid} == $euid;
112             }
113              
114 36         30 $cond = 1;
115             }
116              
117 118 50       173 $cond = !$cond if $args{inverse};
118 118 100       210 next unless $cond;
119              
120 36 100       48 if ($args{detail}) {
121 4         49 push @res, { %$p }; # unbless
122             } else {
123 32         50 push @res, $p->{pid};
124             }
125              
126 36 100       80 if (defined $args{result_max}) {
127 1 50       4 last if @res >= $args{result_max};
128             }
129             }
130              
131 30         175 \@res;
132             }
133              
134             sub proc_exists {
135 2 100   2 1 2452 @{ find_proc(@_, result_max=>1) } > 0 ? 1:0;
  2         5  
136             }
137              
138             sub find_any_proc {
139 1 50   1 1 1951 return [] unless @_;
140              
141 1         4 my $detail = $_[0]->{detail};
142 1   33     4 my $table = $_[0]->{table} // _table();
143              
144 1         1 my @allres;
145 1         3 for my $crit (@_) {
146 2         8 my $res = find_proc(%$crit, table=>$table, detail=>$detail);
147             ITEM:
148 2         7 for my $item (@$res) {
149             # skip duplicate process
150 2 50       6 if ($detail) {
151 0 0   0   0 next ITEM if first {$_->{pid} == $res->{pid}} @allres;
  0         0  
152             } else {
153 2 50   1   16 next ITEM if first {$_ == $res} @allres;
  1         4  
154             }
155 2         14 push @allres, @$res;
156             }
157             }
158              
159 1         8 \@allres;
160             }
161              
162             sub find_all_proc {
163 2 50   2 1 1774 return [] unless @_;
164              
165 2         5 my $detail = $_[0]->{detail};
166 2   33     7 my $table = $_[0]->{table} // _table();
167              
168 2         3 my @allres;
169             CRIT:
170 2         7 for my $crit (@_) {
171 4         20 my $res = find_proc(%$crit, table=>$table);
172 4 100       12 if (!@allres) {
173 2         4 push @allres, @$res;
174 2         7 next CRIT;
175             }
176 4         6 @allres = grep {
177 2         5 my $p = $_;
178 0     0   0 $detail ?
179 4     4   21 ((first {$p->{pid} == $_->{pid}} @$res) ? 1:0) :
180 4 0       31 ((first {$p == $_} @$res) ? 1:0)
    100          
    50          
181             } @allres;
182             }
183              
184 2         16 \@allres;
185             }
186              
187             1;
188             # ABSTRACT: Find processes by name, PID, or some other attributes
189              
190             __END__