%%%---------------------------------------------------------------------- %%% File : uds_server.erl %%% Purpose : Holder for the uds_drv ddll driver. %%% Created : 15 Mar 2000 %%%---------------------------------------------------------------------- -module(uds_server). -behaviour(gen_server). %% External exports -export([start_link/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(DRIVER_NAME,"uds_drv"). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%---------------------------------------------------------------------- init([]) -> process_flag(trap_exit,true), case load_driver() of ok -> {ok, []}; {error, already_loaded} -> {ok, []}; Error -> exit(Error) end. %%---------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_call(Request, From, State) -> Reply = ok, {reply, Reply, State}. %%---------------------------------------------------------------------- %% Func: handle_cast/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_cast(Msg, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_info(Info, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any (ignored by gen_server) %%---------------------------------------------------------------------- terminate(Reason, State) -> erl_ddll:unload_driver(?DRIVER_NAME), ok. %%---------------------------------------------------------------------- %% Func: code_change/3 %% Purpose: Convert process state when code is changed %% Returns: {ok, NewState} %%---------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- %% %% Actually load the driver. %% load_driver() -> Dir = find_priv_lib(), erl_ddll:load_driver(Dir,?DRIVER_NAME). %% %% As this server may be started by the distribution, it is not safe to assume %% a working code server, neither a working file server. %% I try to utilize the most primitive interfaces available to determine %% the directory of the port_program. %% find_priv_lib() -> PrivDir = case (catch code:priv_dir(uds_dist)) of {'EXIT', _} -> %% Code server probably not startet yet {ok, P} = erl_prim_loader:get_path(), ModuleFile = atom_to_list(?MODULE) ++ extension(), Pd = (catch lists:foldl (fun(X,Acc) -> M = filename:join([X, ModuleFile]), %% The file server probably not started %% either, has to use raw interface. case file:raw_read_file_info(M) of {ok,_} -> %% Found our own module in the %% path, lets bail out with %% the priv_dir of this directory Y = filename:split(X), throw(filename:join (lists:sublist (Y,length(Y) - 1) ++ ["priv"])); _ -> Acc end end, false,P)), case Pd of false -> exit(uds_dist_priv_lib_indeterminate); _ -> Pd end; Dir -> Dir end, filename:join([PrivDir, "lib"]). extension() -> %% erlang:info(machine) returns machine name as text in all uppercase "." ++ lists:map(fun(X) -> X + $a - $A end, erlang:info(machine)).