Copying latest tagged version into 0.7. This should add sanity to my deployments...
authorSapan Bhatia <sapanb@cs.princeton.edu>
Thu, 7 Aug 2008 17:18:51 +0000 (17:18 +0000)
committerSapan Bhatia <sapanb@cs.princeton.edu>
Thu, 7 Aug 2008 17:18:51 +0000 (17:18 +0000)
this
will be the stable branch.

30 files changed:
.dep
Makefile
backend.ml
conffile.ml
directfifowatcher.ml [new file with mode: 0644]
dirwatcher.ml
factory/comon_exec [new file with mode: 0755]
factory/hide_netif [new file with mode: 0755]
factory/pfmount [new file with mode: 0755]
factory/pl-ps [new file with mode: 0755]
factory/setup-link [new file with mode: 0755]
factory/setup-nat [new file with mode: 0755]
factory/vtop [new file with mode: 0755]
fdwatcher.ml
fifowatcher.ml
frontend.ml
globals.ml
inotify_stubs.o [deleted file]
main.ml
ocaml_inotify-0.4/Makefile
splice.ml [new file with mode: 0644]
splice_stub.c [new file with mode: 0644]
tests/vsys-test.txt [new file with mode: 0644]
tests/vsys_conctest.c [new file with mode: 0644]
tests/vsys_launch.pl [new file with mode: 0644]
vsys-initscript
vsys.conf [new file with mode: 0644]
vsys.logrotate [new file with mode: 0644]
vsys.spec
vsyssh/vsyssh.c

diff --git a/.dep b/.dep
index 3ec5199..60ed53b 100644 (file)
--- a/.dep
+++ b/.dep
@@ -1,12 +1,22 @@
+backend.cmo: inotify.cmi globals.cmo frontend.cmo fifowatcher.cmo \
+    dirwatcher.cmo 
+backend.cmx: inotify.cmi globals.cmx frontend.cmx fifowatcher.cmx \
+    dirwatcher.cmx 
+conffile.cmo: globals.cmo 
+conffile.cmx: globals.cmx 
+directfifowatcher.cmo: splice.cmo inotify.cmi globals.cmo dirwatcher.cmo 
+directfifowatcher.cmx: splice.cmx inotify.cmi globals.cmx dirwatcher.cmx 
 dirwatcher.cmo: inotify.cmi globals.cmo fdwatcher.cmo 
 dirwatcher.cmx: inotify.cmi globals.cmx fdwatcher.cmx 
 fdwatcher.cmo: globals.cmo 
 fdwatcher.cmx: globals.cmx 
-fifowatcher.cmo: inotify.cmi globals.cmo fdwatcher.cmo dirwatcher.cmo 
-fifowatcher.cmx: inotify.cmi globals.cmx fdwatcher.cmx dirwatcher.cmx 
-frontend.cmo: globals.cmo fifowatcher.cmo 
-frontend.cmx: globals.cmx fifowatcher.cmx 
+fifowatcher.cmo: splice.cmo inotify.cmi globals.cmo fdwatcher.cmo \
+    dirwatcher.cmo 
+fifowatcher.cmx: splice.cmx inotify.cmi globals.cmx fdwatcher.cmx \
+    dirwatcher.cmx 
+frontend.cmo: globals.cmo directfifowatcher.cmo 
+frontend.cmx: globals.cmx directfifowatcher.cmx 
 main.cmo: inotify.cmi globals.cmo frontend.cmo fifowatcher.cmo fdwatcher.cmo \
-    dirwatcher.cmo backend.cmo 
+    dirwatcher.cmo conffile.cmo backend.cmo 
 main.cmx: inotify.cmi globals.cmx frontend.cmx fifowatcher.cmx fdwatcher.cmx \
-    dirwatcher.cmx backend.cmx 
+    dirwatcher.cmx conffile.cmx backend.cmx 
index 65e5736..b5272ca 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -30,11 +30,14 @@ docs: *.ml
 ocaml_inotify-0.4/inotify.cmxa:
        $(MAKE) -C ocaml_inotify-0.4 && cp -f ocaml_inotify-0.4/inotify_stubs.o ./
 
-vsys: ocaml_inotify-0.4/inotify.cmxa globals.cmx fdwatcher.cmx conffile.cmx dirwatcher.cmx fifowatcher.cmx frontend.cmx backend.cmx main.cmx docs
-       ocamlopt -I ocaml_inotify-0.4 str.cmxa unix.cmxa inotify.cmxa globals.cmx fdwatcher.cmx dirwatcher.cmx fifowatcher.cmx frontend.cmx backend.cmx str.cmxa conffile.cmx main.cmx -o vsys
+splice_stub.o: splice_stub.c
+       gcc -c -I /usr/lib/ocaml -I /usr/lib64/ocaml splice_stub.c -o splice_stub.o
 
-vsys.b: inotify.cma inotify.cmi globals.ml fdwatcher.ml dirwatcher.ml fifowatcher.ml frontend.ml backend.ml main.ml
-       ocamlc -g str.cma unix.cma inotify.cma globals.cmo fdwatcher.cmo dirwatcher.cmo fifowatcher.cmo frontend.cmo backend.cmo str.cma main.cmo -o vsys.b
+vsys: ocaml_inotify-0.4/inotify.cmxa globals.cmx fdwatcher.cmx conffile.cmx splice_stub.o splice.cmx dirwatcher.cmx fifowatcher.cmx frontend.cmx backend.cmx main.cmx docs 
+       ocamlopt -I ocaml_inotify-0.4 str.cmxa unix.cmxa inotify.cmxa globals.cmx fdwatcher.cmx dirwatcher.cmx splice.cmx splice_stub.o directfifowatcher.cmx frontend.cmx backend.cmx str.cmxa conffile.cmx main.cmx -o vsys
+
+vsys.b: ocaml_inotify-0.4/inotify.cma inotify.cmi globals.ml fdwatcher.ml dirwatcher.ml directfifowatcher.ml frontend.ml backend.ml main.ml
+       ocamlc -g str.cma unix.cma ocaml_inotify-0.4/inotify.cma globals.cmo fdwatcher.cmo dirwatcher.cmo directfifowatcher.cmo frontend.cmo backend.cmo str.cma conffile.cmo main.cmo -o vsys.b
 
 install: vsys
        cp vsys $(INSTALL_DIR)/usr/bin
index 2f373c0..535c549 100644 (file)
@@ -15,10 +15,6 @@ open Fifowatcher
 open Frontend
 open Printf
 
-(** Helper functions:
-
-*)
-
 (** Turn an absolute path into a relative path. *)
 let delete_prefix prefix str =
   let len = String.length str in
@@ -35,7 +31,6 @@ let rec list_check lst elt =
     | [] -> false
     | car::cdr -> if (car==elt) then true else list_check cdr elt
 
-
 (** The backendhandler class: defines event handlers for events in
 the backend backend directory.
   @param dir_root The location of the backend in the server context (eg. root context for vservers)
@@ -45,34 +40,30 @@ class backendHandler dir_root (frontend_lst: frontendHandler list) =
    let mk_rel_path = delete_prefix dir_root in object(this)
 
      (** Regular expression that defines a legal script name. Filter out
-       * temporary files using this *)
-     val file_regexp = Str.regexp "[a-zA-Z][a-zA-Z0-9_\.]*"
+       * temporary files using it *)
+     val file_regexp = Str.regexp "^[a-zA-Z][a-zA-Z0-9_\.\-]*$"
      val acl_file_regexp = Str.regexp ".*acl$"
 
-     val dir_regexp = Str.regexp "^dir_";
-     val acl_regexp = Str.regexp ".*_.*";
-
      (** Somebody created a new directory *)
-     (* XXX Race condition here *)
      method private new_dir slice_list fqp func =
        let s = Unix.stat fqp in
          List.iter 
            (fun frontend->
               try begin 
                 frontend#mkdir (mk_rel_path fqp) (s.st_perm);
-                Dirwatcher.add_watch fqp [S_Create;S_Delete] (Some(func)) 
+                Dirwatcher.add_watch fqp [S_Create;S_Delete] func 
               end
               with _ ->
-                printf "Could not create %s. Looks like a slice shot itself in the foot\n" fqp;flush Pervasives.stdout;
+                logprint "Could not create %s. Looks like a slice shot itself in the foot\n" fqp;
            )
            slice_list
 
      (** Somebody copied in a new script *)
