Repository: karaf Updated Branches: refs/heads/master 85111bea1 -> 071fdb8a6
[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/071fdb8a Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/071fdb8a Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/071fdb8a Branch: refs/heads/master Commit: 071fdb8a6b2ca4551ba4e181cd908c69c46368d5 Parents: 85111be Author: Guillaume Nodet <[email protected]> Authored: Fri Jun 23 14:19:21 2017 +0200 Committer: Guillaume Nodet <[email protected]> Committed: Fri Jun 23 14:20:03 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/071fdb8a/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 4f3e857..9c0c8a3 100644 --- a/client/src/main/java/org/apache/karaf/client/Main.java +++ b/client/src/main/java/org/apache/karaf/client/Main.java @@ -158,20 +158,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)); @@ -217,30 +220,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/071fdb8a/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 badbf1b..8fe85b3 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");
