Perl Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesPerl Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
Stay one step ahead of the competition. Evaluate and give feedback on some of the hottest web development tools on the market today. Make your opinion heard! Click Here
  #1  
Old December 28th, 2000, 01:07 AM
nebuchadnezzar nebuchadnezzar is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2000
Posts: 5 nebuchadnezzar User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via ICQ to nebuchadnezzar
Hi,

I'm trying to create a perl script to convert a couple of hundred modules, each containing lines of ipchains commands, to be used with iptables. I used to have just one big loop with a number of loops inside it to do this, but it got *slightly* complicated, and I decided to split it up into a function that converts the modules, and then one that replaces the old modules with the new modules.

However! I've come across a problem... When I run the script, I find that the script seems to loop the converting stage of the script. It does this for an uncountable number of times (I CAN post the output, if anyone wants... it makes patterns! ), and then moves onto the onto the next module in the directory. I have no idea why it does this!

Here is the script:

#!/usr/bin/perl -w

sub convert {
opendir(BASE_DIR, "/etc/firewall/modules/") or die "Can't open directory: $!";
@modules_base_dir = grep !/^..?z/, readdir BASE_DIR;
close(BASE_DIR);
foreach $priv_pub (@modules_base_dir) {
print "$priv_pubn";
print "-" x 3, ">";
print "n";
opendir(INTERFACE_DIR, "/etc/firewall/modules/$priv_pub") or die "Can't open directory: $!";
@modules_interface_dir = grep !/^..?z/, readdir INTERFACE_DIR;
close(INTERFACE_DIR);
foreach $module_type (@modules_interface_dir) {
print " $module_typen";
print " " , "=" , ">";
print "n";
opendir(FUNCTION_DIR, "/etc/firewall/modules/$priv_pub/$module_type") or die "Can't open directory: $!";
@modules_function_dir = grep !/.tmp$/, readdir FUNCTION_DIR;
close(FUNCTION_DIR);
foreach $module (@modules_function_dir) {
my $output = $module . ".tmp";
open(INFILE,"/etc/firewall/modules/$priv_pub/$module_type/$module") or die "Can't open module: $!n";
open(OUTFILE, ">/etc/firewall/modules/$priv_pub/$module_type/$output") or die "Can't open temp file: $!n";
my $converted = <INFILE>;
while (<INFILE> ) {
print " Converting $module (writing to $output)...";
$converted =~ s/ipchains/iptables/g;
print OUTFILE "$converted";
$converted = <INFILE>;
}
print "Done!nn" if -e "/etc/firewall/modules/$priv_pub/$module_type/$output";
}
}
}
}

sub move {
opendir(MOVE_BASE_DIR, "/etc/firewall/modules/") or die "Can't open directory: $!";
@move_modules_base_dir = grep /.tmp$/, readdir MOVE_BASE_DIR;
close(MOVE_BASE_DIR);
foreach $priv_pub (@move_modules_base_dir) {
print "$priv_pubn";
print "-" x 3, ">";
print "n";
opendir(MOVE_INTERFACE_DIR, "/etc/firewall/modules/$priv_pub") or die "Can't open directory: $!";
@move_modules_interface_dir = grep /.tmp$/, readdir MOVE_INTERFACE_DIR;
close(MOVE_INTERFACE_DIR);
foreach $module_type (@move_modules_interface_dir) {
print " $module_typen";
print " " , "=" , ">";
print "n";
opendir(MOVE_FUNCTION_DIR, "/etc/firewall/modules/$priv_pub/$module_type") or die "Can't open directory: $!";
@move_modules_function_dir = grep /.tmp$/, readdir MOVE_FUNCTION_DIR;
close(MOVE_FUNCTION_DIR);
foreach $module (@move_modules_function_dir) {
my $old_file = $module;
$old_file =~ s/.tmp//;
rename("/etc/firewall/modules/$priv_pub/$module_type/$module", "/etc/firewall/modules/$priv_pub/$module_type/$old_file");
print "Moved $module to $old_filen" if -e "/etc/firewall/modules/$priv_pub/$module_type/$old_file";
}
}
}
}

convert();
move();

---

