diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1999-01-21 19:04:27 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1999-01-21 19:04:27 +0000 |
commit | f2af2a6b757299f91ae6577ecdf0f275d367de38 (patch) | |
tree | 87a3e18136d0358478e0be623f955dfe23770160 | |
parent | caef934943454a2ca8e07db76857561fc1728b05 (diff) |
this was missed in the 8.9.2 update
-rw-r--r-- | usr.sbin/sendmail/contrib/smcontrol.pl | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/usr.sbin/sendmail/contrib/smcontrol.pl b/usr.sbin/sendmail/contrib/smcontrol.pl new file mode 100644 index 00000000000..b5ef1f8af67 --- /dev/null +++ b/usr.sbin/sendmail/contrib/smcontrol.pl @@ -0,0 +1,361 @@ +#!/usr/local/bin/perl -w + +use FileHandle; +use Socket; + +$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; + + open(CF, "</etc/sendmail.cf") or return $cn; + 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); + + $cn = $qd . "/" . $cn; + } + 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; + + socket(SOCK, PF_UNIX, SOCK_STREAM, $proto) or return undef; + + for ($i = 0; $i < 4; $i++) + { + if (!connect(SOCK, sockaddr_un($controlsocket))) + { + if ($i == 3) + { + close(SOCK); + return undef; + } + sleep 1; + next; + } + last; + } + autoflush SOCK 1; + print SOCK "$command\n"; + @reply = <SOCK>; + 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 $port = getservbyname("smtp", "tcp") || 25; + my $proto = getprotobyname("tcp"); + my $iaddr = inet_aton("localhost"); + my $paddr = sockaddr_in($port, $iaddr); + + socket(SOCK, PF_INET, SOCK_STREAM, $proto) or return undef; + if (!connect(SOCK, $paddr)) + { + close(SOCK); + return undef; + } + autoflush SOCK 1; + 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 = ""; + + if ($raw =~ /^(\d+)\/(\d+)$/mg) + { + $cooked .= "Current number of children: $1"; + if ($2 > 0) + { + $cooked .= " (maximum $2)"; + } + $cooked .= "\n"; + } + while ($raw =~ /^(\d+) (.*)$/mg) + { + if (not $daemonStatus) + { + $daemonStatus = "(process $1) " . ucfirst($2) . "\n"; + } + 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; + + waitpid $pid, 0 or return "Could not get status of created process: $!\n"; + $exitstat = $? / 256; + if ($exitstat != 0) + { + return "sendmail daemon startup exited with exit value $exitstat"; + } + } + elsif (defined $pid) + { + exec($main::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"; + } + return &do_command($control, "SHUTDOWN"); +} + +########################################################################## +# +# &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."; + } + return &do_command($control, "RESTART"); +} + +########################################################################## +# +# &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."; + } + return &do_command($control, "HELP"); +} + +my $command = shift; +my $control = &get_controlname; +my $status = undef; +my $daemonStatus = undef; + +if (not defined $control) +{ + die "No control socket available.\n"; +} +if (not defined $command) +{ + die "Usage: $0 command\n"; +} +if ($command eq "status") +{ + $status = &do_command($control, "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 + ($daemonStatus, $status) = &munge_status($status); + } +} +elsif (lc($command) eq "shutdown") +{ + $status = &stop_daemon($control); +} +elsif (lc($command) eq "restart") +{ + $status = &restart_daemon($control); +} +elsif (lc($command) eq "start") +{ + $status = &start_daemon($control); +} +elsif (lc($command) eq "help") +{ + $status = &help($control); +} +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"; +} |