val reload = "echo \"I would reload exim now.\""
(*"/etc/init.d/exim4 reload"*)
+val handleDomains = "/home/adamc/fake/mail"
+
end
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
--- /dev/null
+{{Exim MTA configuration}}
+
+extern val handleMail : [Domain];
+{{The local server should handle mail for this domain.}}
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 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
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)
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)
val aliasesChanged = ref false
val aliasesDefaultChanged = ref false
+val hostsChanged = ref false
val () = Slave.registerPreHandler
(fn () => (aliasesChanged := false;
- aliasesDefaultChanged := false))
+ aliasesDefaultChanged := false;
+ hostsChanged := false))
val () = Slave.registerFileHandler (fn fs =>
let
aliasesChanged := true
else if #file spl = "aliases.default" then
aliasesDefaultChanged := true
+ else if #file spl = "mail" then
+ hostsChanged := true
else
()
end)
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
()))
+
+val () = Env.action_none "handleMail"
+ (fn () => TextIO.closeOut (Domain.domainFile "mail"))
+
end
(* 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
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
--- /dev/null
+domain "hcoop.net" with
+ handleMail
+end;
+
+domain "tpu.org" with
+ handleMail
+end;
+
+domain "schizomaniac.net" with
+
+end