anchor.diff:  			exit(Reason)
   	end.
   
  +-spec log_file(FileName :: string()) -> ok.
  +%% @doc Write all logged accounting records to a file.
  +%%
  +log_file(FileName) when is_list(FileName) ->
  +   {ok, IODevice} = file:open(FileName, [write]),
  +   file_chunk(?LOGNAME, IODevice, start).
  +
  +-type password() :: [50..57 | 97..104 | 106..107 | 109..110 | 112..116 | 119..122].
  +-spec generate_password() -> password().
  +%% @equiv generate_password(12)
  +generate_password() ->
  +	generate_password(12).
  +
  +-spec start(Type :: auth | acct, Address :: inet:ip_address(),
  +		Port :: pos_integer()) ->
  +	{ok, Pid :: pid()} | {error, Reason :: term()}.
  +%% @doc Start a RADIUS request handler.
  +start(Type, Address, Port) when is_tuple(Address), is_integer(Port) ->
  +	gen_server:call(ocs, {start, Type, Address, Port}).
  +
  +%%----------------------------------------------------------------------
  +%%  internal functions
  +%%----------------------------------------------------------------------
  +
  +-spec generate_password(Length :: pos_integer()) -> password().
  +%% @doc Generate a random uniform password.
  +%% @private
  +generate_password(Length) when Length > 0 ->
  +	Charset = charset(),
  +	NumChars = length(Charset),
  +	Random = crypto:strong_rand_bytes(Length),
  +	generate_password(Random, Charset, NumChars,[]).
  +%% @hidden
  +generate_password(<<N, Rest/binary>>, Charset, NumChars, Acc) ->
  +	CharNum = (N rem NumChars) + 1,
  +	NewAcc = [lists:nth(CharNum, Charset) | Acc],
  +	generate_password(Rest, Charset, NumChars, NewAcc);
  +generate_password(<<>>, _Charset, _NumChars, Acc) ->
  +	Acc.
  +
  +-spec charset() -> Charset :: password().
  +%% @doc Returns the table of valid characters for passwords.
  +%% @private
  +charset() ->
  +	C1 = lists:seq($2, $9),
  +	C2 = lists:seq($a, $h),
  +	C3 = lists:seq($j, $k),
  +	C4 = lists:seq($m, $n),
  +	C5 = lists:seq($p, $t),
  +	C6 = lists:seq($w, $z),
  +	lists:append([C1, C2, C3, C4, C5, C6]).
  +
  +%% @hidden
  +file_chunk(Log, IODevice, Continuation) ->
  +	case disk_log:chunk(Log, Continuation) of
  +		eof ->
  +			file:close(IODevice);
  +		{error, Reason} ->
  +			file:close(IODevice),
  +			exit(Reason);
  +		{Continuation2, Terms} ->
  +			Fun =  fun(Event) ->
  +						io:fwrite(IODevice, "~999p~n", [Event])
  +			end,
  +			lists:foreach(Fun, Terms),
  +			file_chunk(Log, IODevice, Continuation2)
  +	end.
  +
   -spec add_guest_subscriber(Subscriber :: string() | binary(),
   		Password :: string() | binary(),
   		Attributes :: radius:attributes() | binary()) ->
   		ok | {error, Reason :: bad_psk | term()}.
  -%% @doc Create an guest entry in the guest table if subscriber not exists
  -%%		in the subscriber table.
  +%% @doc Create an entry in the subscriber table.
   %%
   %% 	`Password' and `Balance' lookup from the guest table. An optional list of
   %% 	RADIUS `Attributes', to be returned in an `AccessRequest' response,
   %% 	may be provided.
   %%
  +%% @private
   add_guest_subscriber(Subscriber, Password, Attributes)
   		when is_list(Subscriber) ->
   	add_subscriber(list_to_binary(Subscriber), Password, Attributes);
  
positive.code: 		{aborted, Reason} ->
  			{error, Reason}
  	end.
  
  -spec log_file(FileName :: string()) -> ok.
  %% @doc Write all logged accounting records to a file.
  %%
  log_file(FileName) when is_list(FileName) ->
     {ok, IODevice} = file:open(FileName, [write]),
     file_chunk(?LOGNAME, IODevice, start).
  
  -type password() :: [50..57 | 97..104 | 106..107 | 109..110 | 112..116 | 119..122].
  -spec generate_password() -> password().
  %% @equiv generate_password(12)
  generate_password() ->
  	generate_password(12).
  
  -spec start(Type :: auth | acct, Address :: inet:ip_address(),
  		Port :: pos_integer()) ->
  	{ok, Pid :: pid()} | {error, Reason :: term()}.
  %% @doc Start a RADIUS request handler.
  start(Type, Address, Port) when is_tuple(Address), is_integer(Port) ->
  	gen_server:call(ocs, {start, Type, Address, Port}).
  
  %%----------------------------------------------------------------------
  %%  internal functions
  %%----------------------------------------------------------------------
  
  -spec generate_password(Length :: pos_integer()) -> password().
  %% @doc Generate a random uniform password.
  %% @private
  generate_password(Length) when Length > 0 ->
  	Charset = charset(),
  	NumChars = length(Charset),
  	Random = crypto:strong_rand_bytes(Length),
  	generate_password(Random, Charset, NumChars,[]).
  %% @hidden
  generate_password(<<N, Rest/binary>>, Charset, NumChars, Acc) ->
  	CharNum = (N rem NumChars) + 1,
  	NewAcc = [lists:nth(CharNum, Charset) | Acc],
  	generate_password(Rest, Charset, NumChars, NewAcc);
  generate_password(<<>>, _Charset, _NumChars, Acc) ->
  	Acc.
  
  -spec charset() -> Charset :: password().
  %% @doc Returns the table of valid characters for passwords.
  %% @private
  charset() ->
  	C1 = lists:seq($2, $9),
  	C2 = lists:seq($a, $h),
  	C3 = lists:seq($j, $k),
  	C4 = lists:seq($m, $n),
  	C5 = lists:seq($p, $t),
  	C6 = lists:seq($w, $z),
  	lists:append([C1, C2, C3, C4, C5, C6]).
  
  %% @hidden
  file_chunk(Log, IODevice, Continuation) ->
  	case disk_log:chunk(Log, Continuation) of
  		eof ->
  			file:close(IODevice);
  		{error, Reason} ->
  			file:close(IODevice),
  			exit(Reason);
  		{Continuation2, Terms} ->
  			Fun =  fun(Event) ->
  						io:fwrite(IODevice, "~999p~n", [Event])
  			end,
  			lists:foreach(Fun, Terms),
  			file_chunk(Log, IODevice, Continuation2)
  	end.
  
  
negative.code: %% export the ocs public API
  -export([add_client/2, find_client/1]).
  -export([add_subscriber/3, add_subscriber/4, find_subscriber/1, delete_subscriber/1,
  			update_password/3, update_attributes/3, decrement_balance/2, add_psk/2]).
  -export([log_file/1]).
  -export([generate_password/0]).
  -export([start/3]).
  %% export the ocs private API
  -export([add_guest_subscriber/3]).
  
  -include("ocs.hrl").
  -define(LOGNAME, radius_acct).
  %%----------------------------------------------------------------------
  %%  The ocs public API
  %%----------------------------------------------------------------------
  