3 -export([open/0, terminate/1, command/3, read_from/1, wait_for_event/1, run/2]).
6 Pid = spawn(fun startup/0),
7 Pid ! {subscribe, self()},
9 {subscribed, Pid2} when Pid == Pid2 -> Pid
13 Port = open_port({spawn, jukebox:priv_dir() ++ "/execdaemon/execdaemon"}, [stream, use_stdio, eof]),
14 mainloop(Port, 1, [], [], "").
16 mainloop(Port, ReqNum, Requests, Subscribers, Acc) ->
19 Pid ! {subscribed, self()},
20 mainloop(Port, ReqNum, Requests, [Pid | Subscribers], Acc);
21 execdaemon_terminate ->
22 port_command(Port, [0]),
23 mainloop(Port, ReqNum, Requests, Subscribers, Acc);
24 {execdaemon_command, Pid, Command, Arg} ->
25 port_command(Port, lists:flatten([integer_to_list(ReqNum), ":",
26 atom_to_list(Command), ",", Arg, [0]])),
27 mainloop(Port, ReqNum + 1, [{ReqNum, Pid} | Requests], Subscribers, Acc);
29 {_, Pids} = lists:unzip(Requests),
30 send_to_subs(Pids ++ Subscribers, {execdaemon_eof, self()}),
32 {_Port1, {data, Data}} ->
33 {NewRequests, NewAcc} = process_received(Subscribers, Requests, Acc, Data),
34 mainloop(Port, ReqNum, NewRequests, Subscribers, NewAcc)
37 send_to_subs(Subscribers, Msg) ->
38 lists:foreach(fun (Subscriber) -> Subscriber ! Msg end, Subscribers).
40 process_received(_Subscribers, Requests, Acc, []) ->
42 process_received(Subscribers, Requests, Acc, [0 | Rest]) ->
43 {ReqNum, Code, Aux} = split_response(lists:reverse(Acc)),
46 send_to_subs(Subscribers, {execdaemon_event, self(), Code, Aux}),
47 process_received(Subscribers, Requests, [], Rest);
49 case proplists:get_value(ReqNum, Requests, none) of
50 none -> process_received(Subscribers, Requests, [], Rest);
52 Pid ! {execdaemon_response, self(), Code, Aux},
53 process_received(Subscribers, proplists:delete(ReqNum, Requests), [], Rest)
56 process_received(Subscribers, Requests, Acc, [Ch | Rest]) ->
57 process_received(Subscribers, Requests, [Ch | Acc], Rest).
59 split_response(Str) ->
60 {ReqNum, ":" ++ CmdArg} = lists:split(string:chr(Str, $:) - 1, Str),
61 {Cmd, "," ++ Arg} = lists:split(string:chr(CmdArg, $,) - 1, CmdArg),
62 {list_to_integer(ReqNum), list_to_atom(Cmd), Arg}.
65 Pid ! execdaemon_terminate.
67 command(Pid, Command, Arg) ->
68 Pid ! {execdaemon_command, self(), Command, Arg},
73 {execdaemon_response, Pid1, Code, Aux} when Pid == Pid1 ->
75 {execdaemon_eof, Pid1} when Pid == Pid1 ->
79 wait_for_event(Pid) ->
81 {execdaemon_event, Pid1, Code, Aux} when Pid == Pid1 ->
83 {execdaemon_eof, Pid1} when Pid == Pid1 ->
87 run(Program, Argvec) ->
89 command(Pid, program, Program),
90 command(Pid, argc, integer_to_list(length(Argvec))),
91 lists:foldl(fun (Arg, Count) ->
92 command(Pid, arg, [integer_to_list(Count), ",", Arg]),
95 command(Pid, execv, ""),