open Sys
open Unix
let try_finalize f x finally y =
let res = try f x with exn -> finally y; raise exn in
finally y;
res
let exec cmd = execvp cmd.(0) cmd
let launch cmd =
if fork () = 0
then exec cmd
let print_usage () =
List.iter print_endline ["Usage: " ^ Sys.argv.(0) ^ "
"];
exit 0
let die reason =
print_endline ("ERROR! " ^ reason); exit (-1)
let launch_get_output cmd =
let input_lines ic =
let rec aux lines =
try aux (input_line ic :: lines) with End_of_file -> lines in
aux [] in
let (ifd,ofd) = pipe () in
match fork () with
| 0 -> dup2 ofd stdout; dup2 ofd stderr;
close stdin; close ifd; close ofd;
exec cmd
| n -> close ofd;
let lns = input_lines (in_channel_of_descr ifd) in
close ifd; ignore (waitpid [] n);
lns
module Net = struct
let tcp_server s_handler addr =
let setup_tcp_socket addr =
let s = socket PF_INET SOCK_STREAM 0 in
try bind s addr;
listen s 10;
s
with z -> close s; raise z in
ignore (signal sigpipe Signal_ignore);
let ss = setup_tcp_socket addr in
while true do
let client = accept ss in
s_handler ss client
done
let double_fork server service (cfd, _ as client) =
let treat () = match fork () with
| 0 -> if fork () <> 0 then exit 0;
close server; service client; exit 0
| n -> ignore (waitpid [] n) in
try_finalize treat () close cfd
let s_handler c_handler sock (_, caddr as client) =
print_endline
(match caddr with
| ADDR_INET (a,_) -> "Connected to " ^ string_of_inet_addr a
| ADDR_UNIX _ -> "Local connection (dafuq?)");
double_fork sock c_handler client
end
module type XWIN = sig
type wid
val cmdname : string
val search_by_title : string -> wid list
val title : wid -> string
val focus : wid -> unit
val send : wid -> string -> unit
end
module Xdotool : (XWIN with type wid := string) = struct
let cmdname = "xdotool"
let delay = "200"
let search_by_title name =
launch_get_output [|cmdname; "search"; "--name"; name|]
let title wid =
List.hd (launch_get_output [|cmdname; "getwindowname"; wid|])
let focus wid =
launch [|cmdname; "windowfocus"; wid|]
let send wid keys =
launch [|cmdname; "type"; "--delay"; delay; keys|]
end
module Comm = struct
module Window = Xdotool
let get_wid name =
let wids = Window.search_by_title name in
let falses = [Sys.argv.(0); "mednafen"] in (* May have the same title *)
let falsewids = List.concat (List.map Window.search_by_title falses) in
match List.filter (fun wid -> not (List.mem wid falsewids)) wids with
| [x] -> Some (x, Window.title x)
| _ -> None
let c_handler wid (cfd, _) =
dup2 cfd stdin; dup2 cfd stdout; dup2 cfd stderr; close cfd;
Window.focus wid;
while true do
print_string "> ";
flush_all ();
let l = read_line () in
Window.send wid l;
done
(* Window.send wid "awdwawdwawdwawdwa" *)
(* Window.send wid "aaaaaaaaaaaaaaaaa" *)
end
let () =
if Array.length Sys.argv <> 2 then print_usage ();
let addr = inet_addr_any in
let port = 8081 in
let inaddr = ADDR_INET (addr, port) in
let name = Sys.argv.(1) in
match Comm.get_wid name with
| None -> die ("Window '" ^ name ^ "' not found")
| Some (wid, title) ->
print_endline ("Found window '" ^ title ^ "' (WID " ^ wid ^ ")");
Net.tcp_server (Net.s_handler (Comm.c_handler wid)) inaddr