If anyone could provide any hints or point out flaws, that would be great! I am stumped, and I cannot see any errors, even when I compare the syntax in the script to the syntaxes of the functions O'Reilly book that I have.

Thanks!!!

Reply With Quote
  #2  
Old December 28th, 2000, 09:40 PM
vpopper's Avatar
vpopper vpopper is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2000
Location: Southern California
Posts: 73 vpopper User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 m 24 sec
Reputation Power: 9
<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>
my $converted = <INFILE>;
while (<INFILE> ) {
print " Converting $module (writing to $output)...";
$converted =~ s/ipchains/iptables/g;
print OUTFILE "$converted";
$converted = <INFILE>;
}
[/code]

Why not just do this:

<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>
while ($converted = <INFILE> ) {
print " Converting $module (writing to $output)...";
$converted =~ s/ipchains/iptables/g;
print OUTFILE "$converted";
}
[/code]



[This message has been edited by vpopper (edited December 28, 2000).]

Reply With Quote
  #3  
Old December 28th, 2000, 09:47 PM
nebuchadnezzar nebuchadnezzar is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2000
Posts: 5 nebuchadnezzar User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via ICQ to nebuchadnezzar
<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">quote:</font><HR>Originally posted by vpopper:
<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>
my $converted = <INFILE>;
while (<INFILE> ) {
print " Converting $module (writing to $output)...";
$converted =~ s/ipchains/iptables/g;
print OUTFILE "$converted";
$converted = <INFILE>;
}
[/code]

Why not just do this:

<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>
while ($converted = <INFILE> ) {
print " Converting $module (writing to $output)...";
$converted =~ s/ipchains/iptables/g;
print OUTFILE "$converted";
}
[/code]
[/quote]

wouldn't I have to do "my $converted; $converted = <INFILE>;" beforehand though?

I put the while(...) in there to check that <INFILE> was still valid, so it didn't just convert nothing.

thanks

Reply With Quote
  #4  
Old December 28th, 2000, 11:14 PM
vpopper's Avatar
vpopper vpopper is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2000
Location: Southern California
Posts: 73 vpopper User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 m 24 sec
Reputation Power: 9
<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">quote:</font><HR>Originally posted by nebuchadnezzar:
wouldn't I have to do "my $converted; $converted = <INFILE>;" beforehand though?

I put the while(...) in there to check that <INFILE> was still valid, so it didn't just convert nothing.
[/quote]

You can make sure you have something to convert by using a regular expression:

