Jan Kaluza b62706b
diff --git a/bin/mailmanctl b/bin/mailmanctl
ff68684
index fa14a2c..e291df1 100644
Jan Kaluza b62706b
--- a/bin/mailmanctl
Jan Kaluza b62706b
+++ b/bin/mailmanctl
Jan Kaluza b62706b
@@ -36,7 +36,7 @@ in the file data/master-qrunner.pid but you normally don't need to use this
cvsdist 561a783
 pid directly.  The `start', `stop', `restart', and `reopen' commands handle
cvsdist 561a783
 everything for you.
cvsdist 561a783
 
cvsdist 561a783
-Usage: %(PROGRAM)s [options] [ start | stop | restart | reopen ]
cvsdist 561a783
+Usage: %(PROGRAM)s [options] [ start | stop | restart | reopen | status ]
cvsdist 561a783
 
cvsdist 561a783
 Options:
cvsdist 561a783
 
Jan Kaluza b62706b
@@ -90,6 +90,9 @@ Commands:
cvsdist 561a783
 
cvsdist 561a783
     reopen  - This will close all log files, causing them to be re-opened the
cvsdist 561a783
               next time a message is written to them
cvsdist 561a783
+
cvsdist 561a783
+    status  - This returns a string indicating the status of the master
cvsdist 561a783
+              qrunner
cvsdist 561a783
 """
cvsdist 561a783
 
cvsdist 561a783
 import sys
Jan Kaluza b62706b
@@ -190,6 +193,52 @@ def qrunner_state():
13f311e
         return 0
cvsdist 561a783
     return 1
cvsdist 561a783
 
cvsdist 561a783
+def mailman_status():
cvsdist 561a783
+    # return status, pid
13f311e
+    #
13f311e
+    # These status values match the /etc/init.d status values
13f311e
+    # (at least on Red Hat), try to return equivalent status if possible
13f311e
+    # status is 0 if running,
13f311e
+    # status is 1 if dead but pid file exists
13f311e
+    # status is 2 if dead but subsys locked
13f311e
+    # status is 3 if stopped (pid returned will be 0)
13f311e
+    #
cvsdist 561a783
+    #
cvsdist 561a783
+    # We want any user to be able to query the status and this presents
cvsdist 561a783
+    # few interesting permission problems and is why we don't use
cvsdist 561a783
+    # qrunner_state(). The pidfile is only readable by the mailman owner
cvsdist 561a783
+    # and group, however the lockfile is world readable. So we will
cvsdist 561a783
+    # get the master pid from the lockfile. We try to determine if the
cvsdist 561a783
+    # master process exists by sending it a signal. If we don't have
cvsdist 561a783
+    # permission to signal the process, but the process exists we'll
cvsdist 561a783
+    # get a EPERM error, if the process does not exist then we'll get
cvsdist 561a783
+    # a ESRCH error.
cvsdist 561a783
+
cvsdist 561a783
+    try:
cvsdist 561a783
+        hostname, pid, tempfile = get_lock_data()
cvsdist 561a783
+    except IOError, e:
cvsdist 561a783
+        if e.errno == errno.ENOENT:
cvsdist 561a783
+            # Lock file didn't exist, can't be running
13f311e
+            return 3, 0
cvsdist 561a783
+        else:
cvsdist 561a783
+            raise
cvsdist 561a783
+    if hostname <> socket.gethostname():
cvsdist 561a783
+        # not running on this host
13f311e
+        return 3, 0
cvsdist 561a783
+    # Find out if the process exists by calling kill with a signal 0.
cvsdist 561a783
+    try:
cvsdist 561a783
+        os.kill(pid, 0)
cvsdist 561a783
+    except OSError, e:
cvsdist 561a783
+        if e.errno == errno.ESRCH:
cvsdist 561a783
+            # process does not exist
13f311e
+            return 1, pid
cvsdist 561a783
+        elif e.errno == errno.EPERM:
cvsdist 561a783
+            # we don't have permission signal the process but it exists
13f311e
+            return 0, pid
cvsdist 561a783
+        else:
cvsdist 561a783
+            raise
13f311e
+    return 0, pid
cvsdist 561a783
+
13f311e
 
cvsdist 561a783
 def acquire_lock_1(force):
cvsdist 561a783
     # Be sure we can acquire the master qrunner lock.  If not, it means some
ff68684
@@ -338,13 +387,15 @@ def main():
cvsdist 561a783
         command = COMMASPACE.join(args)
33a23d4
         usage(1, C_('Bad command: %(command)s'))
cvsdist 561a783
 
cvsdist 561a783
+    command = args[0].lower()
cvsdist 561a783
+
cvsdist 561a783
     if checkprivs:
cvsdist 561a783
         check_privs()
cvsdist 561a783
     else:
33a23d4
-        print C_('Warning!  You may encounter permission problems.')
cvsdist 561a783
+        if command != 'status':
33a23d4
+	    print C_('Warning!  You may encounter permission problems.')
cvsdist 561a783
 
cvsdist 561a783
     # Handle the commands
cvsdist 561a783
-    command = args[0].lower()
cvsdist 561a783
     if command == 'stop':
cvsdist 561a783
         # Sent the master qrunner process a SIGINT, which is equivalent to
cvsdist 561a783
         # giving cron/qrunner a ctrl-c or KeyboardInterrupt.  This will
ff68684
@@ -363,6 +414,14 @@ def main():
cvsdist 561a783
         if not quiet:
33a23d4
             print C_('Re-opening all log files')
cvsdist 561a783
         kill_watcher(signal.SIGHUP)
cvsdist 561a783
+    elif command == 'status':
cvsdist 561a783
+        status, pid = mailman_status()
13f311e
+        if not quiet:
13f311e
+            if status == 0:
33a23d4
+                print C_("mailman (pid %(pid)d) is running...")
13f311e
+            else:
33a23d4
+                print C_("mailman is stopped")
13f311e
+        sys.exit(status)
cvsdist 561a783
     elif command == 'start':
cvsdist 561a783
         # First, complain loudly if there's no site list.
cvsdist 561a783
         check_for_site_list()