Skip to content
Snippets Groups Projects
Commit c4c582da authored by Richard W.M. Jones's avatar Richard W.M. Jones
Browse files

Run sh/shout/shlines in a temporary directory.

parent 12f53f74
No related branches found
No related tags found
No related merge requests found
...@@ -9,14 +9,14 @@ and built program sources = ...@@ -9,14 +9,14 @@ and built program sources =
List.iter (fun s -> require (compiled s)) sources; List.iter (fun s -> require (compiled s)) sources;
let objects = List.map (change_file_extension "o") sources in let objects = List.map (change_file_extension "o") sources in
sh "cc %s -o %s" (String.concat " " objects) program sh "cd $builddir && cc %s -o %s" (String.concat " " objects) program
(* Goal: Make sure a C file is compiled (to an object file). *) (* Goal: Make sure a C file is compiled (to an object file). *)
and compiled c_file = and compiled c_file =
let o_file = change_file_extension "o" c_file in let o_file = change_file_extension "o" c_file in
target (more_recent [o_file] [c_file]); target (more_recent [o_file] [c_file]);
require (file_exists c_file); require (file_exists c_file);
sh "cc -c %s -o %s" c_file o_file sh "cd $builddir && cc -c %s -o %s" c_file o_file
(* XXX IMPLICIT *) (* XXX IMPLICIT *)
let () = let () =
......
...@@ -103,11 +103,47 @@ let url_contains_string url str = ...@@ -103,11 +103,47 @@ let url_contains_string url str =
unlink tmp; unlink tmp;
r r
(* Create a temporary directory. It is *not* deleted on exit. *)
let tmpdir () =
let chan = open_in "/dev/urandom" in
let data = String.create 16 in
really_input chan data 0 (String.length data);
close_in chan;
let data = Digest.to_hex (Digest.string data) in
let dir = Filename.temp_dir_name // sprintf "goaljobstmp%s" data in
mkdir dir 0o700;
dir
(* Recursively remove directory. *)
let rm_rf dir =
let cmd = sprintf "rm -rf %s" (quote dir) in
ignore (Sys.command cmd)
let shell = ref "/bin/sh"
(* Used by sh, shout etc. Create a temporary directory and a
* 'script.sh' inside it containing the script to run. Returns the
* temporary directory and command to run.
*)
let create_script script =
let dir = tmpdir () in
let script_file = dir // "script.sh" in
let chan = open_out script_file in
fprintf chan "#!%s\n" !shell;
fprintf chan "set -e\n"; (* so that job exits on error *)
fprintf chan "set -x\n"; (* echo commands (must be last) *)
fprintf chan "\n";
output_string chan script;
close_out chan;
chmod script_file 0o700;
let cmd = sprintf "cd %s && exec %s" (quote dir) (quote script_file) in
dir, cmd
let sh fs = let sh fs =
let do_sh cmd = let do_sh script =
let cmd = "set -e\nset -x\n\n" ^ cmd in let dir, cmd = create_script script in
let r = Sys.command cmd in let r = Sys.command cmd in
rm_rf dir;
if r <> 0 then ( if r <> 0 then (
let msg = sprintf "external command failed with code %d" r in let msg = sprintf "external command failed with code %d" r in
goal_failed msg goal_failed msg
...@@ -115,8 +151,8 @@ let sh fs = ...@@ -115,8 +151,8 @@ let sh fs =
in in
ksprintf do_sh fs ksprintf do_sh fs
let do_shlines cmd = let do_shlines script =
let cmd = "set -e\nset -x\n\n" ^ cmd in let dir, cmd = create_script script in
let chan = open_process_in cmd in let chan = open_process_in cmd in
let lines = ref [] in let lines = ref [] in
let rec loop () = let rec loop () =
...@@ -126,6 +162,7 @@ let do_shlines cmd = ...@@ -126,6 +162,7 @@ let do_shlines cmd =
in in
(try loop () with End_of_file -> ()); (try loop () with End_of_file -> ());
let r = close_process_in chan in let r = close_process_in chan in
rm_rf dir;
match r with match r with
| WEXITED 0 -> List.rev !lines | WEXITED 0 -> List.rev !lines
| WEXITED i -> | WEXITED i ->
...@@ -139,15 +176,11 @@ let do_shlines cmd = ...@@ -139,15 +176,11 @@ let do_shlines cmd =
goal_failed msg goal_failed msg
let shlines fs = ksprintf do_shlines fs let shlines fs = ksprintf do_shlines fs
let do_shout cmd = let do_shout script =
let lines = do_shlines cmd in let lines = do_shlines script in
String.concat "\n" lines String.concat "\n" lines
let shout fs = ksprintf do_shout fs let shout fs = ksprintf do_shout fs
(*
val shell : string ref
*)
(* (*
val replace_substring : string -> string -> string -> string val replace_substring : string -> string -> string -> string
*) *)
...@@ -217,6 +250,9 @@ let init () = ...@@ -217,6 +250,9 @@ let init () =
let prog = Sys.executable_name in let prog = Sys.executable_name in
let prog = Filename.basename prog in let prog = Filename.basename prog in
(* Save the current working directory when the program started. *)
putenv "builddir" (getcwd ());
let args = ref [] in let args = ref [] in
let display_version () = let display_version () =
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
let o_file = change_file_extension "o" c_file in let o_file = change_file_extension "o" c_file in
target (more_recent [o_file] [c_file]); target (more_recent [o_file] [c_file]);
sh "cc -c %s -o %s" c_file o_file sh "cd $builddir && cc -c %s -o %s" c_file o_file
} }
In the second example, the rule requires that several files In the second example, the rule requires that several files
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
require (compiled source); require (compiled source);
let object = change_file_extension "o" source in let object = change_file_extension "o" source in
sh "cc %s -o %s" object program sh "cd $builddir && cc %s -o %s" object program
} }
*) *)
...@@ -211,11 +211,14 @@ val quote : string -> string ...@@ -211,11 +211,14 @@ val quote : string -> string
{v command ||: } {v command ||: }
to ignore the result of a command. to ignore the result of a command.
Each shell runs in a new temporary directory. The temporary directory Each shell runs in a new temporary directory. The temporary
and all its contents is deleted after the shell exits. If you directory and all its contents is deleted after the shell exits.
want to save any data, [cd] somewhere. For example you could start If you want to save any data, [cd] somewhere. The environment
the command sequence with: variable [$builddir] is exported to the script. This is the
{v cd $HOME/data/ } current directory when the goaljobs program was started.
For example you could start the command sequence with
[cd $HOME/data/] or [cd $builddir].
*) *)
val sh : ('a, unit, string, unit) format4 -> 'a val sh : ('a, unit, string, unit) format4 -> 'a
...@@ -233,10 +236,8 @@ val shlines : ('a, unit, string, string list) format4 -> 'a ...@@ -233,10 +236,8 @@ val shlines : ('a, unit, string, string list) format4 -> 'a
Any lines printed to stdout is returned as a list of strings. Any lines printed to stdout is returned as a list of strings.
Trailing [\n] characters are not returned. *) Trailing [\n] characters are not returned. *)
(*
val shell : string ref val shell : string ref
(** Set this variable to override the default shell ([/bin/sh]). *) (** Set this variable to override the default shell ([/bin/sh]). *)
*)
(** {2 String functions} (** {2 String functions}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment