1: #!/usr/bin/perl
2:
3: # loncaparestoreconfigurations - restore data to new LON-CAPA conf files
4: #
5: # $Id: loncaparestoreconfigurations,v 1.13 2002/05/16 00:20:30 harris41 Exp $
6: #
7: # YEAR=2000
8: # 10/25, 12/14 Scott Harrison
9: # YEAR=2002
10: # Scott Harrison, 05/15
11: #
12: ###
13:
14: # This tool helps in updating a system. It restores information for
15: # configuration files (.lpmlsave or other backup notations).
16:
17: # By default, the .lpmlsave suffix is used.
18: # Alternatively, there can be two other invocations
19: # Invocation #1:
20: # ARGV[0]=suffix
21: # ARGV[1]=.bak
22: # Invocation #2:
23: # ARGV[0]=lasttimestamp
24:
25: # The criteria for the lasttimestamp is that the
26: # file suffix is a '.' followed by a 14-digit
27: # time-stamp (YYYYMMDDhhmmss).
28: # The time-stamp with the greatest value is
29: # taken as the backup file.
30:
31: # --------------------------------------------- Define program version variable
32: $VERSION = sprintf("%d.%02d", q$Revision: 1.13 $ =~ /(\d+)\.(\d+)/);
33:
34: # ---------------------------------------------- Process command-line arguments
35: my $suffix='.lpmlsave';
36: my $suffixpragma='';
37: if ($ARGV[0] eq 'suffix') {
38: $suffix=$ARGV[1] if $ARGV[1]=~/^[\.\w]+$/;
39: }
40: elsif ($ARGV[0] eq 'lasttimestamp') {
41: $suffixpragma='lasttimestamp';
42: }
43:
44: use strict; # restrict unsafe and poorly coded constructs
45:
46: # ------------------------------------ Configuration files to be concerned with
47: my @special_conf_files=(
48: '/etc/httpd/conf/loncapa.conf',
49: '/etc/httpd/conf/access.conf',
50: '/etc/smb.conf',
51: '/etc/samba/smb.conf'
52: );
53:
54: my %pvar; # store the PerlSetVar variable key/value combinations
55:
56: # --------------------------------------------- Process the configuration files
57: # NOTE that I have structured this processing to make NO assumptions
58: # about the processing of each configuration file. So, in terms
59: # of keeping each file's processing algorithms self-contained, I am not
60: # modularizing things (where it is obvious that they might be modularized.)
61: CONFLOOP: foreach (@special_conf_files) {
62:
63: my $lpmlold; # holds information that needs to be read
64: my $lpmlnew; # holds information that needs to be modified
65:
66: my $lpmlnew_file; # file location of information that needs to be modified
67:
68: # ------------------------------------------- access.conf (becoming deprecated)
69: if (/^\/etc\/httpd\/conf\/access.conf$/ and
70: -e '/etc/httpd/conf/access.conf') {
71: if ($suffixpragma eq 'lasttimestamp' and
72: -e '/etc/httpd/conf/access.conf'.$suffix) {
73: $suffix=&getsuffix('/etc/httpd/conf/access.conf');
74: unless (-e '/etc/httpd/conf/access.conf'.$suffix) {
75: next CONFLOOP;
76: }
77: $lpmlold="\n".&readfile('/etc/httpd/conf/access.conf'.$suffix);
78: $lpmlnew_file='/etc/httpd/conf/access.conf';
79: $lpmlnew=&readfile($lpmlnew_file);
80: }
81: else {
82: $lpmlold="\n".&readfile('/etc/httpd/conf/access.conf');
83: $lpmlnew_file='/etc/httpd/conf/access.conf'.$suffix;
84: unless (-e $lpmlnew_file) {
85: next CONFLOOP;
86: }
87: $lpmlnew=&readfile($lpmlnew_file);
88: }
89: while($lpmlold=~/\n\s*PerlSetVar\s+(\S+)\s+(\S+)/mcg) {
90: my $pkey=$1; my $pval=$2;
91: $lpmlnew=~s/(\n\s*PerlSetVar\s+$pkey\s+)\S+/$1$pval/;
92: $pvar{$pkey}=$pval;
93: }
94: }
95:
96: # ---------------------------------------------------------------- loncapa.conf
97: elsif (/^\/etc\/httpd\/conf\/loncapa.conf$/ and
98: -e '/etc/httpd/conf/loncapa.conf') {
99: if ($suffixpragma eq 'lasttimestamp' and
100: -e '/etc/httpd/conf/loncapa.conf') {
101: $suffix=&getsuffix('/etc/httpd/conf/loncapa.conf');
102: unless (-e '/etc/httpd/conf/loncapa.conf'.$suffix) {
103: next CONFLOOP;
104: }
105: $lpmlold="\n".&readfile('/etc/httpd/conf/loncapa.conf'.$suffix);
106: $lpmlnew_file='/etc/httpd/conf/loncapa.conf';
107: $lpmlnew=&readfile($lpmlnew_file);
108: }
109: else {
110: $lpmlold="\n".&readfile('/etc/httpd/conf/loncapa.conf');
111: $lpmlnew_file='/etc/httpd/conf/loncapa.conf'.$suffix;
112: unless (-e $lpmlnew_file) {
113: next CONFLOOP;
114: }
115: $lpmlnew=&readfile($lpmlnew_file);
116: }
117: while($lpmlold=~/\n\s*PerlSetVar\s+(\S+)\s+(\S+)/mcg) {
118: my $pkey=$1; my $pval=$2;
119: $pvar{$pkey}=$pval;
120: }
121: foreach my $pkey (keys %pvar) {
122: my $pval=$pvar{$pkey};
123: $lpmlnew=~s/(\n\s*PerlSetVar\s+$pkey\s+)\S+/$1$pval/;
124: }
125: open(OUT,'>'.$lpmlnew_file) or
126: die('Cannot open '.$lpmlnew_file.' for output'."\n");
127: print(OUT $lpmlnew);
128: close(OUT);
129: }
130:
131: # -------------------------------------------------------------------- smb.conf
132: elsif (/^\/etc\/smb.conf$/ and -e "/etc/smb.conf$suffix") {
133: if ($suffixpragma eq 'lasttimestamp') {
134: $suffix=&getsuffix('/etc/smb.conf');
135: unless (-e '/etc/httpd/conf/loncapa.conf'.$suffix) {
136: next CONFLOOP;
137: }
138: $lpmlnew=&readfile('/etc/smb.conf');
139: $lpmlnew_file='/etc/smb.conf';
140: }
141: else {
142: $lpmlnew=&readfile('/etc/smb.conf'.$suffix);
143: $lpmlnew_file='/etc/smb.conf'.$suffix;
144: }
145: $lpmlnew=~s/\{\{\{\{\[(.*?)\]\}\}\}\}/$pvar{$1}/ge;
146: open(OUT,'>'.$lpmlnew_file) or
147: die('Cannot open '.$lpmlnew_file.' for output'."\n");
148: print(OUT $lpmlnew);
149: close(OUT);
150: }
151: elsif (/^\/etc\/samba\/smb.conf$/ and -e "/etc/samba/smb.conf$suffix") {
152: if ($suffixpragma eq 'lasttimestamp') {
153: $suffix=&getsuffix('/etc/samba/smb.conf');
154: unless (-e '/etc/samba/smb.conf'.$suffix) {
155: next CONFLOOP;
156: }
157: $lpmlnew=&readfile('/etc/samba/smb.conf');
158: $lpmlnew_file='/etc/samba/smb.conf';
159: }
160: else {
161: $lpmlnew=&readfile('/etc/samba/smb.conf'.$suffix);
162: $lpmlnew_file='/etc/samba/smb.conf'.$suffix;
163: }
164: $lpmlnew=~s/\{\{\{\{\[(.*?)\]\}\}\}\}/$pvar{$1}/ge;
165: open(OUT,'>'.$lpmlnew_file) or
166: die('Cannot open '.$lpmlnew_file.' for output'."\n");
167: print(OUT $lpmlnew);
168: close(OUT);
169: }
170: }
171:
172: # --------------------------------- getsuffix: get the latest time stamp suffix
173: # === INPUT: filename without suffix
174: # === OUTPUT: the latest time stamp suffix; 14 digits YYYYMMDDhhmmss
175: # === ERROR: cannot read the directory in which the filenames reside
176: sub getsuffix {
177: my ($file)=@_;
178: print("$file\n");
179: my $dir=$file; $dir=~s/([^\/]+)$//;
180: my $filename=$1;
181: opendir(DIR,$dir) or
182: die('Cannot open directory '.$dir.' for viewing'."\n");
183: my @a=grep {/$filename\.\d{14}/} readdir(DIR);
184: closedir(DIR);
185: map {s/$filename\.//;} @a;
186: my @b=sort {$a<=>$b} @a;
187: my $suffix='.'.$b[$#b];
188: return($suffix);
189: }
190:
191: # -------------------------- readfile: get the file contents in a scalar string
192: # === INPUT: filename
193: # === OUTPUT: the filename's contents
194: # === ERROR: cannot read the file
195: # === NOTE: big files will hog computer memory
196: sub readfile {
197: my ($filename)=@_;
198: my $contents='';
199: open(IN,'<'.$filename) or die ('Cannot read '.$filename."\n");
200: while(<IN>) {$contents.=$_;}
201: close(IN);
202: return($contents);
203: }
204:
205: =pod
206:
207: =head1 NAME
208:
209: B<loncaparestoreconfigurations> - restore data to new LON-CAPA conf files
210:
211: =head1 SYNOPSIS
212:
213: perl loncaparestoreconfigurations suffix .lpmlnew
214:
215: =head1 DESCRIPTION
216:
217: During software upgrades, it is possible that configuration files will change.
218: It is important to "intelligently" preserve the machine-specific configuration
219: data. This script is meant to run B<after> the software upgrade.
220:
221: For example, consider the configuration file F<loncapa.conf>.
222: During the software upgrade (not performed by by F<loncapa.conf>),
223: the following happens:
224:
225: loncapa.conf is NOT overwritten
226:
227: rather,
228:
229: a NEW file B<loncapa.conf.lpmlnew> is GENERATED
230: (cp UPGRADEDIR/loncapa.conf SYSTEMDIR/loncapa.conf.lpmlnew)
231:
232: This script can be described as:
233:
234: =over 4
235:
236: =item *
237:
238: modifying SYSTEMDIR/loncapa.conf.lpmlnew, and
239:
240: =item *
241:
242: the modification consists of reading values from the old loncapa.conf and
243: placing them in loncapa.conf.lpmlnew.
244:
245: =back
246:
247: Regarding F<loncapa.conf>, for backwards compatibility, this script tries
248: to read values out of F<access.conf>.
249:
250: This script also currently works with F<smb.conf> (a standard Linux
251: configuration file associated with sharing the Linux filesystem with
252: Windows machines).
253:
254: =head2 Working with the file suffix
255:
256: The script is designed to work according to two strategies.
257:
258: =over 4
259:
260: =item * B<aggressive update>
261:
262: In the aggressive update strategy, two things should happen:
263:
264: =over 4
265:
266: =item * The configuration file should be replaced
267:
268: Therefore, the system administrator "trusts" the software update process
269: and this script to handle everything correctly.
270:
271: =item * Information should never be lost
272:
273: Therefore, a backup copy should be made that is unique to the time
274: the action is taken and is never overwritten or destroyed by the
275: automated process.
276:
277: =back
278:
279: =item * B<passive assistance>
280:
281: =over 4
282:
283: =item * The configuration file should not be replaced
284:
285: The system administrator does not trust the software update process.
286: She would rather have a new file "intelligently" generated, and, only
287: by her direct approval, have the new file substitute the contents
288: of the current configuration file.
289:
290: =item * The script should try to help the system administrator
291:
292: Therefore, a new copy is made with the suffix ".lpmlnew". This
293: new copy is modified with data from the existing configuration file.
294: The system administrator is prompted (by the rest of the software
295: upgrade process) to resolve the new changes to the configuration
296: file.
297:
298: =back
299:
300: =back
301:
302: Correspondingly,
303:
304: perl loncaparestoreconfigurations suffix .lpmlnew
305:
306: invokes this script in B<passive assistance> mode; whereas
307:
308: perl loncaparestoreconfigurations lasttimestamp
309:
310: invokes this script in B<aggressive update> mode.
311:
312: =head1 AUTHORS
313:
314: Scott Harrison
315:
316: This module is free software; you can redistribute it
317: and/or modify it under the same terms as LON-CAPA itself.
318:
319: =cut
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>