Operating System - OpenVMS

Adding to DCL$PATH in PERL

 
Jimson_1
Frequent Advisor

Adding to DCL$PATH in PERL

Hi,

I'm trying to extend DCL$PATH in Perl, but having problems with the new definition persisting outside of Perl itself.

I've included the Perl code inside a DCL command script.

Can anyone see what's wrong?


$ PERL SYS$INPUT 'P1'
$ DECK
#!perl -w

my $i;
for ($i=0; defined $ENV{"DCL\$PATH;$i"}; ++$i) {
print $ENV{"DCL\$PATH;$i"} . "\n";
}

$ENV{"DCL\$PATH;$i"} = uc $ARGV[0];

print "\n";
for ($i=0; defined $ENV{"DCL\$PATH;$i"}; ++$i) {
print $ENV{"DCL\$PATH;$i"} . "\n";
}

$ EOD
$!
$ wr ""
$ SHO LOG DCL$PATH
$!


Running the script gives:


$ @addtopath TEST

SCR
BIN

SCR
BIN
TEST

"DCL$PATH" = "SCR" (LNM$PROCESS_TABLE)
= "BIN"
1 "SCR" = "U32$:[BASE.SCR]" (LNM$PROCESS_TABLE)
= "TMPSCR"
= "WORK"
2 "TMPSCR" = "U32$:[BASE.SCR.TMPSCR]" (LNM$PROCESS_TABLE)
1 "BIN" = "U32$:[BASE.BIN]" (LNM$PROCESS_TABLE)
13 REPLIES 13
H.Becker
Honored Contributor

Re: Adding to DCL$PATH in PERL

Not knowing Perl nor its implementation it's likely that Perl uses a CRTL function to retrieve environment variables: getenv. It is a CRTL feature to make logical names and their translations available as environment variables. It is likely that Perl uses the CRTL functions putenv or setenv to add to the environment. These functions manipulate the run-time environment, which is only valid during the life of the image. Changes in that environment are not written back to the process environment, here your logical DCL$PATH.

This is intended behavior which mimics UNIX behavior, where you can't modify a shell environment variable with setenv or putenv

You need to use or check where Perl uses functions like lib$get_logical and lib$set_logical.
Jimson_1
Frequent Advisor

Re: Adding to DCL$PATH in PERL

Hi,

That's not the case as we can see with this slightly modified version of the above script.

P1 is used to extend DCL$PATH and also to define its own logical.

At the end we can see that 'P1' is defined.


$ PERL SYS$INPUT 'P1'
$ DECK
#!perl -w

my $i;
for ($i=0; defined $ENV{"DCL\$PATH;$i"}; ++$i) {
print $ENV{"DCL\$PATH;$i"} . "\n";
}

$log = uc $ARGV[0];
$ENV{"DCL\$PATH;$i"} = $log;
$ENV{$log} = 'Still Testing';

print "\n";
for ($i=0; defined $ENV{"DCL\$PATH;$i"}; ++$i) {
print $ENV{"DCL\$PATH;$i"} . "\n";
}

$ EOD
$!
$ wr ""
$ SHO LOG DCL$PATH
$ SHO LOG 'P1'
$!

H.Becker
Honored Contributor

Re: Adding to DCL$PATH in PERL

Hmm, so I was wrong in assuming Perl only uses getenv and friends: it depends...

Do a show log DCL*, you should see what your script defined.

There is a section in the perlvms documentation which covers $ENV and how you can influence what is used for $ENV by the logical PERL_ENV_TABLES.
Joseph Huber_1
Honored Contributor

Re: Adding to DCL$PATH in PERL

In my perlvms help I read:


In either case, only the first
value found searching PERL_ENV_TABLES is altered. It is not possible at present to define a search list logical name via %ENV.

So I assume that
$ENV{"DCL\$PATH;$i"} = uc $ARGV[0];
does not work, but
$ENV{"DCL\$PATH"} = uc $ARGV[0];
redefines the logical by the argument.

I don't know if newer PerlVMS versions allow to insert into a logical name search least, mine (v5.8.6) at least does not.

So to add an item to the searchlist, loop over the existing definition as You do now, but add each item to a local variable, adding a "," to before, then finally add the new variable from the arglist, and do the $ENV() = from that variable.
http://www.mpp.mpg.de/~huber
Jimson_1
Frequent Advisor

Re: Adding to DCL$PATH in PERL

Hmm, still doesn't work.

DCL$PATH becomes equal to the entire concatenated string.

P_CC(H9-ACT)$ sho log DCL$PATH
"DCL$PATH" = "SCR,BIN,TEST" (LNM$PROCESS_TABLE)


Guess I'll just have to download and use the VMS::Logical module.


OK thanks Guys.
Joseph Huber_1
Honored Contributor

Re: Adding to DCL$PATH in PERL

To invalidate my own suggestion:
no, defining a search list using $ENV() apparently does not work.
e.g.
$ENV{"TEST"} = "sys$login:,sys$manager:";
does define the logical literally, not as a search list, i.e. it is not equivalent to DCL
DEFINE TEST sys$login:,sys$manager:

Sorry, no perl solution.
http://www.mpp.mpg.de/~huber
Jimson_1
Frequent Advisor

Re: Adding to DCL$PATH in PERL

Nearly a Perl solution...

I did what you said and then passed back to DCL the concatenated string as a local symbol, using the DCLSym module.

This I then simply expanded into a DCL DEFINE command.

And here it is:


$ PERL SYS$INPUT 'P1'
$ DECK

#!perl -w
use VMS::DCLsym;
tie %sym, VMS::DCLsym;

my $i;
for ($i=0; defined $ENV{"DCL\$PATH;$i"}; ++$i) {
push @tab, $ENV{"DCL\$PATH;$i"};
}

push @tab, uc $ARGV[0];

$sym{dcl_path} = join ",", @tab;

$ EOD
$!
$ define /nolog /process DCL$PATH 'dcl_path'
$!
Hoff
Honored Contributor

Re: Adding to DCL$PATH in PERL

When this:

$ define /nolog /process DCL$PATH 'dcl_path'

is invoked within the context of a spawned subprocess, the definition will immediately vaporize upon subprocess exit.

You could use /JOB to get broader definition, and which will be retained after subprocess (and main process) termination.

If you want to alter the current process context, then use a call to lib$set_logical or analogous.

if you're going to work within this area of OpenVMS, you will need to know some details of how DCL symbols and logical names and subprocesses work (and don't work) together, or you're going to get confused. (Well, I got confused when I first ran into this stuff.) This whole area is a little cryptic when first encountered (and particularly if you're used to how Unix works), but the propagation (inheritance) rules aren't all that complex within OpenVMS. But they can also and most definitely derail some design approaches.
Jimson_1
Frequent Advisor

Re: Adding to DCL$PATH in PERL

The above solution works fine!

Running Perl does not spawn a sub process and thus a JOB logical is not required.

Its Perl I'm learning, not VMS.

And FYI I've been programming on VMS environments for 20 years.