We have at work a Perl script which is used to perform maintenance. I needed to modify it to handle more tasks. The problem is that the script is compiled and the source was lost long ago.
I tried to use B::Deparse in order to recreate the file but Deparse is not perfect and the output is broken (and very large ~5000 lines of deparsed code).
After reading the deparsed code I found that I need to modify one function. The compiled script loads a plain-text script module, so I altered the module to override the function and perform the task I need it to perform. The problem now is that I cannot access the main script "my" variables.
Here's an example:
# main.pl
my $a = 1;
sub call_me {
print "unmodified";
}
use MOD;
call_me;
MOD.pm
package MOD;
main::{'call_me'} = sub {
print "\$main::a = $main::a\n";
}
The result is: "$main::a =
" instead of getting the real value.
Thanks in advance.
The short answer is that variables declared with my
are not accessible outside of their lexical scope. If you can't change the declaration to "our" (because of the crazy "compiled" nature of the original script), you aren't yet out of luck. Perl almost always provides a way around these types of things.
In this case, you can install the PadWalker module and do something like this (here's a tweaked version of your originally posted code):
The main.pl
script:
my $a = 1;
sub call_me {
print "unmodified: $a";
}
use MOD;
call_me;
And then your module:
package MOD;
# closed_over($code_ref) returns a hash ref keyed on variable
# name(including sigil) with values as references to the value
# of those variables
use PadWalker qw(closed_over);
{
# grab a reference to the original sub
my $orig = \&main::call_me;
# no need to use the symbol table, a glob reference is fine
# but you can't use sub main::call_me { ... } either
*main::call_me = sub {
my $a = closed_over($orig)->{'$a'};
print "\$main::a = $$a\n";
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With