fun isMember (list, addr) = let val proc = Unix.execute ("/usr/sbin/find_member", ["-l", list, addr]) in (case TextIO.inputLine (Unix.textInstreamOf proc) of NONE => false | _ => true) before ignore (Unix.reap proc) end fun isIdent ch = Char.isLower ch orelse Char.isDigit ch fun validHost s = size s > 0 andalso size s < 20 andalso List.all isIdent (String.explode s) fun validDomain s = size s > 0 andalso size s < 100 andalso List.all validHost (String.fields (fn ch => ch = #".") s) fun validEmailUser s = size s > 0 andalso size s < 50 andalso List.all (fn ch => Char.isAlphaNum ch orelse ch = #"." orelse ch = #"_" orelse ch = #"-" orelse ch = #"+") (String.explode s) fun validEmail s = (case String.fields (fn ch => ch = #"@") s of [user, host] => validEmailUser user andalso validDomain host | _ => false) fun main () = case CommandLine.arguments () of [list, cmd, addr] => if list <> "hcoop-discuss" andalso list <> "hcoop-misc" andalso list <> "hcoop-announce" andalso list <> "hcoop-sysadmin" then (print "Bad mailing list name\n"; OS.Process.failure) else if not (validEmail addr) then (print "Invalid e-mail address\n"; OS.Process.failure) else (case cmd of "check" => if isMember (list, addr) then OS.Process.success else OS.Process.failure | "add" => if isMember (list, addr) then OS.Process.success else OS.Process.system (String.concat ["echo ", addr, " | /usr/sbin/add_members -r - ", list]) | "rm" => if list = "hcoop-announce" then (print "You can't remove anyone from hcoop-announce.\n"; OS.Process.failure) else if isMember (list, addr) then OS.Process.system (String.concat ["/usr/sbin/remove_members ", list, " ", addr]) else OS.Process.success | _ => (print ("Invalid command " ^ cmd ^ "\n"); OS.Process.failure)) | _ => (print "Bad command-line arguments\n"; OS.Process.failure) val _ = OS.Process.exit (main ())