File Coverage

blib/lib/Env.pm
Criterion Covered Total %
statement 83 102 81.3
branch 11 16 68.7
condition 0 3 0.0
subroutine 20 26 76.9
pod n/a
total 114 147 77.5


line stmt bran cond sub pod time code
1             package Env;
2              
3             our $VERSION = '1.04';
4              
5             =head1 NAME
6              
7             Env - perl module that imports environment variables as scalars or arrays
8              
9             =head1 SYNOPSIS
10              
11             use Env;
12             use Env qw(PATH HOME TERM);
13             use Env qw($SHELL @LD_LIBRARY_PATH);
14              
15             =head1 DESCRIPTION
16              
17             Perl maintains environment variables in a special hash named C<%ENV>. For
18             when this access method is inconvenient, the Perl module C allows
19             environment variables to be treated as scalar or array variables.
20              
21             The C function ties environment variables with suitable
22             names to global Perl variables with the same names. By default it
23             ties all existing environment variables (C) to scalars. If
24             the C function receives arguments, it takes them to be a list of
25             variables to tie; it's okay if they don't yet exist. The scalar type
26             prefix '$' is inferred for any element of this list not prefixed by '$'
27             or '@'. Arrays are implemented in terms of C and C, using
28             C<$Config::Config{path_sep}> as the delimiter.
29              
30             After an environment variable is tied, merely use it like a normal variable.
31             You may access its value
32              
33             @path = split(/:/, $PATH);
34             print join("\n", @LD_LIBRARY_PATH), "\n";
35              
36             or modify it
37              
38             $PATH .= ":.";
39             push @LD_LIBRARY_PATH, $dir;
40              
41             however you'd like. Bear in mind, however, that each access to a tied array
42             variable requires splitting the environment variable's string anew.
43              
44             The code:
45              
46             use Env qw(@PATH);
47             push @PATH, '.';
48              
49             is equivalent to:
50              
51             use Env qw(PATH);
52             $PATH .= ":.";
53              
54             except that if C<$ENV{PATH}> started out empty, the second approach leaves
55             it with the (odd) value "C<:.>", but the first approach leaves it with "C<.>".
56              
57             To remove a tied environment variable from
58             the environment, assign it the undefined value
59              
60             undef $PATH;
61             undef @LD_LIBRARY_PATH;
62              
63             =head1 LIMITATIONS
64              
65             On VMS systems, arrays tied to environment variables are read-only. Attempting
66             to change anything will cause a warning.
67              
68             =head1 AUTHOR
69              
70             Chip Salzenberg EFE
71             and
72             Gregor N. Purdy EFE
73              
74             =cut
75              
76             sub import {
77 2     2   25 my ($callpack) = caller(0);
78 2         8 my $pack = shift;
79 2 50       25 my @vars = grep /^[\$\@]?[A-Za-z_]\w*$/, (@_ ? @_ : keys(%ENV));
80 2 50       11 return unless @vars;
81              
82 2 100       6 @vars = map { m/^[\$\@]/ ? $_ : '$'.$_ } @vars;
  3         19  
83              
84 2     2   12 eval "package $callpack; use vars qw(" . join(' ', @vars) . ")";
  2         4  
  2         70  
  2         185  
85 2 50       10 die $@ if $@;
86 2         7 foreach (@vars) {
87 3         16 my ($type, $name) = m/^([\$\@])(.*)$/;
88 3 100       21 if ($type eq '$') {
89 2         3 tie ${"${callpack}::$name"}, Env, $name;
  2         11  
90             } else {
91 1 50       6 if ($^O eq 'VMS') {
92 0         0 tie @{"${callpack}::$name"}, Env::Array::VMS, $name;
  0         0  
93             } else {
94 1         1 tie @{"${callpack}::$name"}, Env::Array, $name;
  1         7  
95             }
96             }
97             }
98             }
99              
100             sub TIESCALAR {
101 2     2   2244 bless \($_[1]);
102             }
103              
104             sub FETCH {
105 4     4   648 my ($self) = @_;
106 4         31 $ENV{$$self};
107             }
108              
109             sub STORE {
110 2     2   4 my ($self, $value) = @_;
111 2 50       8 if (defined($value)) {
112 2         17 $ENV{$$self} = $value;
113             } else {
114 0         0 delete $ENV{$$self};
115             }
116             }
117              
118             ######################################################################
119              
120             package Env::Array;
121            
122 2     2   78253 use Config;
  2         5  
  2         93  
123 2     2   2081 use Tie::Array;
  2         2867  
  2         1754  
