4
%% Copyright Ericsson AB 2009. All Rights Reserved.
6
%% The contents of this file are subject to the Erlang Public License,
7
%% Version 1.1, (the "License"); you may not use this file except in
8
%% compliance with the License. You should have received a copy of the
9
%% Erlang Public License along with this software. If not, it can be
10
%% retrieved online at http://www.erlang.org/.
12
%% Software distributed under the License is distributed on an "AS IS"
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
%% the License for the specific language governing rights and limitations
24
-include("ssh_connect.hrl").
26
-behaviour(ssh_channel).
28
%% ssh_channel callbacks
29
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
32
-export([input_loop/2]).
37
channel, %% Id of the ssh channel
38
cm %% Ssh connection manager
42
%%====================================================================
43
%% ssh_channel callbacks
44
%%====================================================================
46
%%--------------------------------------------------------------------
47
%% Function: init(Args) -> {ok, State}
49
%% Description: Initiates the CLI
50
%%--------------------------------------------------------------------
51
init([ConnectionManager, ChannelId] = Args) ->
53
%% Make sure that we are proclib compatible as
54
%% this client should be runnable from the
56
case get('$initial_call') of
59
Ancestors = get_ancestors(),
60
put('$ancestors', [Me | Ancestors]),
61
put('$initial_call', {?MODULE, init, Args});
66
case ssh_connection:shell(ConnectionManager, ChannelId) of
69
process_info(self(), group_leader),
70
IoPid = spawn_link(?MODULE, input_loop,
72
{ok, #state{io = IoPid,
74
cm = ConnectionManager}};
79
%%--------------------------------------------------------------------
80
%% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State}
82
%% Description: Handles channel messages received on the ssh-connection.
83
%%--------------------------------------------------------------------
84
handle_ssh_msg({ssh_cm, _, {data, _ChannelId, 0, Data}}, State) ->
85
%% TODO: When unicode support is ready
86
%% should we call this function or perhaps a new
91
handle_ssh_msg({ssh_cm, _,
92
{data, _ChannelId, ?SSH_EXTENDED_DATA_STDERR, Data}},
94
%% TODO: When unicode support is ready
95
%% should we call this function or perhaps a new
100
handle_ssh_msg({ssh_cm, _, {eof, _ChannelId}}, State) ->
103
handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
104
%% Ignore signals according to RFC 4254 section 6.9.
107
handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}}, State) ->
108
io:put_chars("Connection closed by peer"),
109
%% TODO: When unicode support is ready
110
%% should we call this function or perhaps a new
111
%% function. The error is encoded as UTF-8!
113
{stop, ChannelId, State};
115
handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, 0}}, State) ->
116
io:put_chars("logout"),
117
io:put_chars("Connection closed"),
118
{stop, ChannelId, State};
120
handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State) ->
121
io:put_chars("Connection closed by peer"),
122
io:put_chars("Status: " ++ integer_to_list(Status)),
123
{stop, ChannelId, State}.
125
%%--------------------------------------------------------------------
126
%% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State}
128
%% Description: Handles other channel messages
129
%%--------------------------------------------------------------------
130
handle_msg({ssh_channel_up, ChannelId, ConnectionManager},
131
#state{channel = ChannelId,
132
cm = ConnectionManager} = State) ->
135
handle_msg({input, IoPid, eof}, #state{io = IoPid, channel = ChannelId,
136
cm = ConnectionManager} = State) ->
137
ssh_connection:send_eof(ConnectionManager, ChannelId),
140
handle_msg({input, IoPid, Line}, #state{io = IoPid,
142
cm = ConnectionManager} = State) ->
143
ssh_connection:send(ConnectionManager, ChannelId, Line),
146
%%--------------------------------------------------------------------
147
%% Function: terminate(Reasons, State) -> _
149
%% Description: Cleanup when shell channel is terminated
150
%%--------------------------------------------------------------------
151
terminate(_Reason, #state{io = IoPid}) ->
154
%%--------------------------------------------------------------------
155
%%% Internal functions
156
%%--------------------------------------------------------------------
158
input_loop(Fd, Pid) ->
159
case io:get_line(Fd, '>') of
161
Pid ! {input, self(), eof},
164
Pid ! {input, self(), Line},
169
case process_info(self(),registered_name) of
170
{registered_name,Name} -> Name;
175
case get('$ancestors') of
176
A when is_list(A) -> A;