1119380Sjake(* Copied from Moscow ML source *) 2119380Sjakestructure Mosml = 3119380Sjakestruct 4119380Sjakedatatype runresult = 5119380Sjake Success of string 6119380Sjake | Failure of string 7119380Sjakefun run cmd args inp = 8119380Sjake let fun catenate xs = 9119380Sjake String.concat (List.foldr (fn (s, res) => s :: " " :: res) [] xs) 10119380Sjake fun write filename s = 11119380Sjake let open BinIO 12119380Sjake val os = openOut filename 13119380Sjake in output(os, s); closeOut os end 14119380Sjake fun read filename = 15119380Sjake let open BinIO 16119380Sjake val is = openIn filename 17119380Sjake val res = inputAll is 18119380Sjake in closeIn is; res end 19119380Sjake val infile = OS.FileSys.tmpName () 20119380Sjake val outfile = OS.FileSys.tmpName () 21119380Sjake in let 22119380Sjake val _ = write infile (Byte.stringToBytes inp) 23119380Sjake val cmdline = 24119380Sjake (* This should work for Bourne sh, POSIX sh, ksh, bash: *) 25119380Sjake catenate (cmd :: List.@(args, ["<", infile, "1>", outfile, 26119380Sjake "2>&1"])) 27119380Sjake (* This works for bash, csh and tcsh: *) 28119380Sjake (* catenate (cmd :: List.@(args, ["<", infile, "&>", outfile])) *) 29119380Sjake val status = OS.Process.system cmdline 30119380Sjake val result = if OS.Process.isSuccess status then 31119380Sjake Success (Byte.bytesToString (read outfile)) 32119380Sjake else 33119380Sjake ((Failure (Byte.bytesToString (read outfile))) 34119380Sjake handle IO.Io _ => Failure (cmd ^ ": command failed")) 35119380Sjake in 36119380Sjake (OS.FileSys.remove infile) handle OS.SysErr _ => (); 37119380Sjake (OS.FileSys.remove outfile) handle OS.SysErr _ => (); 38119380Sjake result 39119380Sjake end 40119380Sjakehandle e => 41119380Sjake((OS.FileSys.remove infile) handle OS.SysErr _ => (); 42119380Sjake (OS.FileSys.remove outfile) handle OS.SysErr _ => (); 43119380Sjake raise e) 44119380Sjakeend 45119380Sjakeend; 46119380Sjake