/*
* 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.karaf.shell.ssh;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.EnumSet;
import java.util.Map;
import org.apache.karaf.shell.api.console.SignalListener;
import org.apache.karaf.shell.api.console.Terminal;
import org.apache.sshd.common.channel.PtyMode;
import org.apache.sshd.server.Environment;
import org.jline.terminal.Attributes.ControlChar;
import org.jline.terminal.Attributes.InputFlag;
import org.jline.terminal.Attributes.LocalFlag;
import org.jline.terminal.Attributes.OutputFlag;
import org.jline.terminal.Size;
import org.jline.terminal.impl.ExternalTerminal;
public class SshTerminal extends ExternalTerminal implements Terminal {
private Environment environment;
public SshTerminal(Environment environment, InputStream input, OutputStream output) throws IOException {
super("Karaf SSH terminal",
environment.getEnv().get(Environment.ENV_TERM),
input,
output,
"UTF-8");
this.environment = environment;
this.environment.addSignalListener(this::handleSignal);
for (Map.Entry<PtyMode, Integer> e : environment.getPtyModes().entrySet()) {
switch (e.getKey()) {
case VINTR:
attributes.setControlChar(ControlChar.VINTR, e.getValue());
break;
case VQUIT:
attributes.setControlChar(ControlChar.VQUIT, e.getValue());
break;
case VERASE:
attributes.setControlChar(ControlChar.VERASE, e.getValue());
break;
case VKILL:
attributes.setControlChar(ControlChar.VKILL, e.getValue());
break;
case VEOF:
attributes.setControlChar(ControlChar.VEOF, e.getValue());
break;
case VEOL:
attributes.setControlChar(ControlChar.VEOL, e.getValue());
break;
case VEOL2:
attributes.setControlChar(ControlChar.VEOL2, e.getValue());
break;
case VSTART:
attributes.setControlChar(ControlChar.VSTART, e.getValue());
break;
case VSTOP:
attributes.setControlChar(ControlChar.VSTOP, e.getValue());
break;
case VSUSP:
attributes.setControlChar(ControlChar.VSUSP, e.getValue());
break;
case VDSUSP:
attributes.setControlChar(ControlChar.VDSUSP, e.getValue());
break;
case VREPRINT:
attributes.setControlChar(ControlChar.VREPRINT, e.getValue());
break;
case VWERASE:
attributes.setControlChar(ControlChar.VWERASE, e.getValue());
break;
case VLNEXT:
attributes.setControlChar(ControlChar.VLNEXT, e.getValue());
break;
case VSTATUS:
attributes.setControlChar(ControlChar.VSTATUS, e.getValue());
break;
case VDISCARD:
attributes.setControlChar(ControlChar.VDISCARD, e.getValue());
break;
case ECHO:
attributes.setLocalFlag(LocalFlag.ECHO, e.getValue() != 0);
break;
case ICANON:
attributes.setLocalFlag(LocalFlag.ICANON, e.getValue() != 0);
break;
case ISIG:
attributes.setLocalFlag(LocalFlag.ISIG, e.getValue() != 0);
break;
case ICRNL:
attributes.setInputFlag(InputFlag.ICRNL, e.getValue() != 0);
break;
case INLCR:
attributes.setInputFlag(InputFlag.INLCR, e.getValue() != 0);
break;
case IGNCR:
attributes.setInputFlag(InputFlag.IGNCR, e.getValue() != 0);
break;
case OCRNL:
attributes.setOutputFlag(OutputFlag.OCRNL, e.getValue() != 0);
break;
case ONLCR:
attributes.setOutputFlag(OutputFlag.ONLCR, e.getValue() != 0);
break;
case ONLRET:
attributes.setOutputFlag(OutputFlag.ONLRET, e.getValue() != 0);
break;
case OPOST:
attributes.setOutputFlag(OutputFlag.OPOST, e.getValue() != 0);
break;
}
}
int w = Integer.valueOf(this.environment.getEnv().get(Environment.ENV_COLUMNS));
int h = Integer.valueOf(this.environment.getEnv().get(Environment.ENV_LINES));
setSize(new Size(w, h));
}
protected void handleSignal(org.apache.sshd.server.Signal signal) {
if (signal == org.apache.sshd.server.Signal.INT) {
raise(Signal.INT);
} else if (signal == org.apache.sshd.server.Signal.QUIT) {
raise(Signal.QUIT);
} else if (signal == org.apache.sshd.server.Signal.TSTP) {
raise(Signal.TSTP);
} else if (signal == org.apache.sshd.server.Signal.CONT) {
raise(Signal.CONT);
} else if (signal == org.apache.sshd.server.Signal.WINCH) {
int w = Integer.valueOf(this.environment.getEnv().get(Environment.ENV_COLUMNS));
int h = Integer.valueOf(this.environment.getEnv().get(Environment.ENV_LINES));
setSize(new Size(w, h));
raise(Signal.WINCH);
}
}
@Override
public int getWidth() {
return size.getColumns();
}
@Override
public int getHeight() {
return size.getRows();
}
@Override
public void addSignalListener(SignalListener listener) {
// TODO:JLINE
}
@Override
public void addSignalListener(SignalListener listener, org.apache.karaf.shell.api.console.Signal... signal) {
// TODO:JLINE
}
@Override
public void addSignalListener(SignalListener listener, EnumSet<org.apache.karaf.shell.api.console.Signal> signals) {
// TODO:JLINE
}
@Override
public void removeSignalListener(SignalListener listener) {
// TODO:JLINE
}
@Override
public boolean isAnsiSupported() {
return true;
}
@Override
public boolean isEchoEnabled() {
return echo();
}
@Override
public void setEchoEnabled(boolean enabled) {
echo(enabled);
}
}