3 # $Id: smcontrol.pl,v 8.8 2008-07-21 21:31:43 ca Exp $
10 my $sendmailDaemon = "/usr/sbin/sendmail -q30m -bd";
12 ##########################################################################
14 # &get_controlname -- read ControlSocketName option from sendmail.cf
20 # control socket filename, undef if not found
28 open(CF, "</etc/mail/sendmail.cf") or return $cn;
32 if (/^O ControlSocketName\s*=\s*([^#]+)$/o)
36 if (/^O QueueDirectory\s*=\s*([^#]+)$/o)
52 return undef if (not defined $qd);
54 $cn = $qd . "/" . $cn;
59 ##########################################################################
61 # &do_command -- send command to sendmail daemon view control socket
64 # controlsocket -- filename for socket
65 # command -- command to send
68 # reply from sendmail daemon
73 my $controlsocket = shift;
75 my $proto = getprotobyname('ip');
79 socket(SOCK, PF_UNIX, SOCK_STREAM, $proto) or return undef;
81 for ($i = 0; $i < 4; $i++)
83 if (!connect(SOCK, sockaddr_un($controlsocket)))
96 print SOCK "$command\n";
99 return join '', @reply;
102 ##########################################################################
104 # &sendmail_running -- check if sendmail is running via SMTP
110 # 1 if running, undef otherwise
115 my $port = getservbyname("smtp", "tcp") || 25;
116 my $proto = getprotobyname("tcp");
117 my $iaddr = inet_aton("localhost");
118 my $paddr = sockaddr_in($port, $iaddr);
120 socket(SOCK, PF_INET, SOCK_STREAM, $proto) or return undef;
121 if (!connect(SOCK, $paddr))
129 if (/^(\d{3})([ -])/)
153 ##########################################################################
155 # &munge_status -- turn machine readable status into human readable text
158 # raw -- raw results from sendmail daemon STATUS query
161 # human readable text
168 my $daemonStatus = "";
170 if ($raw =~ /^(\d+)\/(\d+)\/(\d+)\/(\d+)/mg)
172 $cooked .= "Current number of children: $1";
175 $cooked .= " (maximum $2)";
178 $cooked .= "QueueDir free disk space (in blocks): $3\n";
179 $cooked .= "Load average: $4\n";
181 while ($raw =~ /^(\d+) (.*)$/mg)
183 if (not $daemonStatus)
185 $daemonStatus = "(process $1) " . ucfirst($2) . "\n";
189 $cooked .= "Child Process $1 Status: $2\n";
192 return ($daemonStatus, $cooked);
195 ##########################################################################
197 # &start_daemon -- fork off a sendmail daemon
200 # control -- control socket name
203 # Error message or "OK" if successful
215 waitpid $pid, 0 or return "Could not get status of created process: $!\n";
216 $exitstat = $? / 256;
219 return "sendmail daemon startup exited with exit value $exitstat";
224 exec($sendmailDaemon);
225 die "Unable to start sendmail daemon: $!.\n";
229 return "Could not create new process: $!\n";
234 ##########################################################################
236 # &stop_daemon -- stop the sendmail daemon using control socket
239 # control -- control socket name
242 # Error message or status message
250 if (not defined $control)
252 return "The control socket is not configured so the daemon can not be stopped.\n";
254 return &do_command($control, "SHUTDOWN");
257 ##########################################################################
259 # &restart_daemon -- restart the sendmail daemon using control socket
262 # control -- control socket name
265 # Error message or status message
273 if (not defined $control)
275 return "The control socket is not configured so the daemon can not be restarted.";
277 return &do_command($control, "RESTART");
280 ##########################################################################
282 # &memdump -- get memdump from the daemon using the control socket
285 # control -- control socket name
288 # Error message or status message
296 if (not defined $control)
298 return "The control socket is not configured so the daemon can not be queried for memdump.";
300 return &do_command($control, "MEMDUMP");
303 ##########################################################################
305 # &help -- get help from the daemon using the control socket
308 # control -- control socket name
311 # Error message or status message
319 if (not defined $control)
321 return "The control socket is not configured so the daemon can not be queried for help.";
323 return &do_command($control, "HELP");
327 my $daemonStatus = undef;
330 getopts('f:', $opts) || die "Usage: $0 [-f /path/to/control/socket] command\n";
332 my $control = $opts->{f} || &get_controlname;
335 if (not defined $control)
337 die "No control socket available.\n";
339 if (not defined $command)
341 die "Usage: $0 [-f /path/to/control/socket] command\n";
343 if ($command eq "status")
345 $status = &do_command($control, "STATUS");
346 if (not defined $status)
348 # Not responding on control channel, query via SMTP
349 if (&sendmail_running)
351 $daemonStatus = "Sendmail is running but not answering status queries.";
355 $daemonStatus = "Sendmail does not appear to be running.";
360 # Munge control channel output
361 ($daemonStatus, $status) = &munge_status($status);
364 elsif (lc($command) eq "shutdown")
366 $status = &stop_daemon($control);
368 elsif (lc($command) eq "restart")
370 $status = &restart_daemon($control);
372 elsif (lc($command) eq "start")
374 $status = &start_daemon($control);
376 elsif (lc($command) eq "memdump")
378 $status = &memdump($control);
380 elsif (lc($command) eq "help")
382 $status = &help($control);
384 elsif (lc($command) eq "mstat")
386 $status = &do_command($control, "mstat");
387 if (not defined $status)
389 # Not responding on control channel, query via SMTP
390 if (&sendmail_running)
392 $daemonStatus = "Sendmail is running but not answering status queries.";
396 $daemonStatus = "Sendmail does not appear to be running.";
402 die "Unrecognized command $command\n";
404 if (defined $daemonStatus)
406 print "Daemon Status: $daemonStatus\n";