diff --git a/src/lib/eunix.ml b/src/lib/eunix.ml index d771acd..c803b6f 100644 --- a/src/lib/eunix.ml +++ b/src/lib/eunix.ml @@ -142,6 +142,26 @@ let with_stdin_in_raw_mode fn = ~finally:(fun () -> Unix.tcsetattr Unix.stdin TCSADRAIN saved_tio) fn +let resolve_program ?(update = true) ?path hash name = + let v = + if not (String.contains name '/') then begin + path + |> Option.value ~default:"/bin:/usr/bin" + |> String.split_on_char ':' + |> List.find_map (fun dir -> + let p = Filename.concat dir name in + if Sys.file_exists p then Some p else None) + end + else if Sys.file_exists name then Some name + else None + in + match (update, v) with + | true, Some loc -> + let hash = Hash.add ~utility:name ~loc hash in + (hash, Some loc) + | false, Some loc -> (hash, Some loc) + | _, None -> (hash, None) + module Signals = struct type t = | Interrupt diff --git a/src/lib/eval.ml b/src/lib/eval.ml index bfe8763..3f8a615 100644 --- a/src/lib/eval.ml +++ b/src/lib/eval.ml @@ -159,26 +159,6 @@ module Make (S : Types.State) (E : Types.Exec) = struct let file_creation_mode ctx = 0o666 - ctx.umask let cwd_of_ctx ctx = S.cwd ctx.state |> Fpath.to_string |> ( / ) ctx.fs - let resolve_program ?(update = true) ctx name = - let v = - if not (String.contains name '/') then begin - S.lookup ctx.state ~param:"PATH" - |> Option.value ~default:"/bin:/usr/bin" - |> String.split_on_char ':' - |> List.find_map (fun dir -> - let p = Filename.concat dir name in - if Sys.file_exists p then Some p else None) - end - else if Sys.file_exists name then Some name - else None - in - match (update, v) with - | true, Some loc -> - let hash = Hash.add ~utility:name ~loc ctx.hash in - ({ ctx with hash }, Some loc) - | false, Some loc -> (ctx, Some loc) - | _, None -> (ctx, None) - let get_env ?(extra = []) ctx = let extra = extra @ List.map (fun (k, v) -> (k, v)) @@ S.exports ctx.state @@ -237,13 +217,19 @@ module Make (S : Types.State) (E : Types.Exec) = struct let mode = if async then Types.Async else Types.Switched sw in let fds = ctx.rdrs @ Option.value ~default:[] fds in let ctx, process = - match (executable, resolve_program ctx executable) with - | _, (ctx, None) | "", (ctx, _) -> + let hash, prog = + Eunix.resolve_program + ?path:(S.lookup ctx.state ~param:"PATH") + ctx.hash executable + in + let ctx = { ctx with hash } in + match (executable, prog) with + | _, None | "", _ -> Eio.Flow.copy_string (Fmt.str "msh: command not found: %s\n" executable) stdout; (ctx, Error (127, `Not_found)) - | _, (ctx, Some full_path) -> + | _, Some full_path -> Debug.Log.debug (fun f -> f "executing %a\n%a" Fmt.(list ~sep:(Fmt.any " ") (quote string)) @@ -397,12 +383,16 @@ module Make (S : Types.State) (E : Types.Exec) = struct @@ fun () -> if args <> [] then let name = List.hd args in - let prog = - match - resolve_program ~update:false ctx name - with - | _, None -> Fmt.failwith "%s not found" name - | _, Some p -> p + let ctx, prog = + let hash, prog = + Eunix.resolve_program ~update:false + ?path:(S.lookup ctx.state ~param:"PATH") + ctx.hash name + in + let ctx = { ctx with hash } in + match prog with + | None -> Fmt.failwith "%s not found" name + | Some p -> (ctx, p) in Unix.execve prog (Array.of_list args) (Array.of_list @@ -473,23 +463,31 @@ module Make (S : Types.State) (E : Types.Exec) = struct in loop (Exit.value ctx) job rest | _ -> ( - let exec_and_args = + let ctx, exec_and_args = if is_command then begin match command_args with | [] -> assert false | x :: xs -> ( - match - resolve_program ~update:false - ctx x - with - | _, None -> - Exit.nonzero ("", []) 1 - | _, Some prog -> + let hash, prog = + Eunix.resolve_program + ~update:false + ?path: + (S.lookup ctx.state + ~param:"PATH") + ctx.hash x + in + let ctx = { ctx with hash } in + match prog with + | None -> + (ctx, Exit.nonzero ("", []) 1) + | Some prog -> if print_command then - Exit.zero ("echo", [ prog ]) - else Exit.zero (x, xs)) + ( ctx, + Exit.zero + ("echo", [ prog ]) ) + else (ctx, Exit.zero (x, xs))) end - else Exit.zero (executable, args) + else (ctx, Exit.zero (executable, args)) in match exec_and_args with | Exit.Nonzero _ as v -> @@ -1482,9 +1480,15 @@ module Make (S : Types.State) (E : Types.Exec) = struct | _, WEXITED 0 -> Exit.zero ctx | _, (WEXITED n | WSIGNALED n | WSTOPPED n) -> Exit.nonzero ctx n) | Dot file -> ( - match resolve_program ctx file with - | ctx, None -> Exit.nonzero ctx 127 - | ctx, Some fname -> + let hash, prog = + Eunix.resolve_program + ?path:(S.lookup ctx.state ~param:"PATH") + ctx.hash file + in + let ctx = { ctx with hash } in + match prog with + | None -> Exit.nonzero ctx 127 + | Some fname -> Debug.Log.debug (fun f -> f "sourcing..."); let program = Ast.of_file (ctx.fs / fname) in let ctx, _ = diff --git a/src/lib/posix/exec.ml b/src/lib/posix/exec.ml index e2d423a..c06e806 100644 --- a/src/lib/posix/exec.ml +++ b/src/lib/posix/exec.ml @@ -204,7 +204,7 @@ let inherit_fds m = with_fds m @@ fun m -> (* TODO: investigate -- the plan from Eio seems to also invert the list of redirections. This is problematic for redirections, so we have copied the entire action here. *) - let plan = Eio_unix__.Inherit_fds.plan m |> List.rev in + let plan = Eio_unix__.Inherit_fds.plan m in Eio_unix.Private.Fork_action. { run = (fun k -> k (Obj.repr (action_dups, plan, blocking))) }