Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: Custom Arguements

by anonymized user 468275 (Curate)
on Aug 15, 2018 at 18:13 UTC ( [id://1220386]=note: print w/replies, xml ) Need Help??


in reply to Custom Arguements

The question can easily be misunderstood, but my best guess is you want the user to choose what is executed. This means it is a method they name, not a module which has any number of methods including none. It is advisable to "use strict" in perl programs, so to translate data into a perl identifier, you need a dispatcher, e.g.:
use Try::Tiny; while (my @parsed = &parseInput) { &dispatch(@parsed); } sub parseInput { my $inp = <>; chomp $inp; my @parsed = split $inp; return () if $parsed[0] eq `q`; return @parsed; } sub dispatch { my $cmd = shift; try { eval( '&' . $cmd . '(' . join ',', @_ . ');' ); } catch { print STDERR "Unrecognised command $cmd\n"; } # the above is a non-GUI example which would need adaptation + } # and add a sub xxx for each command xxx

One world, one people

Replies are listed 'Best First'.
Re^2: Custom Arguements (updated)
by AnomalousMonk (Archbishop) on Aug 15, 2018 at 19:54 UTC
    while (my @parsed = &parseInput) { &dispatch(@parsed); } sub parseInput { ... my @parsed = split $inp; return 0 if $parsed[0] eq `q`; ... }

    The expression  $parsed[0] eq `q` (backticks) will try to get the system to do  qx{q} and then compare  $parsed[0] against the value returned from the system; it will probably never be true. The statement should probably be
        return 0 if $parsed[0] eq 'q';
    or perhaps better yet
        return 0 if lc($parsed[0]) eq 'q';
    (Update: See also the note about split in Update 2 below.)

    But (Update: anonymized user 468275 has since changed the statement in question to return an empty list.)
        return 0 if $parsed[0] eq 'q';
    still has a problem because it returns a non-empty list if the condition is true, and the while-loop test
        while (my @parsed = &parseInput) { ... }
    will be true because  @parsed is not empty, so  &dispatch(@parsed) will be called with a  (0) argument list. Probably better to use the statement
        return if lc($parsed[0]) eq 'q';
    because that will return an empty list and cause the while-loop to terminate.

    sub dispatch { my $cmd = shift; try { eval( '&' . $cmd . '(' . join ',', @_ . ');' ); } catch { print STDERR "Unrecognised command $cmd\n"; } # the above is a non-GUI example which would need adaptation }

    This looks to me like a bad idea because it seems to offer an injection point for user supplied input — code! (Update: See also the note about building the string for eval in Update 3 below.) Better IMHO to use a dispatch table:

    c:\@Work\Perl\monks>perl -wMstrict -le "BEGIN { ;; my %dispat = ( 'foo' => sub { print 'Fooing: ', qq{(@_)}; }, 'bar' => \&bar, ); ;; sub dispatch { my $cmd = shift; ;; $cmd = lc $cmd; if (not exists $dispat{$cmd}) { print qq{do not know how to '$cmd'}; return; } $dispat{$cmd}->(@_); } } ;; while (my @parsed = parseInput()) { dispatch(@parsed); } ;; sub parseInput { my $inp = <>; chomp $inp; my @parsed = split ' ', $inp; return if lc($parsed[0]) eq 'q'; return @parsed; } ;; sub bar { print 'Baring: ', qq{(@_)}; } " foo Fooing: () bar Baring: () foo 1 2 3 Fooing: (1 2 3) bar x xyzzy Baring: (x xyzzy) boff do not know how to 'boff' Q

    Update 1: Several minor wording changes; formatting adjustment to the code example.

    Update 2: The statement
        my @parsed = split $inp;
    in the OPed code | code here is incorrect because it calls split with a split pattern of  $inp on the (as-yet uninitialized) string in  $_

    Update 3: Sorry to seem like piling on, but the statement
        eval( '&' . $cmd . '(' . join ',', @_ . ');' );
    is also problematic. The scalar concatenation of  @_ with another string will evaluate the array in scalar context, i.e., as the number of elements in the array. The problem is easily fixed by a couple more parentheses (if you really want to dance with the Devil by the pale moonlight):

    c:\@Work\Perl\monks>perl -wMstrict -le "dispatch(qw(foo 9 8 7 6)); ;; sub dispatch { my $cmd = shift; my $evil_string = '&' . $cmd . '(' . join ',', @_ . ');'; print qq{>>$evil_string<<}; } " >>&foo(4);<< c:\@Work\Perl\monks>perl -wMstrict -le "dispatch(qw(foo 9 8 7 6)); ;; sub dispatch { my $cmd = shift; my $evil_string = '&' . $cmd . '(' . join(',', @_) . ');'; eval $evil_string; } ;; sub foo { print qq{'in Foo:' (@_)} } " 'in Foo:' (9 8 7 6)


    Give a man a fish:  <%-{-{-{-<

      Thanks & my bad for not testing - sometimes I have only time to make a suggestion not to test it and time is not my friend these days.

      Upd: Also it was one hour later I found the ' on the Spanish keyboard I was using. Although for the range of annoyingly contradicting keyboards, I just love to blame those foul beasts that slouched out of Armonk and Redmond to be born ;)

      One world, one people

Re^2: Custom Arguements
by AnomalousMonk (Archbishop) on Aug 16, 2018 at 04:59 UTC

    Here's a working version of the code currently posted here (although I still wouldn't recommend this approach; the last command shows an injection):

    c:\@Work\Perl\monks>perl -wMstrict -le "use Try::Tiny; ;; while (my @parsed = &parseInput) { &dispatch(@parsed); } ;; sub parseInput { my $inp = <>; chomp $inp; my @parsed = split ' ', $inp; return () if $parsed[0] eq 'q'; return @parsed; } ;; sub dispatch { my $cmd = shift; my $args = join q{,}, @_; my $e_str = qq{&$cmd($args)}; try { eval $e_str; $@ and die $@; } catch { warn qq{bad command '$e_str': \n$_}; } } ;; sub bar { print qq{Baring: (@_)}; } " bar Baring: () bar 9 8 7 Baring: (9 8 7) bar x yy zzz bad command '&bar(x,yy,zzz)': Bareword "x" not allowed while "strict subs" in use at (eval 4) line 1 +, <> line 3. Bareword "yy" not allowed while "strict subs" in use at (eval 4) line +1, <> line 3. Bareword "zzz" not allowed while "strict subs" in use at (eval 4) line + 1, <> line 3. bar 'x' 'yy' 'zzz' Baring: (x yy zzz) foo bad command '&foo()': Undefined subroutine &main::foo called at (eval 6) line 1, <> line 5. foo 1 bad command '&foo(1)': Undefined subroutine &main::foo called at (eval 7) line 1, <> line 6. foo x bad command '&foo(x)': Bareword "x" not allowed while "strict subs" in use at (eval 8) line 1 +, <> line 7. foo 'x' bad command '&foo('x')': Undefined subroutine &main::foo called at (eval 9) line 1, <> line 8. {sub{print"rm\c@-rf\c@*"}} rm -rf * q


    Give a man a fish:  <%-{-{-{-<

      Man that is too complex and not what i'm looking for, and rm -rf * this is a malicious windows code... so :( thanks for trying but type "metaploit hacking tuto" in google and see the tool its what i'm talking about how to interact with the tool by doing use etc

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1220386]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (4)
As of 2024-04-25 13:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found