System shell processes, with static input/output and propagation of interrupts.
authorwenzelm
Sat, 16 Feb 2008 16:43:54 +0100
changeset 26078 4fc74eb2842b
parent 26077 1498f0362362
child 26079 a58cc0cf4176
System shell processes, with static input/output and propagation of interrupts.
src/Pure/General/system_process.ML
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/General/system_process.ML	Sat Feb 16 16:43:54 2008 +0100
@@ -0,0 +1,44 @@
+(*  Title:      Pure/General/system_process.ML
+    ID:         $Id$
+    Author:     Makarius
+
+System shell processes, with static input/output and propagation of interrupts.
+*)
+
+signature SYSTEM_PROCESS =
+sig
+  val system_out: string -> string * int
+  val system: string -> int
+end;
+
+structure SystemProcess: SYSTEM_PROCESS =
+struct
+
+fun system_out cmdline = uninterruptible (fn restore_attributes => fn () =>
+  let
+    val _ = Secure.deny_secure "Cannot execute shell commands in secure mode";
+
+    val proc = Unix.execute (cmdline, []);
+    val (proc_stdout, proc_stdin) = Unix.streamsOf proc;
+
+    fun read buf =
+      (case Exn.capture (restore_attributes TextIO.input) proc_stdout of
+        Exn.Exn Interrupt => (Unix.kill (proc, Posix.Signal.int); read buf)
+      | Exn.Exn _ => buf
+      | Exn.Result "" => buf
+      | Exn.Result txt => read (Buffer.add txt buf));
+    val output = read Buffer.empty;
+    val status = Unix.reap proc;
+    val rc = Unix.fromStatus status;
+  in
+    tracing (PolyML.makestring (Unix.fromStatus status));
+    if rc = Unix.W_SIGNALED Posix.Signal.int orelse rc = Unix.W_EXITSTATUS 0wx82
+    then raise Interrupt
+    else (Buffer.content output, if OS.Process.isSuccess status then 0 else 1)
+  end) ();
+
+fun system cmdline =
+  let val (output, status) = system_out cmdline in writeln output; status end;
+
+end;
+