commit
52312cc9f2
14
README.unix
14
README.unix
@ -1,20 +1,14 @@
|
|||||||
Unix installation information for ZX
|
Unix installation information for ZX
|
||||||
|
|
||||||
|
|
||||||
This file contains information about how to install and run ZX on a Unix-type system.
|
This file contains information about how to install and run ZX on a Unix-type system.
|
||||||
Consult README.md for general information about ZX as a program and as a project.
|
Consult README.md for general information about ZX as a program and as a project.
|
||||||
|
|
||||||
Current versions of ZX and this file can be found at https://zxq9.com/zx/
|
Current versions of ZX and this file can be found at https://zxq9.com/projects/zomp/
|
||||||
|
|
||||||
|
The unix startup script, "install_unix", must be set as executable to be used.
|
||||||
The unix startup script, "install_unix", is a BASH script and must be set as executable
|
To set the script as executable:
|
||||||
to be used. To set the script as executable:
|
|
||||||
|
|
||||||
|
|
||||||
From the command line:
|
|
||||||
|
|
||||||
To set the file permission correctly you will need to run the following command:
|
|
||||||
chmod +x install_unix
|
chmod +x install_unix
|
||||||
|
|
||||||
Then to execute the installer you will need to run the following command:
|
Then to execute the installer you will need to run the following command:
|
||||||
./install_unix
|
./install_unix
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,11 @@
|
|||||||
|
Windows installation information for Windows
|
||||||
|
|
||||||
This file contains information about how to install and run ZX on a Windows system.
|
This file contains information about how to install and run ZX on a Windows system.
|
||||||
Consult README.md for general information about ZX as a program and as a project.
|
Consult README.md for general information about ZX as a program and as a project.
|
||||||
|
|
||||||
|
A quickstart guide for getting your system ready to run ZX (or any Erlang program)
|
||||||
|
is here: https://zxq9.com/projects/zomp/
|
||||||
|
|
||||||
|
Once you have an Erlang runtime installed (via the installer provided by Erlang
|
||||||
|
Solutions https://www.erlang-solutions.com/resources/download.html) you can click
|
||||||
|
to run the "install_windows" file in this directory.
|
||||||
|
|||||||
@ -103,6 +103,14 @@ do(["list", "deps", PackageString]) ->
|
|||||||
do(["install", PackageFile]) ->
|
do(["install", PackageFile]) ->
|
||||||
ok = start(),
|
ok = start(),
|
||||||
done(zx_daemon:install(PackageFile));
|
done(zx_daemon:install(PackageFile));
|
||||||
|
do(["set", "timeout", String]) ->
|
||||||
|
done(zx_local:set_timeout(String));
|
||||||
|
do(["add", "mirror"]) ->
|
||||||
|
done(zx_local:add_mirror());
|
||||||
|
do(["drop", "mirror"]) ->
|
||||||
|
done(zx_local:drop_mirror());
|
||||||
|
do(["status"]) ->
|
||||||
|
done(zx_local:status());
|
||||||
do(["set", "dep", PackageString]) ->
|
do(["set", "dep", PackageString]) ->
|
||||||
done(zx_local:set_dep(PackageString));
|
done(zx_local:set_dep(PackageString));
|
||||||
do(["set", "version", VersionString]) ->
|
do(["set", "version", VersionString]) ->
|
||||||
@ -139,6 +147,12 @@ do(["dialyze"]) ->
|
|||||||
done(zx_local:dialyze());
|
done(zx_local:dialyze());
|
||||||
do(["create", "user"]) ->
|
do(["create", "user"]) ->
|
||||||
done(zx_local:create_user());
|
done(zx_local:create_user());
|
||||||
|
do(["create", "userfile"]) ->
|
||||||
|
done(zx_local:create_userfile());
|
||||||
|
do(["export", "user"]) ->
|
||||||
|
done(zx_local:export_user());
|
||||||
|
do(["import", "user", ZdufFile]) ->
|
||||||
|
done(zx_local:import_user(ZdufFile));
|
||||||
do(["create", "keypair"]) ->
|
do(["create", "keypair"]) ->
|
||||||
done(zx_local:grow_a_pair());
|
done(zx_local:grow_a_pair());
|
||||||
do(["drop", "key", Realm, KeyName]) ->
|
do(["drop", "key", Realm, KeyName]) ->
|
||||||
@ -147,8 +161,8 @@ do(["create", "plt"]) ->
|
|||||||
done(zx_local:create_plt());
|
done(zx_local:create_plt());
|
||||||
do(["create", "realm"]) ->
|
do(["create", "realm"]) ->
|
||||||
done(zx_local:create_realm());
|
done(zx_local:create_realm());
|
||||||
do(["create", "realmfile", Realm]) ->
|
do(["create", "realmfile"]) ->
|
||||||
done(zx_local:create_realmfile(Realm, "."));
|
done(zx_local:create_realmfile());
|
||||||
do(["takeover", Realm]) ->
|
do(["takeover", Realm]) ->
|
||||||
done(zx_local:takeover(Realm));
|
done(zx_local:takeover(Realm));
|
||||||
do(["abdicate", Realm]) ->
|
do(["abdicate", Realm]) ->
|
||||||
@ -588,7 +602,8 @@ usage() ->
|
|||||||
" zx logpath [Package [1-10]]~n"
|
" zx logpath [Package [1-10]]~n"
|
||||||
" zx status~n"
|
" zx status~n"
|
||||||
" zx set timeout Value~n"
|
" zx set timeout Value~n"
|
||||||
" zx set mirror Realm Host:Port~n"
|
" zx add mirror Realm Host:Port~n"
|
||||||
|
" zx drop mirror Realm Host:Port~n"
|
||||||
"~n"
|
"~n"
|
||||||
"Developer/Packager/Maintainer Actions:~n"
|
"Developer/Packager/Maintainer Actions:~n"
|
||||||
" zx create project [app | lib] PackageID~n"
|
" zx create project [app | lib] PackageID~n"
|
||||||
|
|||||||
@ -14,10 +14,11 @@
|
|||||||
list_realms/0, list_packages/1, list_versions/1,
|
list_realms/0, list_packages/1, list_versions/1,
|
||||||
set_dep/1, list_deps/0, list_deps/1, drop_dep/1, verup/1, package/1,
|
set_dep/1, list_deps/0, list_deps/1, drop_dep/1, verup/1, package/1,
|
||||||
import_realm/1, drop_realm/1,
|
import_realm/1, drop_realm/1,
|
||||||
takeover/1, abdicate/1,
|
takeover/1, abdicate/1, set_timeout/1, add_mirror/0, drop_mirror/0,
|
||||||
create_plt/0, dialyze/0,
|
create_plt/0, dialyze/0,
|
||||||
grow_a_pair/0, drop_key/1,
|
grow_a_pair/0, drop_key/1,
|
||||||
create_user/0, create_realm/0, create_realmfile/2]).
|
create_user/0, create_userfile/0, export_user/0, import_user/1,
|
||||||
|
create_realm/0, create_realmfile/0, create_realmfile/1]).
|
||||||
|
|
||||||
-include("zx_logger.hrl").
|
-include("zx_logger.hrl").
|
||||||
|
|
||||||
@ -785,30 +786,15 @@ dialyze() ->
|
|||||||
%% Execute the key generation procedure for 16k RSA keys once and then terminate.
|
%% Execute the key generation procedure for 16k RSA keys once and then terminate.
|
||||||
|
|
||||||
grow_a_pair() ->
|
grow_a_pair() ->
|
||||||
ok = file:set_cwd(zx_lib:zomp_dir()),
|
case select_realm() of
|
||||||
case zx_lib:list_realms() of
|
error -> {error, "No realms configured.", 61};
|
||||||
[] ->
|
Realm -> grow_a_pair(Realm)
|
||||||
{error, "No realms configured.", 61};
|
|
||||||
[Realm] ->
|
|
||||||
grow_a_pair(Realm);
|
|
||||||
Realms ->
|
|
||||||
Realm = zx_tty:select_string(Realms),
|
|
||||||
grow_a_pair(Realm)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
grow_a_pair(Realm) ->
|
grow_a_pair(Realm) ->
|
||||||
Pattern = zx_lib:path(etc, Realm) ++ "*.user",
|
UserName = select_user(Realm),
|
||||||
case [filename:basename(F, ".user") || F <- filelib:wildcard(Pattern)] of
|
grow_a_pair(Realm, UserName).
|
||||||
[] ->
|
|
||||||
{ok, UserName} = create_user(#user_data{realm = Realm}),
|
|
||||||
grow_a_pair(UserName);
|
|
||||||
[UserName] ->
|
|
||||||
grow_a_pair(Realm, UserName);
|
|
||||||
UserNames ->
|
|
||||||
UserName = zx_tty:select_string(UserNames),
|
|
||||||
grow_a_pair(Realm, UserName)
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
grow_a_pair(Realm, UserName) ->
|
grow_a_pair(Realm, UserName) ->
|
||||||
@ -872,7 +858,7 @@ create_realm(R = #realm_init{realm = Realm, addr = Addr, port = Port, url = URL}
|
|||||||
"[3] Port Number : ~w~n"
|
"[3] Port Number : ~w~n"
|
||||||
"[4] URL : ~ts~n"
|
"[4] URL : ~ts~n"
|
||||||
"Press a number to select something to change, or [ENTER] to continue.~n",
|
"Press a number to select something to change, or [ENTER] to continue.~n",
|
||||||
ok = io:format(Instructions, [Realm, Addr, Port, URL]),
|
ok = io:format(Instructions, [Realm, stringify_address(Addr), Port, URL]),
|
||||||
case zx_tty:get_input() of
|
case zx_tty:get_input() of
|
||||||
"1" -> create_realm(R#realm_init{realm = none});
|
"1" -> create_realm(R#realm_init{realm = none});
|
||||||
"2" -> create_realm(R#realm_init{addr = none});
|
"2" -> create_realm(R#realm_init{addr = none});
|
||||||
@ -892,17 +878,16 @@ store_realm(#realm_init{realm = Realm,
|
|||||||
sysop = Sysop = #user_data{username = UserName,
|
sysop = Sysop = #user_data{username = UserName,
|
||||||
keys = [KeyName]}}) ->
|
keys = [KeyName]}}) ->
|
||||||
ok = make_realm_dirs(Realm),
|
ok = make_realm_dirs(Realm),
|
||||||
Address = parse_maybe_address(Addr),
|
|
||||||
RealmConf =
|
RealmConf =
|
||||||
[{realm, Realm},
|
[{realm, Realm},
|
||||||
{prime, {Address, Port}},
|
{prime, {Addr, Port}},
|
||||||
{sysop, UserName},
|
{sysop, UserName},
|
||||||
{key, KeyName},
|
{key, KeyName},
|
||||||
{url, URL}],
|
{url, URL}],
|
||||||
ok = store_user(Sysop),
|
ok = store_user(Sysop),
|
||||||
RealmConfPath = filename:join(zx_lib:path(etc, Realm), "realm.conf"),
|
RealmConfPath = filename:join(zx_lib:path(etc, Realm), "realm.conf"),
|
||||||
ok = zx_lib:write_terms(RealmConfPath, RealmConf),
|
ok = zx_lib:write_terms(RealmConfPath, RealmConf),
|
||||||
ok = create_realmfile(Realm, "."),
|
ok = create_realmfile(Realm),
|
||||||
ZRF = Realm ++ ".zrf",
|
ZRF = Realm ++ ".zrf",
|
||||||
Message =
|
Message =
|
||||||
"===========================================================================~n"
|
"===========================================================================~n"
|
||||||
@ -966,7 +951,7 @@ ask_addr() ->
|
|||||||
ok = io:format("You need to enter an address.~n"),
|
ok = io:format("You need to enter an address.~n"),
|
||||||
ask_addr();
|
ask_addr();
|
||||||
String ->
|
String ->
|
||||||
String
|
parse_maybe_address(String)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
@ -979,6 +964,15 @@ parse_maybe_address(String) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec stringify_address(inet:hostname() | inet:ip_address()) -> string().
|
||||||
|
|
||||||
|
stringify_address(Address) ->
|
||||||
|
case inet:ntoa(Address) of
|
||||||
|
{error, einval} -> Address;
|
||||||
|
String -> String
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
-spec ask_port() -> inet:port_number().
|
-spec ask_port() -> inet:port_number().
|
||||||
|
|
||||||
ask_port() ->
|
ask_port() ->
|
||||||
@ -1111,7 +1105,7 @@ create_user(U = #user_data{realm = Realm,
|
|||||||
create_user(U#user_data{contact_info = none});
|
create_user(U#user_data{contact_info = none});
|
||||||
"" ->
|
"" ->
|
||||||
ok = store_user(U),
|
ok = store_user(U),
|
||||||
{ok, UserName};
|
UserName;
|
||||||
_ ->
|
_ ->
|
||||||
ok = io:format("~nArglebargle, glop-glyf!?!~n~n"),
|
ok = io:format("~nArglebargle, glop-glyf!?!~n~n"),
|
||||||
create_user(U)
|
create_user(U)
|
||||||
@ -1137,6 +1131,136 @@ store_user(#user_data{realm = Realm,
|
|||||||
log(info, "User ~tp created.", [{Realm, UserName}]).
|
log(info, "User ~tp created.", [{Realm, UserName}]).
|
||||||
|
|
||||||
|
|
||||||
|
-spec create_userfile() -> ok.
|
||||||
|
|
||||||
|
create_userfile() ->
|
||||||
|
case select_realm() of
|
||||||
|
error -> {error, "No realms configured.", 61};
|
||||||
|
Realm -> create_userfile(Realm)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
create_userfile(Realm) ->
|
||||||
|
UserName = select_user(Realm),
|
||||||
|
UserConf = filename:join(zx_lib:path(etc, Realm), UserName ++ ".user"),
|
||||||
|
{ok, UserData} = file:consult(UserConf),
|
||||||
|
Keys = proplists:get_value(keys, UserData),
|
||||||
|
Load =
|
||||||
|
fun(KeyName, Acc) ->
|
||||||
|
case file:read_file(zx_key:path(public, {Realm, KeyName})) of
|
||||||
|
{ok, Data} -> [{KeyName, Data} | Acc];
|
||||||
|
_ -> Acc
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
PubKeyData = lists:foldl(Load, [], Keys),
|
||||||
|
UserFile = Realm ++ "-" ++ UserName ++ ".zpuf",
|
||||||
|
Bin = term_to_binary({UserData, PubKeyData}),
|
||||||
|
ok = file:write_file(UserFile, Bin),
|
||||||
|
Message =
|
||||||
|
"Wrote Zomp public user file to ~tp.~n"
|
||||||
|
"This file can be given to a sysop from ~tp and added to the realm.~n"
|
||||||
|
"It ONLY contains PUBLIC KEY data.~n",
|
||||||
|
io:format(Message, [UserFile, Realm]).
|
||||||
|
|
||||||
|
|
||||||
|
-spec export_user() -> ok.
|
||||||
|
|
||||||
|
export_user() ->
|
||||||
|
case select_realm() of
|
||||||
|
error -> {error, "No realms configured.", 61};
|
||||||
|
Realm -> export_user(Realm)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
export_user(Realm) ->
|
||||||
|
UserName = select_user(Realm),
|
||||||
|
UserConf = filename:join(zx_lib:path(etc, Realm), UserName ++ ".user"),
|
||||||
|
{ok, UserData} = file:consult(UserConf),
|
||||||
|
Keys = proplists:get_value(keys, UserData),
|
||||||
|
Load =
|
||||||
|
fun(KeyName, Acc) ->
|
||||||
|
Pub =
|
||||||
|
case file:read_file(zx_key:path(public, {Realm, KeyName})) of
|
||||||
|
{ok, PD} -> PD;
|
||||||
|
_ -> none
|
||||||
|
end,
|
||||||
|
Key =
|
||||||
|
case file:read_file(zx_key:path(private, {Realm, KeyName})) of
|
||||||
|
{ok, KD} -> KD;
|
||||||
|
_ -> none
|
||||||
|
end,
|
||||||
|
[{KeyName, Key, Pub} | Acc]
|
||||||
|
end,
|
||||||
|
KeyData = lists:foldl(Load, [], Keys),
|
||||||
|
UserFile = Realm ++ "-" ++ UserName ++ ".zduf",
|
||||||
|
Bin = term_to_binary({UserData, KeyData}),
|
||||||
|
ok = file:write_file(UserFile, Bin),
|
||||||
|
Message =
|
||||||
|
"Wrote Zomp DANGEROUS user file to ~tp.~n"
|
||||||
|
"WARNING: This file contains your PRIVATE KEYS and should NEVER be shared with "
|
||||||
|
"anyone. Its only use is for the \"import user [.zduf]\" command!~n",
|
||||||
|
io:format(Message, [UserFile]).
|
||||||
|
|
||||||
|
|
||||||
|
-spec import_user(file:filename()) -> zx:outcome().
|
||||||
|
|
||||||
|
import_user(ZDUF) ->
|
||||||
|
case file:read_file(ZDUF) of
|
||||||
|
{ok, Bin} -> import_user2(Bin);
|
||||||
|
{error, enoent} -> {error, "Bad path/missing file.", 2};
|
||||||
|
{error, eacces} -> {error, "Can't read file: bad permissions.", 13};
|
||||||
|
{error, eisdir} -> {error, "The path provided is a directory.", 21};
|
||||||
|
Error -> Error
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
import_user2(Bin) ->
|
||||||
|
case zx_lib:b_to_t(Bin) of
|
||||||
|
{ok, {UserData, []}} ->
|
||||||
|
ok = log(info, "Note: This user file does not have any keys."),
|
||||||
|
import_user3(UserData, []);
|
||||||
|
{ok, {UserData, KeyData}} ->
|
||||||
|
import_user3(UserData, KeyData);
|
||||||
|
error ->
|
||||||
|
{error, "Bad .zduf data. Is this really a legitimate .zduf?", 1}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
import_user3(UserData, KeyData) ->
|
||||||
|
Realm = proplists:get_value(realm, UserData),
|
||||||
|
UserName = proplists:get_value(username, UserData),
|
||||||
|
case filelib:is_dir(zx_lib:path(etc, Realm)) of
|
||||||
|
true ->
|
||||||
|
UserConf = filename:join(zx_lib:path(etc, Realm), UserName ++ ".user"),
|
||||||
|
ok = zx_lib:write_terms(UserConf, UserData),
|
||||||
|
import_user4(Realm, UserName, KeyData);
|
||||||
|
false ->
|
||||||
|
{error, "User is from a realm which is not available locally.", 1}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
import_user4(Realm, UserName, KeyData) ->
|
||||||
|
Write =
|
||||||
|
fun
|
||||||
|
({KeyName, KeyBin, none}) ->
|
||||||
|
KeyID = {Realm, KeyName},
|
||||||
|
file:write_file(zx_key:path(private, KeyID), KeyBin);
|
||||||
|
({KeyName, none, PubBin}) ->
|
||||||
|
KeyID = {Realm, KeyName},
|
||||||
|
file:write_file(zx_key:path(public, KeyID), PubBin);
|
||||||
|
({KeyName, KeyBin, PubBin}) ->
|
||||||
|
KeyID = {Realm, KeyName},
|
||||||
|
file:write_file(zx_key:path(private, KeyID), KeyBin),
|
||||||
|
file:write_file(zx_key:path(public, KeyID), PubBin);
|
||||||
|
({KeyName, PubBin}) ->
|
||||||
|
ok = log(info, "This file is probably a .zpuf, not a .zduf"),
|
||||||
|
KeyID = {Realm, KeyName},
|
||||||
|
file:write_file(zx_key:path(public, KeyID), PubBin)
|
||||||
|
end,
|
||||||
|
ok = lists:foreach(Write, KeyData),
|
||||||
|
log(info, "Imported user ~ts to realm ~ts.", [UserName, Realm]).
|
||||||
|
|
||||||
|
|
||||||
-spec list_users(Realm) -> UserNames
|
-spec list_users(Realm) -> UserNames
|
||||||
when Realm :: zx:realm(),
|
when Realm :: zx:realm(),
|
||||||
UserNames :: [zx:user_name()].
|
UserNames :: [zx:user_name()].
|
||||||
@ -1280,18 +1404,23 @@ make_realm_dirs(Realm) ->
|
|||||||
% io:format("~tp~n", [ZompSettings]).
|
% io:format("~tp~n", [ZompSettings]).
|
||||||
|
|
||||||
|
|
||||||
-spec create_realmfile(Realm, Dir) -> ok
|
-spec create_realmfile() -> ok.
|
||||||
when Realm :: zx:realm(),
|
|
||||||
Dir :: file:filename().
|
|
||||||
|
|
||||||
create_realmfile(Realm, Dir) ->
|
create_realmfile() ->
|
||||||
|
Realm = select_realm(),
|
||||||
|
create_realmfile(Realm).
|
||||||
|
|
||||||
|
|
||||||
|
-spec create_realmfile(zx:realm()) -> ok.
|
||||||
|
|
||||||
|
create_realmfile(Realm) ->
|
||||||
{ok, RealmConf} = zx_lib:load_realm_conf(Realm),
|
{ok, RealmConf} = zx_lib:load_realm_conf(Realm),
|
||||||
ok = log(info, "Realm found, creating realm file..."),
|
ok = log(info, "Realm found, creating realm file..."),
|
||||||
KeyName = maps:get(key, RealmConf),
|
KeyName = maps:get(key, RealmConf),
|
||||||
PubKeyPath = zx_key:path(public, {Realm, KeyName}),
|
PubKeyPath = zx_key:path(public, {Realm, KeyName}),
|
||||||
{ok, PubDER} = file:read_file(PubKeyPath),
|
{ok, PubDER} = file:read_file(PubKeyPath),
|
||||||
Blob = term_to_binary({RealmConf, PubDER}),
|
Blob = term_to_binary({RealmConf, PubDER}),
|
||||||
ZRF = filename:join(Dir, Realm ++ ".zrf"),
|
ZRF = Realm ++ ".zrf",
|
||||||
ok = file:write_file(ZRF, Blob),
|
ok = file:write_file(ZRF, Blob),
|
||||||
log(info, "Realm conf file written to ~ts", [ZRF]).
|
log(info, "Realm conf file written to ~ts", [ZRF]).
|
||||||
|
|
||||||
@ -1341,3 +1470,86 @@ abdicate(Realm) ->
|
|||||||
{ok, NewConf} -> zx_sys_conf:save(NewConf);
|
{ok, NewConf} -> zx_sys_conf:save(NewConf);
|
||||||
{error, unmanaged} -> log(error, "Cannot abdicate an unmanaged realm.")
|
{error, unmanaged} -> log(error, "Cannot abdicate an unmanaged realm.")
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec set_timeout(string()) -> zx:outcome().
|
||||||
|
|
||||||
|
set_timeout(String) ->
|
||||||
|
case string:to_integer(String) of
|
||||||
|
{Value, ""} when Value > 0 ->
|
||||||
|
zx_sys_conf:save(zx_sys_conf:timeout(Value, zx_sys_conf:load()));
|
||||||
|
_ ->
|
||||||
|
{error, "Enter a positive integer. Common values are 3, 5 and 10.", 22}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec add_mirror() -> ok.
|
||||||
|
|
||||||
|
add_mirror() ->
|
||||||
|
ok = log(info, "Adding a mirror to the local configuration..."),
|
||||||
|
SysConf = zx_sys_conf:load(),
|
||||||
|
ok =
|
||||||
|
case zx_sys_conf:mirrors(SysConf) of
|
||||||
|
[] ->
|
||||||
|
ok;
|
||||||
|
Current ->
|
||||||
|
ok = io:format("Current mirrors:~n"),
|
||||||
|
Print =
|
||||||
|
fun({A, P}) ->
|
||||||
|
S = stringify_address(A),
|
||||||
|
io:format("* ~s:~w~n", [S, P])
|
||||||
|
end,
|
||||||
|
lists:foreach(Print, Current)
|
||||||
|
end,
|
||||||
|
Host = ask_addr(),
|
||||||
|
Port = ask_port(),
|
||||||
|
zx_sys_conf:save(zx_sys_conf:add_mirror({Host, Port}, SysConf)).
|
||||||
|
|
||||||
|
|
||||||
|
-spec drop_mirror() -> ok.
|
||||||
|
|
||||||
|
drop_mirror() ->
|
||||||
|
ok = log(info, "Removing mirrors from the local configuration..."),
|
||||||
|
SysConf = zx_sys_conf:load(),
|
||||||
|
zx_sys_conf:save(drop_mirror(SysConf)).
|
||||||
|
|
||||||
|
|
||||||
|
-spec drop_mirror(zx_sys_conf:data()) -> zx_sys_conf:data().
|
||||||
|
|
||||||
|
drop_mirror(SysConf) ->
|
||||||
|
case zx_sys_conf:mirrors(SysConf) of
|
||||||
|
[] ->
|
||||||
|
ok = log(info, "No mirrors to drop!"),
|
||||||
|
SysConf;
|
||||||
|
Current ->
|
||||||
|
ok = io:format("Pick a host to drop:~n"),
|
||||||
|
Optionize =
|
||||||
|
fun(Host = {A, P}) ->
|
||||||
|
Label = io_lib:format("~s:~w", [stringify_address(A), P]),
|
||||||
|
{Label, Host}
|
||||||
|
end,
|
||||||
|
Options = lists:map(Optionize, Current),
|
||||||
|
Selection = zx_tty:select(Options),
|
||||||
|
zx_sys_conf:rem_mirror(Selection, SysConf)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec select_realm() -> {ok, zx:realm()} | error.
|
||||||
|
|
||||||
|
select_realm() ->
|
||||||
|
case zx_lib:list_realms() of
|
||||||
|
[] -> error;
|
||||||
|
[Realm] -> Realm;
|
||||||
|
Realms -> zx_tty:select_string(Realms)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
-spec select_user(zx:realm()) -> zx:user_name().
|
||||||
|
|
||||||
|
select_user(Realm) ->
|
||||||
|
Pattern = filename:join(zx_lib:path(etc, Realm), "*.user"),
|
||||||
|
case [filename:basename(F, ".user") || F <- filelib:wildcard(Pattern)] of
|
||||||
|
[] -> create_user(#user_data{realm = Realm});
|
||||||
|
[UserName] -> UserName;
|
||||||
|
UserNames -> zx_tty:select_string(UserNames)
|
||||||
|
end.
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
retries = 3 :: non_neg_integer(),
|
retries = 3 :: non_neg_integer(),
|
||||||
maxconn = 5 :: pos_integer(),
|
maxconn = 5 :: pos_integer(),
|
||||||
managed = sets:new() :: sets:set(zx:realm()),
|
managed = sets:new() :: sets:set(zx:realm()),
|
||||||
mirrors = [] :: [zx:host()]}).
|
mirrors = sets:new() :: sets:set(zx:host())}).
|
||||||
|
|
||||||
-opaque data() :: #d{}.
|
-opaque data() :: #d{}.
|
||||||
|
|
||||||
@ -92,8 +92,8 @@ populate_data(List) ->
|
|||||||
end,
|
end,
|
||||||
Mirrors =
|
Mirrors =
|
||||||
case proplists:get_value(mirrors, List, []) of
|
case proplists:get_value(mirrors, List, []) of
|
||||||
MR when is_list(MR) -> MR;
|
MR when is_list(MR) -> sets:from_list(MR);
|
||||||
_ -> []
|
_ -> sets:new()
|
||||||
end,
|
end,
|
||||||
#d{timeout = Timeout,
|
#d{timeout = Timeout,
|
||||||
retries = Retries,
|
retries = Retries,
|
||||||
@ -116,7 +116,7 @@ save(#d{timeout = Timeout,
|
|||||||
{retries, Retries},
|
{retries, Retries},
|
||||||
{maxconn, MaxConn},
|
{maxconn, MaxConn},
|
||||||
{managed, sets:to_list(Managed)},
|
{managed, sets:to_list(Managed)},
|
||||||
{mirrors, Mirrors}],
|
{mirrors, sets:to_list(Mirrors)}],
|
||||||
ok = zx_lib:write_terms(path(), Terms),
|
ok = zx_lib:write_terms(path(), Terms),
|
||||||
log(info, "Wrote etc/sys.conf").
|
log(info, "Wrote etc/sys.conf").
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ timeout(#d{timeout = Timeout}) ->
|
|||||||
%% @doc
|
%% @doc
|
||||||
%% Set the timeout attribute to a new value.
|
%% Set the timeout attribute to a new value.
|
||||||
|
|
||||||
timeout(Value, Data) when is_integer(Value) and Value > 0 ->
|
timeout(Value, Data) when Value > 0 ->
|
||||||
Data#d{timeout = Value}.
|
Data#d{timeout = Value}.
|
||||||
|
|
||||||
|
|
||||||
@ -275,7 +275,7 @@ rem_managed(Realm, Data = #d{managed = Managed}) ->
|
|||||||
%% Return the list of private mirrors.
|
%% Return the list of private mirrors.
|
||||||
|
|
||||||
mirrors(#d{mirrors = Mirrors}) ->
|
mirrors(#d{mirrors = Mirrors}) ->
|
||||||
Mirrors.
|
sets:to_list(Mirrors).
|
||||||
|
|
||||||
|
|
||||||
-spec mirrors(Hosts, Data) -> NewData
|
-spec mirrors(Hosts, Data) -> NewData
|
||||||
@ -286,7 +286,7 @@ mirrors(#d{mirrors = Mirrors}) ->
|
|||||||
%% Reset the mirror configuration.
|
%% Reset the mirror configuration.
|
||||||
|
|
||||||
mirrors(Hosts, Data) ->
|
mirrors(Hosts, Data) ->
|
||||||
Data#d{mirrors = Hosts}.
|
Data#d{mirrors = sets:from_list(Hosts)}.
|
||||||
|
|
||||||
|
|
||||||
-spec add_mirror(Host, Data) -> NewData
|
-spec add_mirror(Host, Data) -> NewData
|
||||||
@ -296,11 +296,8 @@ mirrors(Hosts, Data) ->
|
|||||||
%% @doc
|
%% @doc
|
||||||
%% Add a mirror to the permanent configuration.
|
%% Add a mirror to the permanent configuration.
|
||||||
|
|
||||||
add_mirror(Data = #d{mirrors = Mirrors}, Host) ->
|
add_mirror(Host, Data = #d{mirrors = Mirrors}) ->
|
||||||
case lists:member(Host, Mirrors) of
|
Data#d{mirrors = sets:add_element(Host, Mirrors)}.
|
||||||
false -> Data#d{mirrors = [Host | Mirrors]};
|
|
||||||
true -> Data
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
-spec rem_mirror(Host, Data) -> NewData
|
-spec rem_mirror(Host, Data) -> NewData
|
||||||
@ -311,7 +308,7 @@ add_mirror(Data = #d{mirrors = Mirrors}, Host) ->
|
|||||||
%% Remove a host from the list of permanent mirrors.
|
%% Remove a host from the list of permanent mirrors.
|
||||||
|
|
||||||
rem_mirror(Host, Data = #d{mirrors = Mirrors}) ->
|
rem_mirror(Host, Data = #d{mirrors = Mirrors}) ->
|
||||||
Data#d{mirrors = lists:delete(Host, Mirrors)}.
|
Data#d{mirrors = sets:del_element(Host, Mirrors)}.
|
||||||
|
|
||||||
|
|
||||||
-spec reset() -> data().
|
-spec reset() -> data().
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user