aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src')
-rw-r--r--lib/kernel/src/Makefile1
-rw-r--r--lib/kernel/src/code.erl2
-rw-r--r--lib/kernel/src/disk_log.erl7
-rw-r--r--lib/kernel/src/disk_log.hrl6
-rw-r--r--lib/kernel/src/disk_log_1.erl28
-rw-r--r--lib/kernel/src/dist_ac.erl2
-rw-r--r--lib/kernel/src/dist_util.erl2
-rw-r--r--lib/kernel/src/erl_signal_handler.erl2
-rw-r--r--lib/kernel/src/error_logger.erl22
-rw-r--r--lib/kernel/src/file.erl2
-rw-r--r--lib/kernel/src/global.erl5
-rw-r--r--lib/kernel/src/group.erl3
-rw-r--r--lib/kernel/src/group_history.erl341
-rw-r--r--lib/kernel/src/inet.erl10
-rw-r--r--lib/kernel/src/inet_int.hrl3
-rw-r--r--lib/kernel/src/inet_parse.erl2
-rw-r--r--lib/kernel/src/inet_udp.erl2
-rw-r--r--lib/kernel/src/kernel.app.src1
-rw-r--r--lib/kernel/src/kernel.appup.src2
-rw-r--r--lib/kernel/src/kernel.erl4
-rw-r--r--lib/kernel/src/net_kernel.erl40
-rw-r--r--lib/kernel/src/os.erl2
-rw-r--r--lib/kernel/src/rpc.erl2
23 files changed, 454 insertions, 37 deletions
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index 2a89faaf13..78aa6192a9 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -85,6 +85,7 @@ MODULES = \
global_group \
global_search \
group \
+ group_history \
heart \
hipe_unified_loader \
inet \
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 2a06d0cb15..9969021a6c 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 2ade7fd77a..70cbf1c87c 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -638,6 +638,8 @@ check_arg([{mode, read_only}|Tail], Res) ->
check_arg(Tail, Res#arg{mode = read_only});
check_arg([{mode, read_write}|Tail], Res) ->
check_arg(Tail, Res#arg{mode = read_write});
+check_arg([{quiet, Boolean}|Tail], Res) when is_boolean(Boolean) ->
+ check_arg(Tail, Res#arg{quiet = Boolean});
check_arg(Arg, _) ->
{error, {badarg, Arg}}.
@@ -1276,7 +1278,8 @@ compare_arg(_Attr, _Val, _A) ->
do_open(A) ->
#arg{type = Type, format = Format, name = Name, head = Head0,
file = FName, repair = Repair, size = Size, mode = Mode,
- version = V} = A,
+ quiet = Quiet, version = V} = A,
+ disk_log_1:set_quiet(Quiet),
Head = mk_head(Head0, Format),
case do_open2(Type, Format, Name, FName, Repair, Size, Mode, Head, V) of
{ok, Ret, Extra, FormatType, NoItems} ->
diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl
index 593dbb31ab..a362881f40 100644
--- a/lib/kernel/src/disk_log.hrl
+++ b/lib/kernel/src/disk_log.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -69,13 +69,14 @@
| {file, FileName :: file:filename()}
| {linkto, LinkTo :: none | pid()}
| {repair, Repair :: true | false | truncate}
- | {type, Type :: dlog_type}
+ | {type, Type :: dlog_type()}
| {format, Format :: dlog_format()}
| {size, Size :: dlog_size()}
| {distributed, Nodes :: [node()]}
| {notify, boolean()}
| {head, Head :: dlog_head_opt()}
| {head_func, MFA :: {atom(), atom(), list()}}
+ | {quiet, boolean()}
| {mode, Mode :: dlog_mode()}.
-type dlog_options() :: [dlog_option()].
-type dlog_repair() :: 'truncate' | boolean().
@@ -102,6 +103,7 @@
head = none,
mode = read_write :: dlog_mode(),
notify = false :: boolean(),
+ quiet = false :: boolean(),
options = [] :: dlog_options()}).
-record(cache, %% Cache for logged terms (per file descriptor).
diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl
index d83c30f35f..10c22e1ad6 100644
--- a/lib/kernel/src/disk_log_1.erl
+++ b/lib/kernel/src/disk_log_1.erl
@@ -37,6 +37,7 @@
-export([get_wrap_size/1]).
-export([is_head/1]).
-export([position/3, truncate_at/3, fwrite/4, fclose/2]).
+-export([set_quiet/1, is_quiet/0]).
-compile({inline,[{scan_f2,7}]}).
@@ -500,7 +501,10 @@ lh(H, _F) -> % cannot happen
repair(In, File) ->
FSz = file_size(File),
- error_logger:info_msg("disk_log: repairing ~tp ...\n", [File]),
+ case is_quiet() of
+ true -> ok;
+ _ -> error_logger:info_msg("disk_log: repairing ~tp ...\n", [File])
+ end,
Tmp = add_ext(File, "TMP"),
{ok, {_Alloc, Out, {0, _}, _FileSize}} = new_int_file(Tmp, none),
scan_f_read(<<>>, In, Out, File, FSz, Tmp, ?MAX_CHUNK_SIZE, 0, 0).
@@ -769,8 +773,11 @@ mf_int_chunk(Handle, {FileNo, Pos}, Bin, N) ->
NFileNo = inc(FileNo, Handle#handle.maxF),
case catch int_open(FName, true, read_only, any) of
{error, _Reason} ->
- error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
- [FName]),
+ case is_quiet() of
+ true -> ok;
+ _ -> error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
+ [FName])
+ end,
mf_int_chunk(Handle, {NFileNo, 0}, [], N);
{ok, {_Alloc, FdC, _HeadSize, _FileSize}} ->
case chunk(FdC, FName, Pos, Bin, N) of
@@ -797,9 +804,12 @@ mf_int_chunk_read_only(Handle, {FileNo, Pos}, Bin, N) ->
NFileNo = inc(FileNo, Handle#handle.maxF),
case catch int_open(FName, true, read_only, any) of
{error, _Reason} ->
- error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
- [FName]),
- mf_int_chunk_read_only(Handle, {NFileNo, 0}, [], N);
+ case is_quiet() of
+ true -> ok;
+ _ -> error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
+ [FName])
+ end,
+ mf_int_chunk_read_only(Handle, {NFileNo, 0}, [], N);
{ok, {_Alloc, FdC, _HeadSize, _FileSize}} ->
case do_chunk_read_only(FdC, FName, Pos, Bin, N) of
{NewFdC, eof} ->
@@ -1549,6 +1559,12 @@ fclose(#cache{fd = Fd, c = C}, FileName) ->
_ = write_cache_close(Fd, FileName, C),
file:close(Fd).
+set_quiet(Bool) ->
+ put(quiet, Bool).
+
+is_quiet() ->
+ get(quiet) =:= true.
+
%% -> {Reply, #cache{}}; Reply = ok | Error
write_cache(Fd, _FileName, []) ->
{ok, #cache{fd = Fd}};
diff --git a/lib/kernel/src/dist_ac.erl b/lib/kernel/src/dist_ac.erl
index e63c969b79..2a5cf0ba92 100644
--- a/lib/kernel/src/dist_ac.erl
+++ b/lib/kernel/src/dist_ac.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index d929179715..1c326afca8 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl
index 8f924d2adc..22f235d4e4 100644
--- a/lib/kernel/src/erl_signal_handler.erl
+++ b/lib/kernel/src/erl_signal_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index 3ee8e2c6e6..9bf8547745 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,6 +31,8 @@
handle_event/2, handle_call/2, handle_info/2,
terminate/2]).
+-export([get_format_depth/0, limit_term/1]).
+
-define(buffer_size, 10).
%%-----------------------------------------------------------------
@@ -518,3 +520,21 @@ string_p1([H|T]) when is_list(H) ->
end;
string_p1([]) -> true;
string_p1(_) -> false.
+
+-spec limit_term(term()) -> term().
+
+limit_term(Term) ->
+ case get_format_depth() of
+ unlimited -> Term;
+ D -> io_lib:limit_term(Term, D)
+ end.
+
+-spec get_format_depth() -> 'unlimited' | pos_integer().
+
+get_format_depth() ->
+ case application:get_env(kernel, error_logger_format_depth) of
+ {ok, Depth} when is_integer(Depth) ->
+ max(10, Depth);
+ undefined ->
+ unlimited
+ end.
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 79e72cdc6d..933f2d5f65 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index 5e8bc2ba5d..a9e92b28b8 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -447,7 +447,8 @@ info() ->
init([]) ->
process_flag(trap_exit, true),
_ = ets:new(global_locks, [set, named_table, protected]),
- _ = ets:new(global_names, [set, named_table, protected]),
+ _ = ets:new(global_names, [set, named_table, protected,
+ {read_concurrency, true}]),
_ = ets:new(global_names_ext, [set, named_table, protected]),
_ = ets:new(global_pid_names, [bag, named_table, protected]),
diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl
index b5e73117dd..0eeaaad8d2 100644
--- a/lib/kernel/src/group.erl
+++ b/lib/kernel/src/group.erl
@@ -33,7 +33,7 @@ start(Drv, Shell, Options) ->
server(Drv, Shell, Options) ->
process_flag(trap_exit, true),
edlin:init(),
- put(line_buffer, proplists:get_value(line_buffer, Options, [])),
+ put(line_buffer, proplists:get_value(line_buffer, Options, group_history:load())),
put(read_mode, list),
put(user_drv, Drv),
put(expand_fun,
@@ -783,6 +783,7 @@ save_line_buffer("\n", Lines) ->
save_line_buffer(Line, [Line|_Lines]=Lines) ->
save_line_buffer(Lines);
save_line_buffer(Line, Lines) ->
+ group_history:add(Line),
save_line_buffer([Line|Lines]).
save_line_buffer(Lines) ->
diff --git a/lib/kernel/src/group_history.erl b/lib/kernel/src/group_history.erl
new file mode 100644
index 0000000000..5ca5e2d1dd
--- /dev/null
+++ b/lib/kernel/src/group_history.erl
@@ -0,0 +1,341 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(group_history).
+-export([load/0, add/1]).
+
+%% Make a minimal size that should encompass set of lines and then make
+%% a file rotation for N files of this size.
+-define(DEFAULT_HISTORY_FILE, "erlang-shell-log").
+-define(MAX_HISTORY_FILES, 10).
+-define(DEFAULT_SIZE, 1024*512). % 512 kb total default
+-define(DEFAULT_STATUS, disabled).
+-define(MIN_HISTORY_SIZE, (50*1024)). % 50 kb, in bytes
+-define(DEFAULT_DROP, []).
+-define(DISK_LOG_FORMAT, internal). % since we want repairs
+-define(LOG_NAME, '$#group_history').
+-define(VSN, {0,1,0}).
+
+%%%%%%%%%%%%%%
+%%% PUBLIC %%%
+%%%%%%%%%%%%%%
+
+%% @doc Loads the shell history from memory. This function should only be
+%% called from group:server/3 to inject itself in the previous commands
+%% stack.
+-spec load() -> [string()].
+load() ->
+ wait_for_kernel_safe_sup(),
+ case history_status() of
+ enabled ->
+ case open_log() of
+ {ok, ?LOG_NAME} ->
+ read_full_log(?LOG_NAME);
+ {repaired, ?LOG_NAME, {recovered, Good}, {badbytes, Bad}} ->
+ report_repairs(?LOG_NAME, Good, Bad),
+ read_full_log(?LOG_NAME);
+ {error, {need_repair, _FileName}} ->
+ repair_log(?LOG_NAME);
+ {error, {arg_mismatch, repair, true, false}} ->
+ repair_log(?LOG_NAME);
+ {error, {name_already_open, _}} ->
+ show_rename_warning(),
+ read_full_log(?LOG_NAME);
+ {error, {size_mismatch, Current, New}} ->
+ show_size_warning(Current, New),
+ resize_log(?LOG_NAME, Current, New),
+ load();
+ {error, {invalid_header, {vsn, Version}}} ->
+ upgrade_version(?LOG_NAME, Version),
+ load();
+ {error, Reason} ->
+ handle_open_error(Reason),
+ disable_history(),
+ []
+ end;
+ _ ->
+ []
+ end.
+
+%% @doc adds a log line to the erlang history log, if configured to do so.
+-spec add(iodata()) -> ok.
+add(Line) -> add(Line, history_status()).
+
+add(Line, enabled) ->
+ case lists:member(Line, to_drop()) of
+ false ->
+ case disk_log:log(?LOG_NAME, Line) of
+ ok ->
+ ok;
+ {error, no_such_log} ->
+ _ = open_log(), % a wild attempt we hope works!
+ disk_log:log(?LOG_NAME, Line);
+ {error, _Other} ->
+ % just ignore, we're too late
+ ok
+ end;
+ true ->
+ ok
+ end;
+add(_Line, disabled) ->
+ ok.
+
+%%%%%%%%%%%%%%%
+%%% PRIVATE %%%
+%%%%%%%%%%%%%%%
+
+%% Because loading the shell happens really damn early, processes we depend on
+%% might not be there yet. Luckily, the load function is called from the shell
+%% after a new process has been spawned, so we can block in here
+wait_for_kernel_safe_sup() ->
+ case whereis(kernel_safe_sup) of
+ undefined ->
+ timer:sleep(50),
+ wait_for_kernel_safe_sup();
+ _ ->
+ ok
+ end.
+
+%% Repair the log out of band
+repair_log(Name) ->
+ Opts = lists:keydelete(size, 1, log_options()),
+ case disk_log:open(Opts) of
+ {repaired, ?LOG_NAME, {recovered, Good}, {badbytes, Bad}} ->
+ report_repairs(?LOG_NAME, Good, Bad);
+ _ ->
+ ok
+ end,
+ _ = disk_log:close(Name),
+ load().
+
+%% Return whether the shell history is enabled or not
+-spec history_status() -> enabled | disabled.
+history_status() ->
+ case is_user() orelse application:get_env(kernel, shell_history) of
+ true -> disabled; % don't run for user proc
+ {ok, enabled} -> enabled;
+ undefined -> ?DEFAULT_STATUS;
+ _ -> disabled
+ end.
+
+%% Return whether the user process is running this
+-spec is_user() -> boolean().
+is_user() ->
+ case process_info(self(), registered_name) of
+ {registered_name, user} -> true;
+ _ -> false
+ end.
+
+%% Open a disk_log file while ensuring the required path is there.
+open_log() ->
+ Opts = log_options(),
+ _ = ensure_path(Opts),
+ disk_log:open(Opts).
+
+%% Return logger options
+log_options() ->
+ Path = find_path(),
+ File = filename:join([Path, ?DEFAULT_HISTORY_FILE]),
+ Size = find_wrap_values(),
+ [{name, ?LOG_NAME},
+ {file, File},
+ {repair, true},
+ {format, internal},
+ {type, wrap},
+ {size, Size},
+ {distributed, []},
+ {notify, false},
+ {head, {vsn, ?VSN}},
+ {quiet, true},
+ {mode, read_write}].
+
+-spec ensure_path([{file, string()} | {atom(), _}, ...]) -> ok | {error, term()}.
+ensure_path(Opts) ->
+ {file, Path} = lists:keyfind(file, 1, Opts),
+ filelib:ensure_dir(Path).
+
+%% @private read the logs from an already open file. Treat closed files
+%% as wrong and returns an empty list to avoid crash loops in the shell.
+-spec read_full_log(term()) -> [string()].
+read_full_log(Name) ->
+ case disk_log:chunk(Name, start) of
+ {error, no_such_log} ->
+ show_unexpected_close_warning(),
+ [];
+ eof ->
+ [];
+ {Cont, Logs} ->
+ lists:reverse(maybe_drop_header(Logs) ++ read_full_log(Name, Cont))
+ end.
+
+read_full_log(Name, Cont) ->
+ case disk_log:chunk(Name, Cont) of
+ {error, no_such_log} ->
+ show_unexpected_close_warning(),
+ [];
+ eof ->
+ [];
+ {NextCont, Logs} ->
+ maybe_drop_header(Logs) ++ read_full_log(Name, NextCont)
+ end.
+
+maybe_drop_header([{vsn, _} | Rest]) -> Rest;
+maybe_drop_header(Logs) -> Logs.
+
+-spec handle_open_error(_) -> ok.
+handle_open_error({arg_mismatch, OptName, CurrentVal, NewVal}) ->
+ show('$#erlang-history-arg-mismatch',
+ "Log file argument ~p changed value from ~p to ~p "
+ "and cannot be automatically updated. Please clear the "
+ "history files and try again.~n",
+ [OptName, CurrentVal, NewVal]);
+handle_open_error({not_a_log_file, FileName}) ->
+ show_invalid_file_warning(FileName);
+handle_open_error({invalid_index_file, FileName}) ->
+ show_invalid_file_warning(FileName);
+handle_open_error({invalid_header, Term}) ->
+ show('$#erlang-history-invalid-header',
+ "Shell history expects to be able to use the log files "
+ "which currently have unknown headers (~p) and may belong to "
+ "another mechanism. History logging will be "
+ "disabled.~n",
+ [Term]);
+handle_open_error({file_error, FileName, Reason}) ->
+ show('$#erlang-history-file-error',
+ "Error handling File ~s. Reason: ~p~n"
+ "History logging will be disabled.~n",
+ [FileName, Reason]);
+handle_open_error(Err) ->
+ show_unexpected_warning({disk_log, open, 1}, Err).
+
+find_wrap_values() ->
+ ConfSize = case application:get_env(kernel, shell_history_file_bytes) of
+ undefined -> ?DEFAULT_SIZE;
+ {ok, S} -> S
+ end,
+ SizePerFile = max(?MIN_HISTORY_SIZE, ConfSize div ?MAX_HISTORY_FILES),
+ FileCount = if SizePerFile > ?MIN_HISTORY_SIZE ->
+ ?MAX_HISTORY_FILES
+ ; SizePerFile =< ?MIN_HISTORY_SIZE ->
+ max(1, ConfSize div SizePerFile)
+ end,
+ {SizePerFile, FileCount}.
+
+report_repairs(_, _, 0) ->
+ %% just a regular close repair
+ ok;
+report_repairs(_, Good, Bad) ->
+ show('$#erlang-history-report-repairs',
+ "The shell history log file was corrupted and was repaired. "
+ "~p bytes were recovered and ~p were lost.~n", [Good, Bad]).
+
+resize_log(Name, _OldSize, NewSize) ->
+ show('$#erlang-history-resize-attempt',
+ "Attempting to resize the log history file to ~p...", [NewSize]),
+ Opts = lists:keydelete(size, 1, log_options()),
+ _ = case disk_log:open(Opts) of
+ {error, {need_repair, _}} ->
+ _ = repair_log(Name),
+ disk_log:open(Opts);
+ _ ->
+ ok
+ end,
+ case disk_log:change_size(Name, NewSize) of
+ ok ->
+ show('$#erlang-history-resize-result',
+ "ok~n", []);
+ {error, {new_size_too_small, _}} ->
+ show('$#erlang-history-resize-result',
+ "failed (new size is too small)~n", []),
+ disable_history();
+ {error, Reason} ->
+ show('$#erlang-history-resize-result',
+ "failed (~p)~n", [Reason]),
+ disable_history()
+ end.
+
+upgrade_version(_Name, Unsupported) ->
+ %% We only know of one version and can't support a newer one
+ show('$#erlang-history-upgrade',
+ "The version for the shell logs found on disk (~p) is "
+ "not supported by the current version (~p)~n",
+ [Unsupported, ?VSN]),
+ disable_history().
+
+disable_history() ->
+ show('$#erlang-history-disable', "Disabling shell history logging.~n", []),
+ application:set_env(kernel, shell_history, force_disabled).
+
+find_path() ->
+ case application:get_env(kernel, shell_history_path) of
+ undefined -> filename:basedir(user_cache, "erlang-history");
+ {ok, Path} -> Path
+ end.
+
+to_drop() ->
+ case application:get_env(kernel, shell_history_drop) of
+ undefined ->
+ application:set_env(kernel, shell_history_drop, ?DEFAULT_DROP),
+ ?DEFAULT_DROP;
+ {ok, V} when is_list(V) -> [Ln++"\n" || Ln <- V];
+ {ok, _} -> ?DEFAULT_DROP
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Output functions %%%
+%%%%%%%%%%%%%%%%%%%%%%%%
+show_rename_warning() ->
+ show('$#erlang-history-rename-warn',
+ "A history file with a different path has already "
+ "been started for the shell of this node. The old "
+ "name will keep being used for this session.~n",
+ []).
+
+show_invalid_file_warning(FileName) ->
+ show('$#erlang-history-invalid-file',
+ "Shell history expects to be able to use the file ~s "
+ "which currently exists and is not a file usable for "
+ "history logging purposes. History logging will be "
+ "disabled.~n", [FileName]).
+
+show_unexpected_warning({M,F,A}, Term) ->
+ show('$#erlang-history-unexpected-return',
+ "unexpected return value from ~p:~p/~p: ~p~n"
+ "shell history will be disabled for this session.~n",
+ [M,F,A,Term]).
+
+show_unexpected_close_warning() ->
+ show('$#erlang-history-unexpected-close',
+ "The shell log file has mysteriousy closed. Ignoring "
+ "currently unread history.~n", []).
+
+show_size_warning(_Current, _New) ->
+ show('$#erlang-history-size',
+ "The configured log history file size is different from "
+ "the size of the log file on disk.~n", []).
+
+show(Key, Format, Args) ->
+ case get(Key) of
+ undefined ->
+ io:format(standard_error, Format, Args),
+ put(Key, true),
+ ok;
+ true ->
+ ok
+ end.
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index f5c13ecdd7..6aef5476f1 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -702,7 +702,7 @@ connect_options() ->
header, active, packet, packet_size, buffer, mode, deliver, line_delimiter,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw,
- show_econnreset].
+ show_econnreset, bind_to_device].
connect_options(Opts, Mod) ->
BaseOpts =
@@ -770,7 +770,7 @@ listen_options() ->
header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send,
- packet_size, raw, show_econnreset].
+ packet_size, raw, show_econnreset, bind_to_device].
listen_options(Opts, Mod) ->
BaseOpts =
@@ -850,7 +850,7 @@ udp_options() ->
deliver, ipv6_v6only,
broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop,
add_membership, drop_membership, read_packets,raw,
- high_msgq_watermark, low_msgq_watermark].
+ high_msgq_watermark, low_msgq_watermark, bind_to_device].
udp_options(Opts, Mod) ->
@@ -919,6 +919,7 @@ sctp_options() ->
[ % The following are generic inet options supported for SCTP sockets:
mode, active, buffer, tos, tclass, priority, dontroute, reuseaddr, linger, sndbuf,
recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
+ bind_to_device,
% Other options are SCTP-specific (though they may be similar to their
% TCP and UDP counter-parts):
@@ -1055,7 +1056,6 @@ binary2filename(Bin) ->
Bin
end.
-
translate_ip(any, inet) -> {0,0,0,0};
translate_ip(loopback, inet) -> {127,0,0,1};
translate_ip(any, inet6) -> {0,0,0,0,0,0,0,0};
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 4e8f59a3b9..bc5b67f7bf 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -154,6 +154,7 @@
-define(INET_LOPT_TCP_SHOW_ECONNRESET, 39).
-define(INET_LOPT_LINE_DELIM, 40).
-define(INET_OPT_TCLASS, 41).
+-define(INET_OPT_BIND_TO_DEVICE, 42).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).
diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl
index 9b47199e08..0f5dc40553 100644
--- a/lib/kernel/src/inet_parse.erl
+++ b/lib/kernel/src/inet_parse.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl
index c69791b9aa..1e624b9e90 100644
--- a/lib/kernel/src/inet_udp.erl
+++ b/lib/kernel/src/inet_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 25e4ddd95c..1128ee3ec5 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -44,6 +44,7 @@
global_group,
global_search,
group,
+ group_history,
heart,
hipe_unified_loader,
inet6_tcp,
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index 2dc90e2b3e..77085b2064 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl
index b901da95b8..cba57088ec 100644
--- a/lib/kernel/src/kernel.erl
+++ b/lib/kernel/src/kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -123,7 +123,7 @@ init([]) ->
restart => permanent,
shutdown => 2000,
type => worker,
- modeules => [file, file_server, file_io_server, prim_file]},
+ modules => [file, file_server, file_io_server, prim_file]},
StdError = #{id => standard_error,
start => {standard_error, start_link, []},
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index 0a9f9316b0..ddda396713 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1262,11 +1262,22 @@ create_name(Name, LongOrShortNames, Try) ->
{Head,Host1} = create_hostpart(Name, LongOrShortNames),
case Host1 of
{ok,HostPart} ->
- {ok,list_to_atom(Head ++ HostPart)};
+ case valid_name_head(Head) of
+ true ->
+ {ok,list_to_atom(Head ++ HostPart)};
+ false ->
+ error_logger:info_msg("Invalid node name!\n"
+ "Please check your configuration\n"),
+ {error, badarg}
+ end;
{error,long} when Try =:= 1 ->
%% It could be we haven't read domain name from resolv file yet
inet_config:do_load_resolv(os:type(), longnames),
create_name(Name, LongOrShortNames, 0);
+ {error, hostname_not_allowed} ->
+ error_logger:info_msg("Invalid node name!\n"
+ "Please check your configuration\n"),
+ {error, badarg};
{error,Type} ->
error_logger:info_msg(
lists:concat(["Can\'t set ",
@@ -1279,12 +1290,13 @@ create_name(Name, LongOrShortNames, Try) ->
create_hostpart(Name, LongOrShortNames) ->
{Head,Host} = split_node(Name),
Host1 = case {Host,LongOrShortNames} of
- {[$@,_|_],longnames} ->
- {ok,Host};
+ {[$@,_|_] = Host,longnames} ->
+ validate_hostname(Host);
{[$@,_|_],shortnames} ->
case lists:member($.,Host) of
true -> {error,short};
- _ -> {ok,Host}
+ _ ->
+ validate_hostname(Host)
end;
{_,shortnames} ->
case inet_db:gethostname() of
@@ -1304,6 +1316,24 @@ create_hostpart(Name, LongOrShortNames) ->
end,
{Head,Host1}.
+validate_hostname([$@|HostPart] = Host) ->
+ {ok, MP} = re:compile("^[!-ΓΏ]*$", [unicode]),
+ case re:run(HostPart, MP) of
+ {match, _} ->
+ {ok, Host};
+ nomatch ->
+ {error, hostname_not_allowed}
+ end.
+
+valid_name_head(Head) ->
+ {ok, MP} = re:compile("^[0-9A-Za-z_\\-]*$", [unicode]),
+ case re:run(Head, MP) of
+ {match, _} ->
+ true;
+ nomatch ->
+ false
+ end.
+
split_node(Name) ->
lists:splitwith(fun(C) -> C =/= $@ end, atom_to_list(Name)).
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 7e83b17add..0250783632 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index bd6ea26678..0e0b7dffa3 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.