From 17918cd5c6183ac856e25023ff493e172e22c81e Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Fri, 15 Nov 2019 16:35:25 +0100 Subject: [PATCH] minor fix omnishell functionality - unix agent --- pandora_agents/unix/pandora_agent | 232 +++++++++++++++++++++++++----- 1 file changed, 194 insertions(+), 38 deletions(-) diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index d9b3d32b3f..d6095d6d24 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -296,6 +296,77 @@ sub load_libraries() { } } +################################################################################ +# Erase blank spaces before and after the string +################################################################################ +sub trim { + my $string = shift; + if (empty($string)){ + return ""; + } + + $string =~ s/\r//g; + + chomp($string); + $string =~ s/^\s+//g; + $string =~ s/\s+$//g; + + return $string; +} + +################################################################################ +# Mix hashses +################################################################################ +sub merge_hashes { + my $_h1 = shift; + my $_h2 = shift; + + if (ref($_h1) ne "HASH") { + return \%{$_h2} if (ref($_h2) eq "HASH"); + } + + if (ref($_h2) ne "HASH") { + return \%{$_h1} if (ref($_h1) eq "HASH"); + } + + if ((ref($_h1) ne "HASH") && (ref($_h2) ne "HASH")) { + return {}; + } + + my %ret = (%{$_h1}, %{$_h2}); + + return \%ret; +} + +################################################################################ +# Empty +################################################################################ +sub empty { + my $str = shift; + + if (!(defined($str)) ){ + return 1; + } + + if(looks_like_number($str)){ + return 0; + } + + if (ref($str) eq "ARRAY") { + return (($#{$str}<0)?1:0); + } + + if (ref($str) eq "HASH") { + my @tmp = keys %{$str}; + return (($#tmp<0)?1:0); + } + + if ($str =~ /^\ *[\n\r]{0,2}\ *$/) { + return 1; + } + return 0; +} + ################################################################################ # Check a regular expression. Returns 1 if its valid, 0 otherwise. ################################################################################ @@ -731,13 +802,6 @@ sub parse_conf_modules($) { # Macros } elsif ($line =~ /^\s*module_macro(\S+)\s+(.*)\s*$/) { $module->{'macros'}{$1} = $2; - # Commands - } elsif ($line =~ /^\s*cmd_file\s+(.+)$/) { - if (ref ($Conf{'commands'}) ne "HASH") { - $Conf{'commands'} = {}; - } - # Initialize empty command hash. - $Conf{'commands'}->{$1} = {}; } } return; @@ -832,7 +896,21 @@ sub read_config (;$) { next if ($line =~ /^module\s*\w*/); #Configuration token - if ($line =~ /^\s*(\S+)\s+(.*)$/) { + if ($line =~ /^\s*(\S+)\s+(.*)$/) { + # Reserved keyword. + next if ($1 eq "commands"); + + if ($1 eq "cmd_file") { + # Commands + if (ref ($Conf{'commands'}) ne "HASH") { + $Conf{'commands'} = {}; + } + # Initialize empty command hash. + $Conf{'commands'}->{$2} = {}; + log_message('setup', "Command required $2"); + next; + } + log_message ('setup', "$1 is $2"); $Conf{$1} = $2; @@ -980,8 +1058,6 @@ sub read_config (;$) { $Conf{'secondary_server_opts'} = '-c ' . $Conf{'secondary_server_opts'} if ($Conf{'secondary_server_ssl'} eq '1'); } - # Check remote commands - prepare_commands(); } ################################################################################# @@ -1292,6 +1368,10 @@ sub check_remote_config () { %Collections = (); %Conf = %DefaultConf; + # Supposed to discard current configuration but not. + # Cleanup old commands configuration. + $Conf{'commands'} = {}; + # Reload the new configuration read_config (); @@ -1433,6 +1513,20 @@ sub prepare_commands { return; } + # Force configuration file read. + my @commands = read_config('cmd_file'); + + if (empty(\@commands)) { + $Conf{'commands'} = {}; + } else { + foreach my $rcmd (@commands) { + $Conf{'commands'}->{trim($rcmd)} = {}; + } + } + + # Cleanup old commands. Not registered. + cleanup_old_commands(); + foreach my $ref (keys %{$Conf{'commands'}}) { my $file_content; my $download = 0; @@ -1534,19 +1628,101 @@ sub report_command { return $return; } +################################################################################ +# Cleanup unreferenced rcmd and rcmd.done files. +################################################################################ +sub cleanup_old_commands { + # Cleanup old .rcmd and .rcmd.done files. + my %registered = map { $_.'.rcmd' => 1 } keys %{$Conf{'commands'}}; + if(opendir(my $dir, $ConfDir.'/commands/')) { + while (my $item = readdir($dir)) { + + # Skip other files. + next if ($item !~ /\.rcmd$/); + + # Clean .rcmd.done file if its command is not referenced in conf. + if (!defined($registered{$item})) { + if (-e $ConfDir.'/commands/'.$item) { + unlink($ConfDir.'/commands/'.$item); + } + if (-e $ConfDir.'/commands/'.$item.'.done') { + unlink($ConfDir.'/commands/'.$item.'.done'); + } + } + } + + # Close dir. + closedir($dir); + } + +} + ################################################################################ # Executes a command using defined timeout. ################################################################################ sub execute_command_timeout { - my ($command, $timeout) = @_; + my ($cmd, $timeout) = @_; - if (!looks_like_number($timeout)) { - `$command`; - } else { - `$command`; + if (!defined($timeout) + || !looks_like_number($timeout) + || $timeout <= 0 + ) { + `$cmd`; + return $?>>8; } - return $?>>8; + my $remaining_timeout = $timeout; + + my $RET; + my $output; + + my $pid = open ($RET, "-|"); + if (!defined($pid)) { + # Failed to fork. + log_message('error', '[command] Failed to fork.'); + return undef; + } + if ($pid == 0) { + # Child. + my $ret; + eval { + local $SIG{ALRM} = sub { die "timeout\n" }; + alarm $timeout; + `$cmd`; + alarm 0; + }; + + my $result = ($?>>8); + print $result; + + # Exit child. + # Child finishes. + exit; + + } else { + # Parent waiting. + while( --$remaining_timeout > 0 ){ + if (wait == -1) { + last; + } + # Wait child up to timeout seconds. + sleep 1; + } + } + + if ($remaining_timeout > 0) { + # Retrieve output from child. + $output = do { local $/; <$RET> }; + $output = $output>>8; + } + else { + # Timeout expired. + return 124; + } + + close($RET); + + return $output; } ################################################################################ @@ -3274,28 +3450,8 @@ while (1) { # Check file collections check_collections () unless ($Conf{'debug'} eq '1'); - if ($Conf{'debug'} ne '1') { - # Cleanup old .rcmd and .rcmd.done files. - my %registered = map { $_.'.rcmd' => 1 } keys %{$Conf{'commands'}}; - if(opendir(my $dir, $ConfDir.'/commands/')) { - while (my $item = readdir($dir)) { - # Skip other files. - next if ($item !~ /\.rcmd$/); - # Clean .rcmd.done file if its command is not referenced in conf. - if (!defined($registered{$item})) { - if (-e $item) { - unlink ($item); - } - if (-e $item.'.done') { - unlink ($item.'.done'); - } - } - } - - # Close dir. - closedir($dir); - } - } + # Check scheduled commands + prepare_commands() unless ($Conf{'debug'} eq '1'); # Launch broker agents @BrokerPid = ();