| 101 | rodolico | 1 | #! /usr/bin/env perl
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | use strict;
 | 
        
           |  |  | 4 | use warnings;
 | 
        
           |  |  | 5 |   | 
        
           | 132 | rodolico | 6 | # install.pl
 | 
        
           |  |  | 7 | #
 | 
        
           |  |  | 8 | # installer for perl script, in this case, sysinfo
 | 
        
           |  |  | 9 | #
 | 
        
           |  |  | 10 | # Revision history
 | 
        
           |  |  | 11 | #
 | 
        
           |  |  | 12 | # Version 1.1.7 20161010 RWR
 | 
        
           |  |  | 13 | # Added ability to validate required libraries are installed
 | 
        
           |  |  | 14 | #
 | 
        
           |  |  | 15 | # version 1.2 20170327 RWR
 | 
        
           |  |  | 16 | # did some major modifications to correctly work on BSD systems also
 | 
        
           |  |  | 17 | #
 | 
        
           |  |  | 18 | # version 2.0 20190330 RWR
 | 
        
           |  |  | 19 | # changed it so all configs are YAML
 | 
        
           |  |  | 20 | #
 | 
        
           |  |  | 21 | # version 3.0 20191105 RWR
 | 
        
           |  |  | 22 | # set up so all options are presented on initial screen
 | 
        
           |  |  | 23 | # user can choose options to edit
 | 
        
           |  |  | 24 | # rest of install is automatic
 | 
        
           | 101 | rodolico | 25 |   | 
        
           | 132 | rodolico | 26 | our $VERSION = '3.0';
 | 
        
           |  |  | 27 |   | 
        
           |  |  | 28 | # find our location and use it for searching for libraries
 | 
        
           |  |  | 29 | BEGIN {
 | 
        
           |  |  | 30 |    use FindBin;
 | 
        
           |  |  | 31 |    use File::Spec;
 | 
        
           |  |  | 32 |    use lib File::Spec->catdir($FindBin::Bin);
 | 
        
           |  |  | 33 |    eval( 'use YAML::Tiny' );
 | 
        
           |  |  | 34 | }
 | 
        
           |  |  | 35 |   | 
        
           | 101 | rodolico | 36 | my $sourceDir = File::Spec->catdir($FindBin::Bin);
 | 
        
           |  |  | 37 |   | 
        
           | 132 | rodolico | 38 | use sysinfoconf;
 | 
        
           |  |  | 39 | use Data::Dumper;
 | 
        
           |  |  | 40 | use File::Basename;
 | 
        
           |  |  | 41 | use Getopt::Long;
 | 
        
           | 101 | rodolico | 42 |   | 
        
           | 132 | rodolico | 43 | our %install;
 | 
        
           |  |  | 44 | our %operatingSystems;
 | 
        
           |  |  | 45 | our %libraries;
 | 
        
           |  |  | 46 | our %binaries;
 | 
        
           |  |  | 47 |   | 
        
           |  |  | 48 | do "$sourceDir/installer_config.pl";
 | 
        
           |  |  | 49 |   | 
        
           |  |  | 50 | Getopt::Long::Configure ("bundling"); # allow -vd --os='debian'
 | 
        
           |  |  | 51 | # $verbose can have the following values
 | 
        
           |  |  | 52 | # 0 - do everything
 | 
        
           |  |  | 53 | # 1 - Do everything except the install, display what would be done
 | 
        
           |  |  | 54 | # 2 - Be verbose to STDERR
 | 
        
           |  |  | 55 | # 3 - Be very verbose
 | 
        
           |  |  | 56 | my $verbose = 0; # if test mode, simply show what would be done
 | 
        
           |  |  | 57 | my $dryRun = 0;
 | 
        
           |  |  | 58 | my $os;
 | 
        
           |  |  | 59 | my $help = 0;
 | 
        
           |  |  | 60 | my $version = 0;
 | 
        
           |  |  | 61 |   | 
        
           |  |  | 62 | my @messages; # stores any messages we want to show up at the end
 | 
        
           |  |  | 63 | my @feedback; # store feedback when we execute command line actions
 | 
        
           |  |  | 64 |   | 
        
           |  |  | 65 | my %configuration;
 | 
        
           |  |  | 66 |   | 
        
           |  |  | 67 | # simple display if --help is passed
 | 
        
           |  |  | 68 | sub help {
 | 
        
           |  |  | 69 |    my $oses = join( ' ', keys %operatingSystems );
 | 
        
           |  |  | 70 |    print <<END
 | 
        
           |  |  | 71 | $0 --verbose=x --os="osname" --dryrun --help --version
 | 
        
           |  |  | 72 |   | 
        
           |  |  | 73 | --os      - osname is one of [$oses]
 | 
        
           |  |  | 74 | --dryrun  - do not actually do anything, just tell you what I'd do
 | 
        
           |  |  | 75 | --verbose - x is 0 (normal) to 3 (horrible)
 | 
        
           |  |  | 76 | END
 | 
        
           | 101 | rodolico | 77 | }
 | 
        
           |  |  | 78 |   | 
        
           |  |  | 79 |   | 
        
           | 132 | rodolico | 80 | # attempt to locate the operating system.
 | 
        
           |  |  | 81 | # if found, will set some defaults for it.
 | 
        
           |  |  | 82 | sub setUpOperatingSystemSpecific {
 | 
        
           |  |  | 83 |    my ( $install, $operatingSystems, $os, $installDir ) = @_;
 | 
        
           |  |  | 84 |    print "They passed $os in as the \$os\n" if $verbose > 2;
 | 
        
           |  |  | 85 |    if ( $os ) {
 | 
        
           |  |  | 86 |       # We found the OS, set up some defaults
 | 
        
           |  |  | 87 |       $$install{'os'} = $os;
 | 
        
           |  |  | 88 |       print "Setting keys for operating system\n" if $verbose > 2;
 | 
        
           |  |  | 89 |       # merge operatingSystems into install
 | 
        
           |  |  | 90 |       foreach my $key ( keys %{$operatingSystems->{$os}} ) {
 | 
        
           |  |  | 91 |          if ( $key eq 'files' ) {
 | 
        
           |  |  | 92 |             $install->{'files'} = { %{$install->{'files'}}, %{$operatingSystems->{$os}->{'files'}} }
 | 
        
           |  |  | 93 |          } else {
 | 
        
           |  |  | 94 |             $install->{$key} = $operatingSystems->{ $os }->{$key};
 | 
        
           |  |  | 95 |          }
 | 
        
           |  |  | 96 |       } # if it is a known OS
 | 
        
           |  |  | 97 |    } # if
 | 
        
           |  |  | 98 |    return $os;
 | 
        
           |  |  | 99 | } # getOperatingSystem
 | 
        
           |  |  | 100 |   | 
        
           |  |  | 101 | # validates the libraries needed exist
 | 
        
           |  |  | 102 | # simply eval's each library. If it doesn't exist, creates a list of
 | 
        
           |  |  | 103 | # commands to be executed to install it, and displays missing libraries
 | 
        
           |  |  | 104 | # offering to install them if possible.
 | 
        
           |  |  | 105 | sub validateLibraries {
 | 
        
           |  |  | 106 |    my ( $libraries, $os ) = @_;
 | 
        
           |  |  | 107 |    my %return;
 | 
        
           |  |  | 108 |    foreach my $lib ( keys %$libraries ) {
 | 
        
           |  |  | 109 |       print "Checking on libarary $lib\n" if $verbose;
 | 
        
           |  |  | 110 |       eval( "use $lib;" );
 | 
        
           |  |  | 111 |       if ( $@ ) {
 | 
        
           |  |  | 112 |          $return{ $lib } = $libraries->{$lib}->{$os} ? $libraries->{$lib}->{$os} : 'UNK';
 | 
        
           |  |  | 113 |       }
 | 
        
           |  |  | 114 |    }
 | 
        
           |  |  | 115 |    return \%return;
 | 
        
           |  |  | 116 | } # validateLibraries
 | 
        
           |  |  | 117 |   | 
        
           |  |  | 118 |   | 
        
           |  |  | 119 | # check for any required binaries
 | 
        
           |  |  | 120 | sub validateBinaries {
 | 
        
           |  |  | 121 |    my ( $binaries, $os ) = @_;
 | 
        
           |  |  | 122 |    my %return;
 | 
        
           |  |  | 123 |    foreach my $bin ( keys %$binaries ) {
 | 
        
           |  |  | 124 |       unless ( `which $bin` ) {
 | 
        
           |  |  | 125 |          $return{$bin} = $binaries->{$bin}->{$os} ? $binaries->{$bin}->{$os} : 'UNK';
 | 
        
           |  |  | 126 |       }
 | 
        
           |  |  | 127 |    }
 | 
        
           |  |  | 128 |    return \%return;
 | 
        
           |  |  | 129 | } # validateBinaries
 | 
        
           |  |  | 130 |   | 
        
           |  |  | 131 | # get some input from the user and decide how to install/upgrade/remove/whatever
 | 
        
           |  |  | 132 | sub getInstallActions {
 | 
        
           |  |  | 133 |    my $install = shift;
 | 
        
           |  |  | 134 |    if ( -d $install->{'confdir'} ) {
 | 
        
           |  |  | 135 |       $install->{'action'} = "upgrade";
 | 
        
           |  |  | 136 |    } else {
 | 
        
           |  |  | 137 |       $install->{'action'} = 'install';
 | 
        
           |  |  | 138 |    }
 | 
        
           |  |  | 139 |    $install->{'build config'} = 'Y';
 | 
        
           |  |  | 140 |    $install->{'setup cron'} = 'Y';
 | 
        
           | 101 | rodolico | 141 | }
 | 
        
           |  |  | 142 |   | 
        
           | 132 | rodolico | 143 | # locate all items in $hash which have one of the $placeholder elements in it
 | 
        
           |  |  | 144 | # and replace, ie <binddir> is replaced with the actual binary directory
 | 
        
           |  |  | 145 | sub doPlaceholderSubstitution {
 | 
        
           |  |  | 146 |    my ($hash, $placeholder) = @_;
 | 
        
           |  |  | 147 |    return if ref $hash ne 'HASH';
 | 
        
           |  |  | 148 |    foreach my $key ( keys %$hash ) {
 | 
        
           |  |  | 149 |       if ( ref( $$hash{$key} ) ) {
 | 
        
           |  |  | 150 |          &doPlaceholderSubstitution( $$hash{$key}, $placeholder );
 | 
        
           |  |  | 151 |       } else {
 | 
        
           |  |  | 152 |          foreach my $place ( keys %$placeholder ) {
 | 
        
           |  |  | 153 |             $$hash{$key} =~ s/$place/$$placeholder{$place}/;
 | 
        
           |  |  | 154 |          } # foreach
 | 
        
           |  |  | 155 |       } # if..else
 | 
        
           |  |  | 156 |    } # foreach
 | 
        
           |  |  | 157 |    return;
 | 
        
           |  |  | 158 | }
 | 
        
           |  |  | 159 |   | 
        
           |  |  | 160 | # This will go through and first, see if anything is a directory, in
 | 
        
           |  |  | 161 | # which case, we'll create new entries for all files in there.
 | 
        
           |  |  | 162 | # then, it will do keyword substitution of <bindir> and <confdir>
 | 
        
           |  |  | 163 | # to populate the target.
 | 
        
           |  |  | 164 | # When this is done, each file should have a source and target that is
 | 
        
           |  |  | 165 | # a fully qualified path and filename
 | 
        
           |  |  | 166 | sub populateSourceDir {
 | 
        
           |  |  | 167 |    my ( $install, $sourceDir ) = @_;
 | 
        
           |  |  | 168 |    my %placeHolders = 
 | 
        
           |  |  | 169 |       ( 
 | 
        
           |  |  | 170 |         '<bindir>' => $$install{'bindir'},
 | 
        
           |  |  | 171 |         '<confdir>' => $$install{'confdir'},
 | 
        
           |  |  | 172 |         '<default owner>' => $$install{'default owner'},
 | 
        
           |  |  | 173 |         '<default group>' => $$install{'default group'},
 | 
        
           |  |  | 174 |         '<default permission>' => $$install{'default permission'},
 | 
        
           |  |  | 175 |         '<installdir>' => $sourceDir
 | 
        
           |  |  | 176 |       );
 | 
        
           | 101 | rodolico | 177 |   | 
        
           | 132 | rodolico | 178 |    my $allFiles = $$install{'files'};
 | 
        
           | 101 | rodolico | 179 |   | 
        
           | 132 | rodolico | 180 |    # find all directory entries and load files in that directory into $$install{'files'}
 | 
        
           |  |  | 181 |    foreach my $dir ( keys %$allFiles ) {
 | 
        
           |  |  | 182 |       if ( defined( $$allFiles{$dir}{'type'} ) && $$allFiles{$dir}{'type'} eq 'directory' ) {
 | 
        
           |  |  | 183 |          print "Found directory $dir\n" if $verbose > 2;
 | 
        
           |  |  | 184 |          if ( opendir( my $dh, "$sourceDir/$dir" ) ) {
 | 
        
           |  |  | 185 |             my @files = map{ $dir . '/' . $_ } grep { ! /^\./ && -f "$sourceDir/$dir/$_" } readdir( $dh );
 | 
        
           |  |  | 186 |             print "\tFound files " . join( ' ', @files ) . "\n" if $verbose > 2;
 | 
        
           |  |  | 187 |             foreach my $file ( @files ) {
 | 
        
           |  |  | 188 |                $$allFiles{ $file }{'type'} = 'file';
 | 
        
           |  |  | 189 |                if ( $dir eq 'modules' ) {
 | 
        
           |  |  | 190 |                   $$allFiles{ $file }{'permission'} = ( $file =~ m/$$install{'modules'}/ ) ? '0700' : '0600';
 | 
        
           |  |  | 191 |                } else {
 | 
        
           |  |  | 192 |                   $$allFiles{ $file }{'permission'} = $$allFiles{ $dir }{'permission'};
 | 
        
           |  |  | 193 |                }
 | 
        
           |  |  | 194 |                $$allFiles{ $file }{'owner'} = $$allFiles{ $dir }{'owner'};
 | 
        
           |  |  | 195 |                $$allFiles{ $file }{'target'} = $$allFiles{ $dir }{'target'};
 | 
        
           |  |  | 196 |             } # foreach
 | 
        
           |  |  | 197 |             closedir $dh;
 | 
        
           |  |  | 198 |          } # if opendir
 | 
        
           |  |  | 199 |       } # if it is a directory
 | 
        
           |  |  | 200 |    } # foreach
 | 
        
           |  |  | 201 |    # find all files, and set the source directory, and add the filename to
 | 
        
           |  |  | 202 |    # the target
 | 
        
           |  |  | 203 |    foreach my $file ( keys %$allFiles ) {
 | 
        
           |  |  | 204 |       $$allFiles{$file}{'source'} = "$sourceDir/$file";
 | 
        
           |  |  | 205 |       $$allFiles{$file}{'target'} .= "/$file";
 | 
        
           |  |  | 206 |    } # foreach
 | 
        
           | 101 | rodolico | 207 |   | 
        
           | 132 | rodolico | 208 |    # finally, do place holder substitution. This recursively replaces all keys
 | 
        
           |  |  | 209 |    # in  %placeHolders with the values.
 | 
        
           |  |  | 210 |    &doPlaceholderSubstitution( $install, \%placeHolders );
 | 
        
           | 101 | rodolico | 211 |   | 
        
           | 132 | rodolico | 212 |    print Dump( $install ) if $verbose > 2;
 | 
        
           | 101 | rodolico | 213 |   | 
        
           | 132 | rodolico | 214 |    return 1;
 | 
        
           |  |  | 215 | } # populateSourceDir
 | 
        
           |  |  | 216 |   | 
        
           |  |  | 217 | sub GetPermission {
 | 
        
           |  |  | 218 |    my $install = shift;
 | 
        
           |  |  | 219 |    print "Ready to install, please verify the following\n";
 | 
        
           |  |  | 220 |    print "A. Operating System:  " . $install->{'os'} . "\n";
 | 
        
           |  |  | 221 |    print "B. Installation Type: " . $install->{'action'} . "\n";
 | 
        
           |  |  | 222 |    print "C. Using Seed file: " . $install->{'configuration seed file'} . "\n" if -e $install->{'configuration seed file'};
 | 
        
           |  |  | 223 |    print "D. Target Binary Directory: " . $install->{'bindir'} . "\n";
 | 
        
           |  |  | 224 |    print "E. Target Configuration Directory: " . $install->{'confdir'} . "\n";
 | 
        
           |  |  | 225 |    print "F. Automatic Running: " . ( $install->{'crontab'} ? $install->{'crontab'} : 'No' ) . "\n";
 | 
        
           |  |  | 226 |    print "G. Install Missing Perl Libraries\n";
 | 
        
           |  |  | 227 |    foreach my $task ( sort keys %{ $install->{'missing libraries'} } ) {
 | 
        
           |  |  | 228 |       print "\t$task -> " . $install->{'missing libraries'}->{$task} . "\n";
 | 
        
           | 101 | rodolico | 229 |    }
 | 
        
           | 132 | rodolico | 230 |    print "H. Install Missing Binaries\n";
 | 
        
           |  |  | 231 |    foreach my $task ( sort keys %{ $install->{'missing binaries'} } ) {
 | 
        
           |  |  | 232 |       print "\t$task -> " . $install->{'missing binaries'}->{$task} . "\n";
 | 
        
           |  |  | 233 |    }
 | 
        
           |  |  | 234 |    return &yesno( "Do you want to proceed?" );
 | 
        
           | 101 | rodolico | 235 | }
 | 
        
           |  |  | 236 |   | 
        
           | 132 | rodolico | 237 | # note, this fails badly if you stick non-numerics in the version number
 | 
        
           |  |  | 238 | # simply create a "number" from the version which may have an arbitrary
 | 
        
           |  |  | 239 | # number of digits separated by a period, for example
 | 
        
           |  |  | 240 | # 1.2.5
 | 
        
           |  |  | 241 | # while there are digits, divide current calculation by 100, then add the last
 | 
        
           |  |  | 242 | # digit popped of. So, 1.2.5 would become
 | 
        
           |  |  | 243 | # 1 + 2/100 + 5/10000, or 1.0205
 | 
        
           |  |  | 244 | # and 1.25.16 would become 1.2516
 | 
        
           |  |  | 245 | # 
 | 
        
           |  |  | 246 | # Will give invalid results if any set of digits is more than 99
 | 
        
           |  |  | 247 | sub dotVersion2Number {
 | 
        
           |  |  | 248 |    my $dotVersion = shift;
 | 
        
           |  |  | 249 |   | 
        
           |  |  | 250 |    my @t = split( '\.', $dotVersion );
 | 
        
           |  |  | 251 |    #print "\n$dotVersion\n" . join( "\n", @t ) . "\n";
 | 
        
           |  |  | 252 |    my $return = 0;
 | 
        
           |  |  | 253 |    while ( @t ) {
 | 
        
           |  |  | 254 |       $return /= 100;
 | 
        
           |  |  | 255 |       $return += pop @t;
 | 
        
           |  |  | 256 |    }
 | 
        
           |  |  | 257 |    #print "$return\n";
 | 
        
           |  |  | 258 |    return $return;
 | 
        
           |  |  | 259 | }
 | 
        
           |  |  | 260 |   | 
        
           |  |  | 261 | # there is a file named VERSIONS. We get the values out of the install
 | 
        
           |  |  | 262 | # directory and (if it exists) the target so we can decide what needs
 | 
        
           |  |  | 263 | # to be updated.
 | 
        
           |  |  | 264 | sub getVersions {
 | 
        
           |  |  | 265 |    my $install = shift;
 | 
        
           |  |  | 266 |    my $currentVersionFile = $install->{'files'}->{'VERSION'}->{'target'};
 | 
        
           |  |  | 267 |    my $newVersionFile = $install->{'files'}->{'VERSION'}->{'source'};
 | 
        
           |  |  | 268 |    if ( open FILE,"<$currentVersionFile" ) {
 | 
        
           |  |  | 269 |       while ( my $line = <FILE> ) {
 | 
        
           |  |  | 270 |          chomp $line;
 | 
        
           |  |  | 271 |          my ( $filename, $version, $checksum ) = split( "\t", $line );
 | 
        
           |  |  | 272 |          $install{'files'}->{$filename}->{'installed version'} = $version ? $version : '';
 | 
        
           |  |  | 273 |       }
 | 
        
           |  |  | 274 |       close FILE;
 | 
        
           |  |  | 275 |    }
 | 
        
           |  |  | 276 |    if ( open FILE,"<$newVersionFile" ) {
 | 
        
           |  |  | 277 |       while ( my $line = <FILE> ) {
 | 
        
           |  |  | 278 |          chomp $line;
 | 
        
           |  |  | 279 |          my ( $filename, $version, $checksum ) = split( "\t", $line );
 | 
        
           |  |  | 280 |          $install->{'files'}->{$filename}->{'new version'} = $version ? $version : '';
 | 
        
           |  |  | 281 |       }
 | 
        
           |  |  | 282 |       close FILE;
 | 
        
           |  |  | 283 |    }
 | 
        
           |  |  | 284 |    foreach my $file ( keys %{$$install{'files'}} ) {
 | 
        
           |  |  | 285 |       $install{'files'}->{$file}->{'installed version'} = -2 unless defined $install->{'files'}->{$file}->{'installed version'};
 | 
        
           |  |  | 286 |       $install{'files'}->{$file}->{'new version'} = -1 unless defined $install->{'files'}->{$file}->{'new version'};
 | 
        
           |  |  | 287 |    }
 | 
        
           |  |  | 288 |    return 1;
 | 
        
           |  |  | 289 | } # getVersions
 | 
        
           |  |  | 290 |   | 
        
           |  |  | 291 |   | 
        
           |  |  | 292 | # this actually does the installation, except for the configuration
 | 
        
           |  |  | 293 | sub doInstall {
 | 
        
           |  |  | 294 |    my $install = shift;
 | 
        
           |  |  | 295 |    my $fileList = $install->{'files'};
 | 
        
           |  |  | 296 |   | 
        
           |  |  | 297 |    &checkDirectoryExists( $install->{'bindir'} . '/', $install->{'default permission'}, $install->{'default owner'} . ':' . $install->{'default group'} );
 | 
        
           |  |  | 298 |    foreach my $file ( keys %$fileList ) {
 | 
        
           |  |  | 299 |       next unless ( $fileList->{$file}->{'type'} && $fileList->{$file}->{'type'} eq 'file' );
 | 
        
           |  |  | 300 |   | 
        
           |  |  | 301 |       next if $install->{'action'} eq 'upgrade' && ! defined( $fileList->{$file}->{'installed version'} )
 | 
        
           |  |  | 302 |               ||
 | 
        
           |  |  | 303 |               ( &dotVersion2Number( $fileList->{$file}->{'new version'} ) <= &dotVersion2Number($fileList->{$file}->{'installed version'} ) );
 | 
        
           |  |  | 304 |       &checkDirectoryExists( $fileList->{$file}->{'target'}, $install->{'default permission'}, $install->{'default owner'} . ':' . $install->{'default group'} );
 | 
        
           |  |  | 305 |       &runCommand( 
 | 
        
           |  |  | 306 |             "cp $fileList->{$file}->{'source'} $fileList->{$file}->{'target'}",
 | 
        
           |  |  | 307 |             "chmod $fileList->{$file}->{'permission'} $fileList->{$file}->{'target'}",
 | 
        
           |  |  | 308 |             "chown $fileList->{$file}->{'owner'} $fileList->{$file}->{'target'}"
 | 
        
           |  |  | 309 |             );
 | 
        
           |  |  | 310 |       # if there is a post action, run it and store any return in @feedback
 | 
        
           |  |  | 311 |       push @feedback, `$fileList->{$file}->{'post action'}` if defined $fileList->{$file}->{'post action'};
 | 
        
           |  |  | 312 |       # if there is a message to be passed, store it in @messages
 | 
        
           |  |  | 313 |       push @messages, $fileList->{$file}->{'meesage'} if defined $fileList->{$file}->{'message'};
 | 
        
           |  |  | 314 |    } # foreach file
 | 
        
           |  |  | 315 |    # set up crontab, if necessary
 | 
        
           |  |  | 316 |    &runCommand( $install->{'crontab'} ) if defined ( $install->{'crontab'} );
 | 
        
           |  |  | 317 |    return 1;
 | 
        
           |  |  | 318 | }
 | 
        
           |  |  | 319 |   | 
        
           |  |  | 320 | sub postInstall {
 | 
        
           |  |  | 321 |    my $install = shift;
 | 
        
           |  |  | 322 |   | 
        
           |  |  | 323 |    # seed configuration, if needed
 | 
        
           |  |  | 324 |    if ( $$install{'build config'} ) {
 | 
        
           |  |  | 325 |       my $config;
 | 
        
           |  |  | 326 |       my @fileList;
 | 
        
           |  |  | 327 |   | 
        
           |  |  | 328 |       # the order is important here as, if multiple files exist, latter ones can
 | 
        
           |  |  | 329 |       # overwrite values in the previous. We do a push so the first value pushed
 | 
        
           |  |  | 330 |       # is processed last, ie has higher priority.
 | 
        
           |  |  | 331 |       push @fileList, $install->{'configuration'}->{'old configuration file'};
 | 
        
           |  |  | 332 |       push @fileList, $install->{'configuration'}->{'configuration file'};
 | 
        
           |  |  | 333 |   | 
        
           |  |  | 334 |       my $seedFile = $install->{'configuration'}->{'configuration seed file'};
 | 
        
           |  |  | 335 |       if ( -e $install->{'configuration seed file'} ) {
 | 
        
           |  |  | 336 |          push @fileList, $install->{'configuration seed file'};
 | 
        
           |  |  | 337 |       } # if preload seed file
 | 
        
           |  |  | 338 |   | 
        
           |  |  | 339 |       $config = &makeConfig( @fileList );
 | 
        
           |  |  | 340 |       # if ScriptDirs and moduleDirs not populated, do so from our configuration
 | 
        
           |  |  | 341 |       if ( ! $$config{'scriptDirs'} || ! scalar @{ $$config{'scriptDirs'} }  ) {
 | 
        
           |  |  | 342 |          $config->{'scriptDirs'} = [ $install->{'files'}->{'scripts'}->{'target'} ];
 | 
        
           |  |  | 343 |       }
 | 
        
           |  |  | 344 |       if ( ! $$config{'moduleDirs'} || ! @{ $$config{'moduleDirs'} }  ) {
 | 
        
           |  |  | 345 |          $config->{'moduleDirs'} = [ $install->{'files'}->{'modules'}->{'target'} ];
 | 
        
           |  |  | 346 |       }
 | 
        
           |  |  | 347 |       my $content = &showConf( $config );
 | 
        
           |  |  | 348 |       return &writeConfig( '' , $content );
 | 
        
           |  |  | 349 |    } # if we are building/merging configuration
 | 
        
           |  |  | 350 | }
 | 
        
           |  |  | 351 |   | 
        
           |  |  | 352 | # installs binaries and libraries
 | 
        
           |  |  | 353 | sub installOSStuff {
 | 
        
           |  |  | 354 |    my $install = shift;
 | 
        
           |  |  | 355 |    my @actions = values( %{ $install->{'missing libraries'} } );
 | 
        
           |  |  | 356 |    push @actions, values( %{ $install->{'missing binaries'} } );
 | 
        
           |  |  | 357 |    foreach my $action ( @actions ) {
 | 
        
           |  |  | 358 |       print "$action\n";
 | 
        
           |  |  | 359 |       &runCommand( $action );
 | 
        
           |  |  | 360 |    }
 | 
        
           |  |  | 361 | }
 | 
        
           |  |  | 362 |   | 
        
           |  |  | 363 |   | 
        
           |  |  | 364 | ################################################################
 | 
        
           |  |  | 365 | #               Main Code                                      #
 | 
        
           |  |  | 366 | ################################################################
 | 
        
           |  |  | 367 |   | 
        
           |  |  | 368 | # handle any command line parameters that may have been passed in
 | 
        
           |  |  | 369 |   | 
        
           |  |  | 370 | GetOptions (
 | 
        
           |  |  | 371 |             "verbose|v=i" => \$verbose, # verbosity level, 0-9
 | 
        
           |  |  | 372 |             "os|o=s"      => \$os,      # pass in the operating system
 | 
        
           |  |  | 373 |             "dryrun|n"    => \$dryRun,  # do NOT actually do anything
 | 
        
           |  |  | 374 |             'help|h'      => \$help,
 | 
        
           |  |  | 375 |             'version|V'   => \$version
 | 
        
           |  |  | 376 |             ) or die "Error parsing command line\n";
 | 
        
           |  |  | 377 |   | 
        
           |  |  | 378 | if ( $help ) { &help() ; exit; }
 | 
        
           |  |  | 379 | if ( $version ) { print "$0 version $VERSION\n"; exit; }
 | 
        
           |  |  | 380 |   | 
        
           |  |  | 381 | $install{'os'} = &setUpOperatingSystemSpecific( \%install, \%operatingSystems, $os ? $os : `$sourceDir/determineOS`, $sourceDir );
 | 
        
           |  |  | 382 | $install{'missing libraries'} = &validateLibraries( \%libraries, $install{'os'} );
 | 
        
           |  |  | 383 | $install{'missing binaries'} = &validateBinaries( \%binaries, $install{'os'} );
 | 
        
           |  |  | 384 | &getInstallActions( \%install );
 | 
        
           |  |  | 385 | populateSourceDir( \%install, $sourceDir );
 | 
        
           |  |  | 386 |   | 
        
           |  |  | 387 | if ( &GetPermission( \%install ) ) {
 | 
        
           |  |  | 388 |    &installOSStuff( \%install );
 | 
        
           |  |  | 389 |    &getVersions( \%install ) unless $install{'action'} eq 'new';
 | 
        
           |  |  | 390 | #   print Dump( \%install );
 | 
        
           |  |  | 391 | #   <>;
 | 
        
           |  |  | 392 |    &doInstall( \%install );
 | 
        
           |  |  | 393 | } else {
 | 
        
           |  |  | 394 |    die "Please fix whatever needs to be done and try again\n";
 | 
        
           |  |  | 395 | }
 | 
        
           |  |  | 396 |   | 
        
           |  |  | 397 | my $filename = &postInstall( \%install );
 | 
        
           |  |  | 398 | my $confFileName = $install{'configuration'}{'configuration file'};
 | 
        
           |  |  | 399 | print "Running configure.pl with $filename, output to $confFileName\n";
 | 
        
           |  |  | 400 |   | 
        
           |  |  | 401 | exec( "$install{bindir}/configure.pl -f $filename -o $confFileName" );
 | 
        
           |  |  | 402 |   | 
        
           |  |  | 403 |   | 
        
           |  |  | 404 | ########### ADD LOGGING
 |