summaryrefslogtreecommitdiffstats
path: root/otherlibs/unix/unix.ml
diff options
context:
space:
mode:
Diffstat (limited to 'otherlibs/unix/unix.ml')
-rw-r--r--otherlibs/unix/unix.ml85
1 files changed, 66 insertions, 19 deletions
diff --git a/otherlibs/unix/unix.ml b/otherlibs/unix/unix.ml
index b2d7d124b..1b61cdbba 100644
--- a/otherlibs/unix/unix.ml
+++ b/otherlibs/unix/unix.ml
@@ -133,6 +133,11 @@ let stdin = 0
let stdout = 1
let stderr = 2
+let max_opened_descr = ref 2
+
+let record_descr fd =
+ if fd > !max_opened_descr then max_opened_descr := fd
+
type open_flag =
O_RDONLY
| O_WRONLY
@@ -146,8 +151,14 @@ type open_flag =
type file_perm = int
-external openfile : string -> open_flag list -> file_perm -> file_descr
+external sys_openfile : string -> open_flag list -> file_perm -> file_descr
= "unix_open"
+
+let openfile name flags perm =
+ let fd = sys_openfile name flags perm in
+ record_descr fd;
+ fd
+
external close : file_descr -> unit = "unix_close"
external unsafe_read : file_descr -> string -> int -> int -> int = "unix_read"
external unsafe_write : file_descr -> string -> int -> int -> int = "unix_write"
@@ -218,7 +229,11 @@ external fchown : file_descr -> int -> int -> unit = "unix_fchown"
external umask : int -> int = "unix_umask"
external access : string -> access_permission list -> unit = "unix_access"
-external dup : file_descr -> file_descr = "unix_dup"
+external sys_dup : file_descr -> file_descr = "unix_dup"
+
+let dup fd =
+ let newfd = sys_dup fd in record_descr newfd; newfd
+
external dup2 : file_descr -> file_descr -> unit = "unix_dup2"
external set_nonblock : file_descr -> unit = "unix_set_nonblock"
external clear_nonblock : file_descr -> unit = "unix_clear_nonblock"
@@ -236,7 +251,13 @@ external opendir : string -> dir_handle = "unix_opendir"
external readdir : dir_handle -> string = "unix_readdir"
external rewinddir : dir_handle -> unit = "unix_rewinddir"
external closedir : dir_handle -> unit = "unix_closedir"
-external pipe : unit -> file_descr * file_descr = "unix_pipe"
+
+external sys_pipe : unit -> file_descr * file_descr = "unix_pipe"
+
+let pipe () =
+ let (fd1, fd2 as fdpair) = sys_pipe() in
+ record_descr fd1; record_descr fd2; fdpair
+
external symlink : string -> string -> unit = "unix_symlink"
external readlink : string -> string = "unix_readlink"
external mkfifo : string -> file_perm -> unit = "unix_mkfifo"
@@ -369,12 +390,25 @@ type socket_option =
| SO_DONTROUTE
| SO_OOBINLINE
-external socket : socket_domain -> socket_type -> int -> file_descr
+external sys_socket : socket_domain -> socket_type -> int -> file_descr
= "unix_socket"
-external socketpair :
+let socket domain typ proto =
+ let fd = sys_socket domain typ proto in
+ record_descr fd; fd
+
+external sys_socketpair :
socket_domain -> socket_type -> int -> file_descr * file_descr
= "unix_socketpair"
-external accept : file_descr -> file_descr * sockaddr = "unix_accept"
+let socketpair domain typ proto =
+ let (fd1, fd2 as fdpair) = sys_socketpair domain typ proto in
+ record_descr fd1; record_descr fd2; fdpair
+
+external sys_accept : file_descr -> file_descr * sockaddr = "unix_accept"
+
+let accept fd =
+ let (newfd, addr as result) = sys_accept fd in
+ record_descr newfd; result
+
external bind : file_descr -> sockaddr -> unit = "unix_bind"
external connect : file_descr -> sockaddr -> unit = "unix_connect"
external listen : file_descr -> int -> unit = "unix_listen"
@@ -503,11 +537,27 @@ external tcflow: file_descr -> flow_action -> unit = "unix_tcflow"
(* High-level process management (system, popen) *)
+let closeall () =
+ for i = 3 to !max_opened_descr do close i done
+
let system cmd =
match fork() with
- 0 -> execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |]; exit 127
+ 0 -> closeall();
+ execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |];
+ exit 127
| id -> snd(waitpid [] id)
+let create_process cmd args new_stdin new_stdout new_stderr =
+ match fork() with
+ 0 ->
+ if new_stdin <> stdin then dup2 new_stdin stdin;
+ if new_stdout <> stdout then dup2 new_stdout stdout;
+ if new_stderr <> stderr then dup2 new_stderr stderr;
+ closeall();
+ execvp cmd args;
+ exit 127
+ | id -> id
+
type popen_process =
Process of in_channel * out_channel
| Process_in of in_channel
@@ -515,26 +565,22 @@ type popen_process =
let popen_processes = (Hashtbl.create 7 : (popen_process, int) Hashtbl.t)
-let open_proc cmd proc input output toclose =
- match fork() with
- 0 -> if input <> stdin then begin dup2 input stdin; close input end;
- if output <> stdout then begin dup2 output stdout; close output end;
- List.iter close toclose;
- execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |];
- exit 127
- | id -> Hashtbl.add popen_processes proc id
+let open_proc cmd proc input output =
+ let pid =
+ create_process "/bin/sh" [| "/bin/sh"; "-c"; cmd |] input output stderr in
+ Hashtbl.add popen_processes proc pid
let open_process_in cmd =
let (in_read, in_write) = pipe() in
let inchan = in_channel_of_descr in_read in
- open_proc cmd (Process_in inchan) stdin in_write [in_read];
+ open_proc cmd (Process_in inchan) stdin in_write;
close in_write;
inchan
let open_process_out cmd =
let (out_read, out_write) = pipe() in
let outchan = out_channel_of_descr out_write in
- open_proc cmd (Process_out outchan) out_read stdout [out_write];
+ open_proc cmd (Process_out outchan) out_read stdout;
close out_read;
outchan
@@ -543,8 +589,9 @@ let open_process cmd =
let (out_read, out_write) = pipe() in
let inchan = in_channel_of_descr in_read in
let outchan = out_channel_of_descr out_write in
- open_proc cmd (Process(inchan, outchan))
- out_read in_write [in_read; out_write];
+ open_proc cmd (Process(inchan, outchan)) out_read in_write;
+ close in_write;
+ close out_read;
(inchan, outchan)
let find_proc_id fun_name proc =