val logFile = "/var/log/exim4/mainlog"
(* SMTP log *)
+val pushUserdb = "/usr/bin/rsync -r --delete /etc/courier/userdb /afs/hcoop.net/common/etc/domtool/email/userdb"
+val pullUserdb = "/usr/bin/rsync -r --delete /afs/hcoop.net/common/etc/domtool/email/userdb /etc/courier/userdb"
+
end
val postReload : string
val logFile : string
+
+ val pushUserdb : string
+ val pullUserdb : string
end
val defaultExpiry = 1209600
val defaultMinimum = 3600
-val nodeIps = [("deleuze", "69.90.123.67"), ("mire", "69.90.123.68"), ("outpost", "89.16.166.179")]
+val nodeIps = [("deleuze", "69.90.123.67"), ("mire", "69.90.123.68"), ("outpost", "89.16.166.179"), ("hopper", "69.90.123.74")]
val defaultNode = "deleuze"
val masterNode = "deleuze"
-val slaveNodes = ["mire", "outpost"]
+val slaveNodes = ["mire", "outpost", "hopper"]
val dnsNodes_all = ["deleuze", "mire", "outpost"]
val dnsNodes_admin = []
-val mailNodes_all = ["deleuze"]
+val mailNodes_all = ["deleuze", "hopper"]
val mailNodes_admin = ["mire", "outpost"]
val aclFile = "/afs/hcoop.net/common/etc/domtool/acl"
val reload = "/usr/bin/sudo /usr/local/sbin/domtool-publish exim"
-val aliasTo = ["deleuze"]
+val aliasTo = ["deleuze", "hopper"]
val mainLog = "/var/log/exim4/mainlog"
structure Mailman :> MAILMAN_CONFIG = struct
-val node = "deleuze"
+val node = "hopper"
val mapFile = "/var/domtool/mailman.map"
val handleDomains = "/var/domtool/mailman_domains.cfg"
val your_paths : unit -> DataStructures.StringSet.set
(* UNIX users, groups, and paths the user may act with *)
+ val get_context : unit -> OpenSSL.context
val set_context : OpenSSL.context -> unit
val hasPriv : string -> bool
val ssl_context = ref (NONE : OpenSSL.context option)
fun set_context ctx = ssl_context := SOME ctx
+fun get_context () = valOf (!ssl_context)
val nodes = map #1 Config.nodeIps
val nodeMap = foldl (fn ((node, ip), mp) => SM.insert (mp, node, ip))
val rm : {domain : string, user : string} -> string option
-
+ val doChanged : unit -> bool
end
(* HCoop Domtool (http://hcoop.sourceforge.net/)
- * Copyright (c) 2006, Adam Chlipala
+ * Copyright (c) 2006-2009, Adam Chlipala
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
structure Vmail :> VMAIL = struct
-fun rebuild () = Slave.shell [Config.Courier.postReload]
+open MsgTypes
+
+fun rebuild () =
+ let
+ fun doNode (site, ok) =
+ (print ("New vmail data for node " ^ site ^ "\n");
+ if site = Config.defaultNode then
+ Slave.shell [Config.Courier.postReload] andalso ok
+ else let
+ val bio = OpenSSL.connect true (Domain.get_context (),
+ Domain.nodeIp site
+ ^ ":"
+ ^ Int.toString Config.slavePort)
+ in
+ Msg.send (bio, MsgVmailChanged);
+ (case Msg.recv bio of
+ NONE => (print "Slave closed connection unexpectedly\n";
+ false)
+ | SOME m =>
+ case m of
+ MsgOk => (print ("Slave " ^ site ^ " finished\n");
+ ok)
+ | MsgError s => (print ("Slave " ^ site
+ ^ " returned error: " ^
+ s ^ "\n");
+ false)
+ | _ => (print ("Slave " ^ site
+ ^ " returned unexpected command\n");
+ false))
+ before OpenSSL.close bio
+ end)
+ in
+ Slave.shell [Config.Courier.pushUserdb]
+ andalso foldl doNode true Config.mailNodes_all
+ end
+
+fun doChanged () =
+ Slave.shell [Config.Courier.pullUserdb]
+ andalso Slave.shell [Config.Courier.postReload]
datatype listing =
Error of string
fun list domain =
let
val file = OS.Path.joinDirFile {dir = Config.Courier.userdbDir,
- file = domain}
+ file = domain}
in
if Posix.FileSys.access (file, []) then
let
Msg.send (bio, MsgOk))
| MsgRegenerate => (Domain.resetLocal ();
Msg.send (bio, MsgOk))
+ | MsgVmailChanged => (if Vmail.doChanged () then
+ Msg.send (bio, MsgOk)
+ else
+ Msg.send (bio, MsgError "userdb update failed"))
| _ => (print "Dispatcher sent unexpected command\n";
Msg.send (bio, MsgError "Unexpected command"))
in
| MsgDescription s => (OpenSSL.writeInt (bio, 40);
OpenSSL.writeString (bio, s))
| MsgReUsers => OpenSSL.writeInt (bio, 41)
+ | MsgVmailChanged => OpenSSL.writeInt (bio, 42)
fun checkIt v =
case v of
| 39 => Option.map MsgDescribe (OpenSSL.readString bio)
| 40 => Option.map MsgDescription (OpenSSL.readString bio)
| 41 => SOME MsgReUsers
+ | 42 => SOME MsgVmailChanged
| _ => NONE)
end
(* Reply to MsgDescribe *)
| MsgReUsers
(* Rerun all callbacks for cases where the set of users has changed *)
+ | MsgVmailChanged
+ (* Server tells slave that vmail user information has changed *)
end