+
+structure SM = DataStructures.StringMap
+
+exception Userdb of string
+
+fun readUserdb domain =
+ let
+ val file = OS.Path.joinDirFile {dir = Config.Vmail.userDatabase,
+ file = domain}
+ in
+ if Posix.FileSys.access (file, []) then
+ let
+ val inf = TextIO.openIn file
+
+ fun parseField (field, fields) =
+ case String.fields (fn ch => ch = #"=") field of
+ [key, value] => SM.insert (fields, key, value)
+ | _ => raise Userdb ("Malformed fields in vmail userdb for domain " ^ domain)
+
+ fun loop users =
+ case TextIO.inputLine inf of
+ NONE => users
+ | SOME line =>
+ case String.tokens Char.isSpace line of
+ [addr, fields] => (case String.fields (fn ch => ch = #"@") addr of
+ [user, _] =>
+ loop (SM.insert (users, user, foldl parseField SM.empty (String.fields (fn ch => ch = #"|") fields)))
+ | _ => raise Userdb ("Malformed address in vmail userdb for " ^ domain ^ ": " ^ addr))
+ | _ => raise Userdb ("Malformed record in vmail userdb for domain " ^ domain)
+ in
+ loop SM.empty
+ before TextIO.closeIn inf
+ end
+ else
+ SM.empty
+ end
+