package INSTALL::internaldb; use INSTALL::common; use INSTALL::services; use INSTALL::global; use INSTALL::ini; use strict; no strict 'refs'; no strict 'subs'; # This should be set to a value that evaluates to true, if the internaldb # functionality (provided by postgres) is wanted. Otherwise, it is # assumed that the samples will use a different means to provide the same # functionality. In both cases, the configure and uninstall should be # called. my $CONST_UseInternalDB = 0; ########## Define Globals my $pGlobals = \%INSTALL::global::variables; my $debug = 0; #------------------------------------------------------------------------------ # Returns the files and subdirectories contained in the specified directory and # its subdirectories. It should be noted that the directory passed will be # among the returns. #------------------------------------------------------------------------------ sub directory_scan { ($#_ == 0) || die "Invalid number of parameters to INSTALL::internaldb::directory_scan."; my ($dirname) = @_; local *DIR; opendir(DIR,$dirname); my @unclassified = readdir(DIR); closedir(DIR); my @files = grep { not -d "$dirname/$_" } @unclassified; my @subdirs = grep { -d "$dirname/$_" && ($_ ne ".") && ($_ ne "..") } @unclassified; @files = map { "$dirname/$_" } @files; @subdirs = map { "$dirname/$_" } @subdirs; # Iterate don't recurse. while ($#subdirs >= 0) { my $subdir = pop @subdirs; local *SUBDIR; opendir(SUBDIR,$subdir); @unclassified = readdir(SUBDIR); closedir(SUBDIR); my @subdir_files = grep { not -d "$subdir/$_" } @unclassified; my @subdir_subdirs = grep { -d "$subdir/$_" && ($_ ne ".") && ($_ ne "..") } @unclassified; @subdir_files = map { "$subdir/$_" } @subdir_files; @subdir_subdirs = map { "$subdir/$_" } @subdir_subdirs; push @files, $subdir; push @files, @subdir_files; push @subdirs, @subdir_subdirs; } return(@files); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # External functions #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sub load_globals { ($#_ == -1) || die "Invalid number of arguments."; my $pIni = INSTALL::ini::open($pGlobals->{chili_ini}); if (not $pIni) { return(error("Unable to open $pGlobals->{chili_ini} - load_globals.")); } else { my $pSection = INSTALL::ini::openSection($pIni, $pGlobals->{asphome}); if (not $pSection) { return(error("Unable to locate section [$pGlobals->{asphome}].")); } else { return(%{$pSection}); } } } sub store_globals { my (%additions) = @_; my $pIni = INSTALL::ini::open($pGlobals->{chili_ini}); if (not $pIni) { return(error("Unable to open $pGlobals->{chili_ini} - load_globals.")); } else { my $pSection = INSTALL::ini::insertSection($pIni, $pGlobals->{asphome}); foreach (keys %additions) { $pSection->{$_} = $additions{$_}; } return(INSTALL::ini::save($pIni,$pGlobals->{chili_ini})); } } use INSTALL::os; my $pOS = \%INSTALL::os::Details; sub stop { libpath_append("$pGlobals->{asphome}/odbc/internaldb/lib", "$pGlobals->{asphome}/odbc/sqlnk/lib", "$pGlobals->{lib_dir}"); sub confirm_internaldb_pid { ($#_ == 0) || die "Invalid number of arguments."; my ($pid) = @_; my %global_stats = load_globals; for ($pOS->{os}) { /linux/i && do { my $cmdline = `cat /proc/$pid/cmdline 2>&1 | tr '\\0' ' '`; if (($cmdline =~ /chili-postmaster/) && ($cmdline =~ /\s$global_stats{internaldb::port}\s/)) { return($pid); } else { return(undef); } last; }; return(error("Unsupported operating system.")); } } sub find_internaldb_pid { for ($pOS->{os}) { /linux/i && do { local *PROC; opendir(PROC,"/proc") || return(error("Unable to stop internaldb.")); my @subdirs = readdir(PROC); closdir(PROC); foreach my $file (@subdirs) { if ($file =~ /[0-9]+/) { if (confirm_internaldb_pid($file)) { return($file); } } } last; }; return(error("Unsupported operating system.")); } return(undef); } my %global_stats = load_globals; if ($CONST_UseInternalDB) { my $pid; if (-f "$pGlobals->{log_dir}/internaldb.pid") { if (open(PID_FILE,"<$pGlobals->{log_dir}/internaldb.pid")) { my $internaldb_pid = ; chomp $internaldb_pid; close(PID_FILE); $pid = confirm_internaldb_pid($internaldb_pid); unlink("$pGlobals->{log_dir}/internaldb.pid"); } } if (not $pid) { $pid = find_internaldb_pid; } if ($pid > 1) { kill(&SIGTERM,$pid); } # Make sure the socket connection is gone. unlink("/tmp/.s.PGSQL.$global_stats{internaldb::port}"); return(1); } return(undef); } sub start { if ($CONST_UseInternalDB) { libpath_append("$pGlobals->{asphome}/odbc/internaldb/lib", "$pGlobals->{asphome}/odbc/sqlnk/lib", "$pGlobals->{lib_dir}"); my %global_stats = load_globals; my $executable = "$global_stats{internaldb::dbbin_dir}/chili-postmaster"; stop; my $pid = fork; if (not $pid) { my (undef,undef,$uid,$gid) = getpwnam("chiliasp"); ($(,$),$<,$>) = ($gid,$gid,$uid,$uid); $ENV{PGUSER}="chiliasp"; $ENV{PGPASSWORD}="psailihc"; $ENV{PGDATA}=$global_stats{internaldb::dbdata_dir}; if ($debug) { exec($executable,split(/ /,"-p $global_stats{internaldb::port}"), "-b","$executable"); } else { close(STDERR); close(STDOUT); close(STDIN); exec($executable,split(/ /,"-p $global_stats{internaldb::port}"), "-b","$executable","-o","-Q","-o","-o /dev/null"); } } elsif (open(PID_FILE,">$pGlobals->{log_dir}/internaldb.pid")) { print PID_FILE "$pid\n"; close(PID_FILE); } return(1); } return(undef); } #------------------------------------------------------------------------------ # This method will do the actual installation / configuration of the # internaldb. #------------------------------------------------------------------------------ sub configure { if ($CONST_UseInternalDB) { my %global_additions = ( internaldb::db_dir => "$pGlobals->{asphome}/odbc/internaldb", internaldb::dbbin_dir => "$pGlobals->{asphome}/odbc/internaldb/bin", internaldb::dblib_dir => "$pGlobals->{asphome}/odbc/internaldb/lib", internaldb::dbdata_dir => "$pGlobals->{asphome}/odbc/internaldb/data", ); # Find all of the files. my @files = directory_scan($global_additions{internaldb::db_dir}); # Change the ownership of the database files to chiliasp. # This is required, so that the chili-postmaster process has the # ability to read / write to the database files. my ($username,$password,$uid,$gid) = getpwnam("chiliasp"); note("Installing sample database support."); unless(chown($uid,$gid,@files)) { return(error("Unable to change the ownership of one or more files.\n", "Cause: $!")); } my $postgresql = "$global_additions{internaldb::dbbin_dir}/postgres"; # This is required because we need to run the chili-postmaster (which is # a symlink to postgresql) to always execute as chiliasp, regardless of # who executes it. # It should be noted that this seems to fail on some distributions due # to improper support of seteuid. As such, I have taken further # precautions upon start. unless(chmod(04755,$postgresql)) { return(error("Unable to set the setuid bit of the $postgresql file.\n", "Cause: $!")); } $global_additions{internaldb::port} = INSTALL::services::allocate_free_ports(1025,1,"Sun Chili!Soft ASP InternalDB"); summary_log("Internal database successfully added:", " Port: $global_additions{internaldb::port}"); my @binary_template_files = ( "start-internaldb", "stop-internaldb" ); chmod(0755, (map { "$pGlobals->{template_dir}/$_" } @binary_template_files), @binary_template_files); # If the internaldb is activated, we must make certain to add the start / stop scripts. INSTALL::substitute::template("start-internaldb",$pGlobals->{install_dir},%global_additions); INSTALL::substitute::template("stop-internaldb",$pGlobals->{install_dir},%global_additions); store_globals(%global_additions); } return(1); } #------------------------------------------------------------------------------ # #------------------------------------------------------------------------------ sub uninstall { if ($CONST_UseInternalDB) { my %global_stats = load_globals; if (exists $global_stats{internaldb::port}) { # Deallocate the used ports and stop the started daemon. INSTALL::services::deallocate_ports($global_stats{internaldb::port},1); return(stop); } else { return(undef); } } else { return(1); } } 1;