···11+type t = Flag of int | And of t * t | Or of t * t | Not of t
22+33+let rec pp ppf = function
44+ | Flag s -> Fmt.string ppf (Config.to_string s)
55+ | And (e1, e2) -> Fmt.pf ppf "%a&%a" pp e1 pp e2
66+ | Or (e1, e2) -> Fmt.pf ppf "%a|%a" pp e1 pp e2
77+ | Not e1 -> Fmt.pf ppf "~%a" pp e1
88+99+let check_flag i t = Int.equal (t land i) i
1010+1111+let satisfies (expr : t) flags =
1212+ let rec loop = function
1313+ | Flag s -> check_flag s flags
1414+ | Not e -> not (loop e)
1515+ | And (e1, e2) -> loop e1 && loop e2
1616+ | Or (e1, e2) -> loop e1 || loop e2
1717+ in
1818+ loop expr
+20
lexer.mll
···11+{
22+open Parser
33+44+exception SyntaxError of string
55+}
66+77+let white = [' ' '\t']+
88+let id = ['a'-'z' 'A'-'Z' '_'] ['a'-'z' 'A'-'Z' '0'-'9' '_']*
99+1010+rule read =
1111+ parse
1212+ | white { read lexbuf }
1313+ | id as s { FLAG s }
1414+ | '(' { LPAREN }
1515+ | ')' { RPAREN }
1616+ | '&' { AND }
1717+ | '|' { OR }
1818+ | '~' { NOT }
1919+ | _ { raise (SyntaxError ("Unexpected char: " ^ Lexing.lexeme lexbuf)) }
2020+ | eof { EOF }
···11+%token <string> FLAG
22+%token LPAREN RPAREN
33+%token OR AND
44+%token NOT
55+%token EOF
66+%left OR
77+%left AND
88+%nonassoc NOT
99+1010+%start <Filter.t> filter
1111+%%
1212+1313+filter:
1414+ | f = expr; EOF { f }
1515+1616+expr:
1717+ | f = FLAG { Filter.Flag (Config.of_string f) }
1818+ | LPAREN; e = expr; RPAREN { e }
1919+ | e1 = expr; AND; e2 = expr { Filter.And (e1, e2) }
2020+ | e1 = expr; OR; e2 = expr { Filter.Or (e1, e2) }
2121+ | NOT; e = expr { Filter.Not e }
+88
spawn.ml
···11+open Eio_posix
22+open Eio.Std
33+44+type (_, _, _) Eio.Resource.pi +=
55+ | Posix_dir : ('t, 't -> Low_level.dir_fd, [> `Posix_dir ]) Eio.Resource.pi
66+77+let as_posix_dir (Eio.Resource.T (t, ops)) =
88+ match Eio.Resource.get_opt ops Posix_dir with
99+ | None -> None
1010+ | Some fn -> Some (fn t)
1111+1212+module Process_impl = struct
1313+ type t = Low_level.Process.t
1414+ type tag = [ `Generic | `Unix ]
1515+1616+ let pid = Low_level.Process.pid
1717+1818+ let await t =
1919+ match Eio.Promise.await @@ Low_level.Process.exit_status t with
2020+ | Unix.WEXITED i -> `Exited i
2121+ | Unix.WSIGNALED i -> `Signaled i
2222+ | Unix.WSTOPPED _ -> assert false
2323+2424+ let signal = Low_level.Process.signal
2525+end
2626+2727+let process =
2828+ let handler = Eio.Process.Pi.process (module Process_impl) in
2929+ fun proc -> Eio.Resource.T (proc, handler)
3030+3131+module T = struct
3232+ type t = unit
3333+3434+ external action_setuid : unit -> Eio_unix.Private.Fork_action.fork_fn
3535+ = "eio_unix_fork_setuid"
3636+3737+ let action_setuid = action_setuid ()
3838+3939+ let setuid (uid : int) =
4040+ Eio_unix.Private.Fork_action.
4141+ { run = (fun k -> k (Obj.repr (action_setuid, uid))) }
4242+4343+ external action_setcgroup : unit -> Eio_unix.Private.Fork_action.fork_fn
4444+ = "eio_unix_fork_setcgroup"
4545+4646+ let action_setcgroup = action_setcgroup ()
4747+4848+ let setcgroup group =
4949+ Eio_unix.Private.Fork_action.
5050+ { run = (fun k -> k (Obj.repr (action_setcgroup, group))) }
5151+5252+ let spawn_unix () ~group ~uid ~sw ?cwd ~env ~fds ~executable args =
5353+ let actions =
5454+ Low_level.Process.Fork_action.
5555+ [ inherit_fds fds; execve executable ~argv:(Array.of_list args) ~env ]
5656+ in
5757+ let actions =
5858+ match uid with None -> actions | Some uid -> setuid uid :: actions
5959+ in
6060+ let actions =
6161+ match group with None -> actions | Some g -> setcgroup g :: actions
6262+ in
6363+ let with_actions cwd fn =
6464+ match cwd with
6565+ | None -> fn actions
6666+ | Some ((dir, path) : Eio.Fs.dir_ty Eio.Path.t) -> (
6767+ match as_posix_dir dir with
6868+ | None -> Fmt.invalid_arg "cwd is not an OS directory!"
6969+ | Some dirfd ->
7070+ Switch.run ~name:"spawn_unix" @@ fun launch_sw ->
7171+ let cwd =
7272+ Low_level.openat ~sw:launch_sw ~mode:0 dirfd path
7373+ Low_level.Open_flags.(rdonly + directory)
7474+ in
7575+ fn (Low_level.Process.Fork_action.fchdir cwd :: actions))
7676+ in
7777+ with_actions cwd @@ fun actions ->
7878+ process (Low_level.Process.spawn ~sw actions)
7979+end
8080+8181+let make_process group uid =
8282+ let module T = struct
8383+ type t = unit
8484+8585+ let spawn_unix = T.spawn_unix ~group ~uid
8686+ end in
8787+ let h = Eio_unix.Process.Pi.mgr_unix (module Eio_unix.Process.Make_mgr (T)) in
8888+ Eio.Resource.T ((), h)