Subversion Repositories camp_sysinfo_client_3

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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
138 rodolico 25
#
26
# version 3.1 20191112 RWR
27
# Added logging. Log file will be written to the install directory with
28
# the application name.log as the name (application name taken from installer_config.pl)
144 rodolico 29
#
30
# version 3.1.1 20191117 RWR
31
# Added the ability to verify cpan is installed and configured on systems which need it
32
#
156 rodolico 33
# version 3.1.2 20200215 RWR
34
# Adding version comparisons
210 rodolico 35
#
36
# version 3.3.0 20230308 RWR
37
# major revision. Allows --quiet (don't ask questions) and --inplace, which assumes the source has been installed via a
38
# separate process. Mainly designed to allow checkout from svn repository.
101 rodolico 39
 
132 rodolico 40
# find our location and use it for searching for libraries
41
BEGIN {
42
   use FindBin;
43
   use File::Spec;
203 rodolico 44
   # use libraries from the directory this script is in
132 rodolico 45
   use lib File::Spec->catdir($FindBin::Bin);
203 rodolico 46
   # and its parent
47
   use lib File::Spec->catdir( $FindBin::Bin . '/../' );
132 rodolico 48
   eval( 'use YAML::Tiny' );
49
}
50
 
101 rodolico 51
my $sourceDir = File::Spec->catdir($FindBin::Bin);
52
 
156 rodolico 53
use Digest::MD5 qw(md5_hex);
208 rodolico 54
use File::Copy;
156 rodolico 55
 
56
# define the version number
57
# see https://metacpan.org/pod/release/JPEACOCK/version-0.97/lib/version.pod
58
use version;
210 rodolico 59
our $VERSION = version->declare("v3.003.000");
156 rodolico 60
 
61
 
132 rodolico 62
use Data::Dumper;
63
use File::Basename;
64
use Getopt::Long;
101 rodolico 65
 
132 rodolico 66
our %install;
67
our %operatingSystems;
68
our %libraries;
69
our %binaries;
206 rodolico 70
# load the definitions from installer_config.pl
132 rodolico 71
do "$sourceDir/installer_config.pl";
138 rodolico 72
#
73
# set up log file
74
my $logFile = $install{'application name'};
75
$logFile =~ s/ /_/g;
76
$logFile = "$sourceDir/$logFile.log";
132 rodolico 77
 
78
Getopt::Long::Configure ("bundling"); # allow -vd --os='debian'
79
my $dryRun = 0;
80
my $os;
81
my $help = 0;
82
my $version = 0;
206 rodolico 83
my $quiet = 0;
84
my $inplace = 0;
132 rodolico 85
 
86
my @messages; # stores any messages we want to show up at the end
87
my @feedback; # store feedback when we execute command line actions
88
 
89
my %configuration;
90
 
91
# simple display if --help is passed
92
sub help {
93
   my $oses = join( ' ', keys %operatingSystems );
156 rodolico 94
   use File::Basename;
95
   print basename($0) . " $VERSION\n";
132 rodolico 96
   print <<END
156 rodolico 97
$0 [options]
98
Options:
99
   --os      - osname is one of [$oses]
100
   --dryrun  - do not actually do anything, just tell you what I'd do
101
   --version - display version and exit
206 rodolico 102
   --quiet   - Do not ask questions, just do stuff
103
   --inplace - Do an inplace upgrade
104
 
105
For an inplace upgrade, it is assumed the source code has been
106
downloaded and installed into the correct directories already
132 rodolico 107
END
101 rodolico 108
}
109
 
138 rodolico 110
#######################################################
144 rodolico 111
#
112
# timeStamp
113
#
114
# return current system date as YYYY-MM-DD HH:MM:SS
115
#
116
#######################################################
117
sub timeStamp {
118
   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
119
   return sprintf "%4d-%02d-%02d %02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec;
120
}
121
 
122
sub yesno {
123
   my ( $prompt, $default ) = @_;
124
   $default = 'yes' unless $default;
125
   my $answer = &getAnswer( $prompt, $default eq 'yes' ? ('yes','no' ) : ('no', 'yes') );
126
   return lc( substr( $answer, 0, 1 ) ) eq 'y';
127
}
128
 
129
# prompt the user for a response, then allow them to enter it
130
# the first response is considered the default and is printed
131
# in all caps if more than one exists
132
# first answer is used if they simply press the Enter
133
# key. The response is returned all lower case if more than one
134
# exists.
135
# it is assumed 
136
sub getAnswer {
137
   my ( $prompt, @answers ) = @_;
138
   $answers[0] = '' unless defined( $answers[0] );
139
   my $default = $answers[0];
140
   my $onlyOneAnswer = scalar( @answers ) == 1;
141
   print $prompt . '[ ';
142
   $answers[0] = uc $answers[0] unless $onlyOneAnswer;
143
   print join( ' | ', @answers ) . ' ]: ';
144
   my $thisAnswer = <>;
145
   chomp $thisAnswer;
146
   $thisAnswer = $default unless $thisAnswer;
147
   return $thisAnswer;
148
}
149
 
150
 
151
#######################################################
138 rodolico 152
# function to simply log things
153
# first parameter is the priority, if <= $logDef->{'log level'} will print
154
# all subsequent parameters assumed to be strings to sent to the log
155
# returns 0 on failure
156
#         1 on success
157
#         2 if priority > log level
158
#        -1 if $logDef is unset
159
# currently, only logs to a file
160
#######################################################
161
sub logIt {
140 rodolico 162
   open LOG, ">>$logFile" or die "Could not append to $logFile: $!\n";
138 rodolico 163
   while ( my $t = shift ) {
164
      print LOG &timeStamp() . "\t$t\n";
165
   }
166
   close LOG;
167
   return 1;
168
}
101 rodolico 169
 
138 rodolico 170
 
132 rodolico 171
# attempt to locate the operating system.
172
# if found, will set some defaults for it.
173
sub setUpOperatingSystemSpecific {
174
   my ( $install, $operatingSystems, $os, $installDir ) = @_;
138 rodolico 175
   &logIt( 'Entering setUpOperatingSystemSpecific' );
176
   &logIt( "They passed $os in as the \$os" );
132 rodolico 177
   if ( $os ) {
178
      # We found the OS, set up some defaults
179
      $$install{'os'} = $os;
138 rodolico 180
      &logIt( "Setting keys for operating system" );
132 rodolico 181
      # merge operatingSystems into install
182
      foreach my $key ( keys %{$operatingSystems->{$os}} ) {
183
         if ( $key eq 'files' ) {
184
            $install->{'files'} = { %{$install->{'files'}}, %{$operatingSystems->{$os}->{'files'}} }
185
         } else {
186
            $install->{$key} = $operatingSystems->{ $os }->{$key};
187
         }
188
      } # if it is a known OS
189
   } # if
190
   return $os;
191
} # getOperatingSystem
192
 
193
# validates the libraries needed exist
194
# simply eval's each library. If it doesn't exist, creates a list of
195
# commands to be executed to install it, and displays missing libraries
196
# offering to install them if possible.
197
sub validateLibraries {
198
   my ( $libraries, $os ) = @_;
138 rodolico 199
   &logIt( 'Entering validateLibraries' );
132 rodolico 200
   my %return;
201
   foreach my $lib ( keys %$libraries ) {
138 rodolico 202
      &logIt( "Checking on library $lib" );
132 rodolico 203
      eval( "use $lib;" );
204
      if ( $@ ) {
205
         $return{ $lib } = $libraries->{$lib}->{$os} ? $libraries->{$lib}->{$os} : 'UNK';
206
      }
207
   }
208
   return \%return;
209
} # validateLibraries
210
 
211
 
212
# check for any required binaries
213
sub validateBinaries {
214
   my ( $binaries, $os ) = @_;
138 rodolico 215
   &logIt( 'Entering validateBinaries' );
132 rodolico 216
   my %return;
217
   foreach my $bin ( keys %$binaries ) {
218
      unless ( `which $bin` ) {
219
         $return{$bin} = $binaries->{$bin}->{$os} ? $binaries->{$bin}->{$os} : 'UNK';
220
      }
221
   }
222
   return \%return;
223
} # validateBinaries
224
 
225
# get some input from the user and decide how to install/upgrade/remove/whatever
226
sub getInstallActions {
227
   my $install = shift;
138 rodolico 228
   &logIt( 'Entering getInstallActions' );
132 rodolico 229
   if ( -d $install->{'confdir'} ) {
230
      $install->{'action'} = "upgrade";
231
   } else {
232
      $install->{'action'} = 'install';
233
   }
234
   $install->{'build config'} = 'Y';
235
   $install->{'setup cron'} = 'Y';
101 rodolico 236
}
237
 
132 rodolico 238
# locate all items in $hash which have one of the $placeholder elements in it
239
# and replace, ie <binddir> is replaced with the actual binary directory
240
sub doPlaceholderSubstitution {
241
   my ($hash, $placeholder) = @_;
138 rodolico 242
   &logIt( 'Entering doPlaceholderSubstitution' );
132 rodolico 243
   return if ref $hash ne 'HASH';
244
   foreach my $key ( keys %$hash ) {
245
      if ( ref( $$hash{$key} ) ) {
246
         &doPlaceholderSubstitution( $$hash{$key}, $placeholder );
247
      } else {
248
         foreach my $place ( keys %$placeholder ) {
249
            $$hash{$key} =~ s/$place/$$placeholder{$place}/;
250
         } # foreach
251
      } # if..else
252
   } # foreach
253
   return;
254
}
255
 
256
# This will go through and first, see if anything is a directory, in
257
# which case, we'll create new entries for all files in there.
258
# then, it will do keyword substitution of <bindir> and <confdir>
259
# to populate the target.
260
# When this is done, each file should have a source and target that is
261
# a fully qualified path and filename
208 rodolico 262
sub massageInstallValues {
132 rodolico 263
   my ( $install, $sourceDir ) = @_;
138 rodolico 264
   &logIt( 'Entering populateSourceDir' );
132 rodolico 265
   my %placeHolders = 
266
      ( 
267
        '<bindir>' => $$install{'bindir'},
268
        '<confdir>' => $$install{'confdir'},
269
        '<default owner>' => $$install{'default owner'},
270
        '<default group>' => $$install{'default group'},
271
        '<default permission>' => $$install{'default permission'},
272
        '<installdir>' => $sourceDir
273
      );
101 rodolico 274
 
132 rodolico 275
   my $allFiles = $$install{'files'};
101 rodolico 276
 
132 rodolico 277
   # find all directory entries and load files in that directory into $$install{'files'}
278
   foreach my $dir ( keys %$allFiles ) {
279
      if ( defined( $$allFiles{$dir}{'type'} ) && $$allFiles{$dir}{'type'} eq 'directory' ) {
138 rodolico 280
         &logIt( "Found directory $dir" );
132 rodolico 281
         if ( opendir( my $dh, "$sourceDir/$dir" ) ) {
282
            my @files = map{ $dir . '/' . $_ } grep { ! /^\./ && -f "$sourceDir/$dir/$_" } readdir( $dh );
138 rodolico 283
            &logIt( "\tFound files " . join( ' ', @files ) );
132 rodolico 284
            foreach my $file ( @files ) {
285
               $$allFiles{ $file }{'type'} = 'file';
286
               if ( $dir eq 'modules' ) {
287
                  $$allFiles{ $file }{'permission'} = ( $file =~ m/$$install{'modules'}/ ) ? '0700' : '0600';
288
               } else {
289
                  $$allFiles{ $file }{'permission'} = $$allFiles{ $dir }{'permission'};
290
               }
291
               $$allFiles{ $file }{'owner'} = $$allFiles{ $dir }{'owner'};
292
               $$allFiles{ $file }{'target'} = $$allFiles{ $dir }{'target'};
293
            } # foreach
294
            closedir $dh;
295
         } # if opendir
296
      } # if it is a directory
297
   } # foreach
298
   # find all files, and set the source directory, and add the filename to
299
   # the target
300
   foreach my $file ( keys %$allFiles ) {
301
      $$allFiles{$file}{'source'} = "$sourceDir/$file";
302
      $$allFiles{$file}{'target'} .= "/$file";
303
   } # foreach
101 rodolico 304
 
132 rodolico 305
   # finally, do place holder substitution. This recursively replaces all keys
306
   # in  %placeHolders with the values.
307
   &doPlaceholderSubstitution( $install, \%placeHolders );
101 rodolico 308
 
144 rodolico 309
   &logIt( "Exiting populateSourceDir with values\n" . Dumper( $install ) ) ;
101 rodolico 310
 
132 rodolico 311
   return 1;
312
} # populateSourceDir
313
 
314
sub GetPermission {
315
   my $install = shift;
138 rodolico 316
   &logIt( 'Entering GetPermission' );
132 rodolico 317
   print "Ready to install, please verify the following\n";
318
   print "A. Operating System:  " . $install->{'os'} . "\n";
319
   print "B. Installation Type: " . $install->{'action'} . "\n";
320
   print "C. Using Seed file: " . $install->{'configuration seed file'} . "\n" if -e $install->{'configuration seed file'};
321
   print "D. Target Binary Directory: " . $install->{'bindir'} . "\n";
322
   print "E. Target Configuration Directory: " . $install->{'confdir'} . "\n";
323
   print "F. Automatic Running: " . ( $install->{'crontab'} ? $install->{'crontab'} : 'No' ) . "\n";
324
   print "G. Install Missing Perl Libraries\n";
325
   foreach my $task ( sort keys %{ $install->{'missing libraries'} } ) {
144 rodolico 326
      print "\t$task -> " . $install->{'missing libraries'}->{$task}->{'command'} . ' ' . $install->{'missing libraries'}->{$task}->{'parameter'} . "\n";
101 rodolico 327
   }
132 rodolico 328
   print "H. Install Missing Binaries\n";
329
   foreach my $task ( sort keys %{ $install->{'missing binaries'} } ) {
144 rodolico 330
      print "\t$task -> " . $install->{'missing binaries'}->{$task}->{'command'} . ' ' . $install->{'missing binaries'}->{$task}->{'parameter'} . "\n";
132 rodolico 331
   }
332
   return &yesno( "Do you want to proceed?" );
101 rodolico 333
}
334
 
132 rodolico 335
# note, this fails badly if you stick non-numerics in the version number
336
# simply create a "number" from the version which may have an arbitrary
337
# number of digits separated by a period, for example
338
# 1.2.5
339
# while there are digits, divide current calculation by 100, then add the last
340
# digit popped of. So, 1.2.5 would become
341
# 1 + 2/100 + 5/10000, or 1.0205
342
# and 1.25.16 would become 1.2516
343
# 
344
# Will give invalid results if any set of digits is more than 99
345
sub dotVersion2Number {
346
   my $dotVersion = shift;
347
 
348
   my @t = split( '\.', $dotVersion );
349
   #print "\n$dotVersion\n" . join( "\n", @t ) . "\n";
350
   my $return = 0;
351
   while ( @t ) {
352
      $return /= 100;
353
      $return += pop @t;
354
   }
355
   #print "$return\n";
356
   return $return;
357
}
358
 
359
# there is a file named VERSIONS. We get the values out of the install
360
# directory and (if it exists) the target so we can decide what needs
361
# to be updated.
362
sub getVersions {
363
   my $install = shift;
138 rodolico 364
   &logIt( 'Entering getVersions' );
132 rodolico 365
   my $currentVersionFile = $install->{'files'}->{'VERSION'}->{'target'};
366
   my $newVersionFile = $install->{'files'}->{'VERSION'}->{'source'};
367
   if ( open FILE,"<$currentVersionFile" ) {
368
      while ( my $line = <FILE> ) {
369
         chomp $line;
370
         my ( $filename, $version, $checksum ) = split( "\t", $line );
371
         $install{'files'}->{$filename}->{'installed version'} = $version ? $version : '';
156 rodolico 372
         $install{'files'}->{$filename}->{'installed checksum'} = $checksum ? $checksum : '';
132 rodolico 373
      }
374
      close FILE;
375
   }
376
   if ( open FILE,"<$newVersionFile" ) {
377
      while ( my $line = <FILE> ) {
378
         chomp $line;
379
         my ( $filename, $version, $checksum ) = split( "\t", $line );
380
         $install->{'files'}->{$filename}->{'new version'} = $version ? $version : '';
156 rodolico 381
         $install->{'files'}->{$filename}->{'new checksum'} = $checksum ? $checksum : '';
132 rodolico 382
      }
383
      close FILE;
384
   }
385
   foreach my $file ( keys %{$$install{'files'}} ) {
156 rodolico 386
      $install{'files'}->{$file}->{'installed version'} = '' unless defined $install->{'files'}->{$file}->{'installed version'};
387
      $install{'files'}->{$file}->{'new version'} = '' unless defined $install->{'files'}->{$file}->{'new version'};
132 rodolico 388
   }
389
   return 1;
390
} # getVersions
391
 
144 rodolico 392
# checks if a directory exists and, if not, creates it
393
my %directories; # holds list of directories already created so no need to do an I/O
132 rodolico 394
 
144 rodolico 395
sub checkDirectoryExists {
396
   my ( $filename,$mod,$owner ) = @_;
397
   $mod = "0700" unless $mod;
398
   $owner = "root:root" unless $owner;
399
   &logIt( "Checking Directory for $filename with $mod and $owner" );
400
   my ($fn, $dirname) = fileparse( $filename );
401
   logIt( "\tParsing out $dirname and $filename" );
402
   return '' if exists $directories{$dirname};
403
   if ( -d $dirname ) {
404
      $directories{$dirname} = 1;
405
      return '';
406
   }
407
   if ( &runCommand( "mkdir -p $dirname", "chmod $mod $dirname", "chown $owner $dirname" ) ) {
408
      $directories{$dirname} = 1;
409
   }
410
   return '';   
411
}
412
 
413
# runs a system command. Also, if in testing mode, simply shows what
414
# would have been done.
415
sub runCommand {
416
   while ( my $command = shift ) {
417
      if ( $dryRun ) {
418
         print "$command\n";
419
      } else {
420
         `$command`;
421
      }
422
   }
423
   return 1;
424
} # runCommand
425
 
132 rodolico 426
# this actually does the installation, except for the configuration
427
sub doInstall {
428
   my $install = shift;
138 rodolico 429
   &logIt( 'Entering doInstall' );
132 rodolico 430
   my $fileList = $install->{'files'};
431
 
432
   &checkDirectoryExists( $install->{'bindir'} . '/', $install->{'default permission'}, $install->{'default owner'} . ':' . $install->{'default group'} );
433
   foreach my $file ( keys %$fileList ) {
434
      next unless ( $fileList->{$file}->{'type'} && $fileList->{$file}->{'type'} eq 'file' );
435
 
156 rodolico 436
#   *********** Removed error checking to get this working; should reenable later
437
#      if ( version->parse( $fileList->{$file}->{'installed version'} ) && version->parse( $fileList->{$file}->{'installed version'} ) < version->parse( $fileList->{$file}->{'new version'} ) ) {
438
#         # we have a new version, so overwrite it
439
#      } elsif ( $fileList->{$file}->{'installed checksum'} eq $fileList->{$file}->{'installed checksum'} ) { # has file been modified
440
#      }
441
#         
442
#
443
#      next if $install->{'action'} eq 'upgrade' && ! defined( $fileList->{$file}->{'installed version'} )
444
#              ||
445
#              ( &dotVersion2Number( $fileList->{$file}->{'new version'} ) <= &dotVersion2Number($fileList->{$file}->{'installed version'} ) );
208 rodolico 446
      # check the directory and permissions, creating directory and setting permissions if necessary
132 rodolico 447
      &checkDirectoryExists( $fileList->{$file}->{'target'}, $install->{'default permission'}, $install->{'default owner'} . ':' . $install->{'default group'} );
208 rodolico 448
      # copy the files to the new directory
132 rodolico 449
      &runCommand( 
208 rodolico 450
            "cp $fileList->{$file}->{'source'} $fileList->{$file}->{'target'}",            
132 rodolico 451
            "chmod $fileList->{$file}->{'permission'} $fileList->{$file}->{'target'}",
452
            "chown $fileList->{$file}->{'owner'} $fileList->{$file}->{'target'}"
453
            );
454
      # if there is a post action, run it and store any return in @feedback
455
      push @feedback, `$fileList->{$file}->{'post action'}` if defined $fileList->{$file}->{'post action'};
456
      # if there is a message to be passed, store it in @messages
156 rodolico 457
      push @messages, $fileList->{$file}->{'message'} if defined $fileList->{$file}->{'message'};
132 rodolico 458
   } # foreach file
459
   return 1;
460
}
461
 
462
 
463
# installs binaries and libraries
464
sub installOSStuff {
465
   my $install = shift;
144 rodolico 466
   my %commands;
132 rodolico 467
   my @actions = values( %{ $install->{'missing libraries'} } );
468
   push @actions, values( %{ $install->{'missing binaries'} } );
469
   foreach my $action ( @actions ) {
144 rodolico 470
      $commands{$action->{'command'}} .= ' ' . $action->{'parameter'};
132 rodolico 471
   }
144 rodolico 472
   foreach my $command ( keys %commands ) {
208 rodolico 473
      &logIt( $command );
474
      print "Running command $command $commands{$command}\n" unless $quiet;
144 rodolico 475
      `$command $commands{$command}`;
476
   }
132 rodolico 477
}
144 rodolico 478
 
479
################################################################
480
# validateCPAN
481
#
482
# some of the systems will need to run cpan to get some perl modules.
483
# this will go through each of them and see if command starts with cpan
484
# and, if so, will check that cpan is installed and configured for root.
485
#
486
# when cpan is installed, it requires one manual run as root from the cli
487
# to determine where to get the files. If that is not done, cpan can not
488
# be controlled by a program. We check to see if cpan is installed, then
489
# verify /root/.cpan has been created by the configuration tool
490
################################################################
491
 
492
 
493
sub validateCPAN {
494
   my $libraries = shift;
495
   my $needCPAN = 0;
496
   foreach my $app ( keys %$libraries ) {
497
      if ( $libraries->{$app}->{'command'} =~ m/^cpan/ ) {
498
         $needCPAN = 1;
499
         last;
500
      }
501
   }
502
   return unless $needCPAN;
503
   if ( `which cpan` ) {
504
      die "****ERROR****\nWe need cpan, and it is installed, but not configured\nrun cpan as root one time to configure it\n" unless -d '/root/.cpan';
505
   } else {
506
      die 'In order to install on this OS, we need cpan, which should have been installed with perl.' .
507
          " Can not continue until cpan is installed and configured\n";
508
   }
208 rodolico 509
}
510
 
511
# set up the config file.
512
# at worst, we'll have an empty configuration file
513
sub checkConfig {
514
   my $install = shift;
515
   # if the configuration file does not exist, create one
516
   if ( not -e $install->{'configuration'}->{'configuration file'} ) {
517
      &logIt( "Configuration file " . $install->{'configuration'}->{'configuration file'} . " does not exist, creating" );
518
      &checkDirectoryExists(
519
            $install->{'configuration'}->{'configuration file'},
520
            $install->{'configuration'}->{'permission'},
521
            $install->{'configuration'}->{'owner'}
522
            );
523
      if ( -e $install->{'configuration seed file'} ) {
524
         &logIt( "Seed file " . $install->{'configuration seed file'} . " exists, using as default" );
525
         copy( $install->{'configuration seed file'}, $install->{'configuration'}->{'configuration file'} );
526
      } else { # we don't have a seed, and we don't have a configuration file, so just give it an empty one
527
         &logIt( "No seed file or configuration file, creating an empty YAML" );
528
         open YAML, '>' . $install->{'configuration'}->{'configuration file'} 
529
            or die "Could not create configuration file " . $install->{'configuration'}->{'configuration file'} . ": $!\n";
530
         print YAML "# This is an empty configuration file\n---\n";
531
         close YAML;
532
      }
533
   }
534
}
535
 
536
# create a cron entry if necessary
537
sub cronTab {
538
   my $install = shift;
539
   # set up crontab, if necessary
540
   &logIt("Setting up crontab as " . $install->{'crontab'} );
541
   &runCommand( $install->{'crontab'} ) if defined ( $install->{'crontab'} );
144 rodolico 542
}   
132 rodolico 543
 
544
################################################################
545
#               Main Code                                      #
546
################################################################
547
 
548
# handle any command line parameters that may have been passed in
549
 
550
GetOptions (
551
            "os|o=s"      => \$os,      # pass in the operating system
552
            "dryrun|n"    => \$dryRun,  # do NOT actually do anything
553
            'help|h'      => \$help,
206 rodolico 554
            'version|v'   => \$version,
555
            'quiet|q'     => \$quiet,
556
            'inplace|i'   => \$inplace
132 rodolico 557
            ) or die "Error parsing command line\n";
558
 
559
if ( $help ) { &help() ; exit; }
156 rodolico 560
if ( $version ) { use File::Basename; print basename($0) . " $VERSION\n"; exit; }
132 rodolico 561
 
156 rodolico 562
print "Logging to $logFile\n";
138 rodolico 563
&logIt( 'Beginning installation' );
564
 
208 rodolico 565
# determine the operating system and set up installer hash with correct values
132 rodolico 566
$install{'os'} = &setUpOperatingSystemSpecific( \%install, \%operatingSystems, $os ? $os : `$sourceDir/determineOS`, $sourceDir );
138 rodolico 567
&logIt( "Operating System is $install{'os'}" );
568
 
208 rodolico 569
# check libraries necessary are loaded, and if not, track the ones we need
132 rodolico 570
$install{'missing libraries'} = &validateLibraries( \%libraries, $install{'os'} );
144 rodolico 571
&logIt( "Missing Libraries\n" . Dumper( $install{'missing libraries'} ) );
138 rodolico 572
 
208 rodolico 573
# Check that required binaries are installed and create list of the ones we need
132 rodolico 574
$install{'missing binaries'} = &validateBinaries( \%binaries, $install{'os'} );
144 rodolico 575
&logIt( "Missing binaries\n" . Dumper( $install{'missing binaries'} ) );
138 rodolico 576
 
208 rodolico 577
# if we need libraries and the os needs to use CPAN, validate CPAN
578
&validateCPAN( $install{'missing libraries'} ) if ( $install{'missing libraries'} );
144 rodolico 579
 
208 rodolico 580
# determine if it is an upgrade or fresh install and default to creating conf and cron
132 rodolico 581
&getInstallActions( \%install );
144 rodolico 582
&logIt( "Completed getInstallActions\n" .  Dumper( \%install ) );
138 rodolico 583
 
208 rodolico 584
# go through %install and replace all variables with correct values
585
# moving directories as needed in the %install
586
&massageInstallValues( \%install, $sourceDir );
132 rodolico 587
 
208 rodolico 588
#print Dumper( \%install ) ; die;
589
 
590
# ask permission if $quiet not set
206 rodolico 591
if ( $quiet || &GetPermission( \%install ) ) {
208 rodolico 592
   # install binaries and libraries as needed
132 rodolico 593
   &installOSStuff( \%install );
208 rodolico 594
   # do a version comparison unless we already have it in place, or it is a new install
595
   &getVersions( \%install ) unless $inplace || $install{'action'} eq 'new';
596
   # move the binaries in place unless they are already there
207 rodolico 597
   &doInstall( \%install ) unless $inplace;
132 rodolico 598
} else {
599
   die "Please fix whatever needs to be done and try again\n";
138 rodolico 600
   &logIt( "User chose to kill process" );
132 rodolico 601
}
602
 
210 rodolico 603
# hack to set permissions.
604
`chown root:root $install{bindir}`;
605
`chmod 700 $install{bindir}`;
606
 
208 rodolico 607
# set up automatic running
608
&cronTab( \%install );
609
# make sure something is in the configuration file
610
&checkConfig( \%install );
611
 
144 rodolico 612
&logIt( "Installation done, running \&postInstall if it exists" );
132 rodolico 613
 
206 rodolico 614
&postInstall( \%install, $quiet ) if defined( &postInstall );
144 rodolico 615
 
616
1;