More Exim stuff
authorAdam Chlipala <adamc@hcoop.net>
Sun, 30 Jul 2006 22:29:22 +0000 (22:29 +0000)
committerAdam Chlipala <adamc@hcoop.net>
Sun, 30 Jul 2006 22:29:22 +0000 (22:29 +0000)
configDefault/exim.cfg
configDefault/exim.csg
lib/exim.dtl [new file with mode: 0644]
src/env.sig
src/env.sml
src/plugins/exim.sml
src/slave.sig
src/slave.sml
tests/testExim.dtl [new file with mode: 0644]

index 78c7228..2a537be 100644 (file)
@@ -6,4 +6,6 @@ val aliasesDefault = "/home/adamc/fake/aliases.default"
 val reload = "echo \"I would reload exim now.\""
 (*"/etc/init.d/exim4 reload"*)
 
 val reload = "echo \"I would reload exim now.\""
 (*"/etc/init.d/exim4 reload"*)
 
+val handleDomains = "/home/adamc/fake/mail"
+
 end
 end
index c8a2232..20c0e44 100644 (file)
@@ -8,4 +8,7 @@ val aliasesDefault : string
 val reload : string
 (* Command-line to reload exim configuration *)
 
 val reload : string
 (* Command-line to reload exim configuration *)
 
+val handleDomains : string
+(* File to which to write a comma-separate list of domains to handle mail for *)
+
 end
 end
diff --git a/lib/exim.dtl b/lib/exim.dtl
new file mode 100644 (file)
index 0000000..1152aef
--- /dev/null
@@ -0,0 +1,4 @@
+{{Exim MTA configuration}}
+
+extern val handleMail : [Domain];
+{{The local server should handle mail for this domain.}}
index 5108bea..9c26f00 100644 (file)
@@ -41,11 +41,13 @@ signature ENV = sig
     val string : string arg
     val list : 'a arg -> 'a list arg
 
     val string : string arg
     val list : 'a arg -> 'a list arg
 
+    val none : string -> (unit -> unit) -> action
     val one : string -> string * 'a arg -> ('a -> unit) -> action
     val two : string -> string * 'a arg * string * 'b arg -> ('a * 'b -> unit) -> action
 
     val type_one : string -> 'a arg -> ('a -> bool) -> unit
 
     val one : string -> string * 'a arg -> ('a -> unit) -> action
     val two : string -> string * 'a arg * string * 'b arg -> ('a * 'b -> unit) -> action
 
     val type_one : string -> 'a arg -> ('a -> bool) -> unit
 
+    val action_none : string -> (unit -> unit) -> unit
     val action_one : string -> string * 'a arg -> ('a -> unit) -> unit
     val action_two : string -> string * 'a arg * string * 'b arg -> ('a * 'b -> unit) -> unit
 
     val action_one : string -> string * 'a arg -> ('a -> unit) -> unit
     val action_two : string -> string * 'a arg * string * 'b arg -> ('a * 'b -> unit) -> unit
 
index 48ec715..85c29c9 100644 (file)
@@ -70,6 +70,10 @@ fun mapFail f [] = SOME []
 fun list f (EList ls, _) = mapFail f ls
   | list _ _ = NONE
 
 fun list f (EList ls, _) = mapFail f ls
   | list _ _ = NONE
 
+fun none func f (_, []) = (f ();
+                          SM.empty)
+  | none func _ (_, es) = badArgs (func, es)
+
 fun one func (name, arg) f (_, [e]) =
     (case arg e of
         NONE => badArg (func, name, e)
 fun one func (name, arg) f (_, [e]) =
     (case arg e of
         NONE => badArg (func, name, e)
@@ -91,6 +95,7 @@ fun type_one func arg f =
                               NONE => false
                             | SOME v => f v)
 
                               NONE => false
                             | SOME v => f v)
 
+fun action_none name f = registerAction (name, none name f)
 fun action_one name args f = registerAction (name, one name args f)
 fun action_two name args f = registerAction (name, two name args f)
 
 fun action_one name args f = registerAction (name, one name args f)
 fun action_two name args f = registerAction (name, two name args f)
 
index 112ab5f..ee4cf80 100644 (file)
@@ -22,10 +22,12 @@ structure Exim :> EXIM = struct
 
 val aliasesChanged = ref false
 val aliasesDefaultChanged = ref false
 
 val aliasesChanged = ref false
 val aliasesDefaultChanged = ref false
