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