This commit was manufactured by cvs2svn to create tag
[opensuse:installation-images.git] / lib / ReadConfig.pm
1 #! /usr/bin/perl -w
2
3 # Read the config file ('etc/config') and set up some useful variables.
4 # Exports some useful functions, too.
5 #
6 # Usage:
7 #
8 #   use ReadConfig;
9 #
10 #   exported functions:
11 #     Print2File(file_name, print_args);
12 #     SUSystem(command);
13 #
14 #   exported arrays:
15 #     %ConfigData
16 #
17 #   exported variables:
18 #     $Script, $BasePath, $LibPath, $BinPath, $CfgPath, $ImagePath,
19 #     $DataPath, $TmpBase, $MToolsCfg, $AutoBuild
20 #
21 #   symbols *not* exported by default:
22 #     $SUBinary, DebugInfo
23
24 =head1 ReadConfig
25
26 C<ReadConfig> is a perl module that reads config data from C<etc/config>
27 initializes a few global variables and exports some useful functions. It
28 should always be included in scripts operating within the C<bootdisk>
29 directory hierarchy.
30
31 It assumes that the script that included this library was either called from
32 the base directory or from the C<bin> subdirectory of the base directory.
33 The base directory itself may be located anywhere.
34
35 This is mainly to avoid an environment variable to hold the base directory
36 (like C<BOOTDISK_ROOT> or something similar).
37
38 For the curious: the regular expression used to find the base directory name
39 from the full script name is:
40
41 C<( $0 =~ /(.*?)((?<![^\/])bin\/)?([^\/]+)$/ )[0]>
42
43 =head2 Usage
44
45 C<BEGIN { unshift @INC, ( $0 =~ /(.*?)((?<![^\/])bin\/)?[^\/]+$/ )[0] . "lib" }>
46
47 C<use ReadConfig;>
48
49 =head2 Description
50
51 =over
52
53 =item *
54
55 C<Print2File(file_name, print_args)>
56
57 C<Print2File(file_name, print_args)> opens the file C<file_name> and prints
58 to it. C<print_args> are the arguments that would be given to a normal
59 C<print> command. It's mainly for convenience.
60
61 =for html <p>
62
63 =item *
64
65 C<SUSystem(command)>
66
67 C<SUSystem(command)> executes C<command> with root permissions. This
68 requires a special 'C<sudo>' command to be installed that can give you root
69 privileges without asking for a password. The name of this command is
70 C</usr/local/sw> and can only be changed by editing the C<ReadConfig.pm>
71 file.
72
73 This allows you to run the bootdisk scripts as a normal user.
74
75 If you don't have such a program or are running the scripts as root, C<SUSystem> is
76 I<identical> to the usual C<system> command.
77
78 You can check if this feature is actually available by looking at the
79 C<$ReadConfig::SUBinary> variable that holds the name of the 'C<sudo>'
80 command (or C<undef>).
81
82 =for html <p>
83
84 =item *
85
86 C<%ConfigData>
87
88 C<%ConfigData> is an hash table that holds the config info read from C<etc/config>.
89 C<etc/config> is a shell script that may contain I<only> variable assignments.
90
91 =for html <p>
92
93 =item *
94
95 exported variables
96
97 =over
98
99 =item *
100
101 C<$Script> is the name of the script that included this library (without the path).
102
103 =item *
104
105 C<$BasePath> holds the name of the base directory.
106
107 =item *
108
109 C<$LibPath = "$BasePath/lib">.
110
111 =item *
112
113 C<$BinPath = "$BasePath/bin">. The C<PATH> environment variable is
114 appropriately extended.
115
116 =item *
117
118 C<$CfgPath = "$BasePath/etc">.
119
120 =item *
121
122 C<$ImagePath = "$BasePath/images">.
123
124 =item *
125
126 C<$DataPath = "$BasePath/data">.
127
128 =item *
129
130 C<$TmpBase> is the name used for temporary file/directory names.
131
132 =item *
133
134 C<$MToolsCfg> is the name of a temporary C<mtools> config file. The
135 C<MTOOLSRC> environment variable is set to point to it.
136
137 =back
138
139 =for html <p>
140
141 =item *
142
143 symbols that are not exported
144
145 =over
146
147 =item *
148
149 C<DebugInfo()> prints the current values of some variables.
150
151 =item *
152
153 C<$SUBinary> (see C<SUSystem> above).
154
155 =back
156
157 =back
158
159 =cut
160
161
162 package ReadConfig;
163
164 require Exporter;
165 @ISA = qw ( Exporter );
166 @EXPORT = qw (
167   $Script $BasePath $LibPath $BinPath $CfgPath $ImagePath $DataPath
168   $TmpBase %ConfigData RPMFileName SUSystem Print2File $MToolsCfg $AutoBuild
169 );
170
171 use strict 'vars';
172 use vars qw (
173   $Script $BasePath $LibPath $BinPath $CfgPath $ImagePath $DataPath
174   $TmpBase %ConfigData $SUBinary &RPMFileName &SUSystem &Print2File $MToolsCfg $AutoBuild
175 );
176
177 sub DebugInfo
178 {
179   local $_;
180
181   print "Script = \"$Script\"\n";
182   print "BasePath = \"$BasePath\"\n";
183   print "LibPath = \"$LibPath\"\n";
184   print "BinPath = \"$BinPath\"\n";
185   print "CfgPath = \"$CfgPath\"\n";
186   print "ImagePath = \"$ImagePath\"\n";
187   print "DataPath = \"$DataPath\"\n";
188   print "TmpBase = \"$TmpBase\"\n";
189   print "MToolsCfg = \"$MToolsCfg\"\n";
190
191   print "ConfigData:\n";
192   for (sort keys %ConfigData) {
193     print "  $_ = \"$ConfigData{$_}\"\n"
194   }
195 }
196
197 #
198 #
199 #
200 sub RPMFileName
201 {
202   my ($rpm, $file, @f, $x);
203   local $_;
204
205   $rpm = shift;
206
207   $file = $ConfigData{'cache_dir'};
208
209   if($ConfigData{'use_cache'} && $file && -f "$file/$rpm.rpm") {
210
211     # print "*$rpm: $file/$rpm.rpm\n";
212
213     return "$file/$rpm.rpm";
214   }
215
216   $file = $ConfigData{'tmp_cache_dir'};
217
218   if($file && -d $file) {
219     $file .= "/.rpms";
220     mkdir $file, 0755 unless -d $file;
221     $file .= "/$rpm.rpm";
222
223     # print "#$rpm: $file\n" if -f $file;
224
225     return $file if -f $file;
226   }
227
228   undef $file;
229
230   for (`cat $ConfigData{'suse_base'}/find-name-rpm 2>/dev/null`) {
231     chomp;
232     s/^\.\///;
233     if(m#/(\Q$rpm\E|\Q$rpm\E\-[^\-]+\-[^\-]+\.[^.\-]+)\.rpm$#) {
234       $file = "$ConfigData{'suse_base'}/$_";
235       last;
236     }
237   }
238
239   if(!$file) {
240     @f = glob "$ConfigData{'suse_base'}/$rpm.rpm";
241     if($f[0] && -f $f[0]) {
242       $file = $f[0];
243     }
244   }
245
246   if(!$file) {
247     @f = glob "$ConfigData{'suse_base'}/$rpm-*-*.rpm";
248     for (@f) {
249       next if /\.src\.rpm$/;
250       if($_ && -f $_ && m#/\Q$rpm\E\-[^\-]+\-[^\-]+\.[^.\-]+\.rpm$#) {
251         $file = $_;
252         last;
253       }
254     }
255   }
256
257   $x = $ConfigData{'tmp_cache_dir'};
258
259   if($file && $x && -d($x)) {
260     $x .= "/.rpms";
261     mkdir $x, 0755 unless -d $x;
262     if(-d $x) {
263       symlink($file, "$x/$rpm.rpm");
264     }
265   }
266
267   # print "$rpm: $file\n" if $file;
268
269   return $file;
270 }
271
272
273 #
274 # execute string as root
275 #
276 sub SUSystem
277 {
278   if($SUBinary) {
279     return system "$SUBinary -q 0 $_[0]";
280   }
281   else {
282     return system @_;
283   }
284 }
285
286 #
287 # print to a file
288 #
289 sub Print2File
290 {
291   local $_ = shift;
292
293   open Print2File_F, ">$_" or return undef;
294   print Print2File_F @_;
295   close Print2File_F;
296
297   return 1;
298 }
299
300 sub KernelImg
301 {
302   local $_;
303   my ($ki, @k, @k2);
304
305   ($ki, @k) = @_;
306
307   chomp @k;
308
309   for (@k) {
310     s#^/boot/##;
311     return $ki if $_ eq $ki;
312     push @k2, $_ if /^vmlin/ && !/autoconf|config|version/
313   }
314
315   return $k2[0] if @k2 == 1;
316
317   return $ki;
318 }
319
320
321
322 #
323 # initialization part
324 #
325
326 delete $ENV{'LANG'};
327 delete $ENV{'LANGUAGE'};
328
329 if($0 =~ /(.*?)((?<![^\/])bin\/)?([^\/]+)$/) {
330   $Script = $3;
331   $BasePath = $1;
332   $LibPath = $1 . "lib/";
333   $BinPath = $1 . "bin/";
334   $CfgPath = $1 . "etc/";
335   $ImagePath = $1 . "images/";
336   $DataPath = $1 . "data/";
337 }
338 else {
339   die "OOPS: don't invoke the script that way!\n"
340 }
341
342 if(!(
343   ($BasePath eq "" || -d $BasePath) &&
344   -d $LibPath &&
345   -d $BinPath &&
346   -d $CfgPath &&
347   -d $ImagePath &&
348   -d $DataPath
349 )) {
350   die "$Script: you got it all wrong!\n";
351 }
352
353 $| = 1;
354
355 $_ = $BinPath;
356 s:^(.+)/$:$1:;
357 $ENV{PATH} = "/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:$_";
358
359 $TmpBase = "/tmp/${Script}_${$}";
360 $MToolsCfg = "$TmpBase.mtoolsrc";
361
362 $ENV{MTOOLSRC} = $MToolsCfg;
363
364 # The purpose of this is to allow to run the scripts without having root
365 # permissions.
366 #
367 # The $SUBinary must be a program that gives you superuser rights *without*
368 # a password.
369 #
370 # If you don't have such a program or *are* already root this feature is
371 # turned off.
372
373 if($<) {        # only if we are *not* already root
374   $SUBinary = "/usr/local/bin/sw";
375   $SUBinary = "/usr/bin/sw" if -x "/usr/bin/sw";
376   $SUBinary = undef unless -x $SUBinary && -u $SUBinary;
377 }
378
379
380 #
381 # now, read the config file
382 #
383
384 my ($f, @f);
385
386 $f = $CfgPath . "config";
387 die "$Script: no config file \"$f\"\n" unless open F, $f;
388 @f = grep !/^\s*(#|$)/, (<F>);
389 close F;
390
391 #
392 # only shell variable assignments are allowed
393 #
394 for (@f) {
395   if(/^\s*(\S+)\s*=\s*(.*)$/) {
396     $ENV{$1} = $ConfigData{$1} = `echo -n $2`;
397 #    print STDERR "<$1> <$ConfigData{$1}>\n";
398   }
399   else {
400     chomp;
401     die "$Script: syntax error in config file \"$f\": \"$_\"\n";
402   }
403 }
404
405 {
406   # set suse_release, suse_base, suse_xrelease
407   # kernel_ver
408   # (used to be in etc/config)
409
410   my ( $r, $r0, $rx, $in_abuild, $base, $a, $v, $kv, $kn, $rf, $work, $ki, @f, $prod );
411   my ( $theme, $real_arch, $ul_release, $sles_release, $load_image, $yast_theme, $splash_theme, $product_name, $update_dir );
412
413   $a = $ENV{'suse_arch'};
414
415   $in_abuild = 0;
416
417   if(-f "/.buildenv") {
418     open F, "/.buildenv";
419     @f = grep !/^\s*(#|$)/, (<F>);
420     close F;
421     for (@f) {
422       if(/^\s*(\S+)\s*=\s*(.*)$/) {
423         $ENV{$1} = `echo -n $2`;
424       }
425     }
426     $in_abuild = 1 if $ENV{'BUILD_BASENAME'};
427   }
428
429   $prod = "SuSE Linux";
430
431   if($in_abuild) {
432     if(-f "/etc/SuSE-release") {
433       $r0 = `grep VERSION /etc/SuSE-release`;
434     }
435     elsif(-f "/etc/UnitedLinux-release") {
436       $prod = "UnitedLinux";
437       $r0 = `grep VERSION /etc/UnitedLinux-release`;
438     }
439     $r0 =~ s/^.*=\s*//;
440     $r0 =~ s/\s*$//;
441     $r0 = "\L$r0";
442   }
443   else {
444     $r0 = $ENV{'suserelease'};
445   }
446
447   $r0 = "" unless defined $r0;
448   $rf = $r0;
449
450   $rx = "";
451   $rx = "$1-" if $r0 =~ s/-(.+)\s*$//;
452   $r0 = $1 if $r0 =~ /^(\d+\.\d+)/;
453   $r0 = "$r0-" if $r0 ne "";
454   $work = defined($ENV{'work'}) && -d($ENV{'work'}) ? $ENV{'work'} : "/work";
455   $work .= "/CDs";
456   $work .= "/all" if -d "$work/all";
457   $base = "$work/full-$rf-$a/suse";
458   $base = "$work/full-$a/suse" unless -d $base;
459   $ConfigData{'suse_base'} = $ENV{'suse_base'} = "$base/*";
460
461   if(!$in_abuild) {
462     # die "Sorry, no packages in \"$work\"!\n" unless -d "$base";
463     my $suserelpack = RPMFileName "aaa_version";
464     $suserelpack = RPMFileName "unitedlinux-release" unless $suserelpack && -f($suserelpack);
465     die "invalid SuSE release" unless -f $suserelpack;
466     system "mkdir /tmp/r$$; cd /tmp/r$$; rpm2cpio $suserelpack | cpio -iud --quiet";
467
468     if(-f "/tmp/r$$/etc/SuSE-release") {
469       $r0 = `grep VERSION /tmp/r$$/etc/SuSE-release`;
470     }
471     else {
472       $prod = "UnitedLinux";
473       $r0 = `grep VERSION /tmp/r$$/etc/UnitedLinux-release`;
474     }
475     $r0 =~ s/^.*=\s*//;
476     $r0 =~ s/\s*$//;
477     $r0 = "\L$r0";
478
479     $rf = $r0;
480
481     $rx = "$1-" if $r0 =~ s/-(.+)\s*$//;
482     $r0 = $1 if $r0 =~ /^(\d+\.\d+)/;
483     $r0 = "$r0-" if $r0 ne "";
484
485     system "rm -rf /tmp/r$$";
486   }
487
488   if($prod eq "UnitedLinux") {
489     if($rf eq "1.0") {
490       $r0 = "8.1";
491       $rx = "";
492     }
493   }
494
495   # print "prod = \"$prod\", base = \"$base\", r0 = \"$r0\", rx = \"$rx\", rf = \"$rf\"\n";
496
497   ($ENV{'suse_release'} = $r0) =~ s/-?$//;
498   ($ENV{'suse_xrelease'} = $rx) =~ s/-?$//;
499
500   ($v = "$r0$rx") =~ s/-?$//;
501
502   if(!exists($ENV{'pre_release'})) {
503     $ENV{'pre_release'} = $rf =~ /^\d+\.\d+(a\b|\.99)$/ ? 1 : 0;
504   }
505
506   if($rf =~ /^(\d+)\.(\d+)\.[5-9]/) {
507     $v = "$1." . ($2 + 1);
508     $ENV{'suse_release'} = $v;
509   }
510
511   # there is no 7.4
512   if($ENV{'suse_release'} eq "7.4" && $ENV{'pre_release'}) {
513     $ENV{'suse_release'} = $v = "8.0";
514   }
515
516   my $cache_dir = `pwd`;
517   chomp $cache_dir;
518   my $tmp_cache_dir = $cache_dir;
519   $cache_dir .= "/${BasePath}cache/$ENV{'suse_release'}-$ENV{'suse_arch'}";
520   $ConfigData{'cache_dir'} = $cache_dir;
521   $tmp_cache_dir .= "/${BasePath}tmp/cache/$ENV{'suse_release'}-$ENV{'suse_arch'}";
522   $ConfigData{'tmp_cache_dir'} = $tmp_cache_dir;
523   system "mkdir -p $tmp_cache_dir" unless -d $tmp_cache_dir;
524   my $use_cache = 0;
525
526   $ENV{'cache'} = 4 unless exists $ENV{'cache'};
527   $use_cache = $ENV{'cache'} if exists $ENV{'cache'};
528   $ConfigData{'use_cache'} = $use_cache;
529
530   if($in_abuild) {
531     $ENV{kernel_img} = KernelImg $ENV{kernel_img}, (`ls /boot/*`);
532     undef $kn;
533
534     $kn = `rpm -qf /boot/$ENV{kernel_img} | head -1 | cut -d- -f1` if -f "/boot/$ENV{kernel_img}";
535     chomp $kn if $kn;
536
537     if($ENV{kernel}) {
538       $ENV{kernel_rpm} = $ENV{kernel};
539     }
540     elsif($kn) {
541       $ENV{kernel_rpm} = $kn;
542     }
543     die "oops: unable to determine kernel rpm (looking for /boot/$ENV{kernel_img})" unless $ENV{'kernel_rpm'};
544
545     $kv = `rpm -ql $ENV{'kernel_rpm'} 2>/dev/null | grep modules | head -1 | cut -d / -f 4`;
546   }
547   else {
548     $kv = RPMFileName $ENV{'kernel_rpm'};
549
550     $ENV{'kernel_img'} = KernelImg $ENV{'kernel_img'}, (`rpm -qlp $kv 2>/dev/null | grep /boot`);
551
552     $kv = `rpm -qlp $kv 2>/dev/null | grep modules | head -1 | cut -d / -f 4`;
553   }
554   chomp $kv;
555
556   $ENV{'kernel_ver'} = $kv;
557
558   if($ENV{'suse_release'} !~ /^(\d+)\.(\d+)$/) {
559     die "invalid SuSE release";
560   }
561
562   if($in_abuild) {
563     $r = $ENV{'BUILD_BASENAME'};
564     if(!($r && -d("/.rpm-cache/$r"))) {
565       system "ls -la /.rpm-cache";
566       die "No usable /.rpm-cache (looking for \"$r\")!\n"
567     }
568     $ConfigData{'suse_base'} = $ENV{'suse_base'} = $base = $AutoBuild = "/.rpm-cache/$r"
569   }
570
571   $ENV{product} = $prod unless $ENV{product};
572
573   $theme = $ENV{theme} ? $ENV{theme} : "SuSE";
574
575   $real_arch = `uname -m`;
576   chomp $real_arch;
577   $real_arch = "i386" if $real_arch =~ /^i.86$/;
578
579   $ul_release = "ul1";
580   $sles_release= "sles8";
581
582   if($theme eq "SuSE") {
583     $yast_theme = "SuSELinux";
584     $splash_theme = "SuSE";
585     $product_name = "SuSE Linux";
586     $update_dir = "/linux/suse/$real_arch-$ENV{suse_release}";
587     $load_image = "";
588   }
589   elsif($theme eq "UnitedLinux") {
590     $yast_theme = "UnitedLinux";
591     $splash_theme = "UnitedLinux";
592     $product_name = "UnitedLinux";
593     $update_dir = "/linux/UnitedLinux/$real_arch-$ul_release";
594     $load_image = 96*1024;
595   }
596   elsif($theme eq "SuSE-SLES") {
597     $yast_theme = "SuSELinux";
598     $splash_theme = "SuSE-SLES";
599     $product_name = "SuSE Linux";
600     $update_dir = "/linux/suse/$real_arch-$sles_release";
601     $load_image = 96*1024;
602   }
603   elsif($theme eq "UL-SLES") {
604     $yast_theme = "SuSELinux";
605     $splash_theme = "SuSE-SLES";
606     $product_name = "SuSE Linux";
607     $update_dir = "/linux/UnitedLinux/$real_arch-$ul_release";
608     $load_image = 96*1024;
609   }
610   elsif($theme eq "OpenXchange") {
611     $yast_theme = "SuSELinux";
612     $splash_theme = "OpenXchange";
613     $product_name = "SuSE Linux";
614     $update_dir = "/linux/UnitedLinux/$real_arch-$ul_release";
615     $load_image = 96*1024;
616   }
617   elsif($theme eq "SuSE-SLOS") {
618     $yast_theme = "SuSELinux";
619     $splash_theme = "SuSE-SLOS";
620     $product_name = "SuSE Linux";
621     $update_dir = "/linux/UnitedLinux/$real_arch-$ul_release";
622     $load_image = 96*1024;
623   }
624   elsif($theme eq "OpenSchool") {
625     $yast_theme = "SuSELinux";
626     $splash_theme = "OpenSchool";
627     $product_name = "SuSE Linux";
628     $update_dir = "/linux/UnitedLinux/$real_arch-$ul_release";
629     $load_image = 96*1024;
630   }
631   else {
632     die "don't know theme \"$theme\""
633   }
634
635   $ENV{theme} = $theme;
636   $ENV{yast_theme} = $yast_theme;
637   $ENV{splash_theme} = $splash_theme;
638   $ENV{product_name} = $product_name;
639   $ENV{update_dir} = $update_dir;
640   $ENV{load_image} = $load_image;
641
642   for (qw (kernel_img kernel_rpm kernel_ver suse_release suse_xrelease suse_base pre_release theme product product_name yast_theme splash_theme update_dir load_image) ) {
643     $ConfigData{$_} = $ENV{$_}
644   }
645
646   die "No SuSE release identified.\n" unless $a ne "" && $v ne "";
647
648   $v .= " [$rf]" if $v ne $rf;
649
650   if(!exists $ENV{silent}) {
651     my $p = $ENV{'pre_release'} ? "pre-" : "";
652     print "Building for $product_name $p$v ($ConfigData{theme},$a,$ENV{'kernel_rpm'}:$ENV{'kernel_img'},$ENV{'kernel_ver'}) [$base].\n";
653   }
654
655   # print "<$ENV{'suse_release'}><$ENV{'suse_xrelease'}>\n";
656 }
657
658 1;