python/daemon.py
changeset 0 6f7a81934006
child 2 b3afb9f1e801
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/daemon.py	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,93 @@
+# Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import config
+
+ok = 0
+bad = 1
+err = 2
+econn = 3
+
+class Bad(Exception):   pass
+class Error(Exception): pass
+class Econn(Exception): pass
+
+def encode_int(i):
+    return chr((i/256)%256) + chr(i%256)
+
+def encode_str(str):
+    return encode_int(len(str)) + str
+
+class Command:
+    def __init__(self, name, args):
+        self.name = name
+        self.args = args
+    
+    def encode(self):
+        argcount = len(self.args)
+        cmd = chr(argcount) + encode_str(self.name)
+        for i in range(argcount):
+            cmd = cmd + encode_str(self.args[i])
+        cmd = chr(2) + encode_int(len(cmd)) + cmd
+        return cmd
+
+class Daemon:
+    def __init__(self):
+        self.socket_file = config.read('socket-file', '/tmp/.vmailmgrd')
+        self.socket = None
+
+    def connect(self):
+        import socket
+        self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        self.socket.connect(self.socket_file)
+
+    def read_response_noraise(self):
+        try:
+            reply = self.socket.recv(3)
+            code = ord(reply[0])
+            msglen = ord(reply[1])*256 + ord(reply[2])
+            message = self.socket.recv(msglen)
+        except:
+            return (econn, 'Server aborted the connection')
+        return (code, message)
+        
+    def read_response(self):
+        (code, message) = self.read_response_noraise()
+        if code == err:
+            raise Error, message
+        if code == bad:
+            raise Bad, message
+        if code == econn:
+            raise Econn, message
+        return message
+        
+    def execute(self, command):
+        try:
+            self.connect()
+        except:
+            raise Econn, "Unable to connect to the server"
+        data = command.encode()
+        try:
+            self.socket.send(data)
+        except:
+            raise Econn, "Server aborted the connection"
+        # Don't close the socket here -- it will be closed
+        # as soon as it gets garbage collected, and remains
+        # usable for other commands like listdomain.
+        return self.read_response()
+
+def execute(command, args):
+    return Daemon().execute(Command(command, args))