You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2017/06/23 12:19:46 UTC

karaf git commit: [KARAF-5216] Fix signal support in bin/client and ssh:ssh command

Repository: karaf
Updated Branches:
  refs/heads/karaf-4.1.x e5241da63 -> e6d439325


[KARAF-5216] Fix signal support in bin/client and ssh:ssh command

Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/e6d43932
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/e6d43932
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/e6d43932

Branch: refs/heads/karaf-4.1.x
Commit: e6d439325eb0ca2924fce815fed16d3781898be9
Parents: e5241da
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Jun 23 14:19:21 2017 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Jun 23 14:19:29 2017 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/karaf/client/Main.java | 104 +++++++++++++------
 .../org/apache/karaf/shell/ssh/SshAction.java   |  58 ++++++++---
 2 files changed, 116 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/e6d43932/client/src/main/java/org/apache/karaf/client/Main.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/karaf/client/Main.java b/client/src/main/java/org/apache/karaf/client/Main.java
index 6f246a0..14b0991 100644
--- a/client/src/main/java/org/apache/karaf/client/Main.java
+++ b/client/src/main/java/org/apache/karaf/client/Main.java
@@ -164,20 +164,23 @@ public class Main {
             session.auth().verify();
 
             int exitStatus = 0;
-            try (Terminal terminal = TerminalBuilder.terminal()) {
-                Attributes attributes = terminal.enterRawMode();
-                try {
-                    ClientChannel channel;
-                    if (config.getCommand().length() > 0) {
-                        ChannelExec exec = session.createExecChannel(config.getCommand() + "\n");
-                        channel = exec;
-                        channel.setIn(new ByteArrayInputStream(new byte[0]));
-                        exec.setAgentForwarding(true);
-                    } else {
-                        ChannelShell shell = session.createShellChannel();
-                        channel = shell;
-                        channel.setIn(new NoCloseInputStream(terminal.input()));
-
+            try (Terminal terminal = TerminalBuilder.builder()
+                        .nativeSignals(true)
+                        .signalHandler(Terminal.SignalHandler.SIG_IGN)
+                        .build()) {
+                if (config.getCommand().length() > 0) {
+                    ChannelExec channel = session.createExecChannel(config.getCommand() + "\n");
+                    channel.setIn(new ByteArrayInputStream(new byte[0]));
+                    channel.setAgentForwarding(true);
+                    NoCloseOutputStream output = new NoCloseOutputStream(terminal.output());
+                    channel.setOut(output);
+                    channel.setErr(output);
+                    channel.open().verify();
+                    channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
+                } else {
+                    ChannelShell channel = session.createShellChannel();
+                    Attributes attributes = terminal.enterRawMode();
+                    try {
                         Map<PtyMode, Integer> modes = new HashMap<>();
                         // Control chars
                         modes.put(PtyMode.VINTR, attributes.getControlChar(ControlChar.VINTR));
@@ -223,30 +226,67 @@ public class Main {
                         modes.put(PtyMode.OCRNL, getFlag(attributes, OutputFlag.OCRNL));
                         modes.put(PtyMode.ONOCR, getFlag(attributes, OutputFlag.ONOCR));
                         modes.put(PtyMode.ONLRET, getFlag(attributes, OutputFlag.ONLRET));
-                        shell.setPtyModes(modes);
-                        shell.setPtyColumns(terminal.getWidth());
-                        shell.setPtyLines(terminal.getHeight());
-                        shell.setAgentForwarding(true);
+                        channel.setPtyModes(modes);
+                        channel.setPtyColumns(terminal.getWidth());
+                        channel.setPtyLines(terminal.getHeight());
+                        channel.setAgentForwarding(true);
+                        channel.setEnv("TERM", terminal.getType());
                         String ctype = System.getenv("LC_CTYPE");
                         if (ctype == null) {
                             ctype = Locale.getDefault().toString() + "."
                                     + System.getProperty("input.encoding", Charset.defaultCharset().name());
                         }
-                        shell.setEnv("LC_CTYPE", ctype);
-                    }
-                    NoCloseOutputStream output = new NoCloseOutputStream(terminal.output());
-                    channel.setOut(output);
-                    channel.setErr(output);
-                    channel.open().verify();
-                    if (channel instanceof PtyCapableChannelSession) {
-                        registerSignalHandler(terminal, (PtyCapableChannelSession) channel);
-                    }
-                    channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
-                    if (channel.getExitStatus() != null) {
-                        exitStatus = channel.getExitStatus();
+                        channel.setEnv("LC_CTYPE", ctype);
+                        channel.setIn(new NoCloseInputStream(terminal.input()));
+                        channel.setOut(new NoCloseOutputStream(terminal.output()));
+                        channel.setErr(new NoCloseOutputStream(terminal.output()));
+                        channel.open().verify();
+                        Terminal.SignalHandler prevWinchHandler = terminal.handle(Terminal.Signal.WINCH, signal -> {
+                            try {
+                                Size size = terminal.getSize();
+                                channel.sendWindowChange(size.getColumns(), size.getRows());
+                            } catch (IOException e) {
+                                // Ignore
+                            }
+                        });
+                        Terminal.SignalHandler prevQuitHandler = terminal.handle(Terminal.Signal.QUIT, signal -> {
+                            try {
+                                channel.getInvertedIn().write(attributes.getControlChar(Attributes.ControlChar.VQUIT));
+                                channel.getInvertedIn().flush();
+                            } catch (IOException e) {
+                                // Ignore
+                            }
+                        });
+                        Terminal.SignalHandler prevIntHandler = terminal.handle(Terminal.Signal.INT, signal -> {
+                            try {
+                                channel.getInvertedIn().write(attributes.getControlChar(Attributes.ControlChar.VINTR));
+                                channel.getInvertedIn().flush();
+                            } catch (IOException e) {
+                                // Ignore
+                            }
+                        });
+                        Terminal.SignalHandler prevStopHandler = terminal.handle(Terminal.Signal.TSTP, signal -> {
+                            try {
+                                channel.getInvertedIn().write(attributes.getControlChar(Attributes.ControlChar.VDSUSP));
+                                channel.getInvertedIn().flush();
+                            } catch (IOException e) {
+                                // Ignore
+                            }
+                        });
+                        try {
+                            channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
+                        } finally {
+                            terminal.handle(Terminal.Signal.WINCH, prevWinchHandler);
+                            terminal.handle(Terminal.Signal.INT, prevIntHandler);
+                            terminal.handle(Terminal.Signal.TSTP, prevStopHandler);
+                            terminal.handle(Terminal.Signal.QUIT, prevQuitHandler);
+                        }
+                        if (channel.getExitStatus() != null) {
+                            exitStatus = channel.getExitStatus();
+                        }
+                    } finally {
+                        terminal.setAttributes(attributes);
                     }
-                } finally {
-                    terminal.setAttributes(attributes);
                 }
             }
             System.exit(exitStatus);

http://git-wip-us.apache.org/repos/asf/karaf/blob/e6d43932/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
index 256bb3b..3f87232 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
@@ -22,9 +22,11 @@ import java.io.ByteArrayInputStream;
 import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
+import java.nio.charset.Charset;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import org.apache.karaf.shell.api.action.Action;
@@ -189,8 +191,8 @@ public class SshAction implements Action {
                     channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
                 } else if (session.getTerminal() != null) {
                     final ChannelShell channel = sshSession.createShellChannel();
-                    final org.jline.terminal.Terminal jlineTerminal = (org.jline.terminal.Terminal) session.get(".jline.terminal");
-                    Attributes attributes = jlineTerminal.enterRawMode();
+                    final org.jline.terminal.Terminal terminal = (org.jline.terminal.Terminal) session.get(".jline.terminal");
+                    Attributes attributes = terminal.enterRawMode();
                     try {
                         Map<PtyMode, Integer> modes = new HashMap<>();
                         // Control chars
@@ -242,30 +244,58 @@ public class SshAction implements Action {
                         channel.setPtyLines(getTermHeight());
                         channel.setAgentForwarding(true);
                         channel.setEnv("TERM", session.getTerminal().getType());
-                        Object ctype = session.get("LC_CTYPE");
-                        if (ctype != null) {
-                            channel.setEnv("LC_CTYPE", ctype.toString());
+                        String ctype = (String) session.get("LC_CTYPE");
+                        if (ctype == null) {
+                            ctype = Locale.getDefault().toString() + "."
+                                    + System.getProperty("input.encoding", Charset.defaultCharset().name());
                         }
-                        channel.setIn(new NoCloseInputStream(jlineTerminal.input()));
-                        channel.setOut(new NoCloseOutputStream(jlineTerminal.output()));
-                        channel.setErr(new NoCloseOutputStream(jlineTerminal.output()));
+                        channel.setEnv("LC_CTYPE", ctype);
+                        channel.setIn(new NoCloseInputStream(terminal.input()));
+                        channel.setOut(new NoCloseOutputStream(terminal.output()));
+                        channel.setErr(new NoCloseOutputStream(terminal.output()));
                         channel.open().verify();
-                        SignalListener signalListener = signal -> {
+                        org.jline.terminal.Terminal.SignalHandler prevWinchHandler = terminal.handle(org.jline.terminal.Terminal.Signal.WINCH, signal -> {
                             try {
-                                Size size = jlineTerminal.getSize();
+                                Size size = terminal.getSize();
                                 channel.sendWindowChange(size.getColumns(), size.getRows());
                             } catch (IOException e) {
                                 // Ignore
                             }
-                        };
-                        session.getTerminal().addSignalListener(signalListener, Signal.WINCH);
+                        });
+                        org.jline.terminal.Terminal.SignalHandler prevQuitHandler = terminal.handle(org.jline.terminal.Terminal.Signal.QUIT, signal -> {
+                            try {
+                                channel.getInvertedIn().write(attributes.getControlChar(Attributes.ControlChar.VQUIT));
+                                channel.getInvertedIn().flush();
+                            } catch (IOException e) {
+                                // Ignore
+                            }
+                        });
+                        org.jline.terminal.Terminal.SignalHandler prevIntHandler = terminal.handle(org.jline.terminal.Terminal.Signal.INT, signal -> {
+                            try {
+                                channel.getInvertedIn().write(attributes.getControlChar(Attributes.ControlChar.VINTR));
+                                channel.getInvertedIn().flush();
+                            } catch (IOException e) {
+                                // Ignore
+                            }
+                        });
+                        org.jline.terminal.Terminal.SignalHandler prevStopHandler = terminal.handle(org.jline.terminal.Terminal.Signal.TSTP, signal -> {
+                            try {
+                                channel.getInvertedIn().write(attributes.getControlChar(Attributes.ControlChar.VDSUSP));
+                                channel.getInvertedIn().flush();
+                            } catch (IOException e) {
+                                // Ignore
+                            }
+                        });
                         try {
                             channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
                         } finally {
-                            session.getTerminal().removeSignalListener(signalListener);
+                            terminal.handle(org.jline.terminal.Terminal.Signal.WINCH, prevWinchHandler);
+                            terminal.handle(org.jline.terminal.Terminal.Signal.INT, prevIntHandler);
+                            terminal.handle(org.jline.terminal.Terminal.Signal.TSTP, prevStopHandler);
+                            terminal.handle(org.jline.terminal.Terminal.Signal.QUIT, prevQuitHandler);
                         }
                     } finally {
-                        jlineTerminal.setAttributes(attributes);
+                        terminal.setAttributes(attributes);
                     }
                 } else {
                     throw new IllegalStateException("No terminal for interactive ssh session");