diff options
Diffstat (limited to 'src/xdg_pipe_menu_socket.erl')
| -rw-r--r-- | src/xdg_pipe_menu_socket.erl | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/xdg_pipe_menu_socket.erl b/src/xdg_pipe_menu_socket.erl new file mode 100644 index 0000000..1bfde52 --- /dev/null +++ b/src/xdg_pipe_menu_socket.erl @@ -0,0 +1,66 @@ +%%%------------------------------------------------------------------- +%% @doc Serves the cached menu over a Unix domain socket. +%% +%% Connecting to the socket *is* the request: each accepted connection +%% is handed the current `xdg_pipe_menu_cache:get_menu/0' binary and +%% closed. There is no request payload to parse. +%% @end +%%%------------------------------------------------------------------- + +-module(xdg_pipe_menu_socket). + +-export([start_link/0, socket_path/0]). +-export([init/1]). + +-spec start_link() -> {ok, pid()}. +start_link() -> + proc_lib:start_link(?MODULE, init, [self()]). + +-spec socket_path() -> file:filename_all(). +socket_path() -> + case application:get_env(xdg_pipe_menu, socket_path) of + {ok, Path} -> Path; + undefined -> default_socket_path() + end. + +default_socket_path() -> + case env("XDG_RUNTIME_DIR") of + undefined -> filename:join("/tmp", "xdg_pipe_menu-" ++ os:getenv("USER", "unknown") ++ ".sock"); + Dir -> filename:join(Dir, "xdg_pipe_menu.sock") + end. + +env(Name) -> + case os:getenv(Name) of + false -> undefined; + "" -> undefined; + Value -> Value + end. + +init(Parent) -> + Path = socket_path(), + %% Clean up a stale socket file left behind by a previous run that + %% didn't shut down cleanly; gen_tcp:listen fails with eaddrinuse + %% otherwise. + _ = file:delete(Path), + {ok, Listen} = gen_tcp:listen(0, [ + {ifaddr, {local, Path}}, + binary, + {active, false}, + {packet, raw}, + {reuseaddr, true} + ]), + proc_lib:init_ack(Parent, {ok, self()}), + accept_loop(Listen). + +accept_loop(Listen) -> + case gen_tcp:accept(Listen) of + {ok, Socket} -> + spawn(fun() -> serve(Socket) end), + accept_loop(Listen); + {error, Reason} -> + exit(Reason) + end. + +serve(Socket) -> + gen_tcp:send(Socket, xdg_pipe_menu_cache:get_menu()), + gen_tcp:close(Socket). |
