diff --git a/New/compiler b/New/compiler index 0c4091f95..cacb361da 100755 --- a/New/compiler +++ b/New/compiler @@ -99,7 +99,7 @@ case "$COMMAND" in compile) [ $# -ne 2 ] && usage do_initialize - exec perl $debug /usr/share/shorewall/compiler.pl $1 + exec perl $debug /usr/share/shorewall/compiler.pl $(resolve_file $2) ;; *) usage diff --git a/New/compiler.pl b/New/compiler.pl index 3d0b6a8b0..a747456cc 100755 --- a/New/compiler.pl +++ b/New/compiler.pl @@ -1,6 +1,9 @@ #! /usr/bin/perl -w use strict; +use File::Basename; +use File::Temp qw/ tempfile tempdir /; + # # IPSEC Option types # @@ -137,6 +140,10 @@ my ( $command, $doing, $done ) = qw/ compile Compiling Compiled/; #describe the my $line; # Current config file line +my $object; # Object file Handle Reference + +my $indent = ''; + # # Zone Table. # @@ -418,6 +425,93 @@ sub default_yes_no ( $$ ) { } } +# +# Write the argument to the object file with the current indentation. +# +# Since emacs doesn't understand Perl's rendition of 'here documents', we +# use multi-line quoting instead. To make multi-line emit calls look better, +# we delete a leading newline and add one to the end. +# +sub emit ( $ ) { + my $line = $_[0]; + + $line =~ s/^\n//; + + if ( $indent || $line ) { + $line =~ s/^/$indent/; + $line =~ s/\n(.)/\n$indent$1/g; + } + + print $object "$line\n"; +} + +# +# Write passed message to the object with no indentation. +# + +sub emit_unindented( $ ) { + print $object $_[0]; +} + +# +# Write a progress_message2 command to the output file. +# +sub save_progress_message( $ ) { + print $object "\n"; + emit "progress_message2 $_[0]"; + print $object "\n"; +} + +sub save_progress_message_short( $ ) { + emit "progress_message $_[0]"; +} + +sub indent( $ ) { + my $file = $_[0]; + + open IF , $file or fatal_error "Unable to open $file: $!"; + + while ( my $line = ) { + $line =~ s/^/$indent/ if $indent; + print $object $line; + } + + close IF; +} + +sub indent1( $ ) { + my $file = $_[0]; + + open IF , $file or fatal_error "Unable to open $file: $!"; + + my $do_indent = 1; + + while ( my $line = ) { + if ( $line =~ /^\s+$/ ) { + print $object "\n"; + $do_indent = 1; + next; + } + + $line =~ s/^/$indent/ if $indent && $do_indent; + print $object $line; + $do_indent = ! ( $line =~ /\\$/ ); + } + + close IF; +} + +sub append_file( $ ) { + my $user_exit = find_file $_[0]; + + unless ( $user_exit =~ /$env{SHAREDIR}/ ) { + if ( -f $user_exit ) { + save_progress_message "Processing $user_exit ..."; + indent1 $user_exit; + } + } +} + # # Parse the passed option list and return a reference to a hash as follows: # @@ -5040,17 +5134,17 @@ sub generate_matrix() { } sub create_iptables_restore_file() { - print "#Generated by Shorewall $env{VERSION} - " . ( localtime ) . "\n"; + print $object "#Generated by Shorewall $env{VERSION} - " . ( localtime ) . "\n"; for my $table qw/raw nat mangle filter/ { - print "*$table\n"; + print $object "*$table\n"; my @chains; for my $chain ( grep $chain_table{$table}{$_}->{referenced} , ( sort keys %{$chain_table{$table}} ) ) { my $chainref = $chain_table{$table}{$chain}; if ( $chainref->{builtin} ) { - print ":$chainref->{name} $chainref->{policy} [0:0]\n"; + print $object ":$chainref->{name} $chainref->{policy} [0:0]\n"; } else { - print ":$chainref->{name} - [0:0]\n"; + print $object ":$chainref->{name} - [0:0]\n"; } push @chains, $chainref; @@ -5059,10 +5153,10 @@ sub create_iptables_restore_file() { for my $chainref ( @chains ) { my $name = $chainref->{name}; for my $rule ( @{$chainref->{rules}} ) { - print "-A $name $rule\n"; + print $object "-A $name $rule\n"; } } - print "COMMIT\n"; + print $object "COMMIT\n"; } } @@ -5327,8 +5421,36 @@ sub do_initialize() { sub compile_firewall( $ ) { my $objectfile = $_[0]; + my $tempfile; + my ( $dir, $file ); ( $command, $doing, $done ) = qw/ check Checking Checked / unless $objectfile; + + if ( $command eq 'compile' ) { + eval { + ( $file, $dir, my $suffix ) = fileparse( $objectfile ); + fatal_error "Directory $dir does not exist" unless -d $dir; + fatal_error "$dir is a Symbolic Link" if -l $dir; + fatal_error "$objectfile is a Directory" if -d $objectfile; + fatal_error "$dir is a Symbolic Link" if -l $objectfile; + fatal_error "$objectfile exists and is not a compiled script" if -e _ && ! -x _; + + ( $object, $tempfile ) = tempfile ( 'tempfileXXXX' , DIR => $dir ); + + $file = "$file.$suffix" if $suffix; + }; + + fatal_error "$@" if $@; + + my $date = localtime; + + emit " +# +# Compiled firewall script generated by Shorewall $env{VERSION} - $date +#"; + + } + # # Process the zones file. # @@ -5409,6 +5531,9 @@ sub compile_firewall( $ ) { # unless ( $command eq 'check' ) { progress_message2 "Creating iptables-restore input..."; create_iptables_restore_file; + $file = "$dir/$file"; + rename $tempfile, $file; + chmod 0700, $file; } }