146 lines
5.4 KiB
OCaml
146 lines
5.4 KiB
OCaml
(**************************************************************************)
|
|
(* *)
|
|
(* OCaml *)
|
|
(* *)
|
|
(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *)
|
|
(* OCaml port by John Malecki and Xavier Leroy *)
|
|
(* *)
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
|
(* en Automatique. *)
|
|
(* *)
|
|
(* All rights reserved. This file is distributed under the terms of *)
|
|
(* the GNU Lesser General Public License version 2.1, with the *)
|
|
(* special exception on linking described in the file LICENSE. *)
|
|
(* *)
|
|
(**************************************************************************)
|
|
|
|
(****************** Tools for Unix *************************************)
|
|
|
|
module Real_stdlib = Stdlib
|
|
open Misc
|
|
open Unix
|
|
|
|
(*** Convert a socket name into a socket address. ***)
|
|
let convert_address address =
|
|
try
|
|
let n = String.index address ':' in
|
|
let host = String.sub address 0 n
|
|
and port = String.sub address (n + 1) (String.length address - n - 1)
|
|
in
|
|
(PF_INET,
|
|
ADDR_INET
|
|
((try inet_addr_of_string host with Failure _ ->
|
|
try (gethostbyname host).h_addr_list.(0) with Not_found ->
|
|
prerr_endline ("Unknown host: " ^ host);
|
|
failwith "Can't convert address"),
|
|
(try int_of_string port with Failure _ ->
|
|
prerr_endline "The port number should be an integer";
|
|
failwith "Can't convert address")))
|
|
with Not_found ->
|
|
match Sys.os_type with
|
|
"Win32" -> failwith "Unix sockets not supported"
|
|
| _ -> (PF_UNIX, ADDR_UNIX address)
|
|
|
|
(*** Report a unix error. ***)
|
|
let report_error = function
|
|
| Unix_error (err, fun_name, arg) ->
|
|
prerr_string "Unix error: '";
|
|
prerr_string fun_name;
|
|
prerr_string "' failed";
|
|
if String.length arg > 0 then
|
|
(prerr_string " on '";
|
|
prerr_string arg;
|
|
prerr_string "'");
|
|
prerr_string ": ";
|
|
prerr_endline (error_message err)
|
|
| _ -> fatal_error "report_error: not a Unix error"
|
|
|
|
(* Find program `name' in `PATH'. *)
|
|
(* Return the full path if found. *)
|
|
(* Raise `Not_found' otherwise. *)
|
|
let search_in_path name =
|
|
Printf.fprintf Real_stdlib.stderr "search_in_path [%s]\n%!" name;
|
|
let check name =
|
|
try access name [X_OK]; name with Unix_error _ -> raise Not_found
|
|
in
|
|
if not (Filename.is_implicit name) then
|
|
check name
|
|
else
|
|
let path = Sys.getenv "PATH" in
|
|
let length = String.length path in
|
|
let rec traverse pointer =
|
|
if (pointer >= length) || (path.[pointer] = ':') then
|
|
pointer
|
|
else
|
|
traverse (pointer + 1)
|
|
in
|
|
let rec find pos =
|
|
let pos2 = traverse pos in
|
|
let directory = (String.sub path pos (pos2 - pos)) in
|
|
let fullname =
|
|
if directory = "" then name else directory ^ "/" ^ name
|
|
in
|
|
try check fullname with
|
|
| Not_found ->
|
|
if pos2 < length then find (pos2 + 1)
|
|
else raise Not_found
|
|
in
|
|
find 0
|
|
|
|
(* Expand a path. *)
|
|
(* ### path -> path' *)
|
|
let rec expand_path ch =
|
|
let rec subst_variable ch =
|
|
try
|
|
let pos = String.index ch '$' in
|
|
if (pos + 1 < String.length ch) && (ch.[pos + 1] = '$') then
|
|
(String.sub ch 0 (pos + 1))
|
|
^ (subst_variable
|
|
(String.sub ch (pos + 2) (String.length ch - pos - 2)))
|
|
else
|
|
(String.sub ch 0 pos)
|
|
^ (subst2 (String.sub ch (pos + 1) (String.length ch - pos - 1)))
|
|
with Not_found ->
|
|
ch
|
|
and subst2 ch =
|
|
let suiv =
|
|
let i = ref 0 in
|
|
while !i < String.length ch &&
|
|
(let c = ch.[!i] in (c >= 'a' && c <= 'z')
|
|
|| (c >= 'A' && c <= 'Z')
|
|
|| (c >= '0' && c <= '9')
|
|
|| c = '_')
|
|
do incr i done;
|
|
!i
|
|
in (Sys.getenv (String.sub ch 0 suiv))
|
|
^ (subst_variable (String.sub ch suiv (String.length ch - suiv)))
|
|
in
|
|
let ch = subst_variable ch in
|
|
let concat_root nom ch2 =
|
|
try Filename.concat (getpwnam nom).pw_dir ch2
|
|
with Not_found ->
|
|
"~" ^ nom
|
|
in
|
|
if ch.[0] = '~' then
|
|
try
|
|
match String.index ch '/' with
|
|
1 ->
|
|
(let tail = String.sub ch 2 (String.length ch - 2)
|
|
in
|
|
try Filename.concat (Sys.getenv "HOME") tail
|
|
with Not_found ->
|
|
concat_root (Sys.getenv "LOGNAME") tail)
|
|
| n -> concat_root
|
|
(String.sub ch 1 (n - 1))
|
|
(String.sub ch (n + 1) (String.length ch - n - 1))
|
|
with
|
|
Not_found ->
|
|
expand_path (ch ^ "/")
|
|
else ch
|
|
|
|
let make_absolute name =
|
|
if Filename.is_relative name
|
|
then Filename.concat (getcwd ()) name
|
|
else name
|
|
;;
|