%% %% 2005-2007 %% Ericsson AB, 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. %% %% The Initial Developer of the Original Code is Ericsson AB. %% %% %%% Description: ssh shell client -module(ssh_ssh). -export([connect/1, connect/2, connect/3]). -export([input_loop/2, shell_loop/4]). -include("ssh.hrl"). -include("ssh_connect.hrl"). -define(default_timeout, 10000). connect(A) -> connect(A, []). connect(Host, Opts) when is_list(Host) -> connect(Host, 22, Opts); connect(CM, Opts) -> Timeout = proplists:get_value(connect_timeout, Opts, ?default_timeout), case ssh_cm:attach(CM, Timeout) of {ok,CMPid} -> session(CMPid, Timeout); Error -> Error end. connect(Host, Port, Opts) -> case ssh_cm:connect(Host, Port, Opts) of {ok, CM} -> session(CM, proplists:get_value(connect_timeout, Opts, ?default_timeout)); Error -> Error end. session(CM, Timeout) -> case ssh_cm:session_open(CM, Timeout) of {ok,Channel} -> case ssh_cm:shell(CM, Channel) of ok -> {group_leader,GIO} = process_info(self(), group_leader), IO = spawn(?MODULE, input_loop, [GIO, self()]), shell_loop(CM, Channel, IO, false); Error -> ssh_cm:close(CM, Channel), Error end; Error -> Error end. input_loop(Fd, Pid) -> case io:get_line(Fd, '>') of eof -> Pid ! {input, self(), eof}, ok; % input_loop(Fd, Pid); Line -> Pid ! {input, self(), Line}, input_loop(Fd, Pid) end. shell_loop(CM, Channel, IO, SentClose) -> receive {input, IO, eof} -> ssh_cm:send_eof(CM, Channel), ?MODULE:shell_loop(CM, Channel, IO, SentClose); {input, IO, Line} -> ssh_cm:send(CM, Channel, Line), ?MODULE:shell_loop(CM, Channel, IO, SentClose); {ssh_cm, CM, {data, Channel, Type, Data}} -> if Type == 0 -> io:format("~s", [binary_to_list(Data)]); Type == ?SSH_EXTENDED_DATA_STDERR -> error_logger:format("ssh: STDERR: ~s", [binary_to_list(Data)]); true -> ok end, ssh_cm:adjust_window(CM, Channel, size(Data)), ?MODULE:shell_loop(CM, Channel, IO, SentClose); {ssh_cm, CM, {exit_signal, Channel, _SIG, _Err, _Lang}} -> ?dbg(true, "SIGNAL: ~s (~s)\n", [_SIG, _Err]), send_close(SentClose, CM, Channel), ?MODULE:shell_loop(CM, Channel, IO, true); {ssh_cm, CM, {exit_status,Channel,_Status}} -> %send_close(SentClose, CM, Channel), ?MODULE:shell_loop(CM, Channel, IO, true); {ssh_cm, CM, {eof, Channel}} -> %send_close(SentClose, CM, Channel), ?MODULE:shell_loop(CM, Channel, IO, true); {ssh_cm, CM, {closed, Channel}} -> ssh_cm:detach(CM, ?default_timeout), exit(IO, kill); Other -> error_logger:format("ssh_ssh:shell_loop: unexpected msg ~p\n", [Other]) end. send_close(false, CM, Channel) -> ssh_cm:close(CM, Channel); send_close(_, _, _) -> ok.