···219219 { ctx with last_background_process = string_of_int (E.pid process) }
220220 else ctx
221221 in
222222- let on_process ~async process ctx =
223223- clear_local_state ctx |> set_last_background ~async process
222222+ let on_process ?process ~async ctx =
223223+ let ctx = clear_local_state ctx in
224224+ match process with
225225+ | None -> ctx
226226+ | Some process -> set_last_background ~async process ctx
224227 in
225228 let handle_job ~pgid j p =
226229 match (j, p) with
···228231 Option.some @@ J.make ~state:`Running pgid (Nlist.Singleton p)
229232 | Some j, `Process p -> Option.some @@ J.add_process p j
230233 | Some j, `Built_in p -> Option.some @@ J.add_built_in p j
234234+ | Some j, `Error p -> Option.some @@ J.add_error p j
235235+ in
236236+ let exec_process ctx job ?fds ?stdin ?stdout ~pgid args =
237237+ let process =
238238+ E.exec ctx.executor ?fds ?stdin ?stdout ~pgid ~mode
239239+ ~cwd:(cwd_of_ctx ctx)
240240+ ~env:(get_env ~extra:ctx.local_state ())
241241+ args
242242+ in
243243+ match process with
244244+ | Error (n, _) ->
245245+ let job = handle_job ~pgid job (`Error n) in
246246+ (on_process ~async ctx, job)
247247+ | Ok process ->
248248+ let job = handle_job ~pgid job (`Process process) in
249249+ (on_process ~async ~process ctx, job)
231250 in
232251 let rec loop (ctx : ctx) (job : J.t option)
233252 ((pgid, stdout_of_previous) :
···266285 handle_word_components_to_string ctx executable
267286 in
268287 let ctx, job =
269269- let process =
270270- E.exec ctx.executor ?stdout:some_write ~pgid ~mode
271271- ~cwd:(cwd_of_ctx ctx)
272272- ~env:(get_env ~extra:ctx.local_state ())
273273- [ executable ]
274274- in
275275- let job = handle_job ~pgid job (`Process process) in
276276- (on_process ~async process ctx, job)
288288+ exec_process ctx job ?stdout:some_write ~pgid [ executable ]
277289 in
278290 Option.iter Eio.Flow.close some_write;
279291 loop ctx job (pgid, some_read) rest
···282294 handle_word_components_to_string ctx executable
283295 in
284296 let ctx, job =
285285- let process =
286286- E.exec ctx.executor ~stdin:stdout ~pgid ~mode
287287- ?stdout:some_write
288288- ~env:(get_env ~extra:ctx.local_state ())
289289- ~cwd:(cwd_of_ctx ctx) [ executable ]
290290- in
291291- let job = handle_job ~pgid job (`Process process) in
292292- (on_process ~async process ctx, job)
297297+ exec_process ctx job ~stdin:stdout ?stdout:some_write ~pgid
298298+ [ executable ]
293299 in
294300 Option.iter Eio.Flow.close some_write;
295301 loop ctx job (pgid, some_read) rest))
···328334 handle_word_components_to_string ctx executable
329335 in
330336 let ctx, job =
331331- let process =
332332- E.exec ctx.executor ?stdout:some_write ~pgid ~mode
333333- ~fds:redirect ~cwd:(cwd_of_ctx ctx)
334334- ~env:(get_env ~extra:ctx.local_state ())
335335- (executable :: args)
336336- in
337337- let job = handle_job ~pgid job (`Process process) in
338338- (on_process ~async process ctx, job)
337337+ exec_process ctx job ~fds:redirect ?stdout:some_write ~pgid
338338+ (executable :: args)
339339 in
340340 Option.iter Eio.Flow.close some_write;
341341 loop ctx job (pgid, some_read) rest
···344344 handle_word_components_to_string ctx executable
345345 in
346346 let ctx, job =
347347- let process =
348348- E.exec ctx.executor ~stdin:stdout ~pgid ~mode
349349- ?stdout:some_write ~fds:redirect
350350- ~env:(get_env ~extra:ctx.local_state ())
351351- ~cwd:(cwd_of_ctx ctx) (executable :: args)
352352- in
353353- let job = handle_job ~pgid job (`Process process) in
354354- (on_process ~async process ctx, job)
347347+ exec_process ctx job ~fds:redirect ~stdin:stdout
348348+ ?stdout:some_write ~pgid (executable :: args)
355349 in
356350 Option.iter Eio.Flow.close some_write;
357351 loop ctx job (pgid, some_read) rest))
···376370 E.exec ~mode:(Types.Switched ghost_switch) ~pgid:0
377371 ~cwd:(cwd_of_ctx initial_ctx) initial_ctx.executor
378372 [ "sleep"; "99999999" ]
373373+ |> function
374374+ | Ok p -> p
375375+ | Error (n, `Not_found) ->
376376+ Fmt.epr "Interal error ghost process: not found";
377377+ exit n
379378 in
380379 loop initial_ctx None (E.pid ghost_process, None) p
381380 in
+10-2
src/lib/job.ml
···55 state : [ `Running ];
66 id : int;
77 (* Process list is in reverse order *)
88- processes : [ `Process of E.process | `Built_in of unit Exit.t ] Nlist.t;
88+ processes :
99+ [ `Process of E.process | `Built_in of unit Exit.t | `Error of int ]
1010+ Nlist.t;
911 }
10121113 let make ?(state = `Running) id processes = { state; id; processes }
···15171618 let add_built_in b t =
1719 { t with processes = Nlist.cons (`Built_in b) t.processes }
2020+2121+ let add_error b t = { t with processes = Nlist.cons (`Error b) t.processes }
18221923 (* Section 2.9.2 https://pubs.opengroup.org/onlinepubs/9799919799/ *)
2024 let await_exit ~pipefail t =
2121- let await = function `Process p -> E.await p | `Built_in b -> b in
2525+ let await = function
2626+ | `Process p -> E.await p
2727+ | `Built_in b -> b
2828+ | `Error n -> Exit.nonzero () n
2929+ in
2230 match pipefail with
2331 | false -> await (Nlist.hd t.processes)
2432 | _ -> Fmt.failwith "TODO: pipefail"
+8-3
src/lib/posix/merry_posix.ml
···1616 | `Signaled n -> Merry.Exit.nonzero () n
17171818 let exec ?(fork_actions = []) ?(fds = []) ?stdin ?stdout ?stderr ?env ~mode
1919- ~pgid ~cwd t args : process =
1919+ ~pgid ~cwd t args =
2020 let env =
2121 Option.map
2222 (fun lst -> List.map (fun (a, b) -> a ^ "=" ^ b) lst |> Array.of_list)
2323 env
2424 in
2525- Exec.run ~fork_actions ~mode ~fds ~pgid ~cwd ?stdin ?stdout ?stderr ?env t
2626- args
2525+ try
2626+ Ok
2727+ (Exec.run ~fork_actions ~mode ~fds ~pgid ~cwd ?stdin ?stdout ?stderr
2828+ ?env t args)
2929+ with Eio.Io (Eio.Process.E (Eio.Process.Executable_not_found m), _ctx) ->
3030+ Fmt.epr "msh: command not found: %s\n%!" m;
3131+ Error (127, `Not_found)
2732end
+1-1
src/lib/types.ml
···6464 cwd:Eio.Fs.dir_ty Eio.Path.t ->
6565 t ->
6666 string list ->
6767- process
6767+ (process, int * [ `Not_found ]) result
6868 (** Run a command in a child process *)
69697070 val await : process -> unit Exit.t
+10
test/simple.t
···6161 $ msh test.sh
6262 hello
63636464+ $ msh -c "lssssss"
6565+ msh: command not found: lssssss
6666+ [127]
6767+ $ sh -c "lssssss | echo 'all good'"
6868+ all good
6969+ sh: line 1: lssssss: command not found
7070+ $ msh -c "lssssss | echo 'all good'"
7171+ msh: command not found: lssssss
7272+ all good
7373+64742.2 Simple And
65756676 $ cat >test.sh <<EOF