summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1999-01-21 19:04:27 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1999-01-21 19:04:27 +0000
commitf2af2a6b757299f91ae6577ecdf0f275d367de38 (patch)
tree87a3e18136d0358478e0be623f955dfe23770160
parentcaef934943454a2ca8e07db76857561fc1728b05 (diff)
this was missed in the 8.9.2 update
-rw-r--r--usr.sbin/sendmail/contrib/smcontrol.pl361
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";
+}