sans-clue has asked for the wisdom of the Perl Monks concerning the following question:

I have a perl script that others use to hand up to 256 characters of text. In the script all the arguments are put into a single var. Sometimes despite my requesting otherwise, they include a *. The way they execute the perl script the * does a directory listing which become arguments. I assume this is happening via the shell BEFORE the perl script processes the arguments. Is my only choice to stick that exact same directory listing into a var and look for that pattern and remove it ? Thanks

Replies are listed 'Best First'.
Re: Detect * in arguments
by kennethk (Abbot) on Jul 10, 2015 at 18:03 UTC
    Code is worth 1000 words; please include input, output and code (or pseudocode) for future questions. See How do I post a question effectively?

    Finding out whether a string contains a certain character can be done with index or regular expressions. In your case, maybe your check would look like:

    if (index($args, '*') != -1) { die "No * are allowed.\n" }
    or maybe you'd strip it using
    $args =~ s/\*//g;
    If these don't fit the bill, provide more algorithmic clarity, and I can be more helpful.

    Update: Or do you mean the shell is expanding the '*' metacharacter before it gets fed to your code? In this case, your code never sees the asterisk, and the hassle in protecting the user from themself is almost assuredly not worth your time.


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Detect * in arguments (STDIN)
by tye (Sage) on Jul 10, 2015 at 21:17 UTC

    If you can't get your users to put the string in quotes (sounds like that would indeed be a problem), then instead of expecting the string on the command line of your script, have the script read the string. Instead of:

    % your_script the string from the user that should not contain * char +acters

    Have them use your script like:

    % your_script Enter string> the string from the user that shouldn't contain * charac +ters

    (Wait until a user enters a contraction instead of a "*" using your old invocation strategy.)

    - tye        

Re: Detect * in arguments
by choroba (Cardinal) on Jul 10, 2015 at 23:28 UTC
    To pass the asterisk as an argument to a script from bash or similar shell, you have to backslash or quote it:
    script.pl \* script.pl '*'

    Otherwise, the shell expands the wildcard when processing the command.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Detect * in arguments
by marinersk (Priest) on Jul 10, 2015 at 19:25 UTC

    The Linux shells pre-globber your wildcards and convert them to matching filenames; Windows does not.

    Since your users are Linux users, they should be familiar with the shell processing rules, and the idea that you could reject any input with more than one @ARGV might be reasonable.

    Otherwise, yes, in the Linux environments, you could try to deduce where the wildcard characters were located based on the input your receive, but that's some risky business, as there is a one-to-many relationship there.

    For example, what if what comes back is the only file that matches: test1.dat

    The following is not a complete list of how you might have gotten that:

    • test1.dat
    • test*.dat
    • test%.dat
    • test*.*

    I hope you see my point -- given that one result could have come from a multitude of inputs, it's like a one-way trap door encryption algorithm; you can't navigate the canoe back up the river.

    I'd be inclined to educate the users to use quotes; with a far second of trying to compensate for this particular human problem.

Re: Detect * in arguments
by 1nickt (Canon) on Jul 10, 2015 at 18:28 UTC

    Don't trust user input. Ever.

    That means account for everything that could go wrong in your code.

    It's your fault if your program blows something up.

    ( Said with love. )

    (But don't trust user input. Ever. )

    Remember: Ne dederis in spiritu molere illegitimi!
Re: Detect * in arguments
by fishmonger (Chaplain) on Jul 10, 2015 at 18:20 UTC

    How are they executing the script?
    How should they be executing the scrpt?
    How are you assigning the arg(s) to the single var?

    Please post your code, at least up to the point where you're assigning the arg(s) to the var.

Re: Detect * in arguments
by trippledubs (Deacon) on Jul 10, 2015 at 18:08 UTC
    Adapt your code to accommodate them. Alternatively, fire / replace them. Even better, disable the star key on all their keyboards with a screwdriver. Better yet, catch them in the act and "spill" some coffee on them then politely remind them of the regulations regarding your script
      After more testing it seems the damage is done before perl evals the args, as the args include the files in that directory. I created a string in the perl script that has the files in the directory (Cwd) and once I detect that string in the args, rather that stripping that string I decided to turn the message into "I told you not to use asterisks". I'll see how that goes. Once spanked, I will just remove the dir listing from the string. BTW They fork the perl script from the bash shell, testing for * like kennethk mentioned resulted in no asterisks ...

        You could require them to pass the args as a single string i.e., is quoted, then check @ARGV. If it has more than 1 element, you know they did not execute the script correctly and you (the script) should then die.

        That will catch most of the * shell expansion issues, but not all.

Re: Detect * in arguments
by Anonymous Monk on Jul 10, 2015 at 19:14 UTC
    Hmmm, I think you're talking about this:
    $ ls -a . .. $ touch a_file $ ls -a . .. a_file $ echo a_* a_file $ echo b_* b_*
    This is how shells (or at least Bash) expand globs... if the glob can't be expanded it remains as is. There is a nullglob option in the shell that can fix that...
    Is my only choice to stick that exact same directory listing into a var and look for that pattern and remove it ?
    Yeah, 'remove' sounds good.
Re: Detect * in arguments
by Marshall (Canon) on Jul 12, 2015 at 08:13 UTC
    Please post a simple version of your code.
    AND a couple of examples of the command lines that you don't seem to be able to process.

    I don't know where this 256 character limit comes from.
    Certainly not from Perl. In Unix, in the olden days, a fairly normal restriction would be 7 full command lines, which would be 7x80 characters or 560. More normal now would be at least 1024 or 2048 characters or even 4096 or even more than that. I don't know why you can't process a huge command line.

    It is certainly possible that the shell can expand *.txt into perhaps 2,000 or many, many more file names.

    Show some code and example command line inputs. With proper technique, it should be possible to say process an expanded command line with 5,000 arguments with no problem whatsoever.