aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in12
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin23784 -> 23752 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin85144 -> 85064 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ms_transform.beambin20224 -> 20180 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin7020 -> 7052 bytes
-rw-r--r--erts/doc/src/erlang.xml26
-rw-r--r--erts/doc/src/match_spec.xml6
-rw-r--r--erts/emulator/beam/atom.names3
-rw-r--r--erts/emulator/beam/bif.c18
-rw-r--r--erts/emulator/beam/erl_alloc.types2
-rw-r--r--erts/emulator/beam/erl_bif_info.c11
-rw-r--r--erts/emulator/beam/erl_gc.c3
-rw-r--r--erts/emulator/beam/erl_process.c252
-rw-r--r--erts/emulator/beam/erl_process.h14
-rw-r--r--erts/emulator/test/statistics_SUITE.erl98
-rw-r--r--erts/preloaded/ebin/erlang.beambin41136 -> 42416 bytes
-rw-r--r--erts/preloaded/src/erlang.erl34
-rw-r--r--lib/Makefile54
-rw-r--r--lib/appmon/doc/src/appmon.xml6
-rw-r--r--lib/appmon/doc/src/appmon_chapter.xml6
-rw-r--r--lib/appmon/src/appmon.erl5
-rw-r--r--lib/appmon/src/appmon_a.erl5
-rw-r--r--lib/appmon/src/appmon_lb.erl7
-rw-r--r--lib/appmon/src/appmon_txt.erl5
-rw-r--r--lib/compiler/doc/src/compile.xml2
-rw-r--r--lib/debugger/src/dbg_ui_break_win.erl12
-rw-r--r--lib/debugger/src/dbg_ui_edit_win.erl6
-rw-r--r--lib/debugger/src/dbg_ui_filedialog_win.erl7
-rw-r--r--lib/debugger/src/dbg_ui_mon_win.erl13
-rw-r--r--lib/debugger/src/dbg_ui_trace_win.erl19
-rw-r--r--lib/debugger/src/dbg_ui_win.erl9
-rw-r--r--lib/debugger/src/dbg_ui_winman.erl5
-rw-r--r--lib/debugger/src/dbg_wx_trace_win.erl1
-rw-r--r--lib/dialyzer/src/dialyzer_gui.erl17
-rw-r--r--lib/erl_docgen/priv/css/otp_doc.css29
-rw-r--r--lib/et/src/et_gs_contents_viewer.erl11
-rw-r--r--lib/et/src/et_gs_viewer.erl17
-rw-r--r--lib/gs/contribs/bonk/bonk.erl6
-rw-r--r--lib/gs/contribs/cols/cols.erl6
-rw-r--r--lib/gs/contribs/cols/highscore.erl7
-rw-r--r--lib/gs/contribs/mandel/mandel.erl5
-rw-r--r--lib/gs/contribs/othello/othello_board.erl6
-rw-r--r--lib/gs/doc/src/gs.xml4
-rw-r--r--lib/gs/examples/ball.erl6
-rw-r--r--lib/gs/examples/browser.erl8
-rw-r--r--lib/gs/examples/calc.erl5
-rw-r--r--lib/gs/examples/calc2.erl6
-rw-r--r--lib/gs/examples/color_demo.erl5
-rw-r--r--lib/gs/examples/color_demo2.erl4
-rw-r--r--lib/gs/examples/distrib_draw.erl5
-rw-r--r--lib/gs/examples/entry_demo.erl6
-rw-r--r--lib/gs/examples/event_test.erl3
-rw-r--r--lib/gs/examples/file_dialog.erl5
-rw-r--r--lib/gs/examples/focus_demo.erl5
-rw-r--r--lib/gs/examples/frac.erl3
-rw-r--r--lib/gs/examples/line_demo.erl6
-rw-r--r--lib/gs/examples/man.erl9
-rw-r--r--lib/gs/examples/menu_demo.erl6
-rw-r--r--lib/gs/examples/rubber.erl8
-rw-r--r--lib/gs/src/gs.erl8
-rw-r--r--lib/gs/src/gs_frontend.erl2
-rw-r--r--lib/gs/src/gs_make.erl1
-rw-r--r--lib/gs/src/gse.erl62
-rw-r--r--lib/gs/src/gstk.erl2
-rw-r--r--lib/gs/src/gstk_arc.erl1
-rw-r--r--lib/gs/src/gstk_canvas.erl2
-rw-r--r--lib/gs/src/gstk_editor.erl3
-rw-r--r--lib/gs/src/gstk_entry.erl1
-rw-r--r--lib/gs/src/gstk_generic.erl1
-rw-r--r--lib/gs/src/gstk_grid.erl1
-rw-r--r--lib/gs/src/gstk_gridline.erl2
-rw-r--r--lib/gs/src/gstk_image.erl1
-rw-r--r--lib/gs/src/gstk_menu.erl1
-rw-r--r--lib/gs/src/gstk_menuitem.erl1
-rw-r--r--lib/gs/src/gstk_port_handler.erl1
-rw-r--r--lib/gs/src/gstk_rectangle.erl1
-rw-r--r--lib/gs/src/gstk_window.erl1
-rw-r--r--lib/gs/src/tcl2erl.erl1
-rw-r--r--lib/gs/src/tool_file_dialog.erl10
-rw-r--r--lib/gs/src/tool_utils.erl5
-rw-r--r--lib/hipe/cerl/cerl_hipe_primops.hrl1
-rw-r--r--lib/hipe/cerl/cerl_hipeify.erl1
-rw-r--r--lib/hipe/cerl/cerl_messagean.erl1
-rw-r--r--lib/hipe/cerl/cerl_to_icode.erl3
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl57
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl4
-rw-r--r--lib/hipe/icode/hipe_icode_inline_bifs.erl3
-rw-r--r--lib/hipe/icode/hipe_icode_type.erl6
-rw-r--r--lib/hipe/tools/hipe_tool.erl12
-rw-r--r--lib/observer/src/etop_gui.erl7
-rw-r--r--lib/orber/src/orber_ifr.erl2
-rw-r--r--lib/orber/test/orber_SUITE.erl36
-rw-r--r--lib/os_mon/c_src/memsup.c12
-rw-r--r--lib/pman/doc/src/pman.xml6
-rw-r--r--lib/pman/doc/src/pman_chapter.xml6
-rw-r--r--lib/pman/src/pman_buf_converter.erl1
-rw-r--r--lib/pman/src/pman_buf_printer.erl2
-rw-r--r--lib/pman/src/pman_main.erl2
-rw-r--r--lib/pman/src/pman_module_info.erl2
-rw-r--r--lib/pman/src/pman_shell.erl4
-rw-r--r--lib/pman/src/pman_tool.erl1
-rw-r--r--lib/pman/src/pman_win.erl10
-rw-r--r--lib/public_key/src/pubkey_ssh.erl95
-rw-r--r--lib/sasl/src/release_handler.erl2
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl56
-rw-r--r--lib/ssh/doc/src/ssh.xml57
-rw-r--r--lib/ssh/src/DSS.asn120
-rw-r--r--lib/ssh/src/Makefile33
-rw-r--r--lib/ssh/src/PKCS-1.asn1116
-rw-r--r--lib/ssh/src/prebuild.skip2
-rw-r--r--lib/ssh/src/ssh.app.src7
-rw-r--r--lib/ssh/src/ssh.erl96
-rw-r--r--lib/ssh/src/ssh.hrl17
-rw-r--r--lib/ssh/src/ssh_auth.erl160
-rw-r--r--lib/ssh/src/ssh_bits.erl6
-rw-r--r--lib/ssh/src/ssh_connection.erl4
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl45
-rw-r--r--lib/ssh/src/ssh_connection_manager.erl6
-rw-r--r--lib/ssh/src/ssh_dsa.erl95
-rw-r--r--lib/ssh/src/ssh_file.erl641
-rw-r--r--lib/ssh/src/ssh_key_api.erl45
-rw-r--r--lib/ssh/src/ssh_rsa.erl298
-rw-r--r--lib/ssh/src/ssh_sftpd.erl22
-rw-r--r--lib/ssh/src/ssh_transport.erl266
-rw-r--r--lib/ssh/src/ssh_xfer.erl16
-rw-r--r--lib/ssh/test/Makefile3
-rw-r--r--lib/ssh/test/ssh_SUITE.erl72
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl156
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_dsa.pub1
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_rsa27
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_rsa.pub1
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key20
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub5
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl40
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl32
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl49
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_test_lib.erl174
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl117
-rw-r--r--lib/ssl/src/inet_tls_dist.erl14
-rw-r--r--lib/ssl/src/ssl_handshake.erl17
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl46
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl103
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl10
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl6
-rw-r--r--lib/stdlib/doc/src/binary.xml2
-rw-r--r--lib/stdlib/doc/src/ms_transform.xml4
-rw-r--r--lib/stdlib/doc/src/sofs.xml10
-rw-r--r--lib/stdlib/src/erl_eval.erl1
-rw-r--r--lib/stdlib/src/erl_lint.erl12
-rw-r--r--lib/stdlib/src/ms_transform.erl2
-rw-r--r--lib/stdlib/src/otp_internal.erl18
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl5
-rw-r--r--lib/stdlib/test/sofs_SUITE.erl59
-rw-r--r--lib/toolbar/doc/src/toolbar.xml5
-rw-r--r--lib/toolbar/doc/src/toolbar_chapter.xml5
-rw-r--r--lib/toolbar/src/canvasbutton.erl3
-rw-r--r--lib/toolbar/src/toolbar.erl1
-rw-r--r--lib/toolbar/src/toolbar_graphics.erl3
-rw-r--r--lib/toolbar/src/toolbar_toolconfig.erl5
-rw-r--r--lib/tv/doc/src/table_visualizer_chapter.xml6
-rw-r--r--lib/tv/doc/src/tv.xml6
-rw-r--r--lib/tv/src/tv_db.erl4
-rw-r--r--lib/tv/src/tv_db_search.erl12
-rw-r--r--lib/tv/src/tv_etsread.erl3
-rw-r--r--lib/tv/src/tv_info.erl8
-rw-r--r--lib/tv/src/tv_ip.erl6
-rw-r--r--lib/tv/src/tv_main.erl14
-rw-r--r--lib/tv/src/tv_new_table.erl10
-rw-r--r--lib/tv/src/tv_nodewin.erl9
-rw-r--r--lib/tv/src/tv_pb.erl3
-rw-r--r--lib/tv/src/tv_pb_funcs.erl6
-rw-r--r--lib/tv/src/tv_pc.erl1
-rw-r--r--lib/tv/src/tv_pc_menu_handling.erl4
-rw-r--r--lib/tv/src/tv_pd.erl5
-rw-r--r--lib/tv/src/tv_pd_display.erl7
-rw-r--r--lib/tv/src/tv_pd_frames.erl2
-rw-r--r--lib/tv/src/tv_pd_scale.erl2
-rw-r--r--lib/tv/src/tv_pg.erl1
-rw-r--r--lib/tv/src/tv_pg_gridfcns.erl4
-rw-r--r--lib/tv/src/tv_poll_dialog.erl8
-rw-r--r--lib/tv/src/tv_pw.erl1
-rw-r--r--lib/tv/src/tv_pw_window.erl4
-rw-r--r--lib/tv/src/tv_rec_edit.erl10
-rw-r--r--lib/tv/src/tv_utils.erl3
-rw-r--r--xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf4
190 files changed, 2500 insertions, 1963 deletions
diff --git a/Makefile.in b/Makefile.in
index 648575e5fd..2ded1b4356 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -598,6 +598,18 @@ secondary_bootstrap_copy:
cp $$x $$TF; \
true; \
done
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl ; fi
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl/include ; fi
+ for x in lib/xmerl/include/*.hrl; do \
+ BN=`basename $$x`; \
+ TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/xmerl/include/$$BN; \
+ test -f $$TF && \
+ test '!' -z "`find $$x -newer $$TF -print`" && \
+ cp $$x $$TF; \
+ test '!' -f $$TF && \
+ cp $$x $$TF; \
+ true; \
+ done
tertiary_bootstrap_build:
cd lib && \
diff --git a/bootstrap/lib/stdlib/ebin/erl_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index e646342e2b..6198c4f43a 100644
--- a/bootstrap/lib/stdlib/ebin/erl_eval.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_eval.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index 6fa0884135..798924c19b 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ms_transform.beam b/bootstrap/lib/stdlib/ebin/ms_transform.beam
index f8689ddf72..bc16416161 100644
--- a/bootstrap/lib/stdlib/ebin/ms_transform.beam
+++ b/bootstrap/lib/stdlib/ebin/ms_transform.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index 5bbb23db1b..636a7a24d5 100644
--- a/bootstrap/lib/stdlib/ebin/otp_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam
Binary files differ
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index a21021d864..fbe7b36163 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -4933,6 +4933,21 @@ true</pre>
threads in the Erlang run-time system and may therefore be greater
than the wall-clock time.</p>
</item>
+ <tag><marker id="statistics_scheduler_wall_time"><c>scheduler_wall_time</c></marker></tag>
+ <item>
+ <p>Returns
+ <c>[{Scheduler_Id, Scheduler_Worked_Time, Scheduler_Total_Time}]</c>, time lapses are since the
+ the system flag <seealso marker="#system_flag_scheduler_wall_time">scheduler_wall_time</seealso>
+ was set to true.
+ Returns <c>undefined</c> if the system flag <seealso marker="#system_flag_scheduler_wall_time">
+ scheduler_wall_time</seealso> is set to false.
+ </p>
+ <p>The list of scheduler information is unsorted and may come in different order
+ between calls. The time unit is undefined and may be changed and should only be used
+ to calculate relative utilization.
+ </p>
+ </item>
+
<tag><c>wall_clock</c></tag>
<item>
<p>Returns
@@ -5305,6 +5320,14 @@ true</pre>
flags.
</p>
</item>
+ <tag><marker id="system_flag_scheduler_wall_time"><c>erlang:system_flag(scheduler_wall_time, Boolean)</c></marker></tag>
+ <item>
+ <p>Turns on/off scheduler wall time measurements. </p>
+ <p>For more information see,
+ <seealso marker="#statistics_scheduler_wall_time">erlang:statistics(scheduler_wall_time)</seealso>.
+ </p>
+ </item>
+
<tag><marker id="system_flag_schedulers_online"><c>erlang:system_flag(schedulers_online, SchedulersOnline)</c></marker></tag>
<item>
<p>Sets the amount of schedulers online. Valid range is
@@ -5316,6 +5339,7 @@ true</pre>
<seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>.
</p>
</item>
+
<tag><c>erlang:system_flag(trace_control_word, TCW)</c></tag>
<item>
<p>Sets the value of the node's trace control word to
diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml
index f0390c9db8..cd2b3abc1e 100644
--- a/erts/doc/src/match_spec.xml
+++ b/erts/doc/src/match_spec.xml
@@ -75,7 +75,7 @@
<item>MatchCondition ::= { GuardFunction } |
{ GuardFunction, ConditionExpression, ... }
</item>
- <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_constant]]></c> |
+ <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> |
<c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | <c><![CDATA[is_list]]></c> |
<c><![CDATA[is_number]]></c> | <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> |
<c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | <c><![CDATA[is_binary]]></c> |
@@ -133,7 +133,7 @@
<item>MatchCondition ::= { GuardFunction } |
{ GuardFunction, ConditionExpression, ... }
</item>
- <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_constant]]></c> |
+ <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> |
<c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | <c><![CDATA[is_list]]></c> |
<c><![CDATA[is_number]]></c> | <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> |
<c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | <c><![CDATA[is_binary]]></c> |
@@ -172,7 +172,7 @@
<title>Functions allowed in all types of match specifications</title>
<p>The different functions allowed in <c><![CDATA[match_spec]]></c> work like this:
</p>
- <p><em>is_atom, is_constant, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function: </em> Like the corresponding guard tests in
+ <p><em>is_atom, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function: </em> Like the corresponding guard tests in
Erlang, return <c><![CDATA[true]]></c> or <c><![CDATA[false]]></c>.
</p>
<p><em>is_record: </em>Takes an additional parameter, which SHALL
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 71454b3e57..7be40976f6 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -95,6 +95,7 @@ atom atom
atom atom_used
atom attributes
atom await_proc_exit
+atom await_sched_wall_time_modifications
atom awaiting_load
atom awaiting_unload
atom backtrace backtrace_depth
@@ -239,6 +240,7 @@ atom generational
atom get_seq_token
atom get_tcw
atom getenv
+atom gather_sched_wall_time_result
atom getting_linked
atom getting_unlinked
atom global
@@ -554,6 +556,7 @@ atom waiting
atom wall_clock
atom warning
atom warning_msg
+atom scheduler_wall_time
atom wordsize
atom write_concurrency
atom xor
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 55f4798892..f8305944a4 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -43,6 +43,9 @@ static Export* set_cpu_topology_trap = NULL;
static Export* await_proc_exit_trap = NULL;
Export* erts_format_cpu_topology_trap = NULL;
+static Export *await_sched_wall_time_mod_trap;
+static erts_smp_atomic32_t sched_wall_time;
+
#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
/*
@@ -4160,6 +4163,18 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
BIF_RET(am_true);
+ } else if (BIF_ARG_1 == am_scheduler_wall_time) {
+ if (BIF_ARG_2 == am_true || BIF_ARG_2 == am_false) {
+ erts_aint32_t new = BIF_ARG_2 == am_true ? 1 : 0;
+ erts_aint32_t old = erts_smp_atomic32_xchg_nob(&sched_wall_time,
+ new);
+ Eterm ref = erts_sched_wall_time_request(BIF_P, 1, new);
+ ASSERT(is_value(ref));
+ BIF_TRAP2(await_sched_wall_time_mod_trap,
+ BIF_P,
+ ref,
+ old ? am_true : am_false);
+ }
} else if (ERTS_IS_ATOM_STR("scheduling_statistics", BIF_ARG_1)) {
int what;
if (ERTS_IS_ATOM_STR("disable", BIF_ARG_2))
@@ -4457,6 +4472,9 @@ void erts_init_bif(void)
am_format_cpu_topology,
1);
await_proc_exit_trap = erts_export_put(am_erlang,am_await_proc_exit,3);
+ await_sched_wall_time_mod_trap
+ = erts_export_put(am_erlang, am_await_sched_wall_time_modifications, 2);
+ erts_smp_atomic32_init_nob(&sched_wall_time, 0);
}
#ifdef HARDDEBUG
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index 962db8b831..90a6c0cbee 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -367,6 +367,7 @@ type EXPORT LONG_LIVED_LOW CODE export_entry
type MONITOR_SH STANDARD_LOW PROCESSES monitor_sh
type NLINK_SH STANDARD_LOW PROCESSES nlink_sh
type AINFO_REQ STANDARD_LOW SYSTEM alloc_info_request
+type SCHED_WTIME_REQ STANDARD_LOW SYSTEM sched_wall_time_request
+else # "fullword"
@@ -383,6 +384,7 @@ type EXPORT LONG_LIVED CODE export_entry
type MONITOR_SH FIXED_SIZE PROCESSES monitor_sh
type NLINK_SH FIXED_SIZE PROCESSES nlink_sh
type AINFO_REQ SHORT_LIVED SYSTEM alloc_info_request
+type SCHED_WTIME_REQ SHORT_LIVED SYSTEM sched_wall_time_request
+endif
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 5a806777fe..ebd475f73a 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -57,6 +57,8 @@
static Export* alloc_info_trap = NULL;
static Export* alloc_sizes_trap = NULL;
+static Export *gather_sched_wall_time_res_trap;
+
#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
/* Keep erts_system_version as a global variable for easy access from a core */
@@ -3180,7 +3182,12 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1)
Eterm res;
Eterm* hp;
- if (BIF_ARG_1 == am_context_switches) {
+ if (BIF_ARG_1 == am_scheduler_wall_time) {
+ res = erts_sched_wall_time_request(BIF_P, 0, 0);
+ if (is_non_value(res))
+ BIF_RET(am_undefined);
+ BIF_TRAP1(gather_sched_wall_time_res_trap, BIF_P, res);
+ } else if (BIF_ARG_1 == am_context_switches) {
Eterm cs = erts_make_integer(erts_get_total_context_switches(), BIF_P);
hp = HAlloc(BIF_P, 3);
res = TUPLE2(hp, cs, SMALL_ZERO);
@@ -4160,6 +4167,8 @@ erts_bif_info_init(void)
alloc_info_trap = erts_export_put(am_erlang, am_alloc_info, 1);
alloc_sizes_trap = erts_export_put(am_erlang, am_alloc_sizes, 1);
+ gather_sched_wall_time_res_trap
+ = erts_export_put(am_erlang, am_gather_sched_wall_time_result, 1);
process_info_init();
os_info_init();
}
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 9590aa4a74..bde87b8346 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -357,10 +357,11 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
p->gcstatus = p->status;
p->status = P_GARBING;
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+
if (erts_system_monitor_long_gc != 0) {
get_now(&ms1, &s1, &us1);
}
- erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
ERTS_CHK_OFFHEAP(p);
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 5469a59d8c..30c91af630 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -537,6 +537,209 @@ erts_late_init_process(void)
}
+static void
+init_sched_wall_time(ErtsSchedWallTime *swtp)
+{
+ swtp->enabled = 0;
+ swtp->start = 0;
+ swtp->working.total = 0;
+ swtp->working.start = 0;
+ swtp->working.currently = 0;
+}
+
+static ERTS_INLINE Uint64
+sched_wall_time_ts(void)
+{
+#ifdef HAVE_GETHRTIME
+ return (Uint64) sys_gethrtime();
+#else
+ Uint64 res;
+ SysTimeval tv;
+ sys_gettimeofday(&tv);
+ res = (Uint64) tv.tv_sec*1000000;
+ res += (Uint64) tv.tv_usec;
+ return res;
+#endif
+}
+
+static ERTS_INLINE void
+sched_wall_time_change(ErtsSchedulerData *esdp, int working)
+{
+ if (esdp->sched_wall_time.enabled) {
+ Uint64 ts = sched_wall_time_ts();
+ if (working) {
+#ifdef DEBUG
+ ASSERT(!esdp->sched_wall_time.working.currently);
+ esdp->sched_wall_time.working.currently = 1;
+#endif
+ ts -= esdp->sched_wall_time.start;
+ esdp->sched_wall_time.working.start = ts;
+ }
+ else {
+#ifdef DEBUG
+ ASSERT(esdp->sched_wall_time.working.currently);
+ esdp->sched_wall_time.working.currently = 0;
+#endif
+ ts -= esdp->sched_wall_time.start;
+ ts -= esdp->sched_wall_time.working.start;
+ esdp->sched_wall_time.working.total += ts;
+ }
+ }
+}
+
+typedef struct {
+ int set;
+ int enable;
+ Process *proc;
+ Eterm ref;
+ Eterm ref_heap[REF_THING_SIZE];
+ Uint req_sched;
+ erts_smp_atomic32_t refc;
+} ErtsSchedWallTimeReq;
+
+#if !HALFWORD_HEAP
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(swtreq,
+ ErtsSchedWallTimeReq,
+ 5,
+ ERTS_ALC_T_SCHED_WTIME_REQ)
+#else
+static ERTS_INLINE ErtsSchedWallTimeReq *
+swtreq_alloc(void)
+{
+ return erts_alloc(ERTS_ALC_T_SCHED_WTIME_REQ,
+ sizeof(ErtsSchedWallTimeReq));
+}
+
+static ERTS_INLINE void
+swtreq_free(ErtsSchedWallTimeReq *ptr)
+{
+ erts_free(ERTS_ALC_T_SCHED_WTIME_REQ, ptr);
+}
+#endif
+
+static void
+reply_sched_wall_time(void *vswtrp)
+{
+ Uint64 working = 0, total = 0;
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ ErtsSchedWallTimeReq *swtrp = (ErtsSchedWallTimeReq *) vswtrp;
+ ErtsProcLocks rp_locks = (swtrp->req_sched == esdp->no
+ ? ERTS_PROC_LOCK_MAIN
+ : 0);
+ Process *rp = swtrp->proc;
+ Eterm ref_copy = NIL, msg;
+ Eterm *hp = NULL;
+ Eterm **hpp;
+ Uint sz, *szp;
+ ErlOffHeap *ohp = NULL;
+ ErlHeapFragment *bp = NULL;
+
+ ASSERT(esdp);
+
+ if (swtrp->set) {
+ if (!swtrp->enable && esdp->sched_wall_time.enabled)
+ esdp->sched_wall_time.enabled = 0;
+ else if (swtrp->enable && !esdp->sched_wall_time.enabled) {
+ Uint64 ts = sched_wall_time_ts();
+ esdp->sched_wall_time.enabled = 1;
+ esdp->sched_wall_time.start = ts;
+ esdp->sched_wall_time.working.total = 0;
+ esdp->sched_wall_time.working.start = 0;
+ esdp->sched_wall_time.working.currently = 1;
+ }
+ }
+
+ if (esdp->sched_wall_time.enabled) {
+ Uint64 ts = sched_wall_time_ts();
+ ASSERT(esdp->sched_wall_time.working.currently);
+ ts -= esdp->sched_wall_time.start;
+ total = ts;
+ ts -= esdp->sched_wall_time.working.start;
+ working = esdp->sched_wall_time.working.total + ts;
+ }
+
+ sz = 0;
+ hpp = NULL;
+ szp = &sz;
+
+ while (1) {
+ if (hpp)
+ ref_copy = STORE_NC(hpp, ohp, swtrp->ref);
+ else
+ *szp += REF_THING_SIZE;
+
+ if (swtrp->set)
+ msg = ref_copy;
+ else {
+ msg = (!esdp->sched_wall_time.enabled
+ ? am_notsup
+ : erts_bld_tuple(hpp, szp, 3,
+ make_small(esdp->no),
+ erts_bld_uint64(hpp, szp, working),
+ erts_bld_uint64(hpp, szp, total)));
+
+ msg = erts_bld_tuple(hpp, szp, 2, ref_copy, msg);
+ }
+ if (hpp)
+ break;
+
+ hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ szp = NULL;
+ hpp = &hp;
+ }
+
+ erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+
+ if (swtrp->req_sched == esdp->no)
+ rp_locks &= ~ERTS_PROC_LOCK_MAIN;
+
+ if (rp_locks)
+ erts_smp_proc_unlock(rp, rp_locks);
+
+ erts_smp_proc_dec_refc(rp);
+
+ if (erts_smp_atomic32_dec_read_nob(&swtrp->refc) == 0)
+ swtreq_free(vswtrp);
+}
+
+Eterm
+erts_sched_wall_time_request(Process *c_p, int set, int enable)
+{
+ ErtsSchedulerData *esdp = ERTS_PROC_GET_SCHDATA(c_p);
+ Eterm ref;
+ ErtsSchedWallTimeReq *swtrp;
+ Eterm *hp;
+
+ if (!set && !esdp->sched_wall_time.enabled)
+ return THE_NON_VALUE;
+
+ swtrp = swtreq_alloc();
+ ref = erts_make_ref(c_p);
+ hp = &swtrp->ref_heap[0];
+
+ swtrp->set = set;
+ swtrp->enable = enable;
+ swtrp->proc = c_p;
+ swtrp->ref = STORE_NC(&hp, NULL, ref);
+ swtrp->req_sched = esdp->no;
+ erts_smp_atomic32_init_nob(&swtrp->refc,
+ (erts_aint32_t) erts_no_schedulers);
+
+ erts_smp_proc_add_refc(c_p, (Sint32) erts_no_schedulers);
+
+#ifdef ERTS_SMP
+ if (erts_no_schedulers > 1)
+ erts_schedule_multi_misc_aux_work(1,
+ erts_no_schedulers,
+ reply_sched_wall_time,
+ (void *) swtrp);
+#endif
+
+ reply_sched_wall_time((void *) swtrp);
+
+ return ref;
+}
+
static ERTS_INLINE ErtsProcList *
proclist_create(Process *p)
{
@@ -1707,6 +1910,7 @@ aux_thread(void *unused)
static void
scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
{
+ int working = 1;
ErtsSchedulerSleepInfo *ssi = esdp->ssi;
int spincount;
erts_aint32_t aux_work = 0;
@@ -1737,12 +1941,17 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
tse_wait:
+ if (thr_prgr_active != working)
+ sched_wall_time_change(esdp, thr_prgr_active);
+
while (1) {
aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
if (aux_work) {
- if (!thr_prgr_active)
+ if (!thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
aux_work = handle_aux_work(&esdp->aux_work_data, aux_work);
if (aux_work && erts_thr_progress_update(esdp))
erts_thr_progress_leader_update(esdp);
@@ -1751,8 +1960,10 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
if (aux_work)
flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
else {
- if (thr_prgr_active)
+ if (thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 0);
+ sched_wall_time_change(esdp, 0);
+ }
erts_thr_progress_prepare_wait(esdp);
flgs = sched_spin_wait(ssi, spincount);
@@ -1789,8 +2000,10 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
if (flgs & ~ERTS_SSI_FLG_SUSPENDED)
erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
- if (!thr_prgr_active)
+ if (!thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
erts_smp_runq_lock(rq);
sched_active(esdp->no, rq);
@@ -1806,14 +2019,21 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
sched_waiting_sys(esdp->no, rq);
+
erts_smp_runq_unlock(rq);
+ ASSERT(working);
+ sched_wall_time_change(esdp, working = 0);
+
spincount = ERTS_SCHED_SYS_SLEEP_SPINCOUNT;
while (spincount-- > 0) {
sys_poll_aux_work:
+ if (working)
+ sched_wall_time_change(esdp, working = 0);
+
ASSERT(!erts_port_task_have_outstanding_io_tasks());
erl_sys_schedule(1); /* Might give us something to do */
@@ -1828,6 +2048,8 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
if (aux_work) {
+ if (!working)
+ sched_wall_time_change(esdp, working = 1);
#ifdef ERTS_SMP
if (!thr_prgr_active)
erts_thr_progress_active(esdp, thr_prgr_active = 1);
@@ -1920,6 +2142,9 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
erts_smp_runq_unlock(rq);
+ if (working)
+ sched_wall_time_change(esdp, working = 0);
+
#ifdef ERTS_SMP
if (thr_prgr_active)
erts_thr_progress_active(esdp, thr_prgr_active = 0);
@@ -1955,6 +2180,8 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
if (flgs & ~ERTS_SSI_FLG_SUSPENDED)
erts_smp_atomic32_read_band_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
#endif
+ if (!working)
+ sched_wall_time_change(esdp, working = 1);
sched_active_sys(esdp->no, rq);
}
@@ -3430,9 +3657,14 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online)
esdp->run_queue->scheduler = esdp;
init_aux_work_data(&esdp->aux_work_data, esdp);
+ init_sched_wall_time(&esdp->sched_wall_time);
}
init_misc_aux_work();
+#if !HALFWORD_HEAP
+ init_swtreq_alloc();
+#endif
+
#ifdef ERTS_SMP
@@ -3755,6 +3987,8 @@ suspend_scheduler(ErtsSchedulerData *esdp)
if (erts_system_profile_flags.scheduler)
profile_scheduler(make_small(esdp->no), am_inactive);
+ sched_wall_time_change(esdp, 0);
+
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
flgs = sched_prep_spin_suspended(ssi, ERTS_SSI_FLG_SUSPENDED);
@@ -3813,16 +4047,20 @@ suspend_scheduler(ErtsSchedulerData *esdp)
aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
if (aux_work) {
- if (!thr_prgr_active)
+ if (!thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
aux_work = handle_aux_work(&esdp->aux_work_data, aux_work);
if (aux_work && erts_thr_progress_update(esdp))
erts_thr_progress_leader_update(esdp);
}
if (!aux_work) {
- if (thr_prgr_active)
+ if (thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 0);
+ sched_wall_time_change(esdp, 0);
+ }
erts_thr_progress_prepare_wait(esdp);
flgs = sched_spin_suspended(ssi,
ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT);
@@ -3877,8 +4115,10 @@ suspend_scheduler(ErtsSchedulerData *esdp)
if (erts_system_profile_flags.scheduler)
profile_scheduler(make_small(esdp->no), am_active);
- if (!thr_prgr_active)
+ if (!thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
erts_smp_runq_lock(esdp->run_queue);
non_empty_runq(esdp->run_queue);
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index a51b380bb0..173b7df69d 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -394,6 +394,16 @@ do { \
} while (0)
typedef struct {
+ int enabled;
+ Uint64 start;
+ struct {
+ Uint64 total;
+ Uint64 start;
+ int currently;
+ } working;
+} ErtsSchedWallTime;
+
+typedef struct {
int sched_id;
ErtsSchedulerData *esdp;
ErtsSchedulerSleepInfo *ssi;
@@ -457,6 +467,8 @@ struct ErtsSchedulerData_ {
ErtsSchedAllocData alloc_data;
+ ErtsSchedWallTime sched_wall_time;
+
#ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC
erts_alloc_verify_func_t verify_unused_temp_alloc;
Allctr_t *verify_unused_temp_alloc_data;
@@ -1064,6 +1076,8 @@ void erts_late_init_process(void);
void erts_early_init_scheduling(int);
void erts_init_scheduling(int, int);
+Eterm erts_sched_wall_time_request(Process *c_p, int set, int enable);
+
ErtsProcList *erts_proclist_create(Process *);
void erts_proclist_destroy(ErtsProcList *);
int erts_proclist_same(ErtsProcList *, Process *);
diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl
index 0392312a6f..a93dd309c1 100644
--- a/erts/emulator/test/statistics_SUITE.erl
+++ b/erts/emulator/test/statistics_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. 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
@@ -29,6 +29,7 @@
runtime_zero_diff/1,
runtime_update/1, runtime_diff/1,
run_queue_one/1,
+ scheduler_wall_time/1,
reductions/1, reductions_big/1, garbage_collection/1, io/1,
badarg/1]).
@@ -51,8 +52,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[{group, wall_clock}, {group, runtime}, reductions,
- reductions_big, {group, run_queue}, garbage_collection,
- io, badarg].
+ reductions_big, {group, run_queue}, scheduler_wall_time,
+ garbage_collection, io, badarg].
groups() ->
[{wall_clock, [],
@@ -266,11 +267,10 @@ run_queue_one(Config) when is_list(Config) ->
run_queue_one_test(Config) when is_list(Config) ->
- ?line Hog = spawn_link(?MODULE, hog, [self()]),
+ ?line _Hog = spawn_link(?MODULE, hog, [self()]),
?line receive
- hog_started ->
- Hog ! go
- end,
+ hog_started -> ok
+ end,
?line receive after 100 -> ok end, % Give hog a head start.
?line case statistics(run_queue) of
N when N >= 1 -> ok;
@@ -280,18 +280,88 @@ run_queue_one_test(Config) when is_list(Config) ->
%% CPU-bound process, going at low priority. It will always be ready
%% to run.
-
+
hog(Pid) ->
?line process_flag(priority, low),
?line Pid ! hog_started,
- ?line receive
- go -> hog_iter(0)
+ ?line Mon = erlang:monitor(process, Pid),
+ ?line hog_iter(0, Mon).
+
+hog_iter(N, Mon) when N > 0 ->
+ receive
+ {'DOWN', Mon, _, _, _} -> ok
+ after 0 ->
+ ?line hog_iter(N-1, Mon)
+ end;
+hog_iter(0, Mon) ->
+ ?line hog_iter(10000, Mon).
+
+%%% Tests of statistics(scheduler_wall_time).
+
+scheduler_wall_time(doc) ->
+ "Tests that statistics(scheduler_wall_time) works as intended";
+scheduler_wall_time(Config) when is_list(Config) ->
+ %% Should return undefined if system_flag is not turned on yet
+ undefined = statistics(scheduler_wall_time),
+ %% Turn on statistics
+ false = erlang:system_flag(scheduler_wall_time, true),
+ try
+ Schedulers = erlang:system_info(schedulers_online),
+ %% Let testserver and everyone else finish their work
+ timer:sleep(500),
+ %% Empty load
+ EmptyLoad = get_load(),
+ {false, _} = {lists:any(fun(Load) -> Load > 50 end, EmptyLoad),EmptyLoad},
+ MeMySelfAndI = self(),
+ StartHog = fun() ->
+ Pid = spawn(?MODULE, hog, [self()]),
+ receive hog_started -> MeMySelfAndI ! go end,
+ Pid
+ end,
+ P1 = StartHog(),
+ %% Max on one, the other schedulers empty (hopefully)
+ %% Be generous the process can jump between schedulers
+ %% which is ok and we don't want the test to fail for wrong reasons
+ _L1 = [S1Load|EmptyScheds1] = get_load(),
+ {true,_} = {S1Load > 50,S1Load},
+ {false,_} = {lists:any(fun(Load) -> Load > 50 end, EmptyScheds1),EmptyScheds1},
+ {true,_} = {lists:sum(EmptyScheds1) < 60,EmptyScheds1},
+
+ %% 50% load
+ HalfHogs = [StartHog() || _ <- lists:seq(1, (Schedulers-1) div 2)],
+ HalfLoad = lists:sum(get_load()) div Schedulers,
+ if Schedulers < 2, HalfLoad > 80 -> ok; %% Ok only one scheduler online and one hog
+ %% We want roughly 50% load
+ HalfLoad > 40, HalfLoad < 60 -> ok;
+ true -> exit({halfload, HalfLoad})
+ end,
+
+ %% 100% load
+ LastHogs = [StartHog() || _ <- lists:seq(1, Schedulers div 2)],
+ FullScheds = get_load(),
+ {false,_} = {lists:any(fun(Load) -> Load < 80 end, FullScheds),FullScheds},
+ FullLoad = lists:sum(FullScheds) div Schedulers,
+ if FullLoad > 90 -> ok;
+ true -> exit({fullload, FullLoad})
+ end,
+
+ [exit(Pid, kill) || Pid <- [P1|HalfHogs++LastHogs]],
+ AfterLoad = get_load(),
+ {false,_} = {lists:any(fun(Load) -> Load > 5 end, AfterLoad),AfterLoad},
+ true = erlang:system_flag(scheduler_wall_time, false)
+ after
+ erlang:system_flag(scheduler_wall_time, false)
end.
-hog_iter(N) when N > 0 ->
- ?line hog_iter(N-1);
-hog_iter(0) ->
- ?line hog_iter(10000).
+get_load() ->
+ Start = erlang:statistics(scheduler_wall_time),
+ timer:sleep(500),
+ End = erlang:statistics(scheduler_wall_time),
+ lists:reverse(lists:sort(load_percentage(lists:sort(Start),lists:sort(End)))).
+
+load_percentage([{Id, WN, TN}|Ss], [{Id, WP, TP}|Ps]) ->
+ [100*(WN-WP) div (TN-TP)|load_percentage(Ss, Ps)];
+load_percentage([], []) -> [].
garbage_collection(doc) ->
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 9e369d5348..b78747bc84 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 4affc9bffe..4cbff3f36e 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -43,6 +43,9 @@
-export([memory/0, memory/1]).
-export([alloc_info/1, alloc_sizes/1]).
+-export([gather_sched_wall_time_result/1,
+ await_sched_wall_time_modifications/2]).
+
-deprecated([hash/2]).
% Get rid of autoimports of spawn to avoid clashes with ourselves.
@@ -1202,3 +1205,34 @@ receive_allocator(Ref, N, Acc) ->
{Ref, _, InfoList} ->
receive_allocator(Ref, N-1, insert_info(InfoList, Acc))
end.
+
+-spec await_sched_wall_time_modifications(Ref, Result) -> boolean() when
+ Ref :: reference(),
+ Result :: boolean().
+
+await_sched_wall_time_modifications(Ref, Result) ->
+ sched_wall_time(Ref, erlang:system_info(schedulers)),
+ Result.
+
+-spec gather_sched_wall_time_result(Ref) -> [{pos_integer(),
+ non_neg_integer(),
+ non_neg_integer()}] when
+ Ref :: reference().
+
+gather_sched_wall_time_result(Ref) when is_reference(Ref) ->
+ sched_wall_time(Ref, erlang:system_info(schedulers), []).
+
+sched_wall_time(_Ref, 0) ->
+ ok;
+sched_wall_time(Ref, N) ->
+ receive Ref -> sched_wall_time(Ref, N-1) end.
+
+sched_wall_time(_Ref, 0, Acc) ->
+ Acc;
+sched_wall_time(Ref, N, undefined) ->
+ receive {Ref, _} -> sched_wall_time(Ref, N-1, undefined) end;
+sched_wall_time(Ref, N, Acc) ->
+ receive
+ {Ref, undefined} -> sched_wall_time(Ref, N-1, undefined);
+ {Ref, SWT} -> sched_wall_time(Ref, N-1, [SWT|Acc])
+ end.
diff --git a/lib/Makefile b/lib/Makefile
index 402e73722a..aa4e074830 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -19,53 +19,21 @@
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-#
-# Macros
-#
-ifeq ($(findstring vxworks,$(TARGET)),vxworks)
- ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
- OTHER_SUB_DIRECTORIES = \
- snmp otp_mibs appmon erl_interface os_mon tools runtime_tools
- ifdef BUILD_ALL
- OTHER_SUB_DIRECTORIES += mnesia jinterface ic asn1 debugger \
- inets mnesia_session diameter orber pman tv observer \
- cosTransactions cosEvent cosTime cosNotification cosProperty
- cosFileTransfer cosEventDomain
- endif
-else
-#
-# unix and win32
-# --------------
-#
- ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
- OTHER_SUB_DIRECTORIES = tools test_server common_test runtime_tools
- ifdef BUILD_ALL
- ifeq ($(findstring win32,$(TARGET)),win32) # BUILD_ALL on win32
- OTHER_SUB_DIRECTORIES += \
- snmp otp_mibs appmon erl_interface asn1 jinterface gs wx inets ic \
- mnesia crypto orber os_mon parsetools syntax_tools pman \
- public_key ssl toolbar tv observer debugger reltool odbc \
- diameter \
- cosTransactions cosEvent cosTime cosNotification cosProperty \
- cosFileTransfer cosEventDomain et megaco webtool \
- xmerl edoc eunit ssh inviso typer erl_docgen \
- common_test percept dialyzer
-# dialyzer
- OTHER_SUB_DIRECTORIES += hipe
- else # BUILD_ALL on unix
- OTHER_SUB_DIRECTORIES += \
- snmp otp_mibs appmon erl_interface asn1 jinterface wx debugger reltool gs inets \
+ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
+OTHER_SUB_DIRECTORIES = tools test_server common_test runtime_tools
+ifdef BUILD_ALL
+ OTHER_SUB_DIRECTORIES += \
+ snmp otp_mibs appmon erl_interface asn1 jinterface \
+ wx debugger reltool gs inets \
ic mnesia crypto orber os_mon parsetools syntax_tools \
pman public_key ssl toolbar tv observer odbc \
diameter \
cosTransactions cosEvent cosTime cosNotification \
cosProperty cosFileTransfer cosEventDomain et megaco webtool \
xmerl edoc eunit ssh inviso typer erl_docgen \
- common_test percept dialyzer
-# dialyzer
- OTHER_SUB_DIRECTORIES += hipe $(TSP_APP)
- endif
- endif
+ percept dialyzer hipe
+ EXTRA_FILE := $(wildcard EXTRA-APPLICATIONS)
+ EXTRA_APPLICATIONS := $(if $(EXTRA_FILE),$(shell cat $(EXTRA_FILE)))
endif
ifdef BOOTSTRAP
@@ -78,7 +46,9 @@ else
ifdef TERTIARY_BOOTSTRAP
SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools wx
else # Not bootstrap build
- SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) $(OTHER_SUB_DIRECTORIES)
+ SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) \
+ $(OTHER_SUB_DIRECTORIES) \
+ $(EXTRA_APPLICATIONS)
endif
endif
endif
diff --git a/lib/appmon/doc/src/appmon.xml b/lib/appmon/doc/src/appmon.xml
index ae6147a387..5af50daa53 100644
--- a/lib/appmon/doc/src/appmon.xml
+++ b/lib/appmon/doc/src/appmon.xml
@@ -32,6 +32,12 @@
<module>appmon</module>
<modulesummary>A graphical node and application process tree viewer.</modulesummary>
<description>
+ <warning>
+ <p>
+ The Appmon application has been superseded by the Observer application.
+ Appmon will be removed in R16.
+ </p>
+ </warning>
<p>The application monitor Appmon is a graphical utility used to
supervise applications executing either locally or on remote nodes.
The process tree of an application can furthermore be monitored.</p>
diff --git a/lib/appmon/doc/src/appmon_chapter.xml b/lib/appmon/doc/src/appmon_chapter.xml
index 0dab23b549..3f642ad002 100644
--- a/lib/appmon/doc/src/appmon_chapter.xml
+++ b/lib/appmon/doc/src/appmon_chapter.xml
@@ -31,6 +31,12 @@
<section>
<title>Introduction</title>
+ <warning>
+ <p>
+ The Appmon application has been superseded by the Observer application.
+ Appmon will be removed in R16.
+ </p>
+ </warning>
<p>The application monitor Appmon is a graphical node and application viewer. The tool shows an overview of all applications on all known nodes, and it is possible to view the process tree for an application running on any of the nodes.</p>
<note>
<p>If the Appmon code is not available at a node, for example an
diff --git a/lib/appmon/src/appmon.erl b/lib/appmon/src/appmon.erl
index 2b982cddf0..7a6d86c9ab 100644
--- a/lib/appmon/src/appmon.erl
+++ b/lib/appmon/src/appmon.erl
@@ -17,6 +17,11 @@
%% %CopyrightEnd%
-module(appmon).
-behaviour(gen_server).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%%%---------------------------------------------------------------------
%%% Appmon main module.
diff --git a/lib/appmon/src/appmon_a.erl b/lib/appmon/src/appmon_a.erl
index b0b5847343..2c8185a85d 100644
--- a/lib/appmon/src/appmon_a.erl
+++ b/lib/appmon/src/appmon_a.erl
@@ -17,6 +17,11 @@
%% %CopyrightEnd%
%%
-module(appmon_a).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%%----------------------------------------------------------------------
%%
diff --git a/lib/appmon/src/appmon_lb.erl b/lib/appmon/src/appmon_lb.erl
index 4e433f37c5..55fda83027 100644
--- a/lib/appmon/src/appmon_lb.erl
+++ b/lib/appmon/src/appmon_lb.erl
@@ -29,6 +29,13 @@
%%% then pressing the load button, its application window is started.
-module(appmon_lb).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export ([
start/1,
diff --git a/lib/appmon/src/appmon_txt.erl b/lib/appmon/src/appmon_txt.erl
index 4e1785c53f..8647bc9890 100644
--- a/lib/appmon/src/appmon_txt.erl
+++ b/lib/appmon/src/appmon_txt.erl
@@ -22,6 +22,11 @@
%%------------------------------------------------------------
-module(appmon_txt).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
-export([start/0, start/1, print/1, fprint/1]).
%% gen_server stuff
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 522c1dc411..0f8abf1ccf 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -333,7 +333,7 @@ module.beam: module.erl \
<tag><c>{d,Macro,Value}</c></tag>
<item>
<p>Defines a macro <c>Macro</c> to have the value
- <c>Value</c>. The default is <c>true</c>).</p>
+ <c>Value</c>. The default is <c>true</c>.</p>
</item>
<tag><c>{parse_transform,Module}</c></tag>
diff --git a/lib/debugger/src/dbg_ui_break_win.erl b/lib/debugger/src/dbg_ui_break_win.erl
index abbec158b0..2894e8223b 100644
--- a/lib/debugger/src/dbg_ui_break_win.erl
+++ b/lib/debugger/src/dbg_ui_break_win.erl
@@ -17,6 +17,18 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_break_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/5,
diff --git a/lib/debugger/src/dbg_ui_edit_win.erl b/lib/debugger/src/dbg_ui_edit_win.erl
index 9b0441b44c..fb40ab3812 100644
--- a/lib/debugger/src/dbg_ui_edit_win.erl
+++ b/lib/debugger/src/dbg_ui_edit_win.erl
@@ -17,6 +17,12 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_edit_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/5, get_window/1,
diff --git a/lib/debugger/src/dbg_ui_filedialog_win.erl b/lib/debugger/src/dbg_ui_filedialog_win.erl
index 1eced1104d..50d198f361 100644
--- a/lib/debugger/src/dbg_ui_filedialog_win.erl
+++ b/lib/debugger/src/dbg_ui_filedialog_win.erl
@@ -18,6 +18,13 @@
%%
-module(dbg_ui_filedialog_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/6, create_win/7, get_window/1,
diff --git a/lib/debugger/src/dbg_ui_mon_win.erl b/lib/debugger/src/dbg_ui_mon_win.erl
index 52e8f433ba..f446fb7fcd 100644
--- a/lib/debugger/src/dbg_ui_mon_win.erl
+++ b/lib/debugger/src/dbg_ui_mon_win.erl
@@ -17,6 +17,19 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_mon_win).
+-compile([{nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([init/0]).
diff --git a/lib/debugger/src/dbg_ui_trace_win.erl b/lib/debugger/src/dbg_ui_trace_win.erl
index 82d4199630..f237f30e4a 100644
--- a/lib/debugger/src/dbg_ui_trace_win.erl
+++ b/lib/debugger/src/dbg_ui_trace_win.erl
@@ -17,6 +17,25 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_trace_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
%% External exports
-export([init/0]).
diff --git a/lib/debugger/src/dbg_ui_win.erl b/lib/debugger/src/dbg_ui_win.erl
index 9bed6a1ec5..cef091ee28 100644
--- a/lib/debugger/src/dbg_ui_win.erl
+++ b/lib/debugger/src/dbg_ui_win.erl
@@ -17,6 +17,15 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_win).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% External exports
-export([init/0,
diff --git a/lib/debugger/src/dbg_ui_winman.erl b/lib/debugger/src/dbg_ui_winman.erl
index c7aac0df23..8619be344b 100644
--- a/lib/debugger/src/dbg_ui_winman.erl
+++ b/lib/debugger/src/dbg_ui_winman.erl
@@ -18,6 +18,11 @@
%%
-module(dbg_ui_winman).
-behaviour(gen_server).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,3}}]).
%% External exports
-export([start/0]).
diff --git a/lib/debugger/src/dbg_wx_trace_win.erl b/lib/debugger/src/dbg_wx_trace_win.erl
index 79cf87ae62..aab8fddda7 100644
--- a/lib/debugger/src/dbg_wx_trace_win.erl
+++ b/lib/debugger/src/dbg_wx_trace_win.erl
@@ -19,6 +19,7 @@
%%
-module(dbg_wx_trace_win).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
%% External exports
-export([init/0, stop/1]).
diff --git a/lib/dialyzer/src/dialyzer_gui.erl b/lib/dialyzer/src/dialyzer_gui.erl
index ccd80a4835..f60194e01f 100644
--- a/lib/dialyzer/src/dialyzer_gui.erl
+++ b/lib/dialyzer/src/dialyzer_gui.erl
@@ -28,6 +28,23 @@
%%%-----------------------------------------------------------------------
-module(dialyzer_gui).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,stop,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/1]).
diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css
index 97d8c2df74..c56de378f4 100644
--- a/lib/erl_docgen/priv/css/otp_doc.css
+++ b/lib/erl_docgen/priv/css/otp_doc.css
@@ -1,6 +1,5 @@
-
-
-body {
+/* standard OTP style sheet */
+body {
background: white;
font-family: Verdana, Arial, Helvetica, sans-serif;
margin: 0;
@@ -11,7 +10,6 @@ body {
max-height: 100%;
}
-
th { font-family: Verdana, Arial, Helvetica, sans-serif }
td { font-family: Verdana, Arial, Helvetica, sans-serif }
p { font-family: Verdana, Arial, Helvetica, sans-serif }
@@ -33,8 +31,7 @@ a:visited { color: blue; text-decoration: none }
background-color: #fff;
}
-
-#leftnav {
+#leftnav {
position: fixed;
float: left;
top: 0;
@@ -47,8 +44,7 @@ a:visited { color: blue; text-decoration: none }
border-right: 1px solid red;
}
-
-#content {
+#content {
margin-left: 240px; /* set left value to WidthOfFrameDiv */
}
@@ -57,7 +53,6 @@ a:visited { color: blue; text-decoration: none }
padding-top: 50px; /* Magins for inner DIV inside each DIV (to provide padding) */
}
-
.innertube
{
margin: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */
@@ -66,16 +61,15 @@ a:visited { color: blue; text-decoration: none }
.footer
{
margin: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */
-
}
-span.bold_code { font-family: courier;font-weight: bold}
-span.code { font-family: courier;font-weight: normal}
+
+span.bold_code { font-family: Courier, monospace; font-weight: bold }
+span.code { font-family: Courier, monospace; font-weight: normal }
.note, .warning {
border: solid black 1px;
margin: 1em 3em;
}
-
.note .label {
background: #30d42a;
color: white;
@@ -102,16 +96,15 @@ span.code { font-family: courier;font-weight: normal}
font-size: 90%;
padding: 5px 10px;
}
-
-.example {
+.example {
background-color:#eeeeff;
padding: 0px 10px;
-}
+}
-pre { font-family: courier; font-weight: normal }
+pre { font-family: Courier, monospace; font-weight: normal }
.REFBODY { margin-left: 13mm }
.REFTYPES { margin-left: 8mm }
-footer { }
+footer { }
diff --git a/lib/et/src/et_gs_contents_viewer.erl b/lib/et/src/et_gs_contents_viewer.erl
index f6a87bd608..5331c7697a 100644
--- a/lib/et/src/et_gs_contents_viewer.erl
+++ b/lib/et/src/et_gs_contents_viewer.erl
@@ -21,6 +21,17 @@
%%----------------------------------------------------------------------
-module(et_gs_contents_viewer).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-behaviour(gen_server).
diff --git a/lib/et/src/et_gs_viewer.erl b/lib/et/src/et_gs_viewer.erl
index 0af7814d15..4e6f0e3f64 100644
--- a/lib/et/src/et_gs_viewer.erl
+++ b/lib/et/src/et_gs_viewer.erl
@@ -21,6 +21,23 @@
%%----------------------------------------------------------------------
-module(et_gs_viewer).
+-compile([{nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-behaviour(gen_server).
diff --git a/lib/gs/contribs/bonk/bonk.erl b/lib/gs/contribs/bonk/bonk.erl
index 79f01bf659..7e68a4ddc5 100644
--- a/lib/gs/contribs/bonk/bonk.erl
+++ b/lib/gs/contribs/bonk/bonk.erl
@@ -19,6 +19,12 @@
%%
-module(bonk).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-export([run/0, run/1,bonk_dir/0,start/0]).
-record(colors, {miss, x, bomb, face}).
diff --git a/lib/gs/contribs/cols/cols.erl b/lib/gs/contribs/cols/cols.erl
index 111c9a58f1..9c44837f3e 100644
--- a/lib/gs/contribs/cols/cols.erl
+++ b/lib/gs/contribs/cols/cols.erl
@@ -19,6 +19,12 @@
%%
-module(cols).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0, init/0]).
diff --git a/lib/gs/contribs/cols/highscore.erl b/lib/gs/contribs/cols/highscore.erl
index 9ffbea50a7..8f984aaa83 100644
--- a/lib/gs/contribs/cols/highscore.erl
+++ b/lib/gs/contribs/cols/highscore.erl
@@ -19,6 +19,13 @@
%%
-module(highscore).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([run/2]).
diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl
index 0f1df5c665..6293f867e2 100644
--- a/lib/gs/contribs/mandel/mandel.erl
+++ b/lib/gs/contribs/mandel/mandel.erl
@@ -18,6 +18,11 @@
%%
-module(mandel).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,image,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-author('(mbj,eklas)@erlang.ericsson.se').
%% User's interface
diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl
index 212ba9bfe1..c52211a495 100644
--- a/lib/gs/contribs/othello/othello_board.erl
+++ b/lib/gs/contribs/othello/othello_board.erl
@@ -19,6 +19,12 @@
%%
-module(othello_board).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-export([start/0,stop/0,init/0]).
diff --git a/lib/gs/doc/src/gs.xml b/lib/gs/doc/src/gs.xml
index f2182fc673..c61e8c4938 100644
--- a/lib/gs/doc/src/gs.xml
+++ b/lib/gs/doc/src/gs.xml
@@ -39,9 +39,7 @@
graphical user interface.
</p>
<p>
- GS is not maintained and we plan to deprecate and remove it from
- the distribution as soon as possible, maybe already in the next
- major release (R15).
+ GS is deprecated and will be removed in the R16 release.
</p>
</warning>
<p>The Graphics System, GS, is easy to learn and
diff --git a/lib/gs/examples/ball.erl b/lib/gs/examples/ball.erl
index 3f91a7b379..03fac3b5fc 100644
--- a/lib/gs/examples/ball.erl
+++ b/lib/gs/examples/ball.erl
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(ball).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,oval,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/browser.erl b/lib/gs/examples/browser.erl
index 1dba5a915b..0f8b3fc7e6 100644
--- a/lib/gs/examples/browser.erl
+++ b/lib/gs/examples/browser.erl
@@ -23,6 +23,14 @@
%% ------------------------------------------------------------
-module(browser).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,start/2,init/3]).
diff --git a/lib/gs/examples/calc.erl b/lib/gs/examples/calc.erl
index 992b8adb4e..ca29ae1cb9 100644
--- a/lib/gs/examples/calc.erl
+++ b/lib/gs/examples/calc.erl
@@ -23,6 +23,11 @@
%% ------------------------------------------------------------
-module(calc).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,calc/0]).
diff --git a/lib/gs/examples/calc2.erl b/lib/gs/examples/calc2.erl
index 0e841397f6..83e1870b7a 100644
--- a/lib/gs/examples/calc2.erl
+++ b/lib/gs/examples/calc2.erl
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(calc2).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
+
-export([start/0,calc/0]).
start() ->
diff --git a/lib/gs/examples/color_demo.erl b/lib/gs/examples/color_demo.erl
index 650f853061..a2f4d0eb87 100644
--- a/lib/gs/examples/color_demo.erl
+++ b/lib/gs/examples/color_demo.erl
@@ -24,6 +24,11 @@
%% ------------------------------------------------------------
-module(color_demo).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/color_demo2.erl b/lib/gs/examples/color_demo2.erl
index 817cc9ed7d..3b0b36221d 100644
--- a/lib/gs/examples/color_demo2.erl
+++ b/lib/gs/examples/color_demo2.erl
@@ -24,6 +24,10 @@
%% ------------------------------------------------------------
-module(color_demo2).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/distrib_draw.erl b/lib/gs/examples/distrib_draw.erl
index ecb1386c25..8f76bc6650 100644
--- a/lib/gs/examples/distrib_draw.erl
+++ b/lib/gs/examples/distrib_draw.erl
@@ -43,6 +43,11 @@
%%
-module(distrib_draw).
+-compile([{nowarn_deprecated_function,{gs,canvas,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/2,init/0]).
diff --git a/lib/gs/examples/entry_demo.erl b/lib/gs/examples/entry_demo.erl
index a5ecfbc4d3..4bb64e949e 100644
--- a/lib/gs/examples/entry_demo.erl
+++ b/lib/gs/examples/entry_demo.erl
@@ -23,6 +23,12 @@
%% ------------------------------------------------------------
-module(entry_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/1]).
diff --git a/lib/gs/examples/event_test.erl b/lib/gs/examples/event_test.erl
index f6fcc9b4b9..8c0a109df4 100644
--- a/lib/gs/examples/event_test.erl
+++ b/lib/gs/examples/event_test.erl
@@ -21,6 +21,9 @@
%% Demo for testing some events
-module(event_test).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/file_dialog.erl b/lib/gs/examples/file_dialog.erl
index ff20321374..c1ef6ed8b1 100644
--- a/lib/gs/examples/file_dialog.erl
+++ b/lib/gs/examples/file_dialog.erl
@@ -23,6 +23,11 @@
%% ------------------------------------------------------------
-module(file_dialog).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0,start/1,start/2,fs_init/3]).
diff --git a/lib/gs/examples/focus_demo.erl b/lib/gs/examples/focus_demo.erl
index b9d86866e6..71ca9c6ff5 100644
--- a/lib/gs/examples/focus_demo.erl
+++ b/lib/gs/examples/focus_demo.erl
@@ -23,6 +23,11 @@
%% ------------------------------------------------------------
-module(focus_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/frac.erl b/lib/gs/examples/frac.erl
index 139a4be310..46af83de8a 100644
--- a/lib/gs/examples/frac.erl
+++ b/lib/gs/examples/frac.erl
@@ -21,6 +21,9 @@
%% Purpose : Fractal trees
-module(frac).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0, go/0, test/0, grow/2, expand/3, subst/2]).
diff --git a/lib/gs/examples/line_demo.erl b/lib/gs/examples/line_demo.erl
index c8a6a69e2e..ba88605118 100644
--- a/lib/gs/examples/line_demo.erl
+++ b/lib/gs/examples/line_demo.erl
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(line_demo).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0,line/3]).
diff --git a/lib/gs/examples/man.erl b/lib/gs/examples/man.erl
index a0ffd3364e..bddd6930ab 100644
--- a/lib/gs/examples/man.erl
+++ b/lib/gs/examples/man.erl
@@ -23,6 +23,15 @@
%% ------------------------------------------------------------
-module(man).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/0,init/0]).
-export([man_list/0]).
diff --git a/lib/gs/examples/menu_demo.erl b/lib/gs/examples/menu_demo.erl
index c95fc33152..6b2fc4113a 100644
--- a/lib/gs/examples/menu_demo.erl
+++ b/lib/gs/examples/menu_demo.erl
@@ -19,6 +19,12 @@
%%
-module(menu_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-compile(export_all).
diff --git a/lib/gs/examples/rubber.erl b/lib/gs/examples/rubber.erl
index ba263f07ac..da4aa57391 100644
--- a/lib/gs/examples/rubber.erl
+++ b/lib/gs/examples/rubber.erl
@@ -23,6 +23,14 @@
%% ------------------------------------------------------------
-module(rubber).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0, init/0]).
diff --git a/lib/gs/src/gs.erl b/lib/gs/src/gs.erl
index 3e9a1c4b8b..92dce12580 100644
--- a/lib/gs/src/gs.erl
+++ b/lib/gs/src/gs.erl
@@ -24,7 +24,13 @@
%%
-module(gs).
-
+-deprecated(module).
+-compile([{nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,create_tree,2}},
+ {nowarn_deprecated_function,{gs,foreach,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% ----- Exports -----
-export([start/0, stop/0, start/1]).
diff --git a/lib/gs/src/gs_frontend.erl b/lib/gs/src/gs_frontend.erl
index 009b264e69..73954baa8d 100644
--- a/lib/gs/src/gs_frontend.erl
+++ b/lib/gs/src/gs_frontend.erl
@@ -24,6 +24,8 @@
%%
-module(gs_frontend).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,error,2}}]).
-export([create/2,
config/2,
diff --git a/lib/gs/src/gs_make.erl b/lib/gs/src/gs_make.erl
index e41183f9bf..bf8a66001f 100644
--- a/lib/gs/src/gs_make.erl
+++ b/lib/gs/src/gs_make.erl
@@ -19,6 +19,7 @@
%%
-module(gs_make).
+-compile([{nowarn_deprecated_function,{gs,assq,2}}]).
-export([start/0]).
diff --git a/lib/gs/src/gse.erl b/lib/gs/src/gse.erl
index b3ea2af4d4..c62badcc27 100644
--- a/lib/gs/src/gse.erl
+++ b/lib/gs/src/gse.erl
@@ -23,6 +23,68 @@
%%%----------------------------------------------------------------------
-module(gse).
+-compile([{nowarn_deprecated_function,{gs,arc,2}},
+ {nowarn_deprecated_function,{gs,arc,3}},
+ {nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,canvas,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,create_tree,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,gridline,3}},
+ {nowarn_deprecated_function,{gs,image,2}},
+ {nowarn_deprecated_function,{gs,image,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,line,3}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,message,2}},
+ {nowarn_deprecated_function,{gs,message,3}},
+ {nowarn_deprecated_function,{gs,oval,2}},
+ {nowarn_deprecated_function,{gs,oval,3}},
+ {nowarn_deprecated_function,{gs,polygon,2}},
+ {nowarn_deprecated_function,{gs,polygon,3}},
+ {nowarn_deprecated_function,{gs,prompter,2}},
+ {nowarn_deprecated_function,{gs,prompter,3}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,rectangle,2}},
+ {nowarn_deprecated_function,{gs,rectangle,3}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,scale,3}},
+ {nowarn_deprecated_function,{gs,scrollbar,2}},
+ {nowarn_deprecated_function,{gs,scrollbar,3}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,start,1}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,text,3}},
+ {nowarn_deprecated_function,{gs,window,2}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
%%-compile(export_all).
-export([
diff --git a/lib/gs/src/gstk.erl b/lib/gs/src/gstk.erl
index 6f83cf8be4..ee974a5f63 100644
--- a/lib/gs/src/gstk.erl
+++ b/lib/gs/src/gstk.erl
@@ -20,6 +20,8 @@
%%
-module(gstk).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,creation_error,2}}]).
-export([start_link/4,
stop/1,
diff --git a/lib/gs/src/gstk_arc.erl b/lib/gs/src/gstk_arc.erl
index 8e80ef92b5..3c6fe54d36 100644
--- a/lib/gs/src/gstk_arc.erl
+++ b/lib/gs/src/gstk_arc.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_arc).
+-compile([{nowarn_deprecated_function,{gs,creation_error,2}}]).
%%-----------------------------------------------------------------------------
%% ARC OPTIONS
diff --git a/lib/gs/src/gstk_canvas.erl b/lib/gs/src/gstk_canvas.erl
index 868b3020fe..5d15529995 100644
--- a/lib/gs/src/gstk_canvas.erl
+++ b/lib/gs/src/gstk_canvas.erl
@@ -23,6 +23,8 @@
%% ------------------------------------------------------------
-module(gstk_canvas).
+-compile([{nowarn_deprecated_function,{gs,pair,2}},
+ {nowarn_deprecated_function,{gs,val,2}}]).
%%-----------------------------------------------------------------------------
%% CANVAS OPTIONS
diff --git a/lib/gs/src/gstk_editor.erl b/lib/gs/src/gstk_editor.erl
index 6b90cee1d2..2686997036 100644
--- a/lib/gs/src/gstk_editor.erl
+++ b/lib/gs/src/gstk_editor.erl
@@ -23,6 +23,9 @@
%% ------------------------------------------------------------
-module(gstk_editor).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,error,2}},
+ {nowarn_deprecated_function,{gs,val,2}}]).
%%------------------------------------------------------------------------------
%% CANVAS OPTIONS
diff --git a/lib/gs/src/gstk_entry.erl b/lib/gs/src/gstk_entry.erl
index 14f7831151..432ccd5fde 100644
--- a/lib/gs/src/gstk_entry.erl
+++ b/lib/gs/src/gstk_entry.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_entry).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%------------------------------------------------------------------------------
%% ENTRY OPTIONS
diff --git a/lib/gs/src/gstk_generic.erl b/lib/gs/src/gstk_generic.erl
index 8fe19b428c..50c3da8dc5 100644
--- a/lib/gs/src/gstk_generic.erl
+++ b/lib/gs/src/gstk_generic.erl
@@ -20,6 +20,7 @@
%%
-module(gstk_generic).
+-compile([{nowarn_deprecated_function,{gs,assq,2}}]).
-export([out_opts/8,
read_option/5,
diff --git a/lib/gs/src/gstk_grid.erl b/lib/gs/src/gstk_grid.erl
index 4189246822..f703dad074 100644
--- a/lib/gs/src/gstk_grid.erl
+++ b/lib/gs/src/gstk_grid.erl
@@ -19,6 +19,7 @@
%%
-module(gstk_grid).
+-compile([{nowarn_deprecated_function,{gs,val,2}}]).
-export([event/5,create/3,config/3,option/5,read/3,delete/2,destroy/2,
mk_create_opts_for_child/4,read_option/5]).
diff --git a/lib/gs/src/gstk_gridline.erl b/lib/gs/src/gstk_gridline.erl
index c1dd5a1443..4585c7e043 100644
--- a/lib/gs/src/gstk_gridline.erl
+++ b/lib/gs/src/gstk_gridline.erl
@@ -19,6 +19,8 @@
%%
-module(gstk_gridline).
+-compile([{nowarn_deprecated_function,{gs,val,2}},
+ {nowarn_deprecated_function,{gs,val,3}}]).
-export([event/5,create/3,config/3,option/5,read/3,delete/2,destroy/3,
read_option/5]).
diff --git a/lib/gs/src/gstk_image.erl b/lib/gs/src/gstk_image.erl
index 53789b312d..2b7a324e28 100644
--- a/lib/gs/src/gstk_image.erl
+++ b/lib/gs/src/gstk_image.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_image).
+-compile([{nowarn_deprecated_function,{gs,pair,2}}]).
%%-----------------------------------------------------------------------------
%% BITMAP OPTIONS
diff --git a/lib/gs/src/gstk_menu.erl b/lib/gs/src/gstk_menu.erl
index 3957951a35..e878669de6 100644
--- a/lib/gs/src/gstk_menu.erl
+++ b/lib/gs/src/gstk_menu.erl
@@ -23,6 +23,7 @@
%%------------------------------------------------------------------------------
-module(gstk_menu).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%------------------------------------------------------------------------------
%% MENU OPTIONS
diff --git a/lib/gs/src/gstk_menuitem.erl b/lib/gs/src/gstk_menuitem.erl
index 36a9253598..8abf5d13aa 100644
--- a/lib/gs/src/gstk_menuitem.erl
+++ b/lib/gs/src/gstk_menuitem.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_menuitem).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%-----------------------------------------------------------------------------
%% MENUITEM OPTIONS
diff --git a/lib/gs/src/gstk_port_handler.erl b/lib/gs/src/gstk_port_handler.erl
index 93f3e58dc2..c6ca2c0f5b 100644
--- a/lib/gs/src/gstk_port_handler.erl
+++ b/lib/gs/src/gstk_port_handler.erl
@@ -34,6 +34,7 @@
%% ------------------------------------------------------------
-module(gstk_port_handler).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
-include("gstk.hrl").
diff --git a/lib/gs/src/gstk_rectangle.erl b/lib/gs/src/gstk_rectangle.erl
index 1e02977c9a..14be16c990 100644
--- a/lib/gs/src/gstk_rectangle.erl
+++ b/lib/gs/src/gstk_rectangle.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_rectangle).
+-compile([{nowarn_deprecated_function,{gs,pair,2}}]).
%%-----------------------------------------------------------------------------
%% RECTANGLE OPTIONS
diff --git a/lib/gs/src/gstk_window.erl b/lib/gs/src/gstk_window.erl
index acac452ed1..4b4706eb88 100644
--- a/lib/gs/src/gstk_window.erl
+++ b/lib/gs/src/gstk_window.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_window).
+-compile([{nowarn_deprecated_function,{gs,destroy,1}}]).
%%------------------------------------------------------------------------------
%% WINDOW OPTIONS
diff --git a/lib/gs/src/tcl2erl.erl b/lib/gs/src/tcl2erl.erl
index 8845cf0b9a..d159681c5c 100644
--- a/lib/gs/src/tcl2erl.erl
+++ b/lib/gs/src/tcl2erl.erl
@@ -25,6 +25,7 @@
%% ------------------------------------------------------------
-module(tcl2erl).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
-export([parse_event/1,
ret_int/1,
diff --git a/lib/gs/src/tool_file_dialog.erl b/lib/gs/src/tool_file_dialog.erl
index 6b2c2e8c81..cfcfcd1bf6 100644
--- a/lib/gs/src/tool_file_dialog.erl
+++ b/lib/gs/src/tool_file_dialog.erl
@@ -19,6 +19,16 @@
%%
-module(tool_file_dialog).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
+
-export([start/1]).
-record(opts, {type, % open | save | multiselect
diff --git a/lib/gs/src/tool_utils.erl b/lib/gs/src/tool_utils.erl
index f1b93c1af8..69919b18bd 100644
--- a/lib/gs/src/tool_utils.erl
+++ b/lib/gs/src/tool_utils.erl
@@ -19,6 +19,11 @@
%%
-module(tool_utils).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
+
-include_lib("kernel/include/file.hrl").
%%%---------------------------------------------------------------------
diff --git a/lib/hipe/cerl/cerl_hipe_primops.hrl b/lib/hipe/cerl/cerl_hipe_primops.hrl
index 36b1b62901..1d82f7bfc7 100644
--- a/lib/hipe/cerl/cerl_hipe_primops.hrl
+++ b/lib/hipe/cerl/cerl_hipe_primops.hrl
@@ -59,7 +59,6 @@
-define(PRIMOP_IS_ATOM, 'is_atom'). % arity 1
-define(PRIMOP_IS_BIGNUM, 'is_bignum'). % arity 1
-define(PRIMOP_IS_BINARY, 'is_binary'). % arity 1
--define(PRIMOP_IS_CONSTANT, 'is_constant'). % arity 1
-define(PRIMOP_IS_FIXNUM, 'is_fixnum'). % arity 1
-define(PRIMOP_IS_FLOAT, 'is_float'). % arity 1
-define(PRIMOP_IS_FUNCTION, 'is_function'). % arity 1
diff --git a/lib/hipe/cerl/cerl_hipeify.erl b/lib/hipe/cerl/cerl_hipeify.erl
index 8f6c3561c9..89b4ec147d 100644
--- a/lib/hipe/cerl/cerl_hipeify.erl
+++ b/lib/hipe/cerl/cerl_hipeify.erl
@@ -392,7 +392,6 @@ call_to_primop(erlang, '=<', 2) -> {yes, ?PRIMOP_LE};
call_to_primop(erlang, '>=', 2) -> {yes, ?PRIMOP_GE};
call_to_primop(erlang, is_atom, 1) -> {yes, ?PRIMOP_IS_ATOM};
call_to_primop(erlang, is_binary, 1) -> {yes, ?PRIMOP_IS_BINARY};
-call_to_primop(erlang, is_constant, 1) -> {yes, ?PRIMOP_IS_CONSTANT};
call_to_primop(erlang, is_float, 1) -> {yes, ?PRIMOP_IS_FLOAT};
call_to_primop(erlang, is_function, 1) -> {yes, ?PRIMOP_IS_FUNCTION};
call_to_primop(erlang, is_integer, 1) -> {yes, ?PRIMOP_IS_INTEGER};
diff --git a/lib/hipe/cerl/cerl_messagean.erl b/lib/hipe/cerl/cerl_messagean.erl
index 6dd93adaa3..b9f82f2a43 100644
--- a/lib/hipe/cerl/cerl_messagean.erl
+++ b/lib/hipe/cerl/cerl_messagean.erl
@@ -1083,7 +1083,6 @@ is_imm_op(erlang, is_alive, 0) -> true;
is_imm_op(erlang, is_atom, 1) -> true;
is_imm_op(erlang, is_binary, 1) -> true;
is_imm_op(erlang, is_builtin, 3) -> true;
-is_imm_op(erlang, is_constant, 1) -> true;
is_imm_op(erlang, is_float, 1) -> true;
is_imm_op(erlang, is_function, 1) -> true;
is_imm_op(erlang, is_integer, 1) -> true;
diff --git a/lib/hipe/cerl/cerl_to_icode.erl b/lib/hipe/cerl/cerl_to_icode.erl
index 362c427cbe..089e3f021e 100644
--- a/lib/hipe/cerl/cerl_to_icode.erl
+++ b/lib/hipe/cerl/cerl_to_icode.erl
@@ -88,7 +88,6 @@
-define(TYPE_IS_ATOM, atom).
-define(TYPE_IS_BIGNUM, bignum).
-define(TYPE_IS_BINARY, binary).
--define(TYPE_IS_CONSTANT, constant).
-define(TYPE_IS_FIXNUM, fixnum).
-define(TYPE_IS_FLOAT, float).
-define(TYPE_IS_FUNCTION, function).
@@ -2051,7 +2050,6 @@ is_record_test(T, A, N, True, False, Ctxt, Env, S) ->
type_test(?PRIMOP_IS_ATOM) -> ?TYPE_IS_ATOM;
type_test(?PRIMOP_IS_BIGNUM) -> ?TYPE_IS_BIGNUM;
type_test(?PRIMOP_IS_BINARY) -> ?TYPE_IS_BINARY;
-type_test(?PRIMOP_IS_CONSTANT) -> ?TYPE_IS_CONSTANT;
type_test(?PRIMOP_IS_FIXNUM) -> ?TYPE_IS_FIXNUM;
type_test(?PRIMOP_IS_FLOAT) -> ?TYPE_IS_FLOAT;
type_test(?PRIMOP_IS_FUNCTION) -> ?TYPE_IS_FUNCTION;
@@ -2082,7 +2080,6 @@ is_bool_op(Op, A) when is_atom(Op), is_integer(A) -> false.
is_type_test(?PRIMOP_IS_ATOM, 1) -> true;
is_type_test(?PRIMOP_IS_BIGNUM, 1) -> true;
is_type_test(?PRIMOP_IS_BINARY, 1) -> true;
-is_type_test(?PRIMOP_IS_CONSTANT, 1) -> true;
is_type_test(?PRIMOP_IS_FIXNUM, 1) -> true;
is_type_test(?PRIMOP_IS_FLOAT, 1) -> true;
is_type_test(?PRIMOP_IS_FUNCTION, 1) -> true;
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index cee399e861..845df0ca61 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -54,7 +54,6 @@
t_cons/2,
t_cons_hd/1,
t_cons_tl/1,
- t_constant/0,
t_fixnum/0,
t_non_neg_fixnum/0,
t_pos_fixnum/0,
@@ -81,7 +80,6 @@
t_is_bitstr/1,
t_is_boolean/1,
t_is_cons/1,
- t_is_constant/1,
t_is_float/1,
t_is_float/1,
t_is_fun/1,
@@ -845,11 +843,6 @@ type(erlang, is_boolean, 1, Xs) ->
strict(arg_types(erlang, is_boolean, 1), Xs, Fun);
type(erlang, is_builtin, 3, Xs) ->
strict(arg_types(erlang, is_builtin, 3), Xs, fun (_) -> t_boolean() end);
-type(erlang, is_constant, 1, Xs) ->
- Fun = fun (X) ->
- check_guard(X, fun (Y) -> t_is_constant(Y) end, t_constant())
- end,
- strict(arg_types(erlang, is_constant, 1), Xs, Fun);
type(erlang, is_float, 1, Xs) ->
Fun = fun (X) ->
check_guard(X, fun (Y) -> t_is_float(Y) end, t_float())
@@ -1202,11 +1195,13 @@ type(erlang, process_flag, 2, Xs) ->
case t_atom_vals(Flag) of
['error_handler'] -> t_atom();
['min_heap_size'] -> t_non_neg_integer();
+ ['min_bin_vheap_size'] -> t_non_neg_integer();
['scheduler'] -> t_non_neg_integer();
['monitor_nodes'] -> t_boolean();
['priority'] -> t_process_priority_level();
['save_calls'] -> t_non_neg_integer();
['trap_exit'] -> t_boolean();
+ ['sensitive'] -> t_boolean();
List when is_list(List) ->
T_process_flag_returns;
unknown ->
@@ -1503,6 +1498,8 @@ type(erlang, system_flag, 2, Xs) ->
t_non_neg_fixnum();
['min_heap_size'] ->
t_non_neg_fixnum();
+ ['min_bin_vheap_size'] ->
+ t_non_neg_fixnum();
['multi_scheduling'] ->
t_system_multi_scheduling();
['schedulers_online'] ->
@@ -1546,8 +1543,12 @@ type(erlang, system_info, 1, Xs) ->
t_list(t_tuple([t_atom(),
t_list(t_tuple([t_atom(),
t_any()]))]))]);
+ ['build_type'] ->
+ t_system_build_type_return();
['break_ignored'] ->
t_boolean();
+ ['c_compiler_used'] ->
+ t_tuple([t_atom(), t_any()]);
['cpu_topology'] ->
t_system_cpu_topology();
['compat_rel'] ->
@@ -1560,6 +1561,8 @@ type(erlang, system_info, 1, Xs) ->
t_binary();
['dist_ctrl'] ->
t_list(t_tuple([t_atom(), t_sup([t_pid(), t_port])]));
+ ['driver_version'] ->
+ t_string();
%% elib_malloc is intentionally not included,
%% because it scheduled for removal in R15.
['endian'] ->
@@ -1573,7 +1576,9 @@ type(erlang, system_info, 1, Xs) ->
['heap_sizes'] ->
t_list(t_integer());
['heap_type'] ->
- t_sup([t_atom('private'), t_atom('hybrid')]);
+ t_sup([t_atom('private'),
+ t_atom('shared'),
+ t_atom('hybrid')]);
['hipe_architecture'] ->
t_atoms(['amd64', 'arm', 'powerpc', 'ppc64',
'undefined', 'ultrasparc', 'x86']);
@@ -1581,12 +1586,20 @@ type(erlang, system_info, 1, Xs) ->
t_binary();
['internal_cpu_topology'] -> %% Undocumented internal feature
t_internal_cpu_topology();
+ ['kernel_poll'] ->
+ t_boolean();
['loaded'] ->
t_binary();
['logical_processors'] ->
t_non_neg_fixnum();
['machine'] ->
t_string();
+ ['min_heap_size'] ->
+ t_tuple([t_atom('min_heap_size'),
+ t_non_neg_integer()]);
+ ['min_bin_vheap_size'] ->
+ t_tuple([t_atom('min_bin_vheap_size'),
+ t_non_neg_integer()]);
['multi_scheduling'] ->
t_system_multi_scheduling();
['multi_scheduling_blockers'] ->
@@ -1601,6 +1614,8 @@ type(erlang, system_info, 1, Xs) ->
t_non_neg_fixnum(),
t_non_neg_fixnum()]),
t_string());
+ ['otp_release'] ->
+ t_string();
['process_count'] ->
t_non_neg_fixnum();
['process_limit'] ->
@@ -1630,6 +1645,8 @@ type(erlang, system_info, 1, Xs) ->
t_non_neg_fixnum();
['trace_control_word'] ->
t_integer();
+ ['update_cpu_info'] ->
+ t_sup([t_atom('changed'), t_atom('unchanged')]);
['version'] ->
t_string();
['wordsize'] ->
@@ -3567,8 +3584,6 @@ arg_types(erlang, is_boolean, 1) ->
[t_any()];
arg_types(erlang, is_builtin, 3) ->
[t_atom(), t_atom(), t_arity()];
-arg_types(erlang, is_constant, 1) ->
- [t_any()];
arg_types(erlang, is_float, 1) ->
[t_any()];
arg_types(erlang, is_function, 1) ->
@@ -3747,8 +3762,13 @@ arg_types(erlang, pre_loaded, 0) ->
arg_types(erlang, process_display, 2) ->
[t_pid(), t_atom('backtrace')];
arg_types(erlang, process_flag, 2) ->
- [t_sup([t_atom('trap_exit'), t_atom('error_handler'),
- t_atom('min_heap_size'), t_atom('priority'), t_atom('save_calls'),
+ [t_sup([t_atom('trap_exit'),
+ t_atom('error_handler'),
+ t_atom('min_heap_size'),
+ t_atom('min_bin_vheap_size'),
+ t_atom('priority'),
+ t_atom('save_calls'),
+ t_atom('sensitive'),
t_atom('scheduler'), % undocumented
t_atom('monitor_nodes'), % undocumented
t_tuple([t_atom('monitor_nodes'), t_list()])]), % undocumented
@@ -3861,6 +3881,7 @@ arg_types(erlang, system_flag, 2) ->
t_atom('display_items'), % undocumented
t_atom('fullsweep_after'),
t_atom('min_heap_size'),
+ t_atom('min_bin_vheap_size'),
t_atom('multi_scheduling'),
t_atom('schedulers_online'),
t_atom('scheduler_bind_type'),
@@ -4733,6 +4754,7 @@ t_spawn_options() ->
t_atom('monitor'),
t_tuple([t_atom('priority'), t_process_priority_level()]),
t_tuple([t_atom('min_heap_size'), t_fixnum()]),
+ t_tuple([t_atom('min_bin_vheap_size'), t_fixnum()]),
t_tuple([t_atom('fullsweep_after'), t_fixnum()])]).
t_spawn_opt_return(List) ->
@@ -4821,6 +4843,17 @@ t_system_profile_return() ->
t_sup(t_atom('undefined'),
t_tuple([t_sup(t_pid(), t_port()), t_system_profile_options()])).
+t_system_build_type_return() ->
+ t_sup([t_atom('opt'),
+ t_atom('debug'),
+ t_atom('purify'),
+ t_atom('quantify'),
+ t_atom('purecov'),
+ t_atom('gcov'),
+ t_atom('valgrind'),
+ t_atom('gprof'),
+ t_atom('lcnt')]).
+
%% =====================================================================
%% These are used for the built-in functions of 'ets'
%% =====================================================================
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 992f387bd5..2d2b414a70 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -465,10 +465,6 @@ trans_fun([{test,is_nil,{f,Lbl},[Arg]}|Instructions], Env) ->
trans_fun([{test,is_binary,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(binary,Lbl,Arg,Env),
[Code | trans_fun(Instructions,Env1)];
-%%--- is_constant ---
-trans_fun([{test,is_constant,{f,Lbl},[Arg]}|Instructions], Env) ->
- {Code,Env1} = trans_type_test(constant,Lbl,Arg,Env),
- [Code | trans_fun(Instructions,Env1)];
%%--- is_list ---
trans_fun([{test,is_list,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(list,Lbl,Arg,Env),
diff --git a/lib/hipe/icode/hipe_icode_inline_bifs.erl b/lib/hipe/icode/hipe_icode_inline_bifs.erl
index 27296dcad5..9a2fb7846a 100644
--- a/lib/hipe/icode/hipe_icode_inline_bifs.erl
+++ b/lib/hipe/icode/hipe_icode_inline_bifs.erl
@@ -29,7 +29,7 @@
%% Currently inlined BIFs:
%% and, or, xor, not, <, >, >=, =<, ==, /=, =/=, =:=
-%% is_atom, is_boolean, is_binary, is_constant, is_float, is_function,
+%% is_atom, is_boolean, is_binary, is_float, is_function,
%% is_integer, is_list, is_pid, is_port, is_reference, is_tuple
-module(hipe_icode_inline_bifs).
@@ -131,7 +131,6 @@ is_type_test(Name) ->
is_boolean -> {true, boolean};
is_function -> {true, function};
is_reference -> {true, reference};
- is_constant -> {true, constant};
is_port -> {true, port};
_ -> false
end.
diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl
index 3f9488d7c3..cae4325b9e 100644
--- a/lib/hipe/icode/hipe_icode_type.erl
+++ b/lib/hipe/icode/hipe_icode_type.erl
@@ -899,9 +899,7 @@ test_type0(list, T) ->
test_type0(cons, T) ->
t_is_cons(T);
test_type0(nil, T) ->
- t_is_nil(T);
-test_type0(constant, T) ->
- t_is_constant(T).
+ t_is_nil(T).
true_branch_info(integer) ->
@@ -940,8 +938,6 @@ true_branch_info(nil) ->
t_nil();
true_branch_info(boolean) ->
t_boolean();
-true_branch_info(constant) ->
- t_constant();
true_branch_info(T) ->
exit({?MODULE,unknown_typetest,T}).
diff --git a/lib/hipe/tools/hipe_tool.erl b/lib/hipe/tools/hipe_tool.erl
index 990805ceca..190a68ee56 100644
--- a/lib/hipe/tools/hipe_tool.erl
+++ b/lib/hipe/tools/hipe_tool.erl
@@ -30,6 +30,18 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(hipe_tool).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/0]).
diff --git a/lib/observer/src/etop_gui.erl b/lib/observer/src/etop_gui.erl
index ff1b8078ad..9248d67344 100644
--- a/lib/observer/src/etop_gui.erl
+++ b/lib/observer/src/etop_gui.erl
@@ -17,6 +17,13 @@
%% %CopyrightEnd%
%%
-module(etop_gui).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-author('[email protected]').
-export([init/1,stop/1]).
diff --git a/lib/orber/src/orber_ifr.erl b/lib/orber/src/orber_ifr.erl
index c23374cd68..6799bc1db4 100644
--- a/lib/orber/src/orber_ifr.erl
+++ b/lib/orber/src/orber_ifr.erl
@@ -478,7 +478,7 @@ get_module(Id, Type) ->
What ->
orber:dbg("[~p] ~p:get_module(~p, ~p).~n"
"Id doesn't exist, mismatch Id vs Type or DB error: ~p",
- [?LINE, ?MODULE, Id, What], ?DEBUG_LEVEL),
+ [?LINE, ?MODULE, Id, Type, What], ?DEBUG_LEVEL),
corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
end.
diff --git a/lib/orber/test/orber_SUITE.erl b/lib/orber/test/orber_SUITE.erl
index be6ffa201c..72b0db1e0d 100644
--- a/lib/orber/test/orber_SUITE.erl
+++ b/lib/orber/test/orber_SUITE.erl
@@ -20,7 +20,6 @@
-module(orber_SUITE).
-include_lib("test_server/include/test_server.hrl").
-
-define(default_timeout, ?t:minutes(15)).
-define(application, orber).
@@ -31,7 +30,11 @@
% Test cases must be exported.
-export([app_test/1, undefined_functions/1, install_load_order/1,
- install_local_content/1]).
+ install_local_content/1,
+ otp_9887/1]).
+
+%% Exporting error handler callbacks for use in otp_9887
+-export([init/1, handle_event/2]).
%%
%% all/1
@@ -40,7 +43,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app_test, undefined_functions, install_load_order,
- install_local_content].
+ install_local_content,
+ otp_9887].
groups() ->
[].
@@ -76,6 +80,27 @@ app_test(_Config) ->
?line ok=?t:app_test(orber),
ok.
+otp_9887(_Config) ->
+ orber:jump_stop(),
+ application:set_env(orber, orber_debug_level, 10),
+ orber:jump_start([]),
+
+ mnesia:create_table(orber_light_ifr, []),
+
+ error_logger:add_report_handler(?MODULE,[self()]),
+ catch orber_ifr:get_module(foo, bar),
+
+ receive
+ {stolen,Reason} ->
+ {error,_Pid1, {_Pid2, _ErrorString, ArgumentList}} = Reason,
+ 5 = length(ArgumentList)
+ after 500 ->
+ test_server:fail("OTP_9887 TIMED OUT")
+ end,
+
+ orber:jump_stop(),
+ ok.
+
%% Install Orber using the load_order option.
install_load_order(suite) ->
[];
@@ -192,5 +217,10 @@ key1search(Key, L) ->
fail(Reason) ->
exit({suite_failed, Reason}).
+%% Error handler
+init([Proc]) -> {ok,Proc}.
+handle_event(Event, Proc) ->
+ Proc ! {stolen,Event},
+ {ok,Proc}.
diff --git a/lib/os_mon/c_src/memsup.c b/lib/os_mon/c_src/memsup.c
index 241e7718db..b6e417eaa0 100644
--- a/lib/os_mon/c_src/memsup.c
+++ b/lib/os_mon/c_src/memsup.c
@@ -327,27 +327,27 @@ get_mem_procfs(memory_ext *me){
/* Total and free is NEEDED! */
bp = strstr(buffer, "MemTotal:");
- if (sscanf(bp, "MemTotal: %lu kB\n", &(me->total))) me->flag |= F_MEM_TOTAL;
+ if (bp != NULL && sscanf(bp, "MemTotal: %lu kB\n", &(me->total))) me->flag |= F_MEM_TOTAL;
bp = strstr(buffer, "MemFree:");
- if (sscanf(bp, "MemFree: %lu kB\n", &(me->free))) me->flag |= F_MEM_FREE;
+ if (bp != NULL && sscanf(bp, "MemFree: %lu kB\n", &(me->free))) me->flag |= F_MEM_FREE;
/* Extensions */
bp = strstr(buffer, "Buffers:");
- if (sscanf(bp, "Buffers: %lu kB\n", &(me->buffered))) me->flag |= F_MEM_BUFFERS;
+ if (bp != NULL && sscanf(bp, "Buffers: %lu kB\n", &(me->buffered))) me->flag |= F_MEM_BUFFERS;
bp = strstr(buffer, "Cached:");
- if (sscanf(bp, "Cached: %lu kB\n", &(me->cached))) me->flag |= F_MEM_CACHED;
+ if (bp != NULL && sscanf(bp, "Cached: %lu kB\n", &(me->cached))) me->flag |= F_MEM_CACHED;
/* Swap */
bp = strstr(buffer, "SwapTotal:");
- if (sscanf(bp, "SwapTotal: %lu kB\n", &(me->total_swap))) me->flag |= F_SWAP_TOTAL;
+ if (bp != NULL && sscanf(bp, "SwapTotal: %lu kB\n", &(me->total_swap))) me->flag |= F_SWAP_TOTAL;
bp = strstr(buffer, "SwapFree:");
- if (sscanf(bp, "SwapFree: %lu kB\n", &(me->free_swap))) me->flag |= F_SWAP_FREE;
+ if (bp != NULL && sscanf(bp, "SwapFree: %lu kB\n", &(me->free_swap))) me->flag |= F_SWAP_FREE;
me->pagesize = 1024; /* procfs defines its size in kB */
diff --git a/lib/pman/doc/src/pman.xml b/lib/pman/doc/src/pman.xml
index 84d5a5772a..5f95aecc04 100644
--- a/lib/pman/doc/src/pman.xml
+++ b/lib/pman/doc/src/pman.xml
@@ -32,6 +32,12 @@
<module>pman</module>
<modulesummary>A graphical process manager.</modulesummary>
<description>
+ <warning>
+ <p>
+ The Pman application has been superseded by the Observer application.
+ Pman will be removed in R16.
+ </p>
+ </warning>
<p>A graphical tool used to inspect the Erlang processes executing either
locally or on remote nodes. It is also possible to trace events in
the individual processes.</p>
diff --git a/lib/pman/doc/src/pman_chapter.xml b/lib/pman/doc/src/pman_chapter.xml
index 141b488415..8668628bfa 100644
--- a/lib/pman/doc/src/pman_chapter.xml
+++ b/lib/pman/doc/src/pman_chapter.xml
@@ -32,6 +32,12 @@
<section>
<title>Introduction</title>
+ <warning>
+ <p>
+ The Pman application has been superseded by the Observer application.
+ Pman will be removed in R16.
+ </p>
+ </warning>
<p>The process manager Pman is a tool for viewing processes executing
locally or on remote nodes. Its main purpose is to locate
erroneous code by inspecting the state of the processes and by tracing
diff --git a/lib/pman/src/pman_buf_converter.erl b/lib/pman/src/pman_buf_converter.erl
index b6f560411c..c6cd8ec9ee 100644
--- a/lib/pman/src/pman_buf_converter.erl
+++ b/lib/pman/src/pman_buf_converter.erl
@@ -29,6 +29,7 @@
%%----------------------------------------------------------------------
-module(pman_buf_converter).
+-compile([{nowarn_deprecated_function,{gs,start,0}}]).
%%-compile(export_all).
-export([init/2]).
diff --git a/lib/pman/src/pman_buf_printer.erl b/lib/pman/src/pman_buf_printer.erl
index 74e935171a..62407648d5 100644
--- a/lib/pman/src/pman_buf_printer.erl
+++ b/lib/pman/src/pman_buf_printer.erl
@@ -18,6 +18,8 @@
%%
-module(pman_buf_printer).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
%%-compile(export_all).
-export([init/2]).
diff --git a/lib/pman/src/pman_main.erl b/lib/pman/src/pman_main.erl
index b68da1d2c3..adb5b65cd4 100644
--- a/lib/pman/src/pman_main.erl
+++ b/lib/pman/src/pman_main.erl
@@ -17,6 +17,8 @@
%% %CopyrightEnd%
%%
-module(pman_main).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%% Main process and window
diff --git a/lib/pman/src/pman_module_info.erl b/lib/pman/src/pman_module_info.erl
index cfd711a6e1..58f956aa42 100644
--- a/lib/pman/src/pman_module_info.erl
+++ b/lib/pman/src/pman_module_info.erl
@@ -17,6 +17,8 @@
%% %CopyrightEnd%
%%
-module(pman_module_info).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% Window with module information (View->Module Info...)
diff --git a/lib/pman/src/pman_shell.erl b/lib/pman/src/pman_shell.erl
index 0b13890460..393ef5f84d 100644
--- a/lib/pman/src/pman_shell.erl
+++ b/lib/pman/src/pman_shell.erl
@@ -25,6 +25,10 @@
%% ---------------------------------------------------------------
-module(pman_shell).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% ---------------------------------------------------------------
%% The user interface exports
diff --git a/lib/pman/src/pman_tool.erl b/lib/pman/src/pman_tool.erl
index 1d33fb9764..c548e17d00 100644
--- a/lib/pman/src/pman_tool.erl
+++ b/lib/pman/src/pman_tool.erl
@@ -17,6 +17,7 @@
%% %CopyrightEnd%
%%
-module(pman_tool).
+-compile([{nowarn_deprecated_function,{gs,read,2}}]).
%% Listbox selection window
diff --git a/lib/pman/src/pman_win.erl b/lib/pman/src/pman_win.erl
index 52d5a237cf..9dd446cd81 100644
--- a/lib/pman/src/pman_win.erl
+++ b/lib/pman/src/pman_win.erl
@@ -21,6 +21,16 @@
%% ------------------------------------------------------------
-module(pman_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% ---------------------------------------------------------------
%% The user interface exports
diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl
index f342eab159..f0c94e29a5 100644
--- a/lib/public_key/src/pubkey_ssh.erl
+++ b/lib/public_key/src/pubkey_ssh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. 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
@@ -146,16 +146,7 @@ do_openssh_decode(auth_keys = FileType, [Line | Lines], Acc) ->
Split = binary:split(Line, <<" ">>, [global]),
case mend_split(Split, []) of
%% ssh2
- [Options, KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- [{comment, string_decode(Comment)},
- {options, comma_list_decode(Options)}]}
- | Acc]);
-
- [KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
+ [KeyType, Base64Enc, Comment] ->
do_openssh_decode(FileType, Lines,
[{openssh_pubkey_decode(KeyType, Base64Enc),
[{comment, string_decode(Comment)}]} | Acc]);
@@ -166,44 +157,32 @@ do_openssh_decode(auth_keys = FileType, [Line | Lines], Acc) ->
[{comment, string_decode(Comment)},
{options, comma_list_decode(Options)},
{bits, integer_decode(Bits)}]} | Acc]);
- [Bits, Exponent, Modulus, Comment] ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- [{comment, string_decode(Comment)},
- {bits, integer_decode(Bits)}]} | Acc])
- end;
+ [A, B, C, D] ->
+ ssh_2_or_1(FileType, Lines, Acc, A,B,C,D)
+ end;
do_openssh_decode(known_hosts = FileType, [Line | Lines], Acc) ->
- case binary:split(Line, <<" ">>, [global]) of
+ Split = binary:split(Line, <<" ">>, [global]),
+ case mend_split(Split, []) of
%% ssh 2
- [HostNames, KeyType, Base64Enc] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
+ [HostNames, KeyType, Base64Enc] ->
do_openssh_decode(FileType, Lines,
[{openssh_pubkey_decode(KeyType, Base64Enc),
[{hostnames, comma_list_decode(HostNames)}]}| Acc]);
- [HostNames, KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- [{comment, string_decode(Comment)},
- {hostnames, comma_list_decode(HostNames)}]} | Acc]);
+ [A, B, C, D] ->
+ ssh_2_or_1(FileType, Lines, Acc, A, B, C, D);
%% ssh 1
[HostNames, Bits, Exponent, Modulus, Comment] ->
do_openssh_decode(FileType, Lines,
[{ssh1_rsa_pubkey_decode(Modulus, Exponent),
[{comment, string_decode(Comment)},
{hostnames, comma_list_decode(HostNames)},
- {bits, integer_decode(Bits)}]} | Acc]);
- [HostNames, Bits, Exponent, Modulus] ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- [{comment, []},
- {hostnames, comma_list_decode(HostNames)},
{bits, integer_decode(Bits)}]} | Acc])
end;
do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
- case binary:split(Line, <<" ">>, [global]) of
+ Split = binary:split(Line, <<" ">>, [global]),
+ case mend_split(Split, []) of
[KeyType, Base64Enc, Comment0] when KeyType == <<"ssh-rsa">>;
KeyType == <<"ssh-dss">> ->
Comment = string:strip(binary_to_list(Comment0), right, $\n),
@@ -212,6 +191,46 @@ do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
[{comment, Comment}]} | Acc])
end.
+ssh_2_or_1(known_hosts = FileType, Lines, Acc, A, B, C, D) ->
+ try integer_decode(B) of
+ Int ->
+ file_type_decode_ssh1(FileType, Lines, Acc, A, Int, C,D)
+ catch
+ error:badarg ->
+ file_type_decode_ssh2(FileType, Lines, Acc, A,B,C,D)
+ end;
+ssh_2_or_1(auth_keys = FileType, Lines, Acc, A, B, C, D) ->
+ try integer_decode(A) of
+ Int ->
+ file_type_decode_ssh1(FileType, Lines, Acc, Int, B, C,D)
+ catch
+ error:badarg ->
+ file_type_decode_ssh2(FileType, Lines, Acc, A,B,C,D)
+ end.
+
+file_type_decode_ssh1(known_hosts = FileType, Lines, Acc, HostNames, Bits, Exponent, Modulus) ->
+ do_openssh_decode(FileType, Lines,
+ [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
+ [{comment, []},
+ {hostnames, comma_list_decode(HostNames)},
+ {bits, Bits}]} | Acc]);
+file_type_decode_ssh1(auth_keys = FileType, Lines, Acc, Bits, Exponent, Modulus, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
+ [{comment, string_decode(Comment)},
+ {bits, Bits}]} | Acc]).
+
+file_type_decode_ssh2(known_hosts = FileType, Lines, Acc, HostNames, KeyType, Base64Enc, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{openssh_pubkey_decode(KeyType, Base64Enc),
+ [{comment, string_decode(Comment)},
+ {hostnames, comma_list_decode(HostNames)}]} | Acc]);
+file_type_decode_ssh2(auth_keys = FileType, Lines, Acc, Options, KeyType, Base64Enc, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{openssh_pubkey_decode(KeyType, Base64Enc),
+ [{comment, string_decode(Comment)},
+ {options, comma_list_decode(Options)}]}
+ | Acc]).
openssh_pubkey_decode(<<"ssh-rsa">>, Base64Enc) ->
<<?UINT32(StrLen), _:StrLen/binary,
@@ -231,7 +250,9 @@ openssh_pubkey_decode(<<"ssh-dss">>, Base64Enc) ->
{erlint(SizeY, Y),
#'Dss-Parms'{p = erlint(SizeP, P),
q = erlint(SizeQ, Q),
- g = erlint(SizeG, G)}}.
+ g = erlint(SizeG, G)}};
+openssh_pubkey_decode(KeyType, Base64Enc) ->
+ {KeyType, base64:mime_decode(Base64Enc)}.
erlint(MPIntSize, MPIntValue) ->
Bits= MPIntSize * 8,
@@ -412,6 +433,12 @@ is_key_field(<<"ssh-dss">>) ->
true;
is_key_field(<<"ssh-rsa">>) ->
true;
+is_key_field(<<"ecdsa-sha2-nistp256">>) ->
+ true;
+is_key_field(<<"ecdsa-sha2-nistp384">>) ->
+ true;
+is_key_field(<<"ecdsa-sha2-nistp521">>) ->
+ true;
is_key_field(_) ->
false.
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index 522c7b496b..8d2b9c35d3 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -1572,7 +1572,7 @@ memlib(_Lib, []) -> false.
%% recursively remove file or directory
remove_file(File) ->
- case file:read_file_info(File) of
+ case file:read_link_info(File) of
{ok, Info} when Info#file_info.type==directory ->
case file:list_dir(File) of
{ok, Files} ->
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index ac616dab72..467d1226b3 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -59,7 +59,7 @@ win32_cases() ->
cases() ->
[otp_2740, otp_2760, otp_5761, otp_9402, otp_9417,
otp_9395_check_old_code, otp_9395_check_and_purge,
- otp_9395_update_many_mods, otp_9395_rm_many_mods,
+ otp_9395_update_many_mods, otp_9395_rm_many_mods, otp_9864,
instructions, eval_appup, eval_appup_with_restart,
supervisor_which_children_timeout,
release_handler_which_releases, install_release_syntax_check,
@@ -1205,6 +1205,60 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
otp_9395_rm_many_mods(cleanup,_Conf) ->
stop_node(node_name(otp_9395_rm_many_mods)).
+otp_9864(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9864"),
+ RelDir = filename:join(?config(data_dir, Conf), "app1_app2"),
+ LibDir1 = filename:join(RelDir, "lib1"),
+ LibDir2 = filename:join(RelDir, "lib2"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{app1,"1.0",LibDir1},
+ {app2,"1.0",LibDir1}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{app1,"2.0",LibDir2},
+ {app2,"1.0",LibDir2}],
+ {[Rel1],[Rel1],[LibDir1]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9864, Rel1, filename:join(Rel1Dir,"sys.config")),
+
+ %% Unpack rel2 (make sure it does not work if an AppDir is bad)
+ LibDir3 = filename:join(RelDir, "lib3"),
+ {error, {no_such_directory, _}} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{app1,"2.0",LibDir2}, {app2,"1.0",LibDir3}]]),
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{app1,"2.0",LibDir2}, {app2,"1.0",LibDir2}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% Install RelVsn2 without {update_paths, true} option
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% Install RelVsn1 again
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn1]),
+
+ TempRel2Dir = filename:join(Dir,"releases/2"),
+ file:make_symlink(TempRel2Dir, filename:join(TempRel2Dir, "foo_symlink_dir")),
+
+ %% This will fail if symlinks are not handled
+ ok = rpc:call(Node, release_handler, remove_release, [RelVsn2]),
+
+ ok.
+
upgrade_supervisor(Conf) when is_list(Conf) ->
%% Set some paths
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 2c5096a25f..ed88b3a1af 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -86,7 +86,7 @@
by calling ssh_connect:session_channel/2.</p>
<p>Options are:</p>
<taglist>
- <tag><c><![CDATA[{user_dir, String}]]></c></tag>
+ <tag><c><![CDATA[{user_dir, string()}]]></c></tag>
<item>
<p>Sets the user directory e.i. the directory containing
ssh configuration files for the user such as
@@ -94,6 +94,18 @@
<c><![CDATA[authorized_key]]></c>. Defaults to the directory normally
referred to as <c><![CDATA[~/.ssh]]></c> </p>
</item>
+ <tag><c><![CDATA[{dsa_pass_phrase, string()}]]></c></tag>
+ <item>
+ <p>If the user dsa key is protected by a pass phrase it can be
+ supplied with this option.
+ </p>
+ </item>
+ <tag><c><![CDATA[{rsa_pass_phrase, string()}]]></c></tag>
+ <item>
+ <p>If the user rsa key is protected by a pass phrase it can be
+ supplied with this option.
+ </p>
+ </item>
<tag><c><![CDATA[{silently_accept_hosts, boolean()}]]></c></tag>
<item>
<p>When true hosts are added to the
@@ -222,6 +234,14 @@
option <c>shell</c> which is much less work than implementing
your own cli channel.
</item>
+ <tag><c><![CDATA[{user_dir, String}]]></c></tag>
+ <item>
+ <p>Sets the user directory e.i. the directory containing
+ ssh configuration files for the user such as
+ <c><![CDATA[known_hosts]]></c>, <c><![CDATA[id_rsa, id_dsa]]></c> and
+ <c><![CDATA[authorized_key]]></c>. Defaults to the directory normally
+ referred to as <c><![CDATA[~/.ssh]]></c> </p>
+ </item>
<tag><c><![CDATA[{system_dir, string()}]]></c></tag>
<item>
<p>Sets the system directory, containing the host files
@@ -283,22 +303,6 @@
</func>
<func>
- <name>sign_data(Data, Algorithm) -> Signature | {error, Reason}</name>
- <fsummary> </fsummary>
- <type>
- <v> Data = binary()</v>
- <v> Algorithm = "ssh-rsa"</v>
- <v> Signature = binary()</v>
- <v> Reason = term()</v>
- </type>
- <desc>
- <p>Signs the supplied binary using the SSH key.
- </p>
- </desc>
- </func>
-
-
- <func>
<name>start() -> </name>
<name>start(Type) -> ok | {error, Reason}</name>
<fsummary>Starts the Ssh application. </fsummary>
@@ -356,21 +360,6 @@
</desc>
</func>
- <func>
- <name>verify_data(Data, Signature, Algorithm) -> ok | {error, Reason}</name>
- <fsummary> </fsummary>
- <type>
- <v> Data = binary()</v>
- <v> Algorithm = "ssh-rsa"</v>
- <v> Signature = binary()</v>
- <v> Reason = term()</v>
- </type>
- <desc>
- <p>Verifies the supplied binary against the binary signature.
- </p>
- </desc>
- </func>
-
</funcs>
</erlref>
diff --git a/lib/ssh/src/DSS.asn1 b/lib/ssh/src/DSS.asn1
deleted file mode 100644
index 77aca3808b..0000000000
--- a/lib/ssh/src/DSS.asn1
+++ /dev/null
@@ -1,20 +0,0 @@
-DSS DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-
--- EXPORTS ALL
--- All types and values defined in this module are exported for use
--- in other ASN.1 modules.
-
-DSAPrivateKey ::= SEQUENCE {
- version INTEGER,
- p INTEGER, -- p
- q INTEGER, -- q
- g INTEGER, -- q
- y INTEGER, -- y
- x INTEGER -- x
-}
-
-END
-
-
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index da31d87369..7be97abf66 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. 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
@@ -36,7 +36,11 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN)
# Common Macros
# ----------------------------------------------------
+# Behaviour (api) modules are first so they are compiled when
+# the compiler reaches a callback module using them.
MODULES= \
+ ssh_sftpd_file_api \
+ ssh_key_api \
ssh \
ssh_sup \
sshc_sup \
@@ -56,25 +60,22 @@ MODULES= \
ssh_auth\
ssh_bits \
ssh_cli \
- ssh_dsa \
ssh_file \
ssh_io \
ssh_math \
ssh_no_io \
- ssh_rsa \
ssh_sftp \
ssh_sftpd \
ssh_sftpd_file\
- ssh_sftpd_file_api \
ssh_transport \
ssh_userreg \
ssh_xfer
PUBLIC_HRL_FILES= ssh.hrl ssh_userauth.hrl ssh_xfer.hrl
-ERL_FILES= $(MODULES:%=%.erl) $(ASN_ERLS)
+ERL_FILES= $(MODULES:%=%.erl)
-ALL_MODULES= $(MODULES) $(ASN_MODULES)
+ALL_MODULES= $(MODULES)
TARGET_FILES= $(ALL_MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
@@ -87,22 +88,13 @@ APP_TARGET= $(EBIN)/$(APP_FILE)
APPUP_SRC= $(APPUP_FILE).src
APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-ASN_MODULES = PKCS-1 DSS
-ASN_ASNS = $(ASN_MODULES:%=%.asn1)
-ASN_ERLS = $(ASN_MODULES:%=%.erl)
-ASN_HRLS = $(ASN_MODULES:%=%.hrl)
-ASN_DBS = $(ASN_MODULES:%=%.asn1db)
-ASN_TABLES = $(ASN_MODULES:%=%.table)
-
-ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj +inline
-
-INTERNAL_HRL_FILES = $(ASN_HRLS) ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl
+INTERNAL_HRL_FILES = ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -pa$(EBIN)
-
+ERL_COMPILE_FLAGS += -pa$(EBIN)\
+ -pz $(ERL_TOP)/lib/public_key/ebin
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -114,7 +106,6 @@ debug: ERLC_FLAGS += -Ddebug
clean:
rm -f $(TARGET_FILES)
rm -f errs core *~
- rm -f $(ASN_ERLS) $(ASN_HRLS) $(ASN_DBS)
$(TARGET_FILES): ssh.hrl
@@ -127,10 +118,6 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-%.erl %.hrl: %.asn1
- $(ERLC) $(ASN_FLAGS) $<
-
-$(EBIN)/ssh_file.$(EMULATOR) $(EBIN)/ssh_rsa.$(EMULATOR): $(ASN_HRLS)
docs:
diff --git a/lib/ssh/src/PKCS-1.asn1 b/lib/ssh/src/PKCS-1.asn1
deleted file mode 100644
index e7d6b18c63..0000000000
--- a/lib/ssh/src/PKCS-1.asn1
+++ /dev/null
@@ -1,116 +0,0 @@
-PKCS-1 {
- iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)
- modules(0) pkcs-1(1)
-}
-
--- $Revision: 1.1 $
-
-DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-
--- IMPORTS id-sha256, id-sha384, id-sha512
--- FROM NIST-SHA2 {
--- joint-iso-itu-t(2) country(16) us(840) organization(1)
--- gov(101) csor(3) nistalgorithm(4) modules(0) sha2(1)
--- };
-
-pkcs-1 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1
-}
-
-rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
-
-id-RSAES-OAEP OBJECT IDENTIFIER ::= { pkcs-1 7 }
-
-id-pSpecified OBJECT IDENTIFIER ::= { pkcs-1 9 }
-
-id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 }
-
-md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
-md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
-sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
-sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
-sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
-sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
-
-id-sha1 OBJECT IDENTIFIER ::= {
- iso(1) identified-organization(3) oiw(14) secsig(3)
- algorithms(2) 26
-}
-
-id-md2 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
-}
-
-id-md5 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
-}
-
-id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 }
-
-
-RSAPublicKey ::= SEQUENCE {
- modulus INTEGER, -- n
- publicExponent INTEGER -- e
-}
-
-RSAPrivateKey ::= SEQUENCE {
- version Version,
- modulus INTEGER, -- n
- publicExponent INTEGER, -- e
- privateExponent INTEGER, -- d
- prime1 INTEGER, -- p
- prime2 INTEGER, -- q
- exponent1 INTEGER, -- d mod (p-1)
- exponent2 INTEGER, -- d mod (q-1)
- coefficient INTEGER, -- (inverse of q) mod p
- otherPrimeInfos OtherPrimeInfos OPTIONAL
-}
-
-Version ::= INTEGER { two-prime(0), multi(1) }
- (CONSTRAINED BY {
- -- version must be multi if otherPrimeInfos present --
- })
-
-OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
-
-OtherPrimeInfo ::= SEQUENCE {
- prime INTEGER, -- ri
- exponent INTEGER, -- di
- coefficient INTEGER -- ti
-}
-
-Algorithm ::= SEQUENCE {
- algorithm OBJECT IDENTIFIER,
- parameters ANY DEFINED BY algorithm OPTIONAL
-}
-
-AlgorithmNull ::= SEQUENCE {
- algorithm OBJECT IDENTIFIER,
- parameters NULL
-}
-
-
-RSASSA-PSS-params ::= SEQUENCE {
- hashAlgorithm [0] Algorithm, -- DEFAULT sha1,
- maskGenAlgorithm [1] Algorithm, -- DEFAULT mgf1SHA1,
- saltLength [2] INTEGER DEFAULT 20,
- trailerField [3] TrailerField DEFAULT trailerFieldBC
-}
-
-TrailerField ::= INTEGER { trailerFieldBC(1) }
-
-DigestInfo ::= SEQUENCE {
- digestAlgorithm Algorithm,
- digest OCTET STRING
-}
-
-DigestInfoNull ::= SEQUENCE {
- digestAlgorithm AlgorithmNull,
- digest OCTET STRING
-}
-
-
-END -- PKCS1Definitions
-
diff --git a/lib/ssh/src/prebuild.skip b/lib/ssh/src/prebuild.skip
deleted file mode 100644
index 1d7552d98d..0000000000
--- a/lib/ssh/src/prebuild.skip
+++ /dev/null
@@ -1,2 +0,0 @@
-DSS.asn1db
-PKCS-1.asn1db
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 8a3e15841f..7a58dbe54f 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -3,9 +3,7 @@
{application, ssh,
[{description, "SSH-2 for Erlang/OTP"},
{vsn, "%VSN%"},
- {modules, ['DSS',
- 'PKCS-1',
- ssh,
+ {modules, [ssh,
ssh_app,
ssh_acceptor,
ssh_acceptor_sup,
@@ -21,12 +19,11 @@
ssh_shell,
sshc_sup,
sshd_sup,
- ssh_dsa,
ssh_file,
ssh_io,
+ ssh_key_api,
ssh_math,
ssh_no_io,
- ssh_rsa,
ssh_sftp,
ssh_sftpd,
ssh_sftpd_file,
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index cada109df0..5751f2eaa0 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. 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
@@ -23,6 +23,7 @@
-include("ssh.hrl").
-include("ssh_connect.hrl").
+-include_lib("public_key/include/public_key.hrl").
-export([start/0, start/1, stop/0, connect/3, connect/4, close/1, connection_info/2,
channel_info/3,
@@ -30,6 +31,9 @@
stop_listener/1, stop_listener/2, stop_daemon/1, stop_daemon/2,
shell/1, shell/2, shell/3]).
+-deprecated({sign_data, 2, next_major_release}).
+-deprecated({verify_data, 3, next_major_release}).
+
-export([sign_data/2, verify_data/3]).
%%--------------------------------------------------------------------
@@ -89,6 +93,9 @@ connect(Host, Port, Options, Timeout) ->
%% might return undefined as the connection manager
%% could allready have terminated, so we will not
%% match the Manager in this case
+ {_, not_connected, {error, econnrefused}} when DisableIpv6 == false ->
+ do_demonitor(MRef, Manager),
+ connect(Host, Port, [{ip_v6_disabled, true} | Options], Timeout);
{_, not_connected, {error, Reason}} ->
do_demonitor(MRef, Manager),
{error, Reason};
@@ -247,43 +254,6 @@ shell(Host, Port, Options) ->
Error
end.
-
-%%--------------------------------------------------------------------
-%% Function: sign_data(Data, Algorithm) -> binary() |
-%% {error, Reason}
-%%
-%% Data = binary()
-%% Algorithm = "ssh-rsa"
-%%
-%% Description: Use SSH key to sign data.
-%%--------------------------------------------------------------------
-sign_data(Data, Algorithm) when is_binary(Data) ->
- case ssh_file:private_identity_key(Algorithm,[]) of
- {ok, Key} when Algorithm == "ssh-rsa" ->
- ssh_rsa:sign(Key, Data);
- Error ->
- Error
- end.
-
-%%--------------------------------------------------------------------
-%% Function: verify_data(Data, Signature, Algorithm) -> ok |
-%% {error, Reason}
-%%
-%% Data = binary()
-%% Signature = binary()
-%% Algorithm = "ssh-rsa"
-%%
-%% Description: Use SSH signature to verify data.
-%%--------------------------------------------------------------------
-verify_data(Data, Signature, Algorithm) when is_binary(Data), is_binary(Signature) ->
- case ssh_file:public_identity_key(Algorithm, []) of
- {ok, Key} when Algorithm == "ssh-rsa" ->
- ssh_rsa:verify(Key, Data, Signature);
- Error ->
- Error
- end.
-
-
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -336,6 +306,10 @@ handle_options([{connect_timeout, _} = Opt | Rest], SockOpts, Opts) ->
handle_options(Rest, SockOpts, [Opt | Opts]);
handle_options([{user, _} = Opt | Rest], SockOpts, Opts) ->
handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{dsa_pass_phrase, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{rsa_pass_phrase, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
handle_options([{password, _} = Opt | Rest], SockOpts, Opts) ->
handle_options(Rest, SockOpts, [Opt | Opts]);
handle_options([{user_passwords, _} = Opt | Rest], SockOpts, Opts) ->
@@ -379,6 +353,50 @@ handle_options([Opt | Rest], SockOpts, Opts) ->
inetopt(true) ->
inet;
inetopt(false) ->
- inet6.
+ case gen_tcp:listen(0, [inet6, {ip, loopback}]) of
+ {ok, Dummyport} ->
+ gen_tcp:close(Dummyport),
+ inet6;
+ _ ->
+ inet
+ end.
+
+%%%
+%% Deprecated
+%%%
+
+%%--------------------------------------------------------------------
+%% Function: sign_data(Data, Algorithm) -> binary() |
+%% {error, Reason}
+%%
+%% Data = binary()
+%% Algorithm = "ssh-rsa"
+%%
+%% Description: Use SSH key to sign data.
+%%--------------------------------------------------------------------
+sign_data(Data, Algorithm) when is_binary(Data) ->
+ case ssh_file:user_key(Algorithm,[]) of
+ {ok, Key} when Algorithm == "ssh-rsa" ->
+ public_key:sign(Data, sha, Key);
+ Error ->
+ Error
+ end.
+%%--------------------------------------------------------------------
+%% Function: verify_data(Data, Signature, Algorithm) -> ok |
+%% {error, Reason}
+%%
+%% Data = binary()
+%% Signature = binary()
+%% Algorithm = "ssh-rsa"
+%%
+%% Description: Use SSH signature to verify data.
+%%--------------------------------------------------------------------
+verify_data(Data, Signature, Algorithm) when is_binary(Data), is_binary(Signature) ->
+ case ssh_file:user_key(Algorithm, []) of
+ {ok, #'RSAPrivateKey'{publicExponent = E, modulus = N}} when Algorithm == "ssh-rsa" ->
+ public_key:verify(Data, sha, Signature, #'RSAPublicKey'{publicExponent = E, modulus = N});
+ Error ->
+ Error
+ end.
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index ac249b05e3..da5750b6c3 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. 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
@@ -54,18 +54,6 @@
-define(string(X), << ?STRING(list_to_binary(X)) >> ).
-define(binary(X), << ?STRING(X) >>).
--ifdef(debug).
--define(dbg(Debug, Fmt, As),
- case (Debug) of
- true ->
- io:format([$# | (Fmt)], (As));
- _ ->
- ok
- end).
--else.
--define(dbg(Debug, Fmt, As), ok).
--endif.
-
-define(SSH_CIPHER_NONE, 0).
-define(SSH_CIPHER_3DES, 3).
-define(SSH_CIPHER_AUTHFILE, ?SSH_CIPHER_3DES).
@@ -138,7 +126,8 @@
userauth_quiet_mode, % boolean()
userauth_supported_methods , %
userauth_methods,
- userauth_preference
+ userauth_preference,
+ available_host_keys
}).
-record(alg,
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 9dbd95886e..62d684f4dc 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. 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
@@ -21,8 +21,9 @@
-module(ssh_auth).
--include("ssh.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include("ssh.hrl").
-include("ssh_auth.hrl").
-include("ssh_transport.hrl").
@@ -36,18 +37,21 @@
%%--------------------------------------------------------------------
%%% Internal application API
%%--------------------------------------------------------------------
-publickey_msg([Cb, #ssh{user = User,
+publickey_msg([Alg, #ssh{user = User,
session_id = SessionId,
service = Service,
opts = Opts} = Ssh]) ->
+
+ Hash = sha, %% Maybe option?!
ssh_bits:install_messages(userauth_pk_messages()),
- Alg = Cb:alg_name(),
- case ssh_file:private_identity_key(Alg, Opts) of
- {ok, PrivKey} ->
- PubKeyBlob = ssh_file:encode_public_key(PrivKey),
+ KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+
+ case KeyCb:user_key(Alg, Opts) of
+ {ok, Key} ->
+ PubKeyBlob = encode_public_key(Key),
SigData = build_sig_data(SessionId,
- User, Service, Alg, PubKeyBlob),
- Sig = Cb:sign(PrivKey, SigData),
+ User, Service, PubKeyBlob, Alg),
+ Sig = ssh_transport:sign(SigData, Hash, Key),
SigBlob = list_to_binary([?string(Alg), ?binary(Sig)]),
ssh_transport:ssh_packet(
#ssh_msg_userauth_request{user = User,
@@ -58,8 +62,8 @@ publickey_msg([Cb, #ssh{user = User,
?binary(PubKeyBlob),
?binary(SigBlob)]},
Ssh);
- _Error ->
- not_ok
+ _Error ->
+ not_ok
end.
password_msg([#ssh{opts = Opts, io_cb = IoCb,
@@ -67,29 +71,43 @@ password_msg([#ssh{opts = Opts, io_cb = IoCb,
ssh_bits:install_messages(userauth_passwd_messages()),
Password = case proplists:get_value(password, Opts) of
undefined ->
- IoCb:read_password("ssh password: ");
+ user_interaction(Opts, IoCb);
PW ->
PW
end,
- ssh_transport:ssh_packet(
- #ssh_msg_userauth_request{user = User,
- service = Service,
- method = "password",
- data =
- <<?BOOLEAN(?FALSE),
- ?STRING(list_to_binary(Password))>>},
- Ssh).
+ case Password of
+ not_ok ->
+ not_ok;
+ _ ->
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_request{user = User,
+ service = Service,
+ method = "password",
+ data =
+ <<?BOOLEAN(?FALSE),
+ ?STRING(list_to_binary(Password))>>},
+ Ssh)
+ end.
+
+user_interaction(Opts, IoCb) ->
+ case proplists:get_value(allow_user_interaction, Opts, true) of
+ true ->
+ IoCb:read_password("ssh password: ");
+ false ->
+ not_ok
+ end.
+
%% See RFC 4256 for info on keyboard-interactive
keyboard_interactive_msg([#ssh{user = User,
- service = Service} = Ssh]) ->
+ service = Service} = Ssh]) ->
ssh_bits:install_messages(userauth_keyboard_interactive_messages()),
ssh_transport:ssh_packet(
#ssh_msg_userauth_request{user = User,
service = Service,
method = "keyboard-interactive",
data = << ?STRING(<<"">>),
- ?STRING(<<>>) >> },
+ ?STRING(<<>>) >> },
Ssh).
service_request_msg(Ssh) ->
@@ -103,12 +121,12 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) ->
service = "ssh-connection",
method = "none",
data = <<>>},
- CbFirst = proplists:get_value(public_key_alg, Opts,
- ?PREFERRED_PK_ALG),
- CbSecond = other_cb(CbFirst),
+ FirstAlg = algorithm(proplists:get_value(public_key_alg, Opts,
+ ?PREFERRED_PK_ALG)),
+ SecondAlg = other_alg(FirstAlg),
AllowUserInt = proplists:get_value(allow_user_interaction, Opts,
true),
- Prefs = method_preference(CbFirst, CbSecond, AllowUserInt),
+ Prefs = method_preference(FirstAlg, SecondAlg, AllowUserInt),
ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User,
userauth_preference = Prefs,
userauth_methods = none,
@@ -192,12 +210,12 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
?TRUE ->
case verify_sig(SessionId, User, "ssh-connection", Alg,
KeyBlob, SigWLen, Opts) of
- ok ->
+ true ->
{authorized, User,
ssh_transport:ssh_packet(
#ssh_msg_userauth_success{}, Ssh)};
- {error, Reason} ->
- {not_authorized, {User, {error, Reason}},
+ false ->
+ {not_authorized, {User, {error, "Invalid signature"}},
ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
authentications="publickey,password",
partial_success = false}, Ssh)}
@@ -228,7 +246,6 @@ handle_userauth_info_request(
PromptInfos = decode_keyboard_interactive_prompts(NumPrompts,Data),
Resps = keyboard_interact_get_responses(IoCb, Opts,
Name, Instr, PromptInfos),
- %%?dbg(true, "keyboard_interactive_reply: resps=~n#~p ~n", [Resps]),
RespBin = list_to_binary(
lists:map(fun(S) -> <<?STRING(list_to_binary(S))>> end,
Resps)),
@@ -263,15 +280,15 @@ userauth_messages() ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-method_preference(Callback1, Callback2, true) ->
- [{"publickey", ?MODULE, publickey_msg, [Callback1]},
- {"publickey", ?MODULE, publickey_msg,[Callback2]},
+method_preference(Alg1, Alg2, true) ->
+ [{"publickey", ?MODULE, publickey_msg, [Alg1]},
+ {"publickey", ?MODULE, publickey_msg,[Alg2]},
{"password", ?MODULE, password_msg, []},
{"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}
];
-method_preference(Callback1, Callback2, false) ->
- [{"publickey", ?MODULE, publickey_msg, [Callback1]},
- {"publickey", ?MODULE, publickey_msg,[Callback2]},
+method_preference(Alg1, Alg2, false) ->
+ [{"publickey", ?MODULE, publickey_msg, [Alg1]},
+ {"publickey", ?MODULE, publickey_msg,[Alg2]},
{"password", ?MODULE, password_msg, []}
].
@@ -295,7 +312,6 @@ user_name(Opts) ->
end.
check_password(User, Password, Opts) ->
- %%?dbg(true, " ~p ~p ~p ~n", [User, Password, Opts]),
case proplists:get_value(pwdfun, Opts) of
undefined ->
Static = get_password_option(Opts, User),
@@ -312,25 +328,22 @@ get_password_option(Opts, User) ->
end.
verify_sig(SessionId, User, Service, Alg, KeyBlob, SigWLen, Opts) ->
- case ssh_file:lookup_user_key(User, Alg, Opts) of
- {ok, OurKey} ->
- {ok, Key} = ssh_file:decode_public_key_v2(KeyBlob, Alg),
- case OurKey of
- Key ->
- NewSig = build_sig_data(SessionId,
- User, Service, Alg, KeyBlob),
- <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
- <<?UINT32(AlgLen), _Alg:AlgLen/binary,
- ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
- M = alg_to_module(Alg),
- M:verify(OurKey, NewSig, Sig);
- _ ->
- {error, key_unacceptable}
- end;
- Error -> Error
+ {ok, Key} = decode_public_key_v2(KeyBlob, Alg),
+ KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+
+ case KeyCb:is_auth_key(Key, User, Alg, Opts) of
+ true ->
+ PlainText = build_sig_data(SessionId, User,
+ Service, KeyBlob, Alg),
+ <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
+ <<?UINT32(AlgLen), _Alg:AlgLen/binary,
+ ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
+ ssh_transport:verify(PlainText, sha, Sig, Key);
+ false ->
+ {error, key_unacceptable}
end.
-build_sig_data(SessionId, User, Service, Alg, KeyBlob) ->
+build_sig_data(SessionId, User, Service, KeyBlob, Alg) ->
Sig = [?binary(SessionId),
?SSH_MSG_USERAUTH_REQUEST,
?string(User),
@@ -341,6 +354,11 @@ build_sig_data(SessionId, User, Service, Alg, KeyBlob) ->
?binary(KeyBlob)],
list_to_binary(Sig).
+algorithm(ssh_rsa) ->
+ "ssh-rsa";
+algorithm(ssh_dsa) ->
+ "ssh-dss".
+
decode_keyboard_interactive_prompts(NumPrompts, Data) ->
Types = lists:append(lists:duplicate(NumPrompts, [string, boolean])),
pairwise_tuplify(ssh_bits:decode(Data, Types)).
@@ -412,12 +430,28 @@ userauth_pk_messages() ->
binary]} % key blob
].
-alg_to_module("ssh-dss") ->
- ssh_dsa;
-alg_to_module("ssh-rsa") ->
- ssh_rsa.
-
-other_cb(ssh_rsa) ->
- ssh_dsa;
-other_cb(ssh_dsa) ->
- ssh_rsa.
+other_alg("ssh-rsa") ->
+ "ssh-dss";
+other_alg("ssh-dss") ->
+ "ssh-rsa".
+decode_public_key_v2(K_S, "ssh-rsa") ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint]) of
+ ["ssh-rsa", E, N] ->
+ {ok, #'RSAPublicKey'{publicExponent = E, modulus = N}};
+ _ ->
+ {error, bad_format}
+ end;
+decode_public_key_v2(K_S, "ssh-dss") ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
+ ["ssh-dss",P,Q,G,Y] ->
+ {ok, {Y, #'Dss-Parms'{p = P, q = Q, g = G}}};
+ _ ->
+ {error, bad_format}
+ end;
+decode_public_key_v2(_, _) ->
+ {error, bad_format}.
+
+encode_public_key(#'RSAPrivateKey'{publicExponent = E, modulus = N}) ->
+ ssh_bits:encode(["ssh-rsa",E,N], [string,mpint,mpint]);
+encode_public_key(#'DSAPrivateKey'{p = P, q = Q, g = G, y = Y}) ->
+ ssh_bits:encode(["ssh-dss",P,Q,G,Y], [string,mpint,mpint,mpint,mpint]).
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 3f0a06575c..5841f06d70 100644
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. 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
@@ -105,16 +105,12 @@ bignum(X) ->
install_messages(Codes) ->
foreach(fun({Name, Code, Ts}) ->
- %% ?dbg(true, "install msg: ~s = ~w ~w~n",
-%% [Name,Code,Ts]),
put({msg_name,Code}, {Name,Ts}),
put({msg_code,Name}, {Code,Ts})
end, Codes).
uninstall_messages(Codes) ->
foreach(fun({Name, Code, _Ts}) ->
- %% ?dbg(true, "uninstall msg: ~s = ~w ~w~n",
-%% [Name,Code,_Ts]),
erase({msg_name,Code}),
erase({msg_code,Name})
end, Codes).
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 7b9e9185bf..cb02d7b824 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. 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
@@ -722,8 +722,6 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = _Other,
want_reply = WantReply}, Connection,
ConnectionPid, _) ->
- ?dbg(true, "ssh_msg ssh_msg_channel_request: Other=~p\n",
- [_Other]),
if WantReply == true ->
FailMsg = channel_failure_msg(ChannelId),
{{replies, [{connection_reply, ConnectionPid, FailMsg}]},
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 00b30e5434..9079089d5d 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. 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
@@ -637,16 +637,18 @@ init_ssh(client = Role, Vsn, Version, Options, Socket) ->
{ok, PeerAddr} = inet:peername(Socket),
PeerName = proplists:get_value(host, Options),
+ KeyCb = proplists:get_value(key_cb, Options, ssh_file),
#ssh{role = Role,
c_vsn = Vsn,
c_version = Version,
- key_cb = proplists:get_value(key_cb, Options, ssh_file),
+ key_cb = KeyCb,
io_cb = IOCb,
userauth_quiet_mode = proplists:get_value(quiet_mode, Options, false),
opts = Options,
userauth_supported_methods = AuthMethods,
- peer = {PeerName, PeerAddr}
+ peer = {PeerName, PeerAddr},
+ available_host_keys = supported_host_keys(Role, KeyCb, Options)
};
init_ssh(server = Role, Vsn, Version, Options, Socket) ->
@@ -654,17 +656,48 @@ init_ssh(server = Role, Vsn, Version, Options, Socket) ->
AuthMethods = proplists:get_value(auth_methods, Options,
?SUPPORTED_AUTH_METHODS),
{ok, PeerAddr} = inet:peername(Socket),
-
+ KeyCb = proplists:get_value(key_cb, Options, ssh_file),
+
#ssh{role = Role,
s_vsn = Vsn,
s_version = Version,
- key_cb = proplists:get_value(key_cb, Options, ssh_file),
+ key_cb = KeyCb,
io_cb = proplists:get_value(io_cb, Options, ssh_io),
opts = Options,
userauth_supported_methods = AuthMethods,
- peer = {undefined, PeerAddr}
+ peer = {undefined, PeerAddr},
+ available_host_keys = supported_host_keys(Role, KeyCb, Options)
}.
+supported_host_keys(client, _, _) ->
+ ["ssh-rsa", "ssh-dss"];
+supported_host_keys(server, KeyCb, Options) ->
+ lists:foldl(fun(Type, Acc) ->
+ case available_host_key(KeyCb, Type, Options) of
+ {error, _} ->
+ Acc;
+ Alg ->
+ [Alg | Acc]
+ end
+ end, [],
+ %% Prefered alg last so no need to reverse
+ ["ssh-dss", "ssh-rsa"]).
+
+available_host_key(KeyCb, "ssh-dss"= Alg, Opts) ->
+ case KeyCb:host_key('ssh-dss', Opts) of
+ {ok, _} ->
+ Alg;
+ Other ->
+ Other
+ end;
+available_host_key(KeyCb, "ssh-rsa" = Alg, Opts) ->
+ case KeyCb:host_key('ssh-rsa', Opts) of
+ {ok, _} ->
+ Alg;
+ Other ->
+ Other
+ end.
+
send_msg(Msg, #state{socket = Socket, transport_cb = Transport}) ->
Transport:send(Socket, Msg).
diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl
index 9bfd5270da..f729276e65 100644
--- a/lib/ssh/src/ssh_connection_manager.erl
+++ b/lib/ssh/src/ssh_connection_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. 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
@@ -144,7 +144,7 @@ adjust_window(ConnectionManager, Channel, Bytes) ->
cast(ConnectionManager, {adjust_window, Channel, Bytes}).
close(ConnectionManager, ChannelId) ->
- try call(ConnectionManager, {close, ChannelId}) of
+ try call(ConnectionManager, {close, ChannelId}) of
ok ->
ok;
{error, channel_closed} ->
@@ -604,6 +604,8 @@ call(Pid, Msg, Timeout) ->
exit:{timeout, _} ->
{error, timeout};
exit:{normal, _} ->
+ {error, channel_closed};
+ exit:{noproc,_} ->
{error, channel_closed}
end.
diff --git a/lib/ssh/src/ssh_dsa.erl b/lib/ssh/src/ssh_dsa.erl
deleted file mode 100644
index cb2632beac..0000000000
--- a/lib/ssh/src/ssh_dsa.erl
+++ /dev/null
@@ -1,95 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. 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
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Description: dsa public-key sign and verify
-
--module(ssh_dsa).
-
--export([verify/3]).
--export([sign/2]).
--export([alg_name/0]).
-
--include("ssh.hrl").
-
-%% start() ->
-%% crypto:start().
-
-%% sign_file(File, Opts) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:private_host_dsa_key(user, Opts),
-%% sign(Key, Bin).
-
-%% verify_file(File, Sig) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:public_host_key(user, dsa),
-%% verify(Key, Bin, Sig).
-
-sign(_Private=#ssh_key { private={P,Q,G,X} },Mb) ->
- K = ssh_bits:irandom(160) rem Q,
- R = ssh_math:ipow(G, K, P) rem Q,
- Ki = ssh_math:invert(K, Q),
- <<M:160/big-unsigned-integer>> = crypto:sha(Mb),
- S = (Ki * (M + X*R)) rem Q,
- <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>.
-
-
-%% the paramiko client sends a bad sig sometimes,
-%% instead of crashing, we nicely return error, the
-%% typcally manifests itself as Sb being 39 bytes
-%% instead of 40.
-
-verify(Public, Mb, Sb) ->
- case catch xverify(Public, Mb, Sb) of
- {'EXIT', _Reason} ->
- %store({Public, Mb, Sb, _Reason}),
- {error, inconsistent_key};
- ok ->
- %store({Public, Mb, Sb, ok})
- ok
- end.
-
-%% store(Term) ->
-%% {ok, Fd} = file:open("/tmp/dsa", [append]),
-%% io:format(Fd, "~p~n~n~n", [Term]),
-%% file:close(Fd).
-
-
-xverify(_Public=#ssh_key { public={P,Q,G,Y} },Mb,Sb) ->
- <<R0:160/big-unsigned-integer, S0:160/big-unsigned-integer>> = Sb,
- ?ssh_assert(R0 >= 0 andalso R0 < Q andalso
- S0 >= 0 andalso S0 < Q, out_of_range),
- W = ssh_math:invert(S0,Q),
- <<M0:160/big-unsigned-integer>> = crypto:sha(Mb),
- U1 = (M0*W) rem Q,
- U2 = (R0*W) rem Q,
- T1 = ssh_math:ipow(G,U1,P),
- T2 = ssh_math:ipow(Y,U2,P),
- V = ((T1*T2) rem P) rem Q,
- if V == R0 ->
- ok;
- true ->
- {error, inconsistent_key}
- end.
-
-alg_name() ->
- "ssh-dss".
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 12180f56bb..d05fa8e09a 100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. 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
@@ -23,80 +23,98 @@
-module(ssh_file).
--include("ssh.hrl").
--include("PKCS-1.hrl").
--include("DSS.hrl").
+-behaviour(ssh_key_api).
+-include_lib("public_key/include/public_key.hrl").
-include_lib("kernel/include/file.hrl").
--export([public_host_dsa_key/2,private_host_dsa_key/2,
- public_host_rsa_key/2,private_host_rsa_key/2,
- public_host_key/2,private_host_key/2,
- lookup_host_key/3, add_host_key/3, % del_host_key/2,
- lookup_user_key/3, ssh_dir/2, file_name/3]).
-
--export([private_identity_key/2,
- public_identity_key/2]).
-%% identity_keys/2]).
-
--export([encode_public_key/1, decode_public_key_v2/2]).
+-include("ssh.hrl").
--import(lists, [reverse/1, append/1]).
+-export([host_key/2,
+ user_key/2,
+ is_host_key/4,
+ add_host_key/3,
+ is_auth_key/4]).
--define(DBG_PATHS, true).
-define(PERM_700, 8#700).
-define(PERM_644, 8#644).
+
%% API
-public_host_dsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_dsa_key.pub", Opts),
- read_public_key_v2(File, "ssh-dss").
-
-private_host_dsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_dsa_key", Opts),
- read_private_key_v2(File, "ssh-dss").
-
-public_host_rsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_rsa_key.pub", Opts),
- read_public_key_v2(File, "ssh-rsa").
-
-private_host_rsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_rsa_key", Opts),
- read_private_key_v2(File, "ssh-rsa").
-
-public_host_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_key", Opts),
- case read_private_key_v1(File,public) of
- {error, enoent} ->
- read_public_key_v1(File++".pub");
- Result ->
- Result
- end.
-
-private_host_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_key", Opts),
- read_private_key_v1(File,private).
+%% Used by server
+host_key(Algorithm, Opts) ->
+ File = file_name(system, file_base_name(Algorithm), Opts),
+ %% We do not expect host keys to have pass phrases
+ %% so probably we could hardcod Password = ignore, but
+ %% we keep it as an undocumented option for now.
+ Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore),
+ decode(File, Password).
+is_auth_key(Key, User, Alg, Opts) ->
+ case lookup_user_key(Key, User, Alg, Opts) of
+ {ok, Key} ->
+ true;
+ _ ->
+ false
+ end.
-%% in: "host" out: "host,1.2.3.4.
-add_ip(Host) ->
- case inet:getaddr(Host, inet) of
- {ok, Addr} ->
- case ssh_connection:encode_ip(Addr) of
- false -> Host;
- IPString -> Host ++ "," ++ IPString
- end;
- _ -> Host
- end.
-replace_localhost("localhost") ->
- {ok, Hostname} = inet:gethostname(),
- Hostname;
-replace_localhost(Host) ->
- Host.
+%% Used by client
+is_host_key(Key, PeerName, Algorithm, Opts) ->
+ case lookup_host_key(PeerName, Algorithm, Opts) of
+ {ok, Key} ->
+ true;
+ _ ->
+ false
+ end.
+
+user_key(Algorithm, Opts) ->
+ File = file_name(user, identity_key_filename(Algorithm), Opts),
+ Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore),
+ decode(File, Password).
+
+
+%% Internal functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+file_base_name('ssh-rsa') ->
+ "ssh_host_rsa_key";
+file_base_name('ssh-dss') ->
+ "ssh_host_dsa_key";
+file_base_name(_) ->
+ "ssh_host_key".
+
+decode(File, Password) ->
+ try
+ {ok, decode_ssh_file(read_ssh_file(File), Password)}
+ catch
+ throw:Reason ->
+ {error, Reason};
+ error:Reason ->
+ {error, Reason}
+ end.
+
+read_ssh_file(File) ->
+ {ok, Bin} = file:read_file(File),
+ Bin.
+
+%% Public key
+decode_ssh_file(SshBin, public_key) ->
+ public_key:ssh_decode(SshBin, public_key);
+
+%% Private Key
+decode_ssh_file(Pem, Password) ->
+ case public_key:pem_decode(Pem) of
+ [{_, _, not_encrypted} = Entry] ->
+ public_key:pem_entry_decode(Entry);
+ [Entry] when Password =/= ignore ->
+ public_key:pem_entry_decode(Entry, Password);
+ _ ->
+ throw("No pass phrase provided for private key file")
+ end.
+
%% lookup_host_key
%% return {ok, Key(s)} or {error, not_found}
@@ -106,15 +124,6 @@ lookup_host_key(Host, Alg, Opts) ->
Host1 = replace_localhost(Host),
do_lookup_host_key(Host1, Alg, Opts).
-do_lookup_host_key(Host, Alg, Opts) ->
- case file:open(file_name(user, "known_hosts", Opts), [read]) of
- {ok, Fd} ->
- Res = lookup_host_key_fd(Fd, Host, Alg),
- file:close(Fd),
- Res;
- {error, enoent} -> {error, not_found};
- Error -> Error
- end.
add_host_key(Host, Key, Opts) ->
Host1 = add_ip(replace_localhost(Host)),
@@ -129,383 +138,16 @@ add_host_key(Host, Key, Opts) ->
Error
end.
-%% del_host_key(Host, Opts) ->
-%% Host1 = replace_localhost(Host),
-%% case file:open(file_name(user, "known_hosts", Opts),[write,read]) of
-%% {ok, Fd} ->
-%% Res = del_key_fd(Fd, Host1),
-%% file:close(Fd),
-%% Res;
-%% Error ->
-%% Error
-%% end.
-
-identity_key_filename("ssh-dss") -> "id_dsa";
-identity_key_filename("ssh-rsa") -> "id_rsa".
-
-private_identity_key(Alg, Opts) ->
- Path = file_name(user, identity_key_filename(Alg), Opts),
- read_private_key_v2(Path, Alg).
-
-public_identity_key(Alg, Opts) ->
- Path = file_name(user, identity_key_filename(Alg) ++ ".pub", Opts),
- read_public_key_v2(Path, Alg).
-
-
-read_public_key_v2(File, Type) ->
- case file:read_file(File) of
- {ok,Bin} ->
- List = binary_to_list(Bin),
- case lists:prefix(Type, List) of
- true ->
- List1 = lists:nthtail(length(Type), List),
- K_S = ssh_bits:b64_decode(List1),
- decode_public_key_v2(K_S, Type);
- false ->
- {error, bad_format}
- end;
- Error ->
- Error
- end.
-
-decode_public_key_v2(K_S, "ssh-rsa") ->
- case ssh_bits:decode(K_S,[string,mpint,mpint]) of
- ["ssh-rsa", E, N] ->
- {ok, #ssh_key { type = rsa,
- public = {N,E},
- comment=""}};
- _ ->
- {error, bad_format}
- end;
-decode_public_key_v2(K_S, "ssh-dss") ->
- case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
- ["ssh-dss",P,Q,G,Y] ->
- {ok,#ssh_key { type = dsa,
- public = {P,Q,G,Y}
- }};
- _A ->
- {error, bad_format}
- end;
-decode_public_key_v2(_, _) ->
- {error, bad_format}.
-
-
-read_public_key_v1(File) ->
- case file:read_file(File) of
- {ok,Bin} ->
- List = binary_to_list(Bin),
- case io_lib:fread("~d ~d ~d ~s", List) of
- {ok,[_Sz,E,N,Comment],_} ->
- {ok,#ssh_key { type = rsa,
- public ={N,E},
- comment = Comment }};
- _Error ->
- {error, bad_format}
- end;
- Error ->
- Error
- end.
-
-%% pem_type("ssh-dss") -> "DSA";
-%% pem_type("ssh-rsa") -> "RSA".
-
-read_private_key_v2(File, Type) ->
- case file:read_file(File) of
- {ok, PemBin} ->
- case catch (public_key:pem_decode(PemBin)) of
- [{_, Bin, not_encrypted}] ->
- decode_private_key_v2(Bin, Type);
- Error -> %% Note we do not handle password encrypted keys at the moment
- {error, Error}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-%% case file:read_file(File) of
-%% {ok,Bin} ->
-%% case read_pem(binary_to_list(Bin), pem_type(Type)) of
-%% {ok,Bin1} ->
-%% decode_private_key_v2(Bin1, Type);
-%% Error ->
-%% Error
-%% end;
-%% Error ->
-%% Error
-%% end.
-
-decode_private_key_v2(Private,"ssh-rsa") ->
- case 'PKCS-1':decode( 'RSAPrivateKey', Private) of
- {ok,RSA} -> %% FIXME Check for two-prime version
- {ok, #ssh_key { type = rsa,
- public = {RSA#'RSAPrivateKey'.modulus,
- RSA#'RSAPrivateKey'.publicExponent},
- private = {RSA#'RSAPrivateKey'.modulus,
- RSA#'RSAPrivateKey'.privateExponent}
- }};
- Error ->
- Error
- end;
-decode_private_key_v2(Private, "ssh-dss") ->
- case 'DSS':decode('DSAPrivateKey', Private) of
- {ok,DSA} -> %% FIXME Check for two-prime version
- {ok, #ssh_key { type = dsa,
- public = {DSA#'DSAPrivateKey'.p,
- DSA#'DSAPrivateKey'.q,
- DSA#'DSAPrivateKey'.g,
- DSA#'DSAPrivateKey'.y},
- private= {DSA#'DSAPrivateKey'.p,
- DSA#'DSAPrivateKey'.q,
- DSA#'DSAPrivateKey'.g,
- DSA#'DSAPrivateKey'.x}
- }};
- _ ->
- {error,bad_format}
- end.
-
-%% SSH1 private key format
-%% <<"SSH PRIVATE KEY FILE FORMATE 1.1\n" 0:8
-%% CipherNum:8, Reserved:32,
-%% NSz/uint32, N/bignum, E/bignum, Comment/string,
-%%
-%% [ R0:8 R1:8 R0:8 R1:8, D/bignum, IQMP/bignum, Q/bignum, P/bignum, Pad(8)]>>
-%%
-%% where [ ] is encrypted using des3 (ssh1 version) and
-%% a posssibly empty pass phrase using md5(passphase) as key
-%%
-
-read_private_key_v1(File, Type) ->
- case file:read_file(File) of
- {ok,<<"SSH PRIVATE KEY FILE FORMAT 1.1\n",0,
- CipherNum,_Resereved:32,Bin/binary>>} ->
- decode_private_key_v1(Bin, CipherNum,Type);
- {ok,_} ->
- {error, bad_format};
- Error ->
- Error
- end.
-
-decode_private_key_v1(Bin, CipherNum, Type) ->
- case ssh_bits:decode(Bin,0,[uint32, bignum, bignum, string]) of
- {Offset,[_NSz,N,E,Comment]} ->
- if Type == public ->
- {ok,#ssh_key { type=rsa,
- public={N,E},
- comment=Comment}};
- Type == private ->
- <<_:Offset/binary, Encrypted/binary>> = Bin,
- case ssh_bits:decode(decrypt1(Encrypted, CipherNum),0,
- [uint32, bignum, bignum,
- bignum, bignum,{pad,8}]) of
- {_,[_,D,IQMP,Q,P]} ->
- {ok,#ssh_key { type=rsa,
- public={N,E},
- private={D,IQMP,Q,P},
- comment=Comment}};
- _ ->
- {error,bad_format}
- end
- end;
- _ ->
- {error,bad_format}
- end.
-
-
-decrypt1(Bin, CipherNum) ->
- decrypt1(Bin, CipherNum,"").
-
-decrypt1(Bin, CipherNum, Phrase) ->
- if CipherNum == ?SSH_CIPHER_NONE; Phrase == "" ->
- Bin;
- CipherNum == ?SSH_CIPHER_3DES ->
- <<K1:8/binary, K2:8/binary>> = erlang:md5(Phrase),
- K3 = K1,
- IV = <<0,0,0,0,0,0,0,0>>,
- Bin1 = crypto:des_cbc_decrypt(K3,IV,Bin),
- Bin2 = crypto:des_cbc_encrypt(K2,IV,Bin1),
- crypto:des_cbc_decrypt(K1,IV,Bin2)
- end.
-
-%% encrypt1(Bin, CipherNum) ->
-%% encrypt1(Bin, CipherNum,"").
-
-%% encrypt1(Bin, CipherNum, Phrase) ->
-%% if CipherNum == ?SSH_CIPHER_NONE; Phrase == "" ->
-%% Bin;
-%% CipherNum == ?SSH_CIPHER_3DES ->
-%% <<K1:8/binary, K2:8/binary>> = erlang:md5(Phrase),
-%% K3 = K1,
-%% IV = <<0,0,0,0,0,0,0,0>>,
-%% Bin1 = crypto:des_cbc_encrypt(K1,IV,Bin),
-%% Bin2 = crypto:des_cbc_decrypt(K2,IV,Bin1),
-%% crypto:des_cbc_encrypt(K3,IV,Bin2)
-%% end.
-
-lookup_host_key_fd(Fd, Host, Alg) ->
- case io:get_line(Fd, '') of
- eof ->
- {error, not_found};
- Line ->
- case string:tokens(Line, " ") of
- [HostList, Alg, KeyData] ->
-%% io:format(" ~p lookup_host_key_fd: HostList ~p Alg ~p KeyData ~p\n",
-%% [Host, HostList, Alg, KeyData]),
- case lists:member(Host, string:tokens(HostList, ",")) of
- true ->
- decode_public_key_v2(ssh_bits:b64_decode(KeyData), Alg);
- false ->
- lookup_host_key_fd(Fd, Host, Alg)
- end;
- _ ->
- lookup_host_key_fd(Fd, Host, Alg)
- end
- end.
-
-
-
-%% del_key_fd(Fd, Host) ->
-%% del_key_fd(Fd, Host, 0, 0).
-
-%% del_key_fd(Fd, Host, ReadPos0, WritePos0) ->
-%% case io:get_line(Fd, '') of
-%% eof ->
-%% if ReadPos0 == WritePos0 ->
-%% ok;
-%% true ->
-%% file:truncate(Fd)
-%% end;
-%% Line ->
-%% {ok,ReadPos1} = file:position(Fd, cur),
-%% case string:tokens(Line, " ") of
-%% [HostList, _Type, _KeyData] ->
-%% case lists:member(Host, string:tokens(HostList, ",")) of
-%% true ->
-%% del_key_fd(Fd, Host, ReadPos1, WritePos0);
-%% false ->
-%% if ReadPos0 == WritePos0 ->
-%% del_key_fd(Fd, Host, ReadPos1, ReadPos1);
-%% true ->
-%% file:position(Fd, WritePos0),
-%% file:write(Fd, Line),
-%% {ok,WritePos1} = file:position(Fd,cur),
-%% del_key_fd(Fd, Host, ReadPos1, WritePos1)
-%% end
-%% end;
-%% _ ->
-%% if ReadPos0 == WritePos0 ->
-%% del_key_fd(Fd, Host, ReadPos1, ReadPos1);
-%% true ->
-%% file:position(Fd, WritePos0),
-%% file:write(Fd, Line),
-%% {ok,WritePos1} = file:position(Fd,cur),
-%% del_key_fd(Fd, Host, ReadPos1, WritePos1)
-%% end
-%% end
-%% end.
-
-
-add_key_fd(Fd, Host, Key) ->
- case Key#ssh_key.type of
- rsa ->
- {N,E} = Key#ssh_key.public,
- DK = ssh_bits:b64_encode(
- ssh_bits:encode(["ssh-rsa",E,N],
- [string,mpint,mpint])),
- file:write(Fd, [Host, " ssh-rsa ", DK, "\n"]);
- dsa ->
- {P,Q,G,Y} = Key#ssh_key.public,
- DK = ssh_bits:b64_encode(
- ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint])),
- file:write(Fd, [Host, " ssh-dss ", DK, "\n"])
- end.
-
-
-%% read_pem(Cs, Type) ->
-%% case read_line(Cs) of
-%% {"-----BEGIN "++Rest,Cs1} ->
-%% case string:tokens(Rest, " ") of
-%% [Type, "PRIVATE", "KEY-----"] ->
-%% read_pem64(Cs1, [], Type);
-%% _ ->
-%% {error, bad_format}
-%% end;
-%% {"",Cs1} when Cs1 =/= "" ->
-%% read_pem(Cs1,Type);
-%% {_,""} ->
-%% {error, bad_format}
-%% end.
-
-%% read_pem64(Cs, Acc, Type) ->
-%% case read_line(Cs) of
-%% {"-----END "++Rest,_Cs1} ->
-%% case string:tokens(Rest, " ") of
-%% [Type, "PRIVATE", "KEY-----"] ->
-%% {ok,ssh_bits:b64_decode(append(reverse(Acc)))};
-%% Toks ->
-%% error_logger:format("ssh: TOKENS=~p\n", [Toks]),
-%% {error, bad_format}
-%% end;
-%% {B64, Cs1} when Cs1 =/= "" ->
-%% read_pem64(Cs1, [B64|Acc], Type);
-%% _What ->
-%% {error, bad_format}
-%% end.
-
-
-%% read_line(Cs) -> read_line(Cs,[]).
-%% read_line([$\r,$\n|T], Acc) -> {reverse(Acc), T};
-%% read_line([$\n|T], Acc) -> {reverse(Acc), T};
-%% read_line([C|T], Acc) -> read_line(T,[C|Acc]);
-%% read_line([], Acc) -> {reverse(Acc),[]}.
-
-lookup_user_key(User, Alg, Opts) ->
+lookup_user_key(Key, User, Alg, Opts) ->
SshDir = ssh_dir({remoteuser,User}, Opts),
- case lookup_user_key_f(User, SshDir, Alg, "authorized_keys", Opts) of
+ case lookup_user_key_f(Key, User, SshDir, Alg, "authorized_keys", Opts) of
{ok, Key} ->
{ok, Key};
_ ->
- lookup_user_key_f(User, SshDir, Alg, "authorized_keys2", Opts)
- end.
-
-lookup_user_key_f(_User, [], _Alg, _F, _Opts) ->
- {error, nouserdir};
-lookup_user_key_f(_User, nouserdir, _Alg, _F, _Opts) ->
- {error, nouserdir};
-lookup_user_key_f(_User, Dir, Alg, F, _Opts) ->
- FileName = filename:join(Dir, F),
- case file:open(FileName, [read]) of
- {ok, Fd} ->
- Res = lookup_user_key_fd(Fd, Alg),
- file:close(Fd),
- Res;
- {error, Reason} ->
- {error, {{openerr, Reason}, {file, FileName}}}
- end.
-
-lookup_user_key_fd(Fd, Alg) ->
- case io:get_line(Fd, '') of
- eof ->
- {error, not_found};
- Line ->
- case string:tokens(Line, " ") of
- [Alg, KeyData, _] ->
- %% io:format("lookup_user_key_fd: HostList ~p Alg ~p KeyData ~p\n",
- %% [HostList, Alg, KeyData]),
- decode_public_key_v2(ssh_bits:b64_decode(KeyData), Alg);
- _Other ->
- %%?dbg(false, "key_fd Other: ~w ~w\n", [Alg, _Other]),
- lookup_user_key_fd(Fd, Alg)
- end
+ lookup_user_key_f(Key, User, SshDir, Alg, "authorized_keys2", Opts)
end.
-encode_public_key(#ssh_key{type = rsa, public = {N, E}}) ->
- ssh_bits:encode(["ssh-rsa",E,N],
- [string,mpint,mpint]);
-encode_public_key(#ssh_key{type = dsa, public = {P,Q,G,Y}}) ->
- ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint]).
-
%%
%% Utils
%%
@@ -537,11 +179,130 @@ ssh_dir(user, Opts) ->
ssh_dir(system, Opts) ->
proplists:get_value(system_dir, Opts, "/etc/ssh").
+
file_name(Type, Name, Opts) ->
FN = filename:join(ssh_dir(Type, Opts), Name),
- %%?dbg(?DBG_PATHS, "file_name: ~p\n", [FN]),
FN.
+
+
+%% in: "host" out: "host,1.2.3.4.
+add_ip(Host) ->
+ case inet:getaddr(Host, inet) of
+ {ok, Addr} ->
+ case ssh_connection:encode_ip(Addr) of
+ false -> Host;
+ IPString -> Host ++ "," ++ IPString
+ end;
+ _ -> Host
+ end.
+
+replace_localhost("localhost") ->
+ {ok, Hostname} = inet:gethostname(),
+ Hostname;
+replace_localhost(Host) ->
+ Host.
+
+do_lookup_host_key(Host, Alg, Opts) ->
+ case file:open(file_name(user, "known_hosts", Opts), [read, binary]) of
+ {ok, Fd} ->
+ Res = lookup_host_key_fd(Fd, Host, Alg),
+ file:close(Fd),
+ {ok, Res};
+ {error, enoent} -> {error, not_found};
+ Error -> Error
+ end.
+
+identity_key_filename("ssh-dss") ->
+ "id_dsa";
+identity_key_filename("ssh-rsa") ->
+ "id_rsa".
+
+identity_pass_phrase("ssh-dss") ->
+ dsa_pass_phrase;
+identity_pass_phrase('ssh-dss') ->
+ dsa_pass_phrase;
+identity_pass_phrase('ssh-rsa') ->
+ rsa_pass_phrase;
+identity_pass_phrase("ssh-rsa") ->
+ rsa_pass_phrase.
+
+lookup_host_key_fd(Fd, Host, KeyType) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ {error, not_found};
+ Line ->
+ case public_key:ssh_decode(Line, known_hosts) of
+ [{Key, Attributes}] ->
+ handle_host(Fd, Host, proplists:get_value(hostnames, Attributes), Key, KeyType);
+ [] ->
+ lookup_host_key_fd(Fd, Host, KeyType)
+ end
+ end.
+
+handle_host(Fd, Host, HostList, Key, KeyType) ->
+ Host1 = host_name(Host),
+ case lists:member(Host1, HostList) and key_match(Key, KeyType) of
+ true ->
+ Key;
+ false ->
+ lookup_host_key_fd(Fd, Host, KeyType)
+ end.
+
+host_name(Atom) when is_atom(Atom) ->
+ atom_to_list(Atom);
+host_name(List) ->
+ List.
+
+key_match(#'RSAPublicKey'{}, "ssh-rsa") ->
+ true;
+key_match({_, #'Dss-Parms'{}}, "ssh-dss") ->
+ true;
+key_match(_, _) ->
+ false.
+
+add_key_fd(Fd, Host,Key) ->
+ SshBin = public_key:ssh_encode([{Key, [{hostnames, [Host]}]}], known_hosts),
+ file:write(Fd, SshBin).
+
+lookup_user_key_f(_, _User, [], _Alg, _F, _Opts) ->
+ {error, nouserdir};
+lookup_user_key_f(_, _User, nouserdir, _Alg, _F, _Opts) ->
+ {error, nouserdir};
+lookup_user_key_f(Key, _User, Dir, _Alg, F, _Opts) ->
+ FileName = filename:join(Dir, F),
+ case file:open(FileName, [read, binary]) of
+ {ok, Fd} ->
+ Res = lookup_user_key_fd(Fd, Key),
+ file:close(Fd),
+ Res;
+ {error, Reason} ->
+ {error, {{openerr, Reason}, {file, FileName}}}
+ end.
+
+lookup_user_key_fd(Fd, Key) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ {error, not_found};
+ Line ->
+ case public_key:ssh_decode(Line, auth_keys) of
+ [{AuthKey, _}] ->
+ case is_auth_key(Key, AuthKey) of
+ true ->
+ {ok, Key};
+ false ->
+ lookup_user_key_fd(Fd, Key)
+ end;
+ [] ->
+ lookup_user_key_fd(Fd, Key)
+ end
+ end.
+
+is_auth_key(Key, Key) ->
+ true;
+is_auth_key(_,_) ->
+ false.
+
default_user_dir()->
{ok,[[Home|_]]} = init:get_argument(home),
UserDir = filename:join(Home, ".ssh"),
diff --git a/lib/ssh/src/ssh_key_api.erl b/lib/ssh/src/ssh_key_api.erl
new file mode 100644
index 0000000000..8085c12e21
--- /dev/null
+++ b/lib/ssh/src/ssh_key_api.erl
@@ -0,0 +1,45 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. 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
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ssh_key_api).
+
+-include_lib("public_key/include/public_key.hrl").
+-include("ssh.hrl").
+
+-type ssh_algorithm() :: string().
+-type file_error() :: file:posix() | badarg | system_limit | terminated.
+
+-callback host_key(Algorithm :: ssh_algorithm(), Options :: list()) ->
+ {ok, [{public_key(), Attributes::list()}]} | public_key()
+ | {error, string()}.
+
+-callback user_key(Algorithm :: ssh_algorithm(), Options :: list()) ->
+ {ok, [{public_key(), Attributes::list()}]} | public_key()
+ | {error, string()}.
+
+-callback is_host_key(Key :: public_key(), PeerName :: string(),
+ Algorithm :: ssh_algorithm(), Options :: list()) ->
+ boolean().
+
+-callback add_host_key(Host :: string(), Key :: public_key(), Options :: list()) ->
+ ok | {error, file_error()}.
+
+-callback is_auth_key(Key :: public_key(), User :: string(),
+ Algorithm :: ssh_algorithm(), Options :: list()) ->
+ boolean().
diff --git a/lib/ssh/src/ssh_rsa.erl b/lib/ssh/src/ssh_rsa.erl
deleted file mode 100644
index 77c411b09f..0000000000
--- a/lib/ssh/src/ssh_rsa.erl
+++ /dev/null
@@ -1,298 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. 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
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Description: rsa public-key sign and verify
-
--module(ssh_rsa).
-
--export([verify/3, sign/2]).
--export([alg_name/0]).
-
--include("ssh.hrl").
--include("PKCS-1.hrl").
-
-
--define(MGF(Seed,Len), mgf1((Seed),(Len))).
--define(HASH(X), crypto:sha((X))).
--define(HLen, 20).
-
-%% start() ->
-%% crypto:start().
-
-%% sign_file(File) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:private_host_rsa_key(user),
-%% sign(Key, Bin).
-
-%% verify_file(File, Sig) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:public_host_rsa_key(user),
-%% verify(Key, Bin, Sig).
-
-sign(Private,Mb) ->
- rsassa_pkcs1_v1_5_sign(Private,Mb).
-
-verify(Public,Mb,Sb) ->
- rsassa_pkcs1_v1_5_verify(Public,Mb,Sb).
-
-
-
-%% Integer to octet string
-i2osp(X, XLen) ->
- ssh_bits:i2bin(X, XLen).
-
-%% Octet string to Integer
-os2ip(X) ->
- ssh_bits:bin2i(X).
-
-%% decrypt1, M = message representative
-%% rsaep(#ssh_key { public={N,E}}, M) ->
-%% ?ssh_assert(M >= 0 andalso M =< N-1, out_of_range),
-%% ssh_math:ipow(M, E, N).
-
-%% encrypt1, C = cipher representative
-%% rsadp(#ssh_key { public={N,_}, private={_,D}}, C) ->
-%% ?ssh_assert(C >= 0 andalso C =< N-1, out_of_range),
-%% ssh_math:ipow(C, D, N).
-
-%% sign1, M = message representative
-rsasp1(#ssh_key { public={N,_}, private={_,D}}, M) ->
- ?ssh_assert((M >= 0 andalso M =< N-1), out_of_range),
- ssh_math:ipow(M, D, N).
-
-%% verify1, S =signature representative
-rsavp1(#ssh_key { public={N,E}}, S) ->
- ?ssh_assert(S >= 0 andalso S =< N-1, out_of_range),
- ssh_math:ipow(S, E, N).
-
-
-%% M messaage
-%% rsaes_oaep_encrypt(Public, M) ->
-%% rsaes_oaep_encrypt(Public, M, <<>>).
-
-%% rsaes_oaep_encrypt(Public=#ssh_key { public={N,_E}}, M, L) ->
-%% ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% MLen = size(M),
-%% %% LLen = size(L),
-%% ?ssh_assert(MLen =< K - 2*?HLen - 2, message_to_long),
-%% LHash = ?HASH(L),
-%% PS = ssh_bits:fill_bits(K - MLen - 2*?HLen - 2, 0),
-%% DB = <<LHash/binary, PS/binary, 16#01, M/binary>>,
-%% Seed = ssh_bits:random(?HLen),
-%% DbMask = ?MGF(Seed, K - ?HLen - 1),
-%% MaskedDB = ssh_bits:xor_bits(DB, DbMask),
-%% SeedMask = ?MGF(MaskedDB, ?HLen),
-%% MaskedSeed = ssh_bits:xor_bits(Seed, SeedMask),
-%% EM = <<16#00, MaskedSeed/binary, MaskedDB/binary>>,
-%% Mc = os2ip(EM),
-%% C = rsaep(Public, Mc),
-%% i2osp(C, K).
-
-%% rsaes_oaep_decrypt(Key, C) ->
-%% rsaes_oaep_decrypt(Key, C, <<>>).
-
-%% rsaes_oaep_decrypt(Private=#ssh_key { public={N,_},private={_,_}},Cb,L) ->
-%% ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% ?ssh_assert(K == 2*?HLen + 2, decryption_error),
-%% C = os2ip(Cb),
-%% M = rsadp(Private, C),
-%% EM = i2osp(M, K),
-%% LHash = ?HASH(L),
-%% MLen = K - ?HLen -1,
-%% case EM of
-%% <<16#00, MaskedSeed:?HLen/binary, MaskedDB:MLen>> ->
-%% SeedMask = ?MGF(MaskedDB, ?HLen),
-%% Seed = ssh_bits:xor_bits(MaskedSeed, SeedMask),
-%% DbMask = ?MGF(Seed, K - ?HLen - 1),
-%% DB = ssh_bits:xor_bits(MaskedDB, DbMask),
-%% PSLen = K - MLen - 2*?HLen - 2,
-%% case DB of
-%% <<LHash:?HLen, _PS:PSLen/binary, 16#01, M/binary>> ->
-%% M;
-%% _ ->
-%% exit(decryption_error)
-%% end;
-%% _ ->
-%% exit(decryption_error)
-%% end.
-
-
-%% rsaes_pkcs1_v1_5_encrypt(Public=#ssh_key { public={N,_}}, M) ->
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% MLen = size(M),
-%% ?ssh_assert(MLen =< K - 11, message_to_long),
-%% PS = ssh_bits:random(K - MLen - 3),
-%% EM = <<16#00,16#02,PS/binary,16#00,M/binary>>,
-%% Mc = os2ip(EM),
-%% C = rsaep(Public, Mc),
-%% i2osp(C, K).
-
-
-%% rsaes_pkcs1_v1_5_decrypt(Private=#ssh_key { public={N,_},private={_,_}},
-%% Cb) ->
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% CLen = size(Cb),
-%% ?ssh_assert(CLen == K andalso K >= 11, decryption_error),
-%% C = os2ip(Cb),
-%% M = rsadp(Private, C),
-%% EM = i2osp(M, K),
-%% PSLen = K - CLen - 3,
-%% case EM of
-%% <<16#00, 16#02, _PS:PSLen/binary, 16#00, M>> ->
-%% M;
-%% _ ->
-%% exit(decryption_error)
-%% end.
-
-%% rsassa_pss_sign(Private=#ssh_key { public={N,_},private={_,_}},Mb) ->
-%% ModBits = ssh_bits:isize(N),
-%% K = (ModBits+7) div 8,
-%% EM = emsa_pss_encode(Mb, ModBits - 1),
-%% M = os2ip(EM),
-%% S = rsasp1(Private, M),
-%% i2osp(S, K).
-
-%% rsassa_pss_verify(Public=#ssh_key { public={N,_E}},Mb,Sb) ->
-%% ModBits = ssh_bits:isize(N),
-%% K = (ModBits+7) div 8,
-%% ?ssh_assert(size(Sb) == K, invalid_signature),
-%% S = os2ip(Sb),
-%% M = rsavp1(Public,S),
-%% EMLen = (ModBits-1+7) div 8,
-%% EM = i2osp(M, EMLen),
-%% emsa_pss_verify(Mb, EM, ModBits-1).
-
-
-rsassa_pkcs1_v1_5_sign(Private=#ssh_key { public={N,_},private={_,_D}},Mb) ->
- K = (ssh_bits:isize(N)+7) div 8,
- EM = emsa_pkcs1_v1_5_encode(Mb, K),
- M = os2ip(EM),
- S = rsasp1(Private, M),
- i2osp(S, K).
-
-rsassa_pkcs1_v1_5_verify(Public=#ssh_key { public={N,_E}}, Mb, Sb) ->
- K = (ssh_bits:isize(N)+7) div 8,
- ?ssh_assert(size(Sb) == K, invalid_signature),
- S = os2ip(Sb),
- M = rsavp1(Public, S),
- EM = i2osp(M, K),
- %?dbg(true, "verify K=~p S=~w ~n#M=~w~n#EM=~w~n", [K, S, M, EM]),
- case emsa_pkcs1_v1_5_encode(Mb, K) of
- EM -> ok;
- _S ->
- {error, invalid_signature}
- end.
-
-
-emsa_pkcs1_v1_5_encode(M, EMLen) ->
- H = ?HASH(M),
- %% Must use speical xxNull types here!
- Alg = #'AlgorithmNull' { algorithm = ?'id-sha1',
- parameters = <<>> },
- {ok,TCode} = 'PKCS-1':encode('DigestInfoNull',
- #'DigestInfoNull'{ digestAlgorithm = Alg,
- digest = H }),
- T = list_to_binary(TCode),
- TLen = size(T),
- ?ssh_assert(EMLen >= TLen + 11, message_to_short),
- PS = ssh_bits:fill_bits(EMLen - TLen - 3, 16#ff),
- <<16#00, 16#01, PS/binary, 16#00, T/binary>>.
-
-
-%% emsa_pss_encode(M, EMBits) ->
-%% emsa_pss_encode(M, EMBits, 0).
-
-%% emsa_pss_encode(M, EMBits, SLen) ->
-%% ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
-%% EMLen = (EMBits + 7) div 8,
-%% MHash = ?HASH(M),
-%% ?ssh_assert(EMLen >= ?HLen + SLen + 2, encoding_error),
-%% Salt = ssh_bits:random(SLen),
-%% M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
-%% MHash, Salt],
-%% H = ?HASH(M1),
-%% PS = ssh_bits:fill_bits(EMLen-SLen-?HLen-2, 0),
-%% DB = <<PS/binary, 16#01, Salt/binary>>,
-%% DbMask = ?MGF(H, EMLen - ?HLen -1),
-%% MaskedDB = ssh_bits:xor_bits(DB, DbMask),
-%% ZLen = 8*EMLen - EMBits,
-%% NZLen = (8 - (ZLen rem 8)) rem 8,
-%% <<_:ZLen, NZ:NZLen, MaskedDB1/binary>> = MaskedDB,
-%% MaskedDB2 = <<0:ZLen, NZ:NZLen, MaskedDB1/binary>>,
-%% <<MaskedDB2/binary, H/binary, 16#BC>>.
-
-
-%% emsa_pss_verify(M, EM, EMBits) ->
-%% emsa_pss_verify(M, EM, EMBits, 0).
-
-%% emsa_pss_verify(M, EM, EMBits, SLen) ->
-%% ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
-%% EMLen = (EMBits + 7) div 8,
-%% MHash = ?HASH(M),
-%% ?ssh_assert(EMLen >= ?HLen + SLen + 2, inconsistent),
-%% MaskLen = (EMLen - ?HLen - 1)-1,
-%% ZLen = 8*EMLen - EMBits,
-%% NZLen = (8 - (ZLen rem 8)) rem 8,
-%% case EM of
-%% <<0:ZLen,Nz:NZLen,MaskedDB1:MaskLen/binary, H:?HLen/binary, 16#BC>> ->
-%% MaskedDB = <<0:ZLen,Nz:NZLen,MaskedDB1/binary>>,
-%% DbMask = ?MGF(H, EMLen - ?HLen - 1),
-%% DB = ssh_bits:xor_bits(MaskedDB, DbMask),
-%% PSLen1 = (EMLen - SLen - ?HLen - 2) - 1,
-%% PS = ssh_bits:fill_bits(PSLen1, 0),
-%% case DB of
-%% <<_:ZLen,0:NZLen,PS:PSLen1/binary,16#01,Salt:SLen/binary>> ->
-%% M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
-%% MHash, Salt],
-%% case ?HASH(M1) of
-%% H -> ok;
-%% _ -> exit(inconsistent)
-%% end;
-%% _ ->
-%% exit(inconsistent)
-%% end;
-%% _ ->
-%% exit(inconsistent)
-%% end.
-
-
-
-%% Mask generating function MGF1
-%% mgf1(MGFSeed, MaskLen) ->
-%% T = mgf1_loop(0, ((MaskLen + ?HLen -1) div ?HLen) - 1, MGFSeed, ""),
-%% <<R:MaskLen/binary, _/binary>> = T,
-%% R.
-
-%% mgf1_loop(Counter, N, _, T) when Counter > N ->
-%% list_to_binary(T);
-%% mgf1_loop(Counter, N, MGFSeed, T) ->
-%% C = i2osp(Counter, 4),
-%% mgf1_loop(Counter+1, N, MGFSeed, [T, ?HASH([MGFSeed, C])]).
-
-
-
-
-alg_name() ->
- "ssh-rsa".
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index da91817fd7..8cc414f83a 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. 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
@@ -231,8 +231,6 @@ handle_op(?SSH_FXP_REALPATH, ReqId,
case Res of
{ok, AbsPath} ->
NewAbsPath = chroot_filename(AbsPath, State),
- ?dbg(true, "handle_op ?SSH_FXP_REALPATH: RelPath=~p AbsPath=~p\n",
- [RelPath, NewAbsPath]),
XF = State#state.xf,
Attr = #ssh_xfer_attr{type=directory},
ssh_xfer:xf_send_name(XF, ReqId, NewAbsPath, Attr),
@@ -463,7 +461,6 @@ get_handle(Handles, BinHandle) ->
read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_state = FS0},
XF, ReqId, Handle, RelPath, {cache, Files}) ->
AbsPath = relate_file_name(RelPath, State0),
- ?dbg(true, "read_dir: AbsPath=~p\n", [AbsPath]),
if
length(Files) > MaxLength ->
{ToSend, NewCache} = lists:split(MaxLength, Files),
@@ -484,7 +481,6 @@ read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_sta
read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_state = FS0},
XF, ReqId, Handle, RelPath, _Status) ->
AbsPath = relate_file_name(RelPath, State0),
- ?dbg(true, "read_dir: AbsPath=~p\n", [AbsPath]),
{Res, FS1} = FileMod:list_dir(AbsPath, FS0),
case Res of
{ok, Files} when MaxLength == 0 orelse MaxLength > length(Files) ->
@@ -516,7 +512,6 @@ get_attrs(_RelPath, [], _FileMod, FS, Acc) ->
{lists:reverse(Acc), FS};
get_attrs(RelPath, [F | Rest], FileMod, FS0, Acc) ->
Path = filename:absname(F, RelPath),
- ?dbg(true, "get_attrs fun: F=~p\n", [F]),
case FileMod:read_link_info(Path, FS0) of
{{ok, Info}, FS1} ->
Attrs = ssh_sftp:info_to_attr(Info),
@@ -560,7 +555,6 @@ stat(ReqId, RelPath, State0=#state{file_handler=FileMod,
file_state=FS0}, F) ->
AbsPath = relate_file_name(RelPath, State0),
XF = State0#state.xf,
- ?dbg(false, "stat: AbsPath=~p\n", [AbsPath]),
{Res, FS1} = FileMod:F(AbsPath, FS0),
State1 = State0#state{file_state = FS1},
case Res of
@@ -605,6 +599,8 @@ decode_4_access_flag(add_subdirectory) ->
[read];
decode_4_access_flag(append_data) ->
[append];
+decode_4_access_flag(write_attributes) ->
+ [write];
decode_4_access_flag(_) ->
[read].
@@ -619,8 +615,7 @@ open(Vsn, ReqId, Data, State) when Vsn =< 3 ->
<<?UINT32(BLen), BPath:BLen/binary, ?UINT32(PFlags),
_Attrs/binary>> = Data,
Path = binary_to_list(BPath),
- Flags = ssh_xfer:decode_open_flags(Vsn, PFlags) -- [creat, excl, trunc],
- ?dbg(true, "open: Flags=~p\n", [Flags]),
+ Flags = ssh_xfer:decode_open_flags(Vsn, PFlags),
do_open(ReqId, State, Path, Flags);
open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
<<?UINT32(BLen), BPath:BLen/binary, ?UINT32(Access),
@@ -628,7 +623,6 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
Path = binary_to_list(BPath),
FlagBits = ssh_xfer:decode_open_flags(Vsn, PFlags),
AcessBits = ssh_xfer:decode_ace_mask(Access),
- ?dbg(true, "open: Fl=~p\n", [FlagBits]),
%% TODO: This is to make sure the Access flags are not ignored
%% but this should be thought through better. This solution should
%% be considered a hack in order to buy some time. At least
@@ -638,15 +632,12 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
AcessFlags = decode_4_acess(AcessBits),
Flags = lists:append(lists:umerge(
[[decode_4_flags(FlagBits)] | AcessFlags])),
-
- ?dbg(true, "open: Flags=~p\n", [Flags]),
-
do_open(ReqId, State, Path, Flags).
do_open(ReqId, State0, Path, Flags) ->
#state{file_handler = FileMod, file_state = FS0, root = Root} = State0,
XF = State0#state.xf,
- F = [raw, binary | Flags],
+ F = [binary | Flags],
%% case FileMod:is_dir(Path) of %% This is version 6 we still have 5
%% true ->
%% ssh_xfer:xf_send_status(State#state.xf, ReqId,
@@ -895,14 +886,11 @@ set_stat(Attr, Path,
State0 = #state{file_handler=FileMod, file_state=FS0}) ->
{DecodedAttr, _Rest} =
ssh_xfer:decode_ATTR((State0#state.xf)#ssh_xfer.vsn, Attr),
- ?dbg(true, "set_stat DecodedAttr=~p\n", [DecodedAttr]),
Info = ssh_sftp:attr_to_info(DecodedAttr),
{Res1, FS1} = FileMod:read_link_info(Path, FS0),
case Res1 of
{ok, OldInfo} ->
NewInfo = set_file_info(Info, OldInfo),
- ?dbg(true, "set_stat Path=~p\nInfo=~p\nOldInfo=~p\nNewInfo=~p\n",
- [Path, Info, OldInfo, NewInfo]),
{Res2, FS2} = FileMod:write_file_info(Path, NewInfo, FS1),
State1 = State0#state{file_state = FS2},
{Res2, State1};
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index de3e29e2f1..6140c87f6e 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. 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
@@ -23,10 +23,11 @@
-module(ssh_transport).
--include("ssh_transport.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/inet.hrl").
+-include("ssh_transport.hrl").
-include("ssh.hrl").
--include_lib("kernel/include/inet.hrl").
-export([connect/5, accept/4]).
-export([versions/2, hello_version_msg/1]).
@@ -38,17 +39,8 @@
handle_kex_dh_gex_group/2, handle_kex_dh_gex_reply/2,
handle_new_keys/2, handle_kex_dh_gex_request/2,
handle_kexdh_reply/2,
- unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1]).
-
-%% debug flagso
--define(DBG_ALG, true).
--define(DBG_KEX, true).
--define(DBG_CRYPTO, false).
--define(DBG_PACKET, false).
--define(DBG_MESSAGE, true).
--define(DBG_BIN_MESSAGE, true).
--define(DBG_MAC, false).
--define(DBG_ZLIB, true).
+ unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1,
+ sign/3, verify/4]).
versions(client, Options)->
Vsn = proplists:get_value(vsn, Options, ?DEFAULT_CLIENT_VERSION),
@@ -212,24 +204,24 @@ key_exchange_init_msg(Ssh0) ->
{SshPacket, Ssh} = ssh_packet(Msg, Ssh0),
{Msg, SshPacket, Ssh}.
-kex_init(#ssh{role = Role, opts = Opts}) ->
+kex_init(#ssh{role = Role, opts = Opts, available_host_keys = HostKeyAlgs}) ->
Random = ssh_bits:random(16),
Compression = case proplists:get_value(compression, Opts, none) of
zlib -> ["zlib", "none"];
none -> ["none", "zlib"]
end,
- kexinit_messsage(Role, Random, Compression).
+ kexinit_messsage(Role, Random, Compression, HostKeyAlgs).
key_init(client, Ssh, Value) ->
Ssh#ssh{c_keyinit = Value};
key_init(server, Ssh, Value) ->
Ssh#ssh{s_keyinit = Value}.
-kexinit_messsage(client, Random, Compression) ->
+kexinit_messsage(client, Random, Compression, HostKeyAlgs) ->
#ssh_msg_kexinit{
cookie = Random,
kex_algorithms = ["diffie-hellman-group1-sha1"],
- server_host_key_algorithms = ["ssh-rsa", "ssh-dss"],
+ server_host_key_algorithms = HostKeyAlgs,
encryption_algorithms_client_to_server = ["aes128-cbc","3des-cbc"],
encryption_algorithms_server_to_client = ["aes128-cbc","3des-cbc"],
mac_algorithms_client_to_server = ["hmac-sha1"],
@@ -240,11 +232,11 @@ kexinit_messsage(client, Random, Compression) ->
languages_server_to_client = []
};
-kexinit_messsage(server, Random, Compression) ->
+kexinit_messsage(server, Random, Compression, HostKeyAlgs) ->
#ssh_msg_kexinit{
cookie = Random,
kex_algorithms = ["diffie-hellman-group1-sha1"],
- server_host_key_algorithms = ["ssh-dss"],
+ server_host_key_algorithms = HostKeyAlgs,
encryption_algorithms_client_to_server = ["aes128-cbc","3des-cbc"],
encryption_algorithms_server_to_client = ["aes128-cbc","3des-cbc"],
mac_algorithms_client_to_server = ["hmac-sha1"],
@@ -300,7 +292,6 @@ install_messages('diffie-hellman-group-exchange-sha1') ->
key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) ->
{G, P} = dh_group1(),
{Private, Public} = dh_gen_key(G, P, 1024),
- %%?dbg(?DBG_KEX, "public: ~p~n", [Public]),
{SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_init{e = Public}, Ssh0),
{ok, SshPacket,
Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}};
@@ -320,7 +311,6 @@ key_exchange_first_msg('diffie-hellman-group-exchange-sha1', Ssh0) ->
handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
{G, P} = dh_group1(),
{Private, Public} = dh_gen_key(G, P, 1024),
- %%?dbg(?DBG_KEX, "public: ~p~n", [Public]),
K = ssh_math:ipow(E, Private, P),
{Key, K_S} = get_host_key(Ssh0),
H = kex_h(Ssh0, K_S, E, Public, K),
@@ -329,8 +319,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
f = Public,
h_sig = H_SIG
}, Ssh0),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
{ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}},
shared_secret = K,
exchanged_hash = H,
@@ -338,7 +327,6 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) ->
{Private, Public} = dh_gen_key(G,P,1024),
- %%?dbg(?DBG_KEX, "public: ~p ~n", [Public]),
{SshPacket, Ssh1} =
ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0),
{ok, SshPacket,
@@ -362,8 +350,7 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F,
#ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) ->
K = ssh_math:ipow(F, Private, P),
H = kex_h(Ssh0, HostKey, Public, F, K),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
case verify_host_key(Ssh0, HostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
@@ -396,8 +383,7 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey,
Ssh0) ->
K = ssh_math:ipow(F, Private, P),
H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
case verify_host_key(Ssh0, HostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
@@ -423,83 +409,68 @@ sid(#ssh{session_id = Id}, _) ->
%%
get_host_key(SSH) ->
#ssh{key_cb = Mod, opts = Opts, algorithms = ALG} = SSH,
- Scope = proplists:get_value(key_scope, Opts, system),
- case ALG#alg.hkey of
- 'ssh-rsa' ->
- case Mod:private_host_rsa_key(Scope, Opts) of
- {ok,Key=#ssh_key { public={N,E}} } ->
- %%?dbg(true, "x~n", []),
- {Key,
- ssh_bits:encode(["ssh-rsa",E,N],[string,mpint,mpint])};
- Error ->
- %%?dbg(true, "y~n", []),
- exit(Error)
- end;
- 'ssh-dss' ->
- case Mod:private_host_dsa_key(Scope, Opts) of
- {ok,Key=#ssh_key { public={P,Q,G,Y}}} ->
- {Key, ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint])};
- Error ->
- exit(Error)
- end;
- _ ->
- exit({error, bad_key_type})
+
+ case Mod:host_key(ALG#alg.hkey, Opts) of
+ {ok, #'RSAPrivateKey'{modulus = N, publicExponent = E} = Key} ->
+ {Key,
+ ssh_bits:encode(["ssh-rsa",E,N],[string,mpint,mpint])};
+ {ok, #'DSAPrivateKey'{y = Y, p = P, q = Q, g = G} = Key} ->
+ {Key, ssh_bits:encode(["ssh-dss",P,Q,G,Y],
+ [string,mpint,mpint,mpint,mpint])};
+ Result ->
+ exit({error, {Result, unsupported_key_type}})
end.
-sign_host_key(Ssh, Private, H) ->
- ALG = Ssh#ssh.algorithms,
- Module = case ALG#alg.hkey of
- 'ssh-rsa' ->
- ssh_rsa;
- 'ssh-dss' ->
- ssh_dsa
- end,
- case catch Module:sign(Private, H) of
- {'EXIT', Reason} ->
- error_logger:format("SIGN FAILED: ~p\n", [Reason]),
- {error, Reason};
- SIG ->
- ssh_bits:encode([Module:alg_name() ,SIG],[string,binary])
- end.
+sign_host_key(_Ssh, #'RSAPrivateKey'{} = Private, H) ->
+ Hash = sha, %% Option ?!
+ Signature = sign(H, Hash, Private),
+ ssh_bits:encode(["ssh-rsa", Signature],[string, binary]);
+sign_host_key(_Ssh, #'DSAPrivateKey'{} = Private, H) ->
+ Hash = sha, %% Option ?!
+ RawSignature = sign(H, Hash, Private),
+ ssh_bits:encode(["ssh-dss", RawSignature],[string, binary]).
verify_host_key(SSH, K_S, H, H_SIG) ->
ALG = SSH#ssh.algorithms,
case ALG#alg.hkey of
'ssh-rsa' ->
- case ssh_bits:decode(K_S,[string,mpint,mpint]) of
- ["ssh-rsa", E, N] ->
- ["ssh-rsa",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
- Public = #ssh_key { type=rsa, public={N,E} },
- case catch ssh_rsa:verify(Public, H, SIG) of
- {'EXIT', Reason} ->
- error_logger:format("VERIFY FAILED: ~p\n", [Reason]),
- {error, bad_signature};
- ok ->
- known_host_key(SSH, Public, "ssh-rsa")
- end;
- _ ->
- {error, bad_format}
- end;
+ verify_host_key_rsa(SSH, K_S, H, H_SIG);
'ssh-dss' ->
- case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
- ["ssh-dss",P,Q,G,Y] ->
- ["ssh-dss",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
- Public = #ssh_key { type=dsa, public={P,Q,G,Y} },
- case catch ssh_dsa:verify(Public, H, SIG) of
- {'EXIT', Reason} ->
- error_logger:format("VERIFY FAILED: ~p\n", [Reason]),
- {error, bad_signature};
- ok ->
- known_host_key(SSH, Public, "ssh-dss")
- end;
- _ ->
- {error, bad_host_key_format}
- end;
+ verify_host_key_dss(SSH, K_S, H, H_SIG);
_ ->
{error, bad_host_key_algorithm}
end.
+verify_host_key_rsa(SSH, K_S, H, H_SIG) ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint]) of
+ ["ssh-rsa", E, N] ->
+ ["ssh-rsa",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
+ Public = #'RSAPublicKey'{publicExponent = E, modulus = N},
+ case verify(H, sha, SIG, Public) of
+ false ->
+ {error, bad_signature};
+ true ->
+ known_host_key(SSH, Public, "ssh-rsa")
+ end;
+ _ ->
+ {error, bad_format}
+ end.
+
+verify_host_key_dss(SSH, K_S, H, H_SIG) ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
+ ["ssh-dss",P,Q,G,Y] ->
+ ["ssh-dss",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
+ Public = {Y, #'Dss-Parms'{p = P, q = Q, g = G}},
+ case verify(H, sha, SIG, Public) of
+ false ->
+ {error, bad_signature};
+ true ->
+ known_host_key(SSH, Public, "ssh-dss")
+ end;
+ _ ->
+ {error, bad_host_key_format}
+ end.
+
accepted_host(Ssh, PeerName, Opts) ->
case proplists:get_value(silently_accept_hosts, Opts, false) of
true ->
@@ -511,14 +482,10 @@ accepted_host(Ssh, PeerName, Opts) ->
known_host_key(#ssh{opts = Opts, key_cb = Mod, peer = Peer} = Ssh,
Public, Alg) ->
PeerName = peer_name(Peer),
- case Mod:lookup_host_key(PeerName, Alg, Opts) of
- {ok, Public} ->
+ case Mod:is_host_key(Public, PeerName, Alg, Opts) of
+ true ->
ok;
- {ok, BadPublic} ->
- error_logger:format("known_host_key: Public ~p BadPublic ~p\n",
- [Public, BadPublic]),
- {error, bad_public_key};
- {error, not_found} ->
+ false ->
case accepted_host(Ssh, PeerName, Opts) of
yes ->
Mod:add_host_key(PeerName, Public, Opts);
@@ -621,7 +588,6 @@ install_alg(SSH) ->
alg_setup(SSH) ->
ALG = SSH#ssh.algorithms,
- %%?dbg(?DBG_ALG, "ALG: setup ~p ~n", [ALG]),
SSH#ssh{kex = ALG#alg.kex,
hkey = ALG#alg.hkey,
encrypt = ALG#alg.encrypt,
@@ -638,7 +604,6 @@ alg_setup(SSH) ->
}.
alg_init(SSH0) ->
- %%?dbg(?DBG_ALG, "ALG: init~n", []),
{ok,SSH1} = send_mac_init(SSH0),
{ok,SSH2} = recv_mac_init(SSH1),
{ok,SSH3} = encrypt_init(SSH2),
@@ -648,7 +613,6 @@ alg_init(SSH0) ->
SSH6.
alg_final(SSH0) ->
- %%?dbg(?DBG_ALG, "ALG: final ~n", []),
{ok,SSH1} = send_mac_final(SSH0),
{ok,SSH2} = recv_mac_final(SSH1),
{ok,SSH3} = encrypt_final(SSH2),
@@ -669,19 +633,15 @@ select(CL, SL) ->
[] -> undefined;
[ALG|_] -> ALG
end,
- %%?dbg(?DBG_ALG, "ALG: select: ~p ~p = ~p~n", [CL, SL, C]),
C.
ssh_packet(#ssh_msg_kexinit{} = Msg, Ssh0) ->
BinMsg = ssh_bits:encode(Msg),
Ssh = key_init(Ssh0#ssh.role, Ssh0, BinMsg),
- %%?dbg(?DBG_MESSAGE, "SEND_MSG: ~p~n", [Msg]),
pack(BinMsg, Ssh);
ssh_packet(Msg, Ssh) ->
BinMsg = ssh_bits:encode(Msg),
- %%?dbg(?DBG_MESSAGE, "SEND_MSG: ~p~n", [Msg]),
- %%?dbg(?DBG_BIN_MESSAGE, "Encoded: ~p~n", [BinMsg]),
pack(BinMsg, Ssh).
pack(Data0, #ssh{encrypt_block_size = BlockSize,
@@ -732,17 +692,20 @@ msg_data(PacketData) ->
_:PaddingLen/binary>> = PacketData,
Data.
+sign(SigData, Hash, #'DSAPrivateKey'{} = Key) ->
+ DerSignature = public_key:sign(SigData, Hash, Key),
+ #'Dss-Sig-Value'{r = R, s = S} = public_key:der_decode('Dss-Sig-Value', DerSignature),
+ <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>;
+sign(SigData, Hash, Key) ->
+ public_key:sign(SigData, Hash, Key).
-%% Send a disconnect message
-%% terminate(S, SSH, Code, Message) ->
-%% M = #ssh_msg_disconnect{code=Code,
-%% description = Message,
-%% language = "en"},
-%% send_msg(S, SSH, M),
-%% gen_tcp:close(S),
-%% {error, M}.
+verify(PlainText, Hash, Sig, {_, #'Dss-Parms'{}} = Key) ->
+ <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>> = Sig,
+ Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}),
+ public_key:verify(PlainText, Hash, Signature, Key);
+verify(PlainText, Hash, Sig, Key) ->
+ public_key:verify(PlainText, Hash, Sig, Key).
-
%% public key algorithms
%%
%% ssh-dss REQUIRED sign Raw DSS Key
@@ -761,9 +724,6 @@ msg_data(PacketData) ->
%%
%%
-
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Encryption
%%
@@ -833,19 +793,13 @@ encrypt(#ssh{encrypt = none} = Ssh, Data) ->
encrypt(#ssh{encrypt = '3des-cbc',
encrypt_keys = {K1,K2,K3},
encrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "encrypt: IV=~p K1=~p, K2=~p, K3=~p ~n",
- %% [IV0,K1,K2,K3]),
Enc = crypto:des3_cbc_encrypt(K1,K2,K3,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "encrypt: ~p -> ~p ~n", [Data, Enc]),
IV = crypto:des_cbc_ivec(Enc),
{Ssh#ssh{encrypt_ctx = IV}, Enc};
encrypt(#ssh{encrypt = 'aes128-cbc',
encrypt_keys = K,
encrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "encrypt: IV=~p K=~p ~n",
- %% [IV0,K]),
Enc = crypto:aes_cbc_128_encrypt(K,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "encrypt: ~p -> ~p ~n", [Data, Enc]),
IV = crypto:aes_cbc_ivec(Enc),
{Ssh#ssh{encrypt_ctx = IV}, Enc}.
@@ -893,18 +847,12 @@ decrypt(#ssh{decrypt = none} = Ssh, Data) ->
decrypt(#ssh{decrypt = '3des-cbc', decrypt_keys = Keys,
decrypt_ctx = IV0} = Ssh, Data) ->
{K1, K2, K3} = Keys,
- %%?dbg(?DBG_CRYPTO, "decrypt: IV=~p K1=~p, K2=~p, K3=~p ~n",
- %%[IV0,K1,K2,K3]),
Dec = crypto:des3_cbc_decrypt(K1,K2,K3,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "decrypt: ~p -> ~p ~n", [Data, Dec]),
IV = crypto:des_cbc_ivec(Data),
{Ssh#ssh{decrypt_ctx = IV}, Dec};
decrypt(#ssh{decrypt = 'aes128-cbc', decrypt_keys = Key,
decrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "decrypt: IV=~p Key=~p ~n",
- %% [IV0,Key]),
Dec = crypto:aes_cbc_128_decrypt(Key,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "decrypt: ~p -> ~p ~n", [Data, Dec]),
IV = crypto:aes_cbc_ivec(Data),
{Ssh#ssh{decrypt_ctx = IV}, Dec}.
@@ -936,7 +884,6 @@ compress(#ssh{compress = none} = Ssh, Data) ->
{Ssh, Data};
compress(#ssh{compress = zlib, compress_ctx = Context} = Ssh, Data) ->
Compressed = zlib:deflate(Context, Data, sync),
- %%?dbg(?DBG_ZLIB, "deflate: ~p -> ~p ~n", [Data, Compressed]),
{Ssh, list_to_binary(Compressed)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -960,7 +907,6 @@ decompress(#ssh{decompress = none} = Ssh, Data) ->
{Ssh, Data};
decompress(#ssh{decompress = zlib, decompress_ctx = Context} = Ssh, Data) ->
Decompressed = zlib:inflate(Context, Data),
- %%?dbg(?DBG_ZLIB, "inflate: ~p -> ~p ~n", [Data, Decompressed]),
{Ssh, list_to_binary(Decompressed)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1039,7 +985,6 @@ hash(SSH, Char, N, HASH) ->
K1 = HASH([K, H, Char, SessionID]),
Sz = N div 8,
<<Key:Sz/binary, _/binary>> = hash(K, H, K1, N-128, HASH),
- %%?dbg(?DBG_KEX, "Key ~s: ~s ~n", [Char, fmt_binary(Key, 16, 4)]),
Key.
hash(_K, _H, Ki, N, _HASH) when N =< 0 ->
@@ -1055,6 +1000,7 @@ kex_h(SSH, K_S, E, F, K) ->
[string,string,binary,binary,binary,
mpint,mpint,mpint]),
crypto:sha(L).
+
kex_h(SSH, K_S, Min, NBits, Max, Prime, Gen, E, F, K) ->
L = if Min==-1; Max==-1 ->
@@ -1075,7 +1021,7 @@ kex_h(SSH, K_S, Min, NBits, Max, Prime, Gen, E, F, K) ->
Prime, Gen, E,F,K], Ts)
end,
crypto:sha(L).
-
+
mac_key_size('hmac-sha1') -> 20*8;
mac_key_size('hmac-sha1-96') -> 20*8;
mac_key_size('hmac-md5') -> 16*8;
@@ -1105,9 +1051,6 @@ dh_gen_key(G, P, _Bits) ->
Public = ssh_math:ipow(G, Private, P),
{Private,Public}.
-%% trim(Str) ->
-%% lists:reverse(trim_head(lists:reverse(trim_head(Str)))).
-
trim_tail(Str) ->
lists:reverse(trim_head(lists:reverse(Str))).
@@ -1116,48 +1059,3 @@ trim_head([$\t|Cs]) -> trim_head(Cs);
trim_head([$\n|Cs]) -> trim_head(Cs);
trim_head([$\r|Cs]) -> trim_head(Cs);
trim_head(Cs) -> Cs.
-
-%% Retrieve session_id from ssh, needed by public-key auth
-%get_session_id(SSH) ->
-% {ok, SessionID} = call(SSH, get_session_id),
-
-%% DEBUG utils
-%% Format integers and binaries as hex blocks
-%%
-%% -ifdef(debug).
-%% fmt_binary(B, BlockSize, GroupSize) ->
-%% fmt_block(fmt_bin(B), BlockSize, GroupSize).
-
-%% fmt_block(Bin, BlockSize, GroupSize) ->
-%% fmt_block(Bin, BlockSize, 0, GroupSize).
-
-
-%% fmt_block(Bin, 0, _I, _G) ->
-%% binary_to_list(Bin);
-%% fmt_block(Bin, Sz, G, G) when G =/= 0 ->
-%% ["~n#" | fmt_block(Bin, Sz, 0, G)];
-%% fmt_block(Bin, Sz, I, G) ->
-%% case Bin of
-%% <<Block:Sz/binary, Tail/binary>> ->
-%% if Tail == <<>> ->
-%% [binary_to_list(Block)];
-%% true ->
-%% [binary_to_list(Block), " " | fmt_block(Tail, Sz, I+1, G)]
-%% end;
-%% <<>> ->
-%% [];
-%% _ ->
-%% [binary_to_list(Bin)]
-%% end.
-
-%% %% Format integer or binary as hex
-%% fmt_bin(X) when integer(X) ->
-%% list_to_binary(io_lib:format("~p", [X]));
-%% fmt_bin(X) when binary(X) ->
-%% Sz = size(X)*8,
-%% <<Y:Sz/unsigned-big>> = X,
-%% %%Fmt = "~"++integer_to_list(size(X)*2)++"~p",
-%% list_to_binary(io_lib:format("~p", [Y])).
-
-%% -endif.
-
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index c9631a73b1..d5b6dd03d1 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. 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
@@ -298,8 +298,6 @@ xf_send_names(#ssh_xfer{cm = CM, channel = Channel, vsn = Vsn},
Size = 1 + 4 + 4 + Len,
ToSend = [<<?UINT32(Size), ?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(Count)>>,
Data],
- %%?dbg(true, "xf_send_names: Size=~p size(ToSend)=~p\n",
- %% [Size, size(list_to_binary(ToSend))]),
ssh_connection:send(CM, Channel, ToSend).
xf_send_status(XF, ReqId, ErrorCode) ->
@@ -353,7 +351,6 @@ xf_reply(_XF, <<?SSH_FXP_DATA, ?UINT32(ReqID),
{data, ReqID, Data};
xf_reply(XF, <<?SSH_FXP_NAME, ?UINT32(ReqID),
?UINT32(Count), AData/binary>>) ->
- %%?dbg(true, "xf_reply ?SSH_FXP_NAME: AData=~p\n", [AData]),
{name, ReqID, decode_names(XF#ssh_xfer.vsn, Count, AData)};
xf_reply(XF, <<?SSH_FXP_ATTRS, ?UINT32(ReqID),
AData/binary>>) ->
@@ -579,7 +576,6 @@ encode_attr_flags(Vsn, Flags) ->
end, Flags).
encode_file_type(Type) ->
- %%?dbg(true, "encode_file_type(~p)\n", [Type]),
case Type of
regular -> ?SSH_FILEXFER_TYPE_REGULAR;
directory -> ?SSH_FILEXFER_TYPE_DIRECTORY;
@@ -660,15 +656,12 @@ encode_ATTR(Vsn, A) ->
{extended, A#ssh_xfer_attr.extensions}],
0, []),
Type = encode_file_type(A#ssh_xfer_attr.type),
- %%?dbg(true, "encode_ATTR: Vsn=~p A=~p As=~p Flags=~p Type=~p",
- %% [Vsn, A, As, Flags, Type]),
Result = list_to_binary([?uint32(Flags),
if Vsn >= 5 ->
?byte(Type);
true ->
(<<>>)
end, As]),
- %% ?dbg(true, " Result=~p\n", [Result]),
Result.
@@ -722,7 +715,6 @@ encode_As(_Vsn, [], Flags, Acc) ->
decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
- %%?dbg(true, "decode_ATTR: Vsn=~p Flags=~p Tail=~p\n", [Vsn, Flags, Tail]),
{Type,Tail2} =
if Vsn =< 3 ->
{?SSH_FILEXFER_TYPE_UNKNOWN, Tail};
@@ -751,7 +743,6 @@ decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
Tail2).
decode_As(Vsn, [{AName, AField}|As], R, Flags, Tail) ->
- %%?dbg(false, "decode_As: Vsn=~p AName=~p AField=~p Flags=~p Tail=~p\n", [Vsn, AName, AField, Flags, Tail]),
case AName of
size when ?is_set(?SSH_FILEXFER_ATTR_SIZE, Flags) ->
<<?UINT64(X), Tail2/binary>> = Tail,
@@ -762,7 +753,6 @@ decode_As(Vsn, [{AName, AField}|As], R, Flags, Tail) ->
ownergroup when ?is_set(?SSH_FILEXFER_ATTR_OWNERGROUP, Flags),Vsn>=5 ->
<<?UINT32(Len), Bin:Len/binary, Tail2/binary>> = Tail,
X = binary_to_list(Bin),
- %%?dbg(true, "ownergroup X=~p\n", [X]),
decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
permissions when ?is_set(?SSH_FILEXFER_ATTR_PERMISSIONS,Flags),Vsn>=5->
@@ -824,13 +814,11 @@ decode_names(Vsn, I, <<?UINT32(Len), FileName:Len/binary,
?UINT32(LLen), _LongName:LLen/binary,
Tail/binary>>) when Vsn =< 3 ->
Name = binary_to_list(FileName),
- %%?dbg(true, "decode_names: ~p\n", [Name]),
{A, Tail2} = decode_ATTR(Vsn, Tail),
[{Name, A} | decode_names(Vsn, I-1, Tail2)];
decode_names(Vsn, I, <<?UINT32(Len), FileName:Len/binary,
Tail/binary>>) when Vsn >= 4 ->
Name = binary_to_list(FileName),
- %%?dbg(true, "decode_names: ~p\n", [Name]),
{A, Tail2} = decode_ATTR(Vsn, Tail),
[{Name, A} | decode_names(Vsn, I-1, Tail2)].
@@ -839,8 +827,6 @@ encode_names(Vsn, NamesAndAttrs) ->
encode_name(Vsn, {Name,Attr}, Len) when Vsn =< 3 ->
NLen = length(Name),
- %%?dbg(true, "encode_name: Vsn=~p Name=~p Attr=~p\n",
- %% [Vsn, Name, Attr]),
EncAttr = encode_ATTR(Vsn, Attr),
ALen = size(EncAttr),
NewLen = Len + NLen*2 + 4 + 4 + ALen,
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 1820924ed6..145d5d2ad6 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. 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
@@ -32,7 +32,6 @@ VSN=$(GS_VSN)
MODULES= \
ssh_test_lib \
- ssh_SUITE \
ssh_basic_SUITE \
ssh_to_openssh_SUITE \
ssh_sftp_SUITE \
diff --git a/lib/ssh/test/ssh_SUITE.erl b/lib/ssh/test/ssh_SUITE.erl
deleted file mode 100644
index 953c9080f9..0000000000
--- a/lib/ssh/test/ssh_SUITE.erl
+++ /dev/null
@@ -1,72 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2011. 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
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%%----------------------------------------------------------------
-%%% Purpose:ssh application test suite.
-%%%-----------------------------------------------------------------
--module(ssh_SUITE).
--include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
--define(application, ssh).
-
-% Test server specific exports
--export([all/0,groups/0,init_per_group/2,end_per_group/2]).
--export([init_per_testcase/2, end_per_testcase/2]).
-
-% Test cases must be exported.
--export([app_test/1]).
--define(cases, [app_test]).
-
-%%
-%% all/1
-%%
-all() ->
- [app_test].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-%
-% Test cases starts here.
-%
-app_test(suite) ->
- [];
-app_test(doc) ->
- ["Application consistency test."];
-app_test(Config) when is_list(Config) ->
- ?t:app_test(?application),
- ok.
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 73b60057cc..9c13180159 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -41,20 +41,6 @@
init_per_suite(Config) ->
case catch crypto:start() of
ok ->
- DataDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
- ssh_test_lib:copyfile(DataDir, UserDir, "id_rsa"),
- ssh_test_lib:copyfile(DataDir, UserDir, "id_dsa"),
- RSAFile = filename:join(DataDir, "id_rsa.pub"),
- DSAFile = filename:join(DataDir, "id_dsa.pub"),
- {ok, Ssh1} = file:read_file(RSAFile),
- {ok, Ssh2} = file:read_file(DSAFile),
- [{RSA, _}] = public_key:ssh_decode(Ssh1,public_key),
- [{DSA, _}] = public_key:ssh_decode(Ssh2,public_key),
- AuthKeys = public_key:ssh_encode([{RSA, [{comment, "Test"}]},
- {DSA,[{comment, "Test"}]}], auth_keys),
- AuthKeysFile = filename:join(UserDir, "authorized_keys"),
- file:write_file(AuthKeysFile, AuthKeys),
Config;
_Else ->
{skip, "Crypto could not be started!"}
@@ -66,7 +52,8 @@ init_per_suite(Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
-end_per_suite(Config) ->
+end_per_suite(_Config) ->
+ ssh:stop(),
crypto:stop(),
ok.
@@ -99,11 +86,11 @@ init_per_testcase(_TestCase, Config) ->
end_per_testcase(TestCase, Config) when TestCase == server_password_option;
TestCase == server_userpassword_option ->
UserDir = filename:join(?config(priv_dir, Config), nopubkey),
- file:del_dir(UserDir),
+ ssh_test_lib:del_dirs(UserDir),
end_per_testcase(Config);
-end_per_testcase(_TestCase, Config) ->
+end_per_testcase(TestCase, Config) ->
end_per_testcase(Config).
-end_per_testcase(Config) ->
+end_per_testcase(_Config) ->
ssh:stop(),
ok.
@@ -116,30 +103,72 @@ end_per_testcase(Config) ->
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
all() ->
- [exec, exec_compressed, shell, daemon_already_started,
- server_password_option, server_userpassword_option, known_hosts].
+ [app_test,
+ {group, dsa_key},
+ {group, rsa_key},
+ {group, dsa_pass_key},
+ {group, rsa_pass_key},
+ daemon_already_started,
+ server_password_option, server_userpassword_option].
groups() ->
- [].
+ [{dsa_key, [], [exec, exec_compressed, shell, known_hosts]},
+ {rsa_key, [], [exec, exec_compressed, shell, known_hosts]},
+ {dsa_pass_key, [], [pass_phrase]},
+ {rsa_pass_key, [], [pass_phrase]}
+ ].
-init_per_group(_GroupName, Config) ->
- Config.
+init_per_group(dsa_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ Config;
+init_per_group(rsa_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_rsa(DataDir, PrivDir),
+ Config;
+init_per_group(rsa_pass_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_rsa_pass_pharse(DataDir, PrivDir, "Password"),
+ [{pass_phrase, {rsa_pass_phrase, "Password"}}| Config];
+init_per_group(dsa_pass_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa_pass_pharse(DataDir, PrivDir, "Password"),
+ [{pass_phrase, {dsa_pass_phrase, "Password"}}| Config];
+init_per_group(_, Config) ->
+ Config.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(dsa_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(PrivDir),
+ Config;
+end_per_group(rsa_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_rsa(PrivDir),
+ Config;
+end_per_group(dsa_pass_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(PrivDir),
+ Config;
+end_per_group(rsa_pass_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_rsa(PrivDir),
+ Config;
+end_per_group(_, Config) ->
+ Config.
%% Test cases starts here.
%%--------------------------------------------------------------------
-sign_and_verify_rsa(doc) ->
- ["Test api function ssh:sign_data and ssh:verify_data"];
-
-sign_and_verify_rsa(suite) ->
+app_test(suite) ->
[];
-sign_and_verify_rsa(Config) when is_list(Config) ->
- Data = ssh:sign_data(<<"correct data">>, "ssh-rsa"),
- ok = ssh:verify_data(<<"correct data">>, Data, "ssh-rsa"),
- {error,invalid_signature} = ssh:verify_data(<<"incorrect data">>, Data,"ssh-rsa").
-
+app_test(doc) ->
+ ["Application consistency test."];
+app_test(Config) when is_list(Config) ->
+ ?t:app_test(ssh),
+ ok.
exec(doc) ->
["Test api function ssh_connection:exec"];
@@ -149,7 +178,7 @@ exec(suite) ->
exec(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = ?config(data_dir, Config),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
@@ -195,8 +224,8 @@ exec_compressed(suite) ->
exec_compressed(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
{compression, zlib},
@@ -229,9 +258,9 @@ shell(suite) ->
shell(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = ?config(data_dir, Config),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
-
+
{_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
{failfun, fun ssh_test_lib:failfun/2}]),
test_server:sleep(500),
@@ -301,9 +330,13 @@ daemon_already_started(suite) ->
daemon_already_started(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
+ UserDir = ?config(priv_dir, Config),
+
{Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
{failfun, fun ssh_test_lib:failfun/2}]),
{error, eaddrinuse} = ssh_test_lib:daemon(Port, [{system_dir, SystemDir},
+ {user_dir, UserDir},
{failfun,
fun ssh_test_lib:failfun/2}]),
ssh:stop_daemon(Pid).
@@ -314,10 +347,12 @@ server_password_option(doc) ->
server_password_option(suite) ->
[];
server_password_option(Config) when is_list(Config) ->
- UserDir = filename:join(?config(priv_dir, Config), nopubkey), % to make sure we don't use public-key-auth
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
file:make_dir(UserDir),
- SysDir = ?config(data_dir, Config),
+ SysDir = ?config(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
{password, "morot"}]),
ConnectionRef =
@@ -345,10 +380,12 @@ server_userpassword_option(doc) ->
server_userpassword_option(suite) ->
[];
server_userpassword_option(Config) when is_list(Config) ->
- UserDir = filename:join(?config(priv_dir, Config), nopubkey), % to make sure we don't use public-key-auth
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
file:make_dir(UserDir),
SysDir = ?config(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, PrivDir},
{user_passwords, [{"vego", "morot"}]}]),
ConnectionRef =
@@ -386,17 +423,17 @@ known_hosts(doc) ->
known_hosts(suite) ->
[];
known_hosts(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
+ SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
- {Pid, Host, Port} = ssh_test_lib:daemon([{user_dir, UserDir},{system_dir, DataDir},
+ {Pid, Host, Port} = ssh_test_lib:daemon([{user_dir, PrivDir},{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2}]),
- KnownHosts = filename:join(UserDir, "known_hosts"),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
file:delete(KnownHosts),
{error, enoent} = file:read_file(KnownHosts),
ConnectionRef =
- ssh_test_lib:connect(Host, Port, [{user_dir, UserDir},
+ ssh_test_lib:connect(Host, Port, [{user_dir, PrivDir},
{user_interaction, false},
silently_accept_hosts]),
{ok, _Channel} = ssh_connection:session_channel(ConnectionRef, infinity),
@@ -407,7 +444,30 @@ known_hosts(Config) when is_list(Config) ->
[HostAndIp, Alg, _KeyData] = string:tokens(Line, " "),
[Host, _Ip] = string:tokens(HostAndIp, ","),
"ssh-" ++ _ = Alg,
- ssh:stop_daemon(Pid).
+ ssh:stop_daemon(Pid).
+
+pass_phrase(doc) ->
+ ["Test that we can use keyes protected by pass phrases"];
+
+pass_phrase(suite) ->
+ [];
+
+pass_phrase(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+ PhraseArg = ?config(pass_phrase, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ PhraseArg,
+ {user_dir, UserDir},
+ {user_interaction, false}]),
+ {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
%% Internal functions
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_dsa.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa.pub
deleted file mode 100644
index 9406116777..0000000000
--- a/lib/ssh/test/ssh_basic_SUITE_data/id_dsa.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-dss AAAAB3NzaC1kc3MAAACBAN+LZ+VJNlmh/BPjJBPQ2KRf8sY1PtQ94H9cRZ7/Gi8RgISV9pAA8WLFe8SBfCiiOZnmSJBErMszf3AE/SM8REtudld844PQ8OfDSFoyHt0PtcpUyh38SKBWAd/+oF0zYzzLPWz+tEXufVSktLKnOIqOTMKbsmhJDbNtYg92YEhfAAAAFQDID5Ka+0qtzu7B3W/A+tNQ0Y6BMQAAAIAw5DEN8HYV3yi7Pob3p/9Q7NEwj8p2/yRhgpYkgZj6lFiss/JjNR4nOfBmt44mCtzMBf6W4ecoVYnYOeTkLJ5eTrtayvukn/gwEwM4p4hLRLyqhIE3z4qunv1+AD7JLch+puQku0u7gQFoJfiYpAhfj76Tjh3hTmVzym372GUQjwAAAIEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+euEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AXCy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34= Dsa
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_rsa b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa
index 79968bdd7d..9d7e0dd5fb 100644
--- a/lib/ssh/test/ssh_basic_SUITE_data/id_rsa
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa
@@ -1,16 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337
-zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB
-6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB
-AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW
-NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++
-udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW
-WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt
-n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5
-sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY
-+SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt
-64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB
-m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT
-tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR
+MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU
+DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl
+zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB
+AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V
+TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3
+CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK
+SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p
+z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd
+WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39
+sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3
+xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ
+dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x
+ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak=
-----END RSA PRIVATE KEY-----
-
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_rsa.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa.pub
deleted file mode 100644
index 95bce6bc61..0000000000
--- a/lib/ssh/test/ssh_basic_SUITE_data/id_rsa.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== ingela@dain
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key
index d306f8b26e..51ab6fbd88 100644
--- a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key
@@ -1,13 +1,13 @@
-----BEGIN DSA PRIVATE KEY-----
-MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
-APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
-/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
-kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
-JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
-OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
-+9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
-uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
-Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
-ZU8w8Q+H7z0j+a+70x2iAw==
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
-----END DSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub
new file mode 100644
index 0000000000..75d2025c71
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub
@@ -0,0 +1,5 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8
+semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW
+RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
index a9a568ced6..7644db155d 100644
--- a/lib/ssh/test/ssh_sftp_SUITE.erl
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -24,14 +24,12 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include_lib("kernel/include/file.hrl").
% Default timetrap timeout
-define(default_timeout, ?t:minutes(1)).
--define(SFPD_PORT, 9999).
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
@@ -46,17 +44,12 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- case {catch crypto:start(),catch ssh:start()} of
- {ok,ok} ->
- Dir = ?config(priv_dir, Config),
- {ok, _} = ssh_test_lib:get_id_keys(Dir),
+ case (catch crypto:start()) of
+ ok ->
+ ssh:start(),
Config;
- {ok,_} ->
- {skip,"Could not start ssh!"};
- {_,ok} ->
- {skip,"Could not start crypto!"};
- {_,_} ->
- {skip,"Could not start crypto and ssh!"}
+ _ ->
+ {skip,"Could not start crypto!"}
end.
%%--------------------------------------------------------------------
@@ -66,9 +59,8 @@ init_per_suite(Config) ->
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(Config) ->
+ ssh:stop(),
crypto:stop(),
- Dir = ?config(priv_dir, Config),
- ssh_test_lib:remove_id_keys(Dir),
Config.
%%--------------------------------------------------------------------
@@ -89,28 +81,30 @@ init_per_testcase(_Case, Config) ->
TmpConfig0 = lists:keydelete(watchdog, 1, Config),
TmpConfig = lists:keydelete(sftp, 1, TmpConfig0),
Dog = test_server:timetrap(?default_timeout),
- Dir = ?config(priv_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
SysDir = ?config(data_dir, Config),
Host = ssh_test_lib:hostname(),
%% Run test against openssh server if available
- Sftp = case (catch ssh_sftp:start_channel(Host,
- [{user_dir, Dir},
- {user_interaction, false},
+ Sftp = case (catch ssh_sftp:start_channel(Host,
+ [{user_interaction, false},
{silently_accept_hosts, true}])) of
{ok, ChannelPid, Connection} ->
+ test_server:format("Running against openssh"),
{ChannelPid, Connection};
- _Error -> %% Start own sftp server
- {_Sftpd, _Host, _Port} =
- ssh_test_lib:daemon(Host, ?SFPD_PORT,
- [{system_dir, SysDir},
+ _Error -> %% Start own sftp
+ test_server:format("Running against erlang ssh"),
+ {_Sftpd, Host1, Port} =
+ ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, PrivDir},
{user_passwords,
[{?USER, ?PASSWD}]},
{failfun,
fun ssh_test_lib:failfun/2}]),
- Result = (catch ssh_sftp:start_channel(Host, ?SFPD_PORT,
+ Result = (catch ssh_sftp:start_channel(Host1, Port,
[{user, ?USER},
{password, ?PASSWD},
+ {user_dir, PrivDir},
{user_interaction, false},
{silently_accept_hosts, true}])),
{ok, ChannelPid, Connection} = Result,
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index 0873348be0..6e4480ee9d 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -55,13 +55,16 @@
init_per_suite(Config) ->
case (catch crypto:start()) of
ok ->
- ssh:start(),
- DataDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
- ssh_test_lib:setup_dsa(UserDir, DataDir),
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ %% to make sure we don't use public-key-auth
+ %% this should be tested by other test suites
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:make_dir(UserDir),
Config;
_ ->
- {skip,"Could not start ssh!"}
+ {skip,"Could not start crypto!"}
end.
%%--------------------------------------------------------------------
@@ -71,8 +74,10 @@ init_per_suite(Config) ->
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(Config) ->
- UserDir = ?config(priv_dir, Config),
- ssh_test_lib:clean_dsa(UserDir),
+ SysDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(SysDir),
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:del_dir(UserDir),
ssh:stop(),
crypto:stop(),
ok.
@@ -93,15 +98,18 @@ end_per_suite(Config) ->
init_per_testcase(TestCase, Config) ->
ssh:start(),
prep(Config),
- SysDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ClientUserDir = filename:join(PrivDir, nopubkey),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+
{ok, Sftpd} =
- ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SysDir},
+ ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{user_passwords,[{?USER, ?PASSWD}]},
{pwdfun, fun(_,_) -> true end}]),
Cm = ssh_test_lib:connect(?SFPD_PORT,
- [{system_dir, SysDir},
- {user_dir, SysDir},
+ [{user_dir, ClientUserDir},
{user, ?USER}, {password, ?PASSWD},
{user_interaction, false},
{silently_accept_hosts, true},
@@ -544,7 +552,7 @@ set_attributes(Config) when is_list(Config) ->
{ok, FileInfo} = file:read_file_info(FileName),
OrigPermissions = FileInfo#file_info.mode,
- Permissions = 8#400, %% User read-only
+ Permissions = 8#600, %% User read-write-only
Flags = ?SSH_FILEXFER_ATTR_PERMISSIONS,
diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa b/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa
new file mode 100644
index 0000000000..d306f8b26e
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
+APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
+/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
+kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
+JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
+OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
+uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
+Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
+ZU8w8Q+H7z0j+a+70x2iAw==
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
index c63ad7de73..4c469ed5f7 100644
--- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
@@ -28,7 +28,6 @@
-include_lib("kernel/include/file.hrl").
--define(SSHD_PORT, 9999).
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
-define(SSH_MAX_PACKET_SIZE, 32768).
@@ -48,14 +47,14 @@ init_per_suite(Config) ->
case catch crypto:start() of
ok ->
DataDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"),
c:c(FileAlt),
FileName = filename:join(DataDir, "test.txt"),
{ok, FileInfo} = file:read_file_info(FileName),
ok = file:write_file_info(FileName,
FileInfo#file_info{mode = 8#400}),
- ssh_test_lib:setup_dsa(DataDir, UserDir),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
Config;
_Else ->
{skip,"Could not start ssh!"}
@@ -67,9 +66,11 @@ init_per_suite(Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- UserDir = ?config(priv_dir, Config),
- ssh_test_lib:clean_dsa(UserDir),
+end_per_suite(Config) ->
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:del_dir(UserDir),
+ SysDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(SysDir),
crypto:stop(),
ok.
@@ -89,6 +90,7 @@ end_per_suite(Config) ->
init_per_testcase(TestCase, Config) ->
ssh:start(),
PrivDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(PrivDir, system),
Options =
case atom_to_list(TestCase) of
@@ -96,45 +98,39 @@ init_per_testcase(TestCase, Config) ->
Spec =
ssh_sftpd:subsystem_spec([{file_handler,
ssh_sftpd_file_alt}]),
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, PrivDir},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{subsystems, [Spec]}];
"root_dir" ->
Privdir = ?config(priv_dir, Config),
Root = filename:join(Privdir, root),
file:make_dir(Root),
Spec = ssh_sftpd:subsystem_spec([{root,Root}]),
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, PrivDir},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{subsystems, [Spec]}];
"list_dir_limited" ->
Spec =
ssh_sftpd:subsystem_spec([{max_files,1}]),
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, PrivDir},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{subsystems, [Spec]}];
_ ->
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, PrivDir}]
+ [{user_dir, PrivDir},
+ {system_dir, SystemDir}]
end,
- {Sftpd, Host, _Port} = ssh_test_lib:daemon(any, ?SSHD_PORT, Options),
+ {Sftpd, Host, Port} = ssh_test_lib:daemon(Options),
{ok, ChannelPid, Connection} =
- ssh_sftp:start_channel(Host, ?SSHD_PORT,
+ ssh_sftp:start_channel(Host, Port,
[{silently_accept_hosts, true},
- {user, ?USER}, {password, ?PASSWD},
- {pwdfun, fun(_,_) -> true end},
{user_dir, PrivDir},
{timeout, 30000}]),
TmpConfig = lists:keydelete(sftp, 1, Config),
NewConfig = lists:keydelete(sftpd, 1, TmpConfig),
- [{sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig].
+ [{port, Port}, {sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig].
%%--------------------------------------------------------------------
%% Function: end_per_testcase(TestCase, Config) -> _
@@ -214,6 +210,8 @@ quit_OTP_6349(suite) ->
quit_OTP_6349(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
FileName = filename:join(DataDir, "test.txt"),
+ UserDir = ?config(priv_dir, Config),
+ Port = ?config(port, Config),
{Sftp, _} = ?config(sftp, Config),
@@ -224,11 +222,10 @@ quit_OTP_6349(Config) when is_list(Config) ->
Host = ssh_test_lib:hostname(),
timer:sleep(5000),
- {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, ?SSHD_PORT,
+ {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, Port,
[{silently_accept_hosts, true},
{pwdfun, fun(_,_) -> true end},
- {system_dir, DataDir},
- {user_dir, DataDir},
+ {user_dir, UserDir},
{user, ?USER}, {password, ?PASSWD}]),
{ok, <<_/binary>>} = ssh_sftp:read_file(NewSftp, FileName),
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa
new file mode 100644
index 0000000000..d306f8b26e
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
+APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
+/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
+kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
+JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
+OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
+uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
+Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
+ZU8w8Q+H7z0j+a+70x2iAw==
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index f4e95f9bfb..26bbdf5c5c 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -71,6 +71,9 @@ daemon(Host, Port, Options) ->
start_shell(Port, IOServer, UserDir) ->
spawn_link(?MODULE, init_shell, [Port, IOServer, [{user_dir, UserDir}]]).
+start_shell(Port, IOServer) ->
+ spawn_link(?MODULE, init_shell, [Port, IOServer, []]).
+
init_shell(Port, IOServer, UserDir) ->
Host = hostname(),
Options = [{user_interaction, false}, {silently_accept_hosts,
@@ -91,13 +94,10 @@ init_io_server(TestCase) ->
loop_io_server(TestCase, Buff0) ->
receive
{input, TestCase, Line} ->
- %io:format("~p~n",[{input, TestCase, Line}]),
loop_io_server(TestCase, Buff0 ++ [Line]);
{io_request, From, ReplyAs, Request} ->
- %io:format("request -> ~p~n",[Request]),
{ok, Reply, Buff} = io_request(Request, TestCase, From,
ReplyAs, Buff0),
- %io:format("reply -> ~p~n",[Reply]),
io_reply(From, ReplyAs, Reply),
loop_io_server(TestCase, Buff);
{'EXIT',_, _} ->
@@ -183,34 +183,21 @@ inet_port()->
gen_tcp:close(Socket),
Port.
-
-%% copy private keys to given dir from ~/.ssh
-get_id_keys(DstDir) ->
- SrcDir = filename:join(os:getenv("HOME"), ".ssh"),
- RsaOk = copyfile(SrcDir, DstDir, "id_rsa"),
- DsaOk = copyfile(SrcDir, DstDir, "id_dsa"),
- case {RsaOk, DsaOk} of
- {{ok, _}, {ok, _}} -> {ok, both};
- {{ok, _}, _} -> {ok, rsa};
- {_, {ok, _}} -> {ok, dsa};
- {Error, _} -> Error
- end.
-
-remove_id_keys(Dir) ->
- file:delete(filename:join(Dir, "id_rsa")),
- file:delete(filename:join(Dir, "id_dsa")).
-
-copyfile(SrcDir, DstDir, FileName) ->
- Dest = filename:join(DstDir, FileName),
- Result = file:copy(filename:join(SrcDir, FileName), Dest),
- {ok, Pem} = file:read_file(Dest),
- case public_key:pem_decode(Pem) of
- [{_,_, not_encrypted}] ->
- Result;
+setup_ssh_auth_keys(RSAFile, DSAFile, Dir) ->
+ Entries = ssh_file_entry(RSAFile) ++ ssh_file_entry(DSAFile),
+ AuthKeys = public_key:ssh_encode(Entries , auth_keys),
+ AuthKeysFile = filename:join(Dir, "authorized_keys"),
+ file:write_file(AuthKeysFile, AuthKeys).
+
+ssh_file_entry(PubFile) ->
+ case file:read_file(PubFile) of
+ {ok, Ssh} ->
+ [{Key, _}] = public_key:ssh_decode(Ssh, public_key),
+ [{Key, [{comment, "Test"}]}];
_ ->
- {error, "Has pass phrase can not be used by automated test case"}
- end.
-
+ []
+ end.
+
failfun(_User, {authmethod,none}) ->
ok;
failfun(User, Reason) ->
@@ -232,25 +219,122 @@ known_hosts(BR) ->
end.
setup_dsa(DataDir, UserDir) ->
- ssh_test_lib:copyfile(DataDir, UserDir, "ssh_host_dsa_key"),
- ssh_test_lib:copyfile(DataDir, UserDir, "ssh_host_dsa_key.pub"),
- {ok, Pem} = file:read_file(filename:join(UserDir, "ssh_host_dsa_key")),
- DSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
- PKey = DSA#'DSAPrivateKey'.y,
- P = DSA#'DSAPrivateKey'.p,
- Q = DSA#'DSAPrivateKey'.q,
- G = DSA#'DSAPrivateKey'.g,
- Dss = #'Dss-Parms'{p=P, q=Q, g=G},
+ file:copy(filename:join(DataDir, "id_dsa"), filename:join(UserDir, "id_dsa")),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
+ setup_dsa_known_host(DataDir, UserDir),
+ setup_dsa_auth_keys(DataDir, UserDir).
+
+setup_rsa(DataDir, UserDir) ->
+ file:copy(filename:join(DataDir, "id_rsa"), filename:join(UserDir, "id_rsa")),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key.pub")),
+ setup_rsa_known_host(DataDir, UserDir),
+ setup_rsa_auth_keys(DataDir, UserDir).
+
+clean_dsa(UserDir) ->
+ del_dirs(filename:join(UserDir, "system")),
+ file:delete(filename:join(UserDir,"id_dsa")),
+ file:delete(filename:join(UserDir,"known_hosts")),
+ file:delete(filename:join(UserDir,"authorized_keys")).
+
+clean_rsa(UserDir) ->
+ del_dirs(filename:join(UserDir, "system")),
+ file:delete(filename:join(UserDir,"id_rsa")),
+ file:delete(filename:join(UserDir,"known_hosts")),
+ file:delete(filename:join(UserDir,"authorized_keys")).
+
+setup_dsa_pass_pharse(DataDir, UserDir, Phrase) ->
+ {ok, KeyBin} = file:read_file(filename:join(DataDir, "id_dsa")),
+ setup_pass_pharse(KeyBin, filename:join(UserDir, "id_dsa"), Phrase),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
+ setup_dsa_known_host(DataDir, UserDir),
+ setup_dsa_auth_keys(DataDir, UserDir).
+
+setup_rsa_pass_pharse(DataDir, UserDir, Phrase) ->
+ {ok, KeyBin} = file:read_file(filename:join(DataDir, "id_rsa")),
+ setup_pass_pharse(KeyBin, filename:join(UserDir, "id_rsa"), Phrase),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")),
+ setup_rsa_known_host(DataDir, UserDir),
+ setup_rsa_auth_keys(DataDir, UserDir).
+
+setup_pass_pharse(KeyBin, OutFile, Phrase) ->
+ [{KeyType, _,_} = Entry0] = public_key:pem_decode(KeyBin),
+ Key = public_key:pem_entry_decode(Entry0),
+ Salt = crypto:rand_bytes(8),
+ Entry = public_key:pem_entry_encode(KeyType, Key,
+ {{"DES-CBC", Salt}, Phrase}),
+ Pem = public_key:pem_encode([Entry]),
+ file:write_file(OutFile, Pem).
+
+setup_dsa_known_host(SystemDir, UserDir) ->
+ {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_dsa_key.pub")),
+ [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
+ setup_known_hosts(Key, UserDir).
+
+setup_rsa_known_host(SystemDir, UserDir) ->
+ {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_rsa_key.pub")),
+ [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
+ setup_known_hosts(Key, UserDir).
+
+setup_known_hosts(Key, UserDir) ->
{ok, Hostname} = inet:gethostname(),
{ok, {A, B, C, D}} = inet:getaddr(Hostname, inet),
IP = lists:concat([A, ".", B, ".", C, ".", D]),
- HostNames = [{hostnames,[IP, IP]}],
- KnownHosts = [{{PKey, Dss}, HostNames}],
+ HostNames = [{hostnames,[Hostname, IP]}],
+ KnownHosts = [{Key, HostNames}],
KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts),
KHFile = filename:join(UserDir, "known_hosts"),
file:write_file(KHFile, KnownHostsEnc).
-clean_dsa(UserDir) ->
- file:delete(filename:join(UserDir, "ssh_host_dsa_key")),
- file:delete(filename:join(UserDir, "ssh_host_dsa_key.pub")),
- file:delete(filename:join(UserDir, "known_hosts")).
+setup_dsa_auth_keys(Dir, UserDir) ->
+ {ok, Pem} = file:read_file(filename:join(Dir, "id_dsa")),
+ DSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
+ PKey = DSA#'DSAPrivateKey'.y,
+ P = DSA#'DSAPrivateKey'.p,
+ Q = DSA#'DSAPrivateKey'.q,
+ G = DSA#'DSAPrivateKey'.g,
+ Dss = #'Dss-Parms'{p=P, q=Q, g=G},
+ setup_auth_keys([{{PKey, Dss}, [{comment, "Test"}]}], UserDir).
+
+setup_rsa_auth_keys(Dir, UserDir) ->
+ {ok, Pem} = file:read_file(filename:join(Dir, "id_rsa")),
+ RSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
+ #'RSAPrivateKey'{publicExponent = E, modulus = N} = RSA,
+ PKey = #'RSAPublicKey'{publicExponent = E, modulus = N},
+ setup_auth_keys([{ PKey, [{comment, "Test"}]}], UserDir).
+
+setup_auth_keys(Keys, Dir) ->
+ AuthKeys = public_key:ssh_encode(Keys, auth_keys),
+ AuthKeysFile = filename:join(Dir, "authorized_keys"),
+ file:write_file(AuthKeysFile, AuthKeys).
+
+
+del_dirs(Dir) ->
+ case file:list_dir(Dir) of
+ {ok, []} ->
+ file:del_dir(Dir);
+ {ok, Files} ->
+ lists:foreach(fun(File) ->
+ FullPath = filename:join(Dir,File),
+ case filelib:is_dir(FullPath) of
+ true ->
+ del_dirs(FullPath),
+ file:del_dir(FullPath);
+ false ->
+ file:delete(FullPath)
+ end
+ end, Files);
+ _ ->
+ ok
+ end.
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index 53d04620c5..dfe526564d 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -119,18 +119,15 @@ groups() ->
erlang_client_openssh_server_password]},
{erlang_server, [], [erlang_server_openssh_client_exec,
erlang_server_openssh_client_exec_compressed,
- erlang_server_openssh_client_pulic_key_dsa,
- erlang_client_openssh_server_password]}
+ erlang_server_openssh_client_pulic_key_dsa]}
].
init_per_group(erlang_server, Config) ->
DataDir = ?config(data_dir, Config),
UserDir = ?config(priv_dir, Config),
- ssh_test_lib:setup_dsa(DataDir, UserDir),
+ ssh_test_lib:setup_dsa_known_host(DataDir, UserDir),
Config;
init_per_group(_, Config) ->
- Dir = ?config(priv_dir, Config),
- {ok, _} = ssh_test_lib:get_id_keys(Dir),
Config.
end_per_group(erlang_server, Config) ->
@@ -138,8 +135,6 @@ end_per_group(erlang_server, Config) ->
ssh_test_lib:clean_dsa(UserDir),
Config;
end_per_group(_, Config) ->
- Dir = ?config(priv_dir, Config),
- ssh_test_lib:remove_id_keys(Dir),
Config.
%% TEST cases starts here.
@@ -152,9 +147,8 @@ erlang_shell_client_openssh_server(suite) ->
erlang_shell_client_openssh_server(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- UserDir = ?config(priv_dir, Config),
IO = ssh_test_lib:start_io_server(),
- Shell = ssh_test_lib:start_shell(?SSH_DEFAULT_PORT, IO, UserDir),
+ Shell = ssh_test_lib:start_shell(?SSH_DEFAULT_PORT, IO),
IO ! {input, self(), "echo Hej\n"},
receive_hej(),
IO ! {input, self(), "exit\n"},
@@ -250,8 +244,10 @@ erlang_server_openssh_client_exec(suite) ->
[];
erlang_server_openssh_client_exec(Config) when is_list(Config) ->
- SystemDir = ?config(priv_dir, Config),
-
+ SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -259,7 +255,10 @@ erlang_server_openssh_client_exec(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " 1+1.",
+
+ test_server:format("Cmd: ~p~n", [Cmd]),
+
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -279,7 +278,10 @@ erlang_server_openssh_client_exec_compressed(suite) ->
[];
erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) ->
- SystemDir = ?config(priv_dir, Config),
+ SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{compression, zlib},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -287,7 +289,7 @@ erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no -C "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++ " -C "++ Host ++ " 1+1.",
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -352,26 +354,27 @@ erlang_client_openssh_server_publickey_rsa(suite) ->
[];
erlang_client_openssh_server_publickey_rsa(Config) when is_list(Config) ->
{ok,[[Home]]} = init:get_argument(home),
- SrcDir = filename:join(Home, ".ssh"),
- UserDir = ?config(priv_dir, Config),
- case ssh_test_lib:copyfile(SrcDir, UserDir, "id_rsa") of
- {ok, _} ->
- ConnectionRef =
- ssh_test_lib:connect(?SSH_DEFAULT_PORT,
- [{user_dir, UserDir},
- {public_key_alg, ssh_rsa},
- {user_interaction, false},
- silently_accept_hosts]),
- {ok, Channel} =
- ssh_connection:session_channel(ConnectionRef, infinity),
- ok = ssh_connection:close(ConnectionRef, Channel),
- ok = ssh:close(ConnectionRef),
- ok = file:delete(filename:join(UserDir, "id_rsa"));
- {error, enoent} ->
- {skip, "no ~/.ssh/id_rsa"};
- {error, Reason} ->
- {skip, Reason}
+ KeyFile = filename:join(Home, ".ssh/id_rsa"),
+ case file:read_file(KeyFile) of
+ {ok, Pem} ->
+ case public_key:pem_decode(Pem) of
+ [{_,_, not_encrypted}] ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{public_key_alg, ssh_rsa},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, Channel} =
+ ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, Channel),
+ ok = ssh:close(ConnectionRef);
+ _ ->
+ {skip, {error, "Has pass phrase can not be used by automated test case"}}
+ end;
+ _ ->
+ {skip, "no ~/.ssh/id_rsa"}
end.
+
%%--------------------------------------------------------------------
erlang_client_openssh_server_publickey_dsa(doc) ->
@@ -380,27 +383,26 @@ erlang_client_openssh_server_publickey_dsa(suite) ->
[];
erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) ->
{ok,[[Home]]} = init:get_argument(home),
- SrcDir = filename:join(Home, ".ssh"),
- UserDir = ?config(priv_dir, Config),
- case ssh_test_lib:copyfile(SrcDir, UserDir, "id_dsa") of
- {ok, _} ->
- ConnectionRef =
- ssh_test_lib:connect(?SSH_DEFAULT_PORT,
- [{user_dir, UserDir},
- {public_key_alg, ssh_dsa},
- {user_interaction, false},
- silently_accept_hosts]),
- {ok, Channel} =
- ssh_connection:session_channel(ConnectionRef, infinity),
- ok = ssh_connection:close(ConnectionRef, Channel),
- ok = ssh:close(ConnectionRef),
- ok = file:delete(filename:join(UserDir, "id_dsa"));
- {error, enoent} ->
- {skip, "no ~/.ssh/id_dsa"};
- {error, Reason} ->
- {skip, Reason}
+ KeyFile = filename:join(Home, ".ssh/id_dsa"),
+ case file:read_file(KeyFile) of
+ {ok, Pem} ->
+ case public_key:pem_decode(Pem) of
+ [{_,_, not_encrypted}] ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{public_key_alg, ssh_dsa},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, Channel} =
+ ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, Channel),
+ ok = ssh:close(ConnectionRef);
+ _ ->
+ {skip, {error, "Has pass phrase can not be used by automated test case"}}
+ end;
+ _ ->
+ {skip, "no ~/.ssh/id_dsa"}
end.
-
%%--------------------------------------------------------------------
erlang_server_openssh_client_pulic_key_dsa(doc) ->
["Validate using dsa publickey."];
@@ -409,7 +411,10 @@ erlang_server_openssh_client_pulic_key_dsa(suite) ->
[];
erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
- SystemDir = ?config(priv_dir, Config),
+ SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{public_key_alg, ssh_dsa},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -417,7 +422,8 @@ erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++
+ " " ++ Host ++ " 1+1.",
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -425,7 +431,6 @@ erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
ok
after ?TIMEOUT ->
test_server:fail("Did not receive answer")
-
end,
ssh:stop_daemon(Pid).
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index 115527aae0..bc395cb6d5 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -57,7 +57,7 @@ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
Kernel = self(),
- spawn(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end).
+ spawn_opt(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end, [link, {priority, max}]).
do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
[Name, Address] = splitnode(Node, LongOrShortNames),
@@ -229,9 +229,7 @@ connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Addre
accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed) ->
common_hs_data(Kernel, MyNode, Socket, Timer, #hs_data{
allowed = Allowed,
- f_address = fun(S, N) ->
- ssl_tls_dist_proxy:get_remote_id(S, N)
- end
+ f_address = fun get_remote_id/2
}).
common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
@@ -273,3 +271,11 @@ common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
P = proplists:get_value(send_pend, Stats, 0),
{ok, R,W,P}
end}.
+
+get_remote_id(Socket, _Node) ->
+ case ssl_tls_dist_proxy:get_tcp_address(Socket) of
+ {ok, Address} ->
+ Address;
+ {error, _Reason} ->
+ ?shutdown(no_node)
+ end.
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 371f475c85..542033e6ce 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. 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
@@ -188,14 +188,14 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
ValidationFunAndState =
case VerifyFunAndState of
undefined ->
- {fun(OtpCert, ExtensionOrError, SslState) ->
+ {fun(OtpCert, ExtensionOrVerifyResult, SslState) ->
ssl_certificate:validate_extension(OtpCert,
- ExtensionOrError, SslState)
+ ExtensionOrVerifyResult, SslState)
end, Role};
{Fun, UserState0} ->
- {fun(OtpCert, ExtensionOrError, {SslState, UserState}) ->
+ {fun(OtpCert, {extension, _} = Extension, {SslState, UserState}) ->
case ssl_certificate:validate_extension(OtpCert,
- ExtensionOrError,
+ Extension,
SslState) of
{valid, NewSslState} ->
{valid, {NewSslState, UserState}};
@@ -204,8 +204,11 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
SslState);
{unknown, _} ->
apply_user_fun(Fun, OtpCert,
- ExtensionOrError, UserState, SslState)
- end
+ Extension, UserState, SslState)
+ end;
+ (OtpCert, VerifyResult, {SslState, UserState}) ->
+ apply_user_fun(Fun, OtpCert, VerifyResult, UserState,
+ SslState)
end, {Role, UserState0}}
end,
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
index d63eada571..1c61eb7ccc 100644
--- a/lib/ssl/src/ssl_tls_dist_proxy.erl
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -19,7 +19,7 @@
-module(ssl_tls_dist_proxy).
--export([listen/1, accept/1, connect/2, get_remote_id/2]).
+-export([listen/1, accept/1, connect/2, get_tcp_address/1]).
-export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3, ssl_options/2]).
@@ -47,9 +47,6 @@ accept(Listen) ->
connect(Ip, Port) ->
gen_server:call(?MODULE, {connect, Ip, Port}, infinity).
-get_remote_id(Socket, Node) ->
- gen_server:call(?MODULE, {get_remote_id, {Socket,Node}}, infinity).
-
%%====================================================================
%% gen_server callbacks
%%====================================================================
@@ -65,8 +62,8 @@ handle_call({listen, Name}, _From, State) ->
case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}]) of
{ok, Socket} ->
{ok, World} = gen_tcp:listen(0, [{active, false}, binary, {packet,?PPRE}]),
- TcpAddress = get_tcp_address(Socket),
- WorldTcpAddress = get_tcp_address(World),
+ {ok, TcpAddress} = get_tcp_address(Socket),
+ {ok, WorldTcpAddress} = get_tcp_address(World),
{_,Port} = WorldTcpAddress#net_address.address,
{ok, Creation} = erl_epmd:register_node(Name, Port),
{reply, {ok, {Socket, TcpAddress, Creation}},
@@ -87,17 +84,16 @@ handle_call({connect, Ip, Port}, {From, _}, State) ->
receive
{Pid, go_ahead, LPort} ->
Res = {ok, Socket} = try_connect(LPort),
- ok = gen_tcp:controlling_process(Socket, From),
- flush_old_controller(From, Socket),
- {reply, Res, State};
+ case gen_tcp:controlling_process(Socket, From) of
+ {error, badarg} = Error -> {reply, Error, State}; % From is dead anyway.
+ ok ->
+ flush_old_controller(From, Socket),
+ {reply, Res, State}
+ end;
{Pid, Error} ->
{reply, Error, State}
end;
-handle_call({get_remote_id, {Socket,_Node}}, _From, State) ->
- Address = get_tcp_address(Socket),
- {reply, Address, State};
-
handle_call(_What, _From, State) ->
{reply, ok, State}.
@@ -117,14 +113,18 @@ code_change(_OldVsn, St, _Extra) ->
%%% Internal functions
%%--------------------------------------------------------------------
get_tcp_address(Socket) ->
- {ok, Address} = inet:sockname(Socket),
- {ok, Host} = inet:gethostname(),
- #net_address{
+ case inet:sockname(Socket) of
+ {ok, Address} ->
+ {ok, Host} = inet:gethostname(),
+ NetAddress = #net_address{
address = Address,
host = Host,
protocol = proxy,
family = inet
- }.
+ },
+ {ok, NetAddress};
+ {error, _} = Error -> Error
+ end.
accept_loop(Proxy, erts = Type, Listen, Extra) ->
process_flag(priority, max),
@@ -178,8 +178,8 @@ setup_proxy(Ip, Port, Parent) ->
Opts = get_ssl_options(client),
case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}] ++ Opts) of
{ok, World} ->
- {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, binary, {packet,?PPRE}]),
- #net_address{address={_,LPort}} = get_tcp_address(ErtsL),
+ {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, {127,0,0,1}}, binary, {packet,?PPRE}]),
+ {ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL),
Parent ! {self(), go_ahead, LPort},
case gen_tcp:accept(ErtsL) of
{ok, Erts} ->
@@ -194,7 +194,7 @@ setup_proxy(Ip, Port, Parent) ->
setup_connection(World, ErtsListen) ->
process_flag(trap_exit, true),
- TcpAddress = get_tcp_address(ErtsListen),
+ {ok, TcpAddress} = get_tcp_address(ErtsListen),
{_Addr,Port} = TcpAddress#net_address.address,
{ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}]),
ssl:setopts(World, [{active,true}, {packet,?PPRE}]),
@@ -223,7 +223,11 @@ loop_conn_setup(World, Erts) ->
loop_conn_setup(World, Erts);
{tcp, Erts, Data} ->
ssl:send(World, Data),
- loop_conn_setup(World, Erts)
+ loop_conn_setup(World, Erts);
+ {tcp_closed, Erts} ->
+ ssl:close(World);
+ {ssl_closed, World} ->
+ gen_tcp:close(Erts)
end.
loop_conn(World, Erts) ->
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 527263363c..0059a1e1ec 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. 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
@@ -250,6 +250,8 @@ all() ->
no_authority_key_identifier, invalid_signature_client,
invalid_signature_server, cert_expired,
client_with_cert_cipher_suites_handshake,
+ verify_fun_always_run_client,
+ verify_fun_always_run_server,
unknown_server_ca_fail, der_input,
unknown_server_ca_accept_verify_none,
unknown_server_ca_accept_verify_peer,
@@ -3217,6 +3219,105 @@ client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+verify_fun_always_run_client(doc) ->
+ ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"];
+verify_fun_always_run_client(suite) ->
+ [];
+verify_fun_always_run_client(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ %% If user verify fun is called correctly we fail the connection.
+ %% otherwise we can not tell this case apart form where we miss
+ %% to call users verify fun
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, [ChainLen]) ->
+ {valid, [ChainLen + 1]};
+ (_, valid_peer, [2]) ->
+ {fail, "verify_fun_was_always_run"};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState}
+ | ClientOpts]}]),
+ %% Server error may be esslaccept or closed depending on timing
+ %% this is not a bug it is a circumstance of how tcp works!
+ receive
+ {Server, ServerError} ->
+ test_server:format("Server Error ~p~n", [ServerError])
+ end,
+
+ ssl_test_lib:check_result(Client, {error, esslconnect}).
+
+%%--------------------------------------------------------------------
+verify_fun_always_run_server(doc) ->
+ ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"];
+verify_fun_always_run_server(suite) ->
+ [];
+verify_fun_always_run_server(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ %% If user verify fun is called correctly we fail the connection.
+ %% otherwise we can not tell this case apart form where we miss
+ %% to call users verify fun
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, [ChainLen]) ->
+ {valid, [ChainLen + 1]};
+ (_, valid_peer, [2]) ->
+ {fail, "verify_fun_was_always_run"};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState} |
+ ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer}
+ | ClientOpts]}]),
+
+ %% Client error may be esslconnect or closed depending on timing
+ %% this is not a bug it is a circumstance of how tcp works!
+ receive
+ {Client, ClientError} ->
+ test_server:format("Client Error ~p~n", [ClientError])
+ end,
+
+ ssl_test_lib:check_result(Server, {error, esslaccept}).
+
%%--------------------------------------------------------------------
unknown_server_ca_fail(doc) ->
["Test that the client fails if the ca is unknown in verify_peer mode"];
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 8fe55ee7a4..06182970e3 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -26,7 +26,7 @@
-define(DEFAULT_TIMETRAP_SECS, 240).
--define(AWAIT_SLL_NODE_UP_TIMEOUT, 30000).
+-define(AWAIT_SSL_NODE_UP_TIMEOUT, 30000).
-record(node_handle,
{connection_handler,
@@ -120,6 +120,12 @@ basic(Config) when is_list(Config) ->
pang = net_adm:ping(Node1),
pang = net_adm:ping(Node2),
+ %% SSL nodes should not be able to communicate with the test_server node
+ %% either (and ping should return eventually).
+ TestServer = node(),
+ pang = apply_on_ssl_node(NH1, fun () -> net_adm:ping(TestServer) end),
+ pang = apply_on_ssl_node(NH2, fun () -> net_adm:ping(TestServer) end),
+
%%
%% Check that we are able to communicate over the erlang
%% distribution between the ssl nodes.
@@ -380,7 +386,7 @@ mk_node_cmdline(ListenPort, Name, Args) ->
%%
await_ssl_node_up(Name, LSock) ->
- case gen_tcp:accept(LSock, ?AWAIT_SLL_NODE_UP_TIMEOUT) of
+ case gen_tcp:accept(LSock, ?AWAIT_SSL_NODE_UP_TIMEOUT) of
timeout ->
gen_tcp:close(LSock),
?t:format("Timeout waiting for ssl node ~s to come up~n",
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index f04ab9af50..01fca1f166 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. 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
@@ -1446,8 +1446,8 @@ check_sane_openssl_renegotaite(Config) ->
check_sane_openssl_sslv2(Config) ->
case os:cmd("openssl version") of
- "OpenSSL 1.0.0e" ++ _ ->
- {skip, "Known option bug"};
+ "OpenSSL 1.0.0" ++ _ ->
+ {skip, "sslv2 by default turned of in 1.*"};
_ ->
Config
end.
diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml
index 88ce77e0d0..7ce2defb72 100644
--- a/lib/stdlib/doc/src/binary.xml
+++ b/lib/stdlib/doc/src/binary.xml
@@ -505,7 +505,7 @@
<type>
<v>Subject = binary()</v>
<v>Pos = integer() >= 0</v>
- <v>Len = integer() >= 0</v>
+ <v>Len = integer()</v>
</type>
<desc>
<p>The same as <c>part(Subject, {Pos, Len})</c>.</p>
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml
index f81f8bda96..ad5f8bd5ac 100644
--- a/lib/stdlib/doc/src/ms_transform.xml
+++ b/lib/stdlib/doc/src/ms_transform.xml
@@ -308,7 +308,7 @@ ets:select(emp_tab, ets:fun2ms(
Erlang code. Also arithmetics is allowed, as well as ordinary guard
bif's. Here's a list of bif's and expressions:</p>
<list type="bulleted">
- <item>The type tests: is_atom, is_constant, is_float, is_integer,
+ <item>The type tests: is_atom, is_float, is_integer,
is_list, is_number, is_pid, is_port, is_reference, is_tuple,
is_binary, is_function, is_record</item>
<item>The boolean operators: not, and, or, andalso, orelse </item>
@@ -318,7 +318,7 @@ ets:select(emp_tab, ets:fun2ms(
<item>The guard bif's: abs, element, hd, length, node, round, size, tl,
trunc, self</item>
<item>The obsolete type test (only in guards):
- atom, constant, float, integer,
+ atom, float, integer,
list, number, pid, port, reference, tuple,
binary, function, record</item>
</list>
diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml
index 2e7768a1df..37c41501ae 100644
--- a/lib/stdlib/doc/src/sofs.xml
+++ b/lib/stdlib/doc/src/sofs.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2011</year>
+ <year>2001</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -317,7 +317,7 @@
but is to be preferred since it makes it possible to handle this
case even more efficiently. Examples of SetFuns:</p>
<pre>
-{sofs, union}
+fun sofs:union/1
fun(S) -> sofs:partition(1, S) end
{external, fun(A) -> A end}
{external, fun({A,_,C}) -> {C,A} end}
@@ -711,7 +711,7 @@ fun(S) -> sofs:partition(1, S) end
argument.</p>
<pre>
1> <input>F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),</input>
-<input>F2 = sofs:family_projection({sofs, union}, F1),</input>
+<input>F2 = sofs:family_projection(fun sofs:union/1, F1),</input>
<input>sofs:to_external(F2).</input>
[{a,[1,2,3]},{b,[]}]</pre>
</desc>
@@ -821,7 +821,7 @@ fun(S) -> sofs:partition(1, S) end
<input>sofs:to_external(F2).</input>
[{a,[1,2,3]},{b,[]}]</pre>
<p><c>family_union(F)</c> is equivalent to
- <c>family_projection({sofs,union},&nbsp;F)</c>.</p>
+ <c>family_projection(fun sofs:union/1,&nbsp;F)</c>.</p>
</desc>
</func>
<func>
@@ -1438,7 +1438,7 @@ true</pre>
1> <input>R1 = sofs:relation([{a,1},{b,2}]),</input>
<input>R2 = sofs:relation([{x,1},{x,2},{y,3}]),</input>
<input>S1 = sofs:from_sets([R1,R2]),</input>
-<input>S2 = sofs:specification({sofs,is_a_function}, S1),</input>
+<input>S2 = sofs:specification(fun sofs:is_a_function/1, S1),</input>
<input>sofs:to_external(S2).</input>
[[{a,1},{b,2}]]</pre>
</desc>
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index bf3c7b3504..95ba6b1096 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -947,7 +947,6 @@ type_test(integer) -> is_integer;
type_test(float) -> is_float;
type_test(number) -> is_number;
type_test(atom) -> is_atom;
-type_test(constant) -> is_constant;
type_test(list) -> is_list;
type_test(tuple) -> is_tuple;
type_test(pid) -> is_pid;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index cfbcf54d95..a1af0057ca 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -3436,17 +3436,11 @@ obsolete_guard({call,Line,{atom,Lr,F},As}, St0) ->
false ->
deprecated_function(Line, erlang, F, As, St0);
true ->
- St1 = case F of
- constant ->
- deprecated_function(Lr, erlang, is_constant, As, St0);
- _ ->
- St0
- end,
- case is_warn_enabled(obsolete_guard, St1) of
+ case is_warn_enabled(obsolete_guard, St0) of
true ->
- add_warning(Lr,{obsolete_guard, {F, Arity}}, St1);
+ add_warning(Lr,{obsolete_guard, {F, Arity}}, St0);
false ->
- St1
+ St0
end
end;
obsolete_guard(_G, St) ->
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index 63b397f3a5..4389fd457c 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -881,7 +881,6 @@ translate_language_element(Atom) ->
end.
old_bool_test(atom,1) -> is_atom;
-old_bool_test(constant,1) -> is_constant;
old_bool_test(float,1) -> is_float;
old_bool_test(integer,1) -> is_integer;
old_bool_test(list,1) -> is_list;
@@ -896,7 +895,6 @@ old_bool_test(record,2) -> is_record;
old_bool_test(_,_) -> undefined.
bool_test(is_atom,1) -> true;
-bool_test(is_constant,1) -> true;
bool_test(is_float,1) -> true;
bool_test(is_integer,1) -> true;
bool_test(is_list,1) -> true;
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 7bacc05ff2..b9fbef9ed0 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. 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
@@ -337,11 +337,11 @@ obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 ->
%% Added in R14B03.
obsolete_1(docb_gen, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
obsolete_1(docb_transform, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
obsolete_1(docb_xml_check, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
%% Added in R15B
obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver ->
@@ -350,10 +350,18 @@ obsolete_1(ssl, pid, 1) ->
{deprecated,"deprecated (will be removed in R17); is no longer needed"};
obsolete_1(inviso, _, _) ->
{deprecated,"the inviso application has been deprecated and will be removed in R16"};
+
+%% Added in R15B01.
+obsolete_1(gs, _, _) ->
+ {deprecated,"the gs application has been deprecated and will be removed in R16; use the wx application instead"};
+obsolete_1(ssh, sign_data, 2) ->
+ {deprecated,"deprecated (will be removed in R16A); use public_key:pem_decode/1, public_key:pem_entry_decode/1 "
+ "and public_key:sign/3 instead"};
+obsolete_1(ssh, verify_data, 3) ->
+ {deprecated,"deprecated (will be removed in R16A); use public_key:ssh_decode/1, and public_key:verify/4 instead"};
obsolete_1(_, _, _) ->
no.
-
-spec is_snmp_agent_function(atom(), byte()) -> boolean().
is_snmp_agent_function(c, 1) -> true;
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index c9688354b1..a17307b07b 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -455,7 +455,6 @@ old_guards(Config) when is_list(Config) ->
?line setup(Config),
Tests = [
{atom,is_atom},
- {constant,is_constant},
{float,is_float},
{integer,is_integer},
{list,is_list},
@@ -490,7 +489,6 @@ old_guards(Config) when is_list(Config) ->
?line [{'$1',[{is_integer,'$1'},
{is_float,'$1'},
{is_atom,'$1'},
- {is_constant,'$1'},
{is_list,'$1'},
{is_number,'$1'},
{is_pid,'$1'},
@@ -502,7 +500,7 @@ old_guards(Config) when is_list(Config) ->
[true]}] =
compile_and_run(RD, <<
"ets:fun2ms(fun(X) when integer(X),"
- "float(X), atom(X), constant(X),"
+ "float(X), atom(X),"
"list(X), number(X), pid(X),"
"port(X), reference(X), tuple(X),"
"binary(X), record(X,a) -> true end)"
@@ -530,7 +528,6 @@ autoimported(Config) when is_list(Config) ->
{self,0},
%{float,1}, see float_1_function/1
{is_atom,1},
- {is_constant,1},
{is_float,1},
{is_integer,1},
{is_list,1},
diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl
index c8dca9a6e6..f11c6ec4d6 100644
--- a/lib/stdlib/test/sofs_SUITE.erl
+++ b/lib/stdlib/test/sofs_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. 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
@@ -536,7 +536,7 @@ projection(Conf) when is_list(Conf) ->
from_term([], [[atom]]))),
?line {'EXIT', {badarg, _}} =
(catch projection({external, fun(X) -> X end}, from_term([[a]]))),
- ?line eval(projection({sofs,union},
+ ?line eval(projection(fun sofs:union/1,
from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
from_term([[1,2,3], [a,b,c]])),
?line eval(projection(fun(_) -> from_term([a]) end,
@@ -628,7 +628,7 @@ substitution(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch substitution({external, fun(X) -> X end}, from_term([[a]]))),
?line eval(substitution(fun(X) -> X end, from_term([], [[atom]])), E),
- ?line eval(substitution({sofs,union},
+ ?line eval(substitution(fun sofs:union/1,
from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
from_term([{[[1,2],[2,3]],[1,2,3]}, {[[a,b],[b,c]],[a,b,c]}])),
?line eval(substitution(fun(_) -> from_term([a]) end,
@@ -745,7 +745,7 @@ restriction(Conf) when is_list(Conf) ->
?line eval(restriction(Id, S3, E), E),
?line eval(restriction(Id, from_term([], [[atom]]), set([a])),
from_term([], [[atom]])),
- ?line eval(restriction({sofs,union},
+ ?line eval(restriction(fun sofs:union/1,
from_term([[[a],[b]], [[b],[c]],
[[], [a,b]], [[1],[2]]]),
from_term([[a,b],[1,2,3],[b,c]])),
@@ -862,7 +862,7 @@ drestriction(Conf) when is_list(Conf) ->
?line eval(drestriction(Id, S3, E), S3),
?line eval(drestriction(Id, from_term([], [[atom]]), set([a])),
from_term([], [[atom]])),
- ?line eval(drestriction({sofs,union},
+ ?line eval(drestriction(fun sofs:union/1,
from_term([[[a],[b]], [[b],[c]],
[[], [a,b]], [[1],[2]]]),
from_term([[a,b],[1,2,3],[b,c]])),
@@ -1028,7 +1028,7 @@ specification(Conf) when is_list(Conf) ->
end,
?line eval(specification({external,Fun2x}, S2), from_term([[1],[3]])),
- Fun3 = fun(_) -> neither_true_or_false end,
+ Fun3 = fun(_) -> neither_true_nor_false end,
?line {'EXIT', {badarg, _}} =
(catch specification(Fun3, set([a]))),
?line {'EXIT', {badarg, _}} =
@@ -1810,8 +1810,8 @@ partition_3(Conf) when is_list(Conf) ->
S12a = from_term([[[a],[b]], [[b],[c]], [[], [a,b]], [[1],[2]]]),
S12b = from_term([[a,b],[1,2,3],[b,c]]),
- ?line eval(partition({sofs,union}, S12a, S12b),
- lpartition({sofs,union}, S12a, S12b)),
+ ?line eval(partition(fun sofs:union/1, S12a, S12b),
+ lpartition(fun sofs:union/1, S12a, S12b)),
Fun13 = fun(_) -> from_term([a]) end,
S13a = from_term([], [[atom]]),
@@ -1956,21 +1956,8 @@ misc(Conf) when is_list(Conf) ->
% the "functional" part:
?line eval(union(intersection(partition(1,S), partition(Id,S))),
difference(S, RR)),
-
- %% The function external:foo/1 is undefined.
- case test_server:is_native(sofs) of
- true ->
- %% Create an export entry for external:foo/1 to work
- %% around a bug in the native code. If there is no
- %% export entry, the exception will be
- %% {badfun,{external,foo}}. Remove in R16 when tuple
- %% funs are removed.
- (catch external:foo([]));
- false ->
- ok
- end,
?line {'EXIT', {undef, _}} =
- (catch projection({external,foo}, set([a,b,c]))),
+ (catch projection(fun external:foo/1, set([a,b,c]))),
ok.
relational_restriction(R) ->
@@ -1983,19 +1970,19 @@ family_specification(doc) -> [""];
family_specification(Conf) when is_list(Conf) ->
E = empty_set(),
%% internal
- ?line eval(family_specification({sofs, is_set}, E), E),
+ ?line eval(family_specification(fun sofs:is_set/1, E), E),
?line {'EXIT', {badarg, _}} =
- (catch family_specification({sofs,is_set}, set([]))),
+ (catch family_specification(fun sofs:is_set/1, set([]))),
?line F1 = from_term([{1,[1]}]),
- ?line eval(family_specification({sofs,is_set}, F1), F1),
+ ?line eval(family_specification(fun sofs:is_set/1, F1), F1),
Fun = fun(S) -> is_subset(S, set([0,1,2,3,4])) end,
?line F2 = family([{a,[1,2]},{b,[3,4,5]}]),
?line eval(family_specification(Fun, F2), family([{a,[1,2]}])),
?line F3 = from_term([{a,[]},{b,[]}]),
- ?line eval(family_specification({sofs,is_set}, F3), F3),
+ ?line eval(family_specification(fun sofs:is_set/1, F3), F3),
Fun2 = fun(_) -> throw(fippla) end,
?line fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
- Fun3 = fun(_) -> neither_true_or_false end,
+ Fun3 = fun(_) -> neither_true_nor_false end,
?line {'EXIT', {badarg, _}} =
(catch family_specification(Fun3, F3)),
@@ -2110,22 +2097,22 @@ family_projection(Conf) when is_list(Conf) ->
?line eval(family_projection(fun(X) -> X end, family([])), E),
?line L1 = [{a,[]}],
- ?line eval(family_projection({sofs,union}, E), E),
- ?line eval(family_projection({sofs,union}, from_term(L1, SSType)),
+ ?line eval(family_projection(fun sofs:union/1, E), E),
+ ?line eval(family_projection(fun sofs:union/1, from_term(L1, SSType)),
family(L1)),
?line {'EXIT', {badarg, _}} =
- (catch family_projection({sofs,union}, set([]))),
+ (catch family_projection(fun sofs:union/1, set([]))),
?line {'EXIT', {badarg, _}} =
- (catch family_projection({sofs,union}, from_term([{1,[1]}]))),
+ (catch family_projection(fun sofs:union/1, from_term([{1,[1]}]))),
?line F2 = from_term([{a,[[1],[2]]},{b,[[3,4],[5]]}], SSType),
- ?line eval(family_projection({sofs,union}, F2),
+ ?line eval(family_projection(fun sofs:union/1, F2),
family_union(F2)),
?line F3 = from_term([{1,[{a,b},{b,c},{c,d}]},{3,[]},{5,[{3,5}]}],
SRType),
- ?line eval(family_projection({sofs,domain}, F3), family_domain(F3)),
- ?line eval(family_projection({sofs,range}, F3), family_range(F3)),
+ ?line eval(family_projection(fun sofs:domain/1, F3), family_domain(F3)),
+ ?line eval(family_projection(fun sofs:range/1, F3), family_range(F3)),
?line eval(family_projection(fun(_) -> E end, family([{a,[b,c]}])),
from_term([{a,[]}])),
@@ -2305,7 +2292,7 @@ partition_family(Conf) when is_list(Conf) ->
?line eval(partition_family(1, E), E),
?line eval(partition_family(2, E), E),
- ?line eval(partition_family({sofs,union}, E), E),
+ ?line eval(partition_family(fun sofs:union/1, E), E),
?line eval(partition_family(1, ER), EF),
?line eval(partition_family(2, ER), EF),
?line {'EXIT', {badarg, _}} = (catch partition_family(1, set([]))),
@@ -2369,7 +2356,7 @@ partition_family(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch partition_family({external, fun(X) -> X end},
from_term([[a]]))),
- ?line eval(partition_family({sofs,union},
+ ?line eval(partition_family(fun sofs:union/1,
from_term([[[1],[1,2]], [[1,2]]])),
from_term([{[1,2], [[[1],[1,2]],[[1,2]]]}])),
?line eval(partition_family(fun(X) -> X end,
diff --git a/lib/toolbar/doc/src/toolbar.xml b/lib/toolbar/doc/src/toolbar.xml
index ad379438fe..3ad0b4eb78 100644
--- a/lib/toolbar/doc/src/toolbar.xml
+++ b/lib/toolbar/doc/src/toolbar.xml
@@ -33,6 +33,11 @@
<module>toolbar</module>
<modulesummary>GUI for Starting Tools and User Contributions</modulesummary>
<description>
+ <warning>
+ <p>
+ The Toolbar application is deprecated and will be removed in R16.
+ </p>
+ </warning>
<p>Toolbar makes it easier to use
the different Erlang tools - and the user contributions - which are provided.
It has a graphical user interface with an icon for each tool.
diff --git a/lib/toolbar/doc/src/toolbar_chapter.xml b/lib/toolbar/doc/src/toolbar_chapter.xml
index a80dc5bd3e..4ea2101218 100644
--- a/lib/toolbar/doc/src/toolbar_chapter.xml
+++ b/lib/toolbar/doc/src/toolbar_chapter.xml
@@ -28,6 +28,11 @@
<rev>A</rev>
<file>toolbar_chapter.xml</file>
</header>
+ <warning>
+ <p>
+ The Toolbar application is deprecated and will be removed in R16.
+ </p>
+ </warning>
<p>Toolbar provides an interface to the various Erlang tools which are available. Toolbar can also provide access to user supplied tools which are included with the Erlang software release. These tools are called GS Contributions.</p>
<p>All tools included in Toolbar must have a configuration file which contains information about the tool, such as its start function and the location of help information. The name of a configuration file must include the suffix <c>.tool</c>.
</p>
diff --git a/lib/toolbar/src/canvasbutton.erl b/lib/toolbar/src/canvasbutton.erl
index 38fce537bb..7613253efe 100644
--- a/lib/toolbar/src/canvasbutton.erl
+++ b/lib/toolbar/src/canvasbutton.erl
@@ -17,6 +17,9 @@
%% %CopyrightEnd%
%%
-module(canvasbutton).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar.erl b/lib/toolbar/src/toolbar.erl
index 67967172fe..b78df15700 100644
--- a/lib/toolbar/src/toolbar.erl
+++ b/lib/toolbar/src/toolbar.erl
@@ -17,6 +17,7 @@
%% %CopyrightEnd%
%%
-module(toolbar).
+-compile([{nowarn_deprecated_function,{gs,start,1}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar_graphics.erl b/lib/toolbar/src/toolbar_graphics.erl
index ad390440e3..b442d7ff06 100644
--- a/lib/toolbar/src/toolbar_graphics.erl
+++ b/lib/toolbar/src/toolbar_graphics.erl
@@ -17,6 +17,9 @@
%% %CopyrightEnd%
%%
-module(toolbar_graphics).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar_toolconfig.erl b/lib/toolbar/src/toolbar_toolconfig.erl
index 6dccb7ba72..6fb56cb1bd 100644
--- a/lib/toolbar/src/toolbar_toolconfig.erl
+++ b/lib/toolbar/src/toolbar_toolconfig.erl
@@ -17,6 +17,11 @@
%% %CopyrightEnd%
%%
-module(toolbar_toolconfig).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/tv/doc/src/table_visualizer_chapter.xml b/lib/tv/doc/src/table_visualizer_chapter.xml
index 12efbe643c..dbfd322945 100644
--- a/lib/tv/doc/src/table_visualizer_chapter.xml
+++ b/lib/tv/doc/src/table_visualizer_chapter.xml
@@ -31,6 +31,12 @@
<rev>C</rev>
<file>table_visualizer.xml</file>
</header>
+ <warning>
+ <p>
+ The TV application has been superseded by the Observer application.
+ TV will be removed in R16.
+ </p>
+ </warning>
<p>The TV, TV, is a tool that enables the user to examine
ETS and Mnesia tables on any (connected) node in the currently running Erlang
system. Once a certain table has been opened in the tool, the content may be
diff --git a/lib/tv/doc/src/tv.xml b/lib/tv/doc/src/tv.xml
index 84b9f8c33d..83bbdfc052 100644
--- a/lib/tv/doc/src/tv.xml
+++ b/lib/tv/doc/src/tv.xml
@@ -36,6 +36,12 @@
<module>tv</module>
<modulesummary>TV graphically examines ETS and Mnesia tables. </modulesummary>
<description>
+ <warning>
+ <p>
+ The TV application has been superseded by the Observer application.
+ TV will be removed in R16.
+ </p>
+ </warning>
<p>TV enables the user to examine ETS and Mnesia tables. Once
a certain table has been opened in the tool, the content may be viewed at
various levels of detail. The content viewed may also be sorted, using any
diff --git a/lib/tv/src/tv_db.erl b/lib/tv/src/tv_db.erl
index 201b4c0e6b..179b75c2e6 100644
--- a/lib/tv/src/tv_db.erl
+++ b/lib/tv/src/tv_db.erl
@@ -22,6 +22,10 @@
%%%*********************************************************************
-module(tv_db).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_db_search.erl b/lib/tv/src/tv_db_search.erl
index 7bf5c4c048..6ae999253a 100644
--- a/lib/tv/src/tv_db_search.erl
+++ b/lib/tv/src/tv_db_search.erl
@@ -21,6 +21,18 @@
%%%
%%%*********************************************************************
-module(tv_db_search).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_etsread.erl b/lib/tv/src/tv_etsread.erl
index d3240ef513..b3e38f9d45 100644
--- a/lib/tv/src/tv_etsread.erl
+++ b/lib/tv/src/tv_etsread.erl
@@ -25,6 +25,9 @@
-module(tv_etsread).
+-compile([{nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_info.erl b/lib/tv/src/tv_info.erl
index 7bc31e35cd..941286362c 100644
--- a/lib/tv/src/tv_info.erl
+++ b/lib/tv/src/tv_info.erl
@@ -16,6 +16,14 @@
%%
%% %CopyrightEnd%
-module(tv_info).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_ip.erl b/lib/tv/src/tv_ip.erl
index aeec4e8f6d..2d3ada878a 100644
--- a/lib/tv/src/tv_ip.erl
+++ b/lib/tv/src/tv_ip.erl
@@ -16,6 +16,12 @@
%%
%% %CopyrightEnd%
-module(tv_ip).
+-compile([{nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_main.erl b/lib/tv/src/tv_main.erl
index 36cf92bee3..fbf56971f9 100644
--- a/lib/tv/src/tv_main.erl
+++ b/lib/tv/src/tv_main.erl
@@ -16,6 +16,20 @@
%%
%% %CopyrightEnd%
-module(tv_main).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_new_table.erl b/lib/tv/src/tv_new_table.erl
index 3d62b0548b..d31b9a4ee2 100644
--- a/lib/tv/src/tv_new_table.erl
+++ b/lib/tv/src/tv_new_table.erl
@@ -16,6 +16,16 @@
%%
%% %CopyrightEnd%k
-module(tv_new_table).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_nodewin.erl b/lib/tv/src/tv_nodewin.erl
index 3999d201d8..9030ed930f 100644
--- a/lib/tv/src/tv_nodewin.erl
+++ b/lib/tv/src/tv_nodewin.erl
@@ -16,6 +16,15 @@
%%
%% %CopyrightEnd%
-module(tv_nodewin).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pb.erl b/lib/tv/src/tv_pb.erl
index 78a27185dc..fa3dcde919 100644
--- a/lib/tv/src/tv_pb.erl
+++ b/lib/tv/src/tv_pb.erl
@@ -16,6 +16,9 @@
%%
%% %CopyrightEnd%
-module(tv_pb).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}}]).
diff --git a/lib/tv/src/tv_pb_funcs.erl b/lib/tv/src/tv_pb_funcs.erl
index 87a4719bbd..0670d2795f 100644
--- a/lib/tv/src/tv_pb_funcs.erl
+++ b/lib/tv/src/tv_pb_funcs.erl
@@ -16,6 +16,12 @@
%%
%% %CopyrightEnd%
-module(tv_pb_funcs).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_pc.erl b/lib/tv/src/tv_pc.erl
index 50214fe06a..fcb7aba3a7 100644
--- a/lib/tv/src/tv_pc.erl
+++ b/lib/tv/src/tv_pc.erl
@@ -25,6 +25,7 @@
-module(tv_pc).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pc_menu_handling.erl b/lib/tv/src/tv_pc_menu_handling.erl
index 16195bf91f..5d411b106e 100644
--- a/lib/tv/src/tv_pc_menu_handling.erl
+++ b/lib/tv/src/tv_pc_menu_handling.erl
@@ -25,6 +25,10 @@
-module(tv_pc_menu_handling).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pd.erl b/lib/tv/src/tv_pd.erl
index ea14bf67b1..6694ea22a3 100644
--- a/lib/tv/src/tv_pd.erl
+++ b/lib/tv/src/tv_pd.erl
@@ -24,6 +24,11 @@
-module(tv_pd).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pd_display.erl b/lib/tv/src/tv_pd_display.erl
index f5a30cb640..dab442e28e 100644
--- a/lib/tv/src/tv_pd_display.erl
+++ b/lib/tv/src/tv_pd_display.erl
@@ -22,6 +22,13 @@
%%%*********************************************************************
-module(tv_pd_display).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_pd_frames.erl b/lib/tv/src/tv_pd_frames.erl
index 4e091ac9f0..d18dcaf70d 100644
--- a/lib/tv/src/tv_pd_frames.erl
+++ b/lib/tv/src/tv_pd_frames.erl
@@ -16,6 +16,8 @@
%%
%% %CopyrightEnd%
-module(tv_pd_frames).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,frame,2}}]).
diff --git a/lib/tv/src/tv_pd_scale.erl b/lib/tv/src/tv_pd_scale.erl
index c94e57f468..2f98c3183f 100644
--- a/lib/tv/src/tv_pd_scale.erl
+++ b/lib/tv/src/tv_pd_scale.erl
@@ -24,6 +24,8 @@
-module(tv_pd_scale).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,scale,2}}]).
diff --git a/lib/tv/src/tv_pg.erl b/lib/tv/src/tv_pg.erl
index ba8782392b..0b36b18212 100644
--- a/lib/tv/src/tv_pg.erl
+++ b/lib/tv/src/tv_pg.erl
@@ -16,6 +16,7 @@
%%
%% %CopyrightEnd%
-module(tv_pg).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pg_gridfcns.erl b/lib/tv/src/tv_pg_gridfcns.erl
index 3d23c8a69f..e47dac28a8 100644
--- a/lib/tv/src/tv_pg_gridfcns.erl
+++ b/lib/tv/src/tv_pg_gridfcns.erl
@@ -16,6 +16,10 @@
%%
%% %CopyrightEnd%
-module(tv_pg_gridfcns).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_poll_dialog.erl b/lib/tv/src/tv_poll_dialog.erl
index 8d41251266..4bf49f44f1 100644
--- a/lib/tv/src/tv_poll_dialog.erl
+++ b/lib/tv/src/tv_poll_dialog.erl
@@ -22,7 +22,13 @@
%%%*********************************************************************
-module(tv_poll_dialog).
-
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/1, init/2]).
diff --git a/lib/tv/src/tv_pw.erl b/lib/tv/src/tv_pw.erl
index 8b3186e090..bd6d06e241 100644
--- a/lib/tv/src/tv_pw.erl
+++ b/lib/tv/src/tv_pw.erl
@@ -23,6 +23,7 @@
-module(tv_pw).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pw_window.erl b/lib/tv/src/tv_pw_window.erl
index 9cb5c879c0..0cd241a031 100644
--- a/lib/tv/src/tv_pw_window.erl
+++ b/lib/tv/src/tv_pw_window.erl
@@ -23,6 +23,10 @@
-module(tv_pw_window).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
diff --git a/lib/tv/src/tv_rec_edit.erl b/lib/tv/src/tv_rec_edit.erl
index e8f663073e..f6c09ebc67 100644
--- a/lib/tv/src/tv_rec_edit.erl
+++ b/lib/tv/src/tv_rec_edit.erl
@@ -16,6 +16,16 @@
%%
%% %CopyrightEnd%
-module(tv_rec_edit).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_utils.erl b/lib/tv/src/tv_utils.erl
index fd232bde69..9c7458d302 100644
--- a/lib/tv/src/tv_utils.erl
+++ b/lib/tv/src/tv_utils.erl
@@ -16,6 +16,9 @@
%%
%% %CopyrightEnd%
-module(tv_utils).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}}]).
diff --git a/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf b/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
index f691c6cfd1..31f5306c1a 100644
--- a/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
+++ b/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
@@ -59,7 +59,7 @@ erl_xcomp_host=avr32-atmel-linux-gnu
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
# `configure' script.
-#erl_xcomp_configure_flags=
+erl_xcomp_configure_flags="--disable-hipe --disable-threads --disable-smp"
## -- Cross Compiler and Other Tools -------------------------------------------
@@ -73,7 +73,7 @@ erl_xcomp_host=avr32-atmel-linux-gnu
CC=avr32-linux-gcc
# * `CFLAGS' - C compiler flags.
-#CFLAGS=
+CFLAGS="-O -Dfinite=__finite"
# * `STATIC_CFLAGS' - Static C compiler flags.
#STATIC_CFLAGS=