ofproto: Drop remote command execution feature.
[openvswitch] / debian / reconfigure
1 #! /usr/bin/perl
2
3 use POSIX;
4 use strict;
5 use warnings;
6
7 my $default = '/etc/default/openvswitch-switch';
8
9 my (%config) = load_config($default);
10 if (@ARGV) {
11     foreach my $arg (@ARGV) {
12         my ($key, $value) = $arg =~ /^([^=]+)=(.*)/
13           or die "bad argument '$arg'\n";
14         if ($value ne '') {
15             $config{$key} = $value;
16         } else {
17             delete $config{$key};
18         }
19     }
20     save_config($default, %config);
21 }
22 print "$_=$config{$_}\n" foreach sort(keys(%config));
23
24 sub load_config {
25     my ($file) = @_;
26
27     # Get the list of the variables that the shell sets automatically.
28     my (%auto_vars) = read_vars("set -a && env");
29
30     # Get the variables from $default.
31     my (%config) = read_vars("set -a && . '$default' && env");
32
33     # Subtract.
34     delete @config{keys %auto_vars};
35
36     return %config;
37 }
38
39 sub read_vars {
40     my ($cmd) = @_;
41     local @ENV;
42     if (!open(VARS, '-|', $cmd)) {
43         print STDERR "$cmd: failed to execute: $!\n";
44         return ();
45     }
46     my (%config);
47     while (<VARS>) {
48         my ($var, $value) = /^([^=]+)=(.*)$/ or next;
49         $config{$var} = $value;
50     }
51     close(VARS);
52     return %config;
53 }
54
55 sub shell_escape {
56     local $_ = $_[0];
57     if ($_ eq '') {
58         return '""';
59     } elsif (m&^[-a-zA-Z0-9:./%^_+,]*$&) {
60         return $_;
61     } else {
62         s/'/'\\''/;
63         return "'$_'";
64     }
65 }
66
67 sub shell_assign {
68     my ($var, $value) = @_;
69     return $var . '=' . shell_escape($value);
70 }
71
72 sub save_config {
73     my ($file, %config) = @_;
74     my (@lines);
75     if (open(FILE, '<', $file)) {
76         @lines = <FILE>;
77         chomp @lines;
78         close(FILE);
79     }
80
81     # Replace all existing variable assignments.
82     for (my ($i) = 0; $i <= $#lines; $i++) {
83         local $_ = $lines[$i];
84         my ($var, $value) = /^\s*([^=#]+)=(.*)$/ or next;
85         if (exists($config{$var})) {
86             $lines[$i] = shell_assign($var, $config{$var});
87             delete $config{$var};
88         } else {
89             $lines[$i] = "#$lines[$i]";
90         }
91     }
92
93     # Find a place to put any remaining variable assignments.
94   VAR:
95     for my $var (keys(%config)) {
96         my $assign = shell_assign($var, $config{$var});
97
98         # Replace the last commented-out variable assignment to $var, if any.
99         for (my ($i) = $#lines; $i >= 0; $i--) {
100             local $_ = $lines[$i];
101             if (/^\s*#\s*$var=/) {
102                 $lines[$i] = $assign;
103                 next VAR;
104             }
105         }
106
107         # Find a place to add the var: after the final commented line
108         # just after a line that contains "$var:".
109         for (my ($i) = 0; $i <= $#lines; $i++) {
110             if ($lines[$i] =~ /^\s*#\s*$var:/) {
111                 for (my ($j) = $i + 1; $j <= $#lines; $j++) {
112                     if ($lines[$j] !~ /^\s*#/) {
113                         splice(@lines, $j, 0, $assign);
114                         next VAR;
115                     }
116                 }
117             }
118         }
119
120         # Just append it.
121         push(@lines, $assign);
122     }
123
124     open(NEWFILE, '>', "$file.tmp") or die "$file.tmp: create: $!\n";
125     print NEWFILE join('', map("$_\n", @lines));
126     close(NEWFILE);
127     rename("$file.tmp", $file) or die "$file.tmp: rename to $file: $!\n";
128 }