aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src')
-rw-r--r--lib/kernel/src/Makefile4
-rw-r--r--lib/kernel/src/application.erl2
-rw-r--r--lib/kernel/src/application_controller.erl71
-rw-r--r--lib/kernel/src/auth.erl4
-rw-r--r--lib/kernel/src/code.erl6
-rw-r--r--lib/kernel/src/code_server.erl6
-rw-r--r--lib/kernel/src/disk_log.erl48
-rw-r--r--lib/kernel/src/disk_log_1.erl8
-rw-r--r--lib/kernel/src/dist_util.erl5
-rw-r--r--lib/kernel/src/error_handler.erl2
-rw-r--r--lib/kernel/src/file.erl8
-rw-r--r--lib/kernel/src/group.erl147
-rw-r--r--lib/kernel/src/inet_config.erl37
-rw-r--r--lib/kernel/src/inet_parse.erl4
-rw-r--r--lib/kernel/src/kernel.app.src2
-rw-r--r--lib/kernel/src/kernel_config.erl4
-rw-r--r--lib/kernel/src/net_kernel.erl10
-rw-r--r--lib/kernel/src/os.erl4
-rw-r--r--lib/kernel/src/user.erl172
-rw-r--r--lib/kernel/src/user_drv.erl4
20 files changed, 378 insertions, 170 deletions
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index eaced4861a..cb3c0a49f4 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2012. All Rights Reserved.
+# Copyright Ericsson AB 1996-2013. 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
@@ -148,7 +148,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
ifeq ($(NATIVE_LIBS_ENABLED),yes)
ERL_COMPILE_FLAGS += +native
endif
-ERL_COMPILE_FLAGS += -I../include
+ERL_COMPILE_FLAGS += -I../include -Werror
# ----------------------------------------------------
# Targets
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl
index 4e65883be7..6efc1b4499 100644
--- a/lib/kernel/src/application.erl
+++ b/lib/kernel/src/application.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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/application_controller.erl b/lib/kernel/src/application_controller.erl
index 75ce852001..3c860af48e 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -247,7 +247,7 @@ start_boot_application(Application, RestartType) ->
{{error, {already_loaded, AppName}}, _} ->
gen_server:call(?AC, {start_application, AppName, RestartType}, infinity);
{{error,{bad_environment_value,Env}}, permanent} ->
- Txt = io_lib:format("Bad environment variable: ~p Application: ~p",
+ Txt = io_lib:format("Bad environment variable: ~tp Application: ~p",
[Env, Application]),
exit({error, list_to_atom(lists:flatten(Txt))});
{Error, _} ->
@@ -501,13 +501,13 @@ init(Init, Kernel) ->
{local, ?AC})
end;
{error, ErrorStr} ->
- Str = lists:flatten(io_lib:format("invalid config data: ~s", [ErrorStr])),
+ Str = lists:flatten(io_lib:format("invalid config data: ~ts", [ErrorStr])),
Init ! {ack, self(), {error, to_string(Str)}}
end;
{error, {File, Line, Str}} ->
ReasonStr =
lists:flatten(io_lib:format("error in config file "
- "~p (~w): ~s",
+ "~tp (~w): ~ts",
[File, Line, Str])),
Init ! {ack, self(), {error, to_string(ReasonStr)}}
end.
@@ -537,17 +537,17 @@ check_conf_data(ConfData) when is_list(ConfData) ->
end;
{AppName, List} when is_list(List) ->
ErrMsg = "application: "
- ++ lists:flatten(io_lib:format("~p",[AppName]))
+ ++ lists:flatten(io_lib:format("~tp",[AppName]))
++ "; application name must be an atom",
{error, ErrMsg};
{AppName, _List} ->
ErrMsg = "application: "
- ++ lists:flatten(io_lib:format("~p",[AppName]))
+ ++ lists:flatten(io_lib:format("~tp",[AppName]))
++ "; parameters must be a list",
{error, ErrMsg};
Else ->
ErrMsg = "invalid application name: " ++
- lists:flatten(io_lib:format(" ~p",[Else])),
+ lists:flatten(io_lib:format(" ~tp",[Else])),
{error, ErrMsg}
end;
check_conf_data(_ConfData) ->
@@ -570,10 +570,10 @@ check_para_kernel([{Para, _Val} | ParaList]) when is_atom(Para) ->
check_para_kernel(ParaList);
check_para_kernel([{Para, _Val} | _ParaList]) ->
{error, "application: kernel; invalid parameter: " ++
- lists:flatten(io_lib:format("~p",[Para]))};
+ lists:flatten(io_lib:format("~tp",[Para]))};
check_para_kernel(Else) ->
{error, "application: kernel; invalid parameter list: " ++
- lists:flatten(io_lib:format("~p",[Else]))}.
+ lists:flatten(io_lib:format("~tp",[Else]))}.
check_distributed([]) ->
@@ -594,10 +594,10 @@ check_para([{Para, _Val} | ParaList], AppName) when is_atom(Para) ->
check_para(ParaList, AppName);
check_para([{Para, _Val} | _ParaList], AppName) ->
{error, "application: " ++ AppName ++ "; invalid parameter: " ++
- lists:flatten(io_lib:format("~p",[Para]))};
+ lists:flatten(io_lib:format("~tp",[Para]))};
check_para([Else | _ParaList], AppName) ->
{error, "application: " ++ AppName ++ "; invalid parameter: " ++
- lists:flatten(io_lib:format("~p",[Else]))}.
+ lists:flatten(io_lib:format("~tp",[Else]))}.
-type calls() :: 'info' | 'prep_config_change' | 'which_applications'
@@ -1434,7 +1434,9 @@ make_appl(Name) when is_atom(Name) ->
{ok, [Application]} ->
{ok, make_appl_i(Application)};
{error, Reason} ->
- {error, {file:format_error(Reason), FName}}
+ {error, {file:format_error(Reason), FName}};
+ error ->
+ {error, "bad encoding"}
end
end;
make_appl(Application) ->
@@ -1443,12 +1445,17 @@ make_appl(Application) ->
prim_consult(FullName) ->
case erl_prim_loader:get_file(FullName) of
{ok, Bin, _} ->
- case erl_scan:string(binary_to_list(Bin)) of
- {ok, Tokens, _EndLine} ->
- prim_parse(Tokens, []);
- {error, Reason, _EndLine} ->
- {error, Reason}
- end;
+ case file_binary_to_list(Bin) of
+ {ok, String} ->
+ case erl_scan:string(String, 1, [unicode]) of
+ {ok, Tokens, _EndLine} ->
+ prim_parse(Tokens, []);
+ {error, Reason, _EndLine} ->
+ {error, Reason}
+ end;
+ error ->
+ error
+ end;
error ->
{error, enoent}
end.
@@ -1521,7 +1528,7 @@ do_change_apps(Applications, Config, OldAppls) ->
%% Report errors, but do not terminate
%% (backwards compatible behaviour)
lists:foreach(fun({error, {SysFName, Line, Str}}) ->
- Str2 = lists:flatten(io_lib:format("~p: ~w: ~s~n",
+ Str2 = lists:flatten(io_lib:format("~tp: ~w: ~ts~n",
[SysFName, Line, Str])),
error_logger:format(Str2, [])
end,
@@ -1593,18 +1600,18 @@ conv(_) -> [].
%%% Fix some day: eliminate the duplicated code here
make_term(Str) ->
- case erl_scan:string(Str) of
+ case erl_scan:string(Str, 1, [unicode]) of
{ok, Tokens, _} ->
case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of
{ok, Term} ->
Term;
{error, {_,M,Reason}} ->
- error_logger:format("application_controller: ~s: ~s~n",
+ error_logger:format("application_controller: ~ts: ~ts~n",
[M:format_error(Reason), Str]),
throw({error, {bad_environment_value, Str}})
end;
{error, {_,M,Reason}, _} ->
- error_logger:format("application_controller: ~s: ~s~n",
+ error_logger:format("application_controller: ~ts: ~ts~n",
[M:format_error(Reason), Str]),
throw({error, {bad_environment_value, Str}})
end.
@@ -1828,8 +1835,12 @@ load_file(File) ->
{ok, Bin, _FileName} ->
%% Make sure that there is some whitespace at the end of the string
%% (so that reading a file with no NL following the "." will work).
- Str = binary_to_list(Bin) ++ " ",
- scan_file(Str);
+ case file_binary_to_list(Bin) of
+ {ok, String} ->
+ scan_file(String ++ " ");
+ error ->
+ {error, {none, scan_file, "bad encoding"}}
+ end;
error ->
{error, {none, open_file, "configuration file not found"}}
end.
@@ -1947,6 +1958,18 @@ test_make_apps([], Res) ->
test_make_apps([A|Apps], Res) ->
test_make_apps(Apps, [make_appl(A) | Res]).
+file_binary_to_list(Bin) ->
+ Enc = case epp:read_encoding_from_binary(Bin) of
+ none -> epp:default_encoding();
+ Encoding -> Encoding
+ end,
+ case catch unicode:characters_to_list(Bin, Enc) of
+ String when is_list(String) ->
+ {ok, String};
+ _ ->
+ error
+ end.
+
%%-----------------------------------------------------------------
%% String conversion
%% Exit reason needs to be a printable string
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index 6ae786ebd9..1e12a647d7 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -384,7 +384,7 @@ create_cookie(Name) ->
{{error,Reason}, _} ->
{error,
lists:flatten(
- io_lib:format("Failed to write to cookie file '~s': ~p", [Name, Reason]))};
+ io_lib:format("Failed to write to cookie file '~ts': ~p", [Name, Reason]))};
{ok, {error, Reason}} ->
{error, "Failed to change mode: " ++ atom_to_list(Reason)}
end;
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 361f2bdf8a..8a543abd6f 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -511,7 +511,7 @@ search([{Dir, File} | Tail]) ->
false ->
search(Tail);
{Dir2, File} ->
- io:format("** ~s hides ~s~n",
+ io:format("** ~ts hides ~ts~n",
[filename:join(Dir, File),
filename:join(Dir2, File)]),
[clash | search(Tail)]
@@ -528,7 +528,7 @@ decorate([File|Tail], Dir) ->
[{Dir, File} | decorate(Tail, Dir)].
filter(_Ext, Dir, error) ->
- io:format("** Bad path can't read ~s~n", [Dir]), [];
+ io:format("** Bad path can't read ~ts~n", [Dir]), [];
filter(Ext, _, {ok,Files}) ->
filter2(Ext, length(Ext), Files).
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index b2d2c19f78..b770fce887 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2013. 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
@@ -1266,11 +1266,11 @@ try_load_module_1(File, Mod, Bin, Caller, #state{moddb=Db}=St) ->
{error,on_load} ->
handle_on_load(Mod, File, Caller, St);
{error,What} = Error ->
- error_msg("Loading of ~s failed: ~p\n", [File, What]),
+ error_msg("Loading of ~ts failed: ~p\n", [File, What]),
{reply,Error,St}
end;
Error ->
- error_msg("Native loading of ~s failed: ~p\n",
+ error_msg("Native loading of ~ts failed: ~p\n",
[File,Error]),
{reply,ok,St}
end
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 1513fdaec0..0c5af2857e 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -1527,48 +1527,48 @@ do_format_error({size_mismatch, OldSize, ArgSize}) ->
io_lib:format("The given size ~p does not match the size ~p found on "
"the disk log size file~n", [ArgSize, OldSize]);
do_format_error({read_only_mode, Log}) ->
- io_lib:format("The disk log ~p has been opened read-only, but the "
+ io_lib:format("The disk log ~tp has been opened read-only, but the "
"requested operation needs read-write access~n", [Log]);
do_format_error({format_external, Log}) ->
io_lib:format("The requested operation can only be applied on internally "
- "formatted disk logs, but ~p is externally formatted~n",
+ "formatted disk logs, but ~tp is externally formatted~n",
[Log]);
do_format_error({blocked_log, Log}) ->
- io_lib:format("The blocked disk log ~p does not queue requests, or "
+ io_lib:format("The blocked disk log ~tp does not queue requests, or "
"the log has been blocked by the calling process~n", [Log]);
do_format_error({full, Log}) ->
- io_lib:format("The halt log ~p is full~n", [Log]);
+ io_lib:format("The halt log ~tp is full~n", [Log]);
do_format_error({not_blocked, Log}) ->
- io_lib:format("The disk log ~p is not blocked~n", [Log]);
+ io_lib:format("The disk log ~tp is not blocked~n", [Log]);
do_format_error({not_owner, Pid}) ->
- io_lib:format("The pid ~p is not an owner of the disk log~n", [Pid]);
+ io_lib:format("The pid ~tp is not an owner of the disk log~n", [Pid]);
do_format_error({not_blocked_by_pid, Log}) ->
- io_lib:format("The disk log ~p is blocked, but only the blocking pid "
+ io_lib:format("The disk log ~tp is blocked, but only the blocking pid "
"can unblock a disk log~n", [Log]);
do_format_error({new_size_too_small, Log, CurrentSize}) ->
- io_lib:format("The current size ~p of the halt log ~p is greater than the "
+ io_lib:format("The current size ~p of the halt log ~tp is greater than the "
"requested new size~n", [CurrentSize, Log]);
do_format_error({halt_log, Log}) ->
- io_lib:format("The halt log ~p cannot be wrapped~n", [Log]);
+ io_lib:format("The halt log ~tp cannot be wrapped~n", [Log]);
do_format_error({same_file_name, Log}) ->
- io_lib:format("Current and new file name of the disk log ~p "
+ io_lib:format("Current and new file name of the disk log ~tp "
"are the same~n", [Log]);
do_format_error({arg_mismatch, Option, FirstValue, ArgValue}) ->
- io_lib:format("The value ~p of the disk log option ~p does not match "
- "the current value ~p~n", [ArgValue, Option, FirstValue]);
+ io_lib:format("The value ~tp of the disk log option ~p does not match "
+ "the current value ~tp~n", [ArgValue, Option, FirstValue]);
do_format_error({name_already_open, Log}) ->
- io_lib:format("The disk log ~p has already opened another file~n", [Log]);
+ io_lib:format("The disk log ~tp has already opened another file~n", [Log]);
do_format_error({node_already_open, Log}) ->
- io_lib:format("The distribution option of the disk log ~p does not match "
+ io_lib:format("The distribution option of the disk log ~tp does not match "
"already open log~n", [Log]);
do_format_error({open_read_write, Log}) ->
- io_lib:format("The disk log ~p has already been opened read-write~n",
+ io_lib:format("The disk log ~tp has already been opened read-write~n",
[Log]);
do_format_error({open_read_only, Log}) ->
- io_lib:format("The disk log ~p has already been opened read-only~n",
+ io_lib:format("The disk log ~tp has already been opened read-only~n",
[Log]);
do_format_error({not_internal_wrap, Log}) ->
- io_lib:format("The requested operation cannot be applied since ~p is not "
+ io_lib:format("The requested operation cannot be applied since ~tp is not "
"an internally formatted disk log~n", [Log]);
do_format_error(no_such_log) ->
io_lib:format("There is no disk log with the given name~n", []);
@@ -1579,13 +1579,13 @@ do_format_error(nodedown) ->
io_lib:format("There seems to be no node up that can handle "
"the request~n", []);
do_format_error({corrupt_log_file, FileName}) ->
- io_lib:format("The disk log file \"~s\" contains corrupt data~n",
+ io_lib:format("The disk log file \"~ts\" contains corrupt data~n",
[FileName]);
do_format_error({need_repair, FileName}) ->
- io_lib:format("The disk log file \"~s\" has not been closed properly and "
+ io_lib:format("The disk log file \"~ts\" has not been closed properly and "
"needs repair~n", [FileName]);
do_format_error({not_a_log_file, FileName}) ->
- io_lib:format("The file \"~s\" is not a wrap log file~n", [FileName]);
+ io_lib:format("The file \"~ts\" is not a wrap log file~n", [FileName]);
do_format_error({invalid_header, InvalidHeader}) ->
io_lib:format("The disk log header is not wellformed: ~p~n",
[InvalidHeader]);
@@ -1593,14 +1593,14 @@ do_format_error(end_of_log) ->
io_lib:format("An attempt was made to step outside a not yet "
"full wrap log~n", []);
do_format_error({invalid_index_file, FileName}) ->
- io_lib:format("The wrap log index file \"~s\" cannot be used~n",
+ io_lib:format("The wrap log index file \"~ts\" cannot be used~n",
[FileName]);
do_format_error({no_continuation, BadCont}) ->
io_lib:format("The term ~p is not a chunk continuation~n", [BadCont]);
do_format_error({file_error, FileName, Reason}) ->
- io_lib:format("\"~s\": ~p~n", [FileName, file:format_error(Reason)]);
+ io_lib:format("\"~ts\": ~tp~n", [FileName, file:format_error(Reason)]);
do_format_error(E) ->
- io_lib:format("~p~n", [E]).
+ io_lib:format("~tp~n", [E]).
do_info(L, Cnt) ->
#log{name = Name, type = Type, mode = Mode, filename = File,
diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl
index 0cb1ed579a..9d431bdd30 100644
--- a/lib/kernel/src/disk_log_1.erl
+++ b/lib/kernel/src/disk_log_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -489,7 +489,7 @@ lh(H, _F) -> % cannot happen
repair(In, File) ->
FSz = file_size(File),
- error_logger:info_msg("disk_log: repairing ~p ...\n", [File]),
+ error_logger:info_msg("disk_log: repairing ~tp ...\n", [File]),
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).
@@ -758,7 +758,7 @@ 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 ~p missing.\n\n",
+ error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
[FName]),
mf_int_chunk(Handle, {NFileNo, 0}, [], N);
{ok, {_Alloc, FdC, _HeadSize, _FileSize}} ->
@@ -786,7 +786,7 @@ 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 ~p missing.\n\n",
+ error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
[FName]),
mf_int_chunk_read_only(Handle, {NFileNo, 0}, [], N);
{ok, {_Alloc, FdC, _HeadSize, _FileSize}} ->
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index e3511988a6..fc50ec6717 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. 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
@@ -115,7 +115,8 @@ make_this_flags(RequestType, OtherNode) ->
?DFLAG_NEW_FLOATS bor
?DFLAG_UNICODE_IO bor
?DFLAG_DIST_HDR_ATOM_CACHE bor
- ?DFLAG_SMALL_ATOM_TAGS).
+ ?DFLAG_SMALL_ATOM_TAGS bor
+ ?DFLAG_UTF8_ATOMS).
handshake_other_started(#hs_data{request_type=ReqType}=HSData0) ->
{PreOtherFlags,Node,Version} = recv_name(HSData0),
diff --git a/lib/kernel/src/error_handler.erl b/lib/kernel/src/error_handler.erl
index a3aa1f1dcf..40aabba803 100644
--- a/lib/kernel/src/error_handler.erl
+++ b/lib/kernel/src/error_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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/file.erl b/lib/kernel/src/file.erl
index 16f2dde464..70c4583ad2 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -148,7 +148,7 @@ format_error({Line, ?MODULE, {Reason, Stacktrace}}) ->
io_lib:format("~w: evaluation failed with reason ~w and stacktrace ~w",
[Line, Reason, Stacktrace]);
format_error({Line, Mod, Reason}) ->
- io_lib:format("~w: ~s", [Line, Mod:format_error(Reason)]);
+ io_lib:format("~w: ~ts", [Line, Mod:format_error(Reason)]);
format_error(badarg) ->
"bad argument";
format_error(system_limit) ->
@@ -591,7 +591,7 @@ pread(_, _, _) ->
write(File, Bytes) when (is_pid(File) orelse is_atom(File)) ->
case make_binary(Bytes) of
Bin when is_binary(Bin) ->
- io:request(File, {put_chars,Bin});
+ io:request(File, {put_chars,latin1,Bin});
Error ->
Error
end;
@@ -1345,7 +1345,7 @@ eval_stream(Fd, Handling, Bs) ->
eval_stream(Fd, Handling, 1, undefined, [], Bs).
eval_stream(Fd, H, Line, Last, E, Bs) ->
- eval_stream2(io:parse_erl_exprs(Fd, '', Line), Fd, H, Last, E, Bs).
+ eval_stream2(io:parse_erl_exprs(Fd, '', Line, [unicode]), Fd, H, Last, E, Bs).
eval_stream2({ok,Form,EndLine}, Fd, H, Last, E, Bs0) ->
try erl_eval:exprs(Form, Bs0) of
diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl
index 4d2e31a429..ff835e1047 100644
--- a/lib/kernel/src/group.erl
+++ b/lib/kernel/src/group.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -227,7 +227,7 @@ io_request({put_chars,latin1,Chars}, Drv, Buf) ->
send_drv(Drv, {put_chars, unicode,Binary}),
{ok,ok,Buf};
_ ->
- {error,{error,{put_chars,Chars}},Buf}
+ {error,{error,{put_chars,latin1,Chars}},Buf}
end;
io_request({put_chars,latin1,M,F,As}, Drv, Buf) ->
case catch apply(M, F, As) of
@@ -446,7 +446,6 @@ get_chars_loop(Pbs, M, F, Xa, Drv, Buf0, State, Encoding) ->
end.
get_chars_apply(Pbs, M, F, Xa, Drv, Buf, State0, Line, Encoding) ->
- id(M,F),
case catch M:F(State0, cast(Line,get(read_mode), Encoding), Encoding, Xa) of
{stop,Result,Rest} ->
{ok,Result,append(Rest, Buf, Encoding)};
@@ -456,8 +455,6 @@ get_chars_apply(Pbs, M, F, Xa, Drv, Buf, State0, Line, Encoding) ->
get_chars_loop(Pbs, M, F, Xa, Drv, Buf, State1, Encoding)
end.
-id(M,F) ->
- {M,F}.
%% Convert error code to make it look as before
err_func(io_lib, get_until, {_,F,_}) ->
F;
@@ -515,6 +512,27 @@ get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls0, Encoding)
Drv,
Ls, Encoding)
end;
+%% ^R = backward search, ^S = forward search.
+%% Search is tricky to implement and does a lot of back-and-forth
+%% work with edlin.erl (from stdlib). Edlin takes care of writing
+%% and handling lines and escape characters to get out of search,
+%% whereas this module does the actual searching and appending to lines.
+%% Erlang's shell wasn't exactly meant to traverse the wall between
+%% line and line stack, so we at least restrict it by introducing
+%% new modes: search, search_quit, search_found. These are added to
+%% the regular ones (none, meta_left_sq_bracket) and handle special
+%% cases of history search.
+get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls, Encoding)
+ when ((Mode =:= none) and (Char =:= $\^R)) ->
+ send_drv_reqs(Drv, Rs),
+ %% drop current line, move to search mode. We store the current
+ %% prompt ('N>') and substitute it with the search prompt.
+ send_drv_reqs(Drv, edlin:erase_line(Cont)),
+ put(search_quit_prompt, edlin:prompt(Cont)),
+ Pbs = prompt_bytes("(search)`': ", Encoding),
+ {more_chars,Ncont,Nrs} = edlin:start(Pbs, search),
+ send_drv_reqs(Drv, Nrs),
+ get_line1(edlin:edit_line1(Cs, Ncont), Drv, Ls, Encoding);
get_line1({expand, Before, Cs0, Cont,Rs}, Drv, Ls0, Encoding) ->
send_drv_reqs(Drv, Rs),
ExpandFun = get(expand_fun),
@@ -535,8 +553,59 @@ get_line1({undefined,_Char,Cs,Cont,Rs}, Drv, Ls, Encoding) ->
send_drv_reqs(Drv, Rs),
send_drv(Drv, beep),
get_line1(edlin:edit_line(Cs, Cont), Drv, Ls, Encoding);
+%% The search item was found and accepted (new line entered on the exact
+%% result found)
+get_line1({_What,Cont={line,_Prompt,_Chars,search_found},Rs}, Drv, Ls0, Encoding) ->
+ Line = edlin:current_line(Cont),
+ %% this may create duplicate entries.
+ Ls = save_line(new_stack(get_lines(Ls0)), Line),
+ get_line1({done, Line, "", Rs}, Drv, Ls, Encoding);
+%% The search mode has been exited, but the user wants to remain in line
+%% editing mode wherever that was, but editing the search result.
+get_line1({What,Cont={line,_Prompt,_Chars,search_quit},Rs}, Drv, Ls, Encoding) ->
+ Line = edlin:current_chars(Cont),
+ %% Load back the old prompt with the correct line number.
+ case get(search_quit_prompt) of
+ undefined -> % should not happen. Fallback.
+ LsFallback = save_line(new_stack(get_lines(Ls)), Line),
+ get_line1({done, "\n", Line, Rs}, Drv, LsFallback, Encoding);
+ Prompt -> % redraw the line and keep going with the same stack position
+ NCont = {line,Prompt,{lists:reverse(Line),[]},none},
+ send_drv_reqs(Drv, Rs),
+ send_drv_reqs(Drv, edlin:erase_line(Cont)),
+ send_drv_reqs(Drv, edlin:redraw_line(NCont)),
+ get_line1({What, NCont ,[]}, Drv, pad_stack(Ls), Encoding)
+ end;
+%% Search mode is entered.
+get_line1({What,{line,Prompt,{RevCmd0,_Aft},search},Rs},
+ Drv, Ls0, Encoding) ->
+ send_drv_reqs(Drv, Rs),
+ %% Figure out search direction. ^S and ^R are returned through edlin
+ %% whenever we received a search while being already in search mode.
+ {Search, Ls1, RevCmd} = case RevCmd0 of
+ [$\^S|RevCmd1] ->
+ {fun search_down_stack/2, Ls0, RevCmd1};
+ [$\^R|RevCmd1] ->
+ {fun search_up_stack/2, Ls0, RevCmd1};
+ _ -> % new search, rewind stack for a proper search.
+ {fun search_up_stack/2, new_stack(get_lines(Ls0)), RevCmd0}
+ end,
+ Cmd = lists:reverse(RevCmd),
+ {Ls, NewStack} = case Search(Ls1, Cmd) of
+ {none, Ls2} ->
+ send_drv(Drv, beep),
+ {Ls2, {RevCmd, "': "}};
+ {Line, Ls2} -> % found. Complete the output edlin couldn't have done.
+ send_drv_reqs(Drv, [{put_chars, Encoding, Line}]),
+ {Ls2, {RevCmd, "': "++Line}}
+ end,
+ Cont = {line,Prompt,NewStack,search},
+ more_data(What, Cont, Drv, Ls, Encoding);
get_line1({What,Cont0,Rs}, Drv, Ls, Encoding) ->
send_drv_reqs(Drv, Rs),
+ more_data(What, Cont0, Drv, Ls, Encoding).
+
+more_data(What, Cont0, Drv, Ls, Encoding) ->
receive
{Drv,{data,Cs}} ->
get_line1(edlin:edit_line(Cs, Cont0), Drv, Ls, Encoding);
@@ -557,7 +626,6 @@ get_line1({What,Cont0,Rs}, Drv, Ls, Encoding) ->
get_line1(edlin:edit_line([], Cont0), Drv, Ls, Encoding)
end.
-
get_line_echo_off(Chars, Pbs, Drv) ->
send_drv_reqs(Drv, [{put_chars, unicode,Pbs}]),
get_line_echo_off1(edit_line(Chars,[]), Drv).
@@ -632,12 +700,46 @@ save_line({stack, U, {}, []}, Line) ->
save_line({stack, U, _L, D}, Line) ->
{stack, U, Line, D}.
-get_lines({stack, U, {}, []}) ->
+get_lines(Ls) -> get_all_lines(Ls).
+%get_lines({stack, U, {}, []}) ->
+% U;
+%get_lines({stack, U, {}, D}) ->
+% tl(lists:reverse(D, U));
+%get_lines({stack, U, L, D}) ->
+% get_lines({stack, U, {}, [L|D]}).
+
+%% There's a funny behaviour whenever the line stack doesn't have a "\n"
+%% at its end -- get_lines() seemed to work on the assumption it *will* be
+%% there, but the manipulations done with search history do not require it.
+%%
+%% It is an assumption because the function was built with either the full
+%% stack being on the 'Up' side (we're on the new line) where it isn't
+%% stripped. The only other case when it isn't on the 'Up' side is when
+%% someone has used the up/down arrows (or ^P and ^N) to navigate lines,
+%% in which case, a line with only a \n is stored at the end of the stack
+%% (the \n is returned by edlin:current_line/1).
+%%
+%% get_all_lines works the same as get_lines, but only strips the trailing
+%% character if it's a linebreak. Otherwise it's kept the same. This is
+%% because traversing the stack due to search history will *not* insert
+%% said empty line in the stack at the same time as other commands do,
+%% and thus it should not always be stripped unless we know a new line
+%% is the last entry.
+get_all_lines({stack, U, {}, []}) ->
U;
-get_lines({stack, U, {}, D}) ->
- tl(lists:reverse(D, U));
-get_lines({stack, U, L, D}) ->
- get_lines({stack, U, {}, [L|D]}).
+get_all_lines({stack, U, {}, D}) ->
+ case lists:reverse(D, U) of
+ ["\n"|Lines] -> Lines;
+ Lines -> Lines
+ end;
+get_all_lines({stack, U, L, D}) ->
+ get_all_lines({stack, U, {}, [L|D]}).
+
+%% For the same reason as above, though, we need to expand the stack
+%% in some cases to make sure we play nice with up/down arrows. We need
+%% to insert newlines, but not always.
+pad_stack({stack, U, L, D}) ->
+ {stack, U, L, D++["\n"]}.
save_line_buffer("\n", Lines) ->
save_line_buffer(Lines);
@@ -649,6 +751,27 @@ save_line_buffer(Line, Lines) ->
save_line_buffer(Lines) ->
put(line_buffer, Lines).
+search_up_stack(Stack, Substr) ->
+ case up_stack(Stack) of
+ {none,NewStack} -> {none,NewStack};
+ {L, NewStack} ->
+ case string:str(L, Substr) of
+ 0 -> search_up_stack(NewStack, Substr);
+ _ -> {string:strip(L,right,$\n), NewStack}
+ end
+ end.
+
+search_down_stack(Stack, Substr) ->
+ case down_stack(Stack) of
+ {none,NewStack} -> {none,NewStack};
+ {L, NewStack} ->
+ case string:str(L, Substr) of
+ 0 -> search_down_stack(NewStack, Substr);
+ _ -> {string:strip(L,right,$\n), NewStack}
+ end
+ end.
+
+
%% This is get_line without line editing (except for backspace) and
%% without echo.
get_password_line(Chars, Drv) ->
@@ -687,7 +810,7 @@ edit_password([$\177|Cs],[_|Chars]) ->%% is backspace enough?
edit_password([Char|Cs],Chars) ->
edit_password(Cs,[Char|Chars]).
-%% prompt_bytes(Prompt)
+%% prompt_bytes(Prompt, Encoding)
%% Return a flat list of characters for the Prompt.
prompt_bytes(Prompt, Encoding) ->
lists:flatten(io_lib:format_prompt(Prompt, Encoding)).
diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index 526baca335..2461f3ff25 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -104,7 +104,7 @@ init() ->
%% Add inetrc config entries
case inet_db:add_rc_list(CfgList) of
ok -> ok;
- _ -> error("syntax error in ~s~n", [RcFile])
+ _ -> error("syntax error in ~ts~n", [RcFile])
end,
%% Set up a resolver configuration file for inet_res,
@@ -266,10 +266,10 @@ load_resolv(File, Func) ->
{ok, Ls} ->
inet_db:add_rc_list(Ls);
{error, Reason} ->
- error("parse error in file ~s: ~p", [File, Reason])
+ error("parse error in file ~ts: ~p", [File, Reason])
end;
Error ->
- warning("file not found ~s: ~p~n", [File, Error])
+ warning("file not found ~ts: ~p~n", [File, Error])
end.
%%
@@ -285,12 +285,12 @@ load_hosts(File,Os) ->
inet_db:add_host(IP, [Name|Aliases]) end,
Ls);
{error, Reason} ->
- error("parse error in file ~s: ~p", [File, Reason])
+ error("parse error in file ~ts: ~p", [File, Reason])
end;
Error ->
case Os of
unix ->
- error("file not found ~s: ~p~n", [File, Error]);
+ error("file not found ~ts: ~p~n", [File, Error]);
_ ->
%% for windows or nt the hosts file is not always there
%% and we don't require it
@@ -462,11 +462,11 @@ get_rc(File) ->
{ok,Ls} ->
Ls;
_Error ->
- error("parse error in ~s~n", [File]),
+ error("parse error in ~ts~n", [File]),
error
end;
_Error ->
- error("file ~s not found~n", [File]),
+ error("file ~ts not found~n", [File]),
error
end.
@@ -495,8 +495,12 @@ warning(Fmt, Args) ->
%% Ignore leading whitespace before a token (due to bug in erl_scan) !
%%
parse_inetrc(Bin) ->
- Str = binary_to_list(Bin) ++ "\n",
- parse_inetrc(Str, 1, []).
+ case file_binary_to_list(Bin) of
+ {ok, String} ->
+ parse_inetrc(String ++ "\n", 1, []);
+ error ->
+ {error, 'bad_encoding'}
+ end.
parse_inetrc_skip_line([], _Line, Ack) ->
{ok, reverse(Ack)};
@@ -535,3 +539,16 @@ parse_inetrc(Str, Line, Ack) ->
{more, _} -> %% Bug in erl_scan !!
{error, {'scan_inetrc', {eof, Line}}}
end.
+
+file_binary_to_list(Bin) ->
+ Enc = case epp:read_encoding_from_binary(Bin) of
+ none -> epp:default_encoding();
+ Encoding -> Encoding
+ end,
+ case catch unicode:characters_to_list(Bin, Enc) of
+ String when is_list(String) ->
+ {ok, String};
+ _ ->
+ error
+ end.
+
diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl
index 3551e701b6..619c78a6ca 100644
--- a/lib/kernel/src/inet_parse.erl
+++ b/lib/kernel/src/inet_parse.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -464,7 +464,7 @@ strict_address(Cs) when is_list(Cs) ->
_ ->
ipv6strict_address(Cs)
end;
-strict_address(Cs) ->
+strict_address(_) ->
{error, einval}.
%%
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 9a20baf8d0..cb8c98ab06 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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/kernel_config.erl b/lib/kernel/src/kernel_config.erl
index b1daf655c9..48141cfa03 100644
--- a/lib/kernel/src/kernel_config.erl
+++ b/lib/kernel/src/kernel_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -93,7 +93,7 @@ code_change(_OldVsn, State, _Extra) ->
sync_nodes() ->
case catch get_sync_data() of
{error, Reason} = Error ->
- error_logger:format("~p", [Reason]),
+ error_logger:format("~tp", [Reason]),
Error;
{infinity, MandatoryNodes, OptionalNodes} ->
case wait_nodes(MandatoryNodes, OptionalNodes) of
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index 0d59e7af67..dd0071b914 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -1340,20 +1340,20 @@ start_protos(Name, [Proto | Ps], Node, Ls) ->
start_protos(Name, Ps, Node, Ls)
end;
{'EXIT', {undef,_}} ->
- error_logger:info_msg("Protocol: ~p: not supported~n", [Proto]),
+ error_logger:info_msg("Protocol: ~tp: not supported~n", [Proto]),
start_protos(Name,Ps, Node, Ls);
{'EXIT', Reason} ->
- error_logger:info_msg("Protocol: ~p: register error: ~p~n",
+ error_logger:info_msg("Protocol: ~tp: register error: ~tp~n",
[Proto, Reason]),
start_protos(Name,Ps, Node, Ls);
{error, duplicate_name} ->
- error_logger:info_msg("Protocol: ~p: the name " ++
+ error_logger:info_msg("Protocol: ~tp: the name " ++
atom_to_list(Node) ++
" seems to be in use by another Erlang node",
[Proto]),
start_protos(Name,Ps, Node, Ls);
{error, Reason} ->
- error_logger:info_msg("Protocol: ~p: register/listen error: ~p~n",
+ error_logger:info_msg("Protocol: ~tp: register/listen error: ~tp~n",
[Proto, Reason]),
start_protos(Name,Ps, Node, Ls)
end;
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index e20a2434b4..742c000cc1 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -334,7 +334,7 @@ mk_cmd(Cmd) when is_atom(Cmd) -> % backward comp.
mk_cmd(Cmd) ->
%% We insert a new line after the command, in case the command
%% contains a comment character.
- io_lib:format("(~s\n) </dev/null; echo \"\^D\"\n", [Cmd]).
+ io_lib:format("(~ts\n) </dev/null; echo \"\^D\"\n", [Cmd]).
validate(Atom) when is_atom(Atom) ->
diff --git a/lib/kernel/src/user.erl b/lib/kernel/src/user.erl
index d6449d9e5e..c897d46bc2 100644
--- a/lib/kernel/src/user.erl
+++ b/lib/kernel/src/user.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -17,7 +17,7 @@
%% %CopyrightEnd%
%%
-module(user).
--compile( [ inline, { inline_size, 100 } ] ).
+-compile(inline).
%% Basic standard i/o server for user interface port.
@@ -184,38 +184,52 @@ do_io_request(Req, From, ReplyAs, Port, Q0) ->
io_reply(From, ReplyAs, Reply),
Q1;
{exit,What} ->
- send_port(Port, close),
+ ok = send_port(Port, close),
exit(What)
end.
%% New in R13B
%% Encoding option (unicode/latin1)
io_request({put_chars,unicode,Chars}, Port, Q) -> % Binary new in R9C
- put_chars(wrap_characters_to_binary(Chars,unicode, get(encoding)), Port, Q);
+ case wrap_characters_to_binary(Chars, unicode, get(encoding)) of
+ error ->
+ {error,{error,put_chars},Q};
+ Bin ->
+ put_chars(Bin, Port, Q)
+ end;
io_request({put_chars,unicode,Mod,Func,Args}, Port, Q) ->
- Result = case catch apply(Mod,Func,Args) of
- Data when is_list(Data); is_binary(Data) ->
- wrap_characters_to_binary(Data,unicode,get(encoding));
- Undef ->
- Undef
- end,
- put_chars(Result, Port, Q);
+ case catch apply(Mod,Func,Args) of
+ Data when is_list(Data); is_binary(Data) ->
+ case wrap_characters_to_binary(Data, unicode, get(encoding)) of
+ Bin when is_binary(Bin) ->
+ put_chars(Bin, Port, Q);
+ error ->
+ {error,{error,put_chars},Q}
+ end;
+ Undef ->
+ put_chars(Undef, Port, Q)
+ end;
io_request({put_chars,latin1,Chars}, Port, Q) -> % Binary new in R9C
- Data = case get(encoding) of
- unicode ->
- unicode:characters_to_binary(Chars,latin1,unicode);
- latin1 ->
- erlang:iolist_to_binary(Chars)
- end,
- put_chars(Data, Port, Q);
+ case catch unicode:characters_to_binary(Chars, latin1, get(encoding)) of
+ Data when is_binary(Data) ->
+ put_chars(Data, Port, Q);
+ _ ->
+ {error,{error,put_chars},Q}
+ end;
io_request({put_chars,latin1,Mod,Func,Args}, Port, Q) ->
- Result = case catch apply(Mod,Func,Args) of
- Data when is_list(Data); is_binary(Data) ->
- unicode:characters_to_binary(Data,latin1,get(encoding));
- Undef ->
- Undef
- end,
- put_chars(Result, Port, Q);
+ case catch apply(Mod,Func,Args) of
+ Data when is_list(Data); is_binary(Data) ->
+ case
+ catch unicode:characters_to_binary(Data,latin1,get(encoding))
+ of
+ Bin when is_binary(Bin) ->
+ put_chars(Bin, Port, Q);
+ _ ->
+ {error,{error,put_chars},Q}
+ end;
+ Undef ->
+ put_chars(Undef, Port, Q)
+ end;
io_request({get_chars,Enc,Prompt,N}, Port, Q) -> % New in R9C
get_chars(Prompt, io_lib, collect_chars, N, Port, Q, Enc);
io_request({get_line,Enc,Prompt}, Port, Q) ->
@@ -285,7 +299,8 @@ put_port(List, Port) ->
%% send_port(Port, Command)
send_port(Port, Command) ->
- Port ! {self(),Command}.
+ Port ! {self(),Command},
+ ok.
%% io_reply(From, ReplyAs, Reply)
%% The function for sending i/o command acknowledgement.
@@ -296,7 +311,7 @@ io_reply(From, ReplyAs, Reply) ->
%% put_chars
put_chars(Chars, Port, Q) when is_binary(Chars) ->
- put_port(Chars, Port),
+ ok = put_port(Chars, Port),
{ok,ok,Q};
put_chars(Chars, Port, Q) ->
case catch list_to_binary(Chars) of
@@ -360,16 +375,20 @@ getopts(_Port,Q) ->
Bin = {binary, get(read_mode) =:= binary},
Uni = {encoding, get(encoding)},
{ok,[Bin,Uni],Q}.
-
get_line_bin(Prompt,Port,Q, Enc) ->
- prompt(Port, Prompt),
- case {get(eof),queue:is_empty(Q)} of
- {true,true} ->
- {ok,eof,Q};
- _ ->
- get_line(Prompt,Port, Q, [], Enc)
+ case prompt(Port, Prompt) of
+ error ->
+ {error,{error,get_line},Q};
+ ok ->
+ case {get(eof),queue:is_empty(Q)} of
+ {true,true} ->
+ {ok,eof,Q};
+ _ ->
+ get_line(Prompt,Port, Q, [], Enc)
+ end
end.
+
get_line(Prompt, Port, Q, Acc, Enc) ->
case queue:is_empty(Q) of
true ->
@@ -386,8 +405,12 @@ get_line(Prompt, Port, Q, Acc, Enc) ->
get_line(Prompt, Port, Q, Acc, Enc);
{io_request,From,ReplyAs,Request} when is_pid(From) ->
do_io_request(Request, From, ReplyAs, Port, queue:new()),
- prompt(Port, Prompt),
- get_line(Prompt, Port, Q, Acc, Enc);
+ case prompt(Port, Prompt) of
+ error ->
+ {error,{error,get_line},Q};
+ ok ->
+ get_line(Prompt, Port, Q, Acc, Enc)
+ end;
{'EXIT',From,What} when node(From) =:= node() ->
{exit,What}
end;
@@ -420,6 +443,7 @@ srch(<<X:8,_/binary>>,X,N) ->
{match,[{N,1}]};
srch(<<_:8,T/binary>>,X,N) ->
srch(T,X,N+1).
+
get_line_doit(Prompt, Port, Q, Accu, Enc) ->
case queue:is_empty(Q) of
true ->
@@ -569,12 +593,16 @@ binrev(L, T) ->
%% Entry function.
get_chars(Prompt, M, F, Xa, Port, Q, Enc) ->
- prompt(Port, Prompt),
- case {get(eof),queue:is_empty(Q)} of
- {true,true} ->
- {ok,eof,Q};
- _ ->
- get_chars(Prompt, M, F, Xa, Port, Q, start, Enc)
+ case prompt(Port, Prompt) of
+ error ->
+ {error,{error,get_chars},Q};
+ ok ->
+ case {get(eof),queue:is_empty(Q)} of
+ {true,true} ->
+ {ok,eof,Q};
+ _ ->
+ get_chars(Prompt, M, F, Xa, Port, Q, start, Enc)
+ end
end.
%% First loop. Wait for port data. Respond to output requests.
@@ -608,8 +636,12 @@ get_chars(Prompt, M, F, Xa, Port, Q, State, Enc) ->
get_chars_req(Prompt, M, F, XtraArg, Port, Q, State,
Req, From, ReplyAs, Enc) ->
do_io_request(Req, From, ReplyAs, Port, queue:new()), %Keep Q over this call
- prompt(Port, Prompt),
- get_chars(Prompt, M, F, XtraArg, Port, Q, State, Enc).
+ case prompt(Port, Prompt) of
+ error ->
+ {error,{error,get_chars},Q};
+ ok ->
+ get_chars(Prompt, M, F, XtraArg, Port, Q, State, Enc)
+ end.
%% Second loop. Pass data to client as long as it wants more.
%% A ^G in data interrupts loop if 'noshell' is not undefined.
@@ -671,12 +703,15 @@ get_chars_more(State, M, F, Xa, Port, Q, Enc) ->
%% common case, reduces execution time by 20%
prompt(_Port, '') -> ok;
-
prompt(Port, Prompt) ->
Encoding = get(encoding),
- put_port(wrap_characters_to_binary(io_lib:format_prompt(Prompt, Encoding),
- unicode, Encoding),
- Port).
+ PromptString = io_lib:format_prompt(Prompt, Encoding),
+ case wrap_characters_to_binary(PromptString, unicode, Encoding) of
+ Bin when is_binary(Bin) ->
+ put_port(Bin, Port);
+ error ->
+ error
+ end.
%% Convert error code to make it look as before
err_func(io_lib, get_until, {_,F,_}) ->
@@ -753,21 +788,30 @@ cast(Data, list, unicode, unicode) when is_binary(Data); is_list(Data) ->
_ -> exit({no_translation, unicode, unicode})
end.
-wrap_characters_to_binary(Chars,unicode,latin1) ->
- case unicode:characters_to_binary(Chars,unicode,latin1) of
- {error,_,_} ->
- list_to_binary(
- [ case X of
- High when High > 255 ->
- ["\\x{",erlang:integer_to_list(X, 16),$}];
- Low ->
- Low
- end || X <- unicode:characters_to_list(Chars,unicode) ]);
- Bin ->
- Bin
+wrap_characters_to_binary(Chars, unicode, latin1) ->
+ case catch unicode:characters_to_binary(Chars, unicode, latin1) of
+ Bin when is_binary(Bin) ->
+ Bin;
+ _ ->
+ case catch unicode:characters_to_list(Chars, unicode) of
+ L when is_list(L) ->
+ list_to_binary(
+ [ case X of
+ High when High > 255 ->
+ ["\\x{",erlang:integer_to_list(X, 16),$}];
+ Low ->
+ Low
+ end || X <- L ]);
+ _ ->
+ error
+ end
end;
-
-wrap_characters_to_binary(Bin,From,From) when is_binary(Bin) ->
+wrap_characters_to_binary(Bin, From, From) when is_binary(Bin) ->
Bin;
-wrap_characters_to_binary(Chars,From,To) ->
- unicode:characters_to_binary(Chars,From,To).
+wrap_characters_to_binary(Chars, From, To) ->
+ case catch unicode:characters_to_binary(Chars, From, To) of
+ Bin when is_binary(Bin) ->
+ Bin;
+ _ ->
+ error
+ end.
diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl
index 8f2ca28f56..bb654495d3 100644
--- a/lib/kernel/src/user_drv.erl
+++ b/lib/kernel/src/user_drv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -129,7 +129,7 @@ server1(Iport, Oport, Shell) ->
Gr = gr_add_cur(Gr1, Curr, Shell1),
%% Print some information.
io_request({put_chars, unicode,
- flatten(io_lib:format("~s\n",
+ flatten(io_lib:format("~ts\n",
[erlang:system_info(system_version)]))},
Iport, Oport),
%% Enter the server loop.