Shells in OCaml
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Missing commands

Slightly better handling of missing commands, could still be a little
better. Especially about when we print the error message.

+62 -40
+33 -34
src/lib/eval.ml
··· 219 219 { ctx with last_background_process = string_of_int (E.pid process) } 220 220 else ctx 221 221 in 222 - let on_process ~async process ctx = 223 - clear_local_state ctx |> set_last_background ~async process 222 + let on_process ?process ~async ctx = 223 + let ctx = clear_local_state ctx in 224 + match process with 225 + | None -> ctx 226 + | Some process -> set_last_background ~async process ctx 224 227 in 225 228 let handle_job ~pgid j p = 226 229 match (j, p) with ··· 228 231 Option.some @@ J.make ~state:`Running pgid (Nlist.Singleton p) 229 232 | Some j, `Process p -> Option.some @@ J.add_process p j 230 233 | Some j, `Built_in p -> Option.some @@ J.add_built_in p j 234 + | Some j, `Error p -> Option.some @@ J.add_error p j 235 + in 236 + let exec_process ctx job ?fds ?stdin ?stdout ~pgid args = 237 + let process = 238 + E.exec ctx.executor ?fds ?stdin ?stdout ~pgid ~mode 239 + ~cwd:(cwd_of_ctx ctx) 240 + ~env:(get_env ~extra:ctx.local_state ()) 241 + args 242 + in 243 + match process with 244 + | Error (n, _) -> 245 + let job = handle_job ~pgid job (`Error n) in 246 + (on_process ~async ctx, job) 247 + | Ok process -> 248 + let job = handle_job ~pgid job (`Process process) in 249 + (on_process ~async ~process ctx, job) 231 250 in 232 251 let rec loop (ctx : ctx) (job : J.t option) 233 252 ((pgid, stdout_of_previous) : ··· 266 285 handle_word_components_to_string ctx executable 267 286 in 268 287 let ctx, job = 269 - let process = 270 - E.exec ctx.executor ?stdout:some_write ~pgid ~mode 271 - ~cwd:(cwd_of_ctx ctx) 272 - ~env:(get_env ~extra:ctx.local_state ()) 273 - [ executable ] 274 - in 275 - let job = handle_job ~pgid job (`Process process) in 276 - (on_process ~async process ctx, job) 288 + exec_process ctx job ?stdout:some_write ~pgid [ executable ] 277 289 in 278 290 Option.iter Eio.Flow.close some_write; 279 291 loop ctx job (pgid, some_read) rest ··· 282 294 handle_word_components_to_string ctx executable 283 295 in 284 296 let ctx, job = 285 - let process = 286 - E.exec ctx.executor ~stdin:stdout ~pgid ~mode 287 - ?stdout:some_write 288 - ~env:(get_env ~extra:ctx.local_state ()) 289 - ~cwd:(cwd_of_ctx ctx) [ executable ] 290 - in 291 - let job = handle_job ~pgid job (`Process process) in 292 - (on_process ~async process ctx, job) 297 + exec_process ctx job ~stdin:stdout ?stdout:some_write ~pgid 298 + [ executable ] 293 299 in 294 300 Option.iter Eio.Flow.close some_write; 295 301 loop ctx job (pgid, some_read) rest)) ··· 328 334 handle_word_components_to_string ctx executable 329 335 in 330 336 let ctx, job = 331 - let process = 332 - E.exec ctx.executor ?stdout:some_write ~pgid ~mode 333 - ~fds:redirect ~cwd:(cwd_of_ctx ctx) 334 - ~env:(get_env ~extra:ctx.local_state ()) 335 - (executable :: args) 336 - in 337 - let job = handle_job ~pgid job (`Process process) in 338 - (on_process ~async process ctx, job) 337 + exec_process ctx job ~fds:redirect ?stdout:some_write ~pgid 338 + (executable :: args) 339 339 in 340 340 Option.iter Eio.Flow.close some_write; 341 341 loop ctx job (pgid, some_read) rest ··· 344 344 handle_word_components_to_string ctx executable 345 345 in 346 346 let ctx, job = 347 - let process = 348 - E.exec ctx.executor ~stdin:stdout ~pgid ~mode 349 - ?stdout:some_write ~fds:redirect 350 - ~env:(get_env ~extra:ctx.local_state ()) 351 - ~cwd:(cwd_of_ctx ctx) (executable :: args) 352 - in 353 - let job = handle_job ~pgid job (`Process process) in 354 - (on_process ~async process ctx, job) 347 + exec_process ctx job ~fds:redirect ~stdin:stdout 348 + ?stdout:some_write ~pgid (executable :: args) 355 349 in 356 350 Option.iter Eio.Flow.close some_write; 357 351 loop ctx job (pgid, some_read) rest)) ··· 376 370 E.exec ~mode:(Types.Switched ghost_switch) ~pgid:0 377 371 ~cwd:(cwd_of_ctx initial_ctx) initial_ctx.executor 378 372 [ "sleep"; "99999999" ] 373 + |> function 374 + | Ok p -> p 375 + | Error (n, `Not_found) -> 376 + Fmt.epr "Interal error ghost process: not found"; 377 + exit n 379 378 in 380 379 loop initial_ctx None (E.pid ghost_process, None) p 381 380 in
+10 -2
src/lib/job.ml
··· 5 5 state : [ `Running ]; 6 6 id : int; 7 7 (* Process list is in reverse order *) 8 - processes : [ `Process of E.process | `Built_in of unit Exit.t ] Nlist.t; 8 + processes : 9 + [ `Process of E.process | `Built_in of unit Exit.t | `Error of int ] 10 + Nlist.t; 9 11 } 10 12 11 13 let make ?(state = `Running) id processes = { state; id; processes } ··· 15 17 16 18 let add_built_in b t = 17 19 { t with processes = Nlist.cons (`Built_in b) t.processes } 20 + 21 + let add_error b t = { t with processes = Nlist.cons (`Error b) t.processes } 18 22 19 23 (* Section 2.9.2 https://pubs.opengroup.org/onlinepubs/9799919799/ *) 20 24 let await_exit ~pipefail t = 21 - let await = function `Process p -> E.await p | `Built_in b -> b in 25 + let await = function 26 + | `Process p -> E.await p 27 + | `Built_in b -> b 28 + | `Error n -> Exit.nonzero () n 29 + in 22 30 match pipefail with 23 31 | false -> await (Nlist.hd t.processes) 24 32 | _ -> Fmt.failwith "TODO: pipefail"
+8 -3
src/lib/posix/merry_posix.ml
··· 16 16 | `Signaled n -> Merry.Exit.nonzero () n 17 17 18 18 let exec ?(fork_actions = []) ?(fds = []) ?stdin ?stdout ?stderr ?env ~mode 19 - ~pgid ~cwd t args : process = 19 + ~pgid ~cwd t args = 20 20 let env = 21 21 Option.map 22 22 (fun lst -> List.map (fun (a, b) -> a ^ "=" ^ b) lst |> Array.of_list) 23 23 env 24 24 in 25 - Exec.run ~fork_actions ~mode ~fds ~pgid ~cwd ?stdin ?stdout ?stderr ?env t 26 - args 25 + try 26 + Ok 27 + (Exec.run ~fork_actions ~mode ~fds ~pgid ~cwd ?stdin ?stdout ?stderr 28 + ?env t args) 29 + with Eio.Io (Eio.Process.E (Eio.Process.Executable_not_found m), _ctx) -> 30 + Fmt.epr "msh: command not found: %s\n%!" m; 31 + Error (127, `Not_found) 27 32 end
+1 -1
src/lib/types.ml
··· 64 64 cwd:Eio.Fs.dir_ty Eio.Path.t -> 65 65 t -> 66 66 string list -> 67 - process 67 + (process, int * [ `Not_found ]) result 68 68 (** Run a command in a child process *) 69 69 70 70 val await : process -> unit Exit.t
+10
test/simple.t
··· 61 61 $ msh test.sh 62 62 hello 63 63 64 + $ msh -c "lssssss" 65 + msh: command not found: lssssss 66 + [127] 67 + $ sh -c "lssssss | echo 'all good'" 68 + all good 69 + sh: line 1: lssssss: command not found 70 + $ msh -c "lssssss | echo 'all good'" 71 + msh: command not found: lssssss 72 + all good 73 + 64 74 2.2 Simple And 65 75 66 76 $ cat >test.sh <<EOF