Slaves and Exim
authorAdam Chlipala <adamc@hcoop.net>
Sun, 30 Jul 2006 22:00:16 +0000 (22:00 +0000)
committerAdam Chlipala <adamc@hcoop.net>
Sun, 30 Jul 2006 22:00:16 +0000 (22:00 +0000)
13 files changed:
Makefile
configDefault/domtool.cfg
configDefault/domtool.cfs
configDefault/exim.cfg [new file with mode: 0644]
configDefault/exim.cfs [new file with mode: 0644]
configDefault/exim.csg [new file with mode: 0644]
src/domain.sml
src/domtool.cm
src/plugins/exim.sig [new file with mode: 0644]
src/plugins/exim.sml [new file with mode: 0644]
src/plugins/plugins.cm [deleted file]
src/slave.sig
src/slave.sml

index 4f173d4..7964314 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,8 +3,10 @@ all: configDefault/config.sig configDefault/configDefault.sml
 .PHONY: all
 
 configDefault/config.sig: src/config.sig.header \
-               configDefault/*.cfs src/config.sig.footer
-       cat src/config.sig.header \
+               configDefault/*.csg configDefault/*.cfs \
+               src/config.sig.footer
+       cat configDefault/*.csg \
+               src/config.sig.header \
                configDefault/*.cfs \
                src/config.sig.footer \
                >configDefault/config.sig
index aed3b0b..34d07ee 100644 (file)
@@ -2,6 +2,7 @@ val libRoot = "/home/adamc/cvs/domtool2/lib"
 val resultRoot = "/home/adamc/domtool"
 val tmpDir = "/tmp"
 
+val cat = "/bin/cat"
 val cp = "/bin/cp"
 val diff = "/usr/bin/diff"
 val rm = "/bin/rm"
index 90be237..d72df6f 100644 (file)
@@ -9,6 +9,7 @@ val tmpDir : string
 (* Filesystem location for creating temporary directories *)
 
 (* Paths to standard UNIX utilities *)
+val cat : string
 val cp : string
 val diff : string
 val rm : string
diff --git a/configDefault/exim.cfg b/configDefault/exim.cfg
new file mode 100644 (file)
index 0000000..78c7228
--- /dev/null
@@ -0,0 +1,9 @@
+structure Exim :> EXIM_CONFIG = struct
+
+val aliases = "/home/adamc/fake/aliases"
+val aliasesDefault = "/home/adamc/fake/aliases.default"
+
+val reload = "echo \"I would reload exim now.\""
+(*"/etc/init.d/exim4 reload"*)
+
+end
diff --git a/configDefault/exim.cfs b/configDefault/exim.cfs
new file mode 100644 (file)
index 0000000..c1cd13a
--- /dev/null
@@ -0,0 +1,2 @@
+structure Exim : EXIM_CONFIG
+
diff --git a/configDefault/exim.csg b/configDefault/exim.csg
new file mode 100644 (file)
index 0000000..c8a2232
--- /dev/null
@@ -0,0 +1,11 @@
+signature EXIM_CONFIG = sig
+
+val aliases : string
+val aliasesDefault : string
+(* Paths to e-mail alias files.
+ * The "default" version is for catch-alls. *)
+
+val reload : string
+(* Command-line to reload exim configuration *)
+
+end
index 394bf80..534e440 100644 (file)
@@ -103,18 +103,6 @@ datatype file_action' =
        | Delete' of string
        | Modify' of {src : string, dst : string}
 
-fun shell ss = OS.Process.isSuccess (OS.Process.system (String.concat ss))
-
-fun shellF (ss, msg) =
-    let
-       val s = String.concat ss
-    in
-       if OS.Process.isSuccess (OS.Process.system s) then
-           ()
-       else
-           ErrorMsg.error NONE (msg s)
-    end
-
 fun findDiffs dom =
     let
        val realPath = getPath dom Config.resultRoot
@@ -136,7 +124,7 @@ fun findDiffs dom =
                    if Posix.FileSys.ST.isDir (Posix.FileSys.stat real) then
                        loopReal acts
                    else if Posix.FileSys.access (tmp, []) then
-                       if shell [Config.diff, " ", real, " ",  tmp] then
+                       if Slave.shell [Config.diff, " ", real, " ",  tmp] then
                            loopReal acts
                        else
                            loopReal (Modify' {src = tmp, dst = real} :: acts)
@@ -146,7 +134,7 @@ fun findDiffs dom =
 
        val acts = loopReal []
 
-       val dir = Posix.FileSys.opendir realPath
+       val dir = Posix.FileSys.opendir tmpPath
 
        fun loopTmp acts =
            case Posix.FileSys.readdir dir of
@@ -190,7 +178,7 @@ val _ = Env.container_one "domain"
                                  val diffs = findDiffs dom
 
                                  val diffs = map (fn Add' {src, dst} =>
-                                                     (shellF ([Config.cp, " ", src, " ", dst],
+                                                     (Slave.shellF ([Config.cp, " ", src, " ", dst],
                                                              fn cl => "Copy failed: " ^ cl);
                                                       {action = Slave.Add,
                                                        domain = dom,
@@ -203,7 +191,7 @@ val _ = Env.container_one "domain"
                                                        domain = dom,
                                                        file = dst})
                                                    | Modify' {src, dst} =>
-                                                     (shellF ([Config.cp, " ", src, " ", dst],
+                                                     (Slave.shellF ([Config.cp, " ", src, " ", dst],
                                                           fn cl => "Copy failed: " ^ cl);
                                                       {action = Slave.Modify,
                                                        domain = dom,
@@ -213,7 +201,7 @@ val _ = Env.container_one "domain"
                                      ()
                                  else
                                      Slave.handleChanges diffs;
-                                 ignore (shellF ([Config.rm, " -rf ", Config.tmpDir, "/*"],
+                                 ignore (Slave.shellF ([Config.rm, " -rf ", Config.tmpDir, "/*"],
                                                  fn cl => "Temp file cleanup failed: " ^ cl))
                              end)
 
index bdc790b..29b39c0 100644 (file)
@@ -47,7 +47,11 @@ slave.sml
 domain.sig
 domain.sml
 
-plugins/plugins.cm
+plugins/alias.sig
+plugins/alias.sml
+
+plugins/exim.sig
+plugins/exim.sml
 
 order.sig
 order.sml
diff --git a/src/plugins/exim.sig b/src/plugins/exim.sig
new file mode 100644 (file)
index 0000000..fde572b
--- /dev/null
@@ -0,0 +1,23 @@
+(* HCoop Domtool (http://hcoop.sourceforge.net/)
+ * Copyright (c) 2006, Adam Chlipala
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+(* Exim MTA handling *)
+
+signature EXIM = sig
+
+end
diff --git a/src/plugins/exim.sml b/src/plugins/exim.sml
new file mode 100644 (file)
index 0000000..112ab5f
--- /dev/null
@@ -0,0 +1,58 @@
+(* HCoop Domtool (http://hcoop.sourceforge.net/)
+ * Copyright (c) 2006, Adam Chlipala
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+(* Exim MTA handling *)
+
+structure Exim :> EXIM = struct
+
+val aliasesChanged = ref false
+val aliasesDefaultChanged = ref false
+
+val () = Slave.registerPreHandler
+            (fn () => (aliasesChanged := false;
+                       aliasesDefaultChanged := false))
+
+val () = Slave.registerFileHandler (fn fs =>
+                                      let
+                                          val spl = OS.Path.splitDirFile (#file fs)
+                                      in
+                                          if #file spl = "aliases" then
+                                              aliasesChanged := true
+                                          else if #file spl = "aliases.default" then
+                                              aliasesDefaultChanged := true
+                                          else
+                                              ()
+                                      end)
+
+val () = Slave.registerPostHandler
+        (fn () =>
+            (if !aliasesChanged then
+                 Slave.concatTo (fn s => s = "aliases") Config.Exim.aliases
+             else
+                 ();
+             if !aliasesDefaultChanged then
+                 Slave.concatTo (fn s => s = "aliases.default") Config.Exim.aliasesDefault
+             else
+                 ();
+             if !aliasesChanged orelse !aliasesDefaultChanged then
+                 Slave.shellF ([Config.Exim.reload],
+                               fn cl => "Error reloading exim with " ^ cl)
+             else
+                 ()))
+
+end
diff --git a/src/plugins/plugins.cm b/src/plugins/plugins.cm
deleted file mode 100644 (file)
index 2f3be08..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-Library
-
-signature ALIAS
-structure Alias
-
-is
-
-alias.sig
-alias.sml
index 24082d4..76a4b05 100644 (file)
@@ -39,4 +39,12 @@ signature SLAVE = sig
     (* Register code to run before or after making all changes. *)
 
     val handleChanges : file_status list -> unit
+
+    val shell : string list -> bool
+    val shellF : string list * (string -> string) -> unit
+
+    val concatTo : (string -> bool) -> string -> unit
+    (* Search through the result configuration hierarchy for all files matching
+     * the predicate, concatenating their contents in arbitrary order to the
+     * given file. *)
 end
index b08d41d..1521b73 100644 (file)
@@ -58,4 +58,46 @@ fun handleChanges fs = (!preHandler ();
                        app (!fileHandler) fs;
                        !postHandler ())
 
+fun shell ss = OS.Process.isSuccess (OS.Process.system (String.concat ss))
+
+fun shellF (ss, msg) =
+    let
+       val s = String.concat ss
+    in
+       if OS.Process.isSuccess (OS.Process.system s) then
+           ()
+       else
+           ErrorMsg.error NONE (msg s)
+    end
+
+fun concatTo p fname =
+    let
+       fun visitDir dname =
+           let
+               val dir = Posix.FileSys.opendir dname
+
+               fun loop () =
+                   case Posix.FileSys.readdir dir of
+                       NONE => Posix.FileSys.closedir dir
+                     | SOME fname' =>
+                       let
+                           val path = OS.Path.joinDirFile {dir = dname, file = fname'}
+                       in
+                           if Posix.FileSys.ST.isDir (Posix.FileSys.stat path) then
+                               visitDir path
+                           else if p fname' then
+                               shellF ([Config.cat, " ", path, " >>", fname],
+                                              fn cl => "Error concatenating: " ^ cl)
+                           else
+                               ();
+                           loop ()
+                       end
+           in
+               TextIO.closeOut (TextIO.openOut fname);
+               loop ()
+           end
+    in
+       visitDir Config.resultRoot
+    end
+
 end