common setup for system_out/system;
authorwenzelm
Thu, 06 Mar 2008 20:17:50 +0100
changeset 26220 d34b68c21f9a
parent 26219 2d026932f710
child 26221 e557c20158e2
common setup for system_out/system;
src/Pure/General/file.ML
src/Pure/General/secure.ML
src/Pure/ML-Systems/alice.ML
src/Pure/ML-Systems/mosml.ML
src/Pure/ML-Systems/polyml_common.ML
src/Pure/ML-Systems/smlnj.ML
src/Pure/ML-Systems/system_shell.ML
--- a/src/Pure/General/file.ML	Thu Mar 06 20:17:49 2008 +0100
+++ b/src/Pure/General/file.ML	Thu Mar 06 20:17:50 2008 +0100
@@ -98,8 +98,10 @@
       (case getenv "ISABELLE_FILE_IDENT" of
         "" => Path.implode (full_path path) ^ ": " ^ Time.toString time
       | cmd =>
-         let val id = execute ("\"$ISABELLE_HOME/lib/scripts/fileident\" " ^ shell_path path) in
-           if id <> "" then id
+         let
+           val (id, rc) = system_out ("\"$ISABELLE_HOME/lib/scripts/fileident\" " ^ shell_path path)
+         in
+           if id <> "" andalso rc = 0 then id
            else error ("Failed to identify file " ^ quote (Path.implode path) ^ " by " ^ cmd)
          end)));
 
--- a/src/Pure/General/secure.ML	Thu Mar 06 20:17:49 2008 +0100
+++ b/src/Pure/General/secure.ML	Thu Mar 06 20:17:50 2008 +0100
@@ -14,7 +14,7 @@
   val use_file: (string -> unit) * (string -> 'a) -> bool -> string -> unit
   val use: string -> unit
   val commit: unit -> unit
-  val execute: string -> string
+  val system_out: string -> string * int
   val system: string -> int
 end;
 
@@ -57,11 +57,10 @@
 
 fun secure_shell () = deny_secure "Cannot execute shell commands in secure mode";
 
-val orig_execute = execute;
-val orig_system = system;
+val orig_system_out = system_out;
 
-fun execute s = (secure_shell (); orig_execute s);
-fun system s = (secure_shell (); orig_system s);
+fun system_out s = (secure_shell (); orig_system_out s);
+fun system s = #2 (system_out s);
 
 end;
 
@@ -69,5 +68,5 @@
 val use_text = Secure.use_text;
 val use_file = Secure.use_file;
 fun use s = Secure.use s handle ERROR msg => (writeln msg; raise Fail "ML error");
-val execute = Secure.execute;
+val system_out = Secure.system_out;
 val system = Secure.system;
--- a/src/Pure/ML-Systems/alice.ML	Thu Mar 06 20:17:49 2008 +0100
+++ b/src/Pure/ML-Systems/alice.ML	Thu Mar 06 20:17:50 2008 +0100
@@ -11,6 +11,7 @@
 - use "ML-Systems/exn.ML";
 - use "ML-Systems/multithreading.ML";
 - use "ML-Systems/time_limit.ML";
+- use "ML-Systems/system_shell.ML";
 - use "ML-Systems/alice.ML";
 - use "ROOT.ML";
 - Session.finish ();
@@ -143,29 +144,9 @@
 
 (** OS related **)
 
-(* current directory *)
-
 val cd = OS.FileSys.chDir;
 val pwd = OS.FileSys.getDir;
 
-
-(* system command execution *)
-
-(*execute Unix command which doesn't take any input from stdin and
-  sends its output to stdout; could be done more easily by Unix.execute,
-  but that function doesn't use the PATH*)
-fun execute command =
-  let
-    val tmp_name = OS.FileSys.tmpName ();
-    val is = (OS.Process.system (command ^ " > " ^ tmp_name); TextIO.openIn tmp_name);
-    val result = TextIO.inputAll is;
-  in
-    TextIO.closeIn is;
-    OS.FileSys.remove tmp_name;
-    result
-  end;
-
-(*plain version; with return code*)
 val system = OS.Process.system: string -> int;
 
 structure OS =
@@ -182,9 +163,6 @@
   end;
 end;
 
-
-(* getenv *)
-
 fun getenv var =
   (case OS.Process.getEnv var of
     NONE => ""
--- a/src/Pure/ML-Systems/mosml.ML	Thu Mar 06 20:17:49 2008 +0100
+++ b/src/Pure/ML-Systems/mosml.ML	Thu Mar 06 20:17:50 2008 +0100
@@ -38,6 +38,7 @@
 use "ML-Systems/universal.ML";
 use "ML-Systems/multithreading.ML";
 use "ML-Systems/time_limit.ML";
+use "ML-Systems/system_shell.ML";
 
 
 (*low-level pointer equality*)
@@ -178,38 +179,11 @@
 
 (** OS related **)
 
-(* current directory *)
-
 val cd = OS.FileSys.chDir;
 val pwd = OS.FileSys.getDir;
 
-
-(* system command execution *)
-
-(*execute Unix command which doesn't take any input from stdin and
-  sends its output to stdout; could be done more easily by Unix.execute,
-  but that function doesn't use the PATH*)
-fun execute command =
-  let
-    val tmp_name = FileSys.tmpName ();
-    val is = (Process.system (command ^ " > " ^ tmp_name); TextIO.openIn tmp_name);
-    val result = TextIO.inputAll is;
-  in
-    TextIO.closeIn is;
-    FileSys.remove tmp_name;
-    result
-  end;
-
-(*plain version; with return code*)
-fun system cmd =
-  if Process.system cmd = Process.success then 0 else 1;
-
-
 val string_of_pid = Int.toString;
 
-
-(* getenv *)
-
 fun getenv var =
   (case Process.getEnv var of
     NONE => ""
--- a/src/Pure/ML-Systems/polyml_common.ML	Thu Mar 06 20:17:49 2008 +0100
+++ b/src/Pure/ML-Systems/polyml_common.ML	Thu Mar 06 20:17:50 2008 +0100
@@ -9,6 +9,8 @@
 else use "ML-Systems/universal.ML";
 use "ML-Systems/multithreading.ML";
 use "ML-Systems/time_limit.ML";
+use "ML-Systems/system_shell.ML";
+
 
 
 (** ML system and platform related **)
@@ -190,27 +192,6 @@
 val pwd = OS.FileSys.getDir;
 
 
-(* system command execution *)
-
-(*execute Unix command which doesn't take any input from stdin and
-  sends its output to stdout; could be done more easily by Unix.execute,
-  but that function doesn't use the PATH*)
-fun execute command =
-  let
-    val tmp_name = OS.FileSys.tmpName ();
-    val is = (OS.Process.system (command ^ " > " ^ tmp_name); TextIO.openIn tmp_name);
-    val result = TextIO.inputAll is;
-  in
-    TextIO.closeIn is;
-    OS.FileSys.remove tmp_name;
-    result
-  end;
-
-(*plain version; with return code*)
-fun system cmd =
-  if OS.Process.isSuccess (OS.Process.system cmd) then 0 else 1;
-
-
 (*Convert a process ID to a decimal string (chiefly for tracing)*)
 fun string_of_pid pid =
   Word.fmt StringCvt.DEC (Word.fromLargeWord (Posix.Process.pidToWord pid));
--- a/src/Pure/ML-Systems/smlnj.ML	Thu Mar 06 20:17:49 2008 +0100
+++ b/src/Pure/ML-Systems/smlnj.ML	Thu Mar 06 20:17:50 2008 +0100
@@ -9,6 +9,7 @@
 use "ML-Systems/exn.ML";
 use "ML-Systems/universal.ML";
 use "ML-Systems/multithreading.ML";
+use "ML-Systems/system_shell.ML";
 
 
 (*low-level pointer equality*)
@@ -229,27 +230,12 @@
 
 (* system command execution *)
 
-(*execute Unix command which doesn't take any input from stdin and
-  sends its output to stdout; could be done more easily by Unix.execute,
-  but that function doesn't use the PATH*)
-fun execute command =
-  let
-    val tmp_name = OS.FileSys.tmpName ();
-    val is = (OS.Process.system (command ^ " > " ^ tmp_name); TextIO.openIn tmp_name);
-    val result = TextIO.inputAll is;
-  in
-    TextIO.closeIn is;
-    OS.FileSys.remove tmp_name;
-    result
-  end;
-
-(*plain version; with return code*)
-val system = mk_int o OS.Process.system;
+val system_out = (fn (output, rc) => (output, mk_int rc)) o system_out;
 
 
 (*Convert a process ID to a decimal string (chiefly for tracing)*)
 fun string_of_pid pid =
-    Word.fmt StringCvt.DEC (Word.fromLargeWord (Posix.Process.pidToWord pid));
+  Word.fmt StringCvt.DEC (Word.fromLargeWord (Posix.Process.pidToWord pid));
 
 
 (* getenv *)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/ML-Systems/system_shell.ML	Thu Mar 06 20:17:50 2008 +0100
@@ -0,0 +1,44 @@
+(*  Title:      Pure/ML-Systems/system_shell.ML
+    ID:         $Id$
+    Author:     Makarius
+
+Generic system shell processes (no provisions to propagate interrupts;
+might still work via the controlling tty).
+*)
+
+local
+
+fun read_file name =
+  let val is = TextIO.openIn name
+  in TextIO.inputAll is before TextIO.closeIn is end;
+
+fun write_file name txt =
+  let val os = TextIO.openOut name
+  in TextIO.output (os, txt) before TextIO.closeOut os end;
+
+in
+
+fun system_out script =
+  let
+    val script_name = OS.FileSys.tmpName ();
+    val _ = write_file script_name script;
+
+    val output_name = OS.FileSys.tmpName ();
+
+    val status =
+      OS.Process.system ("perl -w \"$ISABELLE_HOME/lib/scripts/system.pl\" nogroup " ^
+        script_name ^ " /dev/null " ^ output_name);
+    val rc =
+      (case Posix.Process.fromStatus status of
+        Posix.Process.W_EXITED => 0
+      | Posix.Process.W_EXITSTATUS w => Word8.toInt w
+      | Posix.Process.W_SIGNALED s => 256 + LargeWord.toInt (Posix.Signal.toWord s)
+      | Posix.Process.W_STOPPED s => 512 + LargeWord.toInt (Posix.Signal.toWord s));
+
+    val output = read_file output_name handle IO.Io _ => "";
+    val _ = OS.FileSys.remove script_name handle OS.SysErr _ => ();
+    val _ = OS.FileSys.remove output_name handle OS.SysErr _ => ();
+  in (output, rc) end;
+
+end;
+