2014-08-12 Ramon Novoa <rnovoa@artica.es>
* pandora_agent: Fixed to make the 'Command Snapshot' feature work. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@10409 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
parent
7a58f9fa1f
commit
a525b562b0
|
@ -1,3 +1,7 @@
|
|||
2014-08-12 Ramon Novoa <rnovoa@artica.es>
|
||||
|
||||
* pandora_agent: Fixed to make the 'Command Snapshot' feature work.
|
||||
|
||||
2014-08-12 Ramon Novoa <rnovoa@artica.es>
|
||||
|
||||
* pandora_agent: Trim leading and trailing whitespaces from module names
|
||||
|
|
|
@ -1729,12 +1729,7 @@ sub write_module_xml ($@) {
|
|||
|
||||
# Data list
|
||||
if ($#data > 0) {
|
||||
$Xml .= " <datalist>\n";
|
||||
foreach my $data_item (@data) {
|
||||
chomp ($data_item);
|
||||
$Xml .= " <data><value><![CDATA[$data_item]]></value></data>\n";
|
||||
}
|
||||
$Xml .= " </datalist>\n";
|
||||
$Xml .= " <data><![CDATA[" . join('', @data) . "]]></data>\n";
|
||||
# Single data
|
||||
} else {
|
||||
chomp ($data[0]);
|
||||
|
|
|
@ -60,8 +60,14 @@ use strict;
|
|||
use warnings;
|
||||
use Getopt::Std;
|
||||
use IO::Select;
|
||||
use threads;
|
||||
use Thread::Semaphore;
|
||||
use POSIX ":sys_wait_h";
|
||||
use Time::HiRes qw(usleep);
|
||||
|
||||
# Constants for Win32 services.
|
||||
use constant WIN32_SERVICE_STOPPED => 0x01;
|
||||
use constant WIN32_SERVICE_RUNNING => 0x04;
|
||||
|
||||
my $t_libwrap_installed = eval { require Authen::Libwrap } ? 1 : 0;
|
||||
|
||||
|
@ -77,9 +83,8 @@ my $SOCKET_MODULE =
|
|||
: eval { require IO::Socket::INET } ? 'IO::Socket::INET'
|
||||
: die $@;
|
||||
|
||||
if ($SOCKET_MODULE eq 'IO::Socket::INET') {
|
||||
print_log ("IO::Socket::INET6 is not found. IPv6 is disabled.");
|
||||
}
|
||||
# Service name for Win32.
|
||||
my $SERVICE_NAME="Tentacle Server";
|
||||
|
||||
# Program version
|
||||
our $VERSION = '0.4.0';
|
||||
|
@ -130,7 +135,7 @@ my $t_retries = 3;
|
|||
my $t_select;
|
||||
|
||||
# Semaphore
|
||||
my $t_sem;
|
||||
my $t_sem :shared;
|
||||
|
||||
# Server socket
|
||||
my @t_server_sockets;
|
||||
|
@ -197,6 +202,7 @@ sub print_help {
|
|||
print ("\t-p port\t\tPort to listen on (default $t_port).\n");
|
||||
print ("\t-q\t\tQuiet. Do now print error messages.\n");
|
||||
print ("\t-r number\tNumber of retries for network opertions (default $t_retries).\n");
|
||||
print ("\t-S (install|uninstall|run) Manage the win32 service.\n");
|
||||
print ("\t-t time\t\tTime-out for network operations in seconds (default ${t_timeout}s).\n");
|
||||
print ("\t-v\t\tBe verbose.\n");
|
||||
print ("\t-w\t\tPrompt for OpenSSL private key password.\n");
|
||||
|
@ -240,27 +246,6 @@ sub daemonize {
|
|||
POSIX::setsid () || error ("Cannot start a new session: $!.");
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## SUB start_win_service
|
||||
## Turn the current process into a Windows service.
|
||||
################################################################################
|
||||
#sub start_win_service {
|
||||
# require Win32::Daemon;
|
||||
#
|
||||
# # Tell the OS to start the service
|
||||
# Win32::Daemon::StartService ();
|
||||
#
|
||||
# # Wait until the service manager is ready
|
||||
# while (SERVICE_START_PENDING != Win32::Daemon::State()) {
|
||||
# sleep (1);
|
||||
# }
|
||||
#
|
||||
# # Tell the service manager we are running
|
||||
# Win32::Daemon::State (SERVICE_RUNNING);
|
||||
#
|
||||
# # Call Win32::Daemon::StopService() when done
|
||||
#}
|
||||
|
||||
################################################################################
|
||||
## SUB parse_options
|
||||
## Parse command line options and initialize global variables.
|
||||
|
@ -271,7 +256,7 @@ sub parse_options {
|
|||
my @t_addresses_tmp;
|
||||
|
||||
# Get options
|
||||
if (getopts ('a:c:de:f:hi:k:m:op:qr:s:t:vwx:b:g:T', \%opts) == 0 || defined ($opts{'h'})) {
|
||||
if (getopts ('a:b:c:de:f:g:hi:k:m:op:qr:s:S:t:Tvwx:', \%opts) == 0 || defined ($opts{'h'})) {
|
||||
print_help ();
|
||||
exit 1;
|
||||
}
|
||||
|
@ -467,19 +452,33 @@ sub parse_options {
|
|||
error ("Authen::Libwrap is not installed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## SUB sigchld_handler
|
||||
## Handle child process termination.
|
||||
################################################################################
|
||||
sub sigchld_handler {
|
||||
# Win32 service management
|
||||
if (defined ($opts{'S'})) {
|
||||
my $service_action = $opts{'S'};
|
||||
if ($^O ne 'MSWin32') {
|
||||
error ("Windows services are only available on Win32.");
|
||||
} else {
|
||||
eval "use Win32::Daemon";
|
||||
die($@) if ($@);
|
||||
|
||||
while (waitpid(-1, &WNOHANG) > 0) {
|
||||
$t_sem->up ();
|
||||
if ($service_action eq 'install') {
|
||||
install_service();
|
||||
} elsif ($service_action eq 'uninstall') {
|
||||
uninstall_service();
|
||||
} elsif ($service_action eq 'run') {
|
||||
Win32::Daemon::RegisterCallbacks({
|
||||
start => \&callback_start,
|
||||
running => \&callback_running,
|
||||
stop => \&callback_stop,
|
||||
});
|
||||
Win32::Daemon::StartService();
|
||||
exit 0;
|
||||
} else {
|
||||
error("Unknown action: $service_action");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$SIG{CHLD} = \&sigchld_handler;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
@ -660,87 +659,86 @@ sub start_ssl {
|
|||
}
|
||||
|
||||
################################################################################
|
||||
## SUB accept_connection
|
||||
## Accept an incoming connection and fork.
|
||||
## SUB accept_connections
|
||||
## Manage incoming connections.
|
||||
################################################################################
|
||||
sub accept_connection {
|
||||
sub accept_connections {
|
||||
my $pid;
|
||||
my $t_server_socket;
|
||||
|
||||
my @ready = $select->can_read;
|
||||
# Start server
|
||||
start_server ();
|
||||
|
||||
foreach $t_server_socket (@ready) {
|
||||
# Initialize semaphore
|
||||
$t_sem = Thread::Semaphore->new ($t_max_conn);
|
||||
|
||||
# Accept connection
|
||||
$t_client_socket = $t_server_socket->accept ();
|
||||
while (1) {
|
||||
my @ready = $select->can_read;
|
||||
foreach $t_server_socket (@ready) {
|
||||
|
||||
if (! defined ($t_client_socket)) {
|
||||
# Accept connection
|
||||
$t_client_socket = $t_server_socket->accept ();
|
||||
|
||||
# EINTR
|
||||
if ($! ne '') {
|
||||
next;
|
||||
if (! defined ($t_client_socket)) {
|
||||
next if ($! ne ''); # EINTR
|
||||
error ("accept: $!.");
|
||||
}
|
||||
|
||||
error ("accept: $!.");
|
||||
print_log ("Client connected from " . $t_client_socket->sockhost ());
|
||||
|
||||
# Create a new thread and serve the client
|
||||
$t_sem->down();
|
||||
my $thr = threads->create(\&serve_client);
|
||||
if (! defined ($thr)) {
|
||||
error ("Error creating thread: $!.");
|
||||
}
|
||||
$thr->detach();
|
||||
}
|
||||
|
||||
print_log ("Client connected from " . $t_client_socket->sockhost ());
|
||||
usleep (1000);
|
||||
}
|
||||
}
|
||||
|
||||
# Fork and serve the client
|
||||
$pid = fork ();
|
||||
if (! defined ($pid)) {
|
||||
error ("Cannot fork: $!.");
|
||||
################################################################################
|
||||
## SUB serve_client
|
||||
## Serve a connected client.
|
||||
################################################################################
|
||||
sub serve_client() {
|
||||
|
||||
if ($t_use_libwrap) {
|
||||
if (! hosts_ctl($t_program_name, $t_client_socket)) {
|
||||
print_log ("Connection from " . $t_client_socket->sockhost() . " is closed by tcpwrappers.");
|
||||
$t_client_socket->close ();
|
||||
$t_sem->up();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
eval {
|
||||
# Add client socket to select queue
|
||||
$t_select = IO::Select->new ();
|
||||
$t_select->add ($t_client_socket);
|
||||
|
||||
# Start SSL
|
||||
if ($t_ssl == 1) {
|
||||
start_ssl ();
|
||||
}
|
||||
|
||||
# Child
|
||||
if ($pid == 0) {
|
||||
|
||||
# We do not need the server socket
|
||||
$t_server_socket->close ();
|
||||
|
||||
if ($t_use_libwrap) {
|
||||
if (! hosts_ctl($t_program_name, $t_client_socket)) {
|
||||
print_log ("Connection from " . $t_client_socket->sockhost() . " is closed by tcpwrappers.");
|
||||
$t_client_socket->close ();
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
# Add client socket to select queue
|
||||
$t_select = IO::Select->new ();
|
||||
$t_select->add ($t_client_socket);
|
||||
|
||||
# Start SSL
|
||||
if ($t_ssl == 1) {
|
||||
start_ssl ();
|
||||
}
|
||||
|
||||
# Authenticate client
|
||||
if ($t_pwd ne '') {
|
||||
auth_pwd ();
|
||||
}
|
||||
|
||||
# Check if proxy mode is enable
|
||||
if (defined ($t_proxy_ip)) {
|
||||
|
||||
serve_proxy_connection ();
|
||||
|
||||
} else {
|
||||
|
||||
serve_connection ();
|
||||
}
|
||||
|
||||
$t_client_socket->close ();
|
||||
|
||||
# Must exit now
|
||||
exit;
|
||||
# Authenticate client
|
||||
if ($t_pwd ne '') {
|
||||
auth_pwd ();
|
||||
}
|
||||
|
||||
# Check if proxy mode is enable
|
||||
if (defined ($t_proxy_ip)) {
|
||||
serve_proxy_connection ();
|
||||
} else {
|
||||
serve_connection ();
|
||||
}
|
||||
};
|
||||
|
||||
# Parent
|
||||
$t_client_socket->close ();
|
||||
|
||||
}
|
||||
$t_client_socket->close ();
|
||||
$t_sem->up();
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
@ -1045,10 +1043,8 @@ sub print_log {
|
|||
sub error {
|
||||
|
||||
if ($t_quiet == 0) {
|
||||
print (STDERR "[err] $_[0]\n");
|
||||
die("[err] $_[0]\n\n");
|
||||
}
|
||||
|
||||
exit 1;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
@ -1413,6 +1409,91 @@ sub apply_filters ($) {
|
|||
return '';
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## SUB install_service
|
||||
## Install the Windows service.
|
||||
################################################################################
|
||||
sub install_service() {
|
||||
|
||||
my $service_path = $0;
|
||||
my $service_params = "-s \"$t_directory\" -S run";
|
||||
|
||||
my %service_hash = (
|
||||
machine => '',
|
||||
name => 'TENTACLESRV',
|
||||
display => $SERVICE_NAME,
|
||||
path => $service_path,
|
||||
user => '',
|
||||
pwd => '',
|
||||
description => 'Tentacle Server http://sourceforge.net/projects/tentacled/',
|
||||
parameters => $service_params
|
||||
);
|
||||
|
||||
if (Win32::Daemon::CreateService(\%service_hash)) {
|
||||
print "Successfully added.\n";
|
||||
exit 0;
|
||||
} else {
|
||||
print "Failed to add service: " . Win32::FormatMessage(Win32::Daemon::GetLastError()) . "\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## SUB uninstall_service
|
||||
## Install the Windows service.
|
||||
################################################################################
|
||||
sub uninstall_service() {
|
||||
if (Win32::Daemon::DeleteService('', 'TENTACLESRV')) {
|
||||
print "Successfully deleted.\n";
|
||||
exit 0;
|
||||
} else {
|
||||
print "Failed to delete service: " . Win32::FormatMessage(Win32::Daemon::GetLastError()) . "\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## SUB callback_running
|
||||
## Windows service callback function for the running event.
|
||||
################################################################################
|
||||
sub callback_running {
|
||||
|
||||
if (Win32::Daemon::State() == WIN32_SERVICE_RUNNING) {
|
||||
}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## SUB callback_start
|
||||
## Windows service callback function for the start event.
|
||||
################################################################################
|
||||
sub callback_start {
|
||||
|
||||
# Accept_connections ();
|
||||
my $thr = threads->create(\&accept_connections);
|
||||
if (!defined($thr)) {
|
||||
Win32::Daemon::State(WIN32_SERVICE_STOPPED);
|
||||
Win32::Daemon::StopService();
|
||||
return;
|
||||
}
|
||||
$thr->detach();
|
||||
|
||||
Win32::Daemon::State(WIN32_SERVICE_RUNNING);
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## SUB callback_stop
|
||||
## Windows service callback function for the stop event.
|
||||
################################################################################
|
||||
sub callback_stop {
|
||||
|
||||
foreach my $t_server_socket (@t_server_sockets) {
|
||||
$t_server_socket->close ();
|
||||
}
|
||||
|
||||
Win32::Daemon::State(WIN32_SERVICE_STOPPED);
|
||||
Win32::Daemon::StopService();
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Main
|
||||
################################################################################
|
||||
|
@ -1444,25 +1525,16 @@ if ($t_daemon == 1 && $^O ne 'MSWin32') {
|
|||
|
||||
# Handle ctr-c
|
||||
if ($^O eq 'MSWin32') {
|
||||
no warnings;
|
||||
$SIG{INT2} = \&stop_server;
|
||||
use warnings;
|
||||
}
|
||||
else {
|
||||
$SIG{INT} = \&stop_server;
|
||||
}
|
||||
|
||||
# Handle SIGCHLD
|
||||
$SIG{CHLD} = \&sigchld_handler;
|
||||
|
||||
start_server ();
|
||||
|
||||
# Initialize semaphore
|
||||
$t_sem = Thread::Semaphore->new ($t_max_conn);
|
||||
|
||||
# Accept connections
|
||||
while (1) {
|
||||
$t_sem->down ();
|
||||
accept_connection ();
|
||||
}
|
||||
accept_connections();
|
||||
|
||||
__END__
|
||||
|
||||
|
|
Loading…
Reference in New Issue