You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2009/10/30 12:16:12 UTC
svn commit: r831265 - in /mina/sshd/trunk/sshd-core/src:
main/java/org/apache/sshd/client/channel/ main/java/org/apache/sshd/common/
main/java/org/apache/sshd/common/util/ main/java/org/apache/sshd/server/
main/java/org/apache/sshd/server/channel/ test...
Author: gnodet
Date: Fri Oct 30 11:16:11 2009
New Revision: 831265
URL: http://svn.apache.org/viewvc?rev=831265&view=rev
Log:
SSHD-47: the pty terminal parameters are not available to the shell
Added:
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/PtyMode.java
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/util/SttySupport.java
mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/SttySupportTest.java
mina/sshd/trunk/sshd-core/src/test/resources/org/
mina/sshd/trunk/sshd-core/src/test/resources/org/apache/
mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/
mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/
mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/
mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-1.txt
mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-2.txt
Modified:
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/ShellFactory.java
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java
Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java?rev=831265&r1=831264&r2=831265&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java Fri Oct 30 11:16:11 2009
@@ -22,6 +22,9 @@
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.util.Buffer;
+import java.io.IOException;
+import java.io.InputStream;
+
/**
* TODO Add javadoc
*
@@ -75,7 +78,7 @@
buffer.putInt(0);
int wpos2 = buffer.wpos(); // keep buffer position for data write
buffer.wpos(wpos2 + remoteWindow.getPacketSize()); // Make room
- int len = in.read(buffer.array(), wpos2, remoteWindow.getPacketSize()); // read data into buffer
+ int len = securedRead(in, buffer.array(), wpos2, remoteWindow.getPacketSize()); // read data into buffer
if (len > 0) {
buffer.wpos(wpos1);
buffer.putInt(len);
@@ -86,7 +89,32 @@
}
}
} catch (Exception e) {
+ log.info("Caught exception", e);
close(false);
}
}
+
+ //
+ // On some platforms, a call to System.in.read(new byte[65536], 0,32768) always throws an IOException.
+ // So we need to protect against that and chunk the call into smaller calls.
+ // This problem was found on Windows, JDK 1.6.0_03-b05.
+ //
+ protected int securedRead(InputStream in, byte[] buf, int off, int len) throws IOException {
+ int n = 0;
+ for (;;) {
+ int nread = in.read(buf, off + n, Math.min(1024, len - n));
+ if (nread <= 0) {
+ return (n == 0) ? nread : n;
+ }
+ n += nread;
+ if (n >= len) {
+ return n;
+ }
+ // if not closed but no bytes available, return
+ if (in != null && in.available() <= 0) {
+ return n;
+ }
+ }
+ }
+
}
Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java?rev=831265&r1=831264&r2=831265&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java Fri Oct 30 11:16:11 2009
@@ -18,8 +18,13 @@
*/
package org.apache.sshd.client.channel;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sshd.common.PtyMode;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.SttySupport;
/**
* TODO Add javadoc
@@ -28,6 +33,96 @@
*/
public class ChannelShell extends ChannelSession {
+ private String ptyType;
+ private int ptyColumns;
+ private int ptyLines;
+ private int ptyWidth;
+ private int ptyHeight;
+ private Map<PtyMode, Integer> ptyModes;
+
+ public ChannelShell() {
+ ptyType = System.getenv("TERM");
+ if (ptyType == null) {
+ ptyType = "dummy";
+ }
+ ptyColumns = 80;
+ ptyLines = 24;
+ ptyWidth = 640;
+ ptyHeight = 480;
+ // Set up default pty modes
+ ptyModes = new HashMap<PtyMode, Integer>();
+ ptyModes.put(PtyMode.ISIG, 1);
+ ptyModes.put(PtyMode.ICANON, 1);
+ ptyModes.put(PtyMode.ECHO, 1);
+ ptyModes.put(PtyMode.ECHOE, 1);
+ ptyModes.put(PtyMode.ECHOK, 1);
+ ptyModes.put(PtyMode.ECHONL, 0);
+ ptyModes.put(PtyMode.NOFLSH, 0);
+ }
+
+ public void setupSensibleDefaultPty() {
+ try {
+ String os = System.getProperty("os.name").toLowerCase();
+ if (os.indexOf("windows") < 0) {
+ ptyModes = SttySupport.getUnixPtyModes();
+ ptyColumns = SttySupport.getTerminalWidth();
+ ptyLines = SttySupport.getTerminalHeight();
+ } else {
+ ptyType = "windows";
+ }
+ } catch (Throwable t) {
+ // Ignore exceptions
+ }
+ }
+
+ public String getPtyType() {
+ return ptyType;
+ }
+
+ public void setPtyType(String ptyType) {
+ this.ptyType = ptyType;
+ }
+
+ public int getPtyColumns() {
+ return ptyColumns;
+ }
+
+ public void setPtyColumns(int ptyColumns) {
+ this.ptyColumns = ptyColumns;
+ }
+
+ public int getPtyLines() {
+ return ptyLines;
+ }
+
+ public void setPtyLines(int ptyLines) {
+ this.ptyLines = ptyLines;
+ }
+
+ public int getPtyWidth() {
+ return ptyWidth;
+ }
+
+ public void setPtyWidth(int ptyWidth) {
+ this.ptyWidth = ptyWidth;
+ }
+
+ public int getPtyHeight() {
+ return ptyHeight;
+ }
+
+ public void setPtyHeight(int ptyHeight) {
+ this.ptyHeight = ptyHeight;
+ }
+
+ public Map<PtyMode, Integer> getPtyModes() {
+ return ptyModes;
+ }
+
+ public void setPtyModes(Map<PtyMode, Integer> ptyModes) {
+ this.ptyModes = ptyModes;
+ }
+
protected void doOpen() throws Exception {
super.doOpen();
@@ -38,26 +133,16 @@
buffer.putInt(recipient);
buffer.putString("pty-req");
buffer.putBoolean(false);
- buffer.putString(System.getProperty("TERM", "dummy"));
- buffer.putInt(80);
- buffer.putInt(24);
- buffer.putInt(640);
- buffer.putInt(480);
+ buffer.putString(ptyType);
+ buffer.putInt(ptyColumns);
+ buffer.putInt(ptyLines);
+ buffer.putInt(ptyHeight);
+ buffer.putInt(ptyWidth);
Buffer modes = new Buffer();
- modes.putByte((byte) 50); // ISIG
- modes.putInt(1);
- modes.putByte((byte) 51); // ICANON
- modes.putInt(1);
- modes.putByte((byte) 53); // ECHO
- modes.putInt(1);
- modes.putByte((byte) 54); // ECHOE
- modes.putInt(1);
- modes.putByte((byte) 55); // ECHOK
- modes.putInt(1);
- modes.putByte((byte) 56); // ECHONL
- modes.putInt(0);
- modes.putByte((byte) 57); // NOFLSH
- modes.putInt(0);
+ for (PtyMode mode : ptyModes.keySet()) {
+ modes.putByte((byte) mode.toInt());
+ modes.putInt(ptyModes.get(mode));
+ }
modes.putByte((byte) 0);
buffer.putBytes(modes.getCompactData());
session.writePacket(buffer);
@@ -76,4 +161,5 @@
session.writePacket(buffer);
}
+
}
Added: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/PtyMode.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/PtyMode.java?rev=831265&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/PtyMode.java (added)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/PtyMode.java Fri Oct 30 11:16:11 2009
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import org.apache.sshd.server.ShellFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A enum describing the tty modes.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum PtyMode {
+
+ // Chars
+ VINTR(1), VQUIT(2), VERASE(3), VKILL(4), VEOF(5), VEOL(6), VEOL2(7), VSTART(8), VSTOP(9),
+ VSUSP(10), VDSUSP(11), VREPRINT(12), VWERASE(13), VLNEXT(14), VFLUSH(15), VSWTCH(16), VSTATUS(17), VDISCARD(18),
+
+ // I flags
+ IGNPAR(30), PARMRK(31), INPCK(32), ISTRIP(33), INLCR(34), IGNCR(35), ICRNL(36), IUCLC(37), IXON(38), IXANY(39),
+ IXOFF(40), IMAXBEL(41),
+
+ // L flags
+ ISIG(50), ICANON(51), XCASE(52), ECHO(53), ECHOE(54), ECHOK(55), ECHONL(56), NOFLSH(57), TOSTOP(58), IEXTEN(59),
+ ECHOCTL(60), ECHOKE(61), PENDIN(62),
+
+ // O flags
+ OPOST(70), OLCUC(71), ONLCR(72), OCRNL(73), ONOCR(74), ONLRET(75),
+
+ // C flags
+ CS7(90), CS8(91), PARENB(92), PARODD(93),
+
+ // Speeed
+ TTY_OP_ISPEED(128), TTY_OP_OSPEED(129);
+
+ private int v;
+
+ private PtyMode(int v) {
+ this.v = v;
+ }
+
+ public int toInt() {
+ return v;
+ }
+
+ static Map<Integer, PtyMode> commands;
+
+ static {
+ commands = new HashMap<Integer, PtyMode>();
+ for (PtyMode c : PtyMode.values()) {
+ commands.put(c.toInt(), c);
+ }
+ }
+
+ public static PtyMode fromInt(int b) {
+ return commands.get(0x00FF & (b + 256));
+ }
+}
Added: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/util/SttySupport.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/util/SttySupport.java?rev=831265&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/util/SttySupport.java (added)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/common/util/SttySupport.java Fri Oct 30 11:16:11 2009
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+
+import org.apache.sshd.common.PtyMode;
+
+/**
+ * Support for stty command on unix
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class SttySupport {
+
+ private static String sttyCommand = System.getProperty("sshd.sttyCommand", "stty");
+ private static String ttyProps;
+ private static long ttyPropsLastFetched;
+
+ public static Map<PtyMode, Integer> getUnixPtyModes() throws IOException, InterruptedException {
+ return parsePtyModes(getTtyProps());
+ }
+
+ public static Map<PtyMode, Integer> parsePtyModes(String stty) {
+ Map<PtyMode, Integer> modes = new TreeMap<PtyMode, Integer>();
+ for (PtyMode mode : PtyMode.values()) {
+ if (mode == PtyMode.TTY_OP_ISPEED || mode == PtyMode.TTY_OP_OSPEED) {
+
+ } else {
+ String str = mode.name().toLowerCase();
+ // Are we looking for a character?
+ if (str.charAt(0) == 'v') {
+ str = str.substring(1);
+ int v = findChar(stty, str);
+ if (v < 0 && "reprint".equals(str)) {
+ v = findChar(stty, "rprnt");
+ }
+ if (v >= 0) {
+ modes.put(mode, v);
+ }
+ } else {
+ int v = findFlag(stty, str);
+ if (v >= 0) {
+ modes.put(mode, v);
+ }
+ }
+ }
+ }
+ return modes;
+ }
+
+ private static int findFlag(String stty, String name) {
+ int cur = 0;
+ while (cur < stty.length()) {
+ int idx1 = stty.indexOf(name, cur);
+ int idx2 = idx1 + name.length();
+ if (idx1 < 0) {
+ return -1;
+ }
+ if (idx1 > 0 && Character.isLetterOrDigit(stty.charAt(idx1 - 1))
+ || (idx2 < stty.length() && Character.isLetterOrDigit(stty.charAt(idx2)))) {
+ cur = idx2;
+ continue;
+ }
+ return idx1 == 0 ? 1 : stty.charAt(idx1 - 1) == '-' ? 0 : 1;
+ }
+ return -1;
+ }
+
+ private static int findChar(String stty, String name) {
+ int cur = 0;
+ while (cur < stty.length()) {
+ int idx1 = stty.indexOf(name, cur);
+ int idx2 = stty.indexOf('=', idx1);
+ int idx3 = stty.indexOf(';', idx1);
+ if (idx1 < 0 || idx2 < 0 || idx3 < idx2) {
+ // Invalid syntax
+ return -1;
+ }
+ if (idx1 > 0 && Character.isLetterOrDigit(stty.charAt(idx1 - 1))
+ || (idx2 < stty.length() && Character.isLetterOrDigit(stty.charAt(idx2)))) {
+ cur = idx1 + name.length();
+ continue;
+ }
+ String val = stty.substring(idx2 + 1, idx3 < 0 ? stty.length() : idx3).trim();
+ if (val.indexOf("undef") >= 0) {
+ return -1;
+ }
+ if (val.length() == 2 && val.charAt(0) == '^') {
+ int v = (val.charAt(1) - 'A' + 129) % 128;
+ return v;
+ } else {
+ try {
+ return Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // what else ?
+ }
+ }
+ return -1;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the value of "stty size" width param.
+ *
+ * <strong>Note</strong>: this method caches the value from the
+ * first time it is called in order to increase speed, which means
+ * that changing to size of the terminal will not be reflected
+ * in the console.
+ */
+ public static int getTerminalWidth() {
+ int val = -1;
+
+ try {
+ val = getTerminalProperty("columns");
+ } catch (Exception e) {
+ }
+
+ if (val == -1) {
+ val = 80;
+ }
+
+ return val;
+ }
+
+ /**
+ * Returns the value of "stty size" height param.
+ *
+ * <strong>Note</strong>: this method caches the value from the
+ * first time it is called in order to increase speed, which means
+ * that changing to size of the terminal will not be reflected
+ * in the console.
+ */
+ public static int getTerminalHeight() {
+ int val = -1;
+
+ try {
+ val = getTerminalProperty("rows");
+ } catch (Exception e) {
+ }
+
+ if (val == -1) {
+ val = 24;
+ }
+
+ return val;
+ }
+
+ private static int getTerminalProperty(String prop)
+ throws IOException, InterruptedException {
+ // need to be able handle both output formats:
+ // speed 9600 baud; 24 rows; 140 columns;
+ // and:
+ // speed 38400 baud; rows = 49; columns = 111; ypixels = 0; xpixels = 0;
+ for (StringTokenizer tok = new StringTokenizer(getTtyProps(), ";\n");
+ tok.hasMoreTokens();) {
+ String str = tok.nextToken().trim();
+
+ if (str.startsWith(prop)) {
+ int index = str.lastIndexOf(" ");
+
+ return Integer.parseInt(str.substring(index).trim());
+ } else if (str.endsWith(prop)) {
+ int index = str.indexOf(" ");
+
+ return Integer.parseInt(str.substring(0, index).trim());
+ }
+ }
+
+ return -1;
+ }
+
+ public static String getTtyProps() throws IOException, InterruptedException {
+ // tty properties are cached so we don't have to worry too much about getting term widht/height
+ if (ttyProps == null || System.currentTimeMillis() - ttyPropsLastFetched > 1000) {
+ ttyProps = stty("-a");
+ ttyPropsLastFetched = System.currentTimeMillis();
+ }
+ return ttyProps;
+ }
+
+
+ /**
+ * Execute the stty command with the specified arguments
+ * against the current active terminal.
+ */
+ public static String stty(final String args)
+ throws IOException, InterruptedException {
+ return exec("stty " + args + " < /dev/tty").trim();
+ }
+
+ /**
+ * Execute the specified command and return the output
+ * (both stdout and stderr).
+ */
+ public static String exec(final String cmd)
+ throws IOException, InterruptedException {
+ return exec(new String[] {
+ "sh",
+ "-c",
+ cmd
+ });
+ }
+
+ /**
+ * Execute the specified command and return the output
+ * (both stdout and stderr).
+ */
+ private static String exec(final String[] cmd)
+ throws IOException, InterruptedException {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+ Process p = Runtime.getRuntime().exec(cmd);
+ int c;
+ InputStream in;
+
+ in = p.getInputStream();
+
+ while ((c = in.read()) != -1) {
+ bout.write(c);
+ }
+
+ in = p.getErrorStream();
+
+ while ((c = in.read()) != -1) {
+ bout.write(c);
+ }
+
+ p.waitFor();
+
+ String result = new String(bout.toByteArray());
+
+ return result;
+ }
+
+ /**
+ * The command to use to set the terminal options. Defaults
+ * to "stty", or the value of the system property "jline.sttyCommand".
+ */
+ public static void setSttyCommand(String cmd) {
+ sttyCommand = cmd;
+ }
+
+ /**
+ * The command to use to set the terminal options. Defaults
+ * to "stty", or the value of the system property "jline.sttyCommand".
+ */
+ public static String getSttyCommand() {
+ return sttyCommand;
+ }
+
+}
Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/ShellFactory.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/ShellFactory.java?rev=831265&r1=831264&r2=831265&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/ShellFactory.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/ShellFactory.java Fri Oct 30 11:16:11 2009
@@ -24,6 +24,7 @@
import java.util.Map;
import java.util.EnumSet;
+import org.apache.sshd.common.PtyMode;
import org.apache.sshd.server.session.ServerSession;
/**
@@ -129,7 +130,13 @@
* Retrieve the environment map
* @return the environment map
*/
- Map<String,String> getEnv();
+ Map<String, String> getEnv();
+
+ /**
+ * Retrieve the pty modes
+ * @return the map of pty modes
+ */
+ Map<PtyMode, Integer> getPtyModes();
/**
* Add a qualified listener for the specific signal
Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java?rev=831265&r1=831264&r2=831265&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java Fri Oct 30 11:16:11 2009
@@ -21,10 +21,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.ArrayList;
import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -32,6 +29,7 @@
import org.apache.sshd.common.Channel;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.PtyMode;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.channel.ChannelOutputStream;
import org.apache.sshd.common.channel.ChannelPipedInputStream;
@@ -71,11 +69,13 @@
protected static class StandardEnvironment implements Environment {
private final Map<Signal, Set<SignalListener>> listeners;
- private final Map<String,String> env;
+ private final Map<String, String> env;
+ private final Map<PtyMode, Integer> ptyModes;
public StandardEnvironment() {
listeners = new ConcurrentHashMap<Signal, Set<SignalListener>>(3);
env = new ConcurrentHashMap<String, String>();
+ ptyModes = new ConcurrentHashMap<PtyMode, Integer>();
}
public void addSignalListener(SignalListener listener, Signal... signals) {
@@ -105,6 +105,10 @@
return env;
}
+ public Map<PtyMode, Integer> getPtyModes() {
+ return ptyModes;
+ }
+
public void removeSignalListener(SignalListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener may not be null");
@@ -136,7 +140,7 @@
// TODO: listening for property changes would be nice too.
getEnv().put(key, value);
}
-
+
protected Set<SignalListener> getSignalListeners(Signal signal, boolean create) {
Set<SignalListener> ls = listeners.get(signal);
if (ls == null && create) {
@@ -154,60 +158,7 @@
}
- protected static enum PtyMode {
- // Chars
- VINTR(1), VQUIT(2), VERASE(3), VKILL(4), VEOF(5), VEOL(6), VEOL2(7), VSTART(8), VSTOP(9),
- VSUSP(10), VDSUSP(11), VREPRINT(12), VWERASE(13), VLNEXT(14), VFLUSH(15), VSWTCH(16), VSTATUS(17), VDISCARD(18),
- // I flags
- IGNPAR(30), PARMRK(31), INPCK(32), ISTRIP(33), INCLR(34), IGNCR(35), ICRNL(36), IUCLC(37), IXON(38), IXANY(39),
- IXOFF(40), IMAXBEL(41),
- // L flags
- ISIG(50), ICANON(51), XCASE(52), ECHO(53), ECHOE(54), ECHOK(55), ECHONL(56), NOFLSH(57), TOSTOP(58), IEXTEN(59),
- ECHOCTL(60), ECHOKE(61), PENDIN(62),
- // O flags
- OPOST(70), OLCUC(71), ONLCR(72), OCRNL(73), ONOCR(74), ONLRET(75),
- // C flags
- CS7(90), CS8(91), PARENB(92), PARODD(93),
- // Speeed
- TTY_OP_ISPEED(128), TTY_OP_OSPEED(129);
-
- private int v;
- private PtyMode(int v) {
- this.v = v;
- }
-
- public int toInt() {
- return v;
- }
-
- static Map<Integer,PtyMode> commands;
- static {
- commands = new HashMap<Integer, PtyMode>();
- for (PtyMode c : PtyMode.values()) {
- commands.put(c.toInt(), c);
- }
- }
- public static PtyMode fromInt(int b) {
- return commands.get(0x00FF & (b + 256));
- }
- }
-
- protected static class PtyModeValue {
- public final PtyMode mode;
- public final int value;
-
- public PtyModeValue(PtyMode mode, int value) {
- this.mode = mode;
- this.value = value;
- }
-
- public String toString() {
- return mode + "(" + mode.toInt() + ") =" + value;
- }
- }
-
protected String type;
- protected PtyModeValue[] ptyModes;
protected InputStream in;
protected OutputStream out;
protected OutputStream err;
@@ -340,31 +291,20 @@
int tWidth = buffer.getInt();
int tHeight = buffer.getInt();
byte[] modes = buffer.getBytes();
- List<PtyModeValue> modeList = new ArrayList<PtyModeValue>();
for (int i = 0; i < modes.length && modes[i] != 0;) {
PtyMode mode = PtyMode.fromInt(modes[i++]);
int val = ((modes[i++] << 24) & 0xff000000) |
((modes[i++] << 16) & 0x00ff0000) |
((modes[i++] << 8) & 0x0000ff00) |
((modes[i++] ) & 0x000000ff);
- PtyModeValue m = new PtyModeValue(mode, val);
- modeList.add(m);
+ getEnvironment().getPtyModes().put(mode, val);
}
- ptyModes = modeList.toArray(new PtyModeValue[0]);
if (log.isDebugEnabled()) {
- StringBuffer strModes = new StringBuffer();
- for (PtyModeValue m : ptyModes) {
- if (strModes.length() > 0) {
- strModes.append(", ");
- }
- strModes.append(m);
- }
- log.debug("pty for channel {}: term={}, size=({} - {}), pixels=({}, {}), modes=[{}]", new Object[] { id, term, tColumns, tRows, tWidth, tHeight, strModes.toString() });
+ log.debug("pty for channel {}: term={}, size=({} - {}), pixels=({}, {}), modes=[{}]", new Object[] { id, term, tColumns, tRows, tWidth, tHeight, getEnvironment().getPtyModes() });
}
addEnvVariable(Environment.ENV_TERM, term);
addEnvVariable(Environment.ENV_COLUMNS, Integer.toString(tColumns));
addEnvVariable(Environment.ENV_LINES, Integer.toString(tRows));
- // TODO: handle pty request correctly
if (wantReply) {
buffer = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_SUCCESS);
buffer.putInt(recipient);
@@ -464,14 +404,8 @@
}
protected int getPtyModeValue(PtyMode mode) {
- if (ptyModes != null) {
- for (PtyModeValue m : ptyModes) {
- if (m.mode == mode) {
- return m.value;
- }
- }
- }
- return 0;
+ Integer v = getEnvironment().getPtyModes().get(mode);
+ return v != null ? v : 0;
}
protected boolean handleExec(Buffer buffer) throws IOException {
Modified: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ClientTest.java?rev=831265&r1=831264&r2=831265&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ClientTest.java (original)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ClientTest.java Fri Oct 30 11:16:11 2009
@@ -191,7 +191,7 @@
authFuture.await();
closeFuture.await();
assertNotNull(authFuture.getException());
-
+ assertTrue(closeFuture.isClosed());
}
@Test
@@ -209,7 +209,7 @@
openFuture.await();
closeFuture.await();
assertNotNull(openFuture.isOpened());
- assertNotNull(closeFuture.isClosed());
+ assertTrue(closeFuture.isClosed());
}
@Test
@@ -227,7 +227,7 @@
openFuture.await();
closeFuture.await();
assertNotNull(openFuture.getException());
- assertNotNull(closeFuture.isClosed());
+ assertTrue(closeFuture.isClosed());
}
public static void main(String[] args) throws Exception {
Modified: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java?rev=831265&r1=831264&r2=831265&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java (original)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java Fri Oct 30 11:16:11 2009
@@ -109,32 +109,32 @@
String data = "0123456789\n";
File root = new File("target/scp");
- File target = new File("target/scp/o ut.txt");
+ File target = new File("target/scp/out.txt");
root.mkdirs();
assertTrue(root.exists());
target.delete();
assertFalse(target.exists());
- sendFile("target/scp/o ut.txt", "out.txt", data);
+ sendFile("target/scp/out.txt", "out.txt", data);
assertFileLength(target, data.length(), 5000);
target.delete();
assertFalse(target.exists());
- sendFile("target/scp", "o ut.txt", data);
+ sendFile("target/scp", "out.txt", data);
assertFileLength(target, data.length(), 5000);
sendFileError("target", "scp", "0123456789\n");
readFileError("target/scp");
- assertEquals(data, readFile("target/scp/o ut.txt"));
+ assertEquals(data, readFile("target/scp/out.txt"));
assertEquals(data, readDir("target/scp"));
target.delete();
root.delete();
- sendDir("target", "scp", "o ut.txt", data);
+ sendDir("target", "scp", "out.txt", data);
assertFileLength(target, data.length(), 5000);
}
@@ -164,7 +164,7 @@
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
String header = readLine(is);
- assertEquals("C0644 11 o ut.txt", header);
+ assertEquals("C0644 11 out.txt", header);
int length = Integer.parseInt(header.substring(6, header.indexOf(' ', 6)));
os.write(0);
os.flush();
@@ -191,7 +191,7 @@
os.write(0);
os.flush();
header = readLine(is);
- assertEquals("C0644 11 o ut.txt", header);
+ assertEquals("C0644 11 out.txt", header);
int length = Integer.parseInt(header.substring(6, header.indexOf(' ', 6)));
os.write(0);
os.flush();
Added: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/SttySupportTest.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/SttySupportTest.java?rev=831265&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/SttySupportTest.java (added)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/SttySupportTest.java Fri Oct 30 11:16:11 2009
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.util;
+
+import org.apache.sshd.common.PtyMode;
+import org.apache.sshd.common.util.SttySupport;
+import org.junit.Test;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Map;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class SttySupportTest {
+
+ @Test
+ public void parseOutput1() throws Exception {
+ Reader r = new InputStreamReader(getClass().getResourceAsStream("stty-output-1.txt"));
+ char[] buf = new char[8192];
+ int len = r.read(buf);
+ String stty = new String(buf, 0, len);
+ Map<PtyMode, Integer> modes = SttySupport.parsePtyModes(stty);
+ System.err.println(modes);
+ }
+
+ @Test
+ public void parseOutput2() throws Exception {
+ Reader r = new InputStreamReader(getClass().getResourceAsStream("stty-output-2.txt"));
+ char[] buf = new char[8192];
+ int len = r.read(buf);
+ String stty = new String(buf, 0, len);
+ Map<PtyMode, Integer> modes = SttySupport.parsePtyModes(stty);
+ System.err.println(modes);
+ }
+}
Added: mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-1.txt
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-1.txt?rev=831265&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-1.txt (added)
+++ mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-1.txt Fri Oct 30 11:16:11 2009
@@ -0,0 +1,10 @@
+speed 38400 baud; rows 25; columns 80; line = 0;
+intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
+eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
+werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
+-parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts
+-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff
+-iuclc -ixany -imaxbel -iutf8
+opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
+isig icanon -iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
+echoctl echoke
Added: mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-2.txt
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-2.txt?rev=831265&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-2.txt (added)
+++ mina/sshd/trunk/sshd-core/src/test/resources/org/apache/sshd/client/channel/stty-output-2.txt Fri Oct 30 11:16:11 2009
@@ -0,0 +1,13 @@
+speed 9600 baud; 50 rows; 160 columns;
+lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
+ -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
+ -extproc
+iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
+ -ignbrk brkint -inpck -ignpar -parmrk
+oflags: opost onlcr -oxtabs -onocr -onlret
+cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
+ -dtrflow -mdmbuf
+cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
+ eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
+ min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
+ stop = ^S; susp = ^Z; time = 0; werase = ^W;