%%% Copyright (c) 2019, Sunet. %%% See LICENSE for licensing information. -module(p11p_server_sup). -behaviour(supervisor). -export([start_link/0, start_server/1]). -export([init/1, cleanup/0]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> ok = start_servers(p11p_config:nameof(p11p_config:tokens())), {ok, {{simple_one_for_one, 1, 5}, [{sock_server, {p11p_server, start_link, []}, temporary, 1000, worker, [p11p_server]} ]}}. start_server(Args) -> {ok, Pid} = supervisor:start_child(?MODULE, [Args]), Pid. cleanup() -> cleanup(p11p_config:nameof(p11p_config:tokens())). %% Private functions. start_servers([]) -> ok; start_servers([Name|T]) -> Path = socket_path(mkdir_socket_basepath(), Name), file:delete(Path), %% TODO: Consider flow control using {active, once}. %% And if so, don't forget activating after read. {ok, Socket} = gen_tcp:listen(0, [{ifaddr, {local, Path}}, binary]), spawn_link(?MODULE, start_server, [[Name, Socket]]), start_servers(T). cleanup([]) -> ok; cleanup([Token|Tail]) -> file:delete(socket_path(mkdir_socket_basepath(), Token)), cleanup(Tail). mkdir_socket_basepath() -> EUID = integer_to_list(geteuid()), Path = "/run/user/" ++ EUID ++ "/p11p/", ok = case file:make_dir(Path) of ok -> ok; {error, eexist} -> ok; Err -> lager:error("~s: unable to create directory: ~p", [Path, Err]), err end, Path. -spec socket_path(string(), string()) -> string(). socket_path(BasePath, Name) -> BasePath ++ Name ++ "-" ++ os:getpid(). geteuid() -> %% TODO: Maybe find a POSIX library instead of invoking a shell? list_to_integer(string:strip(os:cmd("/usr/bin/id -u"), right, $\n)).