File: innupgrade.in

package info (click to toggle)
inn2 2.4.5-5
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 8,912 kB
  • ctags: 7,860
  • sloc: ansic: 85,104; perl: 11,427; sh: 9,863; makefile: 2,498; yacc: 1,563; python: 298; lex: 252; tcl: 7
file content (152 lines) | stat: -rw-r--r-- 5,250 bytes parent folder | download
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);
}