public static void main()

in client/src/main/java/org/apache/karaf/client/Main.java [72:338]


    public static void main(String[] args) throws Exception {
        ClientConfig config = new ClientConfig(args);
        SimpleLogger.setLevel(config.getLevel());

        if (config.getFile() != null) {
            StringBuilder sb = new StringBuilder();
            sb.setLength(0);
            try (Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(config.getFile())))) {
                for (int c = reader.read(); c >= 0; c = reader.read()) {
                    sb.append((char) c);
                }
            }
            config.setCommand(sb.toString());
        } else if (config.isBatch()) {
            StringBuilder sb = new StringBuilder();
            sb.setLength(0);
            Reader reader = new BufferedReader(new InputStreamReader(System.in));
            for (int c = reader.read(); c >= 0; c = reader.read()) {
                sb.append((char) c);
            }
            config.setCommand(sb.toString());
        }

        try (SshClient client = ClientBuilder.builder().build()) {
            FilePasswordProvider passwordProvider = null;
            final Console console = System.console();
            if (console != null) {
                passwordProvider = (session, resourceKey, retryIndex) -> {
                    char[] pwd = console.readPassword("Enter password for " + resourceKey + ": ");
                    return new String(pwd);
                };
                client.setFilePasswordProvider(passwordProvider);
                client.setUserInteraction(new UserInteraction() {
                    @Override
                    public void welcome(ClientSession s, String banner, String lang) {
                        System.out.println(banner);
                    }
                    @Override
                    public String[] interactive(ClientSession s, String name, String instruction, String lang, String[] prompt, boolean[] echo) {
                        String[] answers = new String[prompt.length];
                        try {
                            for (int i = 0; i < prompt.length; i++) {
                                if (echo[i]) {
                                    answers[i] = console.readLine(prompt[i] + " ");
                                } else {
                                    answers[i] = new String(console.readPassword(prompt[i] + " "));
                                }
                                if (answers[i] == null) {
                                    return null;
                                }
                            }
                            return answers;
                        } catch (IOError e) {
                            return null;
                        }
                    }
                    @Override
                    public boolean isInteractionAllowed(ClientSession session) {
                        return true;
                    }
                    @Override
                    public void serverVersionInfo(ClientSession session, List<String> lines) {
                    }
                    @Override
                    public String getUpdatedPassword(ClientSession session, String prompt, String lang) {
                        return null;
                    }
                });
            }

            if (config.getUser()==null || config.getUser().isEmpty()) {
            	while (true) {
            		String user = console.readLine("Enter user: ");
            		if (user==null || user.isEmpty()) {
            			System.err.println("User must not be empty!");
            		}
            		else {
                    	config.setUser(user);
                    	break;
            		}
            	}
            }
            else if (console != null) {
                console.printf("Logging in as %s\n", config.getUser());
            }

            setupAgent(config.getUser(), config.getKeyFile(), client, passwordProvider);

            // define hearbeat (for the keep alive) and timeouts
            // TODO this should be dealt by Apache SSH client directly using .ssh/config
            CoreModuleProperties.HEARTBEAT_INTERVAL.set(client, Duration.ofMillis(60000));
            CoreModuleProperties.IDLE_TIMEOUT.set(client, Duration.ofMillis(config.getIdleTimeout()));
            CoreModuleProperties.NIO2_READ_TIMEOUT.set(client, Duration.ofMillis(config.getIdleTimeout()));

            // TODO: remove the line below when SSHD-732 is fixed
            // client.setKeyPairProvider(new FileKeyPairProvider());
            client.start();
            ClientSession session = connectWithRetries(client, config);
            if (config.getPassword() != null) {
                session.addPasswordIdentity(config.getPassword());
            }
            session.auth().verify();

            int exitStatus = 0;
            String type = System.getProperty(TerminalBuilder.PROP_TYPE);
            if (type == null) {
                type = System.getenv("TERM");
            }
            if (type == null) {
                type = Terminal.TYPE_DUMB;
            }
            try (Terminal terminal = TerminalBuilder.builder()
                        .nativeSignals(true)
                        .type(type)
                        .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]));
                    if (!config.isBatch()) {
                        new Thread(() -> {
                            while (true) {
                                try {
                                    int a = System.in.read();
                                    if (a == -1) {
                                        channel.close(true);
                                        break;
                                    }
                                    Thread.sleep(1000);
                                } catch (Exception e) {
                                    //ignore
                                }
                            }
                        }).start();
                    }
                    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);
                    if (channel.getExitStatus() != null) {
                        exitStatus = channel.getExitStatus();
                    }

                } else {
                    ChannelShell channel = session.createShellChannel();
                    Attributes attributes = terminal.enterRawMode();
                    try {
                        Map<PtyMode, Integer> modes = new HashMap<>();
                        // Control chars
                        addMode(modes, PtyMode.VINTR, attributes, ControlChar.VINTR);
                        addMode(modes, PtyMode.VQUIT, attributes, ControlChar.VQUIT);
                        addMode(modes, PtyMode.VERASE, attributes, ControlChar.VERASE);
                        addMode(modes, PtyMode.VKILL, attributes, ControlChar.VKILL);
                        addMode(modes, PtyMode.VEOF, attributes, ControlChar.VEOF);
                        addMode(modes, PtyMode.VEOL, attributes, ControlChar.VEOL);
                        addMode(modes, PtyMode.VEOL2, attributes, ControlChar.VEOL2);
                        addMode(modes, PtyMode.VSTART, attributes, ControlChar.VSTART);
                        addMode(modes, PtyMode.VSTOP, attributes, ControlChar.VSTOP);
                        addMode(modes, PtyMode.VSUSP, attributes, ControlChar.VSUSP);
                        addMode(modes, PtyMode.VDSUSP, attributes, ControlChar.VDSUSP);
                        addMode(modes, PtyMode.VREPRINT, attributes, ControlChar.VREPRINT);
                        addMode(modes, PtyMode.VWERASE, attributes, ControlChar.VWERASE);
                        addMode(modes, PtyMode.VLNEXT, attributes, ControlChar.VLNEXT);
                        addMode(modes, PtyMode.VSTATUS, attributes, ControlChar.VSTATUS);
                        addMode(modes, PtyMode.VDISCARD, attributes, ControlChar.VDISCARD);
                        // Input flags
                        modes.put(PtyMode.IGNPAR, getFlag(attributes, InputFlag.IGNPAR));
                        modes.put(PtyMode.PARMRK, getFlag(attributes, InputFlag.PARMRK));
                        modes.put(PtyMode.INPCK, getFlag(attributes, InputFlag.INPCK));
                        modes.put(PtyMode.ISTRIP, getFlag(attributes, InputFlag.ISTRIP));
                        modes.put(PtyMode.INLCR, getFlag(attributes, InputFlag.INLCR));
                        modes.put(PtyMode.IGNCR, getFlag(attributes, InputFlag.IGNCR));
                        modes.put(PtyMode.ICRNL, getFlag(attributes, InputFlag.ICRNL));
                        modes.put(PtyMode.IXON, getFlag(attributes, InputFlag.IXON));
                        modes.put(PtyMode.IXANY, getFlag(attributes, InputFlag.IXANY));
                        modes.put(PtyMode.IXOFF, getFlag(attributes, InputFlag.IXOFF));
                        // Local flags
                        modes.put(PtyMode.ISIG, getFlag(attributes, LocalFlag.ISIG));
                        modes.put(PtyMode.ICANON, getFlag(attributes, LocalFlag.ICANON));
                        modes.put(PtyMode.ECHO, getFlag(attributes, LocalFlag.ECHO));
                        modes.put(PtyMode.ECHOE, getFlag(attributes, LocalFlag.ECHOE));
                        modes.put(PtyMode.ECHOK, getFlag(attributes, LocalFlag.ECHOK));
                        modes.put(PtyMode.ECHONL, getFlag(attributes, LocalFlag.ECHONL));
                        modes.put(PtyMode.NOFLSH, getFlag(attributes, LocalFlag.NOFLSH));
                        modes.put(PtyMode.TOSTOP, getFlag(attributes, LocalFlag.TOSTOP));
                        modes.put(PtyMode.IEXTEN, getFlag(attributes, LocalFlag.IEXTEN));
                        // Output flags
                        modes.put(PtyMode.OPOST, getFlag(attributes, OutputFlag.OPOST));
                        modes.put(PtyMode.ONLCR, getFlag(attributes, OutputFlag.ONLCR));
                        modes.put(PtyMode.OCRNL, getFlag(attributes, OutputFlag.OCRNL));
                        modes.put(PtyMode.ONOCR, getFlag(attributes, OutputFlag.ONOCR));
                        modes.put(PtyMode.ONLRET, getFlag(attributes, OutputFlag.ONLRET));
                        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());
                        }
                        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);
                    }
                }
            }
            System.exit(exitStatus);
        } catch (Throwable t) {
            if (config.getLevel() > SimpleLogger.WARN) {
                t.printStackTrace();
            } else {
                System.err.println(t.getMessage());
            }
            System.exit(1);
        }
    }