File Coverage

blib/lib/Safe/World.pm
Criterion Covered Total %
statement 281 1333 21.0
branch 67 682 9.8
condition 24 351 6.8
subroutine 37 95 38.9
pod 58 69 84.0
total 467 2530 18.4


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: World.pm
3             ## Purpose: Safe::World
4             ## Author: Graciliano M. P.
5             ## Modified by:
6             ## Created: 08/09/2003
7             ## RCS-ID:
8             ## Copyright: (c) 2003 Graciliano M. P.
9             ## Licence: This program is free software; you can redistribute it and/or
10             ## modify it under the same terms as Perl itself
11             #############################################################################
12            
13             package Safe::World ;
14            
15 1     1   9059 use strict qw(vars);
  1         2  
  1         49  
16            
17 1     1   6 use vars qw($VERSION @ISA) ;
  1         2  
  1         78  
18             $VERSION = '0.14' ;
19            
20             require overload ;
21            
22 1     1   6 no warnings ;
  1         6  
  1         56  
23            
24             ########
25             # VARS #
26             ########
27            
28 1     1   5 use vars qw($NOW $EVALX) ;
  1         2  
  1         7415  
29            
30             my ($COMPARTMENT_X , $SAFE_WORLD_SELECTED_STATIC , %WORLDS_LINKS , $IGNORE_EXIT , $SELECT_STDOUT_FIX , $UNIVERSAL_ISA , $TRACK_GLOB_X) ;
31            
32             my $COMPARTMENT_NAME = 'SAFEWORLD' ;
33             my $COMPARTMENT_NAME_CACHE = 'SAFEWORLD_CACHE_' ;
34            
35             my $TRACK_GLOBS_BASE = 'Safe::World::GLOBS::' ;
36            
37             my @DENY_OPS = qw(chroot syscall exit dump fork lock threadsv) ;
38            
39             my @TRACK_VARS_DEF = qw(*_ @INC %INC %ENV) ;
40            
41             my $MAIN_STASH = *{'main::'}{HASH} ;
42            
43             my $BLESS_TABLE = { POOL => Hash::NoRef->new() } ;
44             my $SAFEWORLDS_TABLE = { POOL => Hash::NoRef->new() } ;
45            
46            
47             ########
48             # KEYS #
49             ########
50             ## STDOUT ## stdout ref (GLOB|SCALAR|CODE)
51             ## STDIN ## stdin ref (GLOB)
52             ## STDERR ## stderr ref (GLOB|SCALAR|CODE)
53             ## HEADOUT ## the output of the headers (GLOB|SCALAR|CODE)
54             ## TIESTDOUT ## The tiestdout object
55             ## TIESTDERR ## The tiestderr object
56            
57             ## ## Auto flush (BOOL)
58             ## AUTOHEAD ## If STDOUT start printing the headers, until HEADSPLITTER (like CGI). Def: 1 if HEADOUT
59             ## HEADSPLITTER ## The splitter (REGEXP|CODE) between headers and output. Def: \r\n\r\n (like CGI)
60             ## ONCLOSEHEADERS ## Function to call on close headers block.
61            
62             ## ENV ## Internal %ENV
63            
64             ## ROOT ## root name
65             ## SAFE ## the Safe object
66             ## SHAREDPACK ## what package to share in this WORLD when it's linked with other>> \@
67            
68             ## INSIDE ## bool >> if is running code inside the compartment
69            
70             ## LINKED_PACKS{} ## shared packages
71             ## SHARING{} ## shared vars
72             ## WORLD_SHARED ## if this world is shared and the name of the holder.
73             ## SELECT{} ## Safe::World::select keys.
74            
75             ## NO_SET_SAFEWORLD ## Do not set the variable $SAFEWORLD inside the compartment.
76             ## NO_CLEAN ## If will not clean the pack.
77            
78             ## DESTROIED ## if DESTROY() was alredy called.
79             ## CLEANNED ## if the pack was cleanned.
80             ## EXIT ## exit or die has been called. No more evals!
81            
82             ##########
83             # EVENTS #
84             ##########
85             ## on_closeheaders ## When the headers are closeds.
86             ## on_exit ## When exit() is called.
87             ## on_select ## When the WORLD is selected to evaluate codes inside it.
88             ## on_unselect ## When the WORLD is unselected, just after evaluate the codes.
89            
90             ###############
91             # COMPARTMENT #
92             ###############
93             ## SAFEWORLDx::WORLDSHARE:: ## used to link and unlink a WORLD with other WORLD.
94            
95             ########
96             # EXIT #
97             ########
98            
99             sub EXIT {
100 0 0   0 0 0 return if $IGNORE_EXIT ;
101            
102 0 0 0     0 if ( $NOW && ref($NOW) eq 'Safe::World' ) {
103 0         0 my $exit ;
104 0 0 0     0 if ( $NOW->{ONEXIT} && !$NOW->{EXIT} ) {
105 0         0 my $sub = $NOW->{ONEXIT} ;
106 0         0 $exit = &$sub($NOW , @_) ;
107             }
108 0 0       0 die('#CORE::GLOBAL::exit#') unless $exit eq '0' ;
109             }
110 0         0 else { CORE::exit(@_) ;}
111             }
112            
113             ##########
114             # SELECT #
115             ##########
116            
117             sub SELECT {
118 2 50   2 0 15 if ( @_ > 1 ) {
119 0         0 return CORE::select($_[0],$_[1],$_[2],$_[3]) ;
120             }
121            
122 2         14 my ( $io ) = @_ ;
123            
124             ##open (LOG,">>F:/projects/HPL7/DEV/apps/safeworld-$$.tmp") ;
125            
126 2 50       4 my $outside = ($MAIN_STASH == *{"main::"}{HASH}) ? 1 : undef ;
  2         11  
127            
128 2 50       7 my $root = ref $NOW ? $NOW->{ROOT} : undef ;
129            
130 2         3 my ($prev_sel , $io_ref) ;
131 2 100       8 if ( ref($io) eq 'ARRAY') { ($io , $io_ref) = @{$io} ;}
  1         2  
  1         3  
132            
133 2 50 0     25 if ( ref($io) ) { ; }
    100 0        
    50          
    0          
134             elsif ( $io =~ /^(?:main::)*(?:STDOUT|stdout)$/s ) {
135 1 50       4 $io = $outside ? 'main::STDOUT' : "$root\::STDOUT" ;
136 1         3 $prev_sel = $io ;
137             }
138             elsif ( $io =~ /^(?:(?:main|(SAFEWORLD(?:_CACHE_)?\d+))::)+(?:STDOUT|stdout)$/s ) {
139 1   50     5 my $pack = $1 || 'main' ;
140 1         4 $io = "$pack\::STDOUT" ;
141 1         2 $prev_sel = $io ;
142             }
143             elsif ( $io ne '' && $io !~ /::/ && $io !~ /^(?:STDOUT|STDERR|STDIN)$/ ) {
144 0         0 my $caller = caller ;
145 0         0 $io = "$caller\::$io" ;
146             }
147            
148 2 50 66     19 my $sel = $io ne '' ? CORE::select($io_ref||$io) : CORE::select() ;
149             ##my $sel0 = $sel ;
150            
151 2 50       12 if ( $sel =~ /^(?:(?:main|(SAFEWORLD(?:_CACHE_)?\d+))::)*(?:STDOUT|stdout)$/s ) {
152 2   50     19 my $pack = $1 || 'main' ;
153 2         4 $sel = "$pack\::STDOUT" ;
154 2 100 66     18 if ( $sel eq 'main::STDOUT' && $SELECT_STDOUT_FIX ) { $sel = $SELECT_STDOUT_FIX ;}
  1         3  
155             }
156            
157 2 50       7 $SELECT_STDOUT_FIX = $prev_sel if $io ne '' ;
158            
159             ##my @call = caller ;
160             ##print LOG "$outside>> $sel # $io { $sel0 # $_[0] } <<@call>>\n" ;
161             ##close(LOG) ;
162            
163 2         6 return $sel ;
164             }
165            
166             #################
167             # UNIVERSAL_ISA #
168             #################
169            
170             sub UNIVERSAL_ISA {
171 362     362 0 126413 my $ref = shift ;
172 362         340 my $class = shift ;
173            
174 362 50       343 my $outside = ($MAIN_STASH == *{"main::"}{HASH}) ? 1 : undef ;
  362         895  
175 362 50       581 my $root = ref $NOW ? $NOW->{ROOT} : undef ;
176            
177 362 50 33     752 if ( $class eq 'UNIVERSAL' && is_SvBlessed($ref) ) { return 1 ;}
  0         0  
178            
179 362 50       503 if ( !$outside ) {
180 0         0 my $class1 = "$root\::$class" ;
181 0         0 my ($class2) = ( ref($ref) =~ /^(?:(?:main|(SAFEWORLD(?:_CACHE_)?\d+))::)*.*$/s );
182 0 0       0 $class2 = "$class2\::$class" if $class2 ;
183 0   0     0 return &$UNIVERSAL_ISA($ref , $class) || &$UNIVERSAL_ISA($ref , $class1) || ( $class2 ? &$UNIVERSAL_ISA($ref , $class2) : undef ) ;
184             }
185             else {
186 362         13713 return &$UNIVERSAL_ISA($ref , $class) ;
187             }
188             }
189            
190             ##########
191             # CALLER #
192             ##########
193            
194             sub CALLER {
195 1     1 0 13697 my @ret ;
196 1 50       6 if ( @_ ) { @ret = CORE::caller($_[0]+1) ;}
  0         0  
197 1         10 else { @ret = (CORE::caller(1))[0..2] ;}
198            
199 1 50       3 my $outside = ($MAIN_STASH == *{"main::"}{HASH}) ? 1 : undef ;
  1         8  
200            
201 1 50       6 if ( !$outside ) {
202 0 0       0 if ( $ret[0] =~ /^(?:main|(?:SAFEWORLD(?:_CACHE_)?\d+))(::.*|)$/ ) {
203 0         0 $ret[0] = "main$1" ;
204             }
205             }
206            
207 1 50       7 return @ret if wantarray ;
208 0         0 return $ret[0] ;
209             }
210            
211             #########
212             # BLESS #
213             #########
214            
215             sub BLESS {
216 23     23 0 13317 my $ref ;
217 23 100       56 if ( $#_ == 0 ) {
218 1         4 my $class = CORE::caller ;
219 1         3 $ref = bless($_[0],$class) ;
220             }
221 22         63 else { $ref = bless($_[0] , $_[1]) ;}
222            
223 23 100       35 my $outside = ($MAIN_STASH == *{"main::"}{HASH}) ? 1 : undef ;
  23         79  
224            
225 23 0 66     101 if (
      0        
      33        
226             !$outside
227             && ref($ref) !~ /^(?:(?:main|(?:SAFEWORLD(?:_CACHE_)?\d+))::)?Safe::World(?:::(?:Compartment|select).*)?$/
228             && (
229             $] >= 5.007
230             || (
231             #!ref($ref)->can('()')
232             #&&
233             ref($ref) !~ /^(?:(?:main|(?:SAFEWORLD(?:_CACHE_)?\d+))::)?(?:Object::MultiType.*|XML::Smart)$/
234             )
235             )
236             ) {
237 0         0 my $id = ++$BLESS_TABLE->{id} ;
238 0         0 my ($base) = ( *{"main::"}{HASH}{'main::'} =~ /^\W*(?:main::)*(\w+)/ ) ;
  0         0  
239 0         0 $BLESS_TABLE->{POOL}{$id} = $ref ;
240 0         0 $BLESS_TABLE->{$base}{$id} = undef ;
241             ##print STDOUT "BLESS>> [". ref($ref) ."] # $id\n" ;
242             }
243            
244 23         109 return $ref ;
245             }
246            
247             sub _rebless {
248 0     0   0 my ( $pack , $new_pack ) = @_ ;
249             #print STDOUT "REBLESS>>@_\n" ;
250            
251 0         0 foreach my $ids_i ( keys %{$BLESS_TABLE->{$pack}} ) {
  0         0  
252 0         0 my $obj = $BLESS_TABLE->{POOL}{$ids_i} ;
253 0         0 my $ref = ref($obj) ;
254             ##print STDOUT "REBLESS>> $obj # $ref # $ids_i <$pack , $new_pack >\n" ;
255 0 0 0     0 if ( $ref &&
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
256             $ref ne 'SCALAR' &&
257             $ref ne 'ARRAY' &&
258             $ref ne 'HASH' &&
259             $ref ne 'CODE' &&
260             $ref ne 'GLOB' &&
261             $ref ne 'FORMAT' &&
262             $ref ne 'REF' &&
263             $ref ne 'UNKNOW' &&
264             $ref !~ /^(?:main|(?:SAFEWORLD(?:_CACHE_)?\d+)::)?Safe::World(?:[\w:]*)$/
265             ) {
266 0 0 0     0 if ( $ref =~ /^(?:main|(?:SAFEWORLD(?:_CACHE_)?\d+))(?:::(.*)|)$/ ) { $ref = $1 || 'main' ;}
  0         0  
267 0         0 CORE::bless($obj , "$new_pack\::$ref") ;
268             }
269             else {
270 0         0 delete $BLESS_TABLE->{POOL}{$ids_i} ;
271 0         0 delete $BLESS_TABLE->{$pack}{$ids_i} ;
272             }
273             }
274            
275 0         0 return ;
276             }
277            
278             #########
279             # BEGIN #
280             #########
281            
282 1     1   1203 use Opcode ; ## Need to load Opcode before redefine caller!
  1         5513  
  1         153  
283            
284             sub BEGIN {
285 1     1   5 *CORE::GLOBAL::exit = \&EXIT ;
286 1         3 *CORE::GLOBAL::select = \&SELECT ; ## Fix different behavior of STDOUT select() inside Safe compartments on Perl-5.6x and Perl-5.8x.
287 1         2 *CORE::GLOBAL::caller = \&CALLER ;
288 1         3 *CORE::GLOBAL::bless = \&BLESS ;
289 1         2 $UNIVERSAL_ISA = \&UNIVERSAL::isa ;
290 1         25 *UNIVERSAL::isa = \&UNIVERSAL_ISA ;
291             }
292            
293             ############
294             # REQUIRES #
295             ############
296            
297 1     1   1004 use Hash::NoRef ;
  1         1412  
  1         28  
