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 case code:priv_dir(jukebox) of
21 Port = open_port({spawn, priv_dir() ++ "/execdaemon/execdaemon"}, [stream, use_stdio, eof]),
22 mainloop(Port, 1, [], [], "").
24 mainloop(Port, ReqNum, Requests, Subscribers, Acc) ->
27 Pid ! {subscribed, self()},
28 mainloop(Port, ReqNum, Requests, [Pid | Subscribers], Acc);
29 execdaemon_terminate ->
30 port_command(Port, [0]),
31 mainloop(Port, ReqNum, Requests, Subscribers, Acc);
32 {execdaemon_command, Pid, Command, Arg} ->
33 port_command(Port, lists:flatten([integer_to_list(ReqNum), ":",
34 atom_to_list(Command), ",", Arg, [0]])),
35 mainloop(Port, ReqNum + 1, [{ReqNum, Pid} | Requests], Subscribers, Acc);
37 {_, Pids} = lists:unzip(Requests),
38 send_to_subs(Pids ++ Subscribers, {execdaemon_eof, self()}),
40 {_Port1, {data, Data}} ->
41 {NewRequests, NewAcc} = process_received(Subscribers, Requests, Acc, Data),
42 mainloop(Port, ReqNum, NewRequests, Subscribers, NewAcc)
45 send_to_subs(Subscribers, Msg) ->
46 lists:foreach(fun (Subscriber) -> Subscriber ! Msg end, Subscribers).
48 process_received(_Subscribers, Requests, Acc, []) ->
50 process_received(Subscribers, Requests, Acc, [0 | Rest]) ->
51 {ReqNum, Code, Aux} = split_response(lists:reverse(Acc)),
54 send_to_subs(Subscribers, {execdaemon_event, self(), Code, Aux}),
55 process_received(Subscribers, Requests, [], Rest);
57 case proplists:get_value(ReqNum, Requests, none) of
58 none -> process_received(Subscribers, Requests, [], Rest);
60 Pid ! {execdaemon_response, self(), Code, Aux},
61 process_received(Subscribers, proplists:delete(ReqNum, Requests), [], Rest)
64 process_received(Subscribers, Requests, Acc, [Ch | Rest]) ->
65 process_received(Subscribers, Requests, [Ch | Acc], Rest).
67 split_response(Str) ->
68 {ReqNum, ":" ++ CmdArg} = lists:split(string:chr(Str, $:) - 1, Str),
69 {Cmd, "," ++ Arg} = lists:split(string:chr(CmdArg, $,) - 1, CmdArg),
70 {list_to_integer(ReqNum), list_to_atom(Cmd), Arg}.
73 Pid ! execdaemon_terminate.
75 command(Pid, Command, Arg) ->
76 Pid ! {execdaemon_command, self(), Command, Arg},
81 {execdaemon_response, Pid1, Code, Aux} when Pid == Pid1 ->
83 {execdaemon_eof, Pid1} when Pid == Pid1 ->
87 wait_for_event(Pid) ->
89 {execdaemon_event, Pid1, Code, Aux} when Pid == Pid1 ->
91 {execdaemon_eof, Pid1} when Pid == Pid1 ->
95 run(Program, Argvec) ->
97 command(Pid, program, Program),
98 command(Pid, argc, integer_to_list(length(Argvec))),
99 lists:foldl(fun (Arg, Count) ->
100 command(Pid, arg, [integer_to_list(Count), ",", Arg]),
103 command(Pid, execv, ""),