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 private static final String DEFAULT_URI = "local:#Local";
|
|
45
|
31
|
46 private FileDescriptor shellFd;
|
|
47 private FileInputStream is;
|
0
|
48 private FileOutputStream os;
|
|
49
|
|
50 /**
|
|
51 *
|
|
52 */
|
|
53 public Local() {
|
|
54 }
|
|
55
|
|
56
|
|
57 public static String getProtocolName() {
|
|
58 return PROTOCOL;
|
|
59 }
|
|
60
|
31
|
61
|
|
62 public Uri getUri(String input) {
|
|
63 Uri uri = Uri.parse(DEFAULT_URI);
|
0
|
64
|
31
|
65 if (input != null && input.length() > 0) {
|
|
66 uri = uri.buildUpon().fragment(input).build();
|
0
|
67 }
|
31
|
68
|
|
69 return uri;
|
0
|
70 }
|
|
71
|
31
|
72
|
0
|
73 @Override
|
|
74 public void connect() {
|
|
75 int[] pids = new int[1];
|
|
76
|
|
77 try {
|
|
78 shellFd = Exec.createSubprocess("/system/bin/sh", "-", null, pids);
|
|
79 }
|
|
80 catch (Exception e) {
|
|
81 bridge.outputLine(manager.res.getString(R.string.local_shell_unavailable));
|
|
82 Log.e(TAG, "Cannot start local shell", e);
|
|
83 return;
|
|
84 }
|
|
85
|
|
86 final int shellPid = pids[0];
|
|
87 Runnable exitWatcher = new Runnable() {
|
|
88 public void run() {
|
|
89 Exec.waitFor(shellPid);
|
|
90 bridge.dispatchDisconnect(false);
|
|
91 }
|
|
92 };
|
|
93 Thread exitWatcherThread = new Thread(exitWatcher);
|
|
94 exitWatcherThread.setName("LocalExitWatcher");
|
|
95 exitWatcherThread.setDaemon(true);
|
|
96 exitWatcherThread.start();
|
|
97 is = new FileInputStream(shellFd);
|
|
98 os = new FileOutputStream(shellFd);
|
|
99 bridge.onConnected();
|
|
100 }
|
|
101
|
|
102
|
|
103 @Override
|
|
104 public boolean willBlock() {
|
|
105 if (is == null) return true;
|
112
|
106
|
0
|
107 try {
|
|
108 return is.available() == 0;
|
112
|
109 }
|
|
110 catch (Exception e) {
|
0
|
111 return true;
|
|
112 }
|
|
113 }
|
|
114
|
|
115 @Override
|
|
116 public int read(byte[] buffer, int start, int len) throws IOException {
|
|
117 if (is == null) {
|
|
118 bridge.dispatchDisconnect(false);
|
|
119 throw new IOException("session closed");
|
|
120 }
|
|
121
|
|
122 return is.read(buffer, start, len);
|
|
123 }
|
|
124
|
|
125 @Override
|
|
126 public void write(byte[] buffer) throws IOException {
|
|
127 if (os != null)
|
|
128 os.write(buffer);
|
|
129 }
|
|
130
|
|
131 @Override
|
|
132 public void write(int c) throws IOException {
|
|
133 if (os != null)
|
|
134 os.write(c);
|
|
135 }
|
|
136
|
31
|
137 @Override
|
|
138 public void flush() throws IOException {
|
|
139 os.flush();
|
|
140 }
|
|
141
|
|
142 @Override
|
|
143 public void close() {
|
|
144 try {
|
|
145 if (os != null) {
|
|
146 os.close();
|
|
147 os = null;
|
|
148 }
|
|
149
|
|
150 if (is != null) {
|
|
151 is.close();
|
|
152 is = null;
|
|
153 }
|
|
154 }
|
|
155 catch (IOException e) {
|
|
156 Log.e(TAG, "Couldn't close shell", e);
|
|
157 }
|
|
158 }
|
0
|
159
|
31
|
160 @Override
|
|
161 public void setDimensions(int columns, int rows, int width, int height) {
|
|
162 try {
|
|
163 Exec.setPtyWindowSize(shellFd, rows, columns, width, height);
|
|
164 }
|
|
165 catch (Exception e) {
|
|
166 Log.e(TAG, "Couldn't resize pty", e);
|
0
|
167 }
|
31
|
168 }
|
0
|
169
|
31
|
170 @Override
|
|
171 public int getDefaultPort() {
|
|
172 return 0;
|
|
173 }
|
|
174
|
|
175 @Override
|
|
176 public boolean isConnected() {
|
|
177 return is != null && os != null;
|
|
178 }
|
|
179
|
|
180 @Override
|
|
181 public boolean isSessionOpen() {
|
|
182 return isConnected();
|
|
183 }
|
|
184
|
|
185 @Override
|
|
186 public boolean isAuthenticated() {
|
|
187 return isConnected();
|
|
188 }
|
|
189
|
|
190 @Override
|
|
191 public String getDefaultNickname(String username, String hostname, int port) {
|
|
192 return DEFAULT_URI;
|
|
193 }
|
|
194
|
|
195 @Override
|
|
196 public void getSelectionArgs(Uri uri, Map<String, String> selection) {
|
|
197 selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL);
|
|
198 selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment());
|
0
|
199 }
|
|
200
|
|
201 @Override
|
|
202 public HostBean createHost(Uri uri) {
|
|
203 HostBean host = new HostBean();
|
|
204 host.setProtocol(PROTOCOL);
|
|
205 String nickname = uri.getFragment();
|
|
206
|
|
207 if (nickname == null || nickname.length() == 0) {
|
|
208 host.setNickname(getDefaultNickname(host.getUsername(),
|
|
209 host.getHostname(), host.getPort()));
|
|
210 }
|
|
211 else {
|
|
212 host.setNickname(uri.getFragment());
|
|
213 }
|
|
214
|
|
215 return host;
|
|
216 }
|
|
217
|
12
|
218 public String getFormatHint(Context context) {
|
0
|
219 return context.getString(R.string.hostpref_nickname_title);
|
|
220 }
|
|
221
|
|
222 @Override
|
|
223 public boolean usesNetwork() {
|
|
224 return false;
|
|
225 }
|
|
226 }
|