"Michael Downey" <[EMAIL PROTECTED]> writes:
> I am currently trying to get 5.8.0 to work on VMS 7.3 and having a problem
> with how SYS$INPUT is getting set-up when calling system.  Here is the code
> I'm testing:
> test.pl
> -------
> system("perl a.pl");
>
> a.pl
> -----
> $a = $ENV{'SYS$INPUT'};
> $b = $ENV{'SYS$COMMAND'};
> $c = $ENV{'SYS$OUTPUT'};
> print "INPUT: $a\n";
> print "COMMAND: $b\n";
> print "OUTPUT: $c\n";
> $answer = <STDIN>;
> print "Received: $answer\n";
>
> Both files are in the same directory.  With a standard build of PERL 5.8.0
> this is what I get back when I do
>>perl test.pl
> INPUT: _TST5$DKA100:
> COMMAND: _TST5$FTA195:
> OUTPUT: _TST5$FTA195:
> Use of uninitialized value in concatenation (.) or string at a.pl line 8.
> Received:

I'm not seeing this with the latest bleadperl (5.9.0 @ 18376 on VMS6.2),
and I *think* they have the same safe_popen.  The difference may be in
the perlio implementation, or the conditions under which you're running
the script.

> I tracked this down to the safe_popen call and I believe that the spawning
> of the vmspipe.com file is causing SYS$INPUT to be set up incorrectly.  I
> believe that spawning a DCL script causes SYS$INPUT to be set to the script
> itself.

For system(), safe_popen doesn't change SYS$INPUT at all.

Here's a code snippet from safe_popen from where lib$spawn is called:

    /* Omit arg 2 (input file) so the child will get the parent's SYS$INPUT
     * and SYS$COMMAND.  vmspipe.com will redefine SYS$INPUT, but we'll still
     * have SYS$COMMAND if we need it.
     */
    _ckvmssts(lib$spawn(&vmspipedsc, 0, &nl_desc, &flags,
                      0, &info->pid, &info->completion,
                      0, popen_completion_ast,info,0,0,0));

When handling system(), mode='n' so the "popen_input" symbol passed to
VMSPIPE.COM is empty ("").  So VMSPIPE.COM doesn't set it:

$ pif perl_popen_in  .nes. "" then perl_define/user/name_attributes=confine sys$input 
'perl_popen_in'

(pif = "if", perl_define="define/nolog")

So you get whatever the default is from lib$spawn, which is typically
the DCL script lib$spawn is running (VMSPIPE.COM), as you state.

When the subprocess reads from SYS$INPUT in your test program,
it should just get an EOF.  Perhaps EOFs are being reported as undef's
and triggering an error message?

> So I changed VMS.C to have the following code:
> static PerlIO *
> safe_popen(pTHX_ char *cmd, char *in_mode, int *psts)
> {
>     .....
>     unsigned short len = 0;
>     ....
>     $DESCRIPTOR(d_input, "SYS$INPUT");
>
>     } else if (*mode == 'n') {       /* separate subprocess, no Perl i/o */
>         /* Translate SYS$INPUT so we can pass it to the DCL script and
>            override the SYS$INPUT which will get set to the script itself.
> */
>         d_symbol.dsc$w_length = MAX_DCL_SYMBOL;
>         _ckvmssts(lib$get_logical(&d_input, &d_symbol, &len, 0, 0, 0, 0,
> 0));
>         symbol[len] = '\0';
>         /* Don't know why but lib$get_logical puts something in the first 4
>            characters and then puts the logical translation. */
>         strncpy(in, symbol+4, 512);
>
>         ...
>     }
>     ...
> }
>     I hope that all makes sense.  I'd do a better diff but my diff skills
> are poor.  Once I recompiled perl everything worked as planned with test.pl.
> I'm not too sure if I'm missing something as this is a fairly important bug
> if it is a bug.  I'm compiling perl with just the standard configure and all
> the tests passed except for the few known tests that don't.  If anyone could
> verify that I'm not out to lunch that would be much appreciated.  Also if
> anyone would know what lib$get_logical puts in the first 4 characters of the
> array that would also be helpful.

It makes sense all right.  It's just not clear what the best solution
might be.   But first, a detail:

Take a look at the VMS.C Perl_vmstrnenv routine and docs on
sys$trnlnm.  SYS$INPUT et al are process permanent files, and when
translated have a 4 byte prefix (IIRC, two bytes are a "this is a PPF"
flag and the next two are an i/o channel#) If this route is pursued,
using Perl_vmstrnenv or other `internal' routine would probably be
better than adding a call to lib$get_logical.   There's at least one
example of calling vmstrnenv to get PPF definitions that can be found
in VMS.C.

But, more importantly, what exactly do you think your test program
_should_ do?  (other than "not give an error message") Read from the
terminal?  Get an EOF?

How about when you do:
    perl test.pl <somefile.txt

should the a.pl subprocess grab the next line from "somefile.txt"?
(doable but a real pain...one has to set up mailbox piping code because
file i/o isn't generally sharable across processes)
now generalize to a horde of subprocesses and sub-subprocesses all
glomming onto one parent input. Or should the redirection be ignored,
and subprocess input taken from the terminal?  How about when Perl is
run from a batch job?

My own opinion is that when you do system(), the subprocess shouldn't
be taking any input from sys$input at all...it should have it's input
set to NL: ... if you want a subprocess that gets input, you should
be using open(X,'|some_command').

A more unixy point of view is that a subprocess spawned with system()
should inherit stdin, stdout and stderr from its parent.  But, as
mentioned above, that can be a pain on VMS and may violate the
"rule of least suprises".

The system() implentation in safe_popen() was based on the previous
standalone system() implementation...which just called lib$spawn
with little to no "massaging" of PPF definitions.  In particular,
I think the handling of sys$input is identical to the previous
implementation.  (Not that it's right...we probably should do better).

And the test suite doesn't really test these things very well, IMO.
--
Chuck Lane  [EMAIL PROTECTED]

Reply via email to