File 4292-Read-other-nodes-cookies-from-command-line.patch of Package erlang
From 1bdda7678df6cbf93b42758c8cbc1b0dcbeadc12 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Thu, 29 Jul 2021 12:25:11 +0200
Subject: [PATCH 2/9] Read other nodes' cookies from command line
---
erts/doc/src/erl_cmd.xml | 8 +-
lib/kernel/src/auth.erl | 105 +++++++++++++++-----
system/doc/reference_manual/distributed.xml | 6 +-
3 files changed, 92 insertions(+), 27 deletions(-)
diff --git a/erts/doc/src/erl_cmd.xml b/erts/doc/src/erl_cmd.xml
index 4d59a64b10..c28632ec7a 100644
--- a/erts/doc/src/erl_cmd.xml
+++ b/erts/doc/src/erl_cmd.xml
@@ -629,6 +629,12 @@ $ <input>erl \
<seemfa marker="erlang#set_cookie/2">
<c>erlang:set_cookie/2</c></seemfa>.</p>
</item>
+ <tag><c><![CDATA[-setcookie Node Cookie]]></c></tag>
+ <item>
+ <p>Sets the magic cookie of Node to <c><![CDATA[Cookie]]></c>; see
+ <seemfa marker="erlang#set_cookie/2">
+ <c>erlang:set_cookie/2</c></seemfa>.</p>
+ </item>
<tag><c><![CDATA[-shutdown_time Time]]></c></tag>
<item>
<p>Specifies how long time (in milliseconds) the <c><![CDATA[init]]></c>
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index e552758a0d..6fb4267eb4 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -271,35 +271,90 @@ getnode(P) -> P.
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Read cookie from $HOME/.erlang.cookie and set it.
+%% Read and set cookie from command line or $HOME/.erlang.cookie.
init_cookie() ->
+ case init:get_argument(setcookie) of
+ error ->
+ init_no_setcookie();
+ {ok, Setcookie} ->
+ init_setcookie(Setcookie, [], #{})
+ end.
+
+%% No -setcookie argument
+init_no_setcookie() ->
case init:get_argument(nocookie) of
- error ->
- case init:get_argument(setcookie) of
- {ok, [[C0]]} ->
- C = list_to_atom(C0),
- #state{our_cookie = C,
- other_cookies = ets:new(cookies,
- [?COOKIE_ETS_PROTECTION])};
- _ ->
- %% Here is the default
- case read_cookie() of
- {error, Error} ->
- error_logger:error_msg(Error, []),
- %% Is this really this serious?
- erlang:error(Error);
- {ok, Co} ->
- #state{our_cookie = list_to_atom(Co),
- other_cookies = ets:new(
- cookies,
- [?COOKIE_ETS_PROTECTION])}
- end
- end;
- _Other ->
- #state{our_cookie = nocookie,
- other_cookies = ets:new(cookies, [?COOKIE_ETS_PROTECTION])}
+ error ->
+ %% Here is the default
+ %% - no -setcookie nor -nocookie argument
+ case read_cookie() of
+ {error, Error} ->
+ error_logger:error_msg(Error, []),
+ %% Is this really this serious?
+ erlang:error(Error);
+ {ok, Co} ->
+ #state{our_cookie = list_to_atom(Co),
+ other_cookies = ets_new_cookies()}
+ end;
+ {ok, Nocookie} when is_list(Nocookie) ->
+ %% Ignore the value
+ #state{our_cookie = nocookie,
+ other_cookies = ets_new_cookies()}
end.
+%% Process -setcookie options
+init_setcookie([SetCo | Setcookie], OurCookies, OtherCookies) ->
+ case SetCo of
+ %% Collect arity 0 and 1 options as our cookie
+ [] ->
+ init_setcookie(Setcookie, [SetCo | OurCookies], OtherCookies);
+ [_] ->
+ init_setcookie(Setcookie, [SetCo | OurCookies], OtherCookies);
+ [Node, Co] ->
+ %% Collect arity 2 options as other nodes' cookies
+ init_setcookie(
+ Setcookie, OurCookies,
+ case OtherCookies of
+ #{Node := _} ->
+ %% If a node's cookie is set more than once
+ %% we pretend it was not set, a'la how
+ %% setting our own cookie is handled
+ OtherCookies#{Node := undefined};
+ #{} ->
+ OtherCookies#{Node => Co}
+ end);
+ _ when is_list(SetCo) ->
+ %% Ignore options of arity 3 or more, which changes
+ %% legacy behaviour which was to ignore our own
+ %% cookie due to invalid arity (only valid was 1)
+ init_setcookie(Setcookie, OurCookies, OtherCookies)
+ end;
+init_setcookie([], OurCookies, OtherCookies) ->
+ %% Options collected - handle them
+ State =
+ case OurCookies of
+ [[Co]] ->
+ %% We have no arity 0 and exactly one arity 1
+ %% option i.e our cookie
+ #state{
+ our_cookie = list_to_atom(Co),
+ other_cookies = ets_new_cookies()};
+ _ when is_list(OurCookies) ->
+ %% Any other combination of arity 0 and 1 options
+ %% makes us pretend they were not there;
+ %% legacy behaviour - we have no set cookie
+ init_no_setcookie()
+ end,
+ %% Register all other node's cookies (arity 2 options)
+ ets:insert(
+ State#state.other_cookies,
+ [{list_to_atom(Node), list_to_atom(Co)} ||
+ {Node, Co} <- maps:to_list(OtherCookies),
+ Co =/= undefined]),
+ State.
+
+ets_new_cookies() ->
+ ets:new(cookies, [?COOKIE_ETS_PROTECTION]).
+
read_cookie() ->
case init:get_argument(home) of
{ok, [[Home]]} ->
diff --git a/system/doc/reference_manual/distributed.xml b/system/doc/reference_manual/distributed.xml
index 38cb99dd0d..832a87c2d4 100644
--- a/system/doc/reference_manual/distributed.xml
+++ b/system/doc/reference_manual/distributed.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2017</year>
+ <year>2003</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -273,6 +273,10 @@ dilbert@uab</pre>
<cell align="left" valign="middle"><c>-setcookie Cookie</c></cell>
<cell align="left" valign="middle">Same as calling <c>erlang:set_cookie(node(), Cookie)</c>.</cell>
</row>
+ <row>
+ <cell align="left" valign="middle"><c>-setcookie Node Cookie</c></cell>
+ <cell align="left" valign="middle">Same as calling <c>erlang:set_cookie(Node, Cookie)</c>.</cell>
+ </row>
<row>
<cell align="left" valign="middle"><c>-sname Name</c></cell>
<cell align="left" valign="middle">Makes a runtime system into a node, using short node names.</cell>
--
2.31.1