+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 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
+