Hello monks! I am an arch linux user and I`ve decided to make a small app for the wireless tools and scans as well, adding some extra options to it. It uses imperative code but I`d try object based one soon. For now it`s a baby a bit over 100 lines but works relatively good. If somebody wants to assist me ( no money tho just for hobbyst ) I`ll be very happy to team up and will share the code. Who knows... it might get an approved arch linux app one day :) View the code in my scratchpad. Today 27.02.12 I`ve updated the code with a smapp -p option to record the output to a logger file - supposed to be always in /home/$USER ( $USER is promptable :) This is no big deal tho. I am intending to do the following:

Can somebody check my script ( now script ) if in windows? There must be an error message showing that you are not using the proper OS ( JK :) ) and you don`t have iwlist on your system. Also... some help and advices in parsing iwconfig and iwlist will be great since I am not exactly a geek in these two :)

Today.. I`ve had some time and added a small slice subroutine for further usage....

#!/usr/bin/perl -w use utf8; use strict; #subs here #scan - match all networks available inside ESSID:" <HERE> " HERE #You`ll see HERE in quotted marks and you can select the network to #connect to that net sub slice { #slices a string from given start position to end possition my ($from, $to) = ($_[1], $_[2]); my @sl = split(//, $_[0]); if ( $from <= $to ) { $_[0] = join("", @sl[$from..$to]); } elsif ( (! defined($_[1])) || (! defined($_[2])) ) { $_[0] = join("", @sl); } else { $_[0] = join("", @sl); } } sub scan { my $scanned = `iwlist scan`; my @nets=(); my $loop = 0; my @lines = split(/\n/, $scanned); foreach my $word (@lines) { my @words = split(/:/, $word); foreach my $pat ( @words ) { if ( $pat =~ m/"/i ) { #print "Network found: $pat \n"; #optional mes +sage $nets[$loop++] = $pat."\n"; } } } return @nets; #returns an array of networks... ??? } #end of SCAN #record output to file so you can load later sub record { my $path = "/home/"; my $user = prompt("Please, enter your home user name ( ex. john, s +upposed that it`s /home/john ). \n" ); $path .= $user; $path .= "/"; print "Your home dir is: $path \n"; print "Here will go the files recordyou are creating\n"; #correct ? Y/N later... my $fname = prompt("Name of the file?( no extensions needed)\n"); my $recname = $path . $fname; open (LOG, '>', $recname); my @inp = &scan(); print LOG @inp; close(LOG); } #check connection sub check { my $con = `ping -c 1 yahoo.com`; my @match = split(/ /, $con); foreach (@match) { if ( $_ =~ m/ttl/i || $_ =~ m/rtt/i) { #find any ttl strings or rtt return 1; } } return 0; } #trims all quotes from the ESSID string sub trim { my @tr = @_; my @trimmed = split(/"/, $tr[0]); return @trimmed; } #connect to <HERE> #you can connect to the net here sub connecd { my @conn = @_; print "If network has password enter it: "; chomp(my $pawd = <STDIN>); print $conn[0], " you choose\n"; my $connection = &trim($conn[0]); if (system("iwconfig wlan0 essid $connection key s:$pawd " ) ) { return 1; } else { return 0; } } #PROMPT sub prompt { my @txt = @_; print $txt[0]; chomp(my $choice = <STDIN>); return $choice; } #MENU sub menup { print <<HERE; Please select network by typing it`s name exactly. 1)If you want to connect to the network type "connectme" (you might require a password ) 2)If you want to stop all networks type "killme". 3)If you want to view network status and available networks, type "checkme". 4)If you want to load a network from existing nlog file type "loadme". 5)If you want to quit - type "exitme". HERE my $choice = &prompt(">> "); if ( $choice eq "connectme" ) { print "Available networks.... \n"; printf("%10s \n", &scan()); my $choice2 = &prompt(">> "); &connecd($choice2); } elsif ( $choice eq "killme" ) { system("killall dhcpcd"); } elsif ( $choice eq "checkme" ) { if ( &check() ) { print "Available networks are: \n"; print &scan(), "\n"; print "You are connected to the network\n"; } else { print "You are not connected \n"; } } elsif ( $choice eq "exitme" ) { print "Goodbye!\n"; } else { print "Error! I don`t know what [ $choice ] means ..\n"; &menup(); } } sub oscheck { my $pattern = ("iwlist scan"); if ( ! $pattern ) { print "You don`t have [ iwlist ] installed on your OS\n"; return 0; } else { return 1; } } ###################################################################### +######### my (@options) = @ARGV; # do we use the right ones? if ( &oscheck() ) { if ( $options[0] eq "-s" ) { &menup(); } elsif ( $options[0] eq "-p" ) { &record(); } else { print "Error command!\nPLease use -s for scan or -p for print +to file(WIP)\n"; } } else { print "Are we using LINX shell?\n"; }

