Shells in OCaml
at main 51 lines 1.6 kB view raw
1module Make (E : Types.Exec) = struct 2 type process = E.process 3 4 type t = { 5 reap : unit Eio.Promise.t * unit Eio.Promise.u; 6 id : int; 7 (* Process list is in reverse order *) 8 processes : 9 [ `Process of process 10 | `Built_in of unit Exit.t 11 | `Exit of unit Exit.t 12 | `Rdr of unit Exit.t 13 | `Error of int ] 14 list; 15 } 16 17 let get_id t = t.id 18 let set_id new_id t = { t with id = new_id } 19 let get_reaper t = t.reap 20 21 let make id processes = 22 let reap = Eio.Promise.create () in 23 { id; processes; reap } 24 25 let add_process proc t = 26 { t with processes = List.cons (`Process proc) t.processes } 27 28 let add_built_in b t = 29 { t with processes = List.cons (`Built_in b) t.processes } 30 31 let add_error b t = { t with processes = List.cons (`Error b) t.processes } 32 let add_rdr b t = { t with processes = List.cons (`Rdr b) t.processes } 33 let add_exit b t = { t with processes = List.cons (`Exit b) t.processes } 34 let size t = List.length t.processes 35 36 (* Section 2.9.2 https://pubs.opengroup.org/onlinepubs/9799919799/ *) 37 let await_exit ~pipefail ~interactive t = 38 Eio.Promise.resolve (snd t.reap) (); 39 Eio.Fiber.yield (); 40 let await = function 41 | `Process p -> 42 if interactive then 43 Eunix.delegate_control ~pgid:t.id @@ fun () -> E.await p 44 else E.await p 45 | `Built_in b | `Exit b | `Rdr b -> b 46 | `Error n -> Exit.nonzero () n 47 in 48 match (pipefail, t.processes) with 49 | false, x :: _ -> await x 50 | _ -> Fmt.failwith "TODO: pipefail or no processes" 51end