+val hostsChanged = ref false
 
 val () = Slave.registerPreHandler
             (fn () => (aliasesChanged := false;
 
 val () = Slave.registerPreHandler
             (fn () => (aliasesChanged := false;
-                       aliasesDefaultChanged := false))
+                       aliasesDefaultChanged := false;
+                       hostsChanged := false))
 
 val () = Slave.registerFileHandler (fn fs =>
                                       let
 
 val () = Slave.registerFileHandler (fn fs =>
                                       let
@@ -35,6 +37,8 @@ val () = Slave.registerFileHandler (fn fs =>
                                               aliasesChanged := true
                                           else if #file spl = "aliases.default" then
                                               aliasesDefaultChanged := true
                                               aliasesChanged := true
                                           else if #file spl = "aliases.default" then
                                               aliasesDefaultChanged := true
+                                          else if #file spl = "mail" then
+                                              hostsChanged := true
                                           else
                                               ()
                                       end)
                                           else
                                               ()
                                       end)
@@ -49,10 +53,19 @@ val () = Slave.registerPostHandler
                  Slave.concatTo (fn s => s = "aliases.default") Config.Exim.aliasesDefault
              else
                  ();
                  Slave.concatTo (fn s => s = "aliases.default") Config.Exim.aliasesDefault
              else
                  ();
-             if !aliasesChanged orelse !aliasesDefaultChanged then
+             if !hostsChanged then
+                 Slave.enumerateTo (fn s => s = "mail") ":" Config.Exim.handleDomains
+             else
+                 ();
+             if !aliasesChanged orelse !aliasesDefaultChanged
+                orelse !hostsChanged then
                  Slave.shellF ([Config.Exim.reload],
                                fn cl => "Error reloading exim with " ^ cl)
              else
                  ()))
 
                  Slave.shellF ([Config.Exim.reload],
                                fn cl => "Error reloading exim with " ^ cl)
              else
                  ()))
 
+
+val () = Env.action_none "handleMail"
+        (fn () => TextIO.closeOut (Domain.domainFile "mail"))
+
 end
 end
index 76a4b05..52c9381 100644 (file)
@@ -47,4 +47,9 @@ signature SLAVE = sig
     (* Search through the result configuration hierarchy for all files matching
      * the predicate, concatenating their contents in arbitrary order to the
      * given file. *)
     (* Search through the result configuration hierarchy for all files matching
      * the predicate, concatenating their contents in arbitrary order to the
      * given file. *)
+
+    val enumerateTo : (string -> bool) -> string -> string -> unit
+    (* Search through the result configuration hierarchy for all files matching
+     * the predicate, writing a list of their domains to the file named by the
+     * third argument, delimiting the entries with the second argument. *)
 end
 end
index 1521b73..d43a8fa 100644 (file)
@@ -100,4 +100,48 @@ fun concatTo p fname =
        visitDir Config.resultRoot
     end
 
        visitDir Config.resultRoot
     end
 
+fun enumerateTo p sep fname =
+    let
+       val outf = TextIO.openOut fname
+
+       val first = ref true
+       val baseLen = length (String.fields (fn ch => ch = #"/") Config.resultRoot)
+
+       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
+                               let
+                                   val toks = String.fields (fn ch => ch = #"/") dname
+                                   val toks = List.drop (toks, baseLen)
+                                   val dom = String.concatWith "." (rev toks)
+                               in
+                                   if !first then
+                                       first := false
+                                   else
+                                       TextIO.output (outf, sep);
+                                   TextIO.output (outf, dom)
+                               end
+                           else
+                               ();
+                           loop ()
+                       end
+           in
+               loop ()
+           end
+    in
+       visitDir Config.resultRoot;
+       TextIO.closeOut outf
+    end
+
 end
 end
diff --git a/tests/testExim.dtl b/tests/testExim.dtl
new file mode 100644 (file)
index 0000000..582cea3
--- /dev/null
@@ -0,0 +1,11 @@
+domain "hcoop.net" with
+       handleMail
+end;
+
+domain "tpu.org" with
+       handleMail
+end;
+
+domain "schizomaniac.net" with
+
+end