| 33 | 
           rodolico | 
           1 | 
           #! /usr/bin/env perl
  | 
        
        
            | 
            | 
           2 | 
              | 
        
        
            | 
            | 
           3 | 
           use strict;
  | 
        
        
            | 
            | 
           4 | 
           use warnings;
  | 
        
        
            | 
            | 
           5 | 
              | 
        
        
           | 42 | 
           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 | 
           #
  | 
        
        
           | 50 | 
           rodolico | 
           15 | 
           # version 1.2 20170327 RWR
  | 
        
        
            | 
            | 
           16 | 
           # did some major modifications to correctly work on BSD systems also
  | 
        
        
           | 33 | 
           rodolico | 
           17 | 
              | 
        
        
           | 50 | 
           rodolico | 
           18 | 
           our $VERSION = '1.2';
  | 
        
        
           | 42 | 
           rodolico | 
           19 | 
              | 
        
        
           | 33 | 
           rodolico | 
           20 | 
           # find our location and use it for searching for libraries
  | 
        
        
            | 
            | 
           21 | 
           BEGIN {
  | 
        
        
            | 
            | 
           22 | 
              use FindBin;
  | 
        
        
            | 
            | 
           23 | 
              use File::Spec;
  | 
        
        
            | 
            | 
           24 | 
              use lib File::Spec->catdir($FindBin::Bin);
  | 
        
        
            | 
            | 
           25 | 
           }
  | 
        
        
            | 
            | 
           26 | 
              | 
        
        
            | 
            | 
           27 | 
           use sysinfoconf;
  | 
        
        
            | 
            | 
           28 | 
           use File::Basename;
  | 
        
        
           | 35 | 
           rodolico | 
           29 | 
           use Getopt::Long;
  | 
        
        
            | 
            | 
           30 | 
           Getopt::Long::Configure ("bundling"); # allow -vd --os='debian'
  | 
        
        
           | 33 | 
           rodolico | 
           31 | 
              | 
        
        
            | 
            | 
           32 | 
           use Data::Dumper;
  | 
        
        
            | 
            | 
           33 | 
              | 
        
        
           | 35 | 
           rodolico | 
           34 | 
           # $verbose can have the following values
  | 
        
        
           | 33 | 
           rodolico | 
           35 | 
           # 0 - do everything
  | 
        
        
            | 
            | 
           36 | 
           # 1 - Do everything except the install, display what would be done
  | 
        
        
            | 
            | 
           37 | 
           # 2 - Be verbose to STDERR
  | 
        
        
            | 
            | 
           38 | 
           # 3 - Be very verbose
  | 
        
        
           | 35 | 
           rodolico | 
           39 | 
           my $verbose = 0; # if test mode, simply show what would be done
  | 
        
        
            | 
            | 
           40 | 
           my $dryRun = 0;
  | 
        
        
            | 
            | 
           41 | 
           my $os;
  | 
        
        
            | 
            | 
           42 | 
           my $help = 0;
  | 
        
        
            | 
            | 
           43 | 
           my $version = 0;
  | 
        
        
           | 33 | 
           rodolico | 
           44 | 
              | 
        
        
            | 
            | 
           45 | 
           my $status; # exit status of the processes
  | 
        
        
            | 
            | 
           46 | 
           my $sourceDir = File::Spec->catdir($FindBin::Bin);
  | 
        
        
           | 34 | 
           rodolico | 
           47 | 
           my $installType;
  | 
        
        
           | 33 | 
           rodolico | 
           48 | 
              | 
        
        
           | 57 | 
           rodolico | 
           49 | 
              | 
        
        
           | 33 | 
           rodolico | 
           50 | 
           my %install = (  'bindir' => '/opt/camp/sysinfo-client',
  | 
        
        
            | 
            | 
           51 | 
                            'confdir' => '/etc/camp/sysinfo-client',
  | 
        
        
           | 34 | 
           rodolico | 
           52 | 
                            'application name' => 'sysinfo client',
  | 
        
        
           | 50 | 
           rodolico | 
           53 | 
                            'default group' => 'root',
  | 
        
        
            | 
            | 
           54 | 
                            'default owner' => 'root',
  | 
        
        
            | 
            | 
           55 | 
                            'default permission' => '0700',
  | 
        
        
           | 35 | 
           rodolico | 
           56 | 
                            'configuration' => {
  | 
        
        
            | 
            | 
           57 | 
                                     'configurator' => '<bindir>/configure.pl',
  | 
        
        
            | 
            | 
           58 | 
                                     'configuration file' => '<confdir>/sysinfo-client.conf',
  | 
        
        
            | 
            | 
           59 | 
                                     'configuration seed file' => 'sysinfo-client.seed',
  | 
        
        
            | 
            | 
           60 | 
                                     'permission' => '700',
  | 
        
        
           | 50 | 
           rodolico | 
           61 | 
                                     'owner'      => '<default owner>',
  | 
        
        
           | 35 | 
           rodolico | 
           62 | 
                                     'target'     => '<confdir>'
  | 
        
        
            | 
            | 
           63 | 
                                       },
  | 
        
        
           | 33 | 
           rodolico | 
           64 | 
                            'files' => {
  | 
        
        
            | 
            | 
           65 | 
                                      'configure.pl' => { 
  | 
        
        
            | 
            | 
           66 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           67 | 
                                            'permission' => '700', 
  | 
        
        
           | 50 | 
           rodolico | 
           68 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           69 | 
                                            'target' =>  '<bindir>'
  | 
        
        
            | 
            | 
           70 | 
                                         },
  | 
        
        
            | 
            | 
           71 | 
                                      'sysinfo-client' => { 
  | 
        
        
            | 
            | 
           72 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           73 | 
                                            'permission' => '700',
  | 
        
        
           | 50 | 
           rodolico | 
           74 | 
                                            'owner' => '<default owner>:<default group>',
  | 
        
        
           | 33 | 
           rodolico | 
           75 | 
                                            'target' =>  '<bindir>'
  | 
        
        
            | 
            | 
           76 | 
                                         },
  | 
        
        
            | 
            | 
           77 | 
                                      'sysinfoconf.pm' => {
  | 
        
        
            | 
            | 
           78 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           79 | 
                                            'permission' => '600',
  | 
        
        
           | 50 | 
           rodolico | 
           80 | 
                                            'owner' => '<default owner>:<default group>',
  | 
        
        
           | 33 | 
           rodolico | 
           81 | 
                                            'target' =>  '<bindir>'
  | 
        
        
            | 
            | 
           82 | 
                                         },
  | 
        
        
            | 
            | 
           83 | 
                                      'notes' => { 
  | 
        
        
            | 
            | 
           84 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           85 | 
                                            'permission' => '600', 
  | 
        
        
           | 50 | 
           rodolico | 
           86 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           87 | 
                                            'target' =>  '<bindir>'
  | 
        
        
            | 
            | 
           88 | 
                                         },
  | 
        
        
            | 
            | 
           89 | 
                                      'sysinfo-client.conf.template' => { 
  | 
        
        
            | 
            | 
           90 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           91 | 
                                            'permission' => '600', 
  | 
        
        
           | 50 | 
           rodolico | 
           92 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           93 | 
                                            'target' =>  '<bindir>' 
  | 
        
        
            | 
            | 
           94 | 
                                         },
  | 
        
        
            | 
            | 
           95 | 
                                      'getSendEmail.pl' => { 
  | 
        
        
            | 
            | 
           96 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           97 | 
                                            'permission' => '700', 
  | 
        
        
           | 50 | 
           rodolico | 
           98 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           99 | 
                                            'target' =>  '<bindir>' 
  | 
        
        
            | 
            | 
           100 | 
                                         },
  | 
        
        
            | 
            | 
           101 | 
                                      'install.pl' => {
  | 
        
        
            | 
            | 
           102 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           103 | 
                                            'permission' => '700', 
  | 
        
        
           | 50 | 
           rodolico | 
           104 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           105 | 
                                            'target' =>  '<bindir>' 
  | 
        
        
            | 
            | 
           106 | 
                                         },
  | 
        
        
            | 
            | 
           107 | 
                                      'MANIFEST' => {
  | 
        
        
            | 
            | 
           108 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           109 | 
                                            'permission' => '600', 
  | 
        
        
           | 50 | 
           rodolico | 
           110 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           111 | 
                                            'target' =>  '<bindir>' 
  | 
        
        
            | 
            | 
           112 | 
                                         },
  | 
        
        
            | 
            | 
           113 | 
                                      'sysinfo-client.seed.example' => { 
  | 
        
        
            | 
            | 
           114 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           115 | 
                                            'permission' => '600', 
  | 
        
        
           | 50 | 
           rodolico | 
           116 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           117 | 
                                            'target' =>  '<bindir>' 
  | 
        
        
            | 
            | 
           118 | 
                                         },
  | 
        
        
            | 
            | 
           119 | 
                                      'VERSION' => { 
  | 
        
        
            | 
            | 
           120 | 
                                            'type' => 'file',
  | 
        
        
            | 
            | 
           121 | 
                                            'permission' => '600', 
  | 
        
        
           | 50 | 
           rodolico | 
           122 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           123 | 
                                            'target' =>  '<bindir>' 
  | 
        
        
            | 
            | 
           124 | 
                                         },
  | 
        
        
            | 
            | 
           125 | 
                                         'modules' => {
  | 
        
        
            | 
            | 
           126 | 
                                            'type' => 'directory',
  | 
        
        
            | 
            | 
           127 | 
                                            'permission' => '700', 
  | 
        
        
           | 50 | 
           rodolico | 
           128 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           129 | 
                                            'target' =>  '<bindir>',
  | 
        
        
            | 
            | 
           130 | 
                                            'action' => 'chmod 700 *'
  | 
        
        
            | 
            | 
           131 | 
                                         },
  | 
        
        
            | 
            | 
           132 | 
                                         'scripts' => {
  | 
        
        
            | 
            | 
           133 | 
                                            'type' => 'directory',
  | 
        
        
            | 
            | 
           134 | 
                                            'permission' => '700', 
  | 
        
        
           | 50 | 
           rodolico | 
           135 | 
                                            'owner' => '<default owner>:<default group>', 
  | 
        
        
           | 33 | 
           rodolico | 
           136 | 
                                            'target' =>  '<bindir>',
  | 
        
        
            | 
            | 
           137 | 
                                            'action' => 'chmod 700 *'
  | 
        
        
            | 
            | 
           138 | 
                                         },
  | 
        
        
            | 
            | 
           139 | 
                                }
  | 
        
        
            | 
            | 
           140 | 
                             );
  | 
        
        
            | 
            | 
           141 | 
              | 
        
        
            | 
            | 
           142 | 
           # hash to set up os specific rules                  
  | 
        
        
            | 
            | 
           143 | 
           my %operatingSystems = (
  | 
        
        
            | 
            | 
           144 | 
                             'debian' => {
  | 
        
        
           | 60 | 
           rodolico | 
           145 | 
                                'regex'  = '(debian|mx)',
  | 
        
        
           | 33 | 
           rodolico | 
           146 | 
                                'bindir' => '/opt/camp/sysinfo-client',
  | 
        
        
            | 
            | 
           147 | 
                                'confdir' => '/etc/camp/sysinfo-client',
  | 
        
        
           | 35 | 
           rodolico | 
           148 | 
                                'crontab' => 'ln -s <bindir>/sysinfo-client /etc/cron.daily/sysinfo-client',
  | 
        
        
           | 57 | 
           rodolico | 
           149 | 
                                'modules' => '((linux)|(dpkg)|(unix)|(all))',
  | 
        
        
           | 33 | 
           rodolico | 
           150 | 
                             },
  | 
        
        
            | 
            | 
           151 | 
                             'ipfire' => {
  | 
        
        
           | 60 | 
           rodolico | 
           152 | 
                                'regex'  => 'ipfire',
  | 
        
        
           | 33 | 
           rodolico | 
           153 | 
                                'bindir' => '/opt/camp/sysinfo-client',
  | 
        
        
            | 
            | 
           154 | 
                                'confdir' => '/etc/camp/sysinfo-client',
  | 
        
        
           | 50 | 
           rodolico | 
           155 | 
                                'crontab' => 'ln -s <bindir>/sysinfo-client /etc/fcron.daily/sysinfo-client.fcron',
  | 
        
        
           | 57 | 
           rodolico | 
           156 | 
                                'modules' => '((ipfire)|(unix)|(all))',
  | 
        
        
           | 43 | 
           rodolico | 
           157 | 
                             },
  | 
        
        
            | 
            | 
           158 | 
                             'freebsd' => {
  | 
        
        
           | 60 | 
           rodolico | 
           159 | 
                                'regex' => 'freebsd',
  | 
        
        
           | 43 | 
           rodolico | 
           160 | 
                                'bindir' => '/usr/local/opt/camp/sysinfo-client',
  | 
        
        
            | 
            | 
           161 | 
                                'confdir' => '/usr/local/etc/camp/sysinfo-client',
  | 
        
        
           | 50 | 
           rodolico | 
           162 | 
                                'crontab' => 'ln -s <bindir>/sysinfo-client /etc/periodic/daily/sysinfo-client',
  | 
        
        
           | 57 | 
           rodolico | 
           163 | 
                                'modules' => '((bsd)|(unix)|(all))',
  | 
        
        
           | 50 | 
           rodolico | 
           164 | 
                               'default group' => 'wheel',
  | 
        
        
            | 
            | 
           165 | 
                               'default owner' => 'root',
  | 
        
        
           | 43 | 
           rodolico | 
           166 | 
                             },
  | 
        
        
            | 
            | 
           167 | 
              | 
        
        
            | 
            | 
           168 | 
                           );
  | 
        
        
           | 42 | 
           rodolico | 
           169 | 
              | 
        
        
            | 
            | 
           170 | 
           # list of libraries used by the system. We will offer to install them if
  | 
        
        
            | 
            | 
           171 | 
           # we know how. NOTE: I have chosen to put the full installation command
  | 
        
        
            | 
            | 
           172 | 
           # for each library. This allows us to use the package selector OR a different
  | 
        
        
            | 
            | 
           173 | 
           # piece of code on a per-library basis, but results in something like
  | 
        
        
            | 
            | 
           174 | 
           #      apt-get -y install perl-modules
  | 
        
        
            | 
            | 
           175 | 
           #      apt-get -y install libwww-perl
  | 
        
        
            | 
            | 
           176 | 
           # instead of
  | 
        
        
            | 
            | 
           177 | 
           #      apt-get -y install libwww-perl perl-modules
  | 
        
        
            | 
            | 
           178 | 
           # flexibility vs efficiency in this case.
  | 
        
        
            | 
            | 
           179 | 
           my %libraries = ( 
  | 
        
        
            | 
            | 
           180 | 
                             'File::Basename' => { 'debian' => 'apt-get -y install perl-modules' },
  | 
        
        
            | 
            | 
           181 | 
                             'Exporter' => { 'debian' => 'apt-get -y install perl-base' },
  | 
        
        
           | 50 | 
           rodolico | 
           182 | 
                             'LWP' => { 
  | 
        
        
            | 
            | 
           183 | 
                                        'debian' => 'apt-get -y install libwww-perl',
  | 
        
        
           | 55 | 
           rodolico | 
           184 | 
                                        'freebsd' => 'pkg install -y p5-libwww'
  | 
        
        
           | 50 | 
           rodolico | 
           185 | 
                                      },
  | 
        
        
           | 42 | 
           rodolico | 
           186 | 
                           );
  | 
        
        
            | 
            | 
           187 | 
              | 
        
        
           | 43 | 
           rodolico | 
           188 | 
           # utilities md5sum
  | 
        
        
            | 
            | 
           189 | 
           # freebsd isomd5sum
  | 
        
        
            | 
            | 
           190 | 
              | 
        
        
           | 42 | 
           rodolico | 
           191 | 
           # validates the libraries needed exist
  | 
        
        
            | 
            | 
           192 | 
           # simply eval's each library. If it doesn't exist, creates a list of
  | 
        
        
            | 
            | 
           193 | 
           # commands to be executed to install it, and displays missing libraries
  | 
        
        
            | 
            | 
           194 | 
           # offering to install them if possible.
  | 
        
        
            | 
            | 
           195 | 
           sub validateLibraries {
  | 
        
        
            | 
            | 
           196 | 
              my ( $libraries, $os ) = @_;
  | 
        
        
            | 
            | 
           197 | 
              my @command;
  | 
        
        
            | 
            | 
           198 | 
              my @missingLibs;
  | 
        
        
            | 
            | 
           199 | 
              foreach my $lib ( keys %$libraries ) {
  | 
        
        
            | 
            | 
           200 | 
                 eval( "use $lib;" );
  | 
        
        
            | 
            | 
           201 | 
                 if ( $@ ) {
  | 
        
        
            | 
            | 
           202 | 
                    push @command,$$libraries{$lib}{$os} if $$libraries{$lib}{$os};
  | 
        
        
            | 
            | 
           203 | 
                    push @missingLibs, $lib;
  | 
        
        
            | 
            | 
           204 | 
                 }
  | 
        
        
            | 
            | 
           205 | 
              }
  | 
        
        
            | 
            | 
           206 | 
              if ( @missingLibs ) { # we have missing libraries
  | 
        
        
            | 
            | 
           207 | 
                 if ( @command ) {
  | 
        
        
            | 
            | 
           208 | 
                    &runCommand( join( "\n", @command ) )
  | 
        
        
            | 
            | 
           209 | 
                       if &yesno(
  | 
        
        
            | 
            | 
           210 | 
                                   'Following libraries need to be installed: ' . 
  | 
        
        
            | 
            | 
           211 | 
                                   join( ' ', @missingLibs ) . "\n" .
  | 
        
        
            | 
            | 
           212 | 
                                   "I can install them with the following command(s)\n" . 
  | 
        
        
            | 
            | 
           213 | 
                                   join( "\n", @command ) . "\nDo you want me to do this?\n"
  | 
        
        
            | 
            | 
           214 | 
                                );
  | 
        
        
            | 
            | 
           215 | 
                 } else {
  | 
        
        
            | 
            | 
           216 | 
                    die unless &yesno( 'Following libraries need to be installed: ' . 
  | 
        
        
            | 
            | 
           217 | 
                                       join( ' ', @missingLibs ) . 
  | 
        
        
            | 
            | 
           218 | 
                                       "\nand I don't know how to do this. Abort?" );
  | 
        
        
            | 
            | 
           219 | 
                 }
  | 
        
        
            | 
            | 
           220 | 
              } # if
  | 
        
        
            | 
            | 
           221 | 
           } # validateLibraries
  | 
        
        
           | 33 | 
           rodolico | 
           222 | 
              | 
        
        
            | 
            | 
           223 | 
              | 
        
        
            | 
            | 
           224 | 
           # attempt to locate the operating system.
  | 
        
        
            | 
            | 
           225 | 
           # if found, will set some defaults for it.
  | 
        
        
            | 
            | 
           226 | 
           sub getOS {
  | 
        
        
           | 35 | 
           rodolico | 
           227 | 
              my ( $install, $operatingSystems, $os ) = @_;
  | 
        
        
            | 
            | 
           228 | 
              if ( ! $os ) { # we don't know, so we must try to figure it out
  | 
        
        
            | 
            | 
           229 | 
                 my $osString = `uname -a`;
  | 
        
        
            | 
            | 
           230 | 
                 foreach my $osType ( keys %$operatingSystems ) {
  | 
        
        
            | 
            | 
           231 | 
                    print "Checking if OS is $osType in $osString\n" if $verbose > 2;
  | 
        
        
           | 60 | 
           rodolico | 
           232 | 
                    next unless $osString =~ m/$$operatingSystems{$osType}{'regex'}/i;
  | 
        
        
           | 35 | 
           rodolico | 
           233 | 
                    print "Yes, it is $osType\n" if $verbose > 2;
  | 
        
        
            | 
            | 
           234 | 
                    # We found the OS, set up some defaults
  | 
        
        
            | 
            | 
           235 | 
                    $os = $osType;
  | 
        
        
            | 
            | 
           236 | 
                 } # foreach
  | 
        
        
            | 
            | 
           237 | 
              }
  | 
        
        
            | 
            | 
           238 | 
              if ( $os ) {
  | 
        
        
            | 
            | 
           239 | 
                 $$install{'os'} = $os;
  | 
        
        
            | 
            | 
           240 | 
                 print "Setting keys for operating system\n" if $verbose > 2;
  | 
        
        
           | 42 | 
           rodolico | 
           241 | 
                 foreach my $key ( keys %{$$operatingSystems{ $os }} ) {
  | 
        
        
           | 35 | 
           rodolico | 
           242 | 
                    $$install{$key} = $operatingSystems{ $os }{$key};
  | 
        
        
           | 33 | 
           rodolico | 
           243 | 
                 } # if it is a known OS
  | 
        
        
           | 35 | 
           rodolico | 
           244 | 
              } # if
  | 
        
        
            | 
            | 
           245 | 
              return $os;
  | 
        
        
           | 33 | 
           rodolico | 
           246 | 
           } # getOperatingSystem
  | 
        
        
            | 
            | 
           247 | 
              | 
        
        
           | 37 | 
           rodolico | 
           248 | 
              | 
        
        
           | 34 | 
           rodolico | 
           249 | 
           # get some input from the user and decide how to install/upgrade/remove/whatever
  | 
        
        
            | 
            | 
           250 | 
           sub getInstallActions {
  | 
        
        
            | 
            | 
           251 | 
              my $install = shift;
  | 
        
        
            | 
            | 
           252 | 
              if ( ! &yesno( "This looks like a $$install{'os'} machine, correct?" ) ) {
  | 
        
        
            | 
            | 
           253 | 
                 die "User Aborted\n" if &yesno( "If we continue, I will set this up like a $$install{'os'} system. Abort?" );
  | 
        
        
            | 
            | 
           254 | 
              }
  | 
        
        
            | 
            | 
           255 | 
              if ( -d $$install{'confdir'} ) {
  | 
        
        
            | 
            | 
           256 | 
                 $$install{'action'} = &getAnswer( "It looks like $$install{'application name'} is already installed, what do you want to do?", 
  | 
        
        
            | 
            | 
           257 | 
                                       ( "upgrade","remove", "overwrite" )
  | 
        
        
            | 
            | 
           258 | 
                                     );
  | 
        
        
            | 
            | 
           259 | 
              } else {
  | 
        
        
            | 
            | 
           260 | 
                 if ( &yesno( "This looks like a fresh install, correct?" ) ) {
  | 
        
        
            | 
            | 
           261 | 
                    $$install{'action'} = 'install';
  | 
        
        
            | 
            | 
           262 | 
                    $$install{'preseed config'} = &yesno( "Preseed the configuration file?" );
  | 
        
        
            | 
            | 
           263 | 
                 } else {
  | 
        
        
            | 
            | 
           264 | 
                    die "Can not continue at this time: Do not understand your system\n";
  | 
        
        
            | 
            | 
           265 | 
                 }
  | 
        
        
            | 
            | 
           266 | 
              }
  | 
        
        
            | 
            | 
           267 | 
              $$install{'build config'} = &yesno( "Edit config file when done?" );
  | 
        
        
            | 
            | 
           268 | 
              $$install{'setup cron'} = &yesno( "Set up for automatic running via crontab?" );
  | 
        
        
            | 
            | 
           269 | 
           }
  | 
        
        
           | 33 | 
           rodolico | 
           270 | 
              | 
        
        
           | 34 | 
           rodolico | 
           271 | 
           sub showWork { 
  | 
        
        
            | 
            | 
           272 | 
              my $install = shift;
  | 
        
        
            | 
            | 
           273 | 
              print Dumper( \%install );
  | 
        
        
            | 
            | 
           274 | 
           }
  | 
        
        
           | 35 | 
           rodolico | 
           275 | 
              | 
        
        
            | 
            | 
           276 | 
              | 
        
        
            | 
            | 
           277 | 
           sub doPlaceholderSubstitution {
  | 
        
        
            | 
            | 
           278 | 
              my ($hash, $placeholder) = @_;
  | 
        
        
            | 
            | 
           279 | 
              return if ref $hash ne 'HASH';
  | 
        
        
            | 
            | 
           280 | 
              foreach my $key ( keys %$hash ) {
  | 
        
        
            | 
            | 
           281 | 
                 if ( ref( $$hash{$key} ) ) {
  | 
        
        
            | 
            | 
           282 | 
                    &doPlaceholderSubstitution( $$hash{$key}, $placeholder );
  | 
        
        
            | 
            | 
           283 | 
                 } else {
  | 
        
        
            | 
            | 
           284 | 
                    foreach my $place ( keys %$placeholder ) {
  | 
        
        
            | 
            | 
           285 | 
                       $$hash{$key} =~ s/$place/$$placeholder{$place}/;
  | 
        
        
            | 
            | 
           286 | 
                    } # foreach
  | 
        
        
            | 
            | 
           287 | 
                 } # if..else
  | 
        
        
            | 
            | 
           288 | 
              } # foreach
  | 
        
        
            | 
            | 
           289 | 
              return;
  | 
        
        
            | 
            | 
           290 | 
           }
  | 
        
        
           | 34 | 
           rodolico | 
           291 | 
              | 
        
        
            | 
            | 
           292 | 
           # This will go through and first, see if anything is a directory, in
  | 
        
        
            | 
            | 
           293 | 
           # which case, we'll create new entries for all files in there.
  | 
        
        
            | 
            | 
           294 | 
           # then, it will do keyword substitution of <bindir> and <confdir>
  | 
        
        
            | 
            | 
           295 | 
           # to populate the target.
  | 
        
        
            | 
            | 
           296 | 
           # When this is done, each file should have a source and target that is
  | 
        
        
            | 
            | 
           297 | 
           # a fully qualified path and filename
  | 
        
        
           | 33 | 
           rodolico | 
           298 | 
           sub populateSourceDir {
  | 
        
        
            | 
            | 
           299 | 
              my ( $install, $sourceDir ) = @_;
  | 
        
        
           | 35 | 
           rodolico | 
           300 | 
              my %placeHolders = 
  | 
        
        
            | 
            | 
           301 | 
                 ( 
  | 
        
        
            | 
            | 
           302 | 
                   '<bindir>' => $$install{'bindir'},
  | 
        
        
           | 50 | 
           rodolico | 
           303 | 
                   '<confdir>' => $$install{'confdir'},
  | 
        
        
            | 
            | 
           304 | 
                   '<default owner>' => $$install{'default owner'},
  | 
        
        
            | 
            | 
           305 | 
                   '<default group>' => $$install{'default group'},
  | 
        
        
            | 
            | 
           306 | 
                   '<default permission>' => $$install{'default permission'}
  | 
        
        
           | 35 | 
           rodolico | 
           307 | 
                 );
  | 
        
        
           | 33 | 
           rodolico | 
           308 | 
              | 
        
        
            | 
            | 
           309 | 
              my $allFiles = $$install{'files'};
  | 
        
        
            | 
            | 
           310 | 
              | 
        
        
           | 35 | 
           rodolico | 
           311 | 
              # find all directory entries and load files in that directory into $$install{'files'}
  | 
        
        
           | 33 | 
           rodolico | 
           312 | 
              foreach my $dir ( keys %$allFiles ) {
  | 
        
        
            | 
            | 
           313 | 
                 if ( defined( $$allFiles{$dir}{'type'} ) && $$allFiles{$dir}{'type'} eq 'directory' ) {
  | 
        
        
           | 35 | 
           rodolico | 
           314 | 
                    print "Found directory $dir\n" if $verbose > 2;
  | 
        
        
           | 33 | 
           rodolico | 
           315 | 
                    if ( opendir( my $dh, "$sourceDir/$dir" ) ) {
  | 
        
        
            | 
            | 
           316 | 
                       my @files = map{ $dir . '/' . $_ } grep { ! /^\./ && -f "$sourceDir/$dir/$_" } readdir( $dh );
  | 
        
        
           | 35 | 
           rodolico | 
           317 | 
                       print "\tFound files " . join( ' ', @files ) . "\n" if $verbose > 2;
  | 
        
        
           | 33 | 
           rodolico | 
           318 | 
                       foreach my $file ( @files ) {
  | 
        
        
            | 
            | 
           319 | 
                          $$allFiles{ $file }{'type'} = 'file';
  | 
        
        
           | 37 | 
           rodolico | 
           320 | 
                          if ( $dir eq 'modules' ) {
  | 
        
        
            | 
            | 
           321 | 
                             $$allFiles{ $file }{'permission'} = ( $file =~ m/$$install{'modules'}/ ) ? '0700' : '0600';
  | 
        
        
            | 
            | 
           322 | 
                          } else {
  | 
        
        
            | 
            | 
           323 | 
                             $$allFiles{ $file }{'permission'} = $$allFiles{ $dir }{'permission'};
  | 
        
        
            | 
            | 
           324 | 
                          }
  | 
        
        
           | 33 | 
           rodolico | 
           325 | 
                          $$allFiles{ $file }{'owner'} = $$allFiles{ $dir }{'owner'};
  | 
        
        
            | 
            | 
           326 | 
                          $$allFiles{ $file }{'target'} = $$allFiles{ $dir }{'target'};
  | 
        
        
            | 
            | 
           327 | 
                       } # foreach
  | 
        
        
            | 
            | 
           328 | 
                       closedir $dh;
  | 
        
        
            | 
            | 
           329 | 
                    } # if opendir
  | 
        
        
            | 
            | 
           330 | 
                 } # if it is a directory
  | 
        
        
            | 
            | 
           331 | 
              } # foreach
  | 
        
        
           | 35 | 
           rodolico | 
           332 | 
              # find all files, and set the source directory, and add the filename to
  | 
        
        
            | 
            | 
           333 | 
              # the target
  | 
        
        
           | 33 | 
           rodolico | 
           334 | 
              foreach my $file ( keys %$allFiles ) {
  | 
        
        
            | 
            | 
           335 | 
                 $$allFiles{$file}{'source'} = "$sourceDir/$file";
  | 
        
        
            | 
            | 
           336 | 
                 $$allFiles{$file}{'target'} .= "/$file";
  | 
        
        
            | 
            | 
           337 | 
              } # foreach
  | 
        
        
           | 35 | 
           rodolico | 
           338 | 
              | 
        
        
            | 
            | 
           339 | 
              # finally, do place holder substitution. This recursively replaces all keys
  | 
        
        
            | 
            | 
           340 | 
              # in  %placeHolders with the values.
  | 
        
        
            | 
            | 
           341 | 
              &doPlaceholderSubstitution( $install, \%placeHolders );
  | 
        
        
            | 
            | 
           342 | 
              | 
        
        
            | 
            | 
           343 | 
              print Dumper( $install ) if $verbose > 2;
  | 
        
        
            | 
            | 
           344 | 
              | 
        
        
           | 33 | 
           rodolico | 
           345 | 
              return 1;
  | 
        
        
            | 
            | 
           346 | 
           } # populateSourceDir
  | 
        
        
            | 
            | 
           347 | 
              | 
        
        
           | 34 | 
           rodolico | 
           348 | 
           # there is a file named VERSIONS. We get the values out of the install
  | 
        
        
            | 
            | 
           349 | 
           # directory and (if it exists) the target so we can decide what needs
  | 
        
        
            | 
            | 
           350 | 
           # to be updated.
  | 
        
        
           | 33 | 
           rodolico | 
           351 | 
           sub getVersions {
  | 
        
        
            | 
            | 
           352 | 
              my $install = shift;
  | 
        
        
            | 
            | 
           353 | 
              my $currentVersionFile = $$install{'files'}{'VERSION'}{'target'};
  | 
        
        
            | 
            | 
           354 | 
              my $newVersionFile = $$install{'files'}{'VERSION'}{'source'};
  | 
        
        
            | 
            | 
           355 | 
              if ( open FILE,"<$currentVersionFile" ) {
  | 
        
        
            | 
            | 
           356 | 
                 while ( my $line = <FILE> ) {
  | 
        
        
            | 
            | 
           357 | 
                    chomp $line;
  | 
        
        
            | 
            | 
           358 | 
                    my ( $filename, $version, $checksum ) = split( "\t", $line );
  | 
        
        
            | 
            | 
           359 | 
                    $$install{'files'}{$filename}{'installed version'} = $version ? $version : '';
  | 
        
        
            | 
            | 
           360 | 
                 }
  | 
        
        
            | 
            | 
           361 | 
                 close FILE;
  | 
        
        
            | 
            | 
           362 | 
              }
  | 
        
        
            | 
            | 
           363 | 
              if ( open FILE,"<$newVersionFile" ) {
  | 
        
        
            | 
            | 
           364 | 
                 while ( my $line = <FILE> ) {
  | 
        
        
            | 
            | 
           365 | 
                    chomp $line;
  | 
        
        
            | 
            | 
           366 | 
                    my ( $filename, $version, $checksum ) = split( "\t", $line );
  | 
        
        
            | 
            | 
           367 | 
                    $$install{'files'}{$filename}{'new version'} = $version ? $version : '';
  | 
        
        
            | 
            | 
           368 | 
                 }
  | 
        
        
            | 
            | 
           369 | 
                 close FILE;
  | 
        
        
            | 
            | 
           370 | 
              }
  | 
        
        
           | 40 | 
           rodolico | 
           371 | 
              foreach my $file ( keys %{$$install{'files'}} ) {
  | 
        
        
            | 
            | 
           372 | 
                 $$install{'files'}{$file}{'installed version'} = -2 unless defined $$install{'files'}{$file}{'installed version'};
  | 
        
        
            | 
            | 
           373 | 
                 $$install{'files'}{$file}{'new version'} = -1 unless defined $$install{'files'}{$file}{'new version'};
  | 
        
        
            | 
            | 
           374 | 
              }
  | 
        
        
           | 33 | 
           rodolico | 
           375 | 
              return 1;
  | 
        
        
            | 
            | 
           376 | 
           } # getVersions
  | 
        
        
            | 
            | 
           377 | 
              | 
        
        
           | 34 | 
           rodolico | 
           378 | 
           # this actually does the installation, except for the configuration
  | 
        
        
           | 33 | 
           rodolico | 
           379 | 
           sub doInstall {
  | 
        
        
            | 
            | 
           380 | 
              my $install = shift;
  | 
        
        
            | 
            | 
           381 | 
              my $fileList = $$install{'files'};
  | 
        
        
            | 
            | 
           382 | 
              | 
        
        
           | 50 | 
           rodolico | 
           383 | 
              &checkDirectoryExists( $$install{'bindir'} . '/', $$install{'default permission'}, "$$install{'default owner'}:$$install{'default group'}" );
  | 
        
        
           | 33 | 
           rodolico | 
           384 | 
              foreach my $file ( keys %$fileList ) {
  | 
        
        
            | 
            | 
           385 | 
                 next unless ( $$fileList{$file}{'type'} && $$fileList{$file}{'type'} eq 'file' );
  | 
        
        
           | 40 | 
           rodolico | 
           386 | 
                 next if $$install{'action'} eq 'upgrade' && ! defined( $$fileList{$file}{'installed version'} )
  | 
        
        
            | 
            | 
           387 | 
                         ||
  | 
        
        
            | 
            | 
           388 | 
                         ( $$fileList{$file}{'new version'} eq $$fileList{$file}{'installed version'} );
  | 
        
        
           | 50 | 
           rodolico | 
           389 | 
                 &checkDirectoryExists( $$fileList{$file}{'target'}, $$install{'default permission'}, "$$install{'default owner'}:$$install{'default group'}" );
  | 
        
        
           | 33 | 
           rodolico | 
           390 | 
                 &runCommand( 
  | 
        
        
            | 
            | 
           391 | 
                       "cp $$fileList{$file}{'source'} $$fileList{$file}{'target'}",
  | 
        
        
            | 
            | 
           392 | 
                       "chmod $$fileList{$file}{'permission'} $$fileList{$file}{'target'}",
  | 
        
        
            | 
            | 
           393 | 
                       "chown  $$fileList{$file}{'owner'} $$fileList{$file}{'target'}"
  | 
        
        
            | 
            | 
           394 | 
                       );
  | 
        
        
            | 
            | 
           395 | 
              } # foreach file
  | 
        
        
            | 
            | 
           396 | 
              return 1;
  | 
        
        
            | 
            | 
           397 | 
           }
  | 
        
        
            | 
            | 
           398 | 
              | 
        
        
           | 35 | 
           rodolico | 
           399 | 
           sub postInstall {
  | 
        
        
            | 
            | 
           400 | 
              my $install = shift;
  | 
        
        
           | 37 | 
           rodolico | 
           401 | 
              | 
        
        
           | 35 | 
           rodolico | 
           402 | 
              # set up crontab, if necessary
  | 
        
        
           | 37 | 
           rodolico | 
           403 | 
              &runCommand( $$install{'crontab'} ) if defined ( $$install{'crontab'} );
  | 
        
        
            | 
            | 
           404 | 
              | 
        
        
            | 
            | 
           405 | 
              # seed configuration, if needed
  | 
        
        
            | 
            | 
           406 | 
              if ( $$install{'build config'} ) {
  | 
        
        
           | 43 | 
           rodolico | 
           407 | 
                 my $config;
  | 
        
        
            | 
            | 
           408 | 
                 my @fileList;
  | 
        
        
           | 37 | 
           rodolico | 
           409 | 
                 my $seedFile = $$install{'configuration'}{'configuration seed file'};
  | 
        
        
            | 
            | 
           410 | 
                 my $confFile = $$install{'configuration'}{'configuration file'};
  | 
        
        
            | 
            | 
           411 | 
              | 
        
        
            | 
            | 
           412 | 
                 if ( -f $seedFile  && &yesno( 'Add installation seed file? ' ) ) {
  | 
        
        
           | 43 | 
           rodolico | 
           413 | 
                    push @fileList, $seedFile;
  | 
        
        
           | 37 | 
           rodolico | 
           414 | 
                 } # if preload seed file
  | 
        
        
            | 
            | 
           415 | 
              | 
        
        
           | 35 | 
           rodolico | 
           416 | 
                 if (  -f $confFile  ) {
  | 
        
        
           | 43 | 
           rodolico | 
           417 | 
                    push @fileList, $confFile;
  | 
        
        
           | 35 | 
           rodolico | 
           418 | 
                 }
  | 
        
        
           | 43 | 
           rodolico | 
           419 | 
                 $config = makeConfig( @fileList );
  | 
        
        
           | 54 | 
           rodolico | 
           420 | 
                 # if ScriptDirs and moduleDirs not populated, do so from our configuration
  | 
        
        
            | 
            | 
           421 | 
                 if ( ! scalar @{ $$config{'scriptDirs'} }  ) {
  | 
        
        
            | 
            | 
           422 | 
                    $$config{'scriptDirs'} = [ ( $$install{'files'}{'scripts'}{'target'} ) ];
  | 
        
        
            | 
            | 
           423 | 
                 }
  | 
        
        
            | 
            | 
           424 | 
                 if ( ! @{ $$config{'moduleDirs'} }  ) {
  | 
        
        
            | 
            | 
           425 | 
                    $$config{'moduleDirs'} = [ ( $$install{'files'}{'modules'}{'target'}  ) ];
  | 
        
        
            | 
            | 
           426 | 
                 }
  | 
        
        
            | 
            | 
           427 | 
           #      print Dumper ($config ) ; die;
  | 
        
        
           | 43 | 
           rodolico | 
           428 | 
                 my $content = &showConf( $config );
  | 
        
        
           | 35 | 
           rodolico | 
           429 | 
                 print $content;
  | 
        
        
           | 37 | 
           rodolico | 
           430 | 
                 print &writeConfig( $$install{'configuration'}{'configuration file'} , $content ) . "\n"
  | 
        
        
            | 
            | 
           431 | 
                    if ( &yesno( "Write the above configuration to $$install{'configuration'}{'configuration file'}?" ) );
  | 
        
        
            | 
            | 
           432 | 
              } # if we are building/merging configuration
  | 
        
        
           | 35 | 
           rodolico | 
           433 | 
              | 
        
        
            | 
            | 
           434 | 
           }
  | 
        
        
           | 34 | 
           rodolico | 
           435 | 
              | 
        
        
           | 35 | 
           rodolico | 
           436 | 
           sub help {
  | 
        
        
            | 
            | 
           437 | 
              my $oses = join( ' ', keys %operatingSystems );
  | 
        
        
            | 
            | 
           438 | 
              print <<END
  | 
        
        
            | 
            | 
           439 | 
           $0 --verbose=x --os="osname" --dryrun --help --version
  | 
        
        
           | 34 | 
           rodolico | 
           440 | 
              | 
        
        
           | 35 | 
           rodolico | 
           441 | 
           --os      - osname is one of [$oses]
  | 
        
        
            | 
            | 
           442 | 
           --dryrun  - do not actually do anything, just tell you what I'd do
  | 
        
        
            | 
            | 
           443 | 
           --verbose - x is 0 (normal) to 3 (horrible)
  | 
        
        
            | 
            | 
           444 | 
           END
  | 
        
        
            | 
            | 
           445 | 
           }
  | 
        
        
           | 34 | 
           rodolico | 
           446 | 
              | 
        
        
           | 35 | 
           rodolico | 
           447 | 
              | 
        
        
            | 
            | 
           448 | 
              | 
        
        
            | 
            | 
           449 | 
           ##########################################
  | 
        
        
            | 
            | 
           450 | 
           # Main Loop
  | 
        
        
            | 
            | 
           451 | 
           ##########################################
  | 
        
        
            | 
            | 
           452 | 
              | 
        
        
            | 
            | 
           453 | 
           # handle any command line parameters that may have been passed in
  | 
        
        
            | 
            | 
           454 | 
              | 
        
        
            | 
            | 
           455 | 
           GetOptions (
  | 
        
        
            | 
            | 
           456 | 
                       "verbose|v=i" => \$verbose, # verbosity level, 0-9
  | 
        
        
            | 
            | 
           457 | 
                       "os|o=s"      => \$os,      # pass in the operating system
  | 
        
        
            | 
            | 
           458 | 
                       "dryrun|n"    => \$dryRun,  # do NOT actually do anything
  | 
        
        
            | 
            | 
           459 | 
                       'help|h'      => \$help,
  | 
        
        
            | 
            | 
           460 | 
                       'version|V'   => \$version
  | 
        
        
            | 
            | 
           461 | 
                       ) or die "Error parsing command line\n";
  | 
        
        
            | 
            | 
           462 | 
              | 
        
        
            | 
            | 
           463 | 
           if ( $help ) { &help() ; exit; }
  | 
        
        
            | 
            | 
           464 | 
           if ( $version ) { print "$0 version $VERSION\n"; exit; }
  | 
        
        
            | 
            | 
           465 | 
           &setDryRun( $dryRun ); # tell the library whether this is a dry run or not
  | 
        
        
            | 
            | 
           466 | 
              | 
        
        
           | 33 | 
           rodolico | 
           467 | 
           # figure out if we know our operating system
  | 
        
        
           | 35 | 
           rodolico | 
           468 | 
           $os = &getOS( \%install, \%operatingSystems, $os );
  | 
        
        
           | 33 | 
           rodolico | 
           469 | 
              | 
        
        
           | 42 | 
           rodolico | 
           470 | 
           &validateLibraries( \%libraries, $os );
  | 
        
        
            | 
            | 
           471 | 
              | 
        
        
           | 35 | 
           rodolico | 
           472 | 
           $installType = &getInstallActions( \%install );
  | 
        
        
           | 34 | 
           rodolico | 
           473 | 
              | 
        
        
           | 33 | 
           rodolico | 
           474 | 
           # based on the defaults, flesh out the install hash
  | 
        
        
            | 
            | 
           475 | 
           $status = &populateSourceDir( \%install, $sourceDir );
  | 
        
        
            | 
            | 
           476 | 
              | 
        
        
           | 35 | 
           rodolico | 
           477 | 
              | 
        
        
           | 33 | 
           rodolico | 
           478 | 
           $status = &getVersions( \%install );
  | 
        
        
            | 
            | 
           479 | 
              | 
        
        
           | 35 | 
           rodolico | 
           480 | 
           &showWork( \%install );
  | 
        
        
            | 
            | 
           481 | 
           die unless &yesno( "Ready to run? Select No to abort." );
  | 
        
        
            | 
            | 
           482 | 
              | 
        
        
           | 33 | 
           rodolico | 
           483 | 
           $status = &doInstall( \%install );
  | 
        
        
            | 
            | 
           484 | 
              | 
        
        
           | 35 | 
           rodolico | 
           485 | 
           $status = &postInstall( \%install );
  | 
        
        
           | 34 | 
           rodolico | 
           486 | 
              | 
        
        
           | 57 | 
           rodolico | 
           487 | 
           # create uninstaller script
  | 
        
        
            | 
            | 
           488 | 
           # find the last non-space string in the crontab value. This is the target of the link
  | 
        
        
            | 
            | 
           489 | 
           $install{'crontab'} =~ m/([^ ]+)$/;
  | 
        
        
            | 
            | 
           490 | 
           my $uninstall = "#! /usr/bin/env sh\n\n# Uninstall syinfo\nrm -fR $install{'bindir'} $install{'confdir'} $1\n";
  | 
        
        
            | 
            | 
           491 | 
           my $outFileName = $install{'bindir'} . '/uninstall';
  | 
        
        
            | 
            | 
           492 | 
           open UNINSTALL, ">$outFileName" or die "could not write to $outFileName: $!\n";
  | 
        
        
            | 
            | 
           493 | 
           print UNINSTALL $uninstall;
  | 
        
        
            | 
            | 
           494 | 
           close UNINSTALL;
  | 
        
        
            | 
            | 
           495 | 
           qx ( chmod 700 $outFileName );
  | 
        
        
            | 
            | 
           496 | 
              | 
        
        
            | 
            | 
           497 | 
           print "Uninstall script has been created at $outFileName\n";
  | 
        
        
            | 
            | 
           498 | 
              | 
        
        
           | 37 | 
           rodolico | 
           499 | 
           if ( ( -x $install{'configuration'}{'configurator'} ) && $install{'build config'} ) {
  | 
        
        
            | 
            | 
           500 | 
              exec( $install{'configuration'}{'configurator'} );
  | 
        
        
            | 
            | 
           501 | 
           } else {
  | 
        
        
            | 
            | 
           502 | 
              print "Done, you should check the files in $install{'bindir'} and $install{'confdir'} before running\n";
  | 
        
        
            | 
            | 
           503 | 
              print "If you need help configuring, the helper app at\n$install{'configuration'}{'configurator'}\ncan be used.\n";
  | 
        
        
            | 
            | 
           504 | 
           }
  | 
        
        
            | 
            | 
           505 | 
              | 
        
        
           | 35 | 
           rodolico | 
           506 | 
           1;   
  | 
        
        
           | 40 | 
           rodolico | 
           507 | 
              | 
        
        
            | 
            | 
           508 | 
              | 
        
        
            | 
            | 
           509 | 
           # clean will look for any file in bindir which is NOT in the list of available files and remove them
  | 
        
        
            | 
            | 
           510 | 
           # if files already exist in install, preserve their permissions
  |