0
|
1 /*
|
|
2 * ConnectBot: simple, powerful, open-source SSH client for Android
|
|
3 * Copyright 2007 Kenny Root, Jeffrey Sharkey
|
|
4 *
|
|
5 * Licensed under the Apache License, Version 2.0 (the "License");
|
|
6 * you may not use this file except in compliance with the License.
|
|
7 * You may obtain a copy of the License at
|
|
8 *
|
|
9 * http://www.apache.org/licenses/LICENSE-2.0
|
|
10 *
|
|
11 * Unless required by applicable law or agreed to in writing, software
|
|
12 * distributed under the License is distributed on an "AS IS" BASIS,
|
|
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14 * See the License for the specific language governing permissions and
|
|
15 * limitations under the License.
|
|
16 */
|
|
17
|
|
18 package com.five_ten_sg.connectbot.transport;
|
|
19
|
|
20 import java.io.FileDescriptor;
|
|
21 import java.io.FileInputStream;
|
|
22 import java.io.FileOutputStream;
|
|
23 import java.io.IOException;
|
|
24 import java.util.Map;
|
|
25
|
|
26 import com.five_ten_sg.connectbot.R;
|
|
27 import com.five_ten_sg.connectbot.bean.HostBean;
|
|
28 import com.five_ten_sg.connectbot.service.TerminalBridge;
|
|
29 import com.five_ten_sg.connectbot.service.TerminalManager;
|
|
30 import com.five_ten_sg.connectbot.util.HostDatabase;
|
|
31 import android.content.Context;
|
|
32 import android.net.Uri;
|
|
33 import android.util.Log;
|
|
34
|
|
35 import com.google.ase.Exec;
|
|
36
|
|
37 /**
|
|
38 * @author Kenny Root
|
|
39 *
|
|
40 */
|
|
41 public class Local extends AbsTransport {
|
|
42 private static final String TAG = "ConnectBot.Local";
|
|
43 private static final String PROTOCOL = "local";
|
|
44
|
|
45 private static final String DEFAULT_URI = "local:#Local";
|
|
46
|
|
47 private FileDescriptor shellFd;
|
|
48
|
|
49 private FileInputStream is;
|
|
50 private FileOutputStream os;
|
|
51
|
|
52 /**
|
|
53 *
|
|
54 */
|
|
55 public Local() {
|
|
56 }
|
|
57
|
|
58 /**
|
|
59 * @param host
|
|
60 * @param bridge
|
|
61 * @param manager
|
|
62 */
|
|
63 public Local(HostBean host, TerminalBridge bridge, TerminalManager manager) {
|
|
64 super(host, bridge, manager);
|
|
65 }
|
|
66
|
|
67 public static String getProtocolName() {
|
|
68 return PROTOCOL;
|
|
69 }
|
|
70
|
|
71 @Override
|
|
72 public void close() {
|
|
73 try {
|
|
74 if (os != null) {
|
|
75 os.close();
|
|
76 os = null;
|
|
77 }
|
|
78
|
|
79 if (is != null) {
|
|
80 is.close();
|
|
81 is = null;
|
|
82 }
|
|
83 }
|
|
84 catch (IOException e) {
|
|
85 Log.e(TAG, "Couldn't close shell", e);
|
|
86 }
|
|
87 }
|
|
88
|
|
89 @Override
|
|
90 public void connect() {
|
|
91 int[] pids = new int[1];
|
|
92
|
|
93 try {
|
|
94 shellFd = Exec.createSubprocess("/system/bin/sh", "-", null, pids);
|
|
95 }
|
|
96 catch (Exception e) {
|
|
97 bridge.outputLine(manager.res.getString(R.string.local_shell_unavailable));
|
|
98 Log.e(TAG, "Cannot start local shell", e);
|
|
99 return;
|
|
100 }
|
|
101
|
|
102 final int shellPid = pids[0];
|
|
103 Runnable exitWatcher = new Runnable() {
|
|
104 public void run() {
|
|
105 Exec.waitFor(shellPid);
|
|
106 bridge.dispatchDisconnect(false);
|
|
107 }
|
|
108 };
|
|
109 Thread exitWatcherThread = new Thread(exitWatcher);
|
|
110 exitWatcherThread.setName("LocalExitWatcher");
|
|
111 exitWatcherThread.setDaemon(true);
|
|
112 exitWatcherThread.start();
|
|
113 is = new FileInputStream(shellFd);
|
|
114 os = new FileOutputStream(shellFd);
|
|
115 bridge.onConnected();
|
|
116 }
|
|
117
|
|
118 @Override
|
|
119 public void flush() throws IOException {
|
|
120 os.flush();
|
|
121 }
|
|
122
|
|
123 @Override
|
|
124 public String getDefaultNickname(String username, String hostname, int port) {
|
|
125 return DEFAULT_URI;
|
|
126 }
|
|
127
|
|
128 @Override
|
|
129 public int getDefaultPort() {
|
|
130 return 0;
|
|
131 }
|
|
132
|
|
133 @Override
|
|
134 public boolean isConnected() {
|
|
135 return is != null && os != null;
|
|
136 }
|
|
137
|
|
138 @Override
|
|
139 public boolean isSessionOpen() {
|
|
140 return is != null && os != null;
|
|
141 }
|
|
142
|
|
143 @Override
|
|
144 public boolean isAuthenticated() {
|
|
145 return isConnected();
|
|
146 }
|
|
147
|
|
148 @Override
|
|
149 public boolean willBlock() {
|
|
150 if (is == null) return true;
|
|
151 try {
|
|
152 return is.available() == 0;
|
|
153 } catch (Exception e) {
|
|
154 return true;
|
|
155 }
|
|
156 }
|
|
157
|
|
158 @Override
|
|
159 public int read(byte[] buffer, int start, int len) throws IOException {
|
|
160 if (is == null) {
|
|
161 bridge.dispatchDisconnect(false);
|
|
162 throw new IOException("session closed");
|
|
163 }
|
|
164
|
|
165 return is.read(buffer, start, len);
|
|
166 }
|
|
167
|
|
168 @Override
|
|
169 public void setDimensions(int columns, int rows, int width, int height) {
|
|
170 try {
|
|
171 Exec.setPtyWindowSize(shellFd, rows, columns, width, height);
|
|
172 }
|
|
173 catch (Exception e) {
|
|
174 Log.e(TAG, "Couldn't resize pty", e);
|
|
175 }
|
|
176 }
|
|
177
|
|
178 @Override
|
|
179 public void write(byte[] buffer) throws IOException {
|
|
180 if (os != null)
|
|
181 os.write(buffer);
|
|
182 }
|
|
183
|
|
184 @Override
|
|
185 public void write(int c) throws IOException {
|
|
186 if (os != null)
|
|
187 os.write(c);
|
|
188 }
|
|
189
|
12
|
190 public Uri getUri(String input) {
|
0
|
191 Uri uri = Uri.parse(DEFAULT_URI);
|
|
192
|
|
193 if (input != null && input.length() > 0) {
|
|
194 uri = uri.buildUpon().fragment(input).build();
|
|
195 }
|
|
196
|
|
197 return uri;
|
|
198 }
|
|
199
|
|
200 @Override
|
|
201 public HostBean createHost(Uri uri) {
|
|
202 HostBean host = new HostBean();
|
|
203 host.setProtocol(PROTOCOL);
|
|
204 String nickname = uri.getFragment();
|
|
205
|
|
206 if (nickname == null || nickname.length() == 0) {
|
|
207 host.setNickname(getDefaultNickname(host.getUsername(),
|
|
208 host.getHostname(), host.getPort()));
|
|
209 }
|
|
210 else {
|
|
211 host.setNickname(uri.getFragment());
|
|
212 }
|
|
213
|
|
214 return host;
|
|
215 }
|
|
216
|
|
217 @Override
|
|
218 public void getSelectionArgs(Uri uri, Map<String, String> selection) {
|
|
219 selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL);
|
|
220 selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment());
|
|
221 }
|
|
222
|
12
|
223 public String getFormatHint(Context context) {
|
0
|
224 return context.getString(R.string.hostpref_nickname_title);
|
|
225 }
|
|
226
|
|
227 @Override
|
|
228 public boolean usesNetwork() {
|
|
229 return false;
|
|
230 }
|
|
231 }
|