From 32d2af1417d0f96b1a7d588188f1c37a4fb979d7 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 18 Dec 2023 13:03:22 +0100 Subject: [PATCH] Fix ssh attributes transfer --- .../jline/builtins/ssh/ShellFactoryImpl.java | 74 ++++++++-------- .../main/java/org/jline/builtins/ssh/Ssh.java | 86 ++++++++++--------- 2 files changed, 83 insertions(+), 77 deletions(-) diff --git a/remote-ssh/src/main/java/org/jline/builtins/ssh/ShellFactoryImpl.java b/remote-ssh/src/main/java/org/jline/builtins/ssh/ShellFactoryImpl.java index 795d58144..05582dcdc 100644 --- a/remote-ssh/src/main/java/org/jline/builtins/ssh/ShellFactoryImpl.java +++ b/remote-ssh/src/main/java/org/jline/builtins/ssh/ShellFactoryImpl.java @@ -110,59 +110,50 @@ public void start(final ChannelSession session, final Environment env) throws IO public void run(ChannelSession session, Environment env) throws Exception { try { - Terminal terminal = TerminalBuilder.builder() - .name("JLine SSH") - .type(env.getEnv().get("TERM")) - .system(false) - .streams(in, out) - .build(); - terminal.setSize(new Size( - Integer.parseInt(env.getEnv().get("COLUMNS")), - Integer.parseInt(env.getEnv().get("LINES")))); - Attributes attr = terminal.getAttributes(); + Attributes attributes = new Attributes(); for (Map.Entry e : env.getPtyModes().entrySet()) { switch (e.getKey()) { case VINTR: - attr.setControlChar(ControlChar.VINTR, e.getValue()); + attributes.setControlChar(ControlChar.VINTR, e.getValue()); break; case VQUIT: - attr.setControlChar(ControlChar.VQUIT, e.getValue()); + attributes.setControlChar(ControlChar.VQUIT, e.getValue()); break; case VERASE: - attr.setControlChar(ControlChar.VERASE, e.getValue()); + attributes.setControlChar(ControlChar.VERASE, e.getValue()); break; case VKILL: - attr.setControlChar(ControlChar.VKILL, e.getValue()); + attributes.setControlChar(ControlChar.VKILL, e.getValue()); break; case VEOF: - attr.setControlChar(ControlChar.VEOF, e.getValue()); + attributes.setControlChar(ControlChar.VEOF, e.getValue()); break; case VEOL: - attr.setControlChar(ControlChar.VEOL, e.getValue()); + attributes.setControlChar(ControlChar.VEOL, e.getValue()); break; case VEOL2: - attr.setControlChar(ControlChar.VEOL2, e.getValue()); + attributes.setControlChar(ControlChar.VEOL2, e.getValue()); break; case VSTART: - attr.setControlChar(ControlChar.VSTART, e.getValue()); + attributes.setControlChar(ControlChar.VSTART, e.getValue()); break; case VSTOP: - attr.setControlChar(ControlChar.VSTOP, e.getValue()); + attributes.setControlChar(ControlChar.VSTOP, e.getValue()); break; case VSUSP: - attr.setControlChar(ControlChar.VSUSP, e.getValue()); + attributes.setControlChar(ControlChar.VSUSP, e.getValue()); break; case VDSUSP: - attr.setControlChar(ControlChar.VDSUSP, e.getValue()); + attributes.setControlChar(ControlChar.VDSUSP, e.getValue()); break; case VREPRINT: - attr.setControlChar(ControlChar.VREPRINT, e.getValue()); + attributes.setControlChar(ControlChar.VREPRINT, e.getValue()); break; case VWERASE: - attr.setControlChar(ControlChar.VWERASE, e.getValue()); + attributes.setControlChar(ControlChar.VWERASE, e.getValue()); break; case VLNEXT: - attr.setControlChar(ControlChar.VLNEXT, e.getValue()); + attributes.setControlChar(ControlChar.VLNEXT, e.getValue()); break; /* case VFLUSH: @@ -173,44 +164,53 @@ public void run(ChannelSession session, Environment env) throws Exception { break; */ case VSTATUS: - attr.setControlChar(ControlChar.VSTATUS, e.getValue()); + attributes.setControlChar(ControlChar.VSTATUS, e.getValue()); break; case VDISCARD: - attr.setControlChar(ControlChar.VDISCARD, e.getValue()); + attributes.setControlChar(ControlChar.VDISCARD, e.getValue()); break; case ECHO: - attr.setLocalFlag(LocalFlag.ECHO, e.getValue() != 0); + attributes.setLocalFlag(LocalFlag.ECHO, e.getValue() != 0); break; case ICANON: - attr.setLocalFlag(LocalFlag.ICANON, e.getValue() != 0); + attributes.setLocalFlag(LocalFlag.ICANON, e.getValue() != 0); break; case ISIG: - attr.setLocalFlag(LocalFlag.ISIG, e.getValue() != 0); + attributes.setLocalFlag(LocalFlag.ISIG, e.getValue() != 0); break; case ICRNL: - attr.setInputFlag(InputFlag.ICRNL, e.getValue() != 0); + attributes.setInputFlag(InputFlag.ICRNL, e.getValue() != 0); break; case INLCR: - attr.setInputFlag(InputFlag.INLCR, e.getValue() != 0); + attributes.setInputFlag(InputFlag.INLCR, e.getValue() != 0); break; case IGNCR: - attr.setInputFlag(InputFlag.IGNCR, e.getValue() != 0); + attributes.setInputFlag(InputFlag.IGNCR, e.getValue() != 0); break; case OCRNL: - attr.setOutputFlag(OutputFlag.OCRNL, e.getValue() != 0); + attributes.setOutputFlag(OutputFlag.OCRNL, e.getValue() != 0); break; case ONLCR: - attr.setOutputFlag(OutputFlag.ONLCR, e.getValue() != 0); + attributes.setOutputFlag(OutputFlag.ONLCR, e.getValue() != 0); break; case ONLRET: - attr.setOutputFlag(OutputFlag.ONLRET, e.getValue() != 0); + attributes.setOutputFlag(OutputFlag.ONLRET, e.getValue() != 0); break; case OPOST: - attr.setOutputFlag(OutputFlag.OPOST, e.getValue() != 0); + attributes.setOutputFlag(OutputFlag.OPOST, e.getValue() != 0); break; } } - terminal.setAttributes(attr); + Terminal terminal = TerminalBuilder.builder() + .name("JLine SSH") + .type(env.getEnv().get("TERM")) + .system(false) + .streams(in, out) + .attributes(attributes) + .size(new Size( + Integer.parseInt(env.getEnv().get("COLUMNS")), + Integer.parseInt(env.getEnv().get("LINES")))) + .build(); env.addSignalListener( (channel, signals) -> { terminal.setSize(new Size( diff --git a/remote-ssh/src/main/java/org/jline/builtins/ssh/Ssh.java b/remote-ssh/src/main/java/org/jline/builtins/ssh/Ssh.java index bec189ecc..20b8f68bf 100644 --- a/remote-ssh/src/main/java/org/jline/builtins/ssh/Ssh.java +++ b/remote-ssh/src/main/java/org/jline/builtins/ssh/Ssh.java @@ -203,49 +203,49 @@ public void ssh( try { Map modes = new HashMap<>(); // Control chars - modes.put(PtyMode.VINTR, attributes.getControlChar(Attributes.ControlChar.VINTR)); - modes.put(PtyMode.VQUIT, attributes.getControlChar(Attributes.ControlChar.VQUIT)); - modes.put(PtyMode.VERASE, attributes.getControlChar(Attributes.ControlChar.VERASE)); - modes.put(PtyMode.VKILL, attributes.getControlChar(Attributes.ControlChar.VKILL)); - modes.put(PtyMode.VEOF, attributes.getControlChar(Attributes.ControlChar.VEOF)); - modes.put(PtyMode.VEOL, attributes.getControlChar(Attributes.ControlChar.VEOL)); - modes.put(PtyMode.VEOL2, attributes.getControlChar(Attributes.ControlChar.VEOL2)); - modes.put(PtyMode.VSTART, attributes.getControlChar(Attributes.ControlChar.VSTART)); - modes.put(PtyMode.VSTOP, attributes.getControlChar(Attributes.ControlChar.VSTOP)); - modes.put(PtyMode.VSUSP, attributes.getControlChar(Attributes.ControlChar.VSUSP)); - modes.put(PtyMode.VDSUSP, attributes.getControlChar(Attributes.ControlChar.VDSUSP)); - modes.put(PtyMode.VREPRINT, attributes.getControlChar(Attributes.ControlChar.VREPRINT)); - modes.put(PtyMode.VWERASE, attributes.getControlChar(Attributes.ControlChar.VWERASE)); - modes.put(PtyMode.VLNEXT, attributes.getControlChar(Attributes.ControlChar.VLNEXT)); - modes.put(PtyMode.VSTATUS, attributes.getControlChar(Attributes.ControlChar.VSTATUS)); - modes.put(PtyMode.VDISCARD, attributes.getControlChar(Attributes.ControlChar.VDISCARD)); + setMode(modes, PtyMode.VINTR, attributes.getControlChar(Attributes.ControlChar.VINTR)); + setMode(modes, PtyMode.VQUIT, attributes.getControlChar(Attributes.ControlChar.VQUIT)); + setMode(modes, PtyMode.VERASE, attributes.getControlChar(Attributes.ControlChar.VERASE)); + setMode(modes, PtyMode.VKILL, attributes.getControlChar(Attributes.ControlChar.VKILL)); + setMode(modes, PtyMode.VEOF, attributes.getControlChar(Attributes.ControlChar.VEOF)); + setMode(modes, PtyMode.VEOL, attributes.getControlChar(Attributes.ControlChar.VEOL)); + setMode(modes, PtyMode.VEOL2, attributes.getControlChar(Attributes.ControlChar.VEOL2)); + setMode(modes, PtyMode.VSTART, attributes.getControlChar(Attributes.ControlChar.VSTART)); + setMode(modes, PtyMode.VSTOP, attributes.getControlChar(Attributes.ControlChar.VSTOP)); + setMode(modes, PtyMode.VSUSP, attributes.getControlChar(Attributes.ControlChar.VSUSP)); + setMode(modes, PtyMode.VDSUSP, attributes.getControlChar(Attributes.ControlChar.VDSUSP)); + setMode(modes, PtyMode.VREPRINT, attributes.getControlChar(Attributes.ControlChar.VREPRINT)); + setMode(modes, PtyMode.VWERASE, attributes.getControlChar(Attributes.ControlChar.VWERASE)); + setMode(modes, PtyMode.VLNEXT, attributes.getControlChar(Attributes.ControlChar.VLNEXT)); + setMode(modes, PtyMode.VSTATUS, attributes.getControlChar(Attributes.ControlChar.VSTATUS)); + setMode(modes, PtyMode.VDISCARD, attributes.getControlChar(Attributes.ControlChar.VDISCARD)); // Input flags - modes.put(PtyMode.IGNPAR, getFlag(attributes, Attributes.InputFlag.IGNPAR)); - modes.put(PtyMode.PARMRK, getFlag(attributes, Attributes.InputFlag.PARMRK)); - modes.put(PtyMode.INPCK, getFlag(attributes, Attributes.InputFlag.INPCK)); - modes.put(PtyMode.ISTRIP, getFlag(attributes, Attributes.InputFlag.ISTRIP)); - modes.put(PtyMode.INLCR, getFlag(attributes, Attributes.InputFlag.INLCR)); - modes.put(PtyMode.IGNCR, getFlag(attributes, Attributes.InputFlag.IGNCR)); - modes.put(PtyMode.ICRNL, getFlag(attributes, Attributes.InputFlag.ICRNL)); - modes.put(PtyMode.IXON, getFlag(attributes, Attributes.InputFlag.IXON)); - modes.put(PtyMode.IXANY, getFlag(attributes, Attributes.InputFlag.IXANY)); - modes.put(PtyMode.IXOFF, getFlag(attributes, Attributes.InputFlag.IXOFF)); + setMode(modes, PtyMode.IGNPAR, getFlag(attributes, Attributes.InputFlag.IGNPAR)); + setMode(modes, PtyMode.PARMRK, getFlag(attributes, Attributes.InputFlag.PARMRK)); + setMode(modes, PtyMode.INPCK, getFlag(attributes, Attributes.InputFlag.INPCK)); + setMode(modes, PtyMode.ISTRIP, getFlag(attributes, Attributes.InputFlag.ISTRIP)); + setMode(modes, PtyMode.INLCR, getFlag(attributes, Attributes.InputFlag.INLCR)); + setMode(modes, PtyMode.IGNCR, getFlag(attributes, Attributes.InputFlag.IGNCR)); + setMode(modes, PtyMode.ICRNL, getFlag(attributes, Attributes.InputFlag.ICRNL)); + setMode(modes, PtyMode.IXON, getFlag(attributes, Attributes.InputFlag.IXON)); + setMode(modes, PtyMode.IXANY, getFlag(attributes, Attributes.InputFlag.IXANY)); + setMode(modes, PtyMode.IXOFF, getFlag(attributes, Attributes.InputFlag.IXOFF)); // Local flags - modes.put(PtyMode.ISIG, getFlag(attributes, Attributes.LocalFlag.ISIG)); - modes.put(PtyMode.ICANON, getFlag(attributes, Attributes.LocalFlag.ICANON)); - modes.put(PtyMode.ECHO, getFlag(attributes, Attributes.LocalFlag.ECHO)); - modes.put(PtyMode.ECHOE, getFlag(attributes, Attributes.LocalFlag.ECHOE)); - modes.put(PtyMode.ECHOK, getFlag(attributes, Attributes.LocalFlag.ECHOK)); - modes.put(PtyMode.ECHONL, getFlag(attributes, Attributes.LocalFlag.ECHONL)); - modes.put(PtyMode.NOFLSH, getFlag(attributes, Attributes.LocalFlag.NOFLSH)); - modes.put(PtyMode.TOSTOP, getFlag(attributes, Attributes.LocalFlag.TOSTOP)); - modes.put(PtyMode.IEXTEN, getFlag(attributes, Attributes.LocalFlag.IEXTEN)); + setMode(modes, PtyMode.ISIG, getFlag(attributes, Attributes.LocalFlag.ISIG)); + setMode(modes, PtyMode.ICANON, getFlag(attributes, Attributes.LocalFlag.ICANON)); + setMode(modes, PtyMode.ECHO, getFlag(attributes, Attributes.LocalFlag.ECHO)); + setMode(modes, PtyMode.ECHOE, getFlag(attributes, Attributes.LocalFlag.ECHOE)); + setMode(modes, PtyMode.ECHOK, getFlag(attributes, Attributes.LocalFlag.ECHOK)); + setMode(modes, PtyMode.ECHONL, getFlag(attributes, Attributes.LocalFlag.ECHONL)); + setMode(modes, PtyMode.NOFLSH, getFlag(attributes, Attributes.LocalFlag.NOFLSH)); + setMode(modes, PtyMode.TOSTOP, getFlag(attributes, Attributes.LocalFlag.TOSTOP)); + setMode(modes, PtyMode.IEXTEN, getFlag(attributes, Attributes.LocalFlag.IEXTEN)); // Output flags - modes.put(PtyMode.OPOST, getFlag(attributes, Attributes.OutputFlag.OPOST)); - modes.put(PtyMode.ONLCR, getFlag(attributes, Attributes.OutputFlag.ONLCR)); - modes.put(PtyMode.OCRNL, getFlag(attributes, Attributes.OutputFlag.OCRNL)); - modes.put(PtyMode.ONOCR, getFlag(attributes, Attributes.OutputFlag.ONOCR)); - modes.put(PtyMode.ONLRET, getFlag(attributes, Attributes.OutputFlag.ONLRET)); + setMode(modes, PtyMode.OPOST, getFlag(attributes, Attributes.OutputFlag.OPOST)); + setMode(modes, PtyMode.ONLCR, getFlag(attributes, Attributes.OutputFlag.ONLCR)); + setMode(modes, PtyMode.OCRNL, getFlag(attributes, Attributes.OutputFlag.OCRNL)); + setMode(modes, PtyMode.ONOCR, getFlag(attributes, Attributes.OutputFlag.ONOCR)); + setMode(modes, PtyMode.ONLRET, getFlag(attributes, Attributes.OutputFlag.ONLRET)); channel.setPtyModes(modes); channel.setPtyColumns(terminal.getWidth()); channel.setPtyLines(terminal.getHeight()); @@ -304,6 +304,12 @@ public void ssh( } } + private static void setMode(Map modes, PtyMode vintr, int attributes) { + if (attributes >= 0) { + modes.put(vintr, attributes); + } + } + private static int getFlag(Attributes attributes, Attributes.InputFlag flag) { return attributes.getInputFlag(flag) ? 1 : 0; }