How to find Subnet of the given IP using perl cgi? - perl

I need to find the subnet of any IP that user entered. I am executing the "ypcat -k netmasks.byaddr" unix command in perl to find netmasks. It is working fine in command line execution. But it is not working while executing in webserver.
The below is the code.
use strict;
use CGI;
my $page=new CGI;
print $page->header;
my $ipaddress=$page->param("ip");
my #splitted=split(/\./,$ipaddress);
my $part1=$splitted[0].".".$splitted[1].".".$splitted[2];
my $part2=$splitted[3];
my $comma1="ypcat -k netmasks.byaddr|grep -w $part1|awk '{print \$1}'|awk -F. '{print \$4}'|sort -g";
my $comm2="ypcat -k netmasks.byaddr|grep -w $part1|sort";
my #out=`$comm1`;
my #out2=`$comm2`;
my $match;my $sub;my $found;
foreach my $i(#out){
chomp($i);
if($part2 > $i){
$sub=$i;
$found=$part1.".".$sub;
}
}
my (#matched) = grep $_=~m/$found/, #out2;
chomp(#matched);
print "#matched\n";
The above is the code I am using to find subnet of the given IP. In that the execution of "$comm1" and "$comm2" is failing.
Is any other way to find subnet of the user entered IP using Perl script?
Thanks,
Madhan

You can use NetAddr::IP module for this job as given below:
#!/usr/local/bin/perl
use strict;
use warnings;
use CGI;
use NetAddr::IP;
my $page = new CGI;
print $page->header;
my $ipaddress = $page->param("ip");
my $ip = NetAddr::IP->new($ipaddress);
print "The address is ", $ip->addr, " with mask ", $ip->mask, "\n" ;

Related

Perl parameters passing with special characters

This is a pure Perl parameters passing issue. I cannot use Get::Opt as it is not installed on every machine.
I need to pass parameters with spaces and other special chars sometimes. Three scripts to demo the process. Is there a better way to do this?
[gliang#www stackoverflow]$ perl parameter_wrapper.pl
prep.pl #<5> parameters
prep_v2.pl #<5> parameters
<aaa_777-1>
<bbb-6666-2>
<Incomplete QA>
<-reason>
<too long, mail me at ben#example.com :)>
cat parameter_wrapper.pl
#!/usr/bin/perl -w
use strict;
# call prep.pl with 5 parameters
my $cmd = "./prep.pl aaa_777-1 bbb-6666-2 'Incomplete QA' -reason 'too long, mail me at ben\#example.com :)\n'";
system($cmd);
cat prep.pl
#!/usr/bin/perl -w
use strict;
my #parameters = #ARGV;
my $count = scalar(#parameters);
my #parameters_new = wrap_parameters(#parameters);
my $cmd = "./prep_v2.pl #parameters_new";
print "prep.pl #<$count> parameters\n";
system($cmd);
sub wrap_parameters {
my #parameters = #_;
my #parameters_new;
foreach my $var(#parameters) {
$var = quotemeta($var);
push(#parameters_new, $var);
}
return #parameters_new;
}
cat prep_v2.pl
#!/usr/bin/perl -w
use strict;
my #parameters = #ARGV;
my $count = scalar(#parameters);
print "prep_v2.pl #<$count> parameters\n";
foreach my $var (#parameters) {
#print "<$var>\n";
}
Getopt::Long has been part of the Perl core since Perl 5 was first released in 1994. Are you sure it's not available on the machines you're looking to deploy on? In your comment you refer to it as "Get::Opt", so could you have made a mistake while checking the machines?

CGI Printing issue

#!/usr/bin/perl -w
use CGI qw(:all);
use CGI::Carp qw(fatalsToBrowser);
use strict;
print "Content-type: text/plain\n";
print "\n";
my $date = system('date');
print "Date :: $date";
The above code keeps producing the output of Date :: 0 instead of the current date.
I can't find any solution for this problem. Please help.
Instead of using system command, use backtick. system command doesn't return value in a variable. Change this line:
my $date = system('date');
to
my $date = `date`;
See this for more understanding about system and backtick:
https://stackoverflow.com/a/800105/4248931
The return value of the system command is the return value of the call. For a successful call this will be 0. If you want to capture the output of a command use backticks or IPC. Look at this answer: Capture the output of Perl system()
my $date = `date`;
print "Date :: $date";
But better would be to use DateTime.

Using single quotes inside argument to recursive system bash call

I have a Perl script progA.pl which needs to run another Perl script progB.pl using the system command. However, progB.pl has been aliased in ~/.bashrc so I need to ensure that it is run after ~/.bashrc has been loaded. I can achieve this by using bash with the -lc option.
For this question, I simplify the problem as much as I think is needed, by considering the following version of progB.pl
use feature qw(say);
use strict;
use warnings;
use Data::Dump qw(dd dump);
say "Received \#ARGV: " . dump #ARGV;
and here is progA.pl:
use feature qw(say);
use strict;
use warnings;
use Data::Dump qw(dd dump);
my $cmd = qq(progB.pl --opt='This option contains '"'"'single'"'"' quotes');
say "cmd = " . dump($cmd);
system( "$cmd" );
say "-----";
system( 'bash -c ' . "$cmd" );
say "-----";
system( 'bash -c ' . "'$cmd'" );
say "-----";
system( "bash -c \"$cmd\"" );
Running
$ progA.pl
gives output:
cmd = "progB.pl --opt='This option contains '\"'\"'single'\"'\"' quotes'"
Received #ARGV: "--opt=This option contains 'single' quotes"
-----
Received #ARGV: ()
-----
Received #ARGV: "--opt=This"
-----
Received #ARGV: "--opt=This option contains single quotes"
We see that this works fine, when progB.pl is run directly without using bash -c. When I use bash -c to run the command, none of the three alternatives are working correctly.
How can I run progB.pl with an argument containing single quotes and at the same time using using bash -c ?
You should avoid this quoting madness at first place but if you insist, you should avoid at least one level of quoting by using system ARRAY version.
my $cmd = q{progB.pl --opt='This option contains '"'"'single'"'"' quotes'};
system( qw(bash -c), $cmd );
It makes it only one level of quoting madness.
my $option = q{This option contains 'single' quotes} =~ s/'/'"'"'/gr; # '
my $cmd = qq{progB.pl --opt='$option'};
system( qw(bash -c), $cmd );
There you can make some simple helper
sub sq ($) { "'" . $_[0] =~ s/'/'"'"'/gr . "'" } # "
my $option = q{This option contains 'single' quotes};
my $cmd = qq{progB.pl --opt=#{[sq $option]}};
system( qw(bash -c), $cmd );
After some trial and error, I arrived at:
use feature qw(say);
use strict;
use warnings;
my $cmd = qq(print_first_arg.pl --opt='This option contains '"'"'single'"'"' quotes');
$cmd =~ s/'/'"'"'/g;
system( 'bash -c ' . "'$cmd'" );
It seems to work, for this test case at least..
This also follows the approach suggested by #ysth in this answer:
https://stackoverflow.com/a/24869016/2173773

Perl: Delete multiple lines from text file having a specific string

I have a text file having data in below mentioned format..
#rectype='ABC' #recname='123' #rec_id='1K2j' etc...
#rectype='DEF' #recname='matin' #rec_id='458i' etc...
#rectype='ABC' #recname='John' #rec_id='lom0' etc...
#rectype='GHI' #recname='Kalme, #rec_id='pl90' etc...
#rectype='KLM' #recname='Kitty' #rec_id='987k' etc...
#rectype='ABC' #recname='OMR' #rec_id='lo09' etc...
Now, I have to delete all the lines having #rectype='ABC'..there are multiple lines of this kind in the input file.It's a kind of urgent and as I am not a perl coder , I am finding it difficult to figure out the way.
Please suggest!!!
NOTE: I need to make changes in input file only. I don't need to create a seperate output file.
You don't need to do it in Perl. You can use the grep tool.
grep -v "#rectype='ABC'" input_file > output_file
grep -v means "Print every line that does not match this expression."
perl -i -ne 'print if !/\#rectype = \047ABC\047/x' text_file
#!/usr/bin/perl
use warnings;
use strict;
use File::Slurp;
my $output = 'output.txt';
open my $outfile, '>', $output or die "Can't write to $output: $!";
my #array = read_file('input.txt');
for (#array){
next if ($_ =~ /^\#rectype='ABC'/);
print $outfile $_ ;
}
Output (saved to 'output.txt'):
#rectype='DEF' #recname='matin' #rec_id='458i' etc...
#rectype='GHI' #recname='Kalme, #rec_id='pl90' etc...
#rectype='KLM' #recname='Kitty' #rec_id='987k' etc...

Perl and hosts file mapping question?

I have a hosts file that looks like this:
10.10.10.1 myserver1 myserver1alias
10.10.10.2 myserver2 myserver2alias
I'm looking for a way using perl to pass in an argument of myserver1 and have it return myserver1alias, likewise if I pass in myserver2 it should return myserver2alias. Any suggestions?
From the command line:
$ perl -lane 'print $F[-1] if $F[1] eq "myserver1"' /etc/hosts
while(<>){
if (/myserver1/){
#s = split /myserver1/,$_,2;
print $s[-1];
}
}
The quick-and-dirty way is:
perl -nE 'say $1 if /myserver1\s+(\w+)$/' path/to/hostfile
You might need to do queries similar to this from time to time, so you could probably make a reusable chunk of code to do this for you. Something like:
#!/usr/bin/perl
use strict;
use warnings;
use 5.10;
use HostFileParser;
my $host = HostFileParser->parse("path/to/hostfile")
my $server = $host->find(server => "myserver1")
say $server->alias;
Of course, I'm not going to "give you teh codez" for all of that. ;)
(These answers assume Perl 5.10, but if you don't have it the changes are just say $x => print "$x\n", or sub say { print "#_\n" }.)