-     (* XXX Race condition here *)
      method private new_script slice_list fqp =
        let s = Unix.stat fqp in
          List.iter (fun frontend->
-                      frontend#mkentry (mk_rel_path fqp) fqp (s.st_perm)) slice_list 
+                      frontend#mkentry (mk_rel_path fqp) fqp (s.st_perm)) 
+                   slice_list 
 
      method private make_filter acl_fqp =
        let filter = Hashtbl.create 16 in
@@ -84,7 +75,7 @@ class backendHandler dir_root (frontend_lst: frontendHandler list) =
              with _ -> None
            in
              match next_item with
-               | None -> cur_filter
+               | None -> close_in acl_file;cur_filter
                | Some(item) -> 
                    Hashtbl.add cur_filter item true;
                    read_acl cur_filter
@@ -93,12 +84,14 @@ class backendHandler dir_root (frontend_lst: frontendHandler list) =
        with _ ->
          None
 
+     method is_acl fname = Str.string_match acl_file_regexp fname 0
+
      (** Gets called every time there's an inotify event at the backend 
        @param dirname Name of the backend directory
        @param evlist Description of what happened
        @param fname Name of the file that the event applies to
      *)
-     method handle_dir_event dirname evlist fname = 
+     method handle_dir_event dirname evlist fname = 
        let fqp = String.concat "/" [dirname;fname] in
          if ((Str.string_match file_regexp fname 0) && not (Str.string_match acl_file_regexp fname 0)) then  
            begin
@@ -107,8 +100,10 @@ class backendHandler dir_root (frontend_lst: frontendHandler list) =
              let acl_filter = this#make_filter acl_fqp in
              let slice_list = 
                match acl_filter with
-                 | None -> frontend_lst 
-                 | Some(filter) -> List.filter (fun fe->Hashtbl.mem filter (fe#get_slice_name ())) frontend_lst 
+                 | None -> [] (* No ACL *) 
+                 | Some(filter) -> List.filter 
+                                     (fun fe->Hashtbl.mem filter (fe#get_slice_name ())) 
+                                     frontend_lst 
              in 
              let is_event = list_check evlist in
                if (is_event Create) then
@@ -120,13 +115,6 @@ class backendHandler dir_root (frontend_lst: frontendHandler list) =
                    else
                      (* It's a new script *)
                      begin
-                       (*
-                        if (Str.string_match dir_regexp fname 0) then
-                        let fqp = String.concat "/" [dirname;String.sub fname 4 ((String.length fname)-4+1)]  in 
-                        let real_fqp = String.concat "/" [dirname;fname]  in 
-                        this#new_dir fqp this#handle_spool_event;
-                        Hashtbl.add spools fqp real_fqp
-                        else*)
                        this#new_script slice_list fqp
                      end
                  end
@@ -143,7 +131,7 @@ class backendHandler dir_root (frontend_lst: frontendHandler list) =
                  end
            end
          else (* regex not matched *)
-           ()
+           fprintf logfd "Rejected weird entry %s\n" fname
 
      (** Initializer - build the initial tree based on the contents of /vsys *)
      initializer 
@@ -152,33 +140,38 @@ class backendHandler dir_root (frontend_lst: frontendHandler list) =
        let cont = ref true in
          while (!cont) do
            try 
-             let curfile = readdir dir_handle  in
-             let fqp = String.concat "/" [dir;curfile] in
-             let acl_fqp = String.concat "." [fqp;"acl"] in
-             let acl_filter = this#make_filter acl_fqp in
-             let slice_list = 
-               match acl_filter with
-                 | None -> frontend_lst 
-                 | Some(filter) -> List.filter (fun fe->Hashtbl.mem filter (fe#get_slice_name ())) frontend_lst 
-             in
-               if (Str.string_match file_regexp curfile 0 && not (Str.string_match acl_file_regexp curfile 0)) then
-                 let s = Unix.stat fqp in
-                   begin
-                     match s.st_kind with
-                       | S_DIR ->
-                           this#new_dir slice_list fqp this#handle_dir_event;
-                           build_initial_tree fqp;
-                       | S_REG ->
-                           this#new_script slice_list fqp
-                       | _ ->
-                           printf "Don't know what to do with %s\n" curfile;flush Pervasives.stdout
-                   end
-           with 
-               _->cont:=false;()
+             let curfile = readdir dir_handle in
+               if (not (this#is_acl curfile)) then
+                 begin
+                   let fqp = String.concat "/" [dir;curfile] in
+                   let acl_fqp = String.concat "." [fqp;"acl"] in
+                   let acl_filter = this#make_filter acl_fqp in
+                   let slice_list = 
+                     match acl_filter with
+                       | None -> [] (*frontend_lst -> No ACL => No Show *)
+                       | Some(filter) -> List.filter 
+                                           (fun fe->Hashtbl.mem filter (fe#get_slice_name ())) 
+                                           frontend_lst 
+                   in
+                     if (Str.string_match file_regexp curfile 0) then
+                       let s = Unix.stat fqp in
+                         begin
+                           match s.st_kind with
+                             | S_DIR ->
+                                 this#new_dir slice_list fqp this#handle_dir_event;
+                                 build_initial_tree fqp;
+                             | S_REG ->
+                                 this#new_script slice_list fqp
+                             | _ ->
+                                 logprint "Don't know what to do with %s\n" curfile
+                         end
+                 end
+           with _
+           ->cont:=false;()
          done 
      in
        begin
          build_initial_tree dir_root;
-         Dirwatcher.add_watch dir_root [S_Create;S_Delete] (Some(this#handle_dir_event));
+         Dirwatcher.add_watch dir_root [S_Create;S_Delete] (this#handle_dir_event);
        end
    end
index d7b8715..0d0f0f1 100644 (file)
@@ -1,17 +1,37 @@
 open Printf
+open Globals
 open Scanf
 
 let split_conf_line s =
   sscanf s "%s %s" (fun s1 s2->(s1,s2))
 
+let check_dir fe = 
+  let (vsysdir,slice) = fe in
+  let verdict = try Some(Unix.stat vsysdir) with
+      _ -> logprint "vsys directory not setup for slice %s\n" slice;None
+  in
+    match verdict with 
+      | None->false 
+      | Some(_) -> true
+
+let rec in_list elt lst =
+  match lst with 
+    | car::cdr ->
+        if (elt = car) then true else in_list elt cdr
+    | [] -> false
+
 let read_frontends f =
-  let f_file = try open_in f with e -> printf "Could not open config
-                                         file\n";flush Pervasives.stdout;raise e
+  let setup_ok = if (!Globals.failsafe) then check_dir else fun _ -> true in
+  let f_file = try open_in f with e -> logprint "Could not open config file\n";raise e
   in
   let rec read_conf_file cur_list =
     let next_line = try Some(input_line f_file) with _ -> None in
       match next_line with
-        | Some(inp_line) -> read_conf_file (split_conf_line(inp_line)::cur_list)
+        | Some(inp_line) -> 
+            let fe = split_conf_line inp_line in
+            let new_list = if (not (in_list fe cur_list) && (setup_ok(fe))) then (fe::cur_list) else cur_list
+            in
+            read_conf_file new_list
         | None -> cur_list
   in
     read_conf_file []
diff --git a/directfifowatcher.ml b/directfifowatcher.ml
new file mode 100644 (file)
index 0000000..e97d7c5
--- /dev/null
@@ -0,0 +1,167 @@
+(** directfifowatcher.ml: Routines to handle non-persistent scripts *)
+(* Semantics:
+ *      - The 'out' descriptor must be opened first
+ *      - As soon as the backend script dies, the connection to the entry is
+ *      closed.
+ *      - To avoid user-inflicted pain, all entries are opened at the time
+ *      that they are created. Reopening these entries is a little complicated
+ *      but nevertheless sound:
+ *              * When a script dies, its fd is reopened
+ *              * If a script fails to execute, its fd is closed and reopened to
+ *              beat a race that can happen when the user closes the connection
+ *              before the script can be launched.
+ *)
+
+open Inotify
+open Unix
+open Globals
+open Dirwatcher
+open Printf
+open Splice
+
+let close_if_open fd = (try (ignore(close fd);) with _ -> ())
+
+type in_pathname = string
+type directory = string
+type base_pathname = string
+type slice_name = string
+
+let direct_fifo_table: (in_pathname,(directory*base_pathname*slice_name*Unix.file_descr) option) Hashtbl.t = 
+  Hashtbl.create 1024
+
+let pidmap: (int,in_pathname * Unix.file_descr) Hashtbl.t = Hashtbl.create 1024
+
+let move_gate fname =
+  let tmpfname=String.concat "." [fname;"tmp"] in 
+    Unix.rename fname tmpfname;
+    tmpfname
+
+let move_ungate fname restore =
+  Unix.rename restore fname
+
+let list_check lst elt _ =
+  let rec list_check_rec lst = 
+    match lst with
+      | [] -> false
+      | car::cdr -> 
+          if (car==elt) then
+               true
+          else
+            list_check_rec cdr
+  in
+    list_check_rec lst
+
+let openentry_int fifoin =
+  let fdin =
+    try openfile fifoin [O_RDONLY;O_NONBLOCK] 0o777 with 
+        e->logprint "Error opening and connecting FIFO: %s,%o\n" fifoin 0o777;raise e
+  in
+    fdin
+
+(** Open entry safely, by first masking out the file to be opened *)
+let openentry_safe root_dir fqp_in backend_spec =
+  let restore = move_gate fqp_in in
+  let fd_in = openentry_int restore in
+    move_ungate fqp_in restore;
+    let (fqp,slice_name) = backend_spec in
+      Hashtbl.replace direct_fifo_table fqp_in (Some(root_dir,fqp,slice_name,fd_in))
+
+let openentry root_dir fqp backend_spec =
+  let fqp_in = String.concat "." [fqp;"in"] in
+    openentry_safe root_dir fqp_in backend_spec
+
+let reopenentry fifoin =
+  let entry = try Hashtbl.find direct_fifo_table fifoin with _ -> None in
+    match entry with
+      | Some(dir, fqp,slice_name,fd) -> close_if_open fd;openentry_safe dir fifoin (fqp,slice_name)
+      | None -> ()
+
+(* vsys is activated when a client opens an in file *)
+let connect_file fqp_in =
+  (* Do we care about this file? *)
+  let entry_info = try
+    Hashtbl.find direct_fifo_table fqp_in with _ -> None in
+    match entry_info with
+      | Some(_,execpath,slice_name,fifo_fdin) ->
+          begin
+            let len = String.length fqp_in in
+            let fqp = String.sub fqp_in 0 (len-3) in
+            let fqp_out = String.concat "." [fqp;"out"] in
+            let fifo_fdout =
+              try openfile fqp_out [O_WRONLY;O_NONBLOCK] 0o777 with
+                  _-> (* The client is opening the descriptor too fast *)
+                    sleep 1;try openfile fqp_out [O_WRONLY;O_NONBLOCK] 0o777 with
+                        _->
+                        logprint "%s Output pipe not open, using stdout in place of %s\n" slice_name fqp_out;stdout
+            in
+              ignore(sigprocmask SIG_BLOCK [Sys.sigchld]);
+              (
+                clear_nonblock fifo_fdin;
+                let pid=try Some(create_process execpath [|execpath;slice_name|] fifo_fdin fifo_fdout fifo_fdout) with e -> None in
+                  match pid with 
+                    | Some(pid) ->
+                        if (fifo_fdout <> stdout) then close_if_open fifo_fdout;
+                        Hashtbl.add pidmap pid (fqp_in,fifo_fdout)
+                    | None ->logprint "Error executing service: %s\n" execpath;reopenentry fqp_in
+              );
+              ignore(sigprocmask SIG_UNBLOCK [Sys.sigchld]);
+          end
+      | None -> ()
+
+
+(** Make a pair of fifo entries *)
+let mkentry fqp abspath perm uname = 
+  logprint "Making entry %s->%s\n" fqp abspath;
+  let fifoin=sprintf "%s.in" fqp in
+  let fifoout=sprintf "%s.out" fqp in
+    (try Unix.unlink fifoin with _ -> ());
+    (try Unix.unlink fifoout with _ -> ());
+    (try 
+       let infname =(sprintf "%s.in" fqp) in
+       let outfname =(sprintf "%s.out" fqp) in
+         Unix.mkfifo infname 0o666;
+         Unix.mkfifo outfname 0o666;
+         ( (* Make the user the owner of the pipes in a non-chroot environment *)
+           if (!Globals.nochroot) then
+             let pwentry = Unix.getpwnam uname in
+               Unix.chown infname pwentry.pw_uid pwentry.pw_gid; 
+               Unix.chown outfname pwentry.pw_uid pwentry.pw_gid
+         );
+         Success
+     with 
+         e->logprint "Error creating FIFO: %s->%s. May be something wrong at the frontend.\n" fqp fifoout;Failed)
+
+
+(** Close fifos that just got removed *)
+let closeentry fqp =
+  let fqp_in = String.concat "." [fqp;"in"] in
+  let entry = try Hashtbl.find direct_fifo_table fqp_in with Not_found -> None in
+    match entry with
+      | None -> ()
+      | Some(_,_,_,fd) -> 
+          close_if_open fd;
+          Hashtbl.remove direct_fifo_table fqp_in
+
+let sigchld_handle s =
+  let pid,_=Unix.waitpid [Unix.WNOHANG] 0 in
+    try
+      let fqp_in,fd_out = Hashtbl.find pidmap pid in
+        begin
+          reopenentry fqp_in
+        end
+    with _ -> ()
+
+let rec add_dir_watch fqp =
+  Dirwatcher.add_watch fqp [S_Open] direct_fifo_handler
+and
+    direct_fifo_handler wd dirname evlist fname =
+  let is_event = list_check evlist in
+    if (is_event Open Attrib) then 
+      let fqp_in = String.concat "/" [dirname;fname] in
+        connect_file fqp_in
+
+let del_dir_watch fqp =
+  ()
+
+let initialize () =
+  Sys.set_signal Sys.sigchld (Sys.Signal_handle sigchld_handle)
index b33b890..53c4c1c 100644 (file)
@@ -1,5 +1,5 @@
 (** Watches directories for events. Agnostic to vsys semantics of backends and
-frontends *)
+  frontends *)
 open Inotify
 open Fdwatcher
 open Printf
@@ -8,51 +8,65 @@ open Globals
 (* I don't know if a wd corresponding to a deleted directory is evicted or just
  * leaks - fix implementation of rmdir accordingly
  *)
-
 let wdmap = Hashtbl.create 1024
 
 let fd = Inotify.init ()
 
+let rec list_check lst elt =
+  match lst with
+    | [] -> false
+    | car::cdr -> if (car==elt) then true else list_check cdr elt
+
+let pevlist evlist =
+    List.iter 
+      (fun e -> 
+         logprint "Event: %s\n" (string_of_event e)) 
+      evlist
+
 let handle_dir_event dirname evlist str = 
-    let fname = String.concat "/" [dirname;str] in
-        printf "File: %s. " fname;List.iter 
-                  (fun e -> 
-                     printf "Event: %s\n" (string_of_event e)) 
-                  evlist;
-        flush Pervasives.stdout
+  let fname = String.concat "/" [dirname;str] in
+    logprint "File: %s. " fname;
+    pevlist evlist
 
 let add_watch dir events handler =
-  printf "Adding watch for %s\n" dir;flush Pervasives.stdout;
   let wd = Inotify.add_watch fd dir events in
-      Hashtbl.add wdmap wd (dir,handler)
+    Hashtbl.add wdmap wd (dir,Some(handler))
+      (* Ignore the possibility that the whole directory can disappear and come
+       * back while it is masked *)
 
 let asciiz s =
   let rec findfirstnul str idx len =
     if ((idx==len) || 
-      (str.[idx]==(char_of_int 0))) then idx
-      else
-        findfirstnul str (idx+1) len
+        (str.[idx]==(char_of_int 0))) then idx
+    else
+      findfirstnul str (idx+1) len
   in
   let nulterm = findfirstnul s 0 (String.length s) in
     String.sub s 0 nulterm
 
 let receive_event (eventdescriptor:fname_and_fd) (bla:fname_and_fd) =
   let (_,fd) = eventdescriptor in
-      let evs = Inotify.read fd in
-        List.iter (fun x->
-                match x with
-                  | (wd,evlist,_,Some(str)) ->
-                      let purestr = asciiz(str) in
-                      let (dirname,handler) = 
-                        try Hashtbl.find wdmap wd with Not_found->printf "Unknown watch descriptor\n";raise Not_found
-                      in
-                        (
-                        match handler with
-                          | None->handle_dir_event dirname evlist purestr
-                          | Some(handler)->handler dirname evlist purestr
-                        )
-                  | _ -> ()) 
-          evs
+  let evs = Inotify.read fd in
+    List.iter (fun x->
+                 match x with
+                   | (wd,evlist,_,Some(str)) ->
+                       begin
+                               let purestr = asciiz(str) in
+                               let (dirname,handler) = 
+                                 try Hashtbl.find wdmap wd with Not_found->("",None)
+                               in
+                                 match handler with
+                                   | None->
+                                       logprint "Unhandled watch descriptor\n"
+                                   | Some(handler)->
+                                       let fqp = String.concat "/" [dirname;purestr] in
+                                         begin
+                                         handler wd dirname evlist
+                                           purestr
+                                         end
+                       end
+                   | _ -> ()) 
+      evs
 
 let initialize () =
   Fdwatcher.add_fd (None,fd) (None,fd) receive_event
diff --git a/factory/comon_exec b/factory/comon_exec
new file mode 100755 (executable)
index 0000000..df6e7c0
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+use strict;
+
+#######################################################
+#
+# run any (allowed) progam in the root context
+#
+#######################################################
+
+my @allowed = ("/bin/df"); # allowed commands
+my $cmdline;
+my $path;
+my $p;
+
+# read command line
+$cmdline = <STDIN>;
+chomp($cmdline);
+
+# identify the path
+if ($cmdline =~ /\s*(.+)\s+/) {
+   $path = $1;
+} else {
+   $path = $cmdline;
+}
+
+# run the program if it's executable and allowed to run
+if (-x $path) {
+   foreach $p (@allowed) {
+       if ($p eq $path) {
+           system($cmdline);
+           exit(0);
+       }
+   }
+   print "fatal: '$cmdline' is not allowed to run\n";
+} else {
+   print "fatal: $path either does not exist or is not executable\n";
+}
+
+# some error occurred
+exit(-1);
diff --git a/factory/hide_netif b/factory/hide_netif
new file mode 100755 (executable)
index 0000000..c7ae234
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+# Remove hide_netif network attribute.  Attribute is used to hide interfaces that don't have an IP attached. 
+
+# $Id$
+
+nattribute --set --nid $1 --flag ~hide_netif
diff --git a/factory/pfmount b/factory/pfmount
new file mode 100755 (executable)
index 0000000..0282c76
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Mount the planetflow directory in a slice
+
+#mount --bind /usr/local/fprobe /vservers/$1/pf
+# changed from request of Faiyaz
+DEST="/vservers/$1/pf"
+mount | grep "on $DEST type" > /dev/null
+if [ $? -eq 1 ]; then
+    mount --bind /var/local/fprobe -o ro $DEST
+fi
diff --git a/factory/pl-ps b/factory/pl-ps
new file mode 100755 (executable)
index 0000000..eafdf5b
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+use strict;
+
+###############################################
+# pl-ps for slicestat by KyoungSoo Park
+###############################################
+
+my %slice_id;
+my %slice;
+
+open THIS_PIPE, "/bin/awk -F: \'{print \$1, \$3}\' /etc/passwd |";
+while(<THIS_PIPE>) {
+   if (/(.+)\s+(\d+)/) {
+       $slice_id{$1} = $2;
+       $slice{$2} = $1;
+   }
+}
+close THIS_PIPE;
+
+open THIS_PIPE, "/usr/sbin/vps -eo pid,user | sed 1d | awk \'{print \$1, \$2}\' | sort -k 2 |";
+while(<THIS_PIPE>) {
+   if (/(\d+)\s+(.+)$/) {
+       my $pid = $1;
+       my ($id, $sl);
+
+       if (defined($slice_id{$2})) {
+           $id = $slice_id{$2};
+           $sl = $2;
+       } else {
+           $id = $2;
+           $sl = $slice{$2};
+       }
+       print sprintf("%s %s %s\n", $id, $sl, $pid);
+   }
+}
+close THIS_PIPE;
diff --git a/factory/setup-link b/factory/setup-link
new file mode 100755 (executable)
index 0000000..e5cbd2f
--- /dev/null
@@ -0,0 +1,96 @@
+#!/bin/sh +x
+
+IP=/sbin/ip
+
+SLICE=$1
+SLICEID=`id -u $SLICE`
+read INDEX
+read REMOTE
+read KEY
+
+LINK=${KEY}if${INDEX}
+
+modprobe ip_gre
+modprobe etun
+
+### Setup EGRE tunnel
+EGRE=d$LINK
+$IP tunnel add $EGRE  mode gre/eth remote $REMOTE key $KEY
+$IP link set $EGRE up
+
+### Setup etun
+ETUN0=a$LINK
+ETUN1=b$LINK
+echo $ETUN0,$ETUN1 > /sys/module/etun/parameters/newif
+ifconfig $ETUN0 mtu 1458 up
+ifconfig $ETUN1 up
+
+### Setup bridge
+BRIDGE=c$LINK
+brctl addbr $BRIDGE
+brctl addif $BRIDGE $EGRE 
+brctl addif $BRIDGE $ETUN1
+ifconfig $BRIDGE up
+
+### Setup iptables so that packets are visible in the vserver
+iptables -t mangle -A FORWARD -o $BRIDGE -j MARK --set-mark $SLICEID
+
+### Create "grab link" script
+GRAB=/vsys/local_grab-$ETUN0
+echo $SLICE > $GRAB.acl 
+rm -f $GRAB
+cat > $GRAB <<EOF
+#!/bin/sh
+
+read PID
+
+chcontext --ctx 1 -- echo \$PID > /sys/class/net/$ETUN0/new_ns_pid 
+EOF
+chmod +x $GRAB
+
+### Create script for setting link rate
+BIND=/vsys/local_rate-$ETUN0
+echo $SLICE > $BIND.acl 
+rm -f $BIND
+cat > $BIND <<EOF
+#!/bin/sh
+
+read rt
+
+tc qdisc add dev $EGRE root handle 1: htb default 10
+tc class add dev $EGRE parent 1: classid 1:10 htb rate \$rt ceil \$rt
+
+rm -rf $BIND.acl 
+touch $BIND.acl 
+
+EOF
+chmod +x $BIND
+
+### Create "delete link" script
+DELETE=/vsys/local_delete-$ETUN0
+echo $SLICE > $DELETE.acl 
+rm -f $DELETE
+cat > $DELETE <<EOF
+#!/bin/sh
+
+read NULL
+
+# Remove iptables rule
+iptables -t mangle -D FORWARD -o $BRIDGE -j MARK --set-mark $SLICEID
+
+# Get rid of etun devices, only need name of one of them
+echo $ETUN1 > /sys/module/etun/parameters/delif
+
+# Get rid of bridge
+ifconfig $BRIDGE down
+brctl delbr $BRIDGE
+
+# Get rid of EGRE tunnel
+ip tunnel del $EGRE
+
+# Clean up files
+rm -f $GRAB $GRAB.acl
+rm -f $DELETE $DELETE.acl
+rm -f $BIND $BIND.acl
+EOF
+chmod +x $DELETE
diff --git a/factory/setup-nat b/factory/setup-nat
new file mode 100755 (executable)
index 0000000..64be40b
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/sh +x
+
+IP=/sbin/ip
+
+SLICE=$1
+SLICEID=`id -u $SLICE`
+read KEY
+
+modprobe etun
+
+### Setup etun
+ETUN0=nat$KEY
+ETUN1=natx$KEY
+echo $ETUN0,$ETUN1 > /sys/module/etun/parameters/newif
+ifconfig $ETUN1 10.0.$KEY.1 up
+
+/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
+/sbin/iptables -A FORWARD -i eth0 -o $ETUN1 -m state --state RELATED,ESTABLISHED -j ACCEPT
+/sbin/iptables -A FORWARD -i $ETUN1 -o eth0 -j ACCEPT
+
+### Create "grab link" script
+GRAB=/vsys/local_grab-$ETUN0
+echo $SLICE > $GRAB.acl 
+rm -f $GRAB
+cat > $GRAB <<EOF
+#!/bin/sh
+
+read PID
+
+chcontext --ctx 1 -- echo \$PID > /sys/class/net/$ETUN0/new_ns_pid 
+EOF
+chmod +x $GRAB
+
+### Create "delete link" script
+DELETE=/vsys/local_delete-$ETUN0
+echo $SLICE > $DELETE.acl 
+rm -f $DELETE
+cat > $DELETE <<EOF
+#!/bin/sh
+
+read NULL
+
+# Remove iptables rules
+/sbin/iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
+/sbin/iptables -D FORWARD -i eth0 -o $ETUN1 -m state --state RELATED,ESTABLISHED -j ACCEPT
+/sbin/iptables -D FORWARD -i $ETUN1 -o eth0 -j ACCEPT
+
+# Get rid of etun devices, only need name of one of them
+echo $ETUN1 > /sys/module/etun/parameters/delif
+
+# Clean up files
+rm -f $GRAB $GRAB.acl
+rm -f $DELETE $DELETE.acl
+
+EOF
+chmod +x $DELETE
+
diff --git a/factory/vtop b/factory/vtop
new file mode 100755 (executable)
index 0000000..00e44c0
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+use strict;
+
+###############################################
+# vtop for slicestat by KyoungSoo Park
+###############################################
+
+open THIS_PIPE, "/usr/sbin/vtop bn1 |";
+while(<THIS_PIPE>) {
+    print;
+}
+close THIS_PIPE;
index eb9559c..a85baaa 100644 (file)
@@ -1,34 +1,35 @@
 (** Fdwatcher - The main event loop. Agnostic to the type of file descriptors
- involved.*)
 involved.*)
 
 open Printf
 open Globals
+open Printexc
 
 let fdset = ref []
 let cbtable = Hashtbl.create 1024
 
-(* The in descriptor is always open. Thanks to the broken semantics of
- * fifo outputs, the out descriptor must be opened a nouveau whenever we
- * want to send out data, and so we keep the associated filename as well.
- * Same with input fifos. Yipee.*)
 let add_fd (evpair:fname_and_fd) (fd_other:fname_and_fd) (callback:fname_and_fd->fname_and_fd->unit) = 
   let (fname,fd) = evpair in
-  fdset := (fd::!fdset);
-  Hashtbl.replace cbtable fd (callback,(evpair,fd_other))
+    fdset := (fd::!fdset);
+    Hashtbl.replace cbtable fd (callback,(evpair,fd_other))
 
 let del_fd fd =
   fdset:=List.filter (fun l->l<>fd) !fdset;
-  flush Pervasives.stdout
+  flush logfd
 
 let start_watch () =
-    while (true)
-    do
-              let (fds,_,_) = try Unix.select !fdset [] [] (-1.) 
-              with e->
-                ([],[],[])
-              in
-                List.iter (fun elt->
-                             let (func,(evd,fd_other)) = Hashtbl.find cbtable elt in
-                               func evd fd_other) fds
-    done
-
+  while (true)
+  do
+    let (fds,_,_) = try Unix.select !fdset [] [] (-1.) 
+    with e->
+      ([],[],[])
+    in
+      List.iter (fun elt->
+                   let (func,(evd,fd_other)) = Hashtbl.find cbtable elt in
+                     try (* Never fail *)
+                       func evd fd_other
+                     with e->
+                       let wtf = Printexc.to_string e in
+                         logprint "%s\n" wtf
+                ) fds
+  done
index dc79dad..d9625b6 100644 (file)
@@ -5,21 +5,23 @@ open Unix
 open Globals
 open Dirwatcher
 open Printf
+open Splice
 
 (** A connected process, FIFO *)
-type channel_pipe = Process of out_channel | Fifo of out_channel | BrokenPipe
-(** Signed file descriptors. Usually, we'll make sure that they're not
-  mistreated *)
+type channel_pipe = Process of Unix.file_descr | Fifo of Unix.file_descr | BrokenPipe
+
+(** Signed file descriptors. *)
 type signed_fd = Infd of Unix.file_descr | Outfd of Unix.file_descr | Eventfd of Unix.file_descr
 
+(** XXX This will get deprecated when we switch to inotify *)                                                                                  
 let fdmap: (Unix.file_descr,string*string) Hashtbl.t = Hashtbl.create 1024
+
 (** Maps pids to slice connections. Needed to clean up fds when a script dies
   with EPIPE *)
 let pidmap: (int,signed_fd list) Hashtbl.t = Hashtbl.create 1024
 let backend_prefix = ref ""
 let open_fds: (Unix.file_descr,channel_pipe) Hashtbl.t = Hashtbl.create 1024
 
-
 (** Receive an event from a running script. This event must be relayed to the
   slice that invoked it.
 
@@ -29,32 +31,31 @@ let receive_process_event (idesc: fname_and_fd) (_: fname_and_fd) =
   let (_,ifd) = idesc in
   let cp = try Hashtbl.find open_fds ifd with
       Not_found->
-        printf "Fifo fd disappeared\n";flush Pervasives.stdout;raise Bug
+        fprintf logfd "Fifo fd disappeared\n";flush logfd;raise Bug
   in
     match (cp) with 
-      | Fifo(fifo_outchan) ->
-          let process_inchan = in_channel_of_descr ifd in
-          let cont = ref true in
-            while (!cont) do
-              try 
-                let curline = input_line process_inchan in
-                  fprintf fifo_outchan "%s\n" curline;flush fifo_outchan
-              with 
-                | End_of_file|Sys_blocked_io|Unix_error(EPIPE,_,_)|Unix_error(EBADF,_,_) ->
-                    begin
-                      cont:=false
-                    end
-                | Unix_error(_,s1,s2) -> printf "Unix error %s - %s\n" s1 s2;flush Pervasives.stdout;cont:=false
-                | Sys_error(s) -> (* We get this error if the EPIPE comes before the EOF marker*) cont:=false
-                | e -> printf "Error - received unexpected event from file system !!!\n";raise e
-            done
-      | _ -> printf "Bug! Process fd received in the channel handler\n";flush Pervasives.stdout;raise Bug
-
+      | Fifo(fifo_outfd) ->
+          begin
+            try
+              printf "Received process event\n";flush Pervasives.stdout;
+              (* transferred = 4096 => there were at least 4096 bytes in the
+               * stream, so we should try again.
+               * transferred < 4096 => EAGAIN => either this is all the data we
+               * have (move on)
+               * OR XXX the receiver is blocking (supposedly this can't happen) *)
+              let transferred = ref 4096 in
+                while (!transferred == 4096) do 
+                  transferred:=tee ifd fifo_outfd 4096
+                done;
+            with 
+                Failure(s)->fprintf logfd "Transfer failure: %s\n" s;flush logfd
+          end
+      | _ -> fprintf logfd "Bug! Process fd received in the channel handler\n";flush logfd;raise Bug
 
 let rec openentry_int fifoin fifoout (abspath:string*string) =
   let fdin =
     try openfile fifoin [O_RDONLY;O_NONBLOCK] 0o777 with 
-        e->printf "Error opening and connecting FIFO: %s,%o\n" fifoin 0o777;flush Pervasives.stdout;raise e
+        e->fprintf logfd "Error opening and connecting FIFO: %s,%o\n" fifoin 0o777;flush logfd;raise e
   in
     Hashtbl.replace fdmap fdin abspath;
     Fdwatcher.add_fd (Some(fifoin),fdin) (Some(fifoout),stdout) receive_fifo_event
@@ -62,9 +63,10 @@ and reopenentry_int fdin fifoin fifoout =
   close fdin;
     Fdwatcher.del_fd fdin;
     let abspath = try 
-      Hashtbl.find fdmap fdin with _ -> printf "Bug: Phantom pipe\n";flush Pervasives.stdout;raise Bug
+      Hashtbl.find fdmap fdin with _ -> fprintf logfd "Bug: Phantom pipe\n";flush logfd;raise Bug
     in
       openentry_int fifoin fifoout abspath
+
 (** receive an event from a fifo and connect to the corresponding service, or to
   create it if it doesn't exit 
   @param eventdescriptor Name of input pipe,in descriptor
@@ -79,9 +81,9 @@ and receive_fifo_event eventdescriptor outdescriptor =
       | Some(str)->
           (
             try openfile str [O_WRONLY;O_NONBLOCK] 0o777 with
-                _->printf "Output pipe not open, using stdout in place of %s\n" str;flush Pervasives.stdout;stdout
+                _->fprintf logfd "Output pipe not open, using stdout in place of %s\n" str;flush logfd;stdout
           )
-      | None-> printf "Bug, nameless pipe\n";flush Pervasives.stdout;raise Bug
+      | None-> fprintf logfd "Bug, nameless pipe\n";flush logfd;raise Bug
   in
   (* Check if the input descriptor is already registered (=> a session is open).
    If not, register it and start a new session.*)
@@ -92,7 +94,8 @@ and receive_fifo_event eventdescriptor outdescriptor =
         let (script_infd,pout) = Unix.pipe () in
         let (pin,script_outfd) = Unix.pipe () in
           set_nonblock script_infd;
-          let rpid = try Some(create_process execpath [|execpath;slice_name|] pin pout pout) with e -> printf "Error executing service: %s\n" execpath;flush Pervasives.stdout;None
+          ignore(sigprocmask SIG_BLOCK [Sys.sigchld]);
+          let rpid = try Some(create_process execpath [|execpath;slice_name|] pin pout pout) with e -> fprintf logfd "Error executing service: %s\n" execpath;flush logfd;None
           in
             match rpid with
               | None-> BrokenPipe
@@ -102,52 +105,45 @@ and receive_fifo_event eventdescriptor outdescriptor =
                   Hashtbl.add pidmap pid [Infd(script_infd);Outfd(script_outfd);Eventfd(evfd)];
 
                   (* Connect pipe to running script *)
-                  Hashtbl.add open_fds evfd (Process(out_channel_of_descr script_outfd));
+                  Hashtbl.add open_fds evfd (Process(script_outfd));
 
                   (* Connect the running script to the pipe *)
-                  Hashtbl.add open_fds script_infd (Fifo(out_channel_of_descr outfd));
+                  Hashtbl.add open_fds script_infd (Fifo(outfd));
 
                   (* Activate running script *)
                   Fdwatcher.add_fd (None,script_infd) (None,script_infd) receive_process_event;
 
-                  (Process(out_channel_of_descr script_outfd))
+                  (Process(script_outfd))
   in
-  (* We have the connection to the process - because it was open, or because it
-   just got established *)
-  let inchan_fd = in_channel_of_descr evfd in
+    (* We have the connection to the process - because it was open, or because it
+     just got established *)
     match (pipe) with
-      | Process(out_channel) -> 
-          let cont = ref true in
-            while (!cont) do
-              try 
-                printf "Reading...\n";flush Pervasives.stdout;
-                let curline = input_line inchan_fd in
-                  fprintf out_channel "%s\n" curline;flush out_channel 
-              with 
-                |End_of_file->
-                    (
-                      match (evfname,fname_other) with
-                        | Some(str1),Some(str2)->
-                            printf "Reopening entry\n";flush Pervasives.stdout;
-                            reopenentry_int evfd str1 str2
-                        | Some(str1),None ->
-                            printf "Bug, nameless pipe\n";flush Pervasives.stdout;raise Bug
-                        | None,_ ->
-                            printf "Race condition -> user deleted file before closing it. Clever ploy, but won't work.\n";
-                            flush Pervasives.stdout
-                    );
-                    cont:=false
-                |Sys_blocked_io ->printf "Sysblockedio\n";flush Pervasives.stdout;
-                                  cont:=false
-                | _ ->printf "Bug: unhandled exception\n";flush Pervasives.stdout;raise Bug
-            done
+      | Process(fifo_outfd) -> 
+          begin
+            try
+              let transferred = ref 4096 in
+                while (!transferred == 4096) do
+                  begin
+                  transferred:=tee evfd fifo_outfd 4096;
+                                 printf "Transferred: %d\n" !transferred;flush Pervasives.stdout
+                  end
+                done;
+            with Failure(str) ->
+              begin
+                fprintf logfd "Error connecting user to service: %s\n" str;
+                flush logfd
+              end;
+              ignore(sigprocmask SIG_UNBLOCK [Sys.sigchld]);
+                                 printf "Out of the loop\n";flush Pervasives.stdout
+
+          end
       | BrokenPipe -> ()
-      | Fifo(_) -> printf "BUG! received process event from fifo\n";raise Bug
+      | Fifo(_) -> fprintf logfd "BUG! received process event from fifo\n";raise Bug
 
 
 (** Make a pair of fifo entries *)
 let mkentry fqp abspath perm uname = 
-  printf "Making entry %s->%s\n" fqp abspath;flush Pervasives.stdout;
+  fprintf logfd "Making entry %s->%s\n" fqp abspath;flush logfd;
   let fifoin=sprintf "%s.in" fqp in
   let fifoout=sprintf "%s.out" fqp in
     (try Unix.unlink fifoin with _ -> ());
@@ -158,14 +154,14 @@ let mkentry fqp abspath perm uname =
          Unix.mkfifo infname 0o666;
          Unix.mkfifo outfname 0o666;
          ( (* Make the user the owner of the pipes in a non-chroot environment *)
-         if (!Globals.nochroot) then
-           let pwentry = Unix.getpwnam uname in
-             Unix.chown infname pwentry.pw_uid pwentry.pw_gid; 
-             Unix.chown outfname pwentry.pw_uid pwentry.pw_gid
+           if (!Globals.nochroot) then
+             let pwentry = Unix.getpwnam uname in
+               Unix.chown infname pwentry.pw_uid pwentry.pw_gid; 
+               Unix.chown outfname pwentry.pw_uid pwentry.pw_gid
          );
          Success
      with 
-         e->printf "Error creating FIFO: %s->%s. May be something wrong at the frontend.\n" fqp fifoout;flush Pervasives.stdout;Failed)
+         e->fprintf logfd "Error creating FIFO: %s->%s. May be something wrong at the frontend.\n" fqp fifoout;flush logfd;Failed)
 
 (** Open fifos for a session. Will shutdown vsys if the fifos don't exist *)
 let openentry fqp abspath perm =
index 7cc0c16..ad36172 100644 (file)
@@ -3,7 +3,7 @@
 open Printf
 open Unix
 open Globals
-open Fifowatcher
+open Directfifowatcher
 
 (** frontendhandler class: Methods to create and unlink pipes and directories 
   @param root_dir vsys directory inside a slice
@@ -18,55 +18,79 @@ object(this)
     @param abspath Absolute path of the entry
     @param perm Permissions of the entry at the frontend *)
   method mkentry (rp:relpath) abspath perm = 
-            let realperm = perm land (lnot 0o111) in
-    match rp with Relpath(rel) ->
-      let fqp = String.concat "/" [root_dir;rel] in
-      let res = Fifowatcher.mkentry fqp abspath realperm slice_name in
-        match res with 
-          | Success ->
-              Fifowatcher.openentry fqp (abspath,slice_name) realperm
-          | _ -> ()
+    let realperm = perm land (lnot 0o111) in
+      match rp with Relpath(rel) ->
+        let fqp = String.concat "/" [root_dir;rel] in
+        let res = Directfifowatcher.mkentry fqp abspath realperm slice_name in
+          match res with 
+            | Success ->
+                Directfifowatcher.openentry root_dir fqp (abspath,slice_name)
+            | _ -> ()
 
   (** A new directory was created at the backend, make a corresponding directory
     at the frontend. Refer to mkentry for parameters *)
   method mkdir rp perm =
     match rp with Relpath(rel) ->
-    let fqp = String.concat "/" [root_dir;rel] in
-      try 
-            let s = Unix.stat fqp in
-              if (s.st_kind<>S_DIR) then
-                begin
-                        Unix.unlink fqp;
-                        Unix.mkdir fqp perm
-                end
-              else if (s.st_perm <> perm) then
-                begin
-                        printf "Removing directory %s\n" fqp;
-                        flush Pervasives.stdout;
-                        Unix.rmdir fqp;
-                        Unix.mkdir fqp perm
-                end
-      with Unix.Unix_error(_,_,_) ->
-        Unix.mkdir fqp perm
+      let fqp = String.concat "/" [root_dir;rel] in
+        try 
+          let s = Unix.stat fqp in
+            if (s.st_kind<>S_DIR) then
+              begin
+                Unix.unlink fqp;
+                Unix.mkdir fqp perm
+              end
+            else if (s.st_perm <> perm) then
+              begin
+                Unix.rmdir fqp;
+                Unix.mkdir fqp perm
+              end;
+        with Unix.Unix_error(_,_,_) ->
+          Unix.mkdir fqp perm;
+          Directfifowatcher.add_dir_watch fqp
 
   (** Functions corresponding to file deletion/directory removal *)
 
   (** *)
   method unlink rp =
     match rp with Relpath(rel) ->
-    let fqp1 = String.concat "/" [root_dir;rel;".in"] in
-    let fqp2 = String.concat "/" [root_dir;rel;".out"] in
-      try 
-        Unix.unlink fqp1;
-        Unix.unlink fqp2
-      with _ ->
-        printf "Hm. %s disappeared. Looks like slice %s shot itself in the foot\n" fqp1 (this#get_slice_name ());flush Pervasives.stdout
+      let fqp = String.concat "/" [root_dir;rel] in
+      let fqp_in = String.concat "." [fqp;"in"] in
+      let fqp_out = String.concat "." [fqp;"out"] in
+        Directfifowatcher.closeentry fqp;
+        try 
+          Unix.unlink fqp_in;
+          Unix.unlink fqp_out
+        with _ ->
+          logprint "Hm. %s disappeared. Looks like slice %s shot itself in the foot\n" fqp (this#get_slice_name ())
 
   method rmdir rp =
     match rp with Relpath(rel) ->
-    let fqp = String.concat "/" [root_dir;rel] in
-      try
-      Unix.rmdir fqp
-      with _ ->
-        printf "Hm. %s disappeared. Looks like slice %s shot itself in the foot\n" fqp (this#get_slice_name ());flush Pervasives.stdout
+      let fqp = String.concat "/" [root_dir;rel] in
+        Directfifowatcher.del_dir_watch fqp;
+        try
+          Unix.rmdir fqp
+        with _ ->
+          logprint "Hm. %s disappeared or not empty. Looks like slice %s shot itself in the foot\n" fqp (this#get_slice_name ())
+
+  initializer 
+    (
+      try 
+        let s = Unix.stat root_dir in
+          if (s.st_kind<>S_DIR) then
+            begin
+              Unix.unlink root_dir;
+              Unix.mkdir root_dir 0o700
+            end
+          else if (s.st_perm <> 0o700) then
+            begin
+              Unix.rmdir root_dir;
+              Unix.mkdir root_dir 0o700
+            end;
+      with Unix.Unix_error(_,_,_) ->
+        begin
+          try 
+            Unix.mkdir root_dir 0o700;
+          with _ -> ();
+        end);
+          Directfifowatcher.add_dir_watch root_dir
 end
index 4e2d332..29054a6 100644 (file)
@@ -1,12 +1,19 @@
 (** Some things that didn't fit in elsewhere *)
 let backend = ref ""
 let debug = ref true
-let vsys_version = "0.5"
+let vsys_version = "0.7"
 let nochroot = ref false
 let conffile = ref ""
+let pid_filepath = ref "/var/run/vsys.pid"
+let log_filepath = ref "/var/log/vsys"
+let failsafe = ref false
 
-type result = Success | Failed
+let logfd = open_out_gen [Open_append;Open_creat] 0o644 !log_filepath
+let logprint fmt = Printf.fprintf logfd (fmt ^^ "%!")
+let debprint fmt = if (!debug) then Printf.fprintf logfd (fmt ^^ "%!")
+let print fmt = Printf.printf (fmt ^^ "%!")
 
+type result = Success | Failed
 type fname_and_fd = string option * Unix.file_descr
 
 (* Relative path, never precededed by a '/' *)
diff --git a/inotify_stubs.o b/inotify_stubs.o
deleted file mode 100644 (file)
index 82c7c60..0000000
Binary files a/inotify_stubs.o and /dev/null differ
diff --git a/main.ml b/main.ml
index 391074d..872dc59 100644 (file)
--- a/main.ml
+++ b/main.ml
@@ -4,37 +4,61 @@ open Printf
 open Inotify
 open Backend
 open Frontend
-open Fifowatcher
 open Conffile
 
 let input_file_list = ref []
 let cur_dir = ref ""
 let cur_slice = ref ""
+let daemonize = ref false
 
 let cmdspeclist =
   [
+    ("-daemon",Arg.Set(daemonize), "Daemonize");
     ("-conffile",Arg.Set_string(Globals.conffile), "Config file");
     ("-backend",Arg.Set_string(Globals.backend), "Backend directory");
-    ("-frontend",Arg.Tuple[Arg.String(fun s->cur_dir:=s);Arg.String(fun s->cur_slice:=s;input_file_list:=(!cur_dir,!cur_slice)::!input_file_list)], "frontendN,slicenameN");
-    ("-nochroot",Arg.Set(Globals.nochroot), "Run in non-chroot environment")
+    ("-frontend",Arg.Tuple[Arg.String(fun s->cur_dir:=s);
+                           Arg.String(fun s->cur_slice:=s;
+                                             input_file_list:=(!cur_dir,!cur_slice)::!input_file_list)], 
+     "frontendN,slicenameN");
+    ("-nochroot",Arg.Set(Globals.nochroot), "Run in non-chroot environment");
+    ("-failsafe",Arg.Set(Globals.failsafe), "Never crash. Be stupid, but never crash. Use at your own risk.");
   ]
 
-let cont = ref true
-
 let _ =
-  printf "Vsys v%s\n" Globals.vsys_version;flush stdout;
+  logprint "Starting Vsys v%s\n" Globals.vsys_version;
+  print "Starting Vsys v%s\n" Globals.vsys_version;
   Arg.parse cmdspeclist (fun x->()) "Usage: vsys <list of mount points>";  
   if (!Globals.backend == "") then
-      printf "Try vsys --help\n"
+    printf "Try vsys --help\n"
   else
     begin
-    Dirwatcher.initialize ();
-    Fifowatcher.initialize ();
-    if (!Globals.conffile != "") then
-      let frontends = Conffile.read_frontends !Globals.conffile in
-        input_file_list:=List.concat [!input_file_list;frontends];
+      if (!daemonize) then
+        begin
+          print "Daemonizing\n";
+          let child = Unix.fork () in
+            if (child <> 0) then
+              begin
+                let pidfile = open_out !Globals.pid_filepath in
+                  fprintf pidfile "%d" child;
+                  close_out pidfile;
+                  exit(0)
+              end
+        end;
+
+      Dirwatcher.initialize ();
+      Directfifowatcher.initialize ();
+
+      if (!Globals.conffile <> "") then
+        begin
+          let frontends = Conffile.read_frontends !Globals.conffile in
+            input_file_list:=List.concat [!input_file_list;frontends]
+        end;
 
-    let felst = List.map (fun lst->let (x,y)=lst in printf "Slice %s (%s)\n" x y;flush Pervasives.stdout;new frontendHandler lst) !input_file_list in
-        let _ = new backendHandler !Globals.backend felst in
-         Fdwatcher.start_watch ()
+      let felst = List.map 
+                    (fun lst->let (x,y)=lst in 
+                       logprint "Slice %s (%s)\n" x y;
+                       new frontendHandler lst) 
+                    !input_file_list in
+      let _ = new backendHandler !Globals.backend felst in
+        Fdwatcher.start_watch ()
     end
index 7dd187a..ea4dbe6 100644 (file)
@@ -33,7 +33,7 @@ inotify.cmxa: inotify_stubs.o inotify.cmx
        $(OCAMLOPT) $(OCAMLOPTFLAGS) -c -o $@ $<
 
 %.o: %.c
-       $(CC) -I /usr/lib/ocaml $(CFLAGS) -c -o $@ $<
+       $(CC) -I /usr/lib/ocaml -I /usr/lib64/ocaml $(CFLAGS) -c -o $@ $<
 
 test.inotify: inotify.cmxa test.inotify.ml
        $(OCAMLOPT) -o $@ unix.cmxa $+
diff --git a/splice.ml b/splice.ml
new file mode 100644 (file)
index 0000000..3e1dfad
--- /dev/null
+++ b/splice.ml
@@ -0,0 +1,7 @@
+open Unix
+
+external splice : Unix.file_descr -> Unix.file_descr -> int -> int
+                   = "stub_splice"
+
+external tee : Unix.file_descr -> Unix.file_descr -> int -> int
+                   = "stub_tee"
diff --git a/splice_stub.c b/splice_stub.c
new file mode 100644 (file)
index 0000000..61fbd56
--- /dev/null
@@ -0,0 +1,40 @@
+/* This module allows data between vsys clients and servers to be copied in kernel -
+ * and some of these copies to be eliminated through page rewrites */
+
+#define SPLICE_SYSCALL 313
+#define TEE_SYSCALL    315
+#define SPLICE_F_NONBLOCK 0x02
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <caml/mlvalues.h>
+#include <caml/memory.h>
+#include <caml/alloc.h>
+#include <caml/custom.h>
+#include <caml/fail.h>
+#include <caml/signals.h>
+
+CAMLprim value stub_splice(value fd_in, value fd_out, value len)
+{
+        CAMLparam3(fd_in, fd_out, len);
+       long ret;
+        ret = syscall(SPLICE_SYSCALL, Int_val(fd_in), NULL, Int_val(fd_out),NULL, Int_val(len), SPLICE_F_NONBLOCK);
+        if (ret == -1 && errno!=EAGAIN) {
+                caml_failwith("Splice system call returned -1");
+       }
+        CAMLreturn(Val_int(ret));
+}
+
+CAMLprim value stub_tee(value fd_in, value fd_out, value len)
+{
+        CAMLparam3(fd_in, fd_out, len);
+       long ret;
+        ret = syscall(TEE_SYSCALL,Int_val(fd_in), Int_val(fd_out), Int_val(len), SPLICE_F_NONBLOCK);
+        if (ret == -1 && errno!=EAGAIN) {
+                caml_failwith(strerror(errno));
+       }
+        CAMLreturn(Val_int(ret));
+}
diff --git a/tests/vsys-test.txt b/tests/vsys-test.txt
new file mode 100644 (file)
index 0000000..34b1797
--- /dev/null
@@ -0,0 +1,15 @@
+Description:
+
+Subtest #1 -
+
+Create a new vsys entry, expect it to show up in a slice
+
+Subtest #2 -
+
+Connect to the entry, receive output, validate it and repeat the process 100
+times.
+
+Subtest #3 -
+
+Clean up the entry and expect it to disappear from within the slice.
+
diff --git a/tests/vsys_conctest.c b/tests/vsys_conctest.c
new file mode 100644 (file)
index 0000000..2d174a0
--- /dev/null
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+int main()
+{
+  FILE *fp = NULL, *fp_in = NULL;
+  FILE *out_fp = NULL, *diff_fp = NULL;
+  const char* topcmd = "fe/test.out";
+  const char* top_in_file = "fe/test.in";
+  char buf[4096];
+  int fd_in = -1, fd_out;
+  int res;
+  int flag,flag2;
+  int count = 1;
+  struct timeval tv={.tv_sec=5,.tv_usec=0};
+
+  while (count < 1000000) {
+    fd_set readSet;
+    int res;
+    int nlines=0;
+
+    //usleep(200);
+    printf("(%d)", count);fflush(stdout);
+    if ((fd_out = open(topcmd, O_RDONLY | O_NONBLOCK)) < 0) {
+      fprintf(stderr, "error executing top\n");
+      exit(-1);
+    }
+
+    //printf("((0))");fflush(stdout);
+    while ((fd_in = open(top_in_file, O_WRONLY| O_NONBLOCK)) < 0) {
+      fprintf(stderr, "Waiting for %s (%s)\n", top_in_file,strerror(errno));
+       usleep (50); 
+    }
+
+    //printf("(1)");
+    if ((flag = fcntl(fd_out, F_GETFL)) == -1) {
+      printf("fcntl get failed\n");
+      exit(-1);
+    }
+    //printf("(2)");
+
+    //printf("(3)");
+       if ((flag2 = fcntl(fd_in, F_GETFL)) == -1) {
+      printf("fcntl get failed\n");
+      exit(-1);
+    }
+    //printf("(4)");
+
+
+    while (1) {
+           FD_ZERO(&readSet);
+           FD_SET(fd_out, &readSet);
+
+    //printf("(5)");
+           res = select(fd_out + 1, &readSet, NULL, NULL, NULL);
+    //printf("(6)");
+           if (res < 0) {
+                   if (errno == EINTR || errno == EAGAIN) {
+                           printf(".");
+                           continue;
+                   }
+                   fprintf(stderr,"select failed errno=%d errstr=%s\n", errno, strerror(errno));
+                   exit(-1);
+           }
+           break; /* we're done */
+    }
+
+    //printf("(7)");
+    if (fcntl(fd_out, F_SETFL, flag & ~O_NONBLOCK) == -1) {
+      printf("fcntl set failed\n");
+      exit(-1);
+    }
+    //printf("(8)");
+
+    //printf("(9)");
+    if ((flag = fcntl(fd_out, F_GETFL)) == -1) {
+      printf("fcntl get failed\n");
+      exit(-1);
+    }
+    //printf("(10)");
+
+
+    //printf("(11)");
+    if (fcntl(fd_in, F_SETFL, flag2 & ~O_NONBLOCK) == -1) {
+      printf("fcntl set failed\n");
+      exit(-1);
+    }
+
+    //printf("(11)");
+    if ((flag2 = fcntl(fd_in, F_GETFL)) == -1) {
+      printf("fcntl get failed\n");
+      exit(-1);
+    }
+    //printf("(12)");
+
+    if (flag & O_NONBLOCK == 0) {
+      printf("fd_out still nonblocking\n");
+      exit(-1);
+    }
+
+    if (flag & O_NONBLOCK == 0) {
+      printf("fd_in still nonblocking\n");
+      exit(-1);
+    }
+    if ((fp = fdopen(fd_out, "r")) == NULL) {
+      printf("fdopen failed\n");
+      exit(-1);
+    }
+
+    while (fgets(buf, sizeof(buf), fp) != NULL) {
+           nlines++;
+    }
+
+    if (nlines<5) {
+           printf("Test returned different results - run again to verify\n");
+           exit(-1);
+    }
+
+    fclose(fp);
+    close(fd_in);
+    close(fd_out);
+    count++;
+  }
+  printf("test successful.\n");
+  exit(0);
+
+}
diff --git a/tests/vsys_launch.pl b/tests/vsys_launch.pl
new file mode 100644 (file)
index 0000000..204b8dc
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/perl
+
+# Subtest #1 Create new vsys entry
+
+print "Creating entries...\t";
+
+$vsys_entry="#!/bin/bash\n\ncat /etc/passwd";
+$vsys_entry_acl = "/vservers/pl_netflow pl_netflow";
+
+open ACL,">/vsys/test.acl" || die ("Could not create acl for test entry.");
+print ACL $vsys_entry_acl;
+close ACL;
+
+open FIL,">/vsys/test" || die ("Could not create test entry.");
+print FIL $vsys_entry;
+close $vsys_entry;
+
+chmod 0755,"/vsys/test";
+
+# Check if it has shown up
+
+(-f "/vservers/pl_netflow/test.in") || die ("in file didn't show up in the slice");
+(-f "/vservers/pl_netflow/test.out") || die ("out file didn't show up in the slice");
+
+# OK, SUBTEST #1 SUCCEEDED
+print "(success)\n";
+
+# Subtest #2 
+
+print "Multiple-connection test...\t";
+system("su -c ./vsys_conctest pl_netflow -");
+($? && die ("Multiple-connection test failed\n"));
+
+
+# OK, SUBTEST #2 SUCCEEDED
+print "(success)\n";
+
+# Subtest #3
+unlink "/vsys/test.acl";
+unlink "/vsys/test";
+
+(-f "/vservers/pl_netflow/test.in" || -f "/vservers/pl_netflow/test.out") && die ("cleanup failed");
+
index c448b52..cfeba9a 100755 (executable)
@@ -1,29 +1,56 @@
 #!/bin/bash
-# vsys initscript
-# Author: sapanb
+#
+# chkconfig: 345 84 02
+# description: Vsys file descriptor abritrator startup.
+#
+# Sapan Bhatia <sapanb@cs.princeton.edu>
+#
+# $Id$
+# $HeadURL$
+#
+name="vsys"
 
-backend="/vsys"
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+if [ -f /etc/sysconfig/$name ]; then
+    . /etc/sysconfig/$name
+fi
+
+backend=${BACKEND-/vsys}
+
+conf=${CONF-/etc/$name.conf}
+pidfile=${PIDFILE-/var/run/$name.pid}
+lockfile=${LOCKFILE-/var/lock/subsys/$name}
+RETVAL=0
+
+vsys=${VSYS- "/usr/bin/vsys -failsafe -backend $backend -conffile $conf -daemon"}
 
 case "$1" in
     start)
-        echo -n "Starting vsys:"
+        echo -n "Starting $name:"
         if [ ! -d $backend ]; then mkdir $backend; fi
-        find /vservers -maxdepth 1 -type d | perl -e 'while (<>) {if (/(\/vservers\/(.*_.*))/) {$dir=$1;if (not (-d "$dir/vsys")) {mkdir "$dir/vsys";}}}'
-        frontends=`find /vservers -maxdepth 1 -type d | perl -e 'while (<>) {if (/(\/vservers\/(.*_.*))/) {$dir=$1;$slice=$2;printf "-frontend $dir/vsys $slice "}}'`
-        vsys_command="/usr/bin/vsys -backend $backend $frontends"
-        echo $vsys_command
-        $vsys_command
+        daemon --check=vsys $vsys 
+        RETVAL=$?
+        echo
+        [ $RETVAL -eq 0 ] && touch ${lockfile}
         ;;
     stop)
-        echo -n "Stopping $prog:"
-        killall vsys
-        exit 0
+        echo -n "Stopping $name:"
+        killproc $name
+        #killproc $name - Why were there 2 instances of this? :-|
+        RETVAL=$?
+        echo
+        [ $RETVAL -eq 0 ] && rm -f ${lockfile} ${pidfile}
+        ;;
+    restart)
+        $0 stop
+        $0 start
+        RETVAL=$?
         ;;
     *)
-        echo $"Usage: $0 {start|stop}"
+        echo $"Usage: $0 {start|stop|restart}"
         exit 1
         ;;
 esac
 
-# Source function library.
-. /etc/rc.d/init.d/functions
diff --git a/vsys.conf b/vsys.conf
new file mode 100644 (file)
index 0000000..3312eef
--- /dev/null
+++ b/vsys.conf
@@ -0,0 +1 @@
+/vservers/pl_netflow/vsys pl_netflow
diff --git a/vsys.logrotate b/vsys.logrotate
new file mode 100644 (file)
index 0000000..1eb2c45
--- /dev/null
@@ -0,0 +1,8 @@
+/var/log/netflow.log {
+    copytruncate
+    compress
+    daily
+    notifempty
+    rotate 5
+    missingok
+}
index 549ea90..0842d54 100644 (file)
--- a/vsys.spec
+++ b/vsys.spec
@@ -3,17 +3,21 @@
 #
 # RPM spec file
 #
-# $Id: vsys.spec,v 1.40 2007/04/03 02:08:55 mef Exp $
+# $Id$
 #
 
+%define url $URL$
+
 %define name vsys
-%define version 0.6
-%define release 2%{?pldistro:.%{pldistro}}%{?date:.%{date}}
+%define version 0.7
+%define taglevel 18
+
+%define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 
 Vendor: PlanetLab
 Packager: PlanetLab Central <support@planet-lab.org>
-Distribution: PlanetLab 4.0
-URL: http://cvs.planet-lab.org/cvs/vsys
+Distribution: PlanetLab %{plrelease}
+URL: %(echo %{url} | cut -d ' ' -f 2)
 
 Summary: Vsys filesystem 
 Name: %{name}
@@ -25,7 +29,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
 #Requires: 
 BuildRequires: inotify-tools-devel
 BuildRequires: ocaml
-BuildRequires: ocaml-ocamldocs
+BuildRequires: ocaml-docs
 
 Source0: vsys-%{version}.tar.gz
 
@@ -45,8 +49,13 @@ make
 %install
 mkdir -p $RPM_BUILD_ROOT/usr/bin
 mkdir -p $RPM_BUILD_ROOT/etc/init.d
+mkdir -p $RPM_BUILD_ROOT/vsys
+cp factory/* $RPM_BUILD_ROOT/vsys
 cp vsys $RPM_BUILD_ROOT/usr/bin
 cp vsys-initscript $RPM_BUILD_ROOT/etc/init.d/vsys
+cp vsys.conf $RPM_BUILD_ROOT/etc
+
+install -D -m 644 vsys.logrotate $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/vsys
 
 %clean
 rm -rf $RPM_BUILD_ROOT
@@ -54,11 +63,84 @@ rm -rf $RPM_BUILD_ROOT
 %files
 /usr/bin/vsys
 /etc/init.d/vsys
+/vsys/*
+%config(noreplace) /etc/vsys.conf
+%{_sysconfdir}/logrotate.d/vsys
 
 %post
 chkconfig --add vsys
 chkconfig vsys on
+if [ "$PL_BOOTCD" != "1" ] ; then
+        service vsys restart
+fi
 
 %postun
 
 %changelog
+* Thu Jul 17 2008 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-0.7-18
+- Change for someone at Imperial.ac.uk, who wants access to Netflow data.
+
+* Tue Jul 15 2008 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-0.7-17
+- * Don't kill vsys twice on restarts, do it only once
+- * Restart vsys following a reinstall
+
+* Wed Jul 02 2008 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - vsys-0.7-16
+- Usability changes that are necessary for the stability of CoMon
+
+* Wed Jun 25 2008 Stephen Soltesz <soltesz@cs.princeton.edu> - vsys-0.7-15
+- added patch to pl-ps needed by slicestat
+- 
+- 
+
+* Mon Jun 23 2008 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-0.7-14
+- This change is an attempt to fix unexpected blocking after many days of uptime, reported by KyoungSoo.
+
+* Thu Jun 19 2008 Stephen Soltesz <soltesz@cs.princeton.edu> - vsys-0.7-13
+- accept '-' in filenames also
+- 
+
+* Wed Jun 18 2008 Stephen Soltesz <soltesz@cs.princeton.edu> - vsys-0.7-12
+- don't overwrite the config file that already exists.
+- 
+
+* Wed Jun 18 2008 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-0.7-11
+- Suppress some temp file that RPM creates frmo showing up as a vsys script.
+- 
+- 
+
+* Wed Jun 18 2008 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-0.7-10
+- Changed a policy in vsys. When an acl is empty, the script doesn't show up in ANY slice. The previous behavior was for 
+- it to show up in all slices.
+- 
+- 
+
+* Wed Jun 18 2008 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-0.7-9
+- Added a vsys script for CoMon.
+- 
+
+* Mon Jun 16 2008 Stephen Soltesz <soltesz@cs.princeton.edu> - vsys-0.7-8
+- ignore non-existent directories after restart.
+- 
+
+* Fri May 16 2008 Stephen Soltesz <soltesz@cs.princeton.edu> - vsys-0.7-7
+- added logrotate configuration to package.
+- 
+
+* Mon May 12 2008 Stephen Soltesz <soltesz@cs.princeton.edu> - vsys-0.7-6
+- Added two new scripts for CoMon on 4.2
+- 
+
+* Tue May 06 2008 Stephen Soltesz <soltesz@cs.princeton.edu> - vsys-0.7-5
+- 
+- Corrected directory that the script mounts to the correct one:
+- /var/local/fprobe
+- 
+
+* Wed Apr 23 2008 Stephen Soltesz <soltesz@cs.princeton.edu> - vsys-0.7-4
+- Pulling the latest changes for the 4.2rc2 release
+- 
+
+* Fri Feb 15 2008 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - vsys-0.7-2 vsys-0.7-3
+- * daemonization, writing to a logfile, and saving the pid
+- 
+
index 105f565..0239fec 100644 (file)
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdarg.h>
 #include <dirent.h>
 
+void pipe_handler (int sig) {
+       printf("SIGPIPE");
+}
+
 int main(int argc, char **argv, char **envp)
 {
        if (argc<2) {
-               printf("Usage: vsyssh <vsys entry> <cmd>\n");
+               printf("Usage: vsyssh <vsys entry> [cmd]\n");
                exit(1);
        }
        else {
                int vfd0,vfd1;
                char *inf,*outf;
+               struct timeval tv;
+
+               signal(SIGPIPE,pipe_handler);
                inf=(char *)malloc(strlen(argv[1])+3);
-               outf=(char *)malloc(strlen(argv[2])+4);
+               outf=(char *)malloc(strlen(argv[1])+4);
                strcpy(inf,argv[1]);
-               strcpy(outf,argv[2]);
+               strcpy(outf,argv[1]);
                strcat(inf,".in");
                strcat(outf,".out");
 
+               vfd0 = open(outf,O_RDONLY|O_NONBLOCK);
+               printf("Out file: %d\n",vfd0);
                vfd1 = open(inf,O_WRONLY);
-               vfd0 = open(outf,O_RDONLY);
+               printf("In file: %d\n",vfd1);
 
                if (vfd0==-1 || vfd1 == -1) {
-                       printf("Error opening vsys entry %s\n", argv[1]);
+                       printf("Error opening vsys entry %s (%s)\n", argv[1],strerror(errno));
                        exit(1);
                }
 
-               
                if (argc<3) {
                        fd_set set;
                        FD_ZERO(&set);
-                       FD_SET(0,&set);
-                       FD_SET(vfd0,&set);
-                       while (1) {
+                       FD_SET(0, &set);
+                       FD_SET(vfd0, &set);
+
+                       while (1)
+                        {
                                int ret;
-                               ret = select(2, &set, NULL, NULL, NULL);
+                               printf("vsys>");fflush(stdout);
+                               FD_SET(0, &set);
+                               FD_SET(vfd0, &set);
+                               ret = select(vfd0+1, &set, NULL, NULL, NULL);
                                if (FD_ISSET(0,&set)) {
                                        char lineread[2048];
                                        int ret;
                                        ret=read(0,lineread,2048);
+                                       lineread[ret]='\0';
+                                       printf ("writing %s\n",lineread);
                                        write(vfd1,lineread,ret);
                                        FD_CLR(0,&set);
-                               }
-                               else if (FD_ISSET(vfd0,&set)) {
+                               } if (FD_ISSET(vfd0,&set)) {
                                        char lineread[2048];
                                        int ret;
                                        ret=read(vfd0,lineread,2048);