# $Id: smcontrol.pl,v 8.8 2008-07-21 21:31:43 ca Exp $
use strict;
use FileHandle;
use Socket;
my $sendmailDaemon = "/usr/sbin/sendmail -q30m -bd";
##########################################################################
#
# &get_controlname -- read ControlSocketName option from sendmail.cf
#
# Parameters:
# none.
#
# Returns:
# control socket filename, undef if not found
#
sub get_controlname
{
my $cn = undef;
my $qd = undef;
while (<CF>)
{
chomp;
if (/^O ControlSocketName\s*=\s*([^#]+)$/o)
{
$cn = $1;
}
if (/^O QueueDirectory\s*=\s*([^#]+)$/o)
{
$qd = $1;
}
if (/^OQ([^#]+)$/o)
{
$qd = $1;
}
}
close(CF);
if (not defined $cn)
{
return undef;
}
if ($cn !~ /^\//o)
{
return undef if (not defined $qd);
}
return $cn;
}
##########################################################################
#
# &do_command -- send command to sendmail daemon view control socket
#
# Parameters:
# controlsocket -- filename for socket
# command -- command to send
#
# Returns:
# reply from sendmail daemon
#
sub do_command
{
my $controlsocket = shift;
my $command = shift;
my $proto = getprotobyname('ip');
my @reply;
my $i;
for ($i = 0; $i < 4; $i++)
{
{
if ($i == 3)
{
close(SOCK);
return undef;
}
sleep 1;
next;
}
last;
}
print SOCK "$command\n";
close(SOCK);
return join '', @reply;
}
##########################################################################
#
# &sendmail_running -- check if sendmail is running via SMTP
#
# Parameters:
# none
#
# Returns:
# 1 if running, undef otherwise
#
sub sendmail_running
{
my $proto = getprotobyname("tcp");
{
close(SOCK);
return undef;
}
while (<SOCK>)
{
if (/^(\d{3})([ -])/)
{
if ($1 != 220)
{
close(SOCK);
return undef;
}
}
else
{
close(SOCK);
return undef;
}
last if ($2 eq " ");
}
print SOCK "QUIT\n";
while (<SOCK>)
{
last if (/^\d{3} /);
}
close(SOCK);
return 1;
}
##########################################################################
#
# &munge_status -- turn machine readable status into human readable text
#
# Parameters:
# raw -- raw results from sendmail daemon STATUS query
#
# Returns:
# human readable text
#
sub munge_status
{
my $raw = shift;
my $cooked = "";
my $daemonStatus = "";
{
$cooked .= "Current number of children: $1";
if ($2 > 0)
{
$cooked .= " (maximum $2)";
}
$cooked .= "\n";
$cooked .= "QueueDir free disk space (in blocks): $3\n";
$cooked .= "Load average: $4\n";
}
{
if (not $daemonStatus)
{
}
else
{
$cooked .= "Child Process $1 Status: $2\n";
}
}
return ($daemonStatus, $cooked);
}
##########################################################################
#
# &start_daemon -- fork off a sendmail daemon
#
# Parameters:
# control -- control socket name
#
# Returns:
# Error message or "OK" if successful
#
sub start_daemon
{
my $control = shift;
my $pid;
if ($pid = fork)
{
my $exitstat;
$exitstat = $? / 256;
if ($exitstat != 0)
{
return "sendmail daemon startup exited with exit value $exitstat";
}
}
elsif (defined $pid)
{
exec($sendmailDaemon);
die "Unable to start sendmail daemon: $!.\n";
}
else
{
return "Could not create new process: $!\n";
}
return "OK\n";
}
##########################################################################
#
# &stop_daemon -- stop the sendmail daemon using control socket
#
# Parameters:
# control -- control socket name
#
# Returns:
# Error message or status message
#
sub stop_daemon
{
my $control = shift;
my $status;
if (not defined $control)
{
return "The control socket is not configured so the daemon can not be stopped.\n";
}
}
##########################################################################
#
# &restart_daemon -- restart the sendmail daemon using control socket
#
# Parameters:
# control -- control socket name
#
# Returns:
# Error message or status message
#
sub restart_daemon
{
my $control = shift;
my $status;
if (not defined $control)
{
return "The control socket is not configured so the daemon can not be restarted.";
}
}
##########################################################################
#
# &memdump -- get memdump from the daemon using the control socket
#
# Parameters:
# control -- control socket name
#
# Returns:
# Error message or status message
#
sub memdump
{
my $control = shift;
my $status;
if (not defined $control)
{
return "The control socket is not configured so the daemon can not be queried for memdump.";
}
}
##########################################################################
#
# &help -- get help from the daemon using the control socket
#
# Parameters:
# control -- control socket name
#
# Returns:
# Error message or status message
#
sub help
{
my $control = shift;
my $status;
if (not defined $control)
{
return "The control socket is not configured so the daemon can not be queried for help.";
}
}
my $status = undef;
my $daemonStatus = undef;
my $opts = {};
my $command = shift;
if (not defined $control)
{
die "No control socket available.\n";
}
if (not defined $command)
{
}
if ($command eq "status")
{
if (not defined $status)
{
# Not responding on control channel, query via SMTP
if (&sendmail_running)
{
$daemonStatus = "Sendmail is running but not answering status queries.";
}
else
{
$daemonStatus = "Sendmail does not appear to be running.";
}
}
else
{
# Munge control channel output
}
}
elsif (lc($command) eq "shutdown")
{
}
elsif (lc($command) eq "restart")
{
}
elsif (lc($command) eq "start")
{
}
elsif (lc($command) eq "memdump")
{
}
elsif (lc($command) eq "help")
{
}
elsif (lc($command) eq "mstat")
{
if (not defined $status)
{
# Not responding on control channel, query via SMTP
if (&sendmail_running)
{
$daemonStatus = "Sendmail is running but not answering status queries.";
}
else
{
$daemonStatus = "Sendmail does not appear to be running.";
}
}
}
else
{
die "Unrecognized command $command\n";
}
if (defined $daemonStatus)
{
print "Daemon Status: $daemonStatus\n";
}
if (defined $status)
{
print "$status\n";
}
else
{
die "No response\n";
}