Select the types of activity you want to include in your feed.
Duplicating redirection inputs
This logic also comes with a vendoring of the inherit_fds logic too. See the corresponding issue on Eio's page: https://github.com/ocaml-multicore/eio/issues/826
···2121 Fmt.failwith "Conversion of %a" Yojson.Safe.pp
2222 (Ast.word_component_to_yojson v)
23232424+ let word_components_to_string ws =
2525+ String.concat "" (List.map word_component_to_string ws)
2626+2427 class default_map =
2528 object (_)
2629 inherit Ast.map
···116119 let r, w = Eio_unix.pipe sw in
117120 (Some r, Some (w :> Eio_unix.sink_ty Eio.Flow.sink))
118121122122+ let fd_of_int ?(close_unix = true) ~sw n =
123123+ Eio_unix.Fd.of_unix ~close_unix ~sw (Obj.magic n : Unix.file_descr)
124124+119125 let handle_one_redirection ~sw ctx = function
120126 | Ast.IoRedirect_IoFile (n, (op, file)) -> (
121127 match op with
122128 | Io_op_less ->
129129+ (* Simple redirection for input *)
123130 let r =
124124- Eio.Path.open_in ~sw
125125- (ctx.fs
126126- / (String.concat "" @@ List.map word_component_to_string file))
131131+ Eio.Path.open_in ~sw (ctx.fs / word_components_to_string file)
127132 in
128133 let fd = Eio_unix.Resource.fd_opt r |> Option.get in
129129- (n, fd, `Nonblocking)
134134+ Some (Types.Redirect (n, fd, `Blocking))
135135+ | Io_op_lessand -> (
136136+ match file with
137137+ | [ WordLiteral "-" ] ->
138138+ if n = 0 then Some (Types.Close Eio_unix.Fd.stdin)
139139+ else
140140+ let fd = fd_of_int ~sw n in
141141+ Some (Types.Close fd)
142142+ | [ WordLiteral m ] when Option.is_some (int_of_string_opt m) ->
143143+ let m = int_of_string m in
144144+ Some
145145+ (Types.Redirect
146146+ (n, fd_of_int ~close_unix:false ~sw m, `Blocking))
147147+ | _ -> None)
130148 | _ -> Fmt.failwith "Redirections ...")
131149 | Ast.IoRedirect_IoHere _ ->
132150 Fmt.failwith "HERE documents not yet implemented!"
···169187 | Ast.Suffix_redirect rdr ->
170188 handle_one_redirection ~sw:local_switch ctx rdr :: acc)
171189 [] suffix
172172- |> List.rev
190190+ |> List.rev |> List.filter_map Fun.id
173191 in
174192 let some_read, some_write =
175193 stdout_for_pipeline ~sw:local_switch rest
+76-14
src/lib/posix/exec.ml
···63636464let get_env = function Some e -> e | None -> Unix.environment ()
65656666+external action_dups : unit -> Eio_unix.Private.Fork_action.fork_fn
6767+ = "eio_unix_fork_dups"
6868+6969+let action_dups = action_dups ()
7070+7171+let rec with_fds mapping k =
7272+ match mapping with
7373+ | [] -> k []
7474+ | (dst, src, _) :: xs ->
7575+ Eio_unix.Fd.use_exn "inherit_fds" src @@ fun src ->
7676+ with_fds xs @@ fun xs -> k ((dst, (Obj.magic src : int)) :: xs)
7777+7878+let inherit_fds m =
7979+ let blocking =
8080+ m
8181+ |> List.filter_map (fun (dst, _, flags) ->
8282+ match flags with
8383+ | `Blocking -> Some (dst, true)
8484+ | `Nonblocking -> Some (dst, false)
8585+ | `Preserve_blocking -> None)
8686+ in
8787+ with_fds m @@ fun m ->
8888+ (* TODO: investigate -- the plan from Eio seems to also invert the list of redirections.
8989+ This is problematic for redirections, so we have copied the entire action here. *)
9090+ let plan = Eio_unix__.Inherit_fds.plan m |> List.rev in
9191+ Eio_unix.Private.Fork_action.
9292+ { run = (fun k -> k (Obj.repr (action_dups, plan, blocking))) }
9393+6694let spawn_unix () ~sw ?cwd ?pgid ?uid ?gid ~env ~fds ~executable args =
6795 let open Eio_posix in
6896 let actions =
6969- Low_level.Process.Fork_action.
7070- [ inherit_fds fds; execve executable ~argv:(Array.of_list args) ~env ]
9797+ [
9898+ inherit_fds fds;
9999+ Low_level.Process.Fork_action.execve executable ~argv:(Array.of_list args)
100100+ ~env;
101101+ ]
71102 in
72103 let actions =
73104 match pgid with
···104135 with_actions cwd @@ fun actions ->
105136 Eio_posix__.Process.process (Low_level.Process.spawn ~sw actions)
106137138138+let fd_equal_int fd i =
139139+ Eio_unix.Fd.use_exn "fd_equal_int" fd @@ fun ufd ->
140140+ let ufd_int = (Obj.magic ufd : int) in
141141+ Int.equal i ufd_int
142142+143143+let pp_redirections ppf (i, fd, _) = Fmt.pf ppf "(%i,%a)" i Eio_unix.Fd.pp fd
144144+107145let run ~sw _ ?stdin ?stdout ?stderr ?(fds = []) ?cwd ?env ?executable args =
108146 with_close_list @@ fun to_close ->
109109- let stdin_fd = read_of_fd ~sw stdin ~default:Eio_unix.Fd.stdin ~to_close in
110110- let stdout_fd =
111111- write_of_fd ~sw stdout ~default:Eio_unix.Fd.stdout ~to_close
147147+ let check_fd n = function
148148+ | Merry.Types.Redirect (m, _, _) -> Int.equal n m
149149+ | Merry.Types.Close fd -> fd_equal_int fd n
112150 in
113113- let stderr_fd =
114114- write_of_fd ~sw stderr ~default:Eio_unix.Fd.stderr ~to_close
151151+ let fd_exists n = List.exists (check_fd n) fds in
152152+ let std_fds =
153153+ (if fd_exists 0 then []
154154+ else
155155+ [
156156+ ( 0,
157157+ read_of_fd ~sw stdin ~default:Eio_unix.Fd.stdin ~to_close,
158158+ `Blocking );
159159+ ])
160160+ @ (if fd_exists 1 then []
161161+ else
162162+ [
163163+ ( 1,
164164+ write_of_fd ~sw stdout ~default:Eio_unix.Fd.stdout ~to_close,
165165+ `Blocking );
166166+ ])
167167+ @
168168+ if fd_exists 2 then []
169169+ else
170170+ [
171171+ ( 2,
172172+ write_of_fd ~sw stderr ~default:Eio_unix.Fd.stderr ~to_close,
173173+ `Blocking );
174174+ ]
115175 in
116116- let check_fd n (m, _, _) = Int.equal n m in
117117- let fd_exists n = List.exists (check_fd n) fds in
118118- let fds =
119119- (if fd_exists 0 then [] else [ (0, stdin_fd, `Blocking) ])
120120- @ (if fd_exists 1 then [] else [ (1, stdout_fd, `Blocking) ])
121121- @ (if fd_exists 2 then [] else [ (2, stderr_fd, `Blocking) ])
122122- @ fds
176176+ let need_close, fds =
177177+ List.fold_left
178178+ (fun (cs, fs) -> function
179179+ | Merry.Types.Redirect (a, b, c) -> (cs, (a, b, c) :: fs)
180180+ | Close fd -> (fd :: cs, fs))
181181+ ([], []) fds
182182+ |> fun (cs, fs) -> (List.rev cs, List.rev fs)
123183 in
184184+ List.iter Eio_unix.Fd.close need_close;
185185+ let fds = std_fds @ fds in
124186 let executable = get_executable executable ~args in
125187 let env = get_env env in
126188 spawn_unix ~sw ?cwd ~fds ~env ~executable () args
+5-1
src/lib/types.ml
···2121 (** Update the state with a new parameter mapping *)
2222end
23232424+type redirect =
2525+ | Redirect of int * Eio_unix.Fd.t * Eio_unix.Private.Fork_action.blocking
2626+ | Close of Eio_unix.Fd.t
2727+2428module type Exec = sig
2529 type t
2630 (** An executor for commands *)
···31353236 val exec :
3337 ?fork_actions:fork_action list ->
3434- ?fds:(int * Eio_unix.Fd.t * Eio_unix.Private.Fork_action.blocking) list ->
3838+ ?fds:redirect list ->
3539 ?stdin:_ Eio_unix.source ->
3640 ?stdout:_ Eio_unix.sink ->
3741 ?stderr:_ Eio_unix.sink ->
+16
test/simple.t
···5050 hello
515152522.5 Input redirection
5353+5454+Simple example of redirecing stdin to an open file.
5555+5356 $ cat >hello.md <<EOF
5457 > # Hello, World!
5558 > ---------------
···5861 $ osh -c "cat < hello.md"
5962 # Hello, World!
6063 ---------------
6464+6565+Using `<&-` to close stdin
6666+6767+ $ osh -c "cat <&-"
6868+ cat: -: Bad file descriptor
6969+ cat: closing standard input: Bad file descriptor
7070+ [1]
7171+7272+Using `<&` to copy a file descriptor
7373+7474+ $ osh -c "cat 3<hello.md <&3"
7575+ # Hello, World!
7676+ ---------------