Next batch of tweaks
[vsys.git] / directfifowatcher.ml
1 (** directfifowatcher.ml: Routines to handle non-persistent scripts *)
2 (* Semantics:
3  *      - The 'out' descriptor must be opened first
4  *      - As soon as the backend script dies, the connection to the entry is
5  *      closed.
6  *)
7
8 open Inotify
9 open Unix
10 open Globals
11 open Dirwatcher
12 open Printf
13 open Splice
14
15 let backend_prefix = ref ""
16 let direct_fifo_table: (string,(string*string) option) Hashtbl.t = Hashtbl.create 1024
17
18 let rec list_check lst elt =
19   match lst with
20     | [] -> false
21     | car::cdr -> if (car==elt) then true else list_check cdr elt
22
23 (* vsys is activated when a client opens an in file *)
24 let connect_file mask_events fqp_out =
25   (* Do we care about this file? *)
26   let entry_info = try
27     Hashtbl.find direct_fifo_table fqp_out with _ -> None in
28     match entry_info with
29       | Some(execpath,slice_name) ->
30           fprintf logfd "Executing %s for slice %s\n" execpath slice_name;flush logfd;
31           begin
32             let len = String.length fqp_out in
33             let fqp = String.sub fqp_out 0 (len-4) in
34               mask_events true;
35             let fqp_in = String.concat "." [fqp;"in"] in
36             let fifo_fdin =
37               try openfile fqp_in [O_RDONLY;O_NONBLOCK] 0o777 with
38                   e->fprintf logfd "Error opening and connecting FIFO: %s\n" fqp_in;flush logfd;raise e
39             in
40             let fifo_fdout =
41               try openfile fqp_out [O_WRONLY;O_NONBLOCK] 0o777 with
42                   _->fprintf logfd "%s Output pipe not open, using stdout in place of %s\n" slice_name fqp_out;flush logfd;stdout
43             in
44               try ignore(create_process execpath [|execpath;slice_name|] fifo_fdin fifo_fdout fifo_fdout); with e -> begin fprintf logfd "Error executing service: %s\n" execpath;flush logfd end;
45                 close fifo_fdin;
46                 close fifo_fdout;
47                 mask_events false;
48           end
49       | None -> ()
50
51
52 (** Make a pair of fifo entries *)
53 let mkentry fqp abspath perm uname = 
54   fprintf logfd "Making entry %s->%s\n" fqp abspath;flush logfd;
55   let fifoin=sprintf "%s.in" fqp in
56   let fifoout=sprintf "%s.out" fqp in
57     (try Unix.unlink fifoin with _ -> ());
58     (try Unix.unlink fifoout with _ -> ());
59     (try 
60        let infname =(sprintf "%s.in" fqp) in
61        let outfname =(sprintf "%s.out" fqp) in
62          Unix.mkfifo infname 0o666;
63          Unix.mkfifo outfname 0o666;
64          ( (* Make the user the owner of the pipes in a non-chroot environment *)
65            if (!Globals.nochroot) then
66              let pwentry = Unix.getpwnam uname in
67                Unix.chown infname pwentry.pw_uid pwentry.pw_gid; 
68                Unix.chown outfname pwentry.pw_uid pwentry.pw_gid
69          );
70          Success
71      with 
72          e->fprintf logfd "Error creating FIFO: %s->%s. May be something wrong at the frontend.\n" fqp fifoout;flush logfd;Failed)
73
74 (** Open fifos for a session. SHOULD NOt shutdown vsys if the fifos don't exist *)
75 let openentry fqp backend_spec =
76   let fqp_in = String.concat "." [fqp;"out"] in
77     Hashtbl.replace direct_fifo_table fqp_in (Some(backend_spec))
78
79 (** Close fifos that just got removed *)
80 let closeentry fqp =
81   let fqp_in = String.concat "." [fqp;"out"] in
82     Hashtbl.remove direct_fifo_table fqp_in
83
84 let direct_fifo_handler wd dirname evlist fname =
85   let mask_events flag =
86     if (flag) then Dirwatcher.mask_events wd else Dirwatcher.unmask_events wd
87   in
88   let is_event = list_check evlist in
89     if (is_event Open) then 
90       let fqp_out = String.concat "/" [dirname;fname] in
91         connect_file mask_events fqp_out
92
93 let add_dir_watch fqp =
94   Dirwatcher.add_watch fqp [S_Open] direct_fifo_handler
95
96 let del_dir_watch fqp =
97   (* XXX Dirwatcher.del_watch fqp *)
98   ()