How safe is $0?

B

Bill H

If I use $0 to determine the name of the script that is running is it
safe to assume that it will not change within the script (as long as I
never intentionally try to change it? The way I am using it is setting
certain messages based on the the script. Somthing like this:

if ($0 eq "foo.pl")
{
$blah = "foo";
}
if ($0 eq "bar.pl")
{
$blah = "bar";
}

I tried to find this in the perldocs but didn't.

Bill H
 
A

anno4000

Bill H said:
If I use $0 to determine the name of the script that is running is it
safe to assume that it will not change within the script (as long as I
never intentionally try to change it? The way I am using it is setting
certain messages based on the the script. Somthing like this:

if ($0 eq "foo.pl")
{
$blah = "foo";
}
if ($0 eq "bar.pl")
{
$blah = "bar";
}

Well, $0 is a writable package variable, so in principle anyone
can change it. To do so in a module would have to be considred
bad style, but that's no guarantee it won't happen. To be safe
you can but the code that uses $0 in a BEGIN block in the main
script that happens before any "use" statements:

my $blah;
BEGIN { ( $blah = $0) =~ s/\.pl$// }

use ...;

Anno
 
X

xhoster

Bill H said:
If I use $0 to determine the name of the script that is running is it
safe to assume that it will not change within the script (as long as I
never intentionally try to change it?

That is probably fairly safe to assume, but why assume? I can't think of
Perl's internals mucking with it without being asked to. Some weird module
might want to.

The way I am using it is setting
certain messages based on the the script. Somthing like this:

if ($0 eq "foo.pl")
{
$blah = "foo";
}
if ($0 eq "bar.pl")
{
$blah = "bar";
}

Why not just put "my $orig_0=$0" near the top of the script? Then
you don't have to worry about either Perl's internals or other modules
changing it, plus it frees you (or your successor) to change the real $0
in the future if you ever feel the need to use its status-indicating
feature.

Xho
 
M

Michele Dondi

Why not just put "my $orig_0=$0" near the top of the script? Then
you don't have to worry about either Perl's internals or other modules
changing it, plus it frees you (or your successor) to change the real $0
in the future if you ever feel the need to use its status-indicating
feature.

Huh?!? "near the top"? As Anno correctly pointed out, to be really
sure it needs to be in a BEGIN block before other BEGIN blocks and
use's.


Michele
 
X

xhoster

Michele Dondi said:
Huh?!? "near the top"? As Anno correctly pointed out, to be really
sure it needs to be in a BEGIN block before other BEGIN blocks and
use's.

Sure, if you are afraid someone will assign to $0 during compilation.
That seems even less likely than assigning to it during run-time. But
better safe than sorry, I guess.

my $orig_0; BEGIN {$orig_0=$0};

It would be nice if there was some way to "my" something but causing
it to get defined in the lexical scope one level up (or, one level "out" I
suppose, rather than up).


Xho
 
M

Michele Dondi

^^^^^^^^^^^^^^^^

^^^^^^^^^^^^^^^^


Sure, if you are afraid someone will assign to $0 during compilation.
That seems even less likely than assigning to it during run-time. But
better safe than sorry, I guess.

Since you wrote "or other modules", it was just to be precise.
my $orig_0; BEGIN {$orig_0=$0};

It would be nice if there was some way to "my" something but causing
it to get defined in the lexical scope one level up (or, one level "out" I
suppose, rather than up).

I *thought* that Perl 6's OUTER:: namespace could serve this purpose,
but this doesn't seem to be the case, at least as of the pugs I have
(this is not a definitive proof):

pugs> {my $OUTER::foo=10}
Internal error while running expression:
***
Unexpected "::foo"
expecting word character, "?", "!", trait, "=", infix assignment,
term postf
ix, operator or "}"
at <interactive> line 1, column 11
pugs> my $foo; {$OUTER::foo=10}
10
pugs> say $foo;
10


Michele
 
G

Gary E. Ansok

If I use $0 to determine the name of the script that is running is it
safe to assume that it will not change within the script (as long as I
never intentionally try to change it? The way I am using it is setting
certain messages based on the the script. Somthing like this:

if ($0 eq "foo.pl")
{
$blah = "foo";
}
if ($0 eq "bar.pl")
{
$blah = "bar";
}

Not directly related to your question, but bear in mind that it is not
specified whether $0 will be just the script name, or might contain
directory path information. In my experience, Unix-based systems usually
have $0 containing whatever was entered by the user (just "foo.pl" if the
script was found through $PATH, or the path entered by the user), and
Windows has $0 contain a full path to the script. So you might want
to use basename() (from File::Basename) on the contents of $0.

Also, knowlegable users can set $0 to anything they want to at the time
that your script is started, before any of your code runs. So if this
is critical to your script's functionality (or security), think twice.

That said, I think it pretty safe to say that no Perl core or widely-used
modules are likely to change $0 at all.

Gary Ansok
 
B

Bill H

Not directly related to your question, but bear in mind that it is not
specified whether $0 will be just the script name, or might contain
directory path information. In my experience, Unix-based systems usually
have $0 containing whatever was entered by the user (just "foo.pl" if the
script was found through $PATH, or the path entered by the user), and
Windows has $0 contain a full path to the script. So you might want
to use basename() (from File::Basename) on the contents of $0.

Also, knowlegable users can set $0 to anything they want to at the time
that your script is started, before any of your code runs. So if this
is critical to your script's functionality (or security), think twice.

That said, I think it pretty safe to say that no Perl core or widely-used
modules are likely to change $0 at all.

Gary Ansok

Gary

I learned this today. On my windows system testing $0 was great, on
the linux webserver, it was the full path. So the easiest thing was to
just to use index and cover both bases (ie index($0,"for.pl")).
 
M

Michele Dondi

I learned this today. On my windows system testing $0 was great, on
the linux webserver, it was the full path. So the easiest thing was to
just to use index and cover both bases (ie index($0,"for.pl")).

The easiest and more reliable way would have been to use basename() as
has already been suggested to you. It is unlikely, but what if you
have to do with /path/to/for.pl.for.pl?


Michele
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,205
Messages
2,571,067
Members
47,673
Latest member
MahaliaPal

Latest Threads

Top