124              
125             @ISA = qw(Tie::Array);
126              
127             my $sep = $Config::Config{path_sep};
128              
129             sub TIEARRAY {
130 1     1   29 bless \($_[1]);
131             }
132              
133             sub FETCHSIZE {
134 42     42   4152 my ($self) = @_;
135 42         280 return 1 + scalar(() = $ENV{$$self} =~ /\Q$sep\E/g);
136             }
137              
138             sub STORESIZE {
139 1     1   462 my ($self, $size) = @_;
140 1         16 my @temp = split($sep, $ENV{$$self});
141 1         4 $#temp = $size - 1;
142 1         10 $ENV{$$self} = join($sep, @temp);
143             }
144              
145             sub CLEAR {
146 2     2   738 my ($self) = @_;
147 2         39 $ENV{$$self} = '';
148             }
149              
150             sub FETCH {
151 32     32   134 my ($self, $index) = @_;
152 32         175 return (split($sep, $ENV{$$self}))[$index];
153             }
154              
155             sub STORE {
156 9     9   667 my ($self, $index, $value) = @_;
157 9         55 my @temp = split($sep, $ENV{$$self});
158 9         19 $temp[$index] = $value;
159 9         34 $ENV{$$self} = join($sep, @temp);
160 9         35 return $value;
161             }
162              
163             sub EXISTS {
164 2     2   3 my ($self, $index) = @_;
165 2         9 return $index < $self->FETCHSIZE;
166             }
167              
168             sub DELETE {
169 0     0   0 my ($self, $index) = @_;
170 0         0 my @temp = split($sep, $ENV{$$self});
171 0         0 my $value = splice(@temp, $index, 1, ());
172 0         0 $ENV{$$self} = join($sep, @temp);
173 0         0 return $value;
174             }
175              
176             sub PUSH {
177 2     2   948 my $self = shift;
178 2         24 my @temp = split($sep, $ENV{$$self});
179 2         6 push @temp, @_;
180 2         11 $ENV{$$self} = join($sep, @temp);
181 2         7 return scalar(@temp);
182             }
183              
184             sub POP {
185 1     1   491 my ($self) = @_;
186 1         17 my @temp = split($sep, $ENV{$$self});
187 1         3 my $result = pop @temp;
188 1         8 $ENV{$$self} = join($sep, @temp);
189 1         5 return $result;
190             }
191              
192             sub UNSHIFT {
193 1     1   445 my $self = shift;
194 1         18 my @temp = split($sep, $ENV{$$self});
195 1         5 my $result = unshift @temp, @_;
196 1         6 $ENV{$$self} = join($sep, @temp);
197 1         3 return $result;
198             }
199              
200             sub SHIFT {
201 1     1   487 my ($self) = @_;
202 1         18 my @temp = split($sep, $ENV{$$self});
203 1         3 my $result = shift @temp;
204 1         6 $ENV{$$self} = join($sep, @temp);
205 1         5 return $result;
206             }
207              
208             sub SPLICE {
209 2     2   970 my $self = shift;
210 2         43 my $offset = shift;
211 2         5 my $length = shift;
212 2         26 my @temp = split($sep, $ENV{$$self});
213 2 100       9 if (wantarray) {
214 1         3 my @result = splice @temp, $offset, $length, @_;
215 1         7 $ENV{$$self} = join($sep, @temp);
216 1         5 return @result;
217             } else {
218 1         4 my $result = scalar splice @temp, $offset, $length, @_;
219 1         7 $ENV{$$self} = join($sep, @temp);
220 1         6 return $result;
221             }
222             }
223              
224             ######################################################################
225              
226             package Env::Array::VMS;
227 2     2   17 use Tie::Array;
  2         9  
  2         432  
228              
229             @ISA = qw(Tie::Array);
230            
231             sub TIEARRAY {
232 0     0     bless \($_[1]);
233             }
234              
235             sub FETCHSIZE {
236 0     0     my ($self) = @_;
237 0           my $i = 0;
238 0   0       while ($i < 127 and defined $ENV{$$self . ';' . $i}) { $i++; };
  0            
239 0           return $i;
240             }
241              
242             sub FETCH {
243 0     0     my ($self, $index) = @_;
244 0           return $ENV{$$self . ';' . $index};
245             }
246              
247             sub EXISTS {
248 0     0     my ($self, $index) = @_;
249 0           return $index < $self->FETCHSIZE;
250             }
251              
252 0     0     sub DELETE { }
253              
254             1;