My working unpac repository
at opam/upstream/seq 188 lines 6.3 kB view raw
1(**************************************************************************) 2(* *) 3(* OCaml *) 4(* *) 5(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) 6(* OCaml port by John Malecki and Xavier Leroy *) 7(* *) 8(* Copyright 1996 Institut National de Recherche en Informatique et *) 9(* en Automatique. *) 10(* *) 11(* All rights reserved. This file is distributed under the terms of *) 12(* the GNU Lesser General Public License version 2.1, with the *) 13(* special exception on linking described in the file LICENSE. *) 14(* *) 15(**************************************************************************) 16 17(* Program loading *) 18 19open Unix 20open Debugger_config 21open Parameters 22open Input_handling 23 24(*** Debugging. ***) 25 26let debug_loading = ref false 27 28(*** Load a program. ***) 29 30(* Function used for launching the program. *) 31let launching_func = ref (function () -> ()) 32 33let load_program () = 34 !launching_func (); 35 main_loop () 36 37(*** Launching functions. ***) 38 39(* Returns a command line prefix to set environment for the debuggee *) 40let get_unix_environment () = 41 let f (vname, vvalue) = 42 Printf.sprintf "%s=%s " vname (Filename.quote vvalue) 43 in 44 String.concat "" (List.map f !Debugger_config.environment) 45 46(* Notes: 47 1. This quoting is not the same as [Filename.quote] because the "set" 48 command is a shell built-in and its quoting rules are different 49 from regular commands. 50 2. Microsoft's documentation omits the double-quote from the list 51 of characters that need quoting, but that is a mistake (unquoted 52 quotes are included in the value, but they alter the quoting of 53 characters between them). 54 Reference: http://msdn.microsoft.com/en-us/library/bb490954.aspx 55 *) 56let quote_for_windows_shell s = 57 let b = Buffer.create (20 + String.length s) in 58 for i = 0 to String.length s - 1 do 59 begin match s.[i] with 60 | '<' | '>' | '|' | '&' | '^' | '\"' -> 61 Buffer.add_char b '^'; 62 | _ -> () 63 end; 64 Buffer.add_char b s.[i]; 65 done; 66 Buffer.contents b 67 68(* Returns a command line prefix to set environment for the debuggee *) 69let get_win32_environment () = 70 (* Note: no space before the & or Windows will add it to the value *) 71 let f (vname, vvalue) = 72 Printf.sprintf "set %s=%s&" vname (quote_for_windows_shell vvalue) 73 in 74 String.concat "" (List.map f !Debugger_config.environment) 75 76(* A generic function for launching the program *) 77let generic_exec_unix cmdline = function () -> 78 if !debug_loading then 79 prerr_endline "Launching program..."; 80 let child = 81 try 82 fork () 83 with x -> 84 Unix_tools.report_error x; 85 raise Toplevel in 86 match child with 87 0 -> 88 begin try 89 match fork () with 90 0 -> (* Try to detach the process from the controlling terminal, 91 so that it does not receive SIGINT on ctrl-C. *) 92 begin try ignore(setsid()) with Invalid_argument _ -> () end; 93 execv shell [| shell; "-c"; cmdline() |] 94 | _ -> exit 0 95 with x -> 96 Unix_tools.report_error x; 97 exit 1 98 end 99 | _ -> 100 match wait () with 101 (_, WEXITED 0) -> () 102 | _ -> raise Toplevel 103 104let generic_exec_win cmdline = function () -> 105 if !debug_loading then 106 prerr_endline "Launching program..."; 107 try ignore(create_process "cmd.exe" [| "/C"; cmdline() |] stdin stdout stderr) 108 with x -> 109 Unix_tools.report_error x; 110 raise Toplevel 111 112let generic_exec = 113 match Sys.os_type with 114 "Win32" -> generic_exec_win 115 | _ -> generic_exec_unix 116 117(* Execute the program by calling the runtime explicitly *) 118let exec_with_runtime = 119 generic_exec 120 (function () -> 121 match Sys.os_type with 122 "Win32" -> 123 (* This would fail on a file name with spaces 124 but quoting is even worse because Unix.create_process 125 thinks each command line parameter is a file. 126 So no good solution so far *) 127 Printf.sprintf "%sset CAML_DEBUG_SOCKET=%s& %s %s %s" 128 (get_win32_environment ()) 129 !socket_name 130 runtime_program 131 !program_name 132 !arguments 133 | _ -> 134 Printf.sprintf "%sCAML_DEBUG_SOCKET=%s %s %s %s" 135 (get_unix_environment ()) 136 !socket_name 137 (Filename.quote runtime_program) 138 (Filename.quote !program_name) 139 !arguments) 140 141(* Execute the program directly *) 142let exec_direct = 143 generic_exec 144 (function () -> 145 match Sys.os_type with 146 "Win32" -> 147 (* See the comment above *) 148 Printf.sprintf "%sset CAML_DEBUG_SOCKET=%s& %s %s" 149 (get_win32_environment ()) 150 !socket_name 151 !program_name 152 !arguments 153 | _ -> 154 Printf.sprintf "%sCAML_DEBUG_SOCKET=%s %s %s" 155 (get_unix_environment ()) 156 !socket_name 157 (Filename.quote !program_name) 158 !arguments) 159 160(* Ask the user. *) 161let exec_manual = 162 function () -> 163 print_newline (); 164 print_string "Waiting for connection..."; 165 print_string ("(the socket is " ^ !socket_name ^ ")"); 166 print_newline () 167 168(*** Selection of the launching function. ***) 169 170type launching_function = (unit -> unit) 171 172let loading_modes = 173 ["direct", exec_direct; 174 "runtime", exec_with_runtime; 175 "manual", exec_manual] 176 177let set_launching_function func = 178 launching_func := func 179 180(* Initialization *) 181 182let _ = 183 set_launching_function exec_direct 184 185(*** Connection. ***) 186 187let connection = ref Primitives.std_io 188let connection_opened = ref false