Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Custom Arguements

by Ghosty (Novice)
on Aug 15, 2018 at 09:38 UTC ( [id://1220359]=perlquestion: print w/replies, xml ) Need Help??

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

So hello be ready cause what i'm about to ask is fucked xD, i made a custom terminal shell with custom commands but i made some modules I want the user to do "use <modukle>" and then execute the module, i know how to do so from the command-line but what i mean by custom terminal shell is a function with an user input which repeats itself when the user has input a correct command it acts like a custom shell. so its like <Banner of the script> Input "help" or "?" to conitnue... (USERNAME): <input> You know custom terminal shell and i wanna to know in perl how to make so the user needs to put use <module> then execute the module, is there anyway?

SOLUTION EDITED:

sub ShellInput{ my $host = hostname; print "($host): "; chop(my $shell=<stdin>); # Checks if use was used then read the argument: if($shell =~ /use/){ if ($shell =~ /use \s*(.+)$/) { my $module = $1; print "Module: $module \n"; ShellInput(); } } }

Replies are listed 'Best First'.
Re: Custom Arguments
by hippo (Bishop) on Aug 15, 2018 at 10:34 UTC
    i wanna to know in perl how to make so the user needs to put use <module> then execute the module,

    Perhaps what you are asking for is something like Module::Load?

Re: Custom Arguements
by thanos1983 (Parson) on Aug 15, 2018 at 10:12 UTC

    Hello Ghosty,

    I am not sure if I understood your question correctly but is this (Shell::Perl) something close to what you are looking for?

    If not can you provide a sample of code, not everyone is familiar with custom terminal shell.

    Looking forward to your update, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
      Ok what i meant is the user when executing the script gets a user input and some custom commands as like help or anything which i code myself, but i wanna to make a tool that allows the user to do a lot on his system as in scanning for perl backdoors etc for security so there would be modules, what i want is the user to do use <module> and perl to understand that if the users puts use then a module that perl needs to read what is after use and see if the module exist if it does it executes it, is it more clear? If not type on google "Metasploit hacking tuto" its the only tool i can think of that shows what i'm asking for. Is it more clear?
Re: Custom Arguements
by VinsWorldcom (Prior) on Aug 15, 2018 at 12:13 UTC

    Are you looking for a REPL? Perl has that:

    Devel::REPL
    Perl::Shell
    Shell::Perl
    perlconsole
    psh

    ... and of course, mine:

    App::PerlShell

    UPDATE: Example:

    VinsWorldcom@C:\Users\VinsWorldcom> plsh Perl> print $Bin; Use of uninitialized value $App::PerlShell::Bin in print at (eval 19) +line 2. Perl> use FindBin qw($Bin); Perl> print $Bin; C:/Users/VinsWorldcom/perl5/bin Perl>
      See when you got "use bin" thingy well thats what i want :) but no those modules aren't not what i'm looking for sadly :(
Re: Custom Arguements
by anonymized user 468275 (Curate) on Aug 15, 2018 at 18:13 UTC
    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

      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

      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: perlquestion [id://1220359]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (6)
As of 2024-04-20 00:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found