Replies are listed 'Best First'.
Re: arch linux small app in perl
by jwkrahn (Abbot) on Feb 27, 2012 at 10:16 UTC
    #!/usr/bin/perl -w

    The first line begins with a space character which means that this will not work properly on Linux unless explicitly called by perl on the command line.    To run this as a stand-alone program the first two characters must be '#!'.

    Also, most modern perl programs use the warnings pragma instead of the -w command line switch.    See: perllexwarn for details.



    my $scanned = `iwlist scan`; ... my @lines = split(/\n/, $scanned);

    Could also be written as:

    chomp( my @lines = `iwlist scan` );

    But if you want better error information you might want to use open instead.



    if ( $pat =~ m/"/i ) {

    The /i option is for a case insensitive match but as far as I know the character '"' does not have different upper and lower versions.



    if ( $_ =~ m/ttl/i || $_ =~ m/rtt/i) {

    That could be more concisely written as:

    if ( /ttl|rtt/i ) {


    #trims all quotes from the ESSID string sub trim { my @tr = @_; my @trimmed = split(/"/, $tr[0]); return @trimmed; } ... my $connection = &trim($conn[0]);

    trim() returns an array, and an array in scalar context returns the number of elements in the array:

    $ perl -le' sub test { my @array = "a" .. "z"; # 26 elements return @array; } my $stuff = test(); print $stuff; ' 26

    So your $connection variable will always contain a numerical value.    Perhaps you want something like this instead:

    ( my $connection = $conn[ 0 ] ) =~ tr/"//d;


    Please select network by typing it`s name

    "it`s" is the contraction of "it is", the possessive form does not have an apostrophe.



    The use of an ampersand in subroutine calls is Perl4 style, it is not usually used in Perl5.

    Some uses of @array, and then just using $array[0], can be simplified by just using a single scalar instead.

    The use of a single string with system might be better with a list instead.

      OK, I`ll fix it. The question is how the statement:

       return @some_array;

      would not return all array values like return $a, $b $c... etc? My trim() returned the names without the ' " '. I am still getting used to perl`s syntax since I came from JS/HTML/C. I`ll make it more readable in the future.

      I got the error!

      my @connection = &trim($conn[0]); if (system("iwconfig wlan0 essid $connection[0] key s:$pawd " +) ) { return 1; }

      This should fix it, right?

        The question is how the statement:
        return @some_array;
        would not return all array values like return $a, $b $c... etc?

        Because the subroutine is called in SCALAR context and the context affects the return value(s).    A list (like $a, $b, $c) called in SCALAR context would return the last element of the list.    You can use the wantarray operator to determine what context the subroutine was called in.



        I got the error!

        What error did you get?



        my @connection = &trim($conn[0]); if (system("iwconfig wlan0 essid $connection[0] key s:$pawd " ) ) {

        Now you are calling trim in LIST context but you appear to only need the first element of the returned list.    Perhaps you should only return the first element if that is all you require:

        sub trim { my ( $tr ) = @_; return ( split /"/, $tr )[ 0 ]; }