<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>
while ($converted = <INFILE> ) {
next unless $converted =~ m{S+};
[/code]

or use a regexp that matches what you're looking for...


Reply With Quote
  #5  
Old December 28th, 2000, 11:18 PM
nebuchadnezzar nebuchadnezzar is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2000
Posts: 5 nebuchadnezzar User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via ICQ to nebuchadnezzar
Something like this?:

<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>my $converted = <INFILE>;
while ($converted =~ /ipchains/) {
print " Converting $module (writing to $output)...";
$converted =~ s/ipchains/iptables/g;
print OUTFILE "$converted";
} [/code]

Reply With Quote
  #6  
Old December 28th, 2000, 11:37 PM
vpopper's Avatar
vpopper vpopper is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2000
Location: Southern California
Posts: 73 vpopper User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 m 24 sec
Reputation Power: 9
If I understand your code correctly, you're looping through lines in the file, converting the line, then writing to another file.

If this is true, the reason that your code is looping uncontrollably is because:

This line reads a line from the infile and stores it in $converted

my $converted = <INFILE>;

This line also reads a line from the infile, but stores it in $_

while (<INFILE> ) {

...and so on.

What you want to do is loop through the lines in the file by reading the line, coverting it, then printing it out. Here's a shortcut:

<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>
while (<INFILE> ) {
chomp;
next unless /ipchains/;
print " Converting $module (writing to $output)...";

s/ipchains/iptables/g;
print OUTFILE "$_n";
}
[/code]

Now the line is read into $_, the line is skipped if it doesn't contain 'ipchains' (is this what you want?), the line is converted and written to the outfile.



[This message has been edited by vpopper (edited December 28, 2000).]

Reply With Quote
  #7  
Old December 28th, 2000, 11:43 PM
nebuchadnezzar nebuchadnezzar is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2000
Posts: 5 nebuchadnezzar User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via ICQ to nebuchadnezzar
kind of. What I am trying to do is convert about 100 or more files stored within a number of sub-dirs contained in /etc/firewall/modules , and I want to convert every occurence of ipchains into iptables.

I will try what you just posted, though. Thanks.



[This message has been edited by nebuchadnezzar (edited December 28, 2000).]

Reply With Quote
  #8  
Old December 29th, 2000, 12:30 AM
vpopper's Avatar
vpopper vpopper is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2000
Location: Southern California
Posts: 73 vpopper User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 m 24 sec
Reputation Power: 9
<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">quote:</font><HR>Originally posted by nebuchadnezzar:
[B]kind of. What I am trying to do is convert about 100 or more files stored within a number of sub-dirs contained in /etc/firewall/modules , and I want to convert every occurence of ipchains into iptables.[/B/[/quote]

This is untested, but should work:

<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>
#!/usr/bin/perl

require 5.004;
$| = 1;
umask(022); # change if neccessary

use strict;
use vars qw($BASEDIR @FILES);

$BASEDIR = '/etc/firewall/modules';

die "Invalid BASEDIR!n" unless -d $BASEDIR;

CLS();
INVERSE();
print " Conversion in Progress...", " " x 25, "nn";
NORMAL();

# collect files
print "Collecting files............ ";
chdir $BASEDIR or die "Cannot cd to $BASEDIR: $!n";
&traverse($BASEDIR,(stat('.'))[3]);
printf "%d files found.n", scalar(@FILES);

convert(@FILES);

print "n*All Done*n";
exit;

#==========================================================================
# traverse() -

sub traverse {
my ($dir,$nlink) = @_;
my (@filenames,@subdirs);

opendir DIR, '.' or die "cannot opendir $dir: $!n";
@filenames = grep { !/^..?$/ && !(-l $_) } readdir DIR;
closedir DIR;

for (@filenames) {
next unless stat($_) && -r _;
-d _ && push(@subdirs,$_);
-f _ && -s _ && -T _ && push(@FILES,"$dir/$_");
}

# has subdirs
if ($nlink != 2) {
for (@subdirs) {
chdir $_ or die "cannot cd to $_: $!n";
traverse("$dir/$_",(stat('.'))[3]);
chdir '..';
}
}
}

#==========================================================================
# convert() -

sub convert {
my @files = @_;

foreach my $file (sort @files) {
next unless $file =~ m{$BASEDIR/([^/]+)/([^/]+)/(.+)$};
print "Converting: $1 => $2 => $3 ... ";

open IN, "<$BASEDIR/$1/$2/$3"
or die "Cannot open $BASEDIR/$1/$2/$3: $!n";

open OUT, ">$BASEDIR/$1/$2/$3.tmp"
or die "Cannot open $BASEDIR/$1/$2/$3.tmp: $!n";

while (<IN> ) {
chomp;
next unless m{ipchains};
s{ipchains}{iptables}g;
print OUT "$_n";
}

unless (-e "$BASEDIR/$1/$2/$3.tmp") {
print "Failed.n";
next;
}

print "Succeeded.n";
system("/bin/mv $BASEDIR/$1/$2/$3.tmp $BASEDIR/$1/$2/$3");
die "$!n" if $!;
}

return 1;
}

#==========================================================================
# magic terminal controllers (may not work on your system)

sub CLS { print "e[;He[2J"; } # clear screen
sub INVERSE { print "e[7m"; } # inverse screen
sub NORMAL { print "e[0m"; } # normal screen


[/code]

Reply With Quote
  #9  
Old December 29th, 2000, 12:53 AM
nebuchadnezzar nebuchadnezzar is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2000
Posts: 5 nebuchadnezzar User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via ICQ to nebuchadnezzar
OK... that IS a big difference from the original script...

I have no idea whatsoever about what it does! This is my first script, so I'd aprreciate it if you were able to go through and explain what some of the lines do?

Thanks

Reply With Quote
  #10  
Old December 29th, 2000, 01:20 AM
nebuchadnezzar nebuchadnezzar is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2000
Posts: 5 nebuchadnezzar User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via ICQ to nebuchadnezzar
ok... I've decided to have a go at it for myself, might be educational...

from what I can see, at the beginning, you chdir to $BASEDIR, which has been set to /etc/firewall/modules, then traverse starts at . (which happens to be $BASEDIR, as set by &traverse($BASEDIR, ...)).

Then... it does the equivalent of 'ls' and stores it in the array @filenames, and from there works out whether the variables stored in @filenames are directories or other types of files using the -r switch, right?

I don't know what $nlink does, but it then goes into @subdirs and chdirs to the directories in @subdirs, and then changes dirs to $dir/$_ , which would be /etc/firewall/modules/$dir/$_ , correct? I have NO idea what the stat thing does...

then, after that, the convert function is called, and because of the <BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>my @files = @_ [/code] there, it assigns @files to @FILES, because convert was called using convert(@FILES), am I correct? Then, <IN> and <OUT> are created (I don't know what $1, $2, and $3 do, though).

This is where I get slightly confused:

<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">code:</font><HR><pre>while (<IN> ) {
chomp;
next unless m{ipchains};
s{ipchains}{iptables}g;
print OUT "$_n";
} [/code]

what does the 'm' in front of {ipchains} do?

also, shouldn't s{ipchains}{iptables}g be s/ipchains/iptables ? (correct me if I'm wrong!)

thanks...

Reply With Quote
  #11  
Old December 31st, 2000, 08:38 PM
nebuchadnezzar nebuchadnezzar is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2000
Posts: 5 nebuchadnezzar User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via ICQ to nebuchadnezzar
vpopper - I tried the script you posted, and it worked without any errors (running with -w), but it sseems to only copy the iptables commands to the new modules. What would be good is if all the comments in each of the files was copied along with the new iptables commands.

Do you know how I might be able to do this?

Also, what does the stat function do? I noticed that it is used a couple of times, but I have been unable to understand what it does exactly.

Thanks

Reply With Quote
  #12  
Old January 1st, 2001, 03:44 AM
vpopper's Avatar
vpopper vpopper is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2000
Location: Southern California
Posts: 73 vpopper User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 m 24 sec
Reputation Power: 9
<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">quote:</font><HR>Originally posted by nebuchadnezzar:
vpopper - I tried the script you posted, and it worked without any errors (running with -w), but it sseems to only copy the iptables commands to the new modules. What would be good is if all the comments in each of the files was copied along with the new iptables commands.[/quote]

Just take out this line:
next unless m{ipchains};

<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">quote:</font><HR>Also, what does the stat function do?[/quote]

The stat function returns a 13-element array giving the statistics for a file. Typically used as follows:

($dev,$ino,$mode,$nlink,$uid,$gid,$gid,
$rdev,$size,$atime,$mtime,$ctime,$blksize,
$blocks) = stat($filename);

In my code example, I use stat in the 'traverse' routine to determine the number of directory links. If the number is not equal to 2 (. and ..) then there must be subdirectories. If there are subdirectories, we traverse down the subdirectories in a recursive file search.

Also in 'traverse' we use call stat() on the file in preparation for a number of file tests. We make sure it is not a symbolic link, that it is readable, that it is a regular text file, that it has a positive size value, etc.

Try 'man stat' on your system for more info, or read "Programming Perl".

Hope this helps :-)


Reply With Quote
  #13  
Old January 1st, 2001, 03:53 AM
nebuchadnezzar nebuchadnezzar is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2000
Posts: 5 nebuchadnezzar User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via ICQ to nebuchadnezzar
<BLOCKQUOTE><font size="1" face="Verdana,Arial,Helvetica">quote:</font><HR>Originally posted by vpopper:
Try 'man stat' on your system for more info, or read "Programming Perl".

Hope this helps :-)

[/quote]

Ok... thanks! I do have the O'Reilly book - Programming Perl, but I haven't read all of it (let alone the first couple of sections), yet.

Thanks for your help. I'll try and adapt what you've posted.

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesPerl Programming > some looping problems with a perl script...


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump