1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
#! /usr/bin/perl
## $Id: innupgrade.in 6458 2003-09-03 02:58:51Z rra $
##
## Convert INN configuration files to the current syntax.
##
## Intended to be run during a major version upgrade, this script tries to
## convert existing INN configuration files to the syntax expected by the
## current version, if that's changed.
##
## Note that this script cannot use innshellvars.pl, since loading that file
## requires innconfval be able to parse inn.conf, and until this script runs,
## inn.conf may not be valid.
##
## Currently handles the following conversions:
##
## * Clean up inn.conf for the new parser in INN 2.4.
## * Add the hismethod parameter to inn.conf if not found.
require 5.003;
use strict;
use vars qw(%FIXES);
use subs qw(fix_inn_conf);
use Getopt::Long qw(GetOptions);
# The mappings of file names to fixes.
%FIXES = ('inn.conf' => \&fix_inn_conf);
# Clean up inn.conf for the new parser in INN 2.4. Null keys (keys without
# values) need to be commented out since they're no longer allowed (don't just
# remove them entirely since people may want them there as examples), and
# string values must be quoted if they contain any special characters. Takes
# a reference to an array containing the contents of the file, a reference to
# an array into which the output should be put, and the file name for error
# reporting.
sub fix_inn_conf {
my ($input, $output, $file) = @_;
my $line = 0;
my ($raw, $hismethod);
local $_;
for $raw (@$input) {
$_ = $raw;
$line++;
if (/^\s*\#/ || /^\s*$/) {
push (@$output, $_);
next;
}
chomp;
unless (/^(\s*)(\S+):(\s*)(.*)/) {
warn "$file:$line: cannot parse line: $_\n";
push (@$output, $_);
next;
}
my ($indent, $key, $space, $value) = ($1, $2, $3, $4);
if ($value eq '') {
push (@$output, "#$_\n");
next;
}
$hismethod = 1 if $key eq 'hismethod';
$value =~ s/\s+$//;
if ($value =~ /[\s;\"<>\[\]\\{}]/ && $value !~ /^\".*\"\s*$/) {
$value =~ s/([\"\\])/\\$1/g;
$value = '"' . $value . '"';
}
push (@$output, "$indent$key:$space$value\n");
}
# Add a setting of hismethod if one wasn't present in the original file.
unless ($hismethod) {
push (@$output, "\n# Added by innupgrade\nhismethod: hisv6\n");
}
}
# Upgrade a particular file. Open the file, read it into an array, and then
# run the fix function on it. If the fix function generates different output
# than the current contents of the file, change the file.
sub upgrade_file {
my ($file, $function) = @_;
open (INPUT, $file) or die "$file: cannot open: $!\n";
my @input = <INPUT>;
close INPUT;
my @output;
&$function (\@input, \@output, $file);
if (join ('', @input) ne join ('', @output)) {
if (-e "$file.OLD") {
if (-t STDIN) {
print "$file.OLD already exists, overwrite (y/N)? ";
my $answer = <STDIN>;
if ($answer !~ /y/i) {
die "$file: backup $file.OLD already exists, aborting\n";
}
} else {
die "$file: backup $file.OLD already exists\n";
}
}
print "Updating $file, old version saved as $file.OLD\n";
my ($user, $group) = (stat $file)[4,5];
open (OUTPUT, "> $file.new.$$")
or die "$file: cannot create $file.new.$$: $!\n";
print OUTPUT @output;
close OUTPUT or die "$file: cannot flush new file: $!\n";
unless (link ($file, "$file.OLD")) {
rename ($file, "$file.OLD")
or die "$file: cannot rename to $file.OLD: $!\n";
}
if ($> == 0) {
if (defined ($user) && defined ($group)) {
chown ($user, $group, "$file.new.$$")
or warn "$file: cannot chown $file.new.$$: $!\n";
} else {
warn "$file: cannot find owner and group of $file\n";
}
}
rename ("$file.new.$$", $file)
or die "$file: cannot replace with $file.new.$$: $!\n";
}
}
# Upgrade a directory. Scan the directory for files that have upgrade rules
# defined and for each one of those, try running the upgrade rule.
sub upgrade_directory {
my $directory = shift;
chdir $directory or die "Can't chdir to $directory: $!\n";
opendir (DIR, ".") or die "Can't opendir $directory: $!\n";
for (readdir DIR) {
if ($FIXES{$_}) {
upgrade_file ($_, $FIXES{$_});
}
}
closedir DIR;
}
# The main routine. Parse command-line options to figure out what we're
# doing.
my ($file, $type);
Getopt::Long::config ('bundling');
GetOptions ('file|f=s' => \$file,
'type|t=s' => \$type) or exit 1;
if ($file) {
my $basename = $file;
$basename =~ s%.*/%%;
$type ||= $basename;
if (!$FIXES{$type}) { die "No upgrade rules defined for $basename\n" }
upgrade_file ($file, $FIXES{$type});
} else {
if (@ARGV != 1) { die "Usage: innupgrade <directory>\n" }
my $directory = shift;
upgrade_directory ($directory);
}
|