298 1     1   591 use Safe::World::Compartment ;
  1         3  
  1         42  
299 1     1   612 use Safe::World::ScanPack ;
  1         2  
  1         37  
300            
301             require Safe::World::select ; ## To be loaded after declare Safe::World scope.
302 1     1   548 use Safe::World::stdout ;
  1         3  
  1         36  
303 1     1   600 use Safe::World::stdoutsimple ;
  1         3  
  1         26  
304 1     1   506 use Safe::World::stderr ;
  1         3  
  1         30  
305            
306             ##########
307             # SCOPES #
308             ##########
309            
310 1     1   589 use Safe::World::Scope ;
  1         3  
  1         3877  
311            
312             my $SCOPE_Safe_World_stdout = new Safe::World::Scope('Safe::World::stdout',undef,1) ;
313             my $SCOPE_Safe_World_Compartment = new Safe::World::Scope('Safe::World::Compartment',undef,1) ;
314             my $SCOPE_Safe_World_select = new Safe::World::Scope('Safe::World::select',undef,1) ;
315             my $SCOPE_Safe_World_ScanPack = new Safe::World::Scope('Safe::World::ScanPack',undef,1) ;
316            
317             my $Safe_World_stdout_headsplitter_html = \&Safe::World::stdout::headsplitter_html ;
318            
319             *is_SvBlessed = \&Hash::NoRef::is_SvBlessed ;
320            
321             #########
322             # ALIAS #
323             #########
324            
325 0     0 1 0 sub root { $_[0]->{ROOT} ;}
326 0     0 1 0 sub safe { $_[0]->{SAFE} ;}
327            
328 0     0 1 0 sub tiestdout { $_[0]->{TIESTDOUT} ;}
329 0     0 1 0 sub tiestderr { $_[0]->{TIESTDERR} ;}
330            
331             sub headers {
332 0     0 1 0 my $this = shift ;
333 0 0       0 return if $this->{NO_IO} ;
334 0         0 return $this->{TIESTDOUT}->headers(@_) ;
335             }
336            
337             sub stdout_data {
338 0     0 1 0 my $this = shift ;
339 0 0       0 return if $this->{NO_IO} ;
340 0         0 return $this->{TIESTDOUT}->stdout_data(@_) ;
341             }
342            
343             sub stdout_buffer_data {
344 0     0 1 0 my $this = shift ;
345 0 0       0 return if $this->{NO_IO} ;
346 0         0 return $this->{TIESTDOUT}->buffer_data(@_) ;
347             }
348            
349             #######
350             # NEW # root , stdout , stdin , stderr , env , headout , headsplitter , autohead , &on_closeheaders , &on_exit , &on_select , &on_unselect , sharepack , flush , no_clean , no_set_safeworld
351             #######
352            
353             sub new {
354 1     1 1 19 my $class = shift ;
355 1         4 my $this = bless({} , $class) ;
356 1         9 my ( %args ) = @_ ;
357            
358 1 50       8 $this->{NO_IO} = 1 if $args{no_io} ;
359            
360 1 50       5 if ( !$this->{NO_IO} ) {
361 0   0     0 $this->{STDOUT} = $args{stdout} || \*main::STDOUT ;
362 0   0     0 $this->{STDIN} = $args{stdin} || \*main::STDIN ;
363 0   0     0 $this->{STDERR} = $args{stderr} || \*main::STDERR ;
364 0         0 $this->{HEADOUT} = $args{headout} ;
365            
366 0 0       0 if ( !ref($this->{STDOUT}) ) { $this->{STDOUT} = \*{$this->{STDOUT}} ;}
  0         0  
  0         0  
367 0 0       0 if ( !ref($this->{STDIN}) ) { $this->{STDIN} = \*{$this->{STDIN}} ;}
  0         0  
  0         0  
368 0 0       0 if ( !ref($this->{STDERR}) ) { $this->{STDERR} = \*{$this->{STDERR}} ;}
  0         0  
  0         0  
369 0 0 0     0 if ( $this->{HEADOUT} && !ref($this->{HEADOUT}) ) { $this->{HEADOUT} = \*{$this->{HEADOUT}} ;}
  0         0  
  0         0  
370            
371 0 0       0 if ( ref($this->{HEADOUT}) !~ /^(?:GLOB|SCALAR|CODE)$/ ) { $this->{HEADOUT} = undef ;}
  0         0  
372            
373 0 0       0 ${$this->{STDOUT}} .= '' if ref($this->{STDOUT}) eq 'SCALAR' ;
  0         0  
374 0 0       0 ${$this->{STDERR}} .= '' if ref($this->{STDERR}) eq 'SCALAR' ;
  0         0  
375 0 0       0 ${$this->{HEADOUT}} .= '' if ref($this->{HEADOUT}) eq 'SCALAR' ;
  0         0  
376            
377             ####
378            
379 0         0 $this->{FLUSH} = $args{flush} ;
380            
381 0 0       0 $this->{AUTOHEAD} = $args{autohead} if exists $args{autohead} ;
382 0 0 0     0 $this->{AUTOHEAD} = 1 if ($this->{HEADOUT} && !exists $args{autohead}) ;
383            
384 0 0 0     0 $this->{HEADSPLITTER} = $args{headsplitter} || $args{headspliter} || qr/(?:\r\n\r\n|\012\015\012\015|\n\n|\015\015|\r\r|\012\012)/s if $this->{AUTOHEAD} ;
385 0 0       0 if ( $this->{HEADSPLITTER} eq 'HTML' ) {
386 0         0 $this->{HEADSPLITTER} = $Safe_World_stdout_headsplitter_html ; ##\&Safe::World::stdout::headsplitter_html ;
387             }
388            
389             ####
390            
391            
392 0 0       0 $this->{ONCLOSEHEADERS} = $args{on_closeheaders} if (ref($args{on_closeheaders}) eq 'CODE') ;
393 0 0       0 $this->{ONEXIT} = $args{on_exit} if (ref($args{on_exit}) eq 'CODE') ;
394            
395 0 0       0 $this->{ONSELECT} = $args{on_select} if (ref($args{on_select}) eq 'CODE') ;
396 0 0       0 $this->{ONUNSELECT} = $args{on_unselect} if (ref($args{on_unselect}) eq 'CODE') ;
397             }
398            
399             ####
400            
401 1         3 $this->{SHAREDPACK} = $args{sharepack} ;
402 1 50 33     9 if ( $this->{SHAREDPACK} && ref($this->{SHAREDPACK}) ne 'ARRAY' ) { $this->{SHAREDPACK} = [$this->{SHAREDPACK}] ;}
  0         0  
403            
404 1 50       3 if ( $this->{SHAREDPACK} ) {
405 1         2 foreach my $packs_i ( @{ $this->{SHAREDPACK} } ) {
  1         3  
406 1         2 $packs_i =~ s/[^\w:\.]//gs ;
407 1         3 $packs_i =~ s/[:\.]+/::/ ;
408 1         3 $packs_i =~ s/^(?:main)?::// ;
409 1         2 $packs_i =~ s/::$// ;
410 1         2 my $pm = $packs_i ;
411 1         3 $pm =~ s/::/\//g ;
412 1         2 $pm .= '.pm' ;
413 1         5 $this->{SHAREDPACK_PM}{$packs_i} = $pm ;
414             }
415             }
416            
417             ####
418            
419 1   33     7 $this->{ENV} = $args{env} || $args{ENV} ;
420 1 50       4 if ( ref($this->{ENV}) ne 'HASH') { $this->{ENV} = undef ;}
  1         1  
421            
422 1         2 my $packname = $args{root} ;
423            
424 1 50       7 if ( !$packname ) {
425 1 50       4 $packname = $args{is_cache} ? $COMPARTMENT_NAME_CACHE : $COMPARTMENT_NAME ;
426 1         2 $packname .= ++$COMPARTMENT_X ;
427 1 50       5 $this->{IS_CACHE} = 1 if $args{is_cache} ;
428             }
429            
430 1         2 $this->{ROOT} = $packname ;
431            
432 1 50       4 $this->{NO_SET_SAFEWORLD} = 1 if $args{no_set_safeworld} ;
433 1 50       4 $this->{NO_CLEAN} = 1 if $args{no_clean} ;
434            
435 1         8 $this->{SAFE} = $SCOPE_Safe_World_Compartment->NEW($packname) ; # Safe::World::Compartment->new($packname) ;
436 1         9 $this->{SAFE}->deny_only(@DENY_OPS) ;
437            
438 0         0 *{"$packname\::$packname\::"} = *{"$packname\::"} ;
  0         0  
  0         0  
439 0         0 *{"$packname\::main::"} = *{"$packname\::"} ;
  0         0  
  0         0  
440            
441 0 0       0 if ( $this->{SHAREDPACK} ) {
442 0         0 $this->{SAFE}->reval(q`package WORLDSHARE ;`);
443             }
444            
445             ###
446            
447 0 0       0 if ( !$this->{NO_IO} ) {
448 0 0 0     0 if ( $this->{FLUSH} && !$this->{HEADOUT} && !$this->{AUTOHEAD} ) {
      0        
449 0         0 $this->{TIESTDOUT} = tie(*{"$packname\::STDOUT"} => 'Safe::World::stdoutsimple' , $this->{ROOT} , $this->{STDOUT} ) ;
  0         0  
450             }
451             else {
452 0         0 $this->{TIESTDOUT} = tie(*{"$packname\::STDOUT"} => 'Safe::World::stdout' , $this->{ROOT} , $this->{STDOUT} , $this->{FLUSH} , $this->{HEADOUT} , $this->{AUTOHEAD} , $this->{HEADSPLITTER} , $this->{ONCLOSEHEADERS} ) ;
  0         0  
453             }
454            
455 0         0 $this->{TIESTDERR} = tie(*{"$packname\::STDERR"} => 'Safe::World::stderr' , $this->{ROOT} , $this->{STDERR} ) ;
  0         0  
456            
457 0 0       0 *{"$packname\::STDIN"} = $this->{STDIN} if $this->{STDIN} ;
  0         0  
458             }
459            
460             ###
461            
462 0         0 $this->link_pack('UNIVERSAL') ;
463 0         0 $this->link_pack('attributes') ;
464 0         0 $this->link_pack('DynaLoader') ;
465             # $this->link_pack('IO') ;
466            
467             # $this->link_pack('Exporter') ;
468             # $this->link_pack('warnings') ;
469            
470             # $this->link_pack('AutoLoader') ;
471             # $this->link_pack('Carp') ;
472             # $this->link_pack('Config') ;
473             # $this->link_pack('Errno') ;
474             # $this->link_pack('overload') ;
475             # $this->link_pack('re') ;
476             # $this->link_pack('subs') ;
477             # $this->link_pack('vars') ;
478            
479 0         0 $this->link_pack('CORE') ;
480            
481 0         0 $this->link_pack('') ;
482            
483 0 0       0 $this->link_pack('Apache') if defined *{"Apache::"} ;
  0         0  
484 0 0       0 $this->link_pack('Win32') if defined *{"Win32::"} ;
  0         0  
485            
486 0         0 $this->share_vars( 'main' , [
487             '@INC' , '%INC' ,
488             '$@','$|','$_', '$!',
489             #'$-', , '$/' ,'$!','$.' ,
490             ]) ;
491            
492 0         0 $this->select_static ;
493            
494 0 0       0 $this->set_vars(
495             '%SIG' => \%SIG ,
496             '$/' => $/ ,
497             '$"' => $" ,
498             '$;' => $; ,
499             '$$' => $$ ,
500             '$^W' => 0 ,
501             ( $this->{ENV} ? ('%ENV' => $this->{ENV}) : () ) ,
502             ) ;
503            
504 0         0 $this->set('%INC',{}) ;
505            
506 0 0       0 $this->eval("no strict ;") if !$args{no_strict} ; ## just to load strict inside the compartment.
507            
508             #$this->track_vars(':defaults') if !$this->{TRACK_VARS_DEF} && $this->{SHAREDPACK} ;
509            
510 0 0       0 $this->track_vars(qw(>STDOUT >STDERR {NO_IO} ;
511            
512 0         0 $this->unselect_static ;
513            
514 0         0 $SAFEWORLDS_TABLE->{POOL}{ $this->{ROOT} } = $this ;
515            
516 0         0 return $this ;
517             }
518            
519             ###########
520             # OPCODES #
521             ###########
522            
523             sub op_deny {
524 0     0 1 0 my $this = shift ;
525 0         0 $this->{SAFE}->deny(@_);
526             }
527            
528             sub op_deny_only {
529 0     0 1 0 my $this = shift ;
530 0         0 $this->{SAFE}->deny_only(@_);
531             }
532            
533             sub op_permit {
534 0     0 1 0 my $this = shift ;
535 0         0 $this->{SAFE}->permit(@_);
536             }
537            
538             sub op_permit_only {
539 0     0 1 0 my $this = shift ;
540 0         0 $this->{SAFE}->permit_only(@_);
541             }
542            
543             ##############
544             # SYNC_EVALX #
545             ##############
546            
547             sub sync_evalx {
548 2     2 0 4 my $tmp = $@ ;
549 2         99 eval("=1") ;
550 2         8 $@ = $tmp ;
551 2         8 my ($evalx) = ( $@ =~ /\(eval (\d+)/s );
552 2         10 $EVALX = $evalx ;
553             }
554            
555             #########
556             # RESET #
557             #########
558            
559             sub reset {
560 0     0 1 0 my $this = shift ;
561 0         0 my ( %args ) = @_ ;
562            
563 0         0 my $packname = $this->{ROOT} ;
564            
565 0         0 $this->reset_internals ;
566            
567 0 0       0 if ( !$this->{NO_IO} ) {
568 0 0       0 $this->{STDOUT} = $args{stdout} if $args{stdout} ;
569 0 0       0 $this->{STDIN} = $args{stdin} if $args{stdin} ;
570 0 0       0 $this->{STDERR} = $args{stderr} if $args{stderr} ;
571 0 0       0 $this->{HEADOUT} = $args{headout} if $args{headout} ;
572            
573 0 0 0     0 if ( $this->{STDOUT} && !ref($this->{STDOUT}) ) { $this->{STDOUT} = \*{$this->{STDOUT}} ;}
  0         0  
  0         0  
574 0 0 0     0 if ( $this->{STDIN} && !ref($this->{STDIN}) ) { $this->{STDIN} = \*{$this->{STDIN}} ;}
  0         0  
  0         0  
575 0 0 0     0 if ( $this->{STDERR} && !ref($this->{STDERR}) ) { $this->{STDERR} = \*{$this->{STDERR}} ;}
  0         0  
  0         0  
576 0 0 0     0 if ( $this->{HEADOUT} && !ref($this->{HEADOUT}) ) { $this->{HEADOUT} = \*{$this->{HEADOUT}} ;}
  0         0  
  0         0  
577            
578 0 0       0 if ( ref($this->{HEADOUT}) !~ /^(?:GLOB|SCALAR|CODE)$/ ) { $this->{HEADOUT} = undef ;}
  0         0  
579            
580 0 0       0 ${$this->{STDOUT}} .= '' if ref($this->{STDOUT}) eq 'SCALAR' ;
  0         0  
581 0 0       0 ${$this->{STDERR}} .= '' if ref($this->{STDERR}) eq 'SCALAR' ;
  0         0  
582 0 0       0 ${$this->{HEADOUT}} .= '' if ref($this->{HEADOUT}) eq 'SCALAR' ;
  0         0  
583             }
584            
585 0   0     0 my $env = $args{env} || $args{ENV} ;
586            
587 0 0       0 if ( $env ) {
588 0         0 $this->{ENV} = $env ;
589 0 0       0 if ( ref($this->{ENV}) ne 'HASH') { $this->{ENV} = undef ;}
  0         0  
590             }
591            
592 0         0 my $sel = $this->select_static ;
593            
594 0 0       0 $this->set_vars(
595             '%SIG' => \%SIG ,
596             '$/' => $/ ,
597             '$"' => $" ,
598             '$;' => $; ,
599             '$$' => $$ ,
600             '$^W' => 0 ,
601             ( $env ? ('%ENV' => $this->{ENV}) : () ) ,
602             ) ;
603            
604 0 0       0 if ( !$this->{NO_IO} ) {
605 0         0 untie(*{"$packname\::STDOUT"}) ;
  0         0  
606 0         0 untie(*{"$packname\::STDERR"}) ;
  0         0  
607            
608 0 0 0     0 if ( $this->{FLUSH} && !$this->{HEADOUT} && !$this->{AUTOHEAD} ) {
      0        
609 0         0 $this->{TIESTDOUT} = tie(*{"$packname\::STDOUT"} => 'Safe::World::stdoutsimple' , $this->{ROOT} , $this->{STDOUT} ) ;
  0         0  
610             }
611             else {
612 0         0 $this->{TIESTDOUT} = tie(*{"$packname\::STDOUT"} => 'Safe::World::stdout' , $this->{ROOT} , $this->{STDOUT} , $this->{FLUSH} , $this->{HEADOUT} , $this->{AUTOHEAD} , $this->{HEADSPLITTER} , $this->{ONCLOSEHEADERS} ) ;
  0         0  
613             }
614            
615 0         0 $this->{TIESTDERR} = tie(*{"$packname\::STDERR"} => 'Safe::World::stderr' , $this->{ROOT} , $this->{STDERR} ) ;
  0         0  
616            
617 0 0       0 *{"$packname\::STDIN"} = $this->{STDIN} if $this->{STDIN} ;
  0         0  
618             }
619            
620 0         0 sync_evalx() ;
621            
622 0 0       0 $this->unselect_static if $sel ;
623            
624 0         0 return 1 ;
625             }
626            
627             ###################
628             # RESET_INTERNALS #
629             ###################
630            
631             sub reset_internals {
632 0     0 1 0 my $this = shift ;
633            
634 0         0 $this->{EXIT} = undef ;
635 0         0 $this->{DESTROIED} = undef ;
636 0         0 $this->{CLEANNED} = undef ;
637             }
638            
639             ################
640             # RESET_OUTPUT #
641             ################
642            
643             sub reset_output {
644 0     0 1 0 my $this = shift ;
645 0 0       0 return if $this->{NO_IO} ;
646            
647 0         0 my ( %args ) = @_ ;
648            
649 0         0 my $packname = $this->{ROOT} ;
650            
651 0 0       0 if ( $args{stdout} ) {
652 0         0 $this->{STDOUT} = $args{stdout} ;
653            
654 0 0 0     0 if ( $this->{STDOUT} && !ref($this->{STDOUT}) ) { $this->{STDOUT} = \*{$this->{STDOUT}} ;}
  0         0  
  0         0  
655             #if ( ref($this->{STDOUT}) !~ /^(?:GLOB|SCALAR|CODE)$/ ) { $this->{STDOUT} = undef ;}
656 0 0       0 ${$this->{STDOUT}} .= '' if ref($this->{STDOUT}) eq 'SCALAR' ;
  0         0  
657            
658 0 0       0 $this->{TIESTDOUT}->{STDOUT} = $this->{STDOUT} if $this->{STDOUT} ;
659             }
660            
661 0 0       0 if ( $args{stderr} ) {
662 0         0 $this->{STDERR} = $args{stderr} ;
663            
664 0 0 0     0 if ( $this->{STDERR} && !ref($this->{STDERR}) ) { $this->{STDERR} = \*{$this->{STDERR}} ;}
  0         0  
  0         0  
665             #if ( ref($this->{STDERR}) !~ /^(?:GLOB|SCALAR|CODE)$/ ) { $this->{STDERR} = undef ;}
666 0 0       0 ${$this->{STDERR}} .= '' if ref($this->{STDERR}) eq 'SCALAR' ;
  0         0  
667            
668 0 0       0 $this->{TIESTDERR}->{STDERR} = $this->{STDERR} if $this->{STDERR} ;
669             }
670            
671 0 0       0 if ( $args{headout} ) {
672 0         0 $this->{HEADOUT} = $args{headout} ;
673            
674 0 0 0     0 if ( $this->{HEADOUT} && !ref($this->{HEADOUT}) ) { $this->{HEADOUT} = \*{$this->{HEADOUT}} ;}
  0         0  
  0         0  
675 0 0       0 if ( ref($this->{HEADOUT}) !~ /^(?:GLOB|SCALAR|CODE)$/ ) { $this->{HEADOUT} = undef ;}
  0         0  
676 0 0       0 ${$this->{HEADOUT}} .= '' if ref($this->{HEADOUT}) eq 'SCALAR' ;
  0         0  
677            
678 0 0       0 $this->{TIESTDOUT}->{HEADOUT} = $this->{HEADOUT} if $this->{HEADOUT} ;
679             }
680            
681 0 0       0 if ( $args{stdin} ) {
682 0         0 $this->{STDIN} = $args{stdin} ;
683            
684 0 0 0     0 if ( $this->{STDIN} && !ref($this->{STDIN}) ) { $this->{STDIN} = \*{$this->{STDIN}} ;}
  0         0  
  0         0  
685             #if ( ref($this->{STDIN}) !~ /^(?:GLOB)$/ ) { $this->{STDIN} = undef ;}
686            
687 0 0       0 *{"$packname\::STDIN"} = $this->{STDIN} if $this->{STDIN} ;
  0         0  
688             }
689            
690 0         0 return 1 ;
691             }
692            
693             #################
694             # SELECT_STATIC #
695             #################
696            
697             sub select_static {
698 0 0 0 0 1 0 if ( !$SAFE_WORLD_SELECTED_STATIC && $NOW != $_[0] ) {
699 0         0 $SAFE_WORLD_SELECTED_STATIC = $SCOPE_Safe_World_select->NEW($_[0]) ; ## Safe::World::select->new($_[0]) ;
700 0         0 return 1 ;
701             }
702 0         0 return ;
703             }
704            
705             ###################
706             # UNSELECT_STATIC #
707             ###################
708            
709             sub unselect_static {
710 0 0 0 0 1 0 if ( $SAFE_WORLD_SELECTED_STATIC && $NOW == $_[0] ) {
711 0         0 $SAFE_WORLD_SELECTED_STATIC = undef ;
712 0         0 return 1 ;
713             }
714 0         0 return ;
715             }
716            
717             ########
718             # EVAL #
719             ########
720            
721             sub eval {
722            
723 0 0 0 0 1 0 if ( $_[0]->{WORLD_SHARED} && !$_[0]->{DESTROIED} && $NOW != $_[0] ) {
    0 0        
      0        
      0        
724 0         0 $_[0]->warn("Don't evaluate inside a linked pack (shared with $_[0]->{WORLD_SHARED})! Please unlink first." , 1) ;
725             }
726             elsif ( $_[0]->{EXIT} && !$_[0]->{DESTROIED} && $NOW != $_[0] ) {
727 0         0 $_[0]->warn("Can't evaluate after exit!" , 1) ;
728 0         0 return ;
729             }
730            
731             ##print "[[$_[1]]]\n" ;
732            
733 0 0       0 if ( $MAIN_STASH != *{"main::"}{HASH} ) {
  0         0  
734             ##if ( $_[0]->{INSIDE} ) {
735             ##print STDOUT "EVAL>> INSIDE [[ $_[1] ]]\n" ;
736 0         0 ++$EVALX ;
737            
738 0 0       0 if ( wantarray ) {
739 0         0 my @__HPL_ReT__ = eval("no strict;\@_ = () ; package main ; $_[1]") ;
740 0 0       0 $NOW->warn($@ , 1) if $@ ; ## $_[0] is undef by @_ = () ;
741 0         0 return @__HPL_ReT__ ;
742             }
743             else {
744 0         0 my $__HPL_ReT__ = eval("no strict;\@_ = () ; package main ; $_[1]") ;
745 0 0       0 $NOW->warn($@ , 1) if $@ ; ## $_[0] is undef by @_ = () ;
746 0         0 return $__HPL_ReT__ ;
747             }
748             }
749             else {
750             ##print STDOUT "EVAL>> OUT >> ". \@{'_'} ."\n" ;
751            
752 0         0 my $SAFE_WORLD_selected ;
753 0 0       0 if ( $NOW != $_[0] ) {
754 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($_[0]) ; ##Safe::World::select->new($_[0]) ;
755             }
756            
757 0         0 $NOW->{INSIDE} = 1 ;
758            
759 0 0       0 if ( wantarray ) {
760 0         0 my @ret = $NOW->{SAFE}->reval($_[1]) ;
761 0 0       0 $NOW->warn($@ , 1) if $@ ;
762 0         0 $NOW->{INSIDE} = 0 ;
763 0         0 return @ret ;
764             }
765             else {
766 0         0 my $ret = $NOW->{SAFE}->reval($_[1]) ;
767 0 0       0 $NOW->warn($@ , 1) if $@ ;
768 0         0 $NOW->{INSIDE} = 0 ;
769 0         0 return $ret ;
770             }
771             }
772             }
773            
774             ################
775             # EVAL_NO_WARN #
776             ################
777            
778             sub eval_no_warn {
779 0 0 0 0 1 0 if ( $_[0]->{WORLD_SHARED} && !$_[0]->{DESTROIED} && $NOW != $_[0] ) {
    0 0        
      0        
      0        
780 0         0 $_[0]->warn("Don't evaluate inside a linked pack (shared with ". join(", ", @{$_[0]->{WORLD_SHARED}}) .")! Please unlink first." , 1) ;
  0         0  
781             }
782             elsif ( $_[0]->{EXIT} && !$_[0]->{DESTROIED} && $NOW != $_[0] ) {
783 0         0 $_[0]->warn("Can't evaluate after exit!" , 1) ;
784 0         0 return ;
785             }
786            
787 1     1   9 no warnings ;
  1         2  
  1         9903  
788 0         0 local $^W = 0 ;
789 0         0 $IGNORE_EXIT = 1 ;
790            
791 0         0 my %__SAVE_SIGS__ ;
792            
793 0         0 $__SAVE_SIGS__{warn} = $SIG{__WARN__} ;
794 0         0 $__SAVE_SIGS__{die} = $SIG{__DIE__} ;
795            
796 0     0   0 $SIG{__WARN__} = sub {} ;
  0         0  
797 0     0   0 $SIG{__DIE__} = sub {} ;
  0         0  
798            
799 0 0       0 $_[0]->{TIESTDERR}->block if $_[0]->{TIESTDERR} ;
800            
801 0 0       0 if ( $MAIN_STASH != *{"main::"}{HASH} ) {
  0         0  
802             #if ( $_[0]->{INSIDE} ) {
803 0         0 ++$EVALX ;
804 0 0       0 if ( wantarray ) {
805 0         0 my @__HPL_ReT__ = eval("no strict;\@_ = () ; package main ; $_[1]") ;
806 0 0       0 $SIG{__WARN__} = $__SAVE_SIGS__{warn} ; $SIG{__DIE__} = $__SAVE_SIGS__{die} ; $IGNORE_EXIT = undef ; $NOW->{TIESTDERR}->unblock if $NOW->{TIESTDERR} ;
  0         0  
  0         0  
  0         0  
807 0         0 return @__HPL_ReT__ ;
808             }
809             else {
810 0         0 my $__HPL_ReT__ = eval("no strict;\@_ = () ; package main ; $_[1]") ;
811 0 0       0 $SIG{__WARN__} = $__SAVE_SIGS__{warn} ; $SIG{__DIE__} = $__SAVE_SIGS__{die} ; $IGNORE_EXIT = undef ; $NOW->{TIESTDERR}->unblock if $NOW->{TIESTDERR} ;
  0         0  
  0         0  
  0         0  
812 0         0 return $__HPL_ReT__ ;
813             }
814             }
815             else {
816 0         0 my $SAFE_WORLD_selected ;
817 0 0       0 if ( $NOW != $_[0] ) {
818 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($_[0]) ; ##Safe::World::select->new($_[0]) ;
819             }
820            
821 0         0 $NOW->{INSIDE} = 1 ;
822            
823 0 0       0 if ( wantarray ) {
824 0         0 my @ret = $NOW->{SAFE}->reval($_[1]) ;
825 0         0 $NOW->{INSIDE} = 0 ;
826 0 0       0 $SIG{__WARN__} = $__SAVE_SIGS__{warn} ; $SIG{__DIE__} = $__SAVE_SIGS__{die} ; $IGNORE_EXIT = undef ; $NOW->{TIESTDERR}->unblock if $NOW->{TIESTDERR} ;
  0         0  
  0         0  
  0         0  
827 0         0 return @ret ;
828             }
829             else {
830 0         0 my $ret = $NOW->{SAFE}->reval($_[1]) ;
831 0         0 $NOW->{INSIDE} = 0 ;
832 0 0       0 $SIG{__WARN__} = $__SAVE_SIGS__{warn} ; $SIG{__DIE__} = $__SAVE_SIGS__{die} ; $IGNORE_EXIT = undef ; $NOW->{TIESTDERR}->unblock if $NOW->{TIESTDERR} ;
  0         0  
  0         0  
  0         0  
833 0         0 return $ret ;
834             }
835             }
836             }
837            
838             #############
839             # EVAL_PACK #
840             #############
841            
842 0     0 1 0 sub eval_pack { $_[0]->eval("package $_[1] ; $_[2]") ;}
843            
844             #############
845             # EVAL_ARGS #
846             #############
847            
848             sub eval_args {
849 0     0 1 0 my $this = shift ;
850 0         0 my $code = shift ;
851            
852 0         0 my $tmp = $_ ;
853 0         0 $_ = \@_ ;
854            
855 0 0       0 if ( wantarray ) {
856 0         0 my @ret = $this->eval("\@_=\@{\$_};\$_=undef; $code") ;
857 0         0 $_ = $tmp ;
858 0         0 return @ret ;
859             }
860             else {
861 0         0 my $ret = $this->eval("\@_=\@{\$_};\$_=undef; $code") ;
862 0         0 $_ = $tmp ;
863 0         0 return $ret ;
864             }
865             }
866            
867             ##################
868             # EVAL_PACK_ARGS #
869             ##################
870            
871             sub eval_pack_args {
872 0     0 1 0 my $this = shift ;
873 0         0 my $pack = shift ;
874 0         0 my $code = shift ;
875            
876 0 0       0 if ( @_ ) {
877 0         0 return $this->eval_args("package $pack ; $code" , @_) ;
878             }
879             else {
880 0         0 return $this->eval("package $pack ; $code") ;
881             }
882             }
883            
884             ########
885             # CALL #
886             ########
887            
888             sub call {
889 0     0 1 0 my $this = shift ;
890 0         0 my $sub = shift ;
891            
892 0         0 my $tmp = $_ ;
893 0         0 $_ = \@_ ;
894            
895 0         0 my ( @ret , $ret ) ;
896            
897 0 0       0 if ( wantarray ) { @ret = $this->eval("return $sub(\@{\$_}) ;") ;}
  0         0  
898 0         0 else { $ret = $this->eval("return $sub(\@{\$_}) ;") ;}
899            
900 0         0 $_ = $tmp ;
901            
902 0 0       0 return( @ret ) if wantarray ;
903 0         0 return $ret ;
904             }
905            
906             #######
907             # GET #
908             #######
909            
910             sub get {
911 0     0 1 0 my $this = shift ;
912 0         0 my $var = shift ;
913            
914 0         0 my $pack = $this->{ROOT} ;
915            
916 0         0 my ($var_tp,$var_name,$var_more) = ( $var =~ /^\s*([\$\@\%\*])([\w:]+)(.*)\s*$/s );
917            
918 0 0       0 if ( $var_more ) { $var_tp = '' ;}
  0         0  
919            
920 0 0       0 if ($var_tp eq '$') { return ${$pack.'::'.$var_name} ;}
  0 0       0  
  0 0       0  
    0          
921 0         0 elsif ($var_tp eq '@') { return @{$pack.'::'.$var_name} ;}
  0         0  
922 0         0 elsif ($var_tp eq '%') { return %{$pack.'::'.$var_name} ;}
  0         0  
923 0         0 elsif ($var_tp eq '*') { return *{$pack.'::'.$var_name} ;}
  0         0  
924 0         0 else { return $this->eval($var) ;}
925            
926 0         0 return ;
927             }
928            
929             ############
930             # GET_FROM #
931             ############
932            
933             sub get_from {
934 0     0 1 0 my $this = shift ;
935 0         0 my $pack = shift ;
936 0         0 my $var = shift ;
937            
938 0         0 $pack =~ s/[:\.]+/::/gs ;
939 0 0       0 return if $pack !~ /^\w+(?:::\w+)*(?:::)?$/s ;
940            
941 0         0 my ($var_tp,$var_name,$var_more) = ( $var =~ /^\s*([\$\@\%\*])([\w:]+)(.*)\s*$/s );
942            
943 0 0       0 if ( !$var_tp ) { return $this->eval("package $pack; $var") ;}
  0         0  
944            
945 0         0 my $varfull = "$var_tp$pack\::$var_name$var_more" ;
946 0         0 return $this->get($varfull) ;
947             }
948            
949             ###########
950             # GET_REF #
951             ###########
952            
953             sub get_ref {
954 0     0 1 0 my $this = shift ;
955 0         0 my ( $varfull ) = @_ ;
956            
957 0         0 my $pack = $this->{ROOT} ;
958            
959 0         0 my ($var_tp,$var) = ( $varfull =~ /([\$\@\%\*])(\S+)/ ) ;
960 0         0 $var =~ s/^{'(\S+)'}$/$1/ ;
961 0         0 $var =~ s/^main::// ;
962            
963 0 0       0 if ($var_tp eq '$') { return \${$pack.'::'.$var} ;}
  0 0       0  
  0 0       0  
    0          
964 0         0 elsif ($var_tp eq '@') { return \@{$pack.'::'.$var} ;}
  0         0  
965 0         0 elsif ($var_tp eq '%') { return \%{$pack.'::'.$var} ;}
  0         0  
966 0         0 elsif ($var_tp eq '*') { return \*{$pack.'::'.$var} ;}
  0         0  
967 0         0 else { ++$EVALX ; return eval("package $pack ; \\$varfull") ;}
  0         0  
968             }
969            
970             ################
971             # GET_REF_COPY #
972             ################
973            
974             sub get_ref_copy {
975 0     0 1 0 my $this = shift ;
976 0         0 my ( $varfull ) = @_ ;
977            
978 0         0 my $pack = $this->{ROOT} ;
979            
980 0         0 my ($var_tp,$var) = ( $varfull =~ /([\$\@\%\*])(\S+)/ ) ;
981 0         0 $var =~ s/^{'(\S+)'}$/$1/ ;
982 0         0 $var =~ s/^main::// ;
983            
984 0 0       0 if ($var_tp eq '$') {
    0          
    0          
    0          
985 0         0 my $scalar = ${$pack.'::'.$var} ;
  0         0  
986 0         0 return \$scalar ;
987             }
988 0         0 elsif ($var_tp eq '@') { return [@{$pack.'::'.$var}] ;}
  0         0  
989 0         0 elsif ($var_tp eq '%') { return {%{$pack.'::'.$var}} ;}
  0         0  
990 0         0 elsif ($var_tp eq '*') { return \*{$pack.'::'.$var} ;}
  0         0  
991 0         0 else { ++$EVALX ; return eval("package $pack ; \\$varfull") ;}
  0         0  
992             }
993            
994             #######
995             # SET #
996             #######
997            
998             sub set {
999 3     3 1 6 my $this = shift ;
1000 3         7 my ( $var , undef , $no_parse_ref) = @_ ;
1001            
1002 3         4 my $SAFE_WORLD_selected ;
1003 3 100       10 if ( $NOW != $this ) {
1004 1         6 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($this) ; ## Safe::World::select->new($this) ;
1005             }
1006            
1007 3         6 my $pack = $this->{ROOT} ;
1008            
1009 3         15 my ($var_tp,$var_name) = ( $var =~ /^([\$\@\%\*])(.*)/s );
1010            
1011 3 0       10 my $val = (ref($_[1])) ? $_[1] : ( $_[1] eq '' ? \undef : \$_[1]) ;
    50          
1012            
1013 3 50       7 if ($var_tp eq '$') {
    0          
    0          
    0          
1014 3 100 66     15 if (!$no_parse_ref && ref($val) eq 'SCALAR') { ${$pack.'::'.$var_name} = ${$val} ;}
  2         3  
  2         7  
  2         5  
1015 1         2 else { ${$pack.'::'.$var_name} = $val ;}
  1         6  
1016             }
1017             elsif ($var_tp eq '@') {
1018 0 0 0     0 if (!$no_parse_ref && ref($val) eq 'ARRAY') { @{$pack.'::'.$var_name} = @{$val} ;}
  0 0 0     0  
  0         0  
  0         0  
1019 0         0 elsif (!$no_parse_ref && ref($val) eq 'HASH') { @{$pack.'::'.$var_name} = %{$val} ;}
  0         0  
  0         0  
1020 0         0 else { @{$pack.'::'.$var_name} = $val ;}
  0         0  
1021             }
1022             elsif ($var_tp eq '%') {
1023 0 0 0     0 if (!$no_parse_ref && ref($val) eq 'HASH') { %{$pack.'::'.$var_name} = %{$val} ;}
  0 0 0     0  
  0         0  
  0         0  
1024 0         0 elsif (!$no_parse_ref && ref($val) eq 'ARRAY') { %{$pack.'::'.$var_name} = @{$val} ;}
  0         0  
  0         0  
1025 0         0 else { %{$pack.'::'.$var_name} = $val ;}
  0         0  
1026             }
1027             elsif ($var_tp eq '*') {
1028 0 0       0 if (ref($val) eq 'GLOB') { *{$pack.'::'.$var_name} = $val ;}
  0         0  
  0         0  
1029 0         0 else { *{$pack.'::'.$var_name} = \*{$val} ;}
  0         0  
  0         0  
1030             }
1031             else {
1032 0         0 ++$EVALX ; eval("$var_tp$pack\::$var_name = $val ;") ;
  0         0  
1033             }
1034            
1035 3         12 return ;
1036             }
1037            
1038             ############
1039             # SET_VARS #
1040             ############
1041            
1042             sub set_vars {
1043 0     0 1 0 my $this = shift ;
1044 0         0 my ( %vars ) = @_ ;
1045            
1046 0         0 my $SAFE_WORLD_selected ;
1047 0 0       0 if ( $NOW != $this ) {
1048 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($this) ; ## Safe::World::select->new($this) ;
1049             }
1050            
1051 0         0 my $pack = $this->{ROOT} ;
1052            
1053 0         0 my ($var_tp,$var) ;
1054            
1055 0         0 foreach my $Key ( keys %vars ) {
1056 0         0 ($var_tp,$var) = ( $Key =~ /([\$\@\%\*])(\S+)/ );
1057 0         0 $var =~ s/^{'(\S+)'}$/$1/ ;
1058 0         0 $var =~ s/^main::// ;
1059            
1060 0 0       0 if ($var_tp eq '$') {
    0          
    0          
    0          
1061 0 0       0 if (ref($vars{$Key}) eq 'SCALAR') { ${$pack.'::'.$var} = ${$vars{$Key}} ;}
  0         0  
  0         0  
  0         0  
1062 0         0 else { ${$pack.'::'.$var} = $vars{$Key} ;}
  0         0  
1063             }
1064             elsif ($var_tp eq '@') {
1065 0 0       0 if (ref($vars{$Key}) eq 'ARRAY') { @{$pack.'::'.$var} = @{$vars{$Key}} ;}
  0 0       0  
  0         0  
  0         0  
1066 0         0 elsif (ref($vars{$Key}) eq 'HASH') { @{$pack.'::'.$var} = %{$vars{$Key}} ;}
  0         0  
  0         0  
1067 0         0 else { @{$pack.'::'.$var} = $vars{$Key} ;}
  0         0  
1068             }
1069             elsif ($var_tp eq '%') {
1070 0 0       0 if (ref($vars{$Key}) eq 'HASH') { %{$pack.'::'.$var} = %{$vars{$Key}} ;}
  0 0       0  
  0         0  
  0         0  
1071 0         0 elsif (ref($vars{$Key}) eq 'ARRAY') { %{$pack.'::'.$var} = @{$vars{$Key}} ;}
  0         0  
  0         0  
1072 0         0 else { %{$pack.'::'.$var} = $vars{$Key} ;}
  0         0  
1073             }
1074             elsif ($var_tp eq '*') {
1075 0 0       0 if (ref($vars{$Key}) eq 'GLOB') { *{$pack.'::'.$var} = $vars{$Key} ;}
  0         0  
  0         0  
1076 0         0 else { *{$pack.'::'.$var} = \*{$vars{$Key}} ;}
  0         0  
  0         0  
1077             }
1078 0         0 else { ++$EVALX ; eval("$var_tp$pack\::$var = \$vars{\$Key} ;") ;}
  0         0  
1079             }
1080            
1081 0         0 return 1 ;
1082             }
1083            
1084             ##############
1085             # SHARE_VARS #
1086             ##############
1087            
1088             sub share_vars {
1089 0     0 1 0 my $this = shift ;
1090 0 0       0 if ( $this->{INSIDE} ) { return ;}
  0         0  
1091            
1092 0         0 my ( $from_pack , $vars ) = @_ ;
1093 0 0       0 if ( ref($vars) ne 'ARRAY' ) { return ;}
  0         0  
1094            
1095 0         0 $from_pack =~ s/^:+//s ;
1096 0         0 $from_pack =~ s/:+$//s ;
1097            
1098 0         0 $this->{SAFE}->share_from($from_pack , $vars) ;
1099            
1100 0         0 foreach my $var ( @$vars ) {
1101 0 0 0     0 next if ($var eq '$_' || $var eq '$|' || $var eq '$@' || $var eq '$!') ;
      0        
      0        
1102            
1103 0 0       0 if ( $var !~ /^\W[\w:]+$/ ) {
1104 0         0 my ($t , $n) = ( $var =~ /^(\W)(.*)/s );
1105 0         0 $var = "$t\{'$from_pack\::$n'}" ;
1106             }
1107             else {
1108 0         0 $var =~ s/^(\W)/$1$from_pack\::/ ;
1109             }
1110            
1111 0         0 $this->{SHARING}{$var} = { IN => undef , OUT => undef } ;
1112             }
1113            
1114 0         0 return 1 ;
1115             }
1116            
1117             ################
1118             # UNSHARE_VARS #
1119             ################
1120            
1121             sub unshare_vars {
1122 1     1 1 1 my $this = shift ;
1123 1 50       4 if ( $this->{INSIDE} ) { return ;}
  0         0  
1124            
1125 1         2 my $pack = $this->{ROOT} ;
1126            
1127 1         1 my ($NULL , @NULL , %NULL) ;
1128 1         2 local(*NULL) ;
1129            
1130 1         2 my %vars = map { $_ => 1 } ( keys %{ $this->{SHARING} } ) ;
  0         0  
  1         3  
1131 1 0       5 my @vars = sort { ($a =~ /^\*/ ? 1 : -1 ) } keys %vars ;
  0         0  
1132            
1133 1         3 foreach my $var (@vars) {
1134 0         0 my ($var_tp,$name) = ( $var =~ /([\$\@\%\*])(\S+)/ );
1135 0         0 $name =~ s/^{'(\S+)'}$/$1/ ;
1136 0         0 $name =~ s/^main::// ;
1137            
1138 0 0       0 next if $this->{DONOT_CLEAN}{$name} ;
1139            
1140 0 0       0 if ($var_tp eq '$') { *{$pack.'::'.$name} = \$NULL ;}
  0 0       0  
  0 0       0  
    0          
1141 0         0 elsif ($var_tp eq '@') { *{$pack.'::'.$name} = \@NULL ;}
  0         0  
1142 0         0 elsif ($var_tp eq '%') { *{$pack.'::'.$name} = \%NULL ;}
  0         0  
1143 0         0 elsif ($var_tp eq '*') { *{$pack.'::'.$name} = \*NULL ;}
  0         0  
1144             }
1145            
1146 1         2 return 1 ;
1147             }
1148            
1149             ##############
1150             # TRACK_VARS #
1151             ##############
1152            
1153             sub track_vars {
1154 0     0 0 0 my $this = shift ;
1155 0 0       0 my $world = ref($_[0]) ? shift : undef ;
1156 0 0 0     0 my $world_dependency = ($world && ref($_[0])) ? shift : undef ;
1157 0   0     0 $world ||= $this ;
1158            
1159 0         0 my ( @vars ) = @_ ;
1160            
1161 0         0 my $root = $world->{ROOT} ;
1162            
1163 0 0       0 if ( $world_dependency ) {
1164 0         0 $this->{TRACK_DEPENDENCIES}{$root} = $world_dependency->{ROOT} ;
1165             }
1166            
1167 0 0       0 if ( @vars ) {
1168 0         0 my $set_defaults ;
1169 0         0 foreach my $var ( @vars ) {
1170 0 0       0 if ( $var =~ /^:def\w*$/ ) { $set_defaults = 1 ; next ;}
  0         0  
  0         0  
1171            
1172             ##print STDOUT ">> $var\n" ;
1173            
1174 0         0 my ($t , $n) = ( $var =~ /^(\W)(.*)/s ) ;
1175 0 0       0 $this->{TRACK_VARS}{$root}{$n}{g} = \*{$root.'::'.$n} if !$this->{TRACK_VARS}{$root}{$n}{g} ;
  0         0  
1176            
1177 0 0       0 next if $this->{TRACK_VARS}{$root}{$n}{$t} ;
1178            
1179 0 0       0 push( @{$this->{TRACK_VARS_LIST}} , $var) if $world == $this ;
  0         0  
1180            
1181 0 0 0     0 if ( $root eq $this->{ROOT} && $t ne '>' && $t ne '<' && $t ne '*' ) {
    0 0        
      0        
1182 0 0       0 $this->{TRACK_VARS}{$root}{$n}{$t} = \${$root.'::'.$n} if $t eq '$' ;
  0         0  
1183 0 0       0 $this->{TRACK_VARS}{$root}{$n}{$t} = \@{$root.'::'.$n} if $t eq '@' ;
  0         0  
1184 0 0       0 $this->{TRACK_VARS}{$root}{$n}{$t} = \%{$root.'::'.$n} if $t eq '%' ;
  0         0  
1185             }
1186             elsif ( $t eq '*' ) {
1187 0         0 my $glob = 'G' . ++$TRACK_GLOB_X ;
1188 0         0 push( @{$this->{TRACK_GLOBS}} , $glob) ;
  0         0  
1189 0         0 *{$TRACK_GLOBS_BASE . $glob} = \*{$root.'::'.$n} ;
  0         0  
  0         0  
1190 0         0 $this->{TRACK_VARS}{$root}{$n}{$t} = \*{$TRACK_GLOBS_BASE . $glob} ;
  0         0  
1191             }
1192             else {
1193 0         0 $this->{TRACK_VARS}{$root}{$n}{$t} = 1 ;
1194             }
1195             }
1196            
1197 0 0 0     0 if ( $set_defaults && (!$this->{TRACK_VARS_DEF} || $world != $this) ) {
      0        
1198 0 0       0 $this->{TRACK_VARS_DEF} = 1 if $world == $this ;
1199 0         0 $this->track_vars($world , @TRACK_VARS_DEF) ;
1200             }
1201             }
1202            
1203 0         0 return @{$this->{TRACK_VARS_LIST}} ;
  0         0  
1204             }
1205            
1206             ####################
1207             # SET_TRACKED_VARS #
1208             ####################
1209            
1210             sub set_tracked_vars {
1211 0     0 0 0 my $this = shift ;
1212 0 0       0 my $track_vars = ref($_[0]) eq 'HASH' ? shift : $this->{TRACK_VARS} ;
1213 0 0       0 return if !$track_vars ;
1214            
1215 0         0 my ( $pack_root ) = @_ ;
1216 0 0       0 $pack_root = $pack_root->{ROOT} if ref($pack_root) ;
1217            
1218 0   0     0 $pack_root ||= $this->{ROOT} ;
1219            
1220             ##print main::STDOUT "====================== $this->{ROOT} >> $pack_root\n" ;
1221            
1222 0         0 foreach my $track_root ( keys %$track_vars ) {
1223            
1224 0 0 0     0 if (
      0        
1225             $this->{TRACK_ONLY_LINKED}{$track_root}
1226             &&
1227             (
1228             ( $this->{TRACK_ONLY_LINKED}{$track_root} eq '1' && !$this->{LINKED_WORLDS}{$track_root} )
1229             ||
1230             ( $this->{TRACK_ONLY_LINKED}{$track_root} ne '1' && !$this->{LINKED_WORLDS}{ $this->{TRACK_ONLY_LINKED}{$track_root} } )
1231             )
1232 0         0 ) { next ;}
1233            
1234 0 0       0 if ($track_root ne $pack_root) {
1235 0         0 *{"$pack_root\::$track_root\::"} = \*{"$pack_root\::"} ;
  0         0  
  0         0  
1236             ##print main::STDOUT "LINK>> $pack_root\::$track_root >> $pack_root\n" ;
1237 0         0 _rebless($track_root , $pack_root) ;
1238             }
1239            
1240 0         0 foreach my $n ( keys %{ $$track_vars{$track_root} } ) {
  0         0  
1241 0         0 my $glob = $$track_vars{$track_root}{$n}{g} ;
1242            
1243             ##print main::STDOUT "TRACK>> $track_root\::$n >> $pack_root\::$n \n" ;
1244            
1245 0 0       0 if ( $$track_vars{$track_root}{$n}{'*'} ) {
    0          
    0          
1246 0         0 *$glob = \*{$pack_root.'::'.$n} ;
  0         0  
1247             }
1248             elsif ( $$track_vars{$track_root}{$n}{'>'} ) {
1249 0 0       0 if ($] < 5.007) {
1250 0         0 untie *{"$track_root\::$n"} ;
  0         0  
1251 0         0 tie( *$glob => 'Safe::World::stdoutsimple' , $track_root , \*{"$pack_root\::$n"} ) ;
  0         0  
1252             }
1253             else {
1254 0         0 *$glob = \*{"$pack_root\::$n"} ;
  0         0  
1255             }
1256             }
1257             elsif ( $$track_vars{$track_root}{$n}{'<'} ) {
1258 0         0 *$glob = \*{"$pack_root\::$n"} ;
  0         0  
1259             }
1260            
1261 0 0       0 *$glob = \${$pack_root.'::'.$n} if $$track_vars{$track_root}{$n}{'$'} ;
  0         0  
1262 0 0       0 *$glob = \@{$pack_root.'::'.$n} if $$track_vars{$track_root}{$n}{'@'} ;
  0         0  
1263 0 0       0 *$glob = \%{$pack_root.'::'.$n} if $$track_vars{$track_root}{$n}{'%'} ;
  0         0  
1264             }
1265             }
1266            
1267             }
1268            
1269             ######################
1270             # CLEAN_TRACKED_VARS #
1271             ######################
1272            
1273             sub clean_tracked_vars {
1274 1     1 0 2 my $this = shift ;
1275 1 50       5 return if !$this->{TRACK_VARS} ;
1276            
1277 0         0 my ($NULL , @NULL , %NULL) ;
1278 0         0 local(*NULL) ;
1279            
1280 0         0 foreach my $track_root ( keys %{ $this->{TRACK_VARS} } ) {
  0         0  
1281            
1282 0 0 0     0 if (
      0        
1283             $this->{TRACK_ONLY_LINKED}{$track_root}
1284             &&
1285             (
1286             ( $this->{TRACK_ONLY_LINKED}{$track_root} eq '1' && !$this->{LINKED_WORLDS}{$track_root} )
1287             ||
1288             ( $this->{TRACK_ONLY_LINKED}{$track_root} ne '1' && !$this->{LINKED_WORLDS}{ $this->{TRACK_ONLY_LINKED}{$track_root} } )
1289             )
1290 0         0 ) { next ;}
1291            
1292 0         0 foreach my $n ( keys %{ $this->{TRACK_VARS}{$track_root} } ) {
  0         0  
1293 0         0 my $glob = $this->{TRACK_VARS}{$track_root}{$n}{g} ;
1294            
1295 0         0 my $ref ;
1296            
1297 0 0       0 if ( $ref = $this->{TRACK_VARS}{$track_root}{$n}{'*'} ) {
    0          
    0          
1298 0         0 *$glob = \*$ref ;
1299             }
1300             elsif ( $this->{TRACK_VARS}{$track_root}{$n}{'>'} ) {
1301 0 0       0 if ( tied *{"$track_root\::$n"} ) {
  0         0  
1302 0         0 untie( *$glob ) ;
1303             }
1304             else {
1305 0         0 *$glob = \*NULL ;
1306             }
1307             }
1308             elsif ( $this->{TRACK_VARS}{$track_root}{$n}{'<'} ) {
1309 0         0 *$glob = \*NULL ;
1310             }
1311            
1312 0 0       0 if ( $ref = $this->{TRACK_VARS}{$track_root}{$n}{'$'} ) {
1313 0 0       0 *$glob = $ref eq '1' ? \$NULL : $ref ;
1314             }
1315 0 0       0 if ( $ref = $this->{TRACK_VARS}{$track_root}{$n}{'@'} ) {
1316 0 0       0 *$glob = $ref eq '1' ? \@NULL : $ref ;
1317             }
1318 0 0       0 if ( $ref = $this->{TRACK_VARS}{$track_root}{$n}{'%'} ) {
1319 0 0       0 *$glob = $ref eq '1' ? \%NULL : $ref ;
1320             }
1321            
1322             }
1323            
1324 0 0 0     0 if ( $this->{TRACK_DEPENDENCIES}{$track_root} || $track_root =~ /CACHE/ ) {
1325 0   0     0 my $root = $this->{TRACK_DEPENDENCIES}{$track_root} || $track_root ;
1326 0         0 my ($base , $leaf) = ( "main::$root\::" =~ /^(.*::)(\w+::)$/ ) ;
1327 0 0       0 if ( !defined *{$base}{HASH}{$leaf} ) {
  0         0  
1328 0         0 delete $this->{TRACK_VARS}{$root} ;
1329 0         0 delete $this->{TRACK_VARS}{$track_root} ;
1330 0         0 delete $this->{TRACK_DEPENDENCIES}{$track_root} ;
1331             }
1332             }
1333            
1334             }
1335            
1336 0         0 return 1 ;
1337             }
1338            
1339             ######################
1340             # CHECK_TRACK_DEPEND #
1341             ######################
1342            
1343             sub check_track_depend {
1344 0     0 0 0 my $this = shift ;
1345 0 0       0 return if !$this->{TRACK_VARS} ;
1346            
1347 0         0 foreach my $track_root ( keys %{ $this->{TRACK_VARS} } ) {
  0         0  
1348            
1349 0 0 0     0 if ( $this->{TRACK_DEPENDENCIES}{$track_root} || $track_root =~ /CACHE/ ) {
1350 0   0     0 my $root = $this->{TRACK_DEPENDENCIES}{$track_root} || $track_root ;
1351 0         0 my ($base , $leaf) = ( "main::$root\::" =~ /^(.*::)(\w+::)$/ ) ;
1352 0 0       0 if ( !defined *{$base}{HASH}{$leaf} ) {
  0         0  
1353 0         0 delete $this->{TRACK_VARS}{$root} ;
1354 0         0 delete $this->{TRACK_VARS}{$track_root} ;
1355 0         0 delete $this->{TRACK_DEPENDENCIES}{$track_root} ;
1356             }
1357             }
1358            
1359             }
1360            
1361 0         0 return 1 ;
1362             }
1363            
1364             #############
1365             # LINK_PACK #
1366             #############
1367            
1368             sub link_pack {
1369 0     0 1 0 my $this = shift ;
1370 0 0       0 if ( $this->{INSIDE} ) { return ;}
  0         0  
1371 0         0 my ( $pack ) = @_ ;
1372            
1373 0         0 my $pack_alise = $pack ;
1374 0         0 $pack_alise =~ s/^(?:$COMPARTMENT_NAME|$COMPARTMENT_NAME_CACHE)\d+::// ;
1375            
1376 0         0 my @packs = scanpacks( "$this->{ROOT}::$pack_alise" ) ;
1377            
1378 0         0 foreach my $packs_i ( reverse sort @packs ) {
1379 0 0       0 next if $packs_i eq "$this->{ROOT}::$pack_alise" ;
1380 0         0 my $pack_link = $packs_i ;
1381 0         0 $pack_link =~ s/^(?:$COMPARTMENT_NAME|$COMPARTMENT_NAME_CACHE)\d+::(?:$pack_alise:*)?// ;
1382 0         0 $pack_link = "$pack\::$pack_link" ;
1383 0         0 *{"$packs_i\::"} = *{"$pack_link\::"} ;
  0         0  
  0         0  
1384             }
1385            
1386 0         0 *{"$this->{ROOT}\::$pack_alise\::"} = *{"$pack\::"} ;
  0         0  
  0         0  
1387            
1388 0         0 $this->{LINKED_PACKS}{$pack_alise} = 1 ;
1389            
1390 0         0 return 1 ;
1391             }
1392            
1393             ###############
1394             # UNLINK_PACK #
1395             ###############
1396            
1397             sub unlink_pack {
1398 0     0 1 0 my $this = shift ;
1399 0 0       0 if ( $this->{INSIDE} ) { return ;}
  0         0  
1400 0         0 my ( $pack ) = @_ ;
1401            
1402 0         0 my $packname = $this->{ROOT} ;
1403            
1404 0         0 *{"$packname\::$pack\::"} = *{"$packname\::PACKNULL::"} ;
  0         0  
  0         0  
1405 0         0 undef %{"$packname\::$pack\::"} ;
  0         0  
1406 0         0 undef *{"$packname\::$pack\::"} ;
  0         0  
1407 0         0 return 1 ;
1408             }
1409            
1410             ###################
1411             # UNLINK_PACK_ALL #
1412             ###################
1413            
1414             sub unlink_pack_all {
1415 1     1 1 2 my $this = shift ;
1416 1 50       3 if ( $this->{INSIDE} ) { return ;}
  0         0  
1417            
1418 1         3 my $packname = $this->{ROOT} ;
1419            
1420 1 50       3 if ( $_[0] ) {
1421 1         4 $this->{LINKED_PACKS}{$packname} = 1 ;
1422 1         2 $this->{LINKED_PACKS}{main} = 1 ;
1423             }
1424            
1425 1         2 foreach my $pack ( keys %{$this->{LINKED_PACKS}} ) {
  1         3  
1426 2         3 *{"$packname\::$pack\::"} = *{"$packname\::PACKNULL::"} ;
  2         41  
  2         26  
1427 2         8 undef %{"$packname\::$pack\::"} ;
  2         13  
1428 2         4 undef *{"$packname\::$pack\::"} ;
  2         19  
1429             }
1430            
1431 1         2 $this->{LINKED_PACKS} = {} ;
1432 1         2 return 1 ;
1433             }
1434            
1435             ##################
1436             # SET_SHAREDPACK #
1437             ##################
1438            
1439             sub set_sharedpack {
1440 0     0 1 0 my $this = shift ;
1441 0         0 my ( @packs ) = @_ ;
1442            
1443             #$this->track_vars(':defaults') if !$this->{TRACK_VARS_DEF} && !$this->{SHAREDPACK} || !@{$this->{SHAREDPACK}} ;
1444            
1445 0         0 my @shared_pack = @{$this->{SHAREDPACK}} ;
  0         0  
1446 0         0 my %shared_pack = map { ("$_\::" => 1) } @shared_pack ;
  0         0  
1447            
1448 0         0 foreach my $packs_i ( @packs ) {
1449 0         0 $packs_i =~ s/[^\w:\.]//gs ;
1450 0         0 $packs_i =~ s/[:\.]+/::/ ;
1451 0         0 $packs_i =~ s/^(?:main)?::// ;
1452 0         0 $packs_i =~ s/::$// ;
1453            
1454 0 0 0     0 next if ($shared_pack{$packs_i} || $packs_i eq '') ;
1455            
1456 0         0 push(@{$this->{SHAREDPACK}} , $packs_i) ;
  0         0  
1457            
1458 0         0 my $pm = $packs_i ;
1459 0         0 $pm =~ s/::/\//g ;
1460 0         0 $pm .= '.pm' ;
1461 0         0 $this->{SHAREDPACK_PM}{$packs_i} = $pm ;
1462             }
1463            
1464 0         0 return 1 ;
1465             }
1466            
1467             ####################
1468             # UNSET_SHAREDPACK #
1469             ####################
1470            
1471             sub unset_sharedpack {
1472 0     0 1 0 my $this = shift ;
1473 0         0 my ( @packs ) = @_ ;
1474            
1475 0         0 my %packs = map { ($_ => 1) } @packs ;
  0         0  
1476            
1477 0         0 my @sets ;
1478 0         0 foreach my $shared_pack_i ( @{$this->{SHAREDPACK}} ) {
  0         0  
1479 0 0       0 if ( !$packs{$shared_pack_i} ) { push(@sets , $shared_pack_i) ;}
  0         0  
1480 0         0 else { delete $this->{SHAREDPACK_PM}{$shared_pack_i} ;}
1481             }
1482            
1483 0         0 @{$this->{SHAREDPACK}} = @sets ;
  0         0  
1484            
1485 0         0 return 1 ;
1486             }
1487            
1488             ##############
1489             # USE_SHARED #
1490             ##############
1491            
1492             sub use_shared {
1493 0     0 1 0 my $this = shift ;
1494 0         0 my $module = shift ;
1495            
1496             ##print main::STDOUT "SHARE>> $module\n" ;
1497            
1498 0         0 my $pm = $module ;
1499 0         0 $pm =~ s/::/\//g ; $pm .= '.pm' ;
  0         0  
1500            
1501 0         0 my $SAFE_WORLD_selected ;
1502 0 0       0 if ( $NOW != $this ) {
1503 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($this) ; ## Safe::World::select->new($this) ;
1504             }
1505            
1506 0         0 my (%new_incs) ;
1507            
1508             {
1509 0 0       0 if ( $INC{$pm} ) { return "Module $module already cached!" ;}
  0         0  
  0         0  
1510            
1511 0         0 my %packs_prev = map { $_ => 1 } ( scanpacks( $this->{ROOT} ) ) ;
  0         0  
1512            
1513 0         0 my %inc_now = %INC ;
1514            
1515 0         0 my $use_cmd = "no strict ; require $module ;" ;
1516 0 0 0     0 if ( @_ && join(" ", @_) =~ /\S/s ) {
1517 0         0 $use_cmd .= " $module\::import('$module', qw\0 ". join(" ", @_) ." \0 ) if defined &$module\::import ;" ;
1518             }
1519            
1520 0         0 $this->eval_no_warn($use_cmd) ;
1521            
1522 0 0       0 if ( $@ ) {
1523 0         0 return "Error on loading $module\n$@" ;
1524             }
1525             else {
1526 0 0 0     0 foreach my $Key ( keys %INC ) { $new_incs{$Key} = $INC{$Key} if !$inc_now{$Key} && ($Key =~ /^\w.*?\.pm$/) ;}
  0         0  
1527            
1528 0         0 my @packs_now = scanpacks( $this->{ROOT} ) ;
1529            
1530 0         0 foreach my $packs_now_i ( @packs_now ) {
1531 0 0       0 next if $packs_prev{$packs_now_i} ;
1532            
1533 0         0 my $pm = $packs_now_i ;
1534 0         0 $pm =~ s/^\Q$this->{ROOT}\E::// ;
1535 0         0 $pm =~ s/::/\//gs ; $pm .= '.pm' ;
  0         0  
1536            
1537 0 0       0 next if $new_incs{$pm} ;
1538            
1539 0         0 my $table = *{"$packs_now_i\::"}{HASH} ;
  0         0  
1540 0 0       0 next if !%$table ;
1541            
1542 0         0 my $has_non_pack ;
1543 0         0 foreach my $Key (sort keys %$table ) {
1544 0 0       0 if ( $Key !~ /::$/ ) { $has_non_pack = $Key ; last ;}
  0         0  
  0         0  
1545             }
1546 0 0       0 next if !$has_non_pack ;
1547            
1548 0         0 $new_incs{$pm} = '#not_from_file#' ;
1549             }
1550             }
1551             }
1552            
1553 0         0 my ( %inc , @link_pack ) ;
1554            
1555 0 0       0 if ( %new_incs ) {
1556 0         0 my (%base_set , @set_shared) ;
1557 0         0 foreach my $Key ( sort keys %new_incs ) {
1558 0 0       0 $inc{$Key} = '#shared#' if $new_incs{$Key} ne '#not_from_file#' ;
1559 0 0       0 $this->{USE_SHARED_INC}{$Key} = ($new_incs{$Key} eq '#not_from_file#') ? 2 : 1 ;
1560            
1561 0         0 my $module = $Key ;
1562 0         0 $module =~ s/[\\\/]/::/g ;
1563 0         0 $module =~ s/\.pm$// ;
1564            
1565 0         0 my @path = split("::" , $module) ;
1566            
1567 0         0 my $set ;
1568 0         0 while( @path ) {
1569 0 0       0 if ( $base_set{ join("::", @path) } ) { $set = 1 ; last ;}
  0         0  
  0         0  
1570 0         0 pop (@path) ;
1571             }
1572            
1573 0 0       0 next if $set ;
1574 0         0 $base_set{$module} = 1 ;
1575            
1576 0         0 push(@set_shared , $module) ;
1577            
1578 0         0 push(@link_pack , $this->{ROOT}."::$module") ;
1579             }
1580            
1581             ##print main::STDOUT "SETX>> @set_shared\n" ;
1582            
1583 0         0 $this->set_sharedpack(@set_shared) ;
1584             }
1585            
1586 0         0 return( \@link_pack , \%inc ) ;
1587             }
1588            
1589             ##############
1590             # LINK_WORLD #
1591             ##############
1592            
1593             sub link_world {
1594 0     0 1 0 my $this = shift ;
1595 0         0 my $world = shift ;
1596 0         0 my $dont_touch_main = shift ;
1597            
1598 0 0 0     0 if ( $this->{INSIDE} || ref($world) ne 'Safe::World' || (!$this->{IS_CACHE} && $world->{WORLD_SHARED}) || $world->{INSIDE} ) { return ;}
  0   0     0  
      0        
      0        
1599            
1600 0         0 my $world_root = $world->{ROOT} ;
1601 0         0 my $root = $this->{ROOT} ;
1602            
1603 0 0 0     0 $world->track_vars(':defaults') if !$dont_touch_main && !$world->{TRACK_VARS_DEF} ;
1604            
1605             ########
1606            
1607 0         0 my @shared_pack = @{$world->{SHAREDPACK}} ;
  0         0  
1608 0         0 my %shared_pack = map { ("$_\::" => 1) } @shared_pack ;
  0         0  
1609            
1610 0         0 my $inc ;
1611 0 0       0 if ( $NOW == $this ) { $inc = \%INC ;}
  0         0  
1612 0         0 else { $inc = $this->{SHARING}{'%main::INC'}{IN} ;}
1613            
1614 0         0 my $world_inc ;
1615 0 0       0 if ( $NOW == $world ) { $world_inc = \%INC ;}
  0         0  
1616 0         0 else { $world_inc = $world->{SHARING}{'%main::INC'}{IN} ;}
1617            
1618 0         0 foreach my $shared_pack ( @shared_pack ) {
1619 0 0       0 if ( !$$inc{ $world->{SHAREDPACK_PM}{$shared_pack} } ) {
1620 0         0 $this->link_pack("$world_root\::$shared_pack") ;
1621             }
1622            
1623 0         0 my $base = $shared_pack ;
1624 0         0 $base =~ s/::/\//g ;
1625            
1626 0         0 foreach my $Key ( keys %$world_inc ) {
1627 0 0 0     0 if ( !$this->{USE_SHARED_INC}{$Key} && !$$inc{$Key} && $Key =~ /^(?:auto\/)?\Q$base\E(?:\/|\.)/ ) { $$inc{$Key} = '#shared#' ;}
  0   0     0  
1628             }
1629             }
1630            
1631 0         0 foreach my $Key ( keys %{ $world->{USE_SHARED_INC} } ) {
  0         0  
1632 0 0       0 $$inc{$Key} = '#shared#' if $world->{USE_SHARED_INC}{$Key} != 2 ;
1633             }
1634            
1635             ########
1636            
1637 0 0       0 if ( !$dont_touch_main ) {
1638 0         0 my $table = *{"$world_root\::"}{HASH} ;
  0         0  
1639            
1640 0         0 foreach my $Key ( keys %$table ) {
1641 0 0 0     0 if ( !$shared_pack{$Key} && $$table{$Key} =~ /^\*(?:main|$world_root)::/ && $Key !~ /^(?:.*?::)$/ && $Key !~ /[^\w:]/s) {
      0        
      0        
1642 0 0       0 next if tied( *{"$world_root\::$Key"} ) ;
  0         0  
1643 0         0 *{"$world_root\::WORLDSHARE::$Key"} = \${"$world_root\::$Key"} ;
  0         0  
  0         0  
1644 0         0 *{"$world_root\::WORLDSHARE::$Key"} = \@{"$world_root\::$Key"} ;
  0         0  
  0         0  
1645 0         0 *{"$world_root\::WORLDSHARE::$Key"} = \%{"$world_root\::$Key"} ;
  0         0  
  0         0  
1646 0 0       0 *{"$world_root\::WORLDSHARE::$Key"} = \&{"$world_root\::$Key"} if defined &{"$world_root\::$Key"} ;
  0         0  
  0         0  
  0         0  
1647 0         0 *{"$world_root\::WORLDSHAREGLOBS::$Key"} = \*{"$world_root\::$Key"} ;
  0         0  
  0         0  
1648            
1649 0         0 *{"$world_root\::$Key"} = \${"$root\::$Key"} ;
  0         0  
  0         0  
1650 0         0 *{"$world_root\::$Key"} = \@{"$root\::$Key"} ;
  0         0  
  0         0  
1651 0         0 *{"$world_root\::$Key"} = \%{"$root\::$Key"} ;
  0         0  
  0         0  
1652 0 0       0 *{"$world_root\::$Key"} = \&{"$root\::$Key"} if defined &{"$root\::$Key"} ;
  0         0  
  0         0  
  0         0  
1653 0         0 *{"$world_root\::$Key"} = \*{"$root\::$Key"} ;
  0         0  
  0         0  
1654             #$$table{$Key} = "*$root\::$Key" ;
1655             }
1656             }
1657             }
1658            
1659             ########
1660            
1661 0         0 $this->{LINKED_WORLDS}{ $world->{ROOT} } = 1 ;
1662 0         0 $world->{LINKED_WORLDS}{ $this->{ROOT} } = 1 ;
1663            
1664 0 0       0 $world->set_tracked_vars($this) if !$dont_touch_main ;
1665            
1666             ########
1667            
1668 0         0 push(@{$world->{WORLD_SHARED}} , $root) ;
  0         0  
1669            
1670 0         0 $WORLDS_LINKS{$this}{$world} = $world ;
1671            
1672 0         0 return 1 ;
1673             }
1674            
1675             ################
1676             # UNLINK_WORLD #
1677             ################
1678            
1679             sub unlink_world {
1680 0     0 1 0 my $this = shift ;
1681 0         0 my $world = shift ;
1682 0         0 my $dont_touch_main = shift ;
1683            
1684 0 0 0     0 if ( $this->{INSIDE} || ref($world) ne 'Safe::World' || !$world->{WORLD_SHARED} || $world->{INSIDE} ) { return ;}
  0   0     0  
      0        
1685            
1686 0         0 my $world_root = $world->{ROOT} ;
1687 0         0 my $root = $this->{ROOT} ;
1688            
1689             ########
1690            
1691 0         0 my @shared_pack = @{$world->{SHAREDPACK}} ;
  0         0  
1692 0         0 my %shared_pack = map { ("$_\::" => 1) } @shared_pack ;
  0         0  
1693            
1694 0         0 my $inc ;
1695 0 0       0 if ( $NOW == $this ) { $inc = \%INC ;}
  0         0  
1696 0         0 else { $inc = $this->{SHARING}{'%main::INC'}{IN} ;}
1697            
1698 0         0 my $world_inc ;
1699 0 0       0 if ( $NOW == $world ) { $world_inc = \%INC ;}
  0         0  
1700 0         0 else { $world_inc = $world->{SHARING}{'%main::INC'}{IN} ;}
1701            
1702 0         0 my $track_this ;
1703            
1704 0         0 foreach my $shared_pack ( @shared_pack ) {
1705 0         0 $this->unlink_pack($shared_pack) ;
1706            
1707 0         0 my $base = $shared_pack ;
1708 0         0 $base =~ s/::/\//g ;
1709 0         0 foreach my $Key ( keys %$inc ) {
1710 0 0       0 if ( $Key =~ /^(?:auto\/)?\Q$base\E(?:\/|\.)/ ) {
    0          
1711 0 0 0     0 if (!$$world_inc{$Key} && $$inc{$Key} ne '#shared#' && $world->{USE_SHARED_INC}{$Key} != 2 && $world->{USE_SHARED_INC}{"$base.pm"} != 2) {
      0        
      0        
1712 0         0 $$world_inc{$Key} = $$inc{$Key} ;
1713 0         0 $track_this = 1 ;
1714             }
1715 0         0 delete $$inc{$Key} ;
1716             }
1717 0         0 elsif ( $$inc{$Key} eq '#shared#' ) { delete $$inc{$Key} ;}
1718             }
1719             }
1720            
1721             ########
1722            
1723 0 0       0 $world->clean_tracked_vars if !$dont_touch_main ;
1724            
1725 0         0 delete $this->{LINKED_WORLDS}{ $world->{ROOT} } ;
1726 0         0 delete $world->{LINKED_WORLDS}{ $this->{ROOT} } ;
1727            
1728 0 0 0     0 if ( !$dont_touch_main && $track_this ) {
1729 0         0 $world->track_vars( $this , ':defaults' ) ;
1730             }
1731            
1732             ########
1733            
1734 0 0       0 if ( !$dont_touch_main ) {
1735 0         0 my $table = *{"$world_root\::"}{HASH} ;
  0         0  
1736            
1737 0         0 foreach my $Key ( keys %$table ) {
1738 0 0 0     0 if ( !$shared_pack{$Key} && $$table{$Key} =~ /^\*(?:main|$root)::(.*)/ && $Key !~ /^(?:.*?::)$/ && $Key !~ /[^\w:]/s) {
      0        
      0        
1739 0 0       0 next if tied( *{"$world_root\::$Key"} ) ;
  0         0  
1740            
1741             #$$table{$Key} = "*$world_root\::WORLDSHARE::$1" ;
1742 0         0 *{"$world_root\::$Key"} = \*{"$world_root\::WORLDSHAREGLOBS::$Key"} ;
  0         0  
  0         0  
1743            
1744 0         0 *{"$world_root\::$Key"} = \${"$world_root\::WORLDSHARE::$Key"} ;
  0         0  
  0         0  
1745 0         0 *{"$world_root\::$Key"} = \@{"$world_root\::WORLDSHARE::$Key"} ;
  0         0  
  0         0  
1746 0         0 *{"$world_root\::$Key"} = \%{"$world_root\::WORLDSHARE::$Key"} ;
  0         0  
  0         0  
1747 0 0       0 *{"$world_root\::$Key"} = \&{"$world_root\::WORLDSHARE::$Key"} if defined &{"$world_root\::WORLDSHARE::$Key"} ;
  0         0  
  0         0  
  0         0  
1748             }
1749             }
1750             }
1751            
1752             ########
1753            
1754 0         0 pop @{$world->{WORLD_SHARED}} ;
  0         0  
1755 0 0       0 $world->{WORLD_SHARED} = undef if !@{$world->{WORLD_SHARED}} ;
  0         0  
1756            
1757 0         0 delete $WORLDS_LINKS{$this}{$world} ;
1758            
1759 0 0 0     0 $world->track_vars(':defaults') if !$dont_touch_main && !$world->{TRACK_VARS_DEF} && $world->{SHAREDPACK} && @{$world->{SHAREDPACK}} ;
  0   0     0  
      0        
1760            
1761 0         0 return 1 ;
1762             }
1763            
1764             #####################
1765             # UNLINK_ALL_WORLDS #
1766             #####################
1767            
1768             sub unlink_all_worlds {
1769 1     1 1 2 my $this = shift ;
1770 1 50 33     11 if ( $this->{INSIDE} || !$WORLDS_LINKS{$this} ) { return ;}
  1         3  
1771            
1772 0         0 my @unlink_packs ;
1773            
1774 0         0 foreach my $Key ( keys %{ $WORLDS_LINKS{$this} } ) {
  0         0  
1775 0         0 push(@unlink_packs , $WORLDS_LINKS{$this}{$Key}->{ROOT} ) ;
1776 0         0 $this->unlink_world( $WORLDS_LINKS{$this}{$Key} ) ;
1777             }
1778            
1779 0         0 delete $WORLDS_LINKS{$this} ;
1780            
1781 0         0 return @unlink_packs ;
1782             }
1783            
1784             #############
1785             # SCANPACKS #
1786             #############
1787            
1788             sub scanpacks {
1789 1 50 33 1 1 11 if ( ref($_[0]) && ( $_[0]->{INSIDE} || $NOW == $_[0] ) ) { return ;}
  0   33     0  
1790 1 50       8 my $scan = $SCOPE_Safe_World_ScanPack->NEW( ref($_[0]) ? $_[0]->{ROOT} : $_[0] ) ; ## Safe::World::ScanPack->new( ref($_[0]) ? $_[0]->{ROOT} : $_[0] ) ;
1791 1         5 return reverse $scan->packages ;
1792             }
1793            
1794             ##################
1795             # SCANPACK_TABLE #
1796             ##################
1797            
1798             sub scanpack_table {
1799 0 0   0 1 0 my $this = ref($_[0]) ? shift : undef ;
1800 0 0 0     0 if ( ref($this) && ( $this->{INSIDE} || $NOW == $this ) ) { return ;}
  0   0     0  
1801            
1802 0         0 my ( $packname ) = @_ ;
1803            
1804 0 0       0 $packname = $this->{ROOT} . "::$packname" if $this ;
1805            
1806 0 0       0 $packname .= '::' unless $packname =~ /::$/ ;
1807 1     1   11 no strict "refs" ;
  1         3  
  1         49  
1808 0         0 my $package = *{$packname}{HASH} ;
  0         0  
1809 0 0       0 return unless defined $package ;
1810            
1811 1     1   5 no warnings ;
  1         2  
  1         2452  
1812 0         0 local $^W = 0 ;
1813            
1814 0         0 my @table ;
1815            
1816             my $fullname ;
1817 0         0 foreach my $symb ( keys %$package ) {
1818 0         0 $fullname = "$packname$symb" ;
1819 0 0 0     0 if ( $symb !~ /::$/ && ($symb !~ /[^\w:]/ || $symb =~ /^\W\w?$/ ) ) {
      0        
1820 0         0 my $ok ;
1821 0 0       0 if (defined $$fullname) { push(@table , "\$$fullname") ; $ok = 1 ;}
  0         0  
  0         0  
1822 0 0       0 if (defined %$fullname) { push(@table , "\%$fullname") ; $ok = 1 ;}
  0         0  
  0         0  
1823 0 0       0 if (defined @$fullname) { push(@table , "\@$fullname") ; $ok = 1 ;}
  0         0  
  0         0  
1824 0 0       0 if (defined &$fullname) { push(@table , "\&$fullname") ; $ok = 1 ;}
  0         0  
  0         0  
1825 0 0 0     0 if (*{$fullname}{IO} && fileno $fullname) {
  0         0  
1826 0         0 push(@table , "\*$fullname") ; $ok = 1 ;
  0         0  
1827             }
1828 0 0       0 if (!$ok) { push(@table , "\$$fullname") ;}
  0         0  
1829             }
1830             }
1831            
1832 0         0 return( @table ) ;
1833             }
1834            
1835             ########
1836             # WARN #
1837             ########
1838            
1839             sub warn {
1840 0     0 1 0 my $this = shift ;
1841 0 0       0 return if $this->{NO_IO} ;
1842            
1843 0 0 0     0 return if ($this->{TIESTDERR}->{LAST_ERROR} eq $_[0] || $_[0] =~ /#CORE::GLOBAL::exit#/ ) ;
1844            
1845 0         0 my @call = caller($_[1]) ;
1846            
1847 0         0 my %keys = (
1848             package => 0 ,
1849             file => 1 ,
1850             line => 2 ,
1851             sub => 3 ,
1852             evaltext => 6 ,
1853             ) ;
1854            
1855 0         0 my $caller ;
1856            
1857 0         0 foreach my $Key (sort { $keys{$a} <=> $keys{$b} } keys %keys ) {
  0         0  
1858 0         0 my $val = $call[$keys{$Key}] ;
1859 0 0       0 next if $val eq '' ;
1860 0         0 my $s = '.' x (7 - length($Key)) ;
1861 0 0       0 $val = "\"$val\"" if $val =~/\s/s ;
1862 0         0 $caller .= " $Key$s: $val\n" ;
1863             }
1864            
1865             #my $caller = qq`package="$call[0]" ; file="$call[1]" ; line="$call[2]" ; sub="$call[3]" ; evaltext="$call[6]"`;
1866            
1867 0         0 $this->print_stderr("$_[0] CALLER(\n$caller)\n") ;
1868             }
1869            
1870             #########
1871             # PRINT #
1872             #########
1873            
1874             sub print {
1875 0     0 1 0 my $this = shift ;
1876 0 0       0 return if $this->{NO_IO} ;
1877            
1878 0         0 my $SAFE_WORLD_selected ;
1879 0 0       0 if ( $NOW != $this ) {
1880 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($this) ; ## Safe::World::select->new($this) ;
1881             }
1882            
1883 0         0 $this->{TIESTDOUT}->print(@_) ;
1884             }
1885            
1886             ################
1887             # PRINT_STDOUT #
1888             ################
1889            
1890 0     0 1 0 sub print_stdout { &print ;}
1891            
1892             ################
1893             # PRINT_STDERR #
1894             ################
1895            
1896             sub print_stderr {
1897 0     0 1 0 my $this = shift ;
1898 0 0       0 return if $this->{NO_IO} ;
1899            
1900 0         0 my $SAFE_WORLD_selected ;
1901 0 0       0 if ( $NOW != $this ) {
1902 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($this) ; ## Safe::World::select->new($this) ;
1903             }
1904            
1905 0         0 $this->{TIESTDERR}->print(@_) ;
1906             }
1907            
1908             ################
1909             # PRINT_HEADER #
1910             ################
1911            
1912             sub print_header {
1913 0     0 1 0 my $this = shift ;
1914 0 0       0 return if $this->{NO_IO} ;
1915            
1916 0         0 my $SAFE_WORLD_selected ;
1917 0 0       0 if ( $NOW != $this ) {
1918 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($this) ; ## Safe::World::select->new($this) ;
1919             }
1920            
1921 0         0 $this->{TIESTDOUT}->print_headout(@_) ;
1922             }
1923            
1924             ###################
1925             # REDIRECT_STDOUT #
1926             ###################
1927            
1928             sub redirect_stdout {
1929 0     0 1 0 my $this = shift ;
1930 0 0       0 return if $this->{NO_IO} ;
1931            
1932 0         0 my ( $ref ) = @_ ;
1933 0 0       0 return if ref($ref) ne 'SCALAR' ;
1934            
1935 0 0       0 push( @{ $this->{TIESTDOUT}->{REDIRECT_STACK} } , $this->{TIESTDOUT}->{REDIRECT} ) if $this->{TIESTDOUT}->{REDIRECT} ;
  0         0  
1936 0         0 $this->{TIESTDOUT}->{REDIRECT} = $ref ;
1937             }
1938            
1939             ##################
1940             # RESTORE_STDOUT #
1941             ##################
1942            
1943             sub restore_stdout {
1944 0     0 1 0 my $this = shift ;
1945 0 0       0 return if $this->{NO_IO} ;
1946            
1947 0 0       0 $this->{TIESTDOUT}->{REDIRECT} = @{ $this->{TIESTDOUT}->{REDIRECT_STACK} } ? pop( @{ $this->{TIESTDOUT}->{REDIRECT_STACK} } ) : undef ;
  0         0  
  0         0  
1948             }
1949            
1950             #############
1951             # BLOCK IOS #
1952             #############
1953            
1954 0 0   0 1 0 sub block_stdout { $_[0]->{TIESTDOUT}->block if $_[0]->{TIESTDOUT} ;}
1955 0 0   0 1 0 sub unblock_stdout { $_[0]->{TIESTDOUT}->unblock if $_[0]->{TIESTDOUT} ;}
1956            
1957 0 0   0 1 0 sub block_stderr { $_[0]->{TIESTDERR}->block if $_[0]->{TIESTDERR} ;}
1958 0 0   0 1 0 sub unblock_stderr { $_[0]->{TIESTDERR}->unblock if $_[0]->{TIESTDERR} ;}
1959            
1960             #########
1961             # FLUSH #
1962             #########
1963            
1964             sub flush {
1965 1     1 1 3 my $this = shift ;
1966 1 50       7 return if $this->{NO_IO} ;
1967            
1968 0         0 my ( $set ) = @_ ;
1969            
1970 0 0       0 if ( $#_ == 0 ) {
1971 0 0       0 if ( $set ) { $this->set('$|',1) ;}
  0         0  
1972 0         0 else { $this->set('$|',0) ;}
1973             }
1974            
1975 0 0       0 $this->{TIESTDOUT}->flush if $this->{TIESTDOUT} ;
1976             }
1977            
1978             ###################
1979             # CLOSE_TIESTDOUT #
1980             ###################
1981            
1982             sub close_tiestdout {
1983 1     1 1 2 my $this = shift ;
1984 1 50       5 return if $this->{NO_IO} ;
1985            
1986 0         0 my $SAFE_WORLD_selected ;
1987 0 0       0 if ( $NOW != $this ) {
1988 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($this) ; ## Safe::World::select->new($this) ;
1989             }
1990            
1991 0         0 $this->{TIESTDOUT}->CLOSE ;
1992             }
1993            
1994             ###################
1995             # CLOSE_TIESTDERR #
1996             ###################
1997            
1998             sub close_tiestderr {
1999 1     1 1 3 my $this = shift ;
2000 1 50       5 return if $this->{NO_IO} ;
2001            
2002 0         0 my $SAFE_WORLD_selected ;
2003 0 0       0 if ( $NOW != $this ) {
2004 0         0 $SAFE_WORLD_selected = $SCOPE_Safe_World_select->NEW($this) ; ## Safe::World::select->new($this) ;
2005             }
2006            
2007 0         0 $this->{TIESTDERR}->CLOSE ;
2008             }
2009            
2010             #########
2011             # CLOSE #
2012             #########
2013            
2014             sub close {
2015 1     1 1 10 my $this = shift ;
2016            
2017 1         4 $this->{EXIT} = undef ;
2018            
2019 1         6 $this->close_tiestdout ;
2020 1         4 $this->close_tiestderr ;
2021            
2022 1         7 $this->set('$SAFEWORLD',\undef) ;
2023 1         7 $this->flush(1) ;
2024            
2025 1         2 $this->{EXIT} = 1 ;
2026            
2027 1         1 return 1 ;
2028             }
2029            
2030             sub _root_is_tracked {
2031 0     0   0 my ( @roots ) = @_ ;
2032            
2033 0         0 foreach my $world_root ( keys %{ $SAFEWORLDS_TABLE->{POOL} } ) {
  0         0  
2034 0         0 my $world = $SAFEWORLDS_TABLE->{POOL}{$world_root} ;
2035 0 0       0 if ( !$world ) {
2036 0         0 delete $SAFEWORLDS_TABLE->{POOL}{$world_root} ;
2037 0         0 next ;
2038             }
2039            
2040 0         0 foreach my $track_root ( %{ $world->{TRACK_VARS} } ) {
  0         0  
2041 0         0 foreach my $roots_i ( $world_root , @roots ) {
2042 0 0       0 return 1 if $track_root eq $roots_i ;
2043             }
2044             }
2045             }
2046 0         0 return undef ;
2047             }
2048            
2049             ###########
2050             # DESTROY #
2051             ###########
2052            
2053             sub DESTROY {
2054             my $this = shift ;
2055             return if $this->{DESTROIED} ;
2056            
2057             ##my @call = caller(1) ;
2058             ##print main::STDOUT "DESTSAFE>> $this->{ROOT} [@call]\n" ;
2059            
2060             $this->unlink_all_worlds ;
2061             $this->close ;
2062            
2063             untie *{"$this->{ROOT}\::STDOUT"} ;
2064             untie *{"$this->{ROOT}\::STDERR"} ;
2065            
2066             $this->clean_tracked_vars ;
2067            
2068             if ( ref($this->{TRACK_GLOBS}) eq 'ARRAY' ) {
2069             local(*NULL) ;
2070             my $glob ;
2071             foreach my $glob_i ( @{$this->{TRACK_GLOBS}} ) {
2072             $glob = $TRACK_GLOBS_BASE . $glob_i ;
2073             *{$glob} = \*NULL ;
2074             undef *{$glob} ;
2075             delete *{$TRACK_GLOBS_BASE}{HASH}{$glob_i} ;
2076             #print "GLOBS>> $TRACK_GLOBS_BASE\::$glob_i\n" ;
2077             }
2078             }
2079             if ( $BLESS_TABLE->{$this->{ROOT}} && !_root_is_tracked( $this->{ROOT} ) ) {
2080             ##print "DEST>> $this->{ROOT}\n" ;
2081             foreach my $ids_i ( keys %{ $BLESS_TABLE->{$this->{ROOT}} } ) {
2082             delete $BLESS_TABLE->{POOL}{$ids_i} ;
2083             }
2084             }
2085            
2086             $this->unshare_vars ;
2087            
2088             $this->{DESTROIED} = 1 ;
2089            
2090             $this->unlink_pack_all(1) ;
2091            
2092             $this->CLEAN ;
2093            
2094             }
2095            
2096             #########
2097             # CLEAN #
2098             #########
2099            
2100             sub CLEAN {
2101 1     1 1 2 my $this = shift ;
2102 1 50 33     10 return if ($this->{CLEANNED} || $this->{NO_CLEAN} || $NOW == $this ) ;
      33        
2103            
2104 1         3 $this->{CLEANNED} = 1 ;
2105            
2106 1         5 $this->DESTROY ;
2107            
2108             ## Too slow to unshare the variables, since you change Symbol Table.
2109             ## Also too slow to use Safe::World::select. Better save and reset.
2110            
2111             ############ SAVE main:: SHAREDS
2112 1         1 foreach my $var ( keys %{ $this->{SHARING} } ) {
  1         9  
2113 0         0 my ($var_tp,$var_name) = ( $var =~ /([\$\@\%\*])(\S+)/ ) ;
2114 0         0 $var_name =~ s/^{'(\S+)'}$/$1/ ;
2115            
2116 0 0       0 if ($var_tp eq '$') {
    0          
    0          
    0          
2117 0         0 my $scalar = ${$var_name} ;
  0         0  
2118 0         0 $this->{SHARING}{$var} = \$scalar ;
2119             }
2120 0         0 elsif ($var_tp eq '@') { $this->{SHARING}{$var} = [@{$var_name}] ;}
  0         0  
2121 0         0 elsif ($var_tp eq '%') { $this->{SHARING}{$var} = {%{$var_name}} ;}
  0         0  
2122 0         0 elsif ($var_tp eq '*') { $this->{SHARING}{$var} = \*{$var_name} ;}
  0         0  
2123             }
2124             ############
2125            
2126 1         3 my $packname = $this->{ROOT} ;
2127            
2128 1         5 foreach my $packs_i ( $this->scanpacks ) {
2129 4         36 $this->undef_pack($packs_i , $this->{DONOT_CLEAN} ) ;
2130             }
2131            
2132             ##$this->undef_pack("Safe::World::GLOBS::$packname") ;
2133            
2134 1         4 my $main_packname = "main::$packname\::" ;
2135            
2136 1         2 undef %{*{$main_packname}{HASH}} ;
  1         1  
  1         6  
2137 1         2 undef *{$main_packname} ;
  1         7  
2138 1         7 *{$main_packname} = *{"PACKNULL::"} ;
  1         7  
  1         3  
2139 1         5 delete *{'main::'}{HASH}{"$packname\::"} ;
  1         10  
2140            
2141             ############ RESET main:: SHAREDS
2142 1         4 foreach my $var ( keys %{ $this->{SHARING} } ) {
  1         5  
2143 0         0 my ($var_tp,$var_name) = ( $var =~ /([\$\@\%\*])(\S+)/ ) ;
2144 0         0 $var_name =~ s/^{'(\S+)'}$/$1/ ;
2145            
2146 0 0       0 if ($var_tp eq '$') { ${$var_name} = ${ $this->{SHARING}{$var} } ;}
  0 0       0  
  0 0       0  
  0 0       0  
2147 0         0 elsif ($var_tp eq '@') { @{$var_name} = @{ $this->{SHARING}{$var} } ;}
  0         0  
  0         0  
2148 0         0 elsif ($var_tp eq '%') { %{$var_name} = %{ $this->{SHARING}{$var} } ;}
  0         0  
  0         0  
2149 0         0 elsif ($var_tp eq '*') { *{$var_name} = $this->{SHARING}{$var} ;}
  0         0  
2150             }
2151             ############
2152            
2153 1         128 return 1 ;
2154             }
2155            
2156             ##############
2157             # UNDEF_PACK #
2158             ##############
2159            
2160             sub undef_pack {
2161 4     4 0 7 my $this = shift ;
2162 4         9 my ( $packname , $donot_clean ) = @_ ;
2163            
2164             ##print main::STDOUT "UNDEFPACK>> $packname\n" ;
2165            
2166 4         5 $packname .= '::' ;
2167 1     1   6 no strict "refs" ;
  1         3  
  1         80  
2168 4         3 my $package = *{$packname}{HASH} ;
  4         10  
2169 4 50       10 return unless defined $package ;
2170            
2171 4         7 local(*NULL) ;
2172 4     0   17 my $tmp_sub = sub{} ;
  0         0  
2173            
2174 1     1   7 no warnings ;
  1         2  
  1         708  
2175 4         16 local $^W = 0 ;
2176            
2177             ## 'no warning' still have some warns on Perl-5.8.x
2178 4         10 my $prev_sigwarn = $SIG{__WARN__} ;
2179 4         7 my $prev_sigdie = $SIG{__DIE__} ;
2180 4     0   11 $SIG{__WARN__} = sub{} ;
  0         0  
2181 4     0   11 $SIG{__DIE__} = sub{} ;
  0         0  
2182 4         5 $IGNORE_EXIT = 1 ;
2183            
2184 4         4 my ($fullname) ;
2185 4         9 foreach my $symb ( keys %$package ) {
2186 13         14 $fullname = "$packname$symb" ;
2187 13 50 66     79 if ( $symb !~ /::$/ && $symb !~ /[^\w:]/ && $symb !~ /^[1-9\.]/ && (!$donot_clean || !$donot_clean->{$symb}) ) {
      33        
      33        
      33        
2188             ##print main::STDOUT "undef>> $packname >> $symb\n" ;
2189            
2190 8         8 eval {
2191 8 50       19 if (defined &$fullname) {
2192 0 0       0 if (my $p = prototype $fullname) { ++$EVALX ; *{$fullname} = eval "sub ($p) {}" ;}
  0         0  
  0         0  
  0         0  
2193 0         0 else { *{$fullname} = $tmp_sub ;}
  0         0  
2194 0         0 undef &$fullname ;
2195             }
2196            
2197 8 50       8 untie *{$fullname} if tied *{$fullname} ;
  0         0  
  8         27  
2198 8 100       9 if (*{$fullname}{IO}) { close $fullname ;}
  8         28  
  2         5  
2199            
2200             #if (defined @$fullname) { undef @$fullname ;}
2201 8 100       9 if (defined *{$fullname}{ARRAY}) {
  8         22  
2202 1 50       4 untie @$fullname if tied @$fullname ;
2203 1         3 undef @$fullname ;
2204             }
2205             #undef @$fullname ;
2206            
2207             #if (defined %$fullname) { undef %$fullname ;}
2208 8 100       8 if (defined *{$fullname}{HASH}) {
  8         21  
2209 1 50       3 untie %$fullname if tied %$fullname ;
2210 1         2 undef %$fullname ;
2211             }
2212             #undef %$fullname ;
2213            
2214             #if (defined $$fullname) { undef $$fullname ;}
2215 8 50       23 untie $$fullname if tied $$fullname ;
2216 8         11 undef $$fullname ;
2217            
2218 8         8 undef *{$fullname} ;
  8         32  
2219             };
2220             }
2221             #else { print main::STDOUT "** $packname>> $symb >> $fullname\n" ;}
2222             }
2223            
2224            
2225 4         5 undef %{*{$packname}{HASH}} ;
  4         3  
  4         26  
2226 4         9 undef *{$packname} ;
  4         23  
2227            
2228 4         10 $IGNORE_EXIT = undef ;
2229 4         8 $SIG{__WARN__} = $prev_sigwarn ;
2230 4         11 $SIG{__DIE__} = $prev_sigdie ;
2231            
2232 4         24 return 1 ;
2233             }
2234            
2235             sub END {
2236            
2237 1     1   1 if (0) {
2238             foreach my $Key ( sort {$a <=> $b} keys %{ $BLESS_TABLE->{POOL} } ) {
2239             my $Value = $BLESS_TABLE->{POOL}{$Key} ;
2240             next if !$Value ;
2241             my $package = *{ ref($Value) . '::' }{HASH} ;
2242             my $defin = %$package ? 1 : 0 ;
2243             print ">>> [$defin] $Key = $Value\n" ;
2244            
2245             foreach my $base ( sort keys %$BLESS_TABLE ) {
2246             next if $base eq 'POOL' ;
2247             print " $base\n" if exists $BLESS_TABLE->{$base}{$Key} ;
2248             }
2249            
2250             }
2251             }
2252            
2253 1         2 %{ $BLESS_TABLE->{POOL} } = () ;
  1         11  
2254 1         13 $BLESS_TABLE = undef ;
2255 1         5 %{ $SAFEWORLDS_TABLE->{POOL} } = () ;
  1         12  
2256 1         8 $SAFEWORLDS_TABLE = undef ;
2257             }
2258            
2259             #######
2260             # END #
2261             #######
2262            
2263             1;
2264            
2265             __END__