package INSTALL::substitute; use INSTALL::common; use strict; #------------------------------------------------------------------------------- # This method creates a substitution pattern from the passed in hash table. # The result of this function may be used in the first argument of the string # method, ort the third argument of file. #------------------------------------------------------------------------------- sub create { my %hash = @_; return(\%hash); } #------------------------------------------------------------------------------- # This method expects at least one parameter, and more likely two. The first, # is a value returned from the create method (listed above). The second, third, # fourth, etc. are strings in which you want to replace certain values with # other values. #------------------------------------------------------------------------------- sub string { ($#_ >= 0) || die "Invalid number of arguments to string."; my ($pHash,@strings) = @_; my $pattern = join("|",map(quotemeta,keys %{$pHash})); return(map {s/($pattern)/$pHash->{$1}/eg; $_ } @strings); } #------------------------------------------------------------------------------- # This method is similar to string, except that instead of taking its input from # a string, it takes its input from a file, then redirects those changes to # another file. #------------------------------------------------------------------------------- sub file { ($#_ >= 1) || die "Invalid number of arguments to file."; my ($source,$destination,$pHash) = @_; if (-r $source) { open(SRC,"<$source") || return(error("Unable to open $source for reading.")); my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($source); my @src_lines = ; close(SRC); if (-w $destination || (not -f $destination)) { open(DEST,">$destination") || return(error("Unable to open $destination for writing.")); print DEST string($pHash,@src_lines); close(DEST); chmod($mode,$destination); return(1); } else { return(error("$destination is not writable.")); } } else { return(error("$source is not readable.")); } } #------------------------------------------------------------------------------- # This method is similar to string and file. The input is taken from a string # and is written in its substituted form into the specified destination file. # # Note: There is a somewhat odd passing order to allow for several strings to # be passed. #------------------------------------------------------------------------------- sub string_to_file { ($#_ >= 1) || die "Invalid number of arguments to file."; my ($pHash,$destination,@strings) = @_; string($pHash,@strings); if (-w $destination || (not -f $destination)) { open(DEST,">$destination") || return(error("Unable to open $destination for writing.")); print DEST string($pHash,@strings); close(DEST); chmod(0644,$destination); return(1); } else { return(error("$destination is not writable.")); } } #------------------------------------------------------------------------------- # This method is the exact opposite of string_to_file. Instead of generating a # file from the source string, it generates a string from the source file. # # Note: As with the rest of these functions, whenever string input / output is # involved, several strings are allowed. As a result, the result of this method # is a list of strings, each string being a separate line from the input file. #------------------------------------------------------------------------------- sub file_to_string { ($#_ >= 1) || die "Invalid number of arguments to file."; my ($source,$pHash) = @_; if (-r $source) { open(SRC,"<$source") || return(error("Unable to open $source for reading.")); my @src_lines = ; close(SRC); return(string($pHash,@src_lines)); } else { return(error("$source is not readable.")); } } #------------------------------------------------------------------------------- # This method pulls its source files from the templates directory, and replaces # <<>> nested values within them with user defined values (stored in %hash), # as well as those values in INSTALL::global::variables. It also appends the # values stored in the chili.ini file, associated with the running asphome. # It should be noted that values are substituted such that the user specified # hash takes the most precedence, the INSTALL::globals::variables taking the # second highest precedence, and finally the chili.ini taking the least # precedence (i.e. if duplicate values exist in each hash, precedence will take # over in the listed order of which value will be used). #------------------------------------------------------------------------------- use INSTALL::global; use INSTALL::ini; my $pGlobals = \%INSTALL::global::variables; sub template { sub retrieve_chili_ini { my $pIni = INSTALL::ini::open($pGlobals->{chili_ini}); if (!$pIni) { return(error("Could not open $pGlobals->{chili_ini}.")); } my $pSection = INSTALL::ini::openSection($pIni, $pGlobals->{asphome}); if ($pSection) { return(%{$pSection}); } else { # This is expected on new installs. return; } } ($#_ >= 1) || die "Invalid number of arguments to file."; my ($source,$destination,%hash) = @_; %hash=(retrieve_chili_ini,%{$pGlobals},%hash); my %subst; foreach (keys %hash) { $subst{"<<$_>>"} = $hash{$_}; } if (-d $destination) { my @source_components = split(m@/@,$source); $destination .= "/$source_components[$#source_components]"; } return(file("$pGlobals->{template_dir}/$source",$destination,\%subst)); } sub optional_template { ($#_ >= 2) || die "Invalid number of arguments to file."; my ($source,$destination,$template_dir,%hash) = @_; my $old_template_dir = $pGlobals->{template_dir}; $pGlobals->{template_dir} = $template_dir; my $result = template($source,$destination,%hash); $pGlobals->{template_dir} = $old_template_dir; return($result); }