Perl; socket

2010-04-10 Thread Niko zuna
Hi,
I have made a TCP socket, both a server and a client, and it works just
fine, except from the fact that I cant receive more than one input line from
the server when I execute a Unix command trough the socket. And when I am
trying to send a ps command from the client to the server to count how many
proc a certain user are running, the client does not receive the output,
like the server does.

This problem is a bit hard to explain, so please se my two scripts for more:

*server.pl*

#!/usr/bin/perl

# Needed pkg
use Getopt::Std;
use strict vars;

# Global variables
my $VERBOSE = 0;
my $DEBUG = 0;


# handle flags and
# Example: c == -c, c: == -c argument
my $opt_string = 'hvdk:p:';
getopts( $opt_string, \my %opt ) or usage() and exit 1; # exit other than
0 = error!!

# print help message if -h is invoked
if ( $opt{'h'} ){
usage();
exit 0;
}

$VERBOSE = 1 if $opt{'v'};
$DEBUG = 1 if $opt{'d'};
my $PORT = $opt{'p'};

if ( not $PORT ) {
   print You need to apply a port number;
   usage();
   exit 1;
}

# main program content
use IO::Socket;
$SIG{CHILD} = IGNORE; # Enable us to not make the children hangout and
wait for the parent to die, (children will die)

my  $sock = new IO::Socket::INET(
LocalPort = $PORT,
Proto = 'tcp',
Listen = SOMAXCONN,
Reuse = 1
);

if ( $sock ) {
print Waiting for clients...\n;
while ( my $connection = $sock-accept() ){
my $pid = fork(); # how the server knows if the porc is parent (pid =
xxx) or child (0)
if ( $pid == 0 ) {
my $client = $connection-peerhost(); # use $connection instead of
$sock to get ipaddr
print Connection to the $client\n;

my $buffer = $connection;
chomp $buffer;
print Client said: '$buffer'\n;
# sleep 7;

print $connection Message recived: $buffer\n;

close($connection);
exit; # server child should die after finish the conversation
} else {
close($connection);
next;
}
  }
} else {
die Error: $!\n;
}

close($sock);

verbose(verbose\n);
debug(noe\n);



##
# Helper routines

sub usage {
# print the correct use of this script
  print Usage:\n;
  print -hUsage\n;
  print -vVerbose\n;
  print -dDebug\n;
}

sub verbose {
print $_[0] if ( $VERBOSE or $DEBUG );
}

 sub debug {
print $_[0] if ( $DEBUG );
}


*client.pl *

#!/usr/bin/perl

# Needed pkg
use Getopt::Std;
use strict vars;

# Global variables
my $VERBOSE = 0;
my $DEBUG = 0;


# handle flags and
# Example: c == -c, c: == -c argument
my $opt_string = 'hvdk:p:H:c:';
getopts( $opt_string, \my %opt ) or usage() and exit 1; # exit other than
0 = error!!

# print help message if -h is invoked
if ( $opt{'h'} ){
usage();
exit 0;
}

$VERBOSE = 1 if $opt{'v'};
$DEBUG = 1 if $opt{'d'};
my $PORT = $opt{'p'};
my $SERVER = $opt{'H'};
my $COMMAND = $opt{'c'};

if ( not ( $PORT and $SERVER )){
print You need to supply a port number and hostname\n;
usage();
exit 1;
}


# main program content

use IO::Socket;

my $connection = new IO::Socket::INET(
PeerAddr = $SERVER,
PeerPort = $PORT,
Proto = 'tcp'
) or die Failed to connect: $!\n;

if ( $connection ) {
 print Connection etablished...\n;

# print $connection hello world!\n;
# print $connection Isabelle says hello\n;

 my $load = `uptime | awk '{print \$8   \$9   \$10   \$11  
\$12}'`;
 my $uptime = `uptime | awk '{print \$2   \$3   \$4}'`;
 my $mem_tot = `cat /proc/meminfo | grep MemTotal`;


 if ($COMMAND =~ m/load/){
  print $connection $load;
 }

 if ($COMMAND =~ m/uptime/){
 print $connection $uptime;
 }

 if ($COMMAND =~ m/memory/){
 print $connection $mem_tot\n;
 }

 if ($COMMAND =~ m/user:/){

 while ($COMMAND){
 my @array = split(:, $COMMAND);
 my $user = $array[1];
 my $ps = `ps aux | grep $user | wc -l`;
 print $connection $ps;
 sleep 7;
 }
 }

 # $mem_free\n$mem_buff\nswa_tot\n$swa_free\n;
#  print $connection `$COMMAND`;

 my $response = $connection;

 print Server replied: '$response'\n;

 close($connection);
}


