# status-lib.pl
# Functions for getting the status of services

do '../web-lib.pl';
&init_config();
require '../ui-lib.pl';
%access = &get_module_acl();

$services_dir = "$module_config_directory/services";

# list_services()
# Returns a list of all services this module knows how to get status on.
# If this is the first time the function is called a default set of services
# will be setup.
sub list_services
{
my (%mod, @rv);
if (!-d $services_dir) {
	# setup initial services
	mkdir($module_config_directory, 0700);
	mkdir($services_dir, 0700);
	system("cp services/* $services_dir");
	}
map { $mod{$_}++ } &list_modules();
opendir(DIR, $services_dir);
while($f = readdir(DIR)) {
	next if ($f !~ /^(.*)\.serv$/);
	local $serv = &get_service($1);
	next if (!$serv || !$serv->{'type'} || !$serv->{'id'});
	if ($serv->{'depends'}) {
		local $d;
		map { $d++ if (!$mod{$_}) } split(/\s+/, $serv->{'depends'});
		push(@rv, $serv) if (!$d);
		}
	else {
		push(@rv, $serv);
		}
	}
closedir(DIR);
return @rv;
}

# get_service(id)
sub get_service
{
local %serv;
&read_file("$services_dir/$_[0].serv", \%serv);
return $_[0] ne $serv{'id'} ? undef : \%serv;
}

# save_service(&serv)
sub save_service
{
&lock_file("$services_dir/$_[0]->{'id'}.serv");
&write_file("$services_dir/$_[0]->{'id'}.serv", $_[0]);
&unlock_file("$services_dir/$_[0]->{'id'}.serv");
}

# delete_service(serv)
sub delete_service
{
&lock_file("$services_dir/$_[0]->{'id'}.serv");
unlink("$services_dir/$_[0]->{'id'}.serv");
&unlock_file("$services_dir/$_[0]->{'id'}.serv");
}

# service_status(&service)
# Gets the status of a service, possibly on another server
sub service_status
{
local $t = $_[0]->{'type'};
local $rv;
eval {
	local $SIG{'ALRM'} = sub { die "status alarm\n" };
	alarm(60);	# wait at most 60 secs for a result
	if ($_[0]->{'remote'}) {
		# Make a remote call to another webmin server
		&remote_error_setup(\&remote_error);
		$remote_error_msg = undef;
		&remote_foreign_require($_[0]->{'remote'}, 'status', 'status-lib.pl')
			if (!$done_remote_status{$_[0]->{'remote'}}++);
		if ($remote_error_msg) {
			$rv = { 'up' => -2,
				 'desc' => "$text{'mon_webmin'} : $remote_error_msg" };
			}
		else {
			local %s = %{$_[0]};
			delete($s{'remote'});
			$rv = &remote_foreign_call($_[0]->{'remote'}, 'status',
						    'service_status', \%s);
			if ($remote_error_msg) {
				$rv = { 'up' => -2, 'desc' =>
				    "$text{'mon_webmin'} : $remote_error_msg" };
				}
			}
		}
	else {
		# Just include and use the local monitor library
		do "${t}-monitor.pl" if (!$done_monitor{$t}++);
		local $func = "get_${t}_status";
		$rv = &$func($_[0], $_[0]->{'clone'} ? $_[0]->{'clone'} : $t);
		}
	alarm(0);
	};
if ($@ eq "status alarm\n") {
	return { 'up' => -3 };
	}
elsif ($@) {
	# A real error happened
	die $@;
	}
else {
	return $rv;
	}
}

sub remote_error
{
$remote_error_msg = join("", @_);
}

# list_modules()
# Returns a list of all modules available on this system
sub list_modules
{
return map { $_->{'dir'} } grep { &check_os_support($_) }
	&get_all_module_infos();
}

# list_handlers()
# Returns a list of the module's type handlers
sub list_handlers
{
local ($f, @rv);
opendir(DIR, ".");
while($f = readdir(DIR)) {
	push(@rv, $1) if ($f =~ /^(\S+)-monitor\.pl$/);
	}
closedir(DIR);
return @rv;
}

# depends_check(&service, [module]+)
sub depends_check
{
return if ($_[0]->{'id'});	# only check for new services
if ($_[0]->{'remote'}) {
	# Check on the remote server
	foreach $m (@_[1..$#_]) {
		&remote_foreign_check($_[0]->{'remote'}, $m) ||
			&error(&text('depends_remote', "<tt>$m</tt>",
				     "<tt>$_[0]->{'remote'}</tt>"));
		}
	}
else {
	# Check on this server
	foreach $m (@_[1..$#_]) {
		local %minfo = &get_module_info($m);
		%minfo || &error(&text('depends_mod', "<tt>$m</tt>"));
		&check_os_support(\%minfo) ||
			&error(&text('depends_os', "<tt>$minfo{'desc'}</tt>"));
		}
	$_[0]->{'depends'} = join(" ", @_[1..$#_]);
	}
}

# find_named_process(regexp)
sub find_named_process
{
foreach $p (&foreign_call("proc", "list_processes")) {
	$p->{'args'} =~ s/\s.*$//; $p->{'args'} =~ s/[\[\]]//g;
	if ($p->{'args'} =~ /$_[0]/) {
		return $p;
		}
	}
return undef;
}

# smtp_command(handle, command)
sub smtp_command
{
local ($m, $c) = @_;
print $m $c;
local $r = <$m>;
if ($r !~ /^[23]\d+/) {
	&error(&text('sched_esmtpcmd', "<tt>$c</tt>", "<tt>$r</tt>"));
	}
}

1;

