12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970typec_action=Obj.ttypet={run:'a.((c_action->'a)->'a)}[@@unboxed](* A [fork_fn] is a C function that can be executed after forking. It cannot call OCaml code or
run the OCaml GC. It is passed a [Unix.file_descr] for errors and a pointer
to a [c_action]. On success it should write nothing to the error stream and
return 0. On error, it should write a message to the error FD and return a
non-zero value for the exit status (e.g. 1). *)typefork_fnletrecwith_actionsactionsfn=matchactionswith|[]->fn[]|{run}::xs->run@@func_action->with_actionsxs@@func_actions->fn(c_action::c_actions)typec_arrayexternalmake_string_array:int->c_array="eio_unix_make_string_array"externalaction_execve:unit->fork_fn="eio_unix_fork_execve"letaction_execve=action_execve()letexecvepath~argv~env=letargv_c_array=make_string_array(Array.lengthargv)inletenv_c_array=make_string_array(Array.lengthenv)in{run=funk->k(Obj.repr(action_execve,path,argv_c_array,argv,env_c_array,env))}externalaction_chdir:unit->fork_fn="eio_unix_fork_chdir"letaction_chdir=action_chdir()letchdirpath={run=funk->k(Obj.repr(action_chdir,path))}externalaction_fchdir:unit->fork_fn="eio_unix_fork_fchdir"letaction_fchdir=action_fchdir()letfchdirfd={run=funk->Fd.use_exn"fchdir"fd@@funfd->k(Obj.repr(action_fchdir,fd))}letint_of_fd:Unix.file_descr->int=Obj.magictypeaction=Inherit_fds.action={src:int;dst:int}letrecwith_fdsmappingk=matchmappingwith|[]->k[]|(dst,src,_)::xs->Fd.use_exn"inherit_fds"src@@funsrc->with_fdsxs@@funxs->k((dst,int_of_fdsrc)::xs)typeblocking=[|`Blocking|`Nonblocking|`Preserve_blocking]externalaction_dups:unit->fork_fn="eio_unix_fork_dups"letaction_dups=action_dups()letinherit_fdsm=letblocking=m|>List.filter_map(fun(dst,_,flags)->matchflagswith|`Blocking->Some(dst,true)|`Nonblocking->Some(dst,false)|`Preserve_blocking->None)inwith_fdsm@@funm->letplan:actionlist=Inherit_fds.planmin{run=funk->k(Obj.repr(action_dups,plan,blocking))}