Using a subroutine from another file - perl

Consider:
File display.pl
disp{
my $p = shift;
print $p;
}
File temp.pl
require "display.pl";
$item = "asd";
&disp($item);
When I executed temp.pl, it gave an error:
can't find method "disp" without a package or a object reference at display.pl line 2.

You forgot to write sub before disp{ in display.pl, so Perl doesn't know that you are trying to define a function.
Always use strict and warnings, and you will avoid such problems. Also, as noted by #NEW, you need to end display.pl with a 1; because require requires that a file end with a true value.
Corrected, your code would be:
use strict;
use warnings;
sub disp {
my $p = shift;
print $p;
}
1;

Avoid errors by using
use strict ;
use warnings;
Note that you need the 1; at the end of the file like
sub disp{
my $p=shift;
print $p;
}
1;
This is because Perl needs the last expression in the file to return a true value.
If the require file (display.pl) is in another directory you will need to specify the absolute path:
You don't need to worry about recursive requiring (e.g. requiring a file that requires the current file), Perl will handle everything.
SEE ALSO
perldoc -f require and perldoc -q require and perldoc perlmod for better understanding.

Related

Perl disable shell access

Certain builtins like system and exec (as well as backticks) will use the shell (I think sh by default) if passed a single argument containing shell metacharacters. If I want to write a portable program that avoids making any assumptions about the underlying shell, is there a pragma or some other option I can use to either disable shell access or trigger a fatal error immediately?
I write about this extensively in Mastering Perl. The short answer is to use system in it's list form.
system '/path/to/command', #args;
This doesn't interpret any special characters in #args.
At the same time, you should enable taint checking to help catch bad data before you pass it to the system. See the perlsec documentation for details.
There are limited options to do this, keep in mind that these are core routines and completely disabling them may have some unexpected consequences. You do have a few options.
Override Locally
You can override system and exec locally by using the subs pragma, this will only effect the package into which you have imported the sub routine:
#!/usr/bin/env perl
use subs 'system';
sub system { die('Do not use system calls!!'); }
# .. more code here, note this will runn
my $out = system('ls -lah'); # I will die at this point, but not before
print $out;
Override Globally
To override globally, in the current perl process, you need to import your function into the CORE::GLOBAL pseudo-namespace at compile time:
#!/usr/bin/env perl
BEGIN {
*CORE::GLOBAL::system = sub {
die('Do not use system calls.');
};
*CORE::GLOBAL::exec = sub {
die('Do not use exec.');
};
*CORE::GLOBAL::readpipe = sub {
die('Do not use back ticks.');
};
}
#...
my $out = system('ls -lah'); # I will die at this point, but not before
print $out;
Prevent anything form running if in source
If you want to prevent any code running before getting to a system call you can include the following, note this is fairly loose in it's matching, I've written it to be easy to modify or update:
package Acme::Noshell;
open 0 or print "Can't execute '$0'\n" and exit;
my $source = join "", <0>;
die("Found back ticks in '$0'") if($source =~ m/^.*[^#].*\`/g);
die("Found 'exec' in '$0'") if($source =~ / exec\W/g);
die("Found 'system' in '$0'") if($source =~ / system\W/g);
1;
Which can be used as follows:
#!/usr/bin/env perl
use strict;
use warnings;
use Acme::Noshell;
print "I wont print because of the call below";
my $out = system('ls -lah');

Is there a way to mock the built-in require function in Perl?

I am developing an application that has to replace an existing mess of spaghetti-code piece by piece. To achieve this I have a dispatcher that runs required HTTP resources when a URI has been matched and otherwise uses the legacy HTTP resource class.
So, this legacy HTTP resource has to require the entry point file of the old system, and I'm trying to figure out how to test this process. The way I see it now is I would like to replace the original require function with a mock subroutine and check that it has been called with an appropriate file name.
Is this possible, and if not, maybe there is a better way to do it?
To override require in a single package:
use subs 'require'; # imports `require` so it can be overridden
sub require {print "mock require: #_\n"}
To override require globally:
BEGIN {
*CORE::GLOBAL::require = sub {print "mock require: #_\n"}
}
And then:
require xyz; # mock require: xyz.pm
require Some::Module; # mock require: Some/Module.pm
A better way to override require globally may be to install a hook into #INC. This little-known functionality is described at the end of the require documentation.
Here's a simple example that intercepts any request for a module whose name begins with HTTP:
BEGIN {
unshift #INC, sub {
my ($self, $file) = #_;
return unless $file =~ /^HTTP/;
print "Creating mock $file\n";
my #code = "1"; # Fake module must return true
return sub { $_ = shift #code; defined $_ };
}
}
require HTTP::Foo;
use HTTPBar;
Note that this also mocks use, since it's based on require.
Hooks can be added as code refs into your #INC path. These will then be applied globally to both use and require statements.
To quote perldoc require
You can also insert hooks into the import facility by putting Perl code directly into the #INC array.
There are three forms of hooks: subroutine references, array references, and blessed objects.
Subroutine references are the simplest case. When the inclusion system walks through #INC and encounters a subroutine, this subroutine gets called with two parameters, the first a reference to itself, and the second the name of the file to be included (e.g., "Foo/Bar.pm"). The subroutine should return either nothing or else a list of up to three values in the following order:
1. A filehandle, from which the file will be read.
2. A reference to a subroutine. If there is no filehandle (previous item), then this subroutine is expected to generate one line of source code per call, writing the line into $_ and returning 1, then finally at end of file returning 0. If there is a filehandle, then the subroutine will be called to act as a simple source filter, with the line as read in $_ . Again, return 1 for each valid line, and 0 after all lines have been returned.
3.Optional state for the subroutine. The state is passed in as $_[1] . A reference to the subroutine itself is passed in as $_[0]
Here's an example:
#!/usr/bin/perl
sub my_inc_hook {
my ($sub_ref, $file) = #_;
unless ($file =~ m{^HTTP/}) {
warn "passing through: $file\n";
return;
}
warn "grokking: $file\n";
return (\*DATA);
}
BEGIN {
unshift(#INC, \&my_inc_hook);
}
use strict;
require warnings;
require HTTP::Bazinga;
HTTP::Bazinga::it_works();
__DATA__
package HTTP::Bazinga;
sub it_works {warn "bazinga!\n"};
1;
Produces:
$ perl inc.pl
passing through: strict.pm
passing through: warnings.pm
grokking: HTTP/Bazinga.pm
bazinga!
I believe this works for perl 5.10.0 and above.

Is there a way to encapsulate the common Perl functions into their own scripts?

I am maintaining several Perl scripts that all have similar code blocks for different functions. Each time a code block is updated, I have to go through each script and manually make the change.
Is there a way to encapsulate the common functions into their own scripts and call them?
Put the common functionality in a module. See perldoc perlmod for details.
There are other ways, but they all have severe issues. Modules are the way to go, and they don't have to be very complicated. Here is a basic template:
package Mod;
use strict;
use warnings;
use Exporter 'import';
#list of functions/package variables to automatically export
our #EXPORT = qw(
always_exported
);
#list of functions/package variables to export on request
our #EXPORT_OK = qw(
exported_on_request
also_exported_on_request
);
sub always_exported { print "Hi\n" }
sub exported_on_request { print "Hello\n" }
sub also_exported_on_request { print "hello world\n" }
1; #this 1; is required, see perldoc perlmod for details
Create a directory like /home/user/perllib. Put that code in a file named Mod.pm in that directory. You can use the module like this:
#!/usr/bin/perl
use strict;
use warnings;
#this line tells Perl where your custom modules are
use lib '/home/user/perllib';
use Mod qw/exported_on_request/;
always_exported();
exported_on_request();
Of course, you can name the file anything you want. It is good form to name the package the same as file. If you want to have :: in the name of the package (like File::Find) you will need to create subdirectories in /home/user/perllib. Each :: is equivalent to a /, so My::Neat::Module would go in the file /home/user/perllib/My/Neat/Module.pm. You can read more about modules in perldoc perlmod and more about Exporter in perldoc Exporter
About a third of Intermediate Perl is devoted to just this topic.
Using a module is the most robust way, and learning how to use modules would be helpful.
Less efficient is the do function. Extract your code to a separate file, say "mysub.pl", and
do 'mysub.pl';
This will read and then eval the contents of the file.
You can use the
require "some_lib_file.pl";
where you would put all your common functions and call them from other scripts which would contain the line above.
For example:
146$ cat tools.pl
# this is a common function we are going to call from other scripts
sub util()
{
my $v = shift;
return "$v\n";
}
1; # note this 1; the 'required' script needs to end with a true value
147$ cat test.pl
#!/bin/perl5.8 -w
require 'tools.pl';
print "starting $0\n";
print util("asdfasfdas");
exit(0);
148$ cat test2.pl
#!/bin/perl5.8 -w
require "tools.pl";
print "starting $0\n";
print util(1);
exit(0);
Then executing test.pl and test2.pl will yield the following results:
149$ test.pl
starting test.pl
asdfasfdas
150$ test2.pl
starting test2.pl
1

How can I use Smart::Comments in a module I load without changing its source?

How can I specify that Smart::Comments be loaded for my original script, as well as for any of the modules it directly loads. However, since it is a source-filter, it would probably wreck havoc if applied to every module loaded by every other loaded module.
For example, my script includes
use Neu::Image;
I would like to load Smart::Comments for Neu::Image as well, but specifying
$ perl -MSmart::Comments script.pl
does not load Smart::Comments for Neu::Image.
This behavior is described in the Smart::Comments documentation:
If you're debugging an application you
can also invoke it with the module
from the command-line:
perl -MSmart::Comments $application.pl
Of course, this only enables smart
comments in the application file
itself, not in any modules that the
application loads.
A few other things that I've looked at already:
Perl Command-Line Options
perldoc perlrun (I searched it
for the word "module")
WORKAROUND
As gbacon mentions, Smart::Comments provides an environment variable option that would allow turning it on or off. However, I would like to be able to turn it on without modifying the original source, if possible.
You almost certainly want to add use Smart::Comments to modules that contain such and then flip the switch in your environment by setting $Smart_Comments appropriately.
Stash-munging, import-hijacking monkey-patching is madness.
But maybe you're into that sort of thing. Say you have Foo.pm:
package Foo;
use Exporter 'import';
our #EXPORT = qw/ foo /;
#use Smart::Comments;
sub foo {
my #result;
for (my $i = 0; $i < 5; $i++) {
### $i
push #result => $i if $i % 2 == 0;
}
wantarray ? #result : \#result;
}
1;
Ordinary usage:
$ perl -MFoo -e 'print foo, "\n"'
024
Ordinary is dull and boring, of course. With run-foo, we take bold, dashing steps!
#! /usr/bin/perl
use warnings;
use strict;
BEGIN {
unshift #INC => \&inject_smart_comments;
my %direct;
open my $fh, "<", $0 or die "$0: open: $!";
while (<$fh>) {
++$direct{$1} if /^\s*use\s+([A-Z][:\w]*)/;
}
close $fh;
sub inject_smart_comments {
my(undef,$path) = #_;
s/[\/\\]/::/g, s/\.pm$// for my $mod = $path;
if ($direct{$mod}) {
open my $fh, "<", $path or die "$0: open $path: $!";
return sub {
return 0 unless defined($_ = <$fh>);
s{^(\s*package\s+[A-Z][:\w]*\s*;\s*)$}
{$1 use Smart::Comments;\n};
return 1;
};
}
}
}
use Foo;
print foo, "\n";
(Please pardon the compactness: I shrunk it so it would all fit in an unscrolled block.)
Output:
$ ./run-foo
### $i: 0
### $i: 1
### $i: 2
### $i: 3
### $i: 4
024
¡Viva!
With #INC hooks we can substitute our own or modified sources. The code watches for attempts to require modules directly used by the program. On a hit, inject_smart_comments returns an iterator that yields one line at a time. When this crafty, artful iterator sees the package declaration, it appends an innocent-looking use Smart::Comments to the chunk, making it appear as though it were in the module's source all along.
By trying to parse Perl code with regular expressions, the code will break if the package declaration isn't on a line by itself, for example. Season to taste.
It doesn't seem like this idea makes any sense. If you are utilizing Smart::Comments in a module, why would you not want to use Smart::Comments in that module's source? Even if you could get Smart::Comments to apply to all modules loaded in a script via -M, it probably wouldn't be a good idea because:
You're obfuscating the fact that your modules are using smart comments by not including the use line in their source.
You could potentially introduce bizarre behavior from modules you use in your script which happen to have what look like smart comments, but aren't really. If a module doesn't contain smart comments, you should not force them down its throat.
As gbacon said, the right way to do this is to use the module in each of your modules that make use of it, and then suppress them with an environment variable when you don't want the output.
Also as he said, it's still probably possible to do this with some "Stash-munging, import-hijacking monkey-patching" madness, but that's a lot of work. I don't think anyone is going to put the effort into giving you a solution along those lines when it is not a good idea in the first place.

How can I dynamically include Perl modules without using eval?

I need to dynamically include a Perl module, but if possible would like to stay away from eval due to work coding standards. This works:
$module = "My::module";
eval("use $module;");
But I need a way to do it without eval if possible. All google searches lead to the eval method, but none in any other way.
Is it possible to do it without eval?
Use require to load modules at runtime. It often a good idea to wrap this in a block (not string) eval in case the module can't be loaded.
eval {
require My::Module;
My::Module->import();
1;
} or do {
my $error = $#;
# Module load failed. You could recover, try loading
# an alternate module, die with $error...
# whatever's appropriate
};
The reason for the eval {...} or do {...} syntax and making a copy of $# is because $# is a global variable that can be set by many different things. You want to grab the value as atomically as possible to avoid a race condition where something else has set it to a different value.
If you don't know the name of the module until runtime you'll have to do the translation between module name (My::Module) and file name (My/Module.pm) manually:
my $module = 'My::Module';
eval {
(my $file = $module) =~ s|::|/|g;
require $file . '.pm';
$module->import();
1;
} or do {
my $error = $#;
# ...
};
How about using the core module Module::Load
With your example:
use Module::Load;
my $module = "My::module";
load $module;
"Module::Load - runtime require of both modules and files"
"load eliminates the need to know whether you are trying to require either a file or a module."
If it fails it will die with something of the like "Can't locate xxx in #INC (#INC contains: ...".
Well, there's always require as in
require 'My/Module.pm';
My::Module->import();
Note that you lose whatever effects you may have gotten from the import being called at compile time instead of runtime.
Edit: The tradeoffs between this and the eval way are: eval lets you use the normal module syntax and gives you a more explicit error if the module name is invalid (as opposed to merely not found). OTOH, the eval way is (potentially) more subject to arbitrary code injection.
No, it's not possible to without eval, as require() needs the bareword module name, as described at perldoc -f require. However, it's not an evil use of eval, as it doesn't allow injection of arbitrary code (assuming you have control over the contents of the file you are requireing, of course).
EDIT: Code amended below, but I'm leaving the first version up for completeness.
I use I used to use this little sugar module to do dynamic loads at runtime:
package MyApp::Util::RequireClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our #EXPORT_OK = qw(requireClass);
# Usage: requireClass(moduleName);
# does not do imports (wrong scope) -- you should do this after calling me: $class->import(#imports);
sub requireClass
{
my ($class) = #_;
eval "require $class" or do { die "Ack, can't load $class: $#" };
}
1;
PS. I'm staring at this definition (I wrote it quite a while ago) and I'm pondering adding this:
$class->export_to_level(1, undef, #imports);... it should work, but is not tested.
EDIT: version 2 now, much nicer without an eval (thanks ysth): :)
package MyApp::Util::RequireClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our #EXPORT_OK = qw(requireClass);
# Usage: requireClass(moduleName);
# does not do imports (wrong scope) -- you should do this after calling me: $class->import(#imports);
sub requireClass
{
my ($class) = #_;
(my $file = $class) =~ s|::|/|g;
$file .= '.pm';
require $file; # will die if there was an error
}
1;
Class::MOP on CPAN has a load_class method for this:
http://metacpan.org/pod/Class::MOP
i like doing things like..
require Win32::Console::ANSI if ( $^O eq "MSWin32" );