···109109 in
110110 (o#complete_command ast ctx, ast)
111111112112+ let stdout_for_pipeline ~sw = function
113113+ | [] -> (None, None)
114114+ | _ ->
115115+ let r, w = Eio_unix.pipe sw in
116116+ (Some r, Some (w :> Eio_unix.sink_ty Eio.Flow.sink))
117117+112118 let exec ctx (ast : Ast.complete_command) =
113119 let command, _ = ast in
114114- let execute_command p =
115115- let h = List.hd p in
116116- match h with
117117- | Ast.SimpleCommand (Prefixed _) -> None
118118- | Ast.SimpleCommand (Named (executable, None)) ->
119119- E.exec ctx.executor (List.map word_component_to_string executable)
120120- |> Option.some
121121- | Ast.SimpleCommand (Named (executable, Some suffix)) ->
122122- let args =
123123- List.filter_map
124124- (function
125125- | Ast.Suffix_word w ->
126126- Some (List.map word_component_to_string w)
127127- | Ast.Suffix_redirect _ -> None)
128128- suffix
129129- in
130130- E.exec ctx.executor
131131- (List.map word_component_to_string executable @ List.concat args)
132132- |> Option.some
133133- | v ->
134134- Fmt.epr "TODO: %a" Yojson.Safe.pp (Ast.command_to_yojson v);
135135- failwith "Err"
120120+ let execute_commands local_switch p =
121121+ let rec loop (status_of_previous, stdout_of_previous) = function
122122+ | Ast.SimpleCommand (Prefixed _) :: next ->
123123+ loop (status_of_previous, stdout_of_previous) next
124124+ | Ast.SimpleCommand (Named (executable, None)) :: rest -> (
125125+ let some_read, some_write =
126126+ stdout_for_pipeline ~sw:local_switch rest
127127+ in
128128+ match stdout_of_previous with
129129+ | None ->
130130+ E.exec ctx.executor ?stdout:some_write
131131+ (List.map word_component_to_string executable)
132132+ |> Option.some
133133+ | Some stdout ->
134134+ let res =
135135+ E.exec ctx.executor ~stdin:stdout ?stdout:some_write
136136+ (List.map word_component_to_string executable)
137137+ in
138138+ Option.iter Eio.Flow.close some_write;
139139+ loop (Some res, some_read) rest)
140140+ | Ast.SimpleCommand (Named (executable, Some suffix)) :: rest -> (
141141+ let args =
142142+ List.filter_map
143143+ (function
144144+ | Ast.Suffix_word w ->
145145+ Some (List.map word_component_to_string w)
146146+ | Ast.Suffix_redirect _ -> None)
147147+ suffix
148148+ in
149149+ let some_read, some_write =
150150+ stdout_for_pipeline ~sw:local_switch rest
151151+ in
152152+ match stdout_of_previous with
153153+ | None ->
154154+ let res =
155155+ E.exec ctx.executor ?stdout:some_write
156156+ (List.map word_component_to_string executable
157157+ @ List.concat args)
158158+ |> Option.some
159159+ in
160160+ Option.iter Eio.Flow.close some_write;
161161+ loop (res, some_read) rest
162162+ | Some stdout ->
163163+ let res =
164164+ E.exec ctx.executor ~stdin:stdout ?stdout:some_write
165165+ (List.map word_component_to_string executable
166166+ @ List.concat args)
167167+ |> Option.some
168168+ in
169169+ Option.iter Eio.Flow.close some_write;
170170+ loop (res, some_read) rest)
171171+ | v :: _ ->
172172+ Fmt.epr "TODO: %a" Yojson.Safe.pp (Ast.command_to_yojson v);
173173+ failwith "Err"
174174+ | [] -> status_of_previous
175175+ in
176176+ loop (None, None) p
136177 in
137178 let pipeline = function
138179 | Ast.Pipeline p -> (Fun.id, p)
139180 | Ast.Pipeline_Bang p ->
140181 (Option.map (fun i -> if Int.equal i 0 then -1 else 0), p)
141182 in
142142- let loop : Ast.clist -> int option = function
143143- | Nlist.Singleton (c, _) ->
144144- let rec fold :
145145- Ast.and_or * int option ->
146146- Ast.pipeline Ast.and_or_list ->
147147- int option =
148148- fun (sep, exit_so_far) pipe ->
149149- match (sep, pipe) with
150150- | And, Nlist.Singleton (p, _) -> (
151151- match exit_so_far with
152152- | Some 0 ->
153153- let f, p = pipeline p in
154154- f @@ execute_command p
155155- | v -> v)
156156- | Or, Nlist.Singleton (p, _) -> (
157157- match exit_so_far with
158158- | Some 0 -> Some 0
159159- | _ ->
160160- let f, p = pipeline p in
161161- f @@ execute_command p)
162162- | Noand_or, Nlist.Singleton (p, _) ->
163163- let f, p = pipeline p in
164164- f @@ execute_command p
165165- | Noand_or, Nlist.Cons ((p, next_sep), rest) ->
166166- let f, p = pipeline p in
167167- fold (next_sep, f (execute_command p)) rest
168168- | And, Nlist.Cons ((p, next_sep), rest) -> (
169169- match exit_so_far with
170170- | Some 0 ->
171171- let f, p = pipeline p in
172172- fold (next_sep, f (execute_command p)) rest
173173- | (None | Some _) as v -> v)
174174- | Or, Nlist.Cons ((p, next_sep), rest) -> (
175175- match exit_so_far with
176176- | Some 0 -> fold (next_sep, exit_so_far) rest
177177- | None | Some _ ->
178178- let f, p = pipeline p in
179179- fold (next_sep, f (execute_command p)) rest)
180180- in
181181- fold (Noand_or, None) c
182182- | _ -> Fmt.failwith "TODO!!!"
183183+ let loop : Eio.Switch.t -> Ast.clist -> int option =
184184+ fun sw -> function
185185+ | Nlist.Singleton (c, _) ->
186186+ let rec fold :
187187+ Ast.and_or * int option ->
188188+ Ast.pipeline Ast.and_or_list ->
189189+ int option =
190190+ fun (sep, exit_so_far) pipe ->
191191+ match (sep, pipe) with
192192+ | And, Nlist.Singleton (p, _) -> (
193193+ match exit_so_far with
194194+ | Some 0 ->
195195+ let f, p = pipeline p in
196196+ f @@ execute_commands sw p
197197+ | v -> v)
198198+ | Or, Nlist.Singleton (p, _) -> (
199199+ match exit_so_far with
200200+ | Some 0 -> Some 0
201201+ | _ ->
202202+ let f, p = pipeline p in
203203+ f @@ execute_commands sw p)
204204+ | Noand_or, Nlist.Singleton (p, _) ->
205205+ let f, p = pipeline p in
206206+ f @@ execute_commands sw p
207207+ | Noand_or, Nlist.Cons ((p, next_sep), rest) ->
208208+ let f, p = pipeline p in
209209+ fold (next_sep, f (execute_commands sw p)) rest
210210+ | And, Nlist.Cons ((p, next_sep), rest) -> (
211211+ match exit_so_far with
212212+ | Some 0 ->
213213+ let f, p = pipeline p in
214214+ fold (next_sep, f (execute_commands sw p)) rest
215215+ | (None | Some _) as v -> v)
216216+ | Or, Nlist.Cons ((p, next_sep), rest) -> (
217217+ match exit_so_far with
218218+ | Some 0 -> fold (next_sep, exit_so_far) rest
219219+ | None | Some _ ->
220220+ let f, p = pipeline p in
221221+ fold (next_sep, f (execute_commands sw p)) rest)
222222+ in
223223+ fold (Noand_or, None) c
224224+ | _ -> Fmt.failwith "TODO!!!"
183225 in
184184- (loop command, ctx, ast)
226226+ Eio.Switch.run @@ fun sw -> (loop sw command, ctx, ast)
185227186228 let apply_pair (a, b) f = f a b
187229 let ( ||> ) = apply_pair
+5-3
src/lib/posix/merry_posix.ml
···33module State = State
4455module Exec = struct
66- type t = { mgr : [ `Generic ] Eio.Process.mgr_ty Eio.Process.mgr }
66+ type t = { mgr : Eio_unix.Process.mgr_ty Eio_unix.Process.mgr }
77 type fork_action = unit
8899- let exec ?fork_actions:_ t s =
99+ let exec ?fork_actions:_ ?stdin ?stdout ?stderr t s =
1010+ (* let fds = List.map (fun (i, fd) -> (i, fd, `Nonblocking)) fds in *)
1011 Eio.Switch.run @@ fun sw ->
1111- Eio.Process.spawn ~sw t.mgr s |> Eio.Process.await |> function
1212+ Eio.Process.spawn ~sw ?stdin ?stdout ?stderr t.mgr s |> Eio.Process.await
1313+ |> function
1214 | `Exited n -> n
1315 | `Signaled n -> n
1416end
+8-1
src/lib/types.ml
···2929 (** A fork action is a piece of C-code to run inbetween the fork and the exec
3030 *)
31313232- val exec : ?fork_actions:fork_action list -> t -> string list -> int
3232+ val exec :
3333+ ?fork_actions:fork_action list ->
3434+ ?stdin:[> Eio__Flow.source_ty ] Eio_unix.source ->
3535+ ?stdout:_ Eio_unix.sink ->
3636+ ?stderr:[> Eio__Flow.sink_ty ] Eio_unix.source ->
3737+ t ->
3838+ string list ->
3939+ int
3340 (** Run a command in a child process *)
3441end