jonnyfolk has asked for the wisdom of the Perl Monks concerning the following question:

I have called a script using system, and it's working okay.
my @args = ($program, $username, $user); system(@args) == 0 or die "system @args failed: $?"
However the arguments are not coming through to the next script.

I have tested @args and the arguments are ok, and I use the same arguments in the receiving script. What am I doing wrong?

Replies are listed 'Best First'.
Re: relaying arguments using system call
by tachyon (Chancellor) on Mar 20, 2003 at 23:50 UTC
    C:\>type test.pl #!/usr/bin/perl # test.pl my $prog = 'receive.pl'; my $user = 'foo'; my $pass = 'bar'; system( $prog, $user, $pass ) && die "system failed $?"; print "Did system( $prog, $user, $pass ) OK"; exit 0; C:\>type receive.pl #!/usr/bin/perl # receive.pl print "I am recieving, got: @ARGV\n\n"; exit 0; C:\>receive.pl arg1 arg2 arg3 blah I am recieving, got: arg1 arg2 arg3 blah C:\>test.pl I am recieving, got: foo bar Did system( receive.pl, foo, bar ) OK C:\>

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Much obliged, tachyon. I'm still not sure what's up but I'll build upon what you've shown me there and find out.

      Cheers!

Re: relaying arguments using system call
by Ineffectual (Scribe) on Mar 20, 2003 at 23:49 UTC
    When a script reads in arguments from the command line, they're put into @ARGV (not @ARG - that's only for passing between subroutines) and you can retrieve them using $ARGV[0] for the first one, etc. (Or use GetOpt)

    Most likely your system call is working, and your next script is failing to read in the correct variables, but I can't really tell unless you post more specific code.

    HTH
    'Fect
      Thanks for the input, I think I probably have enough info to sort it out for myself, now.
Re: relaying arguments using system call
by jonnyfolk (Vicar) on Mar 21, 2003 at 01:24 UTC
    Just to complete the record, my arguments are passing through to the next script. Having done a system call on the initial script as described previously:
    my @args = ($program, $username, $user); system(@args) == 0 or die "system @args failed: $?"
    I began the second script with:
    my $username = shift @ARGV; my $user =shift @ARGV;
    That did it for me but if there is a better way or other comments, I welcome them.

    Thanks once again for the help

      I prefer this form (it is a little faster, a little shorter and lets you add more args at the cost of a , and the $arg_name).

      my( $username, $user ) = @ARGV;

      The multi-arg form of system offers some protection from hacking but remember you are passing $username and $user to the SHELL so it is a good idea to make sure that they only contain non shell chars. Typically you remove everything except your allowed list (it is better to specify what you will allow than try to think of everything bad - you will miss stuff):

      $var = ";rm -rf /*;"; my $ILLEGAL_CHARS = qr/[^A-Za-z0-9._-]/; $var =~ s/$ILLEGAL_CHARS/_/g; print $var;

      If you were using the single arg form of system and allowed that string (un-sanitized) it would try to execute that command.....

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        Hi tachyon, thanks once again.

        I wonder if you have time if you could help me unravel what you're doing!
        If I'm correct you are saying $var minus $ILLEGAL_CHARS equals acceptable $var. However I don't understand the expression   $var = ";rm -rf /*;";   also   qr/[^A-Za-z0-9._-]/;   Am I right in thinking that   qr//;  allows you to assign the regex to the variable, rather than have it act upon the variable?

        Also it looks as though the $ILLEGAL_CHARS are the one's that I would wish to keep (as per the sense of your explanation) but they are being removed from the variable.

        I'm sorry if this all seems to be silly or uninformed - I am doing my best to make sense of it and I hope that by not flinching in asking silly questions now I might learn enough to start asking sensible questions in the first place!!
Re: relaying arguments using system call
by and (Pilgrim) on Mar 21, 2003 at 07:39 UTC
    system(@args) == 0 or die ...

    No! It is supposed to be system(@args) and die ... Please.

    I am sure it seems like a small matter to you. But with the new language coming out and the clamor about it being too complex, I'm afraid they are looking for things to cut. I don't want to have to find a new job in the current economy.

      Now I know why it's called @ARGV - as in @AAARRRGH!V. I tend to tiptoe around the site on my best behaviour because I don't know very much and there's a lot I can learn here by watching and 'listening'.

      I thought if I looked at perldocs and used their suggested code that this time I would be beyond reproach.

      Apparently not.
      Have a nice day!
        I think your perldoc inspired code is just fine.

        I think "and" is mistaken.

        --
        Regards,
        Helgi Briem
        helgi AT decode DOT is

      Why do you feel this is better?

      I personally find the former much more readable and understandable to others.

      Is there any reason to expect this not to work in Perl6?

      Enquiring minds want to know.

      --
      Regards,
      Helgi Briem
      helgi AT decode DOT is

        Well actually neither way (system == 0 or die versus system and die) will work as expected in Perl 6 for the simple reason that the return code of system will be switched around. 0 will indicate failure, 1, success.

        Which means that you'll finally be able to write code which appears follows the usual logic such as for opening files:

        if( !system( qw/ifconfig eth0 down/ )) { die "could not ignore the world\n"; }

        You can fix Perl5 to behave like this now. japhy posted some code in japhygesis that switches this (and other inconsistencies) around to make things flow more naturally.

        _____________________________________________
        Come to YAPC::Europe 2003 in Paris, 23-25 July 2003.