##
# Helper routines

sub usage {
# print the correct use of this script
  print Usage:\n;
  print -hUsage\n;
  print -vVerbose\n;
  print -dDebug\n;
  print -pPort\n;
  print -HHost/Server\n;

}

sub verbose {
$_[0] if ( $VERBOSE or $DEBUG );
}

sub debug {
print $_[0] if ( $DEBUG );
}


Re: Perl; socket

2010-04-10 Thread Uri Guttman
 Nz == Niko zuna niko.z...@gmail.com writes:

  Nz #!/usr/bin/perl

  Nz # Needed pkg

no need for comments like that.
  Nz use Getopt::Std;

use Getopt::Long instead. you can still have short names but also long
names. 

  Nz use strict vars;

why 'vars'? just plain strict is better.

  Nz # Global variables

again, a useless comment. this is like saying $i++ # add 1 to $i

  Nz my $VERBOSE = 0;
  Nz my $DEBUG = 0;

  Nz 
  Nz # handle flags and
  Nz # Example: c == -c, c: == -c argument

  Nz my $opt_string = 'hvdk:p:';
  Nz getopts( $opt_string, \my %opt ) or usage() and exit 1; # exit other 
than
  Nz 0 = error!!

be careful how you paste code into email or other places. that word
wrapped and would break if i tried to cut/paste it to run here.

  Nz # print help message if -h is invoked
  Nz if ( $opt{'h'} ){
  Nz usage();
  Nz exit 0;
  Nz }

  Nz $VERBOSE = 1 if $opt{'v'};
  Nz $DEBUG = 1 if $opt{'d'};
  Nz my $PORT = $opt{'p'};

  Nz if ( not $PORT ) {
  Nzprint You need to apply a port number;
  Nzusage();
  Nzexit 1;
  Nz }

put all that arg processing into a sub. it makes it easier to manage and
also to read the code. i call it process_options() and put it at the
bottom of the script out of the way.

  Nz # main program content
  Nz use IO::Socket;
  Nz $SIG{CHILD} = IGNORE; # Enable us to not make the children hangout and
  Nz wait for the parent to die, (children will die)

  Nz my  $sock = new IO::Socket::INET(

use direct method calls. this was discussed here very recently.

IO::Socket::INET-new(


  Nz LocalPort = $PORT,
  Nz Proto = 'tcp',
  Nz Listen = SOMAXCONN,
  Nz Reuse = 1
  Nz );

  Nz if ( $sock ) {
  Nz print Waiting for clients...\n;
  Nz while ( my $connection = $sock-accept() ){
  Nz my $pid = fork(); # how the server knows if the porc is parent (pid =
  Nz xxx) or child (0)
  Nz if ( $pid == 0 ) {
  Nz my $client = $connection-peerhost(); # use $connection instead of
  Nz $sock to get ipaddr
  Nz print Connection to the $client\n;

  Nz my $buffer = $connection;
  Nz chomp $buffer;
  Nz print Client said: '$buffer'\n;
  Nz # sleep 7;

  Nz print $connection Message recived: $buffer\n;

you only read one line there. if you want to read multiple lines you
need to loop until you detect eof or some end of command line you send
from the client.

  Nz close($connection);
  Nz exit; # server child should die after finish the conversation
  Nz } else {
  Nz close($connection);
  Nz next;
  Nz }
  Nz   }
  Nz } else {
  Nz die Error: $!\n;
  Nz }

that should be:

$socket or die Error: $!\n;

then the good socket code follows inline with no block. no need for
if/else and blocks and extra indents.


  Nz close($sock);

  Nz verbose(verbose\n);
  Nz debug(noe\n);



  Nz ##
  Nz # Helper routines

again, useless comments.

put the process_options sub down here. it will be easier to edit these
if they are near each other.

  Nz sub usage {
  Nz # print the correct use of this script
  Nz   print Usage:\n;
  Nz   print -hUsage\n;
  Nz   print -vVerbose\n;
  Nz   print -dDebug\n;
  Nz }

  Nz sub verbose {
  Nz print $_[0] if ( $VERBOSE or $DEBUG );
  Nz }

  Nz  sub debug {
  Nz print $_[0] if ( $DEBUG );
  Nz }


many of the comments above are also for the client code.


  Nz my $COMMAND = $opt{'c'};

  Nz if ( not ( $PORT and $SERVER )){
  Nz print You need to supply a port number and hostname\n;
  Nz usage();
  Nz exit 1;
  Nz }


  Nz # main program content

  Nz use IO::Socket;

  Nz my $connection = new IO::Socket::INET(
  Nz PeerAddr = $SERVER,
  Nz PeerPort = $PORT,
  Nz Proto = 'tcp'
  Nz ) or die Failed to connect: $!\n;


  Nz if ( $connection ) {
  Nz  print Connection etablished...\n;

  Nz # print $connection hello world!\n;
  Nz # print $connection Isabelle says hello\n;

  Nz  my $load = `uptime | awk '{print \$8   \$9   \$10   \$11  
  Nz \$12}'`;
  Nz  my $uptime = `uptime | awk '{print \$2   \$3   \$4}'`;
  Nz  my $mem_tot = `cat /proc/meminfo | grep MemTotal`;

why execute all the command when only one is needed? this is a waste of
cpu.

  Nz  if ($COMMAND =~ m/load/){
  Nz   print $connection $load;
  Nz  }

those are multiple lines of text. you print them to the socket but the
server only reads one line and closes the connection. 

  Nz  if ($COMMAND =~ m/uptime/){
  Nz  print $connection $uptime;
  Nz  }

  Nz  if ($COMMAND =~ m/memory/){
  Nz  print $connection $mem_tot\n;
  Nz  }

  Nz  if ($COMMAND =~ m/user:/){

use a dispatch table (google for that). then you have a sub for each
command which will execute the command and send the output to the
socket. or 

Re: Modules download from CPAN

2010-04-10 Thread Alan Haggai Alavi
Hi,

CPAN::Mini can be used to create/update local mirrors. minicpan script 
(http://search.cpan.org/perldoc?minicpan) which uses CPAN::Mini will be 
helpful in maintaining a local CPAN mirror.

Regards,
Alan Haggai Alavi.
-- 
The difference makes the difference.

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: Modules download from CPAN

2010-04-10 Thread Shawn H Corey

Alan Haggai Alavi wrote:

Hi,

CPAN::Mini can be used to create/update local mirrors. minicpan script 
(http://search.cpan.org/perldoc?minicpan) which uses CPAN::Mini will be 
helpful in maintaining a local CPAN mirror.


If you're going to working on CPAN, you should sign up for the CPAN 
mailing lists:  http://lists.perl.org/tag/cpan.html



--
Just my 0.0002 million dollars worth,
  Shawn

Programming is as much about organization and communication
as it is about coding.

I like Perl; it's the only language where you can bless your
thingy.

Eliminate software piracy:  use only FLOSS.

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: Getting a subroutine reference from an object instance

2010-04-10 Thread Peter Scott
On Fri, 09 Apr 2010 16:34:27 +0200, Eric Veith1 wrote:

 Peter,
 I suspect you would have an easier time if you wrote what sounds like a
 largish project using Moose and composed in a forkable role.  If you
 must
 use method attributes there is MooseX::MethodAttributes but (and I am
 getting beyond my experience here) it does not appear popular.
 
 Hm, what else would you have prefered? Right now I use a r/o attribute
 to set up a per-class list of methods that do not fork (actually, more
 commands *do* fork than not). Method attributes would have eliminated
 some typos. *grin*

You appear to be further along than your original post suggested to me.  
Well, it's an interesting problem.  I've not done much advanced Moose, 
although I'd like to.  You could define a forkable role with before and 
after hooks to do the forking, but that requires retyping the method 
names, so I see the appeal of using attributes to label forking methods. 
Then I wonder about moving all the forkable methods to their own file and 
using meta to apply the forkability, but I am getting out of my depth.

You'd probably benefit from taking this to a Moose list.

-- 
Peter Scott
http://www.perlmedic.com/ http://www.perldebugged.com/
http://www.informit.com/store/product.aspx?isbn=0137001274
http://www.oreillyschool.com/courses/perl1/

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Feeding ouput from Net::Telnet into sub

2010-04-10 Thread Joseph L. Casale
I get a page full of output from a command passed into a Net::Telnet session
that as per the cpan example is stored in $output. I then want to call a sub
passing $output into it, that matches a string against each line, and sets a
a var to OK if the match is successful.

All is well, but I am unclear on the correct way to loop through each line in
$output, when I simply print it, it appears over several lines in the terminal.

When I run it into my sub, its being treated as one line?

sub parse_output {
foreach (@_) {
chomp($_);
print Line: $_\n;
if ( $_ =~ /$match/ ) {
$status = OK;
next;
}
}
}

parse_output($output);

It only prints one Line: although it works as it sets $status?

What am I missing?
Thanks!
jlc




--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: Feeding ouput from Net::Telnet into sub

2010-04-10 Thread Uri Guttman
 JLC == Joseph L Casale jcas...@activenetwerx.com writes:

  JLC I get a page full of output from a command passed into a
  JLC Net::Telnet session that as per the cpan example is stored in
  JLC $output. I then want to call a sub passing $output into it, that
  JLC matches a string against each line, and sets a a var to OK if
  JLC the match is successful.

  JLC All is well, but I am unclear on the correct way to loop through
  JLC each line in $output, when I simply print it, it appears over
  JLC several lines in the terminal.

  JLC When I run it into my sub, its being treated as one line?

you need to show how you call this sub and its input. there is no way to
diagnose it from just this code.

  JLC sub parse_output {
  JLC foreach (@_) {

use a named variable with foreach loops. sure some docs and examples
show using the default $_ but it can have problems with action at a
distance. also a name makes the code read better.

  JLC chomp($_);

if you do use $_, there is no need to pass it to many ops including
chomp. chomp by itself does the same thing.

  JLC print Line: $_\n;
  JLC if ( $_ =~ /$match/ ) {

again, m// will match against $_ so either don't bind to it or bind to a
named variable (or some expression).

and where does $match get set? it must be from outside the sub so it is
a global. bad!

  JLC $status = OK;

same with status. either declare it locally and return it or do
something else but don't set globals just to mark something as ok

  JLC next;
  JLC }
  JLC }
  JLC }

  JLC parse_output($output);

  JLC It only prints one Line: although it works as it sets $status?

works in what way? if i pass it one line with something that matches, it
will pass that 'test'.

  JLC What am I missing?

more code and data. use Data::Dumper to show exactly what you are
passing in.

uri

-- 
Uri Guttman  --  u...@stemsystems.com    http://www.sysarch.com --
-  Perl Code Review , Architecture, Development, Training, Support --
-  Gourmet Hot Cocoa Mix    http://bestfriendscocoa.com -

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




RE: Feeding ouput from Net::Telnet into sub

2010-04-10 Thread Joseph L. Casale
use a named variable with foreach loops. sure some docs and examples
show using the default $_ but it can have problems with action at a
distance. also a name makes the code read better.

Ok, simple enough to do.

and where does $match get set? it must be from outside the sub so it is
a global. bad!

Well $match comes from Getopt::Long, it has to be global, no? Now I'm confused:)

same with status. either declare it locally and return it or do
something else but don't set globals just to mark something as ok

Soon after posting I realized it was cleaner to return the value...

more code and data. use Data::Dumper to show exactly what you are
passing in.

I used Data::Dumper to see what was actually being passed and it takes
the following form:

$VAR1 = 'system status
   system status: Normal

hostname';

Sorry for the noobish question, but I am not sure how to interpret this?
I assumed this was 4 lines of text, but I guess not?

Thanks for the help!
jlc

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: Feeding ouput from Net::Telnet into sub

2010-04-10 Thread Uri Guttman
 JLC == Joseph L Casale jcas...@activenetwerx.com writes:

   use a named variable with foreach loops. sure some docs and examples
   show using the default $_ but it can have problems with action at a
   distance. also a name makes the code read better.

  JLC Ok, simple enough to do.

   and where does $match get set? it must be from outside the sub so it is
   a global. bad!

  JLC Well $match comes from Getopt::Long, it has to be global, no? Now I'm 
confused:)

nothing HAS to be global. you can pass it to a sub, you can store the
options in a hash (my way and easy with getopt::long), etc. some globals
may be useful but always using them or not know other ways is bad.

   same with status. either declare it locally and return it or do
   something else but don't set globals just to mark something as ok

  JLC Soon after posting I realized it was cleaner to return the value...

   more code and data. use Data::Dumper to show exactly what you are
   passing in.

  JLC I used Data::Dumper to see what was actually being passed and it takes
  JLC the following form:

  JLC $VAR1 = 'system status
  JLCsystem status: Normal

  JLC hostname';

  JLC Sorry for the noobish question, but I am not sure how to interpret this?
  JLC I assumed this was 4 lines of text, but I guess not?

no. it is a single string with 4 lines in it. why would you think
foreach would loop over its lines vs its single string? arrays can
contain strings without lines and a scalar could contain a single string
with lines. so foreach is neutral and just loops over what you pass it
in terms of perl elements. if you want lines, split them yourself or get
them some other way. e.g. backticks in a list context will split its
output into lines for you. i dunno how you are doing this telnet thing
(as i said SHOW MORE/ALL CODE :).

uri

-- 
Uri Guttman  --  u...@stemsystems.com    http://www.sysarch.com --
-  Perl Code Review , Architecture, Development, Training, Support --
-  Gourmet Hot Cocoa Mix    http://bestfriendscocoa.com -

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




RE: Feeding ouput from Net::Telnet into sub

2010-04-10 Thread Joseph L. Casale
nothing HAS to be global. you can pass it to a sub, you can store the
options in a hash (my way and easy with getopt::long), etc. some globals
may be useful but always using them or not know other ways is bad.

Ok, fair enough.

no. it is a single string with 4 lines in it. why would you think
foreach would loop over its lines vs its single string? arrays can
contain strings without lines and a scalar could contain a single string
with lines. so foreach is neutral and just loops over what you pass it
in terms of perl elements. if you want lines, split them yourself or get
them some other way. e.g. backticks in a list context will split its
output into lines for you. i dunno how you are doing this telnet thing
(as i said SHOW MORE/ALL CODE :).

Well the rest of the code _only_ does the telnet part and has too much
hardcoded stuff atm. It works perfectly as per cpan docs.

I'm just stuck on formatting the sub to match a string, just don't know
enough about Perl:)

I think I have it:

sub parse_output {
my ( $string, $match ) = @_;
die Error in parse_output sub\n unless ((defined $string) || (defined 
$match));
if ( $string =~ /$match/ ) {
return OK;
} else {
return CRITICAL;
}
}

$status = parse_output($output, $expect);
print Status: $status\n;

From what I can see, this follows all the suggestions you have provided?
Thanks for all your help!
jlc

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: Feeding ouput from Net::Telnet into sub

2010-04-10 Thread Uri Guttman
 JLC == Joseph L Casale jcas...@activenetwerx.com writes:

   nothing HAS to be global. you can pass it to a sub, you can store the
   options in a hash (my way and easy with getopt::long), etc. some globals
   may be useful but always using them or not know other ways is bad.

  JLC Ok, fair enough.

that is true for all programming, not just perl.

  JLC Well the rest of the code _only_ does the telnet part and has too much
  JLC hardcoded stuff atm. It works perfectly as per cpan docs.

so it could still likely use a review. especially if you are learning
perl. many doc examples aren't written to the best coding standards.

  JLC I think I have it:

  JLC sub parse_output {
  JLC my ( $string, $match ) = @_;

better.
  JLC die Error in parse_output sub\n unless ((defined $string) || 
(defined $match));

don't put the \n in the die string so it will report the line number
too. and your boolean test is wrong. you want both to be defined. and
even defined is overkill if you know you have text and a match
string. unless either is just '' or '0' they will be true. so that line
can be:

die Error in parse_output sub unless $string  $match ;

  JLC if ( $string =~ /$match/ ) {
  JLC return OK;
  JLC } else {
  JLC return CRITICAL;
  JLC }

that is a very odd indent style. the returns should be indented the
same. the }else and close should be left indented one more. like this:

if ( $string =~ /$match/ ) {
return OK;
}
else {
return CRITICAL;
}


  JLC $status = parse_output($output, $expect);
  JLC print Status: $status\n;

   From what I can see, this follows all the suggestions you have provided?

and there are more! always more. :)

uri

-- 
Uri Guttman  --  u...@stemsystems.com    http://www.sysarch.com --
-  Perl Code Review , Architecture, Development, Training, Support --
-  Gourmet Hot Cocoa Mix    http://bestfriendscocoa.com -

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




RE: Feeding ouput from Net::Telnet into sub

2010-04-10 Thread Joseph L. Casale
so it could still likely use a review. especially if you are learning
perl. many doc examples aren't written to the best coding standards.

I'll take you up on that once its supposedly done:)

Many great tips, thanks for all the help!
jlc

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/