#! /usr/bin/perl -w ## Copyright (C) 1998 Hrvoje Niksic ## Modification by Zeljko Boros (block entries, removing old entries) ## More options and use strict by Zoran Dzelajlija on 2004-02-24 ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## $Id: cp-update,v 2.2 2004/02/24 jelly Exp $ use strict; my ($name, $usage); ($name = $0) =~ s%.*/%%; # Looks nicer without the slashes $usage = "Usage:\n"; $usage .= "$name [-r] [-m] [-i AFTER|-t] [-b START -e STOP] [-c CHAR] PACKAGE FILE\n"; $usage .= " -r Remove entry PACKAGE from FILE\n"; $usage .= " Default is to add lines from stdin.\n"; $usage .= " -m Allow multiple blocks of the same type\n"; $usage .= " By default, old blocks are replaced with the new one.\n"; $usage .= "\n"; $usage .= " Special placement of config blocks:\n"; $usage .= " -i Insert after this line\n"; $usage .= " -t Insert on top\n"; $usage .= " The default is to append at the bottom.\n"; $usage .= "\n"; $usage .= " Manipulating block marks:\n"; $usage .= " -c Use alternative comment character (default: #)\n"; $usage .= " Alternative block marks:\n"; $usage .= " -b Start mark (ie 'service ftp')\n"; $usage .= " -e Stop mark (ie. '}')\n"; $usage .= " These will delete to the end of the file if no end mark\n"; $usage .= " is found. The deletion is otherwise not greedy and\n"; $usage .= " stops at the first end mark found. You can use\n"; $usage .= " %P to insert the PACKAGE argument, and\n"; $usage .= " %% to insert a literal % sign into the mark.\n"; my ($begin, $end, $trailer); my ($parambegin, $paramend, $insert); my ($pkg, $file); my ($block, $multi, $addafter, $addontop); my $add = 1; my $comment = "#"; my $SEEK_END = 2; while (@ARGV) { $_ = shift; if (/^-c$/ || /^--comment$/) { defined ($comment = shift) || die "$name: `-c' must be followed by an argument\n"; } elsif (/^-r$/ || /^--remove$/) { $add = 0; } elsif (/^-m$/ || /^--allow-multiple$/) { $multi = 1; } elsif (/^-b$/ || /^--begin$/) { defined ($parambegin = shift) || die "$name: '-b' must be followed by an argument\n"; $block = 1; } elsif (/^-e$/ || /^--end$/) { defined ($paramend = shift) || die "$name: '-e' must be followed by an argument\n"; $block = 1; } elsif (/^-i$/ || /^--insert-after$/) { defined($insert = shift) || die "$name: '-i' must be followed by an anrgument\n"; #$multi = 1; # uncomment for -i backward compatibility $addafter = 1; } elsif (/^-t$/ || /^--insert-on-top$/) { $insert = ""; $addafter = 1; } elsif (/^-/) { die "$name: Unrecognized option \`$_'\n"; } else { unshift(@ARGV, $_); last; } } ($pkg = shift) || die $usage; ($file = shift) || die $usage; (! $block || ($parambegin && $paramend)) || die ("$name: must provide both begin and end marks.\n"); if ($block) { $parambegin =~ s,%P,$pkg,g; $parambegin =~ s,%%,%,g; $paramend =~ s,%P,$pkg,g; $paramend =~ s,%%,%,g; $begin = $parambegin; $end = $paramend; $trailer = ""; } else { $begin = "$comment Begin update by CARNet package $pkg"; $end = "$comment End update by CARNet package $pkg"; $trailer = " -- DO NOT DELETE THIS LINE!"; } if ($add) { if (! $multi) { &del; } &add; } else { &del; } sub add() { $trailer .= "\n"; $begin .= $trailer; $end .= $trailer; my $byte = ""; # @#$@#$@#$$@#$@#$#@$! -w my $prefix = ""; open (HANDLE, "<$file") || die "$file: $!\n"; # Need to load it all into memory if we want to write it # out to the same file. my @lines = if ($addafter); # If FILE does not have a trailing newline, be suire to add it # before appending anything else. # Unless it is size 0! if ((-s $file)) { seek HANDLE, -1, $SEEK_END; defined (read HANDLE, $byte, 1) && ($byte ne "\n") && ($prefix = "\n"); close HANDLE; } if(!$addafter) { # The actual work is in the following three lines: open (HANDLE, ">>$file") || die "$file: $!\n"; print HANDLE $prefix . $begin . join('', ) . $end; close HANDLE; } else { # Overwrite it open (HANDLE, ">$file") || die "$file: $!\n"; my $added = 0; foreach (@lines) { if (! $added && /^$insert/o) { print HANDLE if ($insert ne ""); print HANDLE $begin . join('', ) . $end; print HANDLE if ($insert eq ""); $added = 1; } else { print HANDLE; } } if(! $added) { print HANDLE $prefix . $begin . join('', ) . $end; } close HANDLE; } } sub del() { # saving vars for &add function... my ($mybegin, $myend, $mytrailer); $mybegin = $begin; $myend = $end; $mytrailer = $trailer; # Make the strings regexp-friendly by quoting non-word chars. $mybegin =~ s/\W/\\$&/g; $myend =~ s/\W/\\$&/g; $mytrailer =~ s/\W/\\$&/g; open (HANDLE, "<$file") || die "$file: $!\n"; # Need to load it all into memory, because we'll want to write it # out to the same file. my @lines = ; close HANDLE; open (HANDLE, ">$file") || die "$file: $!\n"; foreach (@lines) { print HANDLE unless (/^$mybegin(?:$mytrailer)?$/o .. /^$myend(?:$mytrailer)?$/o); } close HANDLE; }