5 could work via the controlling tty). |
5 could work via the controlling tty). |
6 *) |
6 *) |
7 |
7 |
8 signature BASH = |
8 signature BASH = |
9 sig |
9 sig |
10 val process: string -> {output: string, rc: int, terminate: unit -> unit} |
10 val process: string -> {out: string, err: string, rc: int, terminate: unit -> unit} |
11 end; |
11 end; |
12 |
12 |
13 structure Bash: BASH = |
13 structure Bash: BASH = |
14 struct |
14 struct |
15 |
15 |
16 fun process script = |
16 fun process script = |
17 let |
17 let |
18 val id = serial_string (); |
18 val id = serial_string (); |
19 val script_path = File.tmp_path (Path.basic ("bash_script" ^ id)); |
19 val script_path = File.tmp_path (Path.basic ("bash_script" ^ id)); |
20 val output_path = File.tmp_path (Path.basic ("bash_output" ^ id)); |
20 val out_path = File.tmp_path (Path.basic ("bash_out" ^ id)); |
21 fun cleanup () = (try File.rm script_path; try File.rm output_path); |
21 val err_path = File.tmp_path (Path.basic ("bash_err" ^ id)); |
|
22 fun cleanup () = (try File.rm script_path; try File.rm out_path; try File.rm err_path); |
22 in |
23 in |
23 let |
24 let |
24 val _ = File.write script_path script; |
25 val _ = File.write script_path script; |
25 val status = |
26 val status = |
26 OS.Process.system |
27 OS.Process.system |
27 ("exec \"$ISABELLE_HOME/lib/scripts/process\" no_group /dev/null" ^ |
28 ("exec \"$ISABELLE_HOME/lib/scripts/process\" no_group /dev/null" ^ |
28 " script \"exec bash " ^ File.shell_path script_path ^ " > " ^ |
29 " script \"exec bash " ^ File.shell_path script_path ^ |
29 File.shell_path output_path ^ "\""); |
30 " > " ^ File.shell_path out_path ^ |
|
31 " 2> " ^ File.shell_path err_path ^ "\""); |
30 val rc = |
32 val rc = |
31 (case Posix.Process.fromStatus status of |
33 (case Posix.Process.fromStatus status of |
32 Posix.Process.W_EXITED => 0 |
34 Posix.Process.W_EXITED => 0 |
33 | Posix.Process.W_EXITSTATUS w => Word8.toInt w |
35 | Posix.Process.W_EXITSTATUS w => Word8.toInt w |
34 | Posix.Process.W_SIGNALED s => 256 + LargeWord.toInt (Posix.Signal.toWord s) |
36 | Posix.Process.W_SIGNALED s => 256 + LargeWord.toInt (Posix.Signal.toWord s) |
35 | Posix.Process.W_STOPPED s => 512 + LargeWord.toInt (Posix.Signal.toWord s)); |
37 | Posix.Process.W_STOPPED s => 512 + LargeWord.toInt (Posix.Signal.toWord s)); |
36 |
38 |
37 val output = the_default "" (try File.read output_path); |
39 val out = the_default "" (try File.read out_path); |
|
40 val err = the_default "" (try File.read err_path); |
38 val _ = cleanup (); |
41 val _ = cleanup (); |
39 in {output = output, rc = rc, terminate = fn () => ()} end |
42 in {out = out, err = err, rc = rc, terminate = fn () => ()} end |
40 handle exn => (cleanup (); reraise exn) |
43 handle exn => (cleanup (); reraise exn) |
41 end; |
44 end; |
42 |
45 |
43 end; |
46 end; |
44 |
47 |