val (_, files) = Order.order (SOME b) files
in
if !ErrorMsg.anyErrors then
- false
+ raise ErrorMsg.Error
else
(foldl (fn (fname, G) => check' G fname) b files;
- !ErrorMsg.anyErrors)
+ if !ErrorMsg.anyErrors then
+ raise ErrorMsg.Error
+ else
+ ())
end
fun reduce fname =
Eval.exec (Defaults.eInit ()) body'
| NONE => raise ErrorMsg.Error
+fun eval' fname =
+ case reduce fname of
+ (SOME body') =>
+ if !ErrorMsg.anyErrors then
+ raise ErrorMsg.Error
+ else
+ ignore (Eval.exec' (Defaults.eInit ()) body')
+ | NONE => raise ErrorMsg.Error
+
val dispatcher =
Config.dispatcher ^ ":" ^ Int.toString Config.dispatcherPort
fun requestDir dname =
let
- val (user, bio) = requestBio (fn () => ignore (checkDir dname))
+ val _ = ErrorMsg.reset ()
+
+ val (user, bio) = requestBio (fn () => checkDir dname)
val b = basis ()
before TextIO.closeIn inf
end) files
in
- Msg.send (bio, MsgMultiConfig codes);
- case Msg.recv bio of
- NONE => print "Server closed connection unexpectedly.\n"
- | SOME m =>
- case m of
- MsgOk => print "Configuration succeeded.\n"
- | MsgError s => print ("Configuration failed: " ^ s ^ "\n")
- | _ => print "Unexpected server reply.\n";
- OpenSSL.close bio
+ if !ErrorMsg.anyErrors then
+ ()
+ else
+ (Msg.send (bio, MsgMultiConfig codes);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Configuration succeeded.\n"
+ | MsgError s => print ("Configuration failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio)
end
handle ErrorMsg.Error => ()
before OpenSSL.close bio
end
+fun requestRegen () =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgRegenerate);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Regeneration succeeded.\n"
+ | MsgError s => print ("Regeneration failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestRmdom dom =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgRmdom dom);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Removal succeeded.\n"
+ | MsgError s => print ("Removal failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestRmuser user =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgRmuser user);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Removal succeeded.\n"
+ | MsgError s => print ("Removal failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun requestDbUser dbtype =
+ let
+ val (_, bio) = requestBio (fn () => ())
+ in
+ Msg.send (bio, MsgCreateDbUser dbtype);
+ case Msg.recv bio of
+ NONE => print "Server closed connection unexpectedly.\n"
+ | SOME m =>
+ case m of
+ MsgOk => print "Your user has been created.\n"
+ | MsgError s => print ("Creation failed: " ^ s ^ "\n")
+ | _ => print "Unexpected server reply.\n";
+ OpenSSL.close bio
+ end
+
+fun regenerate context =
+ let
+ val b = basis ()
+ val () = Tycheck.disallowExterns ()
+
+ val () = Domain.resetGlobal ()
+
+ fun contactNode (node, ip) =
+ if node = Config.defaultNode then
+ Domain.resetLocal ()
+ else let
+ val bio = OpenSSL.connect (context,
+ ip
+ ^ ":"
+ ^ Int.toString Config.slavePort)
+ in
+ Msg.send (bio, MsgRegenerate);
+ case Msg.recv bio of
+ NONE => print "Slave closed connection unexpectedly\n"
+ | SOME m =>
+ case m of
+ MsgOk => print ("Slave " ^ node ^ " pre-regeneration finished\n")
+ | MsgError s => print ("Slave " ^ node
+ ^ " returned error: " ^
+ s ^ "\n")
+ | _ => print ("Slave " ^ node
+ ^ " returned unexpected command\n");
+ OpenSSL.close bio
+ end
+
+ fun doUser user =
+ let
+ val _ = Domain.setUser user
+ val _ = ErrorMsg.reset ()
+
+ val dname = Config.domtoolDir user
+
+ val dir = Posix.FileSys.opendir dname
+
+ fun loop files =
+ case Posix.FileSys.readdir dir of
+ NONE => (Posix.FileSys.closedir dir;
+ files)
+ | SOME fname =>
+ if notTmp fname then
+ loop (OS.Path.joinDirFile {dir = dname,
+ file = fname}
+ :: files)
+ else
+ loop files
+
+ val files = loop []
+ val (_, files) = Order.order (SOME b) files
+ in
+ if !ErrorMsg.anyErrors then
+ print ("User " ^ user ^ "'s configuration has errors!\n")
+ else
+ app eval' files
+ end
+ handle IO.Io _ => ()
+ | OS.SysErr (s, _) => print ("System error processing user " ^ user ^ ": " ^ s ^ "\n")
+ in
+ app contactNode Config.nodeIps;
+ Env.pre ();
+ app doUser (Acl.users ());
+ Env.post ()
+ end
+
+fun rmuser user =
+ let
+ val doms = Acl.class {user = user, class = "domain"}
+ val doms = List.filter (fn dom =>
+ case Acl.whoHas {class = "domain", value = dom} of
+ [_] => true
+ | _ => false) (StringSet.listItems doms)
+ in
+ Acl.rmuser user;
+ Domain.rmdom doms
+ end
+
fun service () =
let
val () = Acl.read Config.aclFile
in
TextIO.output (outf, code);
TextIO.closeOut outf;
- eval outname
+ eval' outname
end
in
- (app doOne codes;
+ (Env.pre ();
+ app doOne codes;
+ Env.post ();
Msg.send (bio, MsgOk))
handle ErrorMsg.Error =>
(print "Compilation error\n";
handle OpenSSL.OpenSSL _ => ();
loop ())
+ | MsgRmdom doms =>
+ if Acl.query {user = user, class = "priv", value = "all"}
+ orelse List.all (fn dom => Acl.query {user = user, class = "domain", value = dom}) doms then
+ ((Domain.rmdom doms;
+ app (fn dom =>
+ Acl.revokeFromAll {class = "domain", value = dom}) doms;
+ Acl.write Config.aclFile;
+ Msg.send (bio, MsgOk);
+ print ("Removed domains" ^ foldl (fn (d, s) => s ^ " " ^ d) "" doms ^ ".\n"))
+ handle OpenSSL.OpenSSL s =>
+ (print "OpenSSL error\n";
+ Msg.send (bio,
+ MsgError
+ ("Error during revocation: "
+ ^ s)));
+ (ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+ else
+ ((Msg.send (bio, MsgError "Not authorized to remove that domain");
+ print "Unauthorized user asked to remove a domain!\n";
+ ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+
+ | MsgRegenerate =>
+ if Acl.query {user = user, class = "priv", value = "regen"}
+ orelse Acl.query {user = user, class = "priv", value = "all"} then
+ ((regenerate context;
+ Msg.send (bio, MsgOk);
+ print "Regenerated all configuration.\n")
+ handle OpenSSL.OpenSSL s =>
+ (print "OpenSSL error\n";
+ Msg.send (bio,
+ MsgError
+ ("Error during regeneration: "
+ ^ s)));
+ (ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+ else
+ ((Msg.send (bio, MsgError "Not authorized to regeneration");
+ print "Unauthorized user asked to regenerate!\n";
+ ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+
+ | MsgRmuser user' =>
+ if Acl.query {user = user, class = "priv", value = "all"} then
+ ((rmuser user';
+ Acl.write Config.aclFile;
+ Msg.send (bio, MsgOk);
+ print ("Removed user " ^ user' ^ ".\n"))
+ handle OpenSSL.OpenSSL s =>
+ (print "OpenSSL error\n";
+ Msg.send (bio,
+ MsgError
+ ("Error during revocation: "
+ ^ s)));
+ (ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+ else
+ ((Msg.send (bio, MsgError "Not authorized to remove users");
+ print "Unauthorized user asked to remove a user!\n";
+ ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+
+ | MsgCreateDbUser dbtype =>
+ (case Dbms.lookup dbtype of
+ NONE => ((Msg.send (bio, MsgError ("Unknown database type " ^ dbtype));
+ print ("Database user creation request with unknown datatype type " ^ dbtype);
+ ignore (OpenSSL.readChar bio))
+ handle OpenSSL.OpenSSL _ => ();
+ OpenSSL.close bio
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+ | SOME handler =>
+ case #adduser handler user of
+ NONE => ((Msg.send (bio, MsgOk);
+ print ("Added " ^ dbtype ^ " user " ^ user ^ ".\n"))
+ handle OpenSSL.OpenSSL s =>
+ (print "OpenSSL error\n";
+ Msg.send (bio,
+ MsgError
+ ("Error during creation: "
+ ^ s)));
+ (ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ())
+ | SOME msg => ((Msg.send (bio, MsgError ("Error adding user: " ^ msg));
+ print ("Error adding a " ^ dbtype ^ " user " ^ user ^ ": " ^ msg ^ "\n");
+ ignore (OpenSSL.readChar bio);
+ OpenSSL.close bio)
+ handle OpenSSL.OpenSSL _ => ();
+ loop ()))
+
| _ =>
(Msg.send (bio, MsgError "Unexpected command")
handle OpenSSL.OpenSSL _ => ();
MsgFile file => loop' (file :: files)
| MsgDoFiles => (Slave.handleChanges files;
Msg.send (bio, MsgOk))
+ | MsgRegenerate => (Domain.resetLocal ();
+ Msg.send (bio, MsgOk))
| _ => (print "Dispatcher sent unexpected command\n";
Msg.send (bio, MsgError "Unexpected command"))
in
OpenSSL.shutdown sock
end
-fun autodocBasis outdir =
+fun listBasis () =
let
val dir = Posix.FileSys.opendir Config.libRoot
:: files)
else
loop files
-
- val files = loop []
in
- Autodoc.autodoc {outdir = outdir, infiles = files}
+ loop []
end
+fun autodocBasis outdir =
+ Autodoc.autodoc {outdir = outdir, infiles = listBasis ()}
+
end