#! /usr/bin/env perl

# This file will contain information for a specific installer
# this allows the installer to be used on different programs.

# defines a basic install. Values are overridden depending on operating
# system as defined by %operatingSystems
our %install = (  'bindir' => '/opt/camp/sysinfo-client',
                 'confdir' => '/etc/camp/sysinfo-client',
                 'application name' => 'sysinfo client',
                 'default group' => 'root',
                 'default owner' => 'root',
                 'default permission' => '0700',
                 'configuration seed file' => '<installdir>/sysinfo-client.seed.yaml',
                 'configuration' => {
                          'configurator' => '<bindir>/configure.pl',
                          'configuration file' => '<confdir>/sysinfo-client.yaml',
                          'old configuration file' => '<confdir>/sysinfo-client.conf',
                          'permission' => '700',
                          'owner'      => '<default owner>',
                          'target'     => '<confdir>'
                            },
                 'files' => {
                           'configure.pl' => { 
                                 'type' => 'file',
                                 'permission' => '700', 
                                 'owner' => '<default owner>:<default group>', 
                                 'target' =>  '<bindir>'
                              },
                           'sysinfo-client' => { 
                                 'type' => 'file',
                                 'permission' => '700',
                                 'owner' => '<default owner>:<default group>',
                                 'target' =>  '<bindir>'
                              },
                           'sysinfoconf.pm' => {
                                 'type' => 'file',
                                 'permission' => '600',
                                 'owner' => '<default owner>:<default group>',
                                 'target' =>  '<bindir>'
                              },
                           'notes' => { 
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => '<default owner>:<default group>', 
                                 'target' =>  '<bindir>'
                              },
                           'sysinfo-client.conf.template.yaml' => { 
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => '<default owner>:<default group>', 
                                 'target' =>  '<bindir>' 
                              },
                           'getSendEmail.pl' => { 
                                 'type' => 'file',
                                 'permission' => '700', 
                                 'owner' => '<default owner>:<default group>', 
                                 'target' =>  '<bindir>' 
                              },
                           'install' => {
                                 'type' => 'file',
                                 'permission' => '700', 
                                 'owner' => '<default owner>:<default group>', 
                                 'target' =>  '<bindir>' 
                              },
                           'sysinfo-client.seed.example.yaml' => { 
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => '<default owner>:<default group>', 
                                 'target' =>  '<bindir>' 
                              },
                           'VERSION' => { 
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => '<default owner>:<default group>', 
                                 'target' =>  '<bindir>' 
                              },
                           'SYSTEM_VERSION' => { 
                                 'type' => 'file',
                                 'permission' => '755', 
                                 'owner' => '<default owner>:<default group>', 
                                 'target' =>  '<bindir>' 
                           },
                           'modules' => {
                              'type' => 'directory',
                              'permission' => '700', 
                              'owner' => '<default owner>:<default group>', 
                              'target' =>  '<bindir>',
                              'action' => 'chmod 700 *'
                           },
                           'scripts' => {
                              'type' => 'directory',
                              'permission' => '700', 
                              'owner' => '<default owner>:<default group>', 
                              'target' =>  '<bindir>',
                              'action' => 'chmod 700 *'
                           },
                     }
                  );

# hash to set up os specific rules. these override values in %install when a particular operating
# system is detected.
our %operatingSystems = (
                  'debian' => {
                     'regex'  => '(debian|mx|devuan)',
                     'bindir' => '/opt/camp/sysinfo-client',
                     'confdir' => '/etc/camp/sysinfo-client',
                     'crontab' => 'ln -fs <bindir>/sysinfo-client /etc/cron.daily/sysinfo-client',
                     'modules' => '((linux)|(dpkg)|(unix)|(all))',
                  },
                  'ipfire' => {
                     'regex'  => 'ipfire',
                     'bindir' => '/opt/camp/sysinfo-client',
                     'confdir' => '/etc/camp/sysinfo-client',
                     'crontab' => 'ln -fs <bindir>/sysinfo-client /etc/fcron.daily/sysinfo-client.fcron',
                     'modules' => '((ipfire)|(unix)|(all))',
                  },
                  'freebsd' => {
                     'regex' => 'freebsd',
                     'bindir' => '/usr/local/opt/camp/sysinfo-client',
                     'confdir' => '/usr/local/etc/camp/sysinfo-client',
                     'crontab' => 'ln -fs <bindir>/sysinfo-client /etc/periodic/daily/sysinfo-client',
                     'modules' => '((bsd)|(unix)|(all))',
                    'default group' => 'wheel',
                    'default owner' => 'root',
                  },
                  'opnsense' => {
                     'fileexists' => '/conf/config.xml',
                     'bindir' => '/usr/local/opt/camp/sysinfo-client',
                     'confdir' => '/usr/local/etc/camp/sysinfo-client',
                     #'crontab' => 'ln -fs <bindir>/sysinfo-client /etc/periodic/daily/sysinfo-client',
                     'modules' => '((bsd)|(unix)|(all))',
                    'default group' => 'wheel',
                    'default owner' => 'root',
                    'files' => {
                              'actions_sysinfo.conf' => {
                                    'type' => 'file',
                                    'permission' => '755',
                                    'owner' => '<default owner>:<default group>',
                                    'target' => '/usr/local/opnsense/service/conf/actions.d',
                                    'post action' => 'service configd restart',
                                    'message' => 'No automatic run can be done. Please log in through the webui and enable the sysinfo cron job'
                                 },
                              },
                 },
                  
                );

# list of libraries used by the system. We will offer to install them if
# we know how. NOTE: I have chosen to put the full installation command
# for each library. This allows us to use the package selector OR a different
# piece of code on a per-library basis, but results in something like
#      apt-get -y install perl-modules
#      apt-get -y install libwww-perl
# instead of
#      apt-get -y install libwww-perl perl-modules
# flexibility vs efficiency in this case.
our %libraries = ( 
                  'File::Basename' => {
                     'debian' => {
                        'command'   => 'apt-get -y install',
                        'parameter' => 'perl-modules'
                     }
                  },
                  'Exporter' => {
                     'debian' => {
                        'comand' => 'apt-get -y install',
                        'parameter' => 'perl-base'
                     },
                  },
                  'LWP' => { 
                     'debian' => {
                        'command'   => 'apt-get -y install',
                        'parameter' => 'libwww-perl'
                     },
                     'freebsd' => {
                        'command'   => 'echo y | pkg install',
                        'parameter' => 'p5-libwww'
                     },
                     'opnsense' => {
                        'command'   => 'cpan -i',
                        'parameter' => 'LWP'
                     }
                  },
                  'YAML::Tiny' => {
                     'debian' => {
                        'command'   => 'apt-get -y install',
                        'parameter' => 'libyaml-tiny-perl',
                     },
                     'freebsd' => {
                        'command' => 'echo y | pkg install',
                        'parameter' => 'p5-YAML-Tiny'
                     },
                     'opnsense' => {
                        'command' => 'cpan -i',
                        'parameter' => 'YAML::Tiny'
                     },
                     'ipfire' => {
                        'command' => 'cpan -i',
                        'parameter' => 'YAML::Tiny'
                     }
                  },
                  'Sys::Syslog' => {
                     'debian' => {
                        'command' => 'apt-get -y install',
                        'parameter' => 'libsys-syslog-perl',
                     },
                     'freebsd' => {
                        'command' => 'echo y | pkg install',
                        'parameter' => 'p5-Unix-Syslog',
                     },
                     'opnsense' => {
                        'command' => 'cpan -i',
                        'parameter' => 'Unix::Syslog'
                     }
                  },
                  'JSON' => {
                     'debian' => {
                        'command' => 'apt-get -y install',
                        'parameter' => 'libjson-perl'
                     },
                     'freebsd' => {
                        'command' => 'echo y | pkg install',
                        'parameter' => 'p5-JSON'
                     },
                    'opnsense' => {
                        'command' => 'cpan -i',
                        'parameter' => 'JSON'
                     },
                  }
                );

our %binaries = (
                  'dmidecode' => {
                     'debian' => {
                        'command' => 'apt-get -y install',
                        'parameter' => 'dmidecode'
                     },
                     'freebsd' => {
                        'command' => 'echo y | pkg install',
                        'parameter' => 'dmidecode'
                     },
                     'opnsense' => {
                        'command' => 'echo y | pkg install',
                        'parameter' => 'dmidecode'
                     }
                  }
               );


# if subroutine &postInstall exists, it is called with a reference to the %install hash
# postInstall may return, or may call some other script. it is the last thing called by
# the installer
sub postInstall {
   my $install = shift;
   
   # We need to open sysinfoconf so we can build the configuration file
   # using eval, since the installer is responsible for loading YAML::Tiny, so we may not
   # have it defined when we first start up.
   eval( 'use sysinfoconf qw/&writeConfig &makeConfig &showConf/;' );

   &logIt( 'Entering postInstall to build configuration' );
   # seed configuration, if needed
   if ( $$install{'build config'} ) {
      my $config;
      my @fileList;

      # the order is important here as, if multiple files exist, latter ones can
      # overwrite values in the previous. We do a push so the first value pushed
      # is processed last, ie has higher priority.
      push @fileList, $install->{'configuration'}->{'old configuration file'};
      push @fileList, $install->{'configuration'}->{'configuration file'};

      my $seedFile = $install->{'configuration'}->{'configuration seed file'};
      if ( -e $install->{'configuration seed file'} ) {
         push @fileList, $install->{'configuration seed file'};
      } # if preload seed file

      &logIt( "Order of configuration files is\n\t" . join( "\n\t", @fileList ) . "\n" );

      $config = &makeConfig( @fileList );
      # if ScriptDirs and moduleDirs not populated, do so from our configuration
      if ( ! $$config{'scriptDirs'} || ! scalar @{ $$config{'scriptDirs'} }  ) {
         $config->{'scriptDirs'} = [ $install->{'files'}->{'scripts'}->{'target'} ];
      }
      if ( ! $$config{'moduleDirs'} || ! @{ $$config{'moduleDirs'} }  ) {
         $config->{'moduleDirs'} = [ $install->{'files'}->{'modules'}->{'target'} ];
      }
      # We should have a nice combined configuration, so we'll write it to a temporary file
      my $filename = &writeConfig( '', &showConf( $config ) );
      my $confFileName = $install{'configuration'}{'configuration file'};
      # configure.pl is already designed to combine our temp file with our current config file and write it ou
      # so we'll just use that instead of reinventing the wheel
      exec( "$install{bindir}/configure.pl -f $filename -o $confFileName" );
   } # if we are building/merging configuration
}
