File Coverage

blib/lib/ShellScript/Env.pm
Criterion Covered Total %
statement 122 149 81.8
branch 28 36 77.7
condition 11 17 64.7
subroutine 11 12 91.6
pod 0 10 0.0
total 172 224 76.7


line stmt bran cond sub pod time code
1             package ShellScript::Env;
2              
3 2     2   3946 use strict;
  2         4  
  2         75  
4              
5 2     2   11 use File::Find;
  2         5  
  2         3670  
6              
7             sub new {
8 2     2 0 46 my $this = shift;
9 2   33     15 my $class = ref($this) || $this;
10 2         5 my $self = {};
11 2         6 bless $self, $class;
12              
13 2         13 $self->{'prefix'} = shift;
14 2 50       8 if (!defined $self->{'prefix'}) {
15 0         0 warn ref($self) . ' constructed with no argument, using `.\' as prefix';
16 0         0 $self->{'prefix'} = '.';
17             }
18              
19 2         8 %{$self->{'dir_search'}} =
  2         16  
20             (
21             'LD_LIBRARY_PATH' => ['lib'],
22             'PATH' => ['bin'],
23             'MANPATH' => ['man'],
24             'INFOPATH' => ['info'],
25             );
26              
27 2         5 push @{$self->{'skip_dirs'}}, 'src';
  2         5  
28              
29 2         8 return $self;
30             }
31              
32            
33             #######################
34             # Functions to be considered public
35              
36             # Functions that searches the prefix directory for common path names.
37             sub automatic {
38 2     2 0 26 my $self = shift;
39              
40 2         2 foreach my $env (keys %{$self->{'dir_search'}}) {
  2         10  
41 8         9 my @found = $self->dir_find(@{$self->{'dir_search'}->{$env}});
  8         26  
42 8 100       24 if (scalar(@found) > 0) {
43 3         16 $self->set_path($env, @found, "\$$env");
44             }
45             }
46 2         6 return $self;
47             }
48              
49              
50             # Just sets a list, no processing or notten.
51             sub set {
52 6     6 0 12 my $self = shift;
53 6         8 my $env = shift;
54              
55 6         9 @{$self->{'env'}->{$env}} = @_;
  6         22  
56 6         14 $self->{'utok'}->{$env} = 0;
57 6         7 push @{$self->{'order'}}, $env;
  6         11  
58            
59 6         11 return $self;
60             }
61              
62             # Make a list and check it twice. Well, appends $self->{'prefix'} if
63             # needed and check if you want utok.
64             sub set_path {
65 4     4 0 8 my $self = shift;
66 4         6 my $env = shift;
67 4         8 my @dirs = @_;
68              
69 4         8 for (@dirs) {
70 9         20 my $prefix = quotemeta($self->{'prefix'});
71 9 100 100     82 if (($_ !~ m/^$prefix/) && ($_ =~ m:^[^\$\/]:)) {
72 1         7 s:^:$self->{'prefix'}/:;
73             }
74             }
75 4         17 $self->set($env, @dirs);
76 4   50     20 $self->{'utok'}->{$env} = ($ShellScript::Env::utok || 0);
77              
78 4         15 return $self;
79             }
80              
81             # deletes a variable.
82             sub unset {
83 2     2 0 4 my $self = shift;
84 2         4 my $env = shift;
85              
86             # Remove one element from a list. Isn't there a cool way to do this
87             # with map?
88 2         3 my @rebuild;
89 2         2 for (@{$self->{'order'}}) {
  2         14  
90 3 100       9 if ($_ ne $env) {
91 1         3 push @rebuild, $_;
92             }
93             }
94 2         4 @{$self->{'order'}} = @rebuild;
  2         6  
95              
96 2         6 delete $self->{'env'}->{$env};
97 2         3 delete $self->{'utok'}->{$env};
98              
99 2         5 return $self;
100             }
101              
102             # Returns 0 if there are no errors.
103             sub save {
104 0     0 0 0 my $self = shift;
105              
106 0         0 my $error = 0;
107              
108 0         0 my $csh_file = "$self->{prefix}.csh";
109 0 0       0 if (open(CSH, ">$csh_file")) {
110 0         0 print "Writing $csh_file\n";
111 0         0 print CSH $self->csh();
112 0         0 close(CSH);
113             } else {
114 0         0 ++$error;
115 0         0 warn "Can't write $csh_file: $!";
116             }
117              
118 0         0 my $sh_file = "$self->{prefix}sh";
119 0 0       0 if (open(SH, ">$sh_file")) {
120 0         0 print "Writing $sh_file.\n";
121 0         0 print SH $self->sh();
122 0         0 close(SH);
123             } else {
124 0         0 ++$error;
125 0         0 warn "Can't write $sh_file: $!";
126             }
127              
128 0         0 return $error;
129             }
130            
131              
132            
133             ##################
134             # functions to generate shell scripts, these are considered public
135             # too. Are there other common shells that arn't compatible with C or
136             # Bourne Shell?
137              
138             # output Bourne Shell.
139             sub sh {
140 5     5 0 15 my $self = shift;
141              
142 5         10 my $output = '';
143 5         6 my $export = 'export ';
144              
145 5         8 for (@{$self->{'order'}}) {
  5         11  
146 11         41 $export .= "$_ ";
147              
148 11 100       24 if ($self->{'utok'}->{$_}) {
149 1         2 $output .= "$_=`utok ";
150             } else {
151 10         17 $output .= "$_=";
152             }
153              
154              
155 11         11 for (@{$self->{'env'}->{$_}}) {
  11         20  
156 17         30 $output .= "$_:";
157             }
158            
159 11 100       25 if ($self->{'utok'}->{$_}) {
160 1         5 $output =~ s/:$/\`\n/;
161             } else {
162 10         40 $output =~ s/:$/\n/;
163             }
164              
165             }
166              
167 5 50       15 if ($export ne 'export ') {
168 5         8 $output .= $export;
169             }
170 5         13 $output =~ s/\ $/\n/;
171              
172 5         24 return $output;
173             }
174              
175             # output C Shell.
176             sub csh {
177 3     3 0 6 my $self = shift;
178              
179 3         3 my $output = '';
180 3         4 for (@{$self->{'order'}}) {
  3         8  
181              
182 8         10 my $delimiter = ':';
183             # I hate how C Shell set every variable one way, and PATH another.
184             # It bugs me to no end.
185 8 100       15 if ($_ eq 'PATH') {
186 2         2 $delimiter = ' ';
187 2         5 $output .= "set path = (";
188             } else {
189 6         11 $output .= "setenv $_ ";
190             }
191              
192 8 100       22 if ($self->{'utok'}->{$_}) {
193 1 50       5 if ($delimiter ne ':') {
194 1         3 $output .= "`utok -s '$delimiter' ";
195             } else {
196 0         0 $output .= '`utok ';
197             }
198             }
199              
200 8         8 my $item;
201 8         14 foreach $item (@{$self->{'env'}->{$_}}) {
  8         20  
202 10 100 100     32 if (($_ eq 'PATH') && ($item eq '$PATH')) {
203 2         6 $output .= "\$path$delimiter";
204             } else {
205 8         21 $output .= "$item$delimiter";
206             }
207             }
208              
209 8         12 $delimiter = quotemeta($delimiter);
210 8 100       32 if ($self->{'utok'}->{$_}) {
211 1         29 $output =~ s/$delimiter$/\`\n/;
212             } else {
213 7         70 $output =~ s/$delimiter$/\n/;
214             }
215              
216 8 100       25 if ($_ eq 'PATH') {
217 2         17 $output =~ s/\n$/\)\n/;
218             }
219             }
220              
221 3         15 return $output;
222             }
223              
224            
225             #####################
226             # Private functions.
227              
228             # I really wish File::Find's find returned an array. I also wish it
229             # worked while tainted. oh well.
230             sub dir_find {
231 9     9 0 20 my $self = shift;
232              
233 9         21 @ShellScript::Env::find = @_;
234 9         13 undef @ShellScript::Env::found;
235 9         7 @ShellScript::Env::skip = @{$self->{'skip_dirs'}};
  9         24  
236              
237 9         10 my @output;
238 9 50       107 if (-l $self->{'prefix'}) {
239              
240              
241 0         0 my $newdir = $self->{'prefix'};
242 0         0 $newdir =~ s<[^/]*$><>;
243 0         0 chdir($newdir);
244              
245 0         0 my $prefix = readlink($self->{'prefix'});
246 0         0 find(\&wanted, $prefix);
247 0         0 $prefix = quotemeta($prefix);
248 0   0     0 @output = map(s/^$prefix/$self->{'prefix'}/g && $_,
249             @ShellScript::Env::found);
250              
251             } else {
252 9         500 find(\&wanted, $self->{'prefix'});
253 9         25 @output = @ShellScript::Env::found;
254             }
255              
256 9         12 undef @ShellScript::Env::skip;
257 9         12 undef @ShellScript::Env::found;
258 9         8 undef $ShellScript::Env::find;
259              
260 9         25 return sort @output;
261             }
262              
263             # Only used for call to find.
264             sub wanted {
265 99     99 0 153 foreach my $find (@ShellScript::Env::find) {
266 99         111 $find = quotemeta($find);
267 99 100 100     603 if (m/^$find$/ && -d $_) {
268 8         15 for (@ShellScript::Env::skip) {
269 11         18 my $skip = quotemeta($_);
270 11 100       103 if ($File::Find::name =~ m) {
271 2         96 return 0;
272             }
273             }
274 6         9 push @ShellScript::Env::found, $File::Find::name;
275 6         301 return 1;
276             }
277             }
278 91         2955 return 0;
279             }
280              
281              
282            
283             ###################
284             # bye, bye.
285             return 1;
286