home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-07-24 | 41.1 KB | 1,342 lines |
- #!/usr/local/bin/perl
- #
- # Copyright (C) Ready-to-Run Software, Inc. 1991-1997.
- # 4 Pleasant Street
- # Forge Village, MA 01886.
- #
- # All Rights Reserved.
- #
- # This Module contains Proprietary Information of
- # Ready-to-Run Software, Inc.
- #
- # Ready-to-Run Software, Inc. is a software service company. Most
- # of the software provided to our customers is "publically
- # available"; we provide the service of locating and building
- # the software for you. In general, you may make as many copies
- # as you want of the software that we deliver to you (individual
- # package license information is provided during the installation
- # process). The major exception to that is Ready-to-Run Software's
- # "Smart Installation System". We view the installation system
- # and the proprietary techniques used in it, as the vehicle that
- # allows us to effectively deliver our services to you. Accordingly:
- #
- # Use of this "Smart Installation System" is limited as follows:
- #
- # 1) by anyone, to install a SAMPLE ReadyPak(tm) from
- # Ready-to-Run Software, Inc.
- # 2) by a ReadyPak Purchaser to install a ReadyPak obtained from
- # Ready-to-Run Software, Inc. on any machine within your
- # organization.
- # 3) It may not be copied or otherwise distributed without written
- # permission from Ready-to-Run Software, Inc.
- #
- # $Id: powertools,v 1.7 1997/06/20 17:20:32 mike Exp jeff $
- #
- # Based on ReadyPak - Revision 1.9 1992/12/06 21:18:36 jeff
- #
- # $Log: powertools,v $
- # Revision 1.7 1997/06/20 17:20:32 mike
- # fix for linux tar
- #
- # Revision 1.6 1997/06/18 17:39:54 mike
- # fix for perl5 (for linux)
- #
- # Revision 1.5 1997/06/18 17:38:51 jeff
- # work with symbolic links...
- #
- # Revision 1.4 1997/05/16 17:33:34 jeff
- # work with symbolic links
- # use our zcat for gzipped archives
- # workaround for alpha perl bug
- #
- # Revision 1.3 1993/01/16 14:04:54 jeff
- # Actual release version
- #
- # Revision 1.2 1992/12/18 02:33:17 jeff
- # Changes for ISO naming conventions.
- #
- # Revision 1.1 1992/12/14 21:56:08 jeff
- # Initial revision
- #
- #
- $0 =~ m|(.*/)(.*)|, $PROG = $2; $EXECDIR = $1; # find program name
-
- # set up some necessary constants and defaults
- $TRUE = 1;
- $FALSE = 0;
- $SYMLINK_EXISTS = (eval 'symlink("","");', $@ eq '' );
-
- $MACHINE = shift @ARGV;
- $CDROM = shift @ARGV;
- $SourcePak = $FALSE;
-
- $[ = 0; # set array base to 0
- $, = ' '; # set output field separator
- $\ = "\n"; # set output record separator
- chop($cwd = `pwd`);
- $workdir = ($ENV{'TMPDIR'} || '/tmp'); # find a place to work
- chdir($workdir);
-
- $TESTING = $FALSE; # Should be FALSE when we ship
-
- $INFO = 1;
- $START = 1;
- $PROCESS = 2;
- $END = 3;
-
- $DEFAULT = 1;
- $REQUIRED = 2;
- $OPTIONAL = 3;
-
- $TarCmd= '/usr/bin/tar';
- $TarCmd='/bin/tar' if ($MACHINE =~ /linux/i);
- $TarCmd='/bin/tar' if ($MACHINE =~ /RISC/i);
- $TarCmd='/bin/tar' if ($MACHINE =~ /hp700/i);
- $TarCmd='/bin/tar' if ($MACHINE =~ /xenix/i);
-
- @PiecesPerPak = ( '$deco_name', '$cont_name', '$arch_name' );
-
-
- $SUID = 04000;
- $SGID = 02000;
-
- $BlockSize = 4096;
- $PathPrefix = '/' x 50;
- $STAGEPath = 'usr/STAGE';
- $InstallPath = '/usr/local';
- $InstallSharePath = '/usr/local/share';
- $ShareDirs = '(sbin|slib|sspool|sinclude|man|texinfo|doc|hardcopy)';
- $ConvertDirs = '(sbin|slib|sspool|sinclude)';
- $AbsDir = 'ABS';
- $RelativePathPrefix = '../';
-
- # this tells us how to process each section of the description file
- %SECTION = (
- '*PREREQS*', 'Processing(*prereq, *prereq_cnt)',
- '*DESCRIPTION*', 'Processing(*desc, *desc_cnt)',
- '*APPNOTES*', 'Processing(*appnote, *appnote_cnt)',
- '*FILEGROUP*', 'Processing(*filelist, *file_cnt)',
- '*MESSAGE*', 'Processing(*message, *msg_cnt)',
- '*OPTIONS*', 'Processing(*decoopt, *deco_opt_cnt)',
- '*INFO*', 'Processing(*info, *info_cnt)',
- '*LICENSE*', 'Processing(*license, *license_cnt)',
- '*PRE_PROCESSING*', 'Processing(*preprocessing,*pre_cnt)',
- '*POST_PROCESSING*', 'Processing(*postprocessing,*post_cnt)'
- );
-
- $STAGEset = $FALSE;
-
- BEGINNING:
- # options
- $Remote = '';
- $Verbose = $TRUE;
- $Install = $TRUE;
- $Operation = 'Install';
- $OpDest = 'at';
- $DeleteToo = $TRUE;
-
- # check for options
- while ($ARGV[0] =~ /^-/) {
- $_ = shift @ARGV;
- $Verbose = !$Verbose ,next if (/^-v/);
- $UseDefaultAnswers = $TRUE ,next if (/^-D/);
- $Operation = 'Remove',$OpDest='from',
- $Install=$FALSE ,next if (/^-R/);
- # we only get here for -h or unknown options
- print STDERR "\nUnknown option: $_" if (!/^-h/i);
- print STDERR <<"ENDOFHELP";
-
- Usage: $PROG [-DRLdhi] [-d device] package...;
- -D use default answers
- -R remove instead of installing
- -h this message
- ENDOFHELP
- exit;
- }
-
- $SIG{'INT'} = $SIG{'TERM'} = 'abort';
-
- &SetupHelp;
-
- print STDERR <<"EndOfIntro";
-
- Welcome to Ready-to-Run Software's
- * Smart Installation System *
-
- This installation system requires write permission in /tmp (or \$TMPDIR if
- it's set) directory (for staging the install) and write permission in the
- installation directory for the actual install (these may be the same).
-
- You may typically answer all questions with the default answer and end up with
- a working system (provided that the install device is correct). You may
- override the default answers to tailor what gets installed (e.g. you may leave
- out optional pieces) and where it gets installed.
-
- * If you answer any question with a '++' which tells the installation system
- to assume default answers for all remaining questions (you may also specify
- this with the -D flag on the command line).
-
- * If you want your answer to this question to be used for all remaining
- packages, respond with a completely uppercase answer (a '+' uses the
- default answer for all remaining packages). If the question refers to a
- path name, the path will be converted to lower case for you.
-
- * To see additional information, answer any question with a '?'.
- EndOfIntro
-
- die( "You don't have write permission in: $workdir\n" ) if ! -w $workdir;
-
- $umask = umask;
- umask 022
- if $Install && $umask != 022 &&
- &YesNo(sprintf("Use umask of 022 instead of %03o for install", umask ), 'umask');
-
-
- $taroptions = 'x';
- $taroptions .= 'oh' if $MACHINE =~ /(sun|RISC)/;
-
- # figure out the naming conventions on the CDROM
- $UPPER = 1;
- $REVISION = 2;
- $DOT = 4;
- $UPPERZ = 8;
- $NAMEFAULT = 16;
- for ($NAMING = 0 ; $NAMING < 16 ; $NAMING++) {
- last if -f &iso9660("config1") &&
- -f &iso9660("config2.rev") &&
- -f &iso9660("config3.Z");
- }
- die "Can't determine CDROM naming conventions\n" if $NAMING >= $NAMEFAULT;
-
- # start processing
- open(PAKS, &iso9660("COMMON/PACKAGES"));
-
- local($PAKname);
- while (<PAKS>) {
- undef @packages; $pak_cnt = 0;
- chop;
- $PAKname = $_;
- while (<PAKS>) {
- chop;
- last if $_ eq '';
- @field = split;
- next if $field[1] eq 'S' && !$SourcePak;
- next if $field[1] eq 'R' && $SourcePak;
- $packages[$pak_cnt++] = $field[0];
- $packages{$field[0]} = $TRUE;
- if ($field[1] ne 'T') { $rpackages{$field[0]} = $TRUE; }
- else { $opackages{$field[0]} = $TRUE; }
- $fullname{&standard($field[0])} = $field[0];
- }
- next if defined(%pak) && !defined($pak{$PAKname});
- }
-
-
- while (1) {
- &ListPackages( %opackages, "scripts" );
- &GetReturn( '' );
- &ListPackages( %rpackages, "packages" );
- printf( STDERR "Enter the name of a package to install or choose Search, Quit or All\n");
- printf( STDERR "<package>, S(earch), A(ll), Q(uit) [Search]? " );
- $option = <STDIN>;
- chop $option;
- &Help('<package>'), next if $option eq '?';
- &search, next if $option =~ /^($|S(|(E(|A(|R(C(|H)))))))$/i;
- &InstallAll, next if $option =~ /^A(|(L(|L)))$/;
- last if $option =~ /^Q(|(U(|I(|T))))$/i;
- &ProcessInstall($option),next if defined $packages{$option};
- printf STDERR "$option is not an option or package\n";
- }
-
- &PathMsg();
- exit 0;
-
- # we never get here because of the exit!
-
- sub search {
- local( $desire, $des2 );
- local( $UseDefaultAnswers )= ( $FALSE );
- local( %DefaultAnswer );
- local( @dolist, @desc, $desc, $cnt, $choice );
- while (1) {
- $desire = &GetAnswer( "Search package descriptions for (? for help)", '', 'SEARCH', '' );
- &Help('SEARCH'), redo if $desire eq '?';
- return if $desire eq '';
- last;
- }
- ($des2 = $desire) =~ s/(\s)+/\\;/g;
- open( DESCRIPTIONS, &iso9660s("$MACHINE/BIN/AGREP")." -l -i -d '^\\*' \\\\\\*DESC\\;$des2 ".&iso9660s("INSTINFO/*")."|" );
- $cnt = 0;
- while (<DESCRIPTIONS>) {
- chop;
- $_ =~ s:.*/([^\.;]*).*:$1:;
- $desc[ $cnt++ ] = $fullname{&standard($_)};
- }
- printf( STDERR "\nNo descriptions mention \"$desire\".\n\n"), return if !$cnt;
- @dolist = ($desc[0]);
- pickone: while ($#desc > 0)
- {
- printf STDERR
- "\nThe descriptions for the following packages mention \"$desire\":\n";
- $cnt = 0;
- foreach $desc (@desc)
- {
- printf( STDERR " %2d. %s\n", ++$cnt, $desc) ;
- }
- printf STDERR "\n A. ALL";
- printf STDERR "\n N. NONE\n";
- printf STDERR "\nChoose one please: ";
- $choice = <>;
- return if $choice =~ /^n/i;
- @dolist = @desc, last if $choice =~ /^a/i;
- $choice--;
-
- if ($choice >= 0 && $choice <= $#desc)
- {
- @dolist = ($desc[$choice]);
- last pickone;
- }
- }
- for $p (@dolist) { &ProcessInstall($p); };
- }
-
- sub InstallAll {
- local( $pak_index );
- for $pak_index (0..$pak_cnt) { &ProcessInstall($packages[$pak_index]); }
- }
-
- sub ListPackages {
- local(%paks, $title) = @_;
- local($line,$cnt,$p);
- printf "\nThe $PAKname package contains the following $title:\n\n";
- for $p (sort keys %paks) {
- $line = sprintf( "$line%-13s", $p );
- printf("$line\n"), $line='', $cnt=0 if (++$cnt == 6);
- }
- printf "$line\n" if $cnt;
- printf "\n";
- }
-
- sub iso9660 {
- local( $path ) = @_;
- $path =~ s:($CDROM/|;1$)::g;
- if ($NAMING & $UPPER) {
- $path =~ tr/a-z+!\-/A-Z_/;
- }
- else {
- $path =~ tr/A-Z+!\-/a-z_/;
- }
- if ($path !~ /\*$/) {
- if ($NAMING & $DOT) {
- $path .= '.' if $path !~ /(.*\/)?.*\./;
- }
- $path .= ';1' if $NAMING & $REVISION;
- }
- $path =~ s/\.z/\.Z/ if $NAMING & $UPPERZ;
-
- return "$CDROM/$path";
- }
-
- sub iso9660s {
- local( $path ) = @_;
- ($path = &iso9660($path)) =~ s/;/\\;/g;
- return $path;
- }
-
- sub CDROMNames {
- local($package,$machine) = @_;
- $pn=substr($package,0,8);
- return (&iso9660("$machine/ARCHIVE/$pn.Z"),
- &iso9660("$machine/PACKLIST/$pn."),
- &iso9660("INSTINFO/$pn.") );
- }
-
- sub ProcessInstall {
- # find out what we want to process
- ($package) = @_;
- local($p,$firstTry);
- $firstTry = $TRUE;
- do {
- undef %sizes; undef %owners; undef %names; undef %perms; undef %groups;
- undef %justcopy; undef @rmlist; undef $rm_cnt;
- ($arch_name,$cont_name,$deco_name) = &CDROMNames($package,$MACHINE);
- printf( "\a\n$package is not available for this platform.\n" ), return
- if ! -f &iso9660($arch_name) && ! -e &iso9660($arch_name);
- &ReadContents($cont_name);
- &ReadDecorations($deco_name,$INFO);
- &TellAboutPak($package) if $firstTry;
- &RemoveSTAGE, return if !&YesNo( "\n$Operation $package", $Operation );
- &License if $firstTry;
- &SetOrigin("$workdir/STAGE.$$");
- &AskUser;
- &ReadDecorations($deco_name, $PROCESS);
- (&GetPak($package) || (&RemoveSTAGE, return)) if ($Install && $firstTry);
- $firstTry = $FALSE;
- } until &Install;
- &RemoveSTAGE;
- }
-
- #
- # Subroutines
- #
-
- sub PathMsg {
- printf STDERR
- "\nSee /tmp/RTRinstall.log for a list of the packages and files processed.\n";
- return if !$Install;
- local($p,$pnew,$msg,$i);
- $p = $ENV{'PATH'};
- $msg = "\nYou may want to change your path to include:\n ";
-
- foreach $i (sort keys %execpath) {
- next if $p =~ /(^|:)$i(:|$)/;
- $pnew .= "$i:";
- printf STDERR "$msg$i\n";
- $msg = " ";
- }
-
- if ($pnew ne '') {
- $pnew = ".:$pnew" if $p =~ s/^\.://;
- printf STDERR
- "\nSuggested new path: $pnew$p\n"
- if $pnew ne '';
- }
- }
-
- sub GetPak {
- local($package) = @_;
- local($name,$i);
- print STDERR "Please wait....";
- $name = &iso9660s(eval($PiecesPerPak[$#PiecesPerPak]));
- mkdir ("/$STAGEOrigin", 0775 );
- $STAGEset = $TRUE;
- warn( "Failure untarring archive!\n$package install aborted.\n") , return 0
- if (system( "cat $name | ".&iso9660s("$MACHINE/BIN/ZCAT")." -d | (cd /$STAGEOrigin ; $TarCmd xf - 2>/dev/null)"));
- return 1;
- }
-
- sub TellAboutPak {
- local($package) = @_;
- local($i,$n);
- &Show( '', *desc, *desc_cnt );
- printf (STDERR
- "\nThe $package package is approximately %s\n", &FmtSize($total_size) );
- foreach $i (sort keys %gs) {
- next if !$gc{$i};
- $n = ($i ne ': ' ? $i : 'Required');
- printf(STDERR "%9s - $n\n",&FmtSize($gs{$i}));
- }
- }
-
- sub AskUser {
- $ConvertShareables = $FALSE;
- local($tmp);
- $tmp = &FileName(&GetAnswer("$Operation package $OpDest dir", $InstallPath,
- 'DIR', '^[~/.]' ));
- if ($tmp ne $InstallPath) {
- $InstallPath = $tmp;
- $InstallSharePath = $InstallPath . '/share';
- }
- $InstallPathOld = -d $InstallPath;
- $InstallSharePath = &FileName( &GetAnswer("$Operation shared files $OpDest",
- $InstallSharePath,'SDIR', '^[~/.]' ));
- $ConvertShareables = $TRUE
- if &YesNo(
- 'Convert slib->lib, sbin->bin, sspool->spool, sinclude->include',
- 'CONVERT');
- }
-
- sub ReadContents {
- local($ContentsFile) = @_;
- local($size, $owner, $group, $perms, $sum, $name, $dash, $linkto);
-
- open( CONTENTS, $ContentsFile);
- while (<CONTENTS>) {
- next if /^\s*#/; chop;
- ($size, $owner, $group, $perms, $sum, $name, $dash, $linkto) =
- split(' ', $_, 8);
- $perms {$name} = $perms;
- $sizes {$name} = $size;
- $owners{$name} = $owner;
- $groups{$name} = $group;
- $links {$name} = $linkto;
- $names {$name} = $DEFAULT;
- }
- close(CONTENTS);
- }
-
- sub FixWithEval {
- local($string) = @_;
- eval("\$string = $string" ) if $Pass == $PROCESS && $string =~ /^['&\$]/;
- return $string;
- }
-
- sub CheckQuery {
- local($one);
- if ($_ =~ /(.)user:([^:]*):/i) {
- $one = $1;
- return $FALSE if ($one eq '~' && $user =~ $2) ||
- ($one ne '~' && $user !~ $2);
- }
- if ($_ =~ /(.)machine:([^:]*):/i) {
- $one = $1;
- return $FALSE if ($one eq '~' && $MACHINE =~ $2) ||
- ($one ne '~' && $MACHINE !~ $2);
- }
- return $TRUE if ($Pass != $PROCESS) || ($_ !~ /(.)query:([^:]*):/i);
- return &YesNo(&FixWithEval($2),'',$1 eq '~' ? 'n' : 'y');
- }
-
- sub FileHelp {
- local($help,$n) = @_;
- if ($lasthelp eq $help) {
- undef $lasthelp;
- foreach $i ($start..$file_cnt-1) {
- # ($n = $filelist[$i]) =~ s:^.+/::g;
- $n = &TranslateName("/$STAGEOrigin/$filelist[$i]");
- printf( STDERR " $n\n" );
- }
- return;
- }
- printf( STDERR "\n$HELP{$help}" );
- printf( STDERR "Enter '?' again for a list of the $help\n\n" );
- $lasthelp = $help;
- }
-
- sub filelist {
- local($option) = @_;
-
- undef $lasthelp, $grouping = $heading = '', $start = $file_cnt, return
- if $option==$START;
-
- return if ($option == $PROCESS) || ($start == $file_cnt);
-
- local($i,$s,$n,$rm_tmp_cnt,$dflt,$skipit);
- $rm_tmp_cnt = $rm_cnt;
- foreach $i ($start..$file_cnt-1) {
- $n = $filelist[$i];
- $rmlist[$rm_tmp_cnt++] = $n;
- if ($n =~ /\*(.*)/) {
- $justcopy{$n} = $1;
- $n = $1;
- }
- $s += $sizes{$n} if $links{$n} eq '';
- delete $names{$n};
- }
- $gc{"$grouping: $heading"} = $TRUE if $start < $file_cnt;
-
- # Handle the info only pass
- $gs{"$grouping: $heading"}+=$s, $total_size+=$s, return if $Pass==$INFO;
-
- return if $heading eq '';
- if (!defined $grouping{$grouping}) {
- $grouping{$grouping} =
- &GetAnswer("$Operation $grouping files (All, Some, None)", 's',
- $grouping, '[aAnNsS]' );
- }
- if ($grouping{$grouping} !~ /^a/i) {
- $helpindx = $heading if $helpindx eq '';
- $skipit = ($grouping{$grouping} =~ /^n/i);
- if (!$skipit) {
- $dflt = $grpdflt;
- $dflt = $headingdflt{$heading} if defined $headingdflt{$heading};
- $headingdflt{$heading} =
- &GetAnswer(
- sprintf("$Operation $heading (Approx %s)",&FmtSize($s)),
- $dflt,
- "&FileHelp(\"$helpindx\")",
- '^[YyNn]' );
- $skipit = $TRUE if $headingdflt{$heading} =~ /^(n|\s*)$/i;
- }
- $file_cnt = $start, $rm_cnt = $rm_tmp_cnt if $skipit;
- }
- undef $helpindx; undef $heading; undef $grouping;
- }
-
- sub decoopt {
- local($state) = @_;
- return if ($Pass != $PROCESS) || ($state != $PROCESS);
- local ($i,@f);
- foreach ($i = 0; $i < $deco_opt_cnt; $i++) {
- @f = split( /\s+/, $decoopt[$i] );
- $decoopt{$f[0]} .= "|" if defined $decoopt{$f[0]};
- $decoopt{$f[0]} .= $f[1];
- }
- $deco_opt_cnt = 0;
- }
-
- sub appnote {
- local($state) = @_;
- return if ($Pass != $PROCESS) || ($state != $START);
- $appnote[$appnote_cnt++] = '^';
- }
-
- sub message {
- local($state) = @_;
- return if ($Pass != $PROCESS) || ($state != $PROCESS);
- local ($i);
- foreach $i (0..$msg_cnt-1) {
- print $message[$i];
- }
- $msg_cnt = 0;
- }
-
- sub Processing {
- local(*type,*cnt) = @_;
- local($message) = $1 if $_ =~ /message:([^:]*):/i;
-
- &type($START) if defined &type;
-
- $heading = $1 if $_ =~ /heading:([^:]*):/i;
- $helpindx = $1 if $_ =~ /help:([^:]*):/i;
- $grouping = $2 if $_ =~ /(.)grouping:([^:]*):/i;
- $grpdflt = ($1 eq '~' ? 'n' : 'y' );
- local($keep) = &CheckQuery;
-
- $type[$cnt++] = "echo $message" if ($keep && defined $message);
- while (<DECORATION>) {
- next if /^\s*#/; chop;
- last if '.' eq $_;
- next if !$keep;
- $type[$cnt++] = &FixWithEval($_);
- &type($PROCESS) if defined &type;
- }
- &type($END) if defined &type;
- }
-
- sub ReadDecorations {
- local($File,$pass) = @_;
-
- $Pass = $pass;
-
- undef %grouping; undef $heading; undef $grouping;
- undef %gs ; undef %gc; undef $total_size;
- undef @prereq; undef $prereq_cnt;
- undef @message; undef $msg_cnt;
- undef @filelist; undef $file_cnt;
- undef @desc; undef $desc_cnt;
- undef @info; undef $info_cnt;
- undef @decoopt; undef %decoopt; undef $deco_opt_cnt;
- undef @appnote; undef $appnote_cnt;
- undef @license; undef $license_cnt;
- undef @preprocessing; undef $pre_cnt;
- undef @postprocessing; undef $post_cnt;
-
- open( DECORATION, "$File") ||
- warn "No decoration file for $File\n";
- while (<DECORATION>) {
- next if /^\s#/; chop;
- @field = split;
- if (defined $SECTION{$field[0]}) {
- eval "&$SECTION{$field[0]}";
- }
- elsif ($field[0] =~ /\*\w+\*/) {
- print STDERR "Unknown section type $field[0]";
- }
- }
- close(DECORATION);
-
- # Add any missing filenames to the file list (e.g. in TOC, not in deco).
- foreach $i (sort keys %names) {
- $filelist[$file_cnt++] = $i;
- print STDERR "$i in TOC, not in decoration file\n" if $DEBUG;
- }
- foreach $i (0..$file_cnt-1) {
- $n = $filelist[$i];
- while ($n =~ m|[\*]?(.+)/([^/]*)|) {
- $dirs{$1} = 1;
- $n = $1;
- }
- }
- }
-
- sub RemoveSTAGE {
- system( "rm -rf /$STAGEOrigin" ) if $STAGEset;
- }
-
- sub abort {
- local($reason) = @_;
- warn("$reason\n");
- &RemoveSTAGE;
- exit 1;
- }
-
- sub Show {
- local($title,*type,*cnt,$first) = @_;
-
- local( $lines );
- print STDERR "$title" if $title ne '' && $cnt != 0;
- foreach $i ($first..$cnt-1) {
- if ($type[$i] eq '^') {
- next if ($type[$i-1] eq '^');
- print STDERR while ($lines++ < 23);
- $lines = 0;
- &GetReturn( '' );
- next;
- }
- if ($lines++ == 23) {
- $lines = 1;
- &GetReturn( '' );
- }
- print STDERR $type[$i];
- }
- }
-
- sub check_prereqs {
- local(@field,$file,$here,$i,$plist,$ipath,%ipaths,$package);
- foreach $i (0..$prereq_cnt-1) {
- @field = split( /\s+/, $prereq[$i], 2 );
- $here = $file = &TranslateName("/$STAGEOrigin/$field[1]");
- next if (-e $here);
- # first check the paths that we already know
- foreach $ipath (values %ipaths) {
- $file = &TranslateName("$ipath/$field[1]");
- last if -e $file;
- }
- while (! -e $file) {
- $ipath = &FileName( &GetAnswer(
- "Can't find package $field[0], where was it installed",
- "/usr/local", 'Prereq', '^[~/.]'
- ));
- $file = &TranslateName("$ipath/$field[1]");
- }
- $ipaths{$field[0]} = $ipath;
- $plist .= " -p $here $file";
- }
- return $plist;
- }
-
- sub License {
- &Show(
- "$package was compiled and made \"Ready-to-Run\" by \
- Ready-to-Run Software, Inc.\n",
- *license, *license_cnt );
- print STDERR " ************************\n\n" ;
- }
-
- sub Appnotes {
- local($package) = @_;
- local($cmd,$file,$dflt);
- $dflt = 'view';
- for (;;) {
- $cmd = &GetAnswer( 'Notes (file, print, view, done)',
- $dflt,
- 'APPNOTES',
- '^[dfpv]' );
- return if $cmd =~ /^d/;
- $dflt = 'done';
- if ($cmd =~ /^v/) {
- &Show('Notes', *appnote, *appnote_cnt, 1);
- next;
- }
- elsif ($cmd =~ /^p/) {
- $cmd = &GetAnswer( 'Print command', '| lpr', 'PRINT' );
- }
- else {
- $file = &FileName( &GetAnswer( 'File to save appnote in',
- "$InstallPath/doc/$package.note", 'FILE' ));
- local($path);
- ($path = $file) =~ s:/[^/]+$::;
- mkdir($path,0775);
- $cmd = ">$file"; $file = " $file";
- }
- if (open( PIPE, $cmd )) {
- foreach $i (1..$appnote_cnt-1) {
- print (PIPE "\n\n\n******\n\n\n"),next if $appnote[$i] eq '^';
- print (PIPE $appnote[$i]);
- }
- close( PIPE );
- }
- else {
- warn "Couldn't open$file: $!\n";
- }
- }
- }
-
- sub Install {
-
- local($options) = " -N \"$package\" -o $STAGEOrigin -L /tmp/RTRinstall.log";
-
- $options .= ' -i ' . $InstallPath;
- $options .= ' -s '. $InstallSharePath;
- $options .= ' -c' if $ConvertShareables;
- $options .= ' -t' ; # if &YesNo("show totals");
- $options .= ' -r' if !$Install;
- $options .= ' -v' if $LocalInstall; # || &YesNo("verbose output");
- $options .= ' -d' if $DeleteToo;
-
- # We don't care where/if the prerequisites exist if we're removing...
- $options .= &check_prereqs() if $Install;
-
- # Verify that we are about to install what they want.
- printf STDERR <<"EndOfVerifyMsg";
-
- About To $Operation: $package
-
- $OpDest $InstallPath
- with shareable files $OpDest $InstallSharePath
- EndOfVerifyMsg
- print STDERR ' slib->lib, sbin->bin, sspool->spool, sinclude->include'
- if $ConvertShareables;
-
- return $FALSE if !&YesNo( "\nAre these correct", CORRECT );
-
- $execpath{"$InstallPath/bin"} = 1;
- $execpath{"$InstallSharePath/bin"} = 1;
-
- print STDERR "Proceeding with install...";
-
- # first delete any files that we won't be installing
- while ($rm_cnt) {
- unlink("/$STAGEOrigin/$rmlist[--$rm_cnt]");
- print STDERR "unlink(/$STAGEOrigin/$rmlist[$rm_cnt])" if $TESTING;
- }
-
- local($cmd,$name,$dest);
- # process any requests which must be done prior to "rtrinstall"
- print "Pre Processing" if $Debug;
- foreach $i (0..$pre_cnt-1) {
- if ($preprocessing[$i] =~ /^[\&']/) {
- eval("\$cmd = $preprocessing[$i]" );
- }
- else {
- eval("\$cmd = \"$preprocessing[$i]\"");
- }
- print STDERR $@ if $@ ne '';
- print STDERR $cmd if $debug;
- system ($cmd) if $Install;
- }
-
- $RTRPID = open( RTRINSTALL,
- '|'.&iso9660s("$MACHINE/BIN/PERL").' '.&iso9660s("COMMON/INSTALL.RTR").
- $options) ||
- &abort;
-
- foreach $i (sort keys %dirs) {
- print RTRINSTALL $i;
- }
- $s = 0;
- foreach $i (0..$file_cnt-1) {
- $n = $filelist[$i];
- print RTRINSTALL $n;
- $n = $justcopy{$n} if defined $justcopy{$n};
- $s += $sizes{$n} if $links{$n} eq '';
- }
- close(RTRINSTALL);
- waitpid($RTRPID,0);
-
- return $TRUE if !$Install; #we're done if we're just removing
- $now = time;
- # ranlib, set owners, set modes if necessary
- # change times on man/cat files to be later than man/man files
- foreach $i (0..$file_cnt-1) {
- $n = $filelist[$i];
- $n = $justcopy{$n} if defined $justcopy{$n};
- system( "/usr/bin/ranlib -t " . &TranslateName("/$STAGEOrigin/$n") )
- if ($n =~ /\.(a|sa\.\d+\.d+)$/ && $MACHINE =~ /sun/);
- utime $now, $now, &TranslateName("/$STAGEOrigin/$n")
- if ($n =~ m|^man/cat|);
- next if ($n eq $InstallPath && $InstallPathOld);
- &FixOwnersAndModes($n,$owners{$n},$groups{$n},$perms{$n},
- $decoopt{'KeepOwner'});
- }
-
- print "Post Processing" if $Debug;
- foreach $i (0..$post_cnt-1) {
- if ($postprocessing[$i] =~ /^[\&']/) {
- eval("\$cmd = $postprocessing[$i]" );
- }
- else {
- eval("\$cmd = \"$postprocessing[$i]\"");
- }
- print STDERR $@ if $@ ne '';
- print STDERR $cmd if $debug;
- system ($cmd) if $Install;
- }
- &Appnotes($package) if defined @appnote;
- return $TRUE;
- }
-
- sub SetupHelp {
- $HELP{ '' } = 'There is no help available for this question\n\n';
-
- $HELP{ 'Device' } = <<"EndOfMessage";
- This is the device from which the install package reads all of the
- packages and files to be installed. It should be the same device that
- was used to load the install package. Remember to use the "non-rewinding"
- device (starts with an "n") if you are using some sort of a tape device.
-
- EndOfMessage
-
- $HELP{ 'Device' } .= <<"EndOfMessage" if $MACHINE eq 'i386';
- On SCO machines, the file /etc/default/tar describes a number of
- archive devices, including:
-
- 2 5.25" High Density Drive A (or 0)
- 3 5.25" High Density Drive B (or 1)
- 6 3.5" High Density Drive A (or 0)
- 7 3.5" High Density Drive B (or 1)
-
- EndOfMessage
-
- $HELP{ 'Device' } .= <<"EndOfMessage" if $MACHINE eq 'RS6000';
- On AIX machines, the non-rewinding device is usually designated by
- added a '.1' to the device name (e.g. /dev/rmt0.1).
- EndOfMessage
-
- $HELP{ 'DIR' } = <<"EndOfMessage";
- This is the root of the install tree for the package. Most files
- will be installed relative to this directory in the appropriate
- subdirectories (e.g. bin, lib, include, man, spool, ...). Files
- which must be stored in an absolute position (e.g. /bin or /etc) are
- not stored relative to this path. Also, the "shareable" files (see
- the next installation question) are not necessarily stored in the
- "install tree".
-
- You may enter: EXAMPLE
- 1) a fully qualified pathname /packages/rtr
- 2) a pathname beginning with ~ ~fred/bambam
- 3) a pathname beginning with . ./apps
-
- EndOfMessage
-
- $HELP{ 'Shared' } = <<"EndOfMessage";
- Shared files are files which are machine/architecture independent.
- You need to have only one copy of each file for an entire network (you
- may want more copies because of performance or other configuration
- considerations).
- If this package is already installed on another machine, and you
- will be sharing files, then there is no reason to install the shared
- files again.
-
- EndOfMessage
-
- $HELP{ 'SDIR' } = <<"EndOfMessage";
- This is the root of the shared portion of the install tree for the
- package. By default it is set to <INSTALLDIR>/share. You have many
- options on what to do with shared files. Your "shared" directory can be:
-
- * symbolically linked to a common shared file tree (except System V)
- * a file system which is mounted as the shared tree
- * set to <INSTALLDIR> so that shared files will not be in a separate
- subtree
- * set to some directory completely separate from the <INSTALLDIR>
-
- $HELP{ 'Shared' } You may enter: EXAMPLE
- 1) a fully qualified pathname /packages/rtr
- 2) a pathname beginning with ~ ~fred/bambam
- 3) a pathname beginning with . ./apps
-
- EndOfMessage
-
- $HELP{ 'CONVERT' } = <<"EndOfMessage";
- By default, the shared files are put in the directories lib, bin,
- include and spool (typically in a separate subtree, e.g. share/lib),
- but they can be kept in the uniquely named directories slib, sbin,
- sinclude and sspool; you might want to do this if you install your
- "shareable" files in the same place as your "non-shareable" files.
-
- EndOfMessage
-
- $HELP{ 'APPNOTES' } = <<"EndOfMessage";
- These are generally brief notes/hints to help when you first use
- this package. They are combined into a single "document" which you
- may View, Print, or File (you are in the "App Note" loop until you
- enter "D", so you may View the notes before deciding to Print or File
- them.
-
- EndOfMessage
-
- $HELP{ 'FILE' } = <<"EndOfMessage";
- The installation system will redirect the text to any file you
- request.
-
- EndOfMessage
-
- $HELP{ 'PRINT' } = <<"EndOfMessage";
- The installation system will pipe the text to any program/filter.
- Generally this is simply "lpr".
-
- EndOfMessage
-
- $HELP{ 'umask' } = <<"EndOfMessage";
- Your umask helps determine which file permissions are assigned when
- you create/install files. A umask of 022 is "safe": it will allow
- others to see/execute the installed files, but not modify them.
-
- EndOfMessage
-
- $HELP{ 'Install' } = <<"EndOfMessage";
- You can choose to install this package, or you can skip this package
- and proceed to the next one.
-
- EndOfMessage
-
- $HELP{ 'Remove' } = <<"EndOfMessage";
- You can choose to remove this package, or you can skip this package
- and proceed to the next one. If you elect to remove the package, you
- will be prompted with variations of the "install" questions (this
- allows you to remove a package with shared files from a single
- machine).
-
- EndOfMessage
-
- $HELP{ 'Prereq' } = <<"EndOfMessage";
- Some packages depend on other packages already being installed in
- order to work. When this is the case, the installation system will
- verify the existence of the prerequisite package and ensure that the
- references to that package are mapped appropriately.
-
- EndOfMessage
-
- $HELP{ 'Unformatted Man pages' } = <<"EndOfMessage";
- Unformatted versions of the manual pages are generally smaller than
- the formatted versions (and can be typeset for many different output
- devices), but will be slower to access and require nroff or groff to
- be installed in order for "man" to work.
-
- EndOfMessage
-
- $HELP{ 'Formatted Man pages' } = <<"EndOfMessage";
- Formatted versions of the manual pages are generally larger than
- the formatted versions (and cannot be typeset for different output
- devices), but they are faster to access and do not require nroff or
- groff to be installed in order for "man" to work.
-
- EndOfMessage
-
- $HELP{ 'Texinfo files' } = <<"EndOfMessage";
- These files are part of the texinfo documentation for this package.
- Ready-to-Run Software supplies texinfo documentation in four formats:
-
- .texinfo - unified documentation source
- .info - for on-line use (via info or emacs)
- .dvi - formatted by TeX
- .ps - PostScript format
-
- You can choose to install as many or as few formats as you need.
-
- EndOfMessage
-
- $HELP{ 'Info files' } = $HELP{ 'Texinfo files' };
-
- $HELP{ 'PostScript Format Documentation' } = <<"EndOfMessage";
- These PostScript format documentation files are included for your
- convenience. You may want to install them if you have a PostScript
- printer or previewer.
-
- EndOfMessage
-
- $HELP{ 'DVI Format Documentation' } = <<"EndOfMessage";
- These TeX formatted documentation files are included for your
- convenience. You may want to install them if you have a .dvi
- previewer or a way to print .dvi files.
-
- EndOfMessage
-
- $HELP{ 'Other Documentation' } = <<"EndOfMessage";
- These files are documentation of some sort which has been included
- for your information.
-
- EndOfMessage
-
- $HELP{ 'Required Compiled Emacs Lisp Files' } = <<"EndOfMessage";
- These files are the byte-compiled versions of some emacs commands
- that you should include when you install this package.
-
- EndOfMessage
-
- $HELP{ 'Required Emacs Lisp Source Files' } = <<"EndOfMessage";
- These files are the elisp source versions of some emacs commands
- that you should include when you install this package.
-
- EndOfMessage
-
-
- $HELP{ 'Optional Emacs Lisp Source Files' } = <<"EndOfMessage";
- These files are the elisp source versions of some emacs commands
- that you may want to include when you install this package. They are
- marked "optional" because the corresponding .elc files are supplied.
-
- EndOfMessage
-
-
- $HELP{ 'examples/templates/extra info' }
- = <<"EndOfMessage";
- These files are provided by Ready-to-Run Software as a way to help
- you get started using a package. Generally they are example,
- initialization, or demo files that make it easier to about learn a
- package.
-
- EndOfMessage
-
- $HELP{ 'Other Shareable files' } = <<"EndOfMessage";
- These shared files probably need to be installed unless you have
- already installed them in your "shared" directory tree when doing a
- previous installation.
-
- EndOfMessage
-
- $HELP{ 'Library' } = <<"EndOfMessage";
- Libraries are "ar" archives of object (.o) files which are used when
- linking programs.
-
- EndOfMessage
-
- $HELP{ 'Optional Libraries' } = <<"EndOfMessage";
- These libraries are not required to run this package. However, you
- might want them installed if you plan on rebuilding this package or
- building other packages that require the libraries from this package.
-
- EndOfMessage
-
- $HELP{ 'Optional Include Files' } = <<"EndOfMessage";
- These include files are not required to run this package. However,
- you might want them installed if you plan on rebuilding this package or
- building other packages that require the include files from this
- package.
-
- EndOfMessage
-
- $HELP{ 'Binary' } = <<"EndOfMessage";
- These binary files are not required to run this package. Binary files
- are typically programs that you can run.
-
- EndOfMessage
-
- $HELP{ 'Required' } = <<"EndOfMessage";
- These files are required to run this package. They are optionally
- installed because you may already have them installed.
-
- EndOfMessage
-
- $HELP{ 'Suggested' } = <<"EndOfMessage";
- These files are not necessary, but are recommended. They are optionally
- installed because in some cases you may already have them installed.
-
- EndOfMessage
-
- $HELP{ 'CORRECT' } = <<"EndOfMessage";
- If you are satisfied with the values you supplied, then you may allow the
- install to proceed. Otherwise, you may respecify any of the installation
- parameters for this package.
-
- EndOfMessage
-
- $HELP{ 'SOURCEDIR' } = <<"EndOfMessage";
- This is the root of the source tree. The sources for each package is
- installed in a subdirectory with the package name (e.g. <sourcedir>/calc).
-
- EndOfMessage
-
- $HELP{ 'SEARCH' } = <<"EndOfMessage";
- You may enter any string and the Smart Installation System will
- search the package descriptions for any mention of this string (case
- independent) and then give you the chance to review/install any
- matching packages. If you enter multiple strings (e.g. "shell
- interactive"), the SIS will search for descriptions which contain all
- of the strings listed (each string can appear anywhere in the
- description). There is a limit of approximately 20 characters of
- search string(s).
-
- Try: "terminal"
-
- EndOfMessage
-
- $HELP{ '<package>' } = <<"EndOfMessage";
- You may enter the name of any package listed below, you may search through
- the package descriptions for a particular package, or you may quit out of the
- Smart Installation System.
-
- EndOfMessage
-
- }
-
- #
- # Useful subroutines
- #
-
- sub key_ready {
- return 0 if $SVR3 || $MACHINE =~ /xenix/i;
- local($rin, $nfd);
- vec($rin, fileno(STDIN), 1) = 1;
- return $nfd = select($rin,undef,undef,0);
- }
-
- sub RemoveLS
- {
- local( $name ) = @_;
- $name =~ s:^//+:/:;
- return $name;
- }
-
- # both SetOrigin and TranslateName strip leading /'s so they are mutually
- # consistent
- # remember to update RWSubst if changing translation rules.
- sub TranslateName
- {
- local($out, $in) = @_;
- local($ip, $isp);
- ($ip = $InstallPath) =~ s|^/+||;
- ($isp = $InstallSharePath) =~ s|^/+||;
- if ($out =~ /$SharePattern/o) {
- # currently, all convertable shareables start with $STAGEOrigin."/s"
- # so we simply remove the "s"
- $out =~ s/$ConvertFrom/$ConvertTo/o if ($ConvertShareables);
- $out =~ s/$STAGEOrigin/$isp/o;
- return &RemoveLS($out);
- }
- return &RemoveLS($out) if ($out =~ s/$AbsPath//o);
- return &RemoveLS($out) if ($out=~ s/$STAGEOrigin/$ip/o);
- # Problems exist if we have a relative path referencing a
- # shareable file and we convert or relocate shareable entries
- warn "Relative Path Problem: $out\n"
- if $out =~ m|\.\./| &&
- ($out =~ m:/$ShareDirs(\W|$):o ||
- $in =~ m:/$ShareDirs(\W|$):o)
- &&($ConvertShareables ||
- $ip ne $isp)
- && $INTERNAL_RELATIVE_CHECK;
- return &RemoveLS($out);
- }
-
- sub FmtSize {
- local($size) = @_;
-
- return sprintf( "%.1fMb", $size/1048576.0 ) if $size > 1000000.0;#1048576.0;
- return sprintf( "%3dKb", int($size/1024) ) if $size > 1024;
- return sprintf( "%d bytes", $size );
- }
-
- # both SetOrigin and TranslateName strip leading /'s so they are mutually
- # consistent
- sub SetOrigin {
- ($STAGEOrigin) = @_;
- $STAGEOrigin =~ s|^/+||;
- $SharePattern = $STAGEOrigin . '/' . $ShareDirs;
- $ConvertFrom = $STAGEOrigin . '/s';
- $ConvertTo = $STAGEOrigin . '/';
- $AbsPath = "$STAGEOrigin/ABS"; # staged component - absolute path
- }
-
- sub EmptySTDIN {
- while (&key_ready) { getc; }
- }
-
- sub Help {
- local($help) = @_;
- if (substr($help,0,1) eq '&') {
- eval($help);
- return;
- }
- printf( STDERR "\n$HELP{$help}" );
- }
-
- sub FileName {
- local($in,$out,$d) = @_;
- {
- $out = $in, last if $in !~ m:^~([^/]*):;
- if ($1 eq '') {
- $out = ($ENV{'HOME'} || $ENV{'LOGDIR'} ||
- (getpwuid($<))[7]) . substr($in,1);
- }
- else
- {
- $out = (getpwnam($1))[7] . $' ;
- }
- }
- return $out if substr($out,0,1) eq '/';
- $d = $cwd;
- while ($out =~ m:(\.{1,2}/)(.*$):) {
- $out = $2;
- next if ($1 eq './');
- $d =~ s:(.*)/[^/]+$:$1:;
- }
- return "$d/$out";
- }
-
- sub GetAnswer {
- local($msg,$default,$help,$validate) = @_;
- local($answer,$msgidx);
- ($msgidx = $msg) =~ s/\(Approx.*\)//;
- &EmptySTDIN;
- return $DefaultAnswer{$msgidx} if defined $DefaultAnswer{$msgidx};
- if (!$UseDefaultAnswers) {
- substr( $default, -1 ) = '' if substr($default,-1) eq "\n";
- for (;;) {
- printf( STDERR "$msg [$default]? " );
- $answer = <STDIN>;
- chop $answer;
- $UseDefaultAnswers = $TRUE, last if $answer =~ /\+\+/;
- $DefaultAnswer{$msgidx} = $answer = $default, last if $answer =~ /\+/;
- &Help($help), redo if $answer eq '?';
- last if $validate eq '' || $answer =~ /$validate|^$/;
- printf( STDERR "'$answer' is not a valid response (enter ? for help)\n" );
- }
- }
- return $default if ($UseDefaultAnswers || $answer eq '');
- if ($answer =~ /^[^a-z]+$/ && $answer =~ /[A-Z]/) {
- $answer =~ tr/A-Z/a-z/;
- $DefaultAnswer{$msgidx} = $answer ;
- }
- return ($answer);
- }
-
- sub GetReturn {
- local($msg) = @_;
- return if $UseDefaultAnswers;
- printf STDERR "$msg ... hit RETURN to continue ...";
- &EmptySTDIN;
- <STDIN>;
- }
-
- sub YesNo {
- local($msg,$help,$deflt) = @_;
- $deflt = 'y' if $deflt eq '';
- return $TRUE
- if &GetAnswer( $msg, $deflt, $help, '^[YyNn]' ) =~ /^(y|\s*)$/i;
- return $FALSE;
- }
-
- sub Name {
- local($name,$ext,$limit) = @_;
- $name = substr( $name, 0, $limit - (length($ext)+1) );
- return "$name.$ext";
- }
-
- sub FixOwnersAndModes {
- local($in,$owner,$group,$perms,$force_owner) = @_;
- $force_owner = '\|' if $force_owner eq '';
- local($mode,$file,$grp);
- $file = &TranslateName("/$STAGEOrigin/$in");
- $mode = (umask ^ 077777777777) & 0777;
- $mode &= 0666 if $perms !~ /[sgx]/ && !-d $file;
- $grp = $(;
- if (substr($perms, $[+6, 1) eq 's') { # it's sgid!!
- if (!defined $gid{$group}) {
- local($n, $p, $g, $m) = getgrnam($group);
- $gid{$group} = $g;
- }
- chown($<, $grp = $gid{$group}, $file)
- || warn ("Can't change group of $file to $group: $!\n");
- $mode |= $SGID;
- }
- if (substr($perms, $[+3, 1) eq 's' || $owner =~ $force_owner) {
- if (!defined $uid{$owner}) {
- local($n, $p, $u, $g) = getpwnam($owner);
- $uid{$owner} = $u;
- }
- chown($uid{$owner}, $grp, $file)
- || warn ("Can't change owner of $file to $owner: $!\n");
- $mode |= $SUID if (substr($perms, $[+3, 1) eq 's'); # it's suid!!
- }
- chmod $mode, $file
- || ($mode = sprintf("o", $mode), warn("Can't chmod $out to $mode: $!\n"));
- }
-
- sub standard {
- local($name) = @_;
- ($name = substr($name,0,8)) =~ tr/A-Z/a-z/;
- return $name;
- }
-