8306983: Do not invoke external programs when switch terminal to raw mode on selected platforms

Co-authored-by: Adam Sotona <asotona@openjdk.org>
Reviewed-by: erikj, vromero, bpb
This commit is contained in:
Jan Lahoda 2023-05-22 10:39:26 +00:00
parent 6b65e5754c
commit a9705196ce
22 changed files with 2072 additions and 15 deletions

View File

@ -27,14 +27,16 @@ include LibCommon.gmk
################################################################################
ifeq ($(call isTargetOs, windows), true)
ifeq ($(call isTargetOs, linux macosx windows), true)
$(eval $(call SetupJdkLibrary, BUILD_LIBLE, \
NAME := le, \
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB), \
CFLAGS := $(CXXFLAGS_JDKLIB), \
LDFLAGS := $(LDFLAGS_JDKLIB), \
LIBS := $(JDKLIB_LIBS) user32.lib, \
LIBS_unix := $(JDKLIB_LIBS) $(LIBCXX), \
LIBS_windows := $(JDKLIB_LIBS) user32.lib, \
))
TARGETS += $(BUILD_LIBLE)

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.org.jline.terminal.impl.jna;
import java.io.IOException;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.impl.jna.linux.LinuxNativePty;
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
class JDKNativePty {
static JnaNativePty current(TerminalProvider.Stream console) throws IOException {
return LinuxNativePty.current(console);
}
static JnaNativePty open(Attributes attr, Size size) throws IOException {
return LinuxNativePty.open(attr, size);
}
static int isatty(int fd) {
return LinuxNativePty.isatty(fd);
}
static String ttyname(int fd) {
return LinuxNativePty.ttyname(fd);
}
}

View File

@ -0,0 +1,389 @@
/*
* Copyright (c) 2002-2020, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna.linux;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
//import com.sun.jna.LastErrorException;
//import com.sun.jna.Platform;
//import com.sun.jna.Structure;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.Attributes.ControlChar;
import jdk.internal.org.jline.terminal.Attributes.ControlFlag;
import jdk.internal.org.jline.terminal.Attributes.InputFlag;
import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
public interface CLibrary {//extends com.sun.jna.Library {
void tcgetattr(int fd, termios termios) throws LastErrorException;
void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException;
void ioctl(int fd, int cmd, winsize data) throws LastErrorException;
int isatty(int fd);
void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException;
class winsize { //extends Structure {
public short ws_row;
public short ws_col;
public short ws_xpixel;
public short ws_ypixel;
public winsize() {
}
public winsize(Size ws) {
ws_row = (short) ws.getRows();
ws_col = (short) ws.getColumns();
}
public Size toSize() {
return new Size(ws_col, ws_row);
}
// @Override
// protected List<String> getFieldOrder() {
// return Arrays.asList(//
// "ws_row",//
// "ws_col",//
// "ws_xpixel",//
// "ws_ypixel"//
// );
// }
}
class termios {// extends Structure {
public int c_iflag;
public int c_oflag;
public int c_cflag;
public int c_lflag;
public byte c_line;
public byte[] c_cc = new byte[32];
public int c_ispeed;
public int c_ospeed;
// @Override
// protected List<String> getFieldOrder() {
// return Arrays.asList(//
// "c_iflag",//
// "c_oflag",//
// "c_cflag",//
// "c_lflag",//
// "c_line",//
// "c_cc",//
// "c_ispeed",//
// "c_ospeed"//
// );
// }
public termios() {
}
public termios(Attributes t) {
// Input flags
c_iflag = setFlag(t.getInputFlag(InputFlag.IGNBRK), IGNBRK, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.BRKINT), BRKINT, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.IGNPAR), IGNPAR, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.PARMRK), PARMRK, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.INPCK), INPCK, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.ISTRIP), ISTRIP, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.INLCR), INLCR, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.IGNCR), IGNCR, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.ICRNL), ICRNL, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.IXON), IXON, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.IXOFF), IXOFF, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.IXANY), IXANY, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.IMAXBEL), IMAXBEL, c_iflag);
c_iflag = setFlag(t.getInputFlag(InputFlag.IUTF8), IUTF8, c_iflag);
// Output flags
c_oflag = setFlag(t.getOutputFlag(OutputFlag.OPOST), OPOST, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONLCR), ONLCR, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.OCRNL), OCRNL, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONOCR), ONOCR, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONLRET), ONLRET, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.OFILL), OFILL, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.NLDLY), NLDLY, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.TABDLY), TABDLY, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.CRDLY), CRDLY, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.FFDLY), FFDLY, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.BSDLY), BSDLY, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.VTDLY), VTDLY, c_oflag);
c_oflag = setFlag(t.getOutputFlag(OutputFlag.OFDEL), OFDEL, c_oflag);
// Control flags
c_cflag = setFlag(t.getControlFlag(ControlFlag.CS5), CS5, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.CS6), CS6, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.CS7), CS7, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.CS8), CS8, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.CSTOPB), CSTOPB, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.CREAD), CREAD, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.PARENB), PARENB, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.PARODD), PARODD, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.HUPCL), HUPCL, c_cflag);
c_cflag = setFlag(t.getControlFlag(ControlFlag.CLOCAL), CLOCAL, c_cflag);
// Local flags
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOKE), ECHOKE, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOE), ECHOE, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOK), ECHOK, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHO), ECHO, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHONL), ECHONL, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOPRT), ECHOPRT, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOCTL), ECHOCTL, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ISIG), ISIG, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ICANON), ICANON, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.EXTPROC), EXTPROC, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.TOSTOP), TOSTOP, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.FLUSHO), FLUSHO, c_lflag);
c_lflag = setFlag(t.getLocalFlag(LocalFlag.NOFLSH), NOFLSH, c_lflag);
// Control chars
c_cc[VEOF] = (byte) t.getControlChar(ControlChar.VEOF);
c_cc[VEOL] = (byte) t.getControlChar(ControlChar.VEOL);
c_cc[VEOL2] = (byte) t.getControlChar(ControlChar.VEOL2);
c_cc[VERASE] = (byte) t.getControlChar(ControlChar.VERASE);
c_cc[VWERASE] = (byte) t.getControlChar(ControlChar.VWERASE);
c_cc[VKILL] = (byte) t.getControlChar(ControlChar.VKILL);
c_cc[VREPRINT] = (byte) t.getControlChar(ControlChar.VREPRINT);
c_cc[VINTR] = (byte) t.getControlChar(ControlChar.VINTR);
c_cc[VQUIT] = (byte) t.getControlChar(ControlChar.VQUIT);
c_cc[VSUSP] = (byte) t.getControlChar(ControlChar.VSUSP);
c_cc[VSTART] = (byte) t.getControlChar(ControlChar.VSTART);
c_cc[VSTOP] = (byte) t.getControlChar(ControlChar.VSTOP);
c_cc[VLNEXT] = (byte) t.getControlChar(ControlChar.VLNEXT);
c_cc[VDISCARD] = (byte) t.getControlChar(ControlChar.VDISCARD);
c_cc[VMIN] = (byte) t.getControlChar(ControlChar.VMIN);
c_cc[VTIME] = (byte) t.getControlChar(ControlChar.VTIME);
}
private int setFlag(boolean flag, int value, int org) {
return flag ? (org | value) : org;
}
public Attributes toAttributes() {
Attributes attr = new Attributes();
// Input flags
EnumSet<InputFlag> iflag = attr.getInputFlags();
addFlag(c_iflag, iflag, InputFlag.IGNBRK, IGNBRK);
addFlag(c_iflag, iflag, InputFlag.IGNBRK, IGNBRK);
addFlag(c_iflag, iflag, InputFlag.BRKINT, BRKINT);
addFlag(c_iflag, iflag, InputFlag.IGNPAR, IGNPAR);
addFlag(c_iflag, iflag, InputFlag.PARMRK, PARMRK);
addFlag(c_iflag, iflag, InputFlag.INPCK, INPCK);
addFlag(c_iflag, iflag, InputFlag.ISTRIP, ISTRIP);
addFlag(c_iflag, iflag, InputFlag.INLCR, INLCR);
addFlag(c_iflag, iflag, InputFlag.IGNCR, IGNCR);
addFlag(c_iflag, iflag, InputFlag.ICRNL, ICRNL);
addFlag(c_iflag, iflag, InputFlag.IXON, IXON);
addFlag(c_iflag, iflag, InputFlag.IXOFF, IXOFF);
addFlag(c_iflag, iflag, InputFlag.IXANY, IXANY);
addFlag(c_iflag, iflag, InputFlag.IMAXBEL, IMAXBEL);
addFlag(c_iflag, iflag, InputFlag.IUTF8, IUTF8);
// Output flags
EnumSet<OutputFlag> oflag = attr.getOutputFlags();
addFlag(c_oflag, oflag, OutputFlag.OPOST, OPOST);
addFlag(c_oflag, oflag, OutputFlag.ONLCR, ONLCR);
addFlag(c_oflag, oflag, OutputFlag.OCRNL, OCRNL);
addFlag(c_oflag, oflag, OutputFlag.ONOCR, ONOCR);
addFlag(c_oflag, oflag, OutputFlag.ONLRET, ONLRET);
addFlag(c_oflag, oflag, OutputFlag.OFILL, OFILL);
addFlag(c_oflag, oflag, OutputFlag.NLDLY, NLDLY);
addFlag(c_oflag, oflag, OutputFlag.TABDLY, TABDLY);
addFlag(c_oflag, oflag, OutputFlag.CRDLY, CRDLY);
addFlag(c_oflag, oflag, OutputFlag.FFDLY, FFDLY);
addFlag(c_oflag, oflag, OutputFlag.BSDLY, BSDLY);
addFlag(c_oflag, oflag, OutputFlag.VTDLY, VTDLY);
addFlag(c_oflag, oflag, OutputFlag.OFDEL, OFDEL);
// Control flags
EnumSet<ControlFlag> cflag = attr.getControlFlags();
addFlag(c_cflag, cflag, ControlFlag.CS5, CS5);
addFlag(c_cflag, cflag, ControlFlag.CS6, CS6);
addFlag(c_cflag, cflag, ControlFlag.CS7, CS7);
addFlag(c_cflag, cflag, ControlFlag.CS8, CS8);
addFlag(c_cflag, cflag, ControlFlag.CSTOPB, CSTOPB);
addFlag(c_cflag, cflag, ControlFlag.CREAD, CREAD);
addFlag(c_cflag, cflag, ControlFlag.PARENB, PARENB);
addFlag(c_cflag, cflag, ControlFlag.PARODD, PARODD);
addFlag(c_cflag, cflag, ControlFlag.HUPCL, HUPCL);
addFlag(c_cflag, cflag, ControlFlag.CLOCAL, CLOCAL);
// Local flags
EnumSet<LocalFlag> lflag = attr.getLocalFlags();
addFlag(c_lflag, lflag, LocalFlag.ECHOKE, ECHOKE);
addFlag(c_lflag, lflag, LocalFlag.ECHOE, ECHOE);
addFlag(c_lflag, lflag, LocalFlag.ECHOK, ECHOK);
addFlag(c_lflag, lflag, LocalFlag.ECHO, ECHO);
addFlag(c_lflag, lflag, LocalFlag.ECHONL, ECHONL);
addFlag(c_lflag, lflag, LocalFlag.ECHOPRT, ECHOPRT);
addFlag(c_lflag, lflag, LocalFlag.ECHOCTL, ECHOCTL);
addFlag(c_lflag, lflag, LocalFlag.ISIG, ISIG);
addFlag(c_lflag, lflag, LocalFlag.ICANON, ICANON);
addFlag(c_lflag, lflag, LocalFlag.EXTPROC, EXTPROC);
addFlag(c_lflag, lflag, LocalFlag.TOSTOP, TOSTOP);
addFlag(c_lflag, lflag, LocalFlag.FLUSHO, FLUSHO);
addFlag(c_lflag, lflag, LocalFlag.NOFLSH, NOFLSH);
// Control chars
EnumMap<ControlChar, Integer> cc = attr.getControlChars();
cc.put(ControlChar.VEOF, (int) c_cc[VEOF]);
cc.put(ControlChar.VEOL, (int) c_cc[VEOL]);
cc.put(ControlChar.VEOL2, (int) c_cc[VEOL2]);
cc.put(ControlChar.VERASE, (int) c_cc[VERASE]);
cc.put(ControlChar.VWERASE, (int) c_cc[VWERASE]);
cc.put(ControlChar.VKILL, (int) c_cc[VKILL]);
cc.put(ControlChar.VREPRINT, (int) c_cc[VREPRINT]);
cc.put(ControlChar.VINTR, (int) c_cc[VINTR]);
cc.put(ControlChar.VQUIT, (int) c_cc[VQUIT]);
cc.put(ControlChar.VSUSP, (int) c_cc[VSUSP]);
cc.put(ControlChar.VSTART, (int) c_cc[VSTART]);
cc.put(ControlChar.VSTOP, (int) c_cc[VSTOP]);
cc.put(ControlChar.VLNEXT, (int) c_cc[VLNEXT]);
cc.put(ControlChar.VDISCARD, (int) c_cc[VDISCARD]);
cc.put(ControlChar.VMIN, (int) c_cc[VMIN]);
cc.put(ControlChar.VTIME, (int) c_cc[VTIME]);
// Return
return attr;
}
private <T extends Enum<T>> void addFlag(int value, EnumSet<T> flags, T flag, int v) {
if ((value & v) != 0) {
flags.add(flag);
}
}
}
// CONSTANTS
int TIOCGWINSZ = /*Platform.isMIPS() || Platform.isPPC() || Platform.isSPARC() ? 0x40087468 : */0x00005413;
int TIOCSWINSZ = /*Platform.isMIPS() || Platform.isPPC() || Platform.isSPARC() ? 0x80087467 : */0x00005414;
int VINTR = 0;
int VQUIT = 1;
int VERASE = 2;
int VKILL = 3;
int VEOF = 4;
int VTIME = 5;
int VMIN = 6;
int VSWTC = 7;
int VSTART = 8;
int VSTOP = 9;
int VSUSP = 10;
int VEOL = 11;
int VREPRINT = 12;
int VDISCARD = 13;
int VWERASE = 14;
int VLNEXT = 15;
int VEOL2 = 16;
int IGNBRK = 0x0000001;
int BRKINT = 0x0000002;
int IGNPAR = 0x0000004;
int PARMRK = 0x0000008;
int INPCK = 0x0000010;
int ISTRIP = 0x0000020;
int INLCR = 0x0000040;
int IGNCR = 0x0000080;
int ICRNL = 0x0000100;
int IUCLC = 0x0000200;
int IXON = 0x0000400;
int IXANY = 0x0000800;
int IXOFF = 0x0001000;
int IMAXBEL = 0x0002000;
int IUTF8 = 0x0004000;
int OPOST = 0x0000001;
int OLCUC = 0x0000002;
int ONLCR = 0x0000004;
int OCRNL = 0x0000008;
int ONOCR = 0x0000010;
int ONLRET = 0x0000020;
int OFILL = 0x0000040;
int OFDEL = 0x0000080;
int NLDLY = 0x0000100;
int NL0 = 0x0000000;
int NL1 = 0x0000100;
int CRDLY = 0x0000600;
int CR0 = 0x0000000;
int CR1 = 0x0000200;
int CR2 = 0x0000400;
int CR3 = 0x0000600;
int TABDLY = 0x0001800;
int TAB0 = 0x0000000;
int TAB1 = 0x0000800;
int TAB2 = 0x0001000;
int TAB3 = 0x0001800;
int XTABS = 0x0001800;
int BSDLY = 0x0002000;
int BS0 = 0x0000000;
int BS1 = 0x0002000;
int VTDLY = 0x0004000;
int VT0 = 0x0000000;
int VT1 = 0x0004000;
int FFDLY = 0x0008000;
int FF0 = 0x0000000;
int FF1 = 0x0008000;
int CBAUD = 0x000100f;
int B0 = 0x0000000;
int B50 = 0x0000001;
int B75 = 0x0000002;
int B110 = 0x0000003;
int B134 = 0x0000004;
int B150 = 0x0000005;
int B200 = 0x0000006;
int B300 = 0x0000007;
int B600 = 0x0000008;
int B1200 = 0x0000009;
int B1800 = 0x000000a;
int B2400 = 0x000000b;
int B4800 = 0x000000c;
int B9600 = 0x000000d;
int B19200 = 0x000000e;
int B38400 = 0x000000f;
int EXTA = B19200;
int EXTB = B38400;
int CSIZE = 0x0000030;
int CS5 = 0x0000000;
int CS6 = 0x0000010;
int CS7 = 0x0000020;
int CS8 = 0x0000030;
int CSTOPB = 0x0000040;
int CREAD = 0x0000080;
int PARENB = 0x0000100;
int PARODD = 0x0000200;
int HUPCL = 0x0000400;
int CLOCAL = 0x0000800;
int ISIG = 0x0000001;
int ICANON = 0x0000002;
int XCASE = 0x0000004;
int ECHO = 0x0000008;
int ECHOE = 0x0000010;
int ECHOK = 0x0000020;
int ECHONL = 0x0000040;
int NOFLSH = 0x0000080;
int TOSTOP = 0x0000100;
int ECHOCTL = 0x0000200;
int ECHOPRT = 0x0000400;
int ECHOKE = 0x0000800;
int FLUSHO = 0x0001000;
int PENDIN = 0x0002000;
int IEXTEN = 0x0008000;
int EXTPROC = 0x0010000;
int TCSANOW = 0x0;
int TCSADRAIN = 0x1;
int TCSAFLUSH = 0x2;
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.org.jline.terminal.impl.jna.linux;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
public final class CLibraryImpl implements CLibrary {
static {
System.loadLibrary("le");
initIDs();
}
private static native void initIDs();
@Override
public native void tcgetattr(int fd, termios termios) throws LastErrorException;
@Override
public native void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException;
@Override
public void ioctl(int fd, int cmd, winsize data) throws LastErrorException {
if (cmd == CLibrary.TIOCGWINSZ || cmd == CLibrary.TIOCSWINSZ) {
ioctl0(fd, cmd, data);
} else {
throw new UnsupportedOperationException("Command: " + cmd + ", not supported.");
}
}
private native void ioctl0(int fd, int cmd, winsize data) throws LastErrorException;
@Override
public native int isatty(int fd);
@Override
public native void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException;
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2002-2020, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna.linux;
import java.io.FileDescriptor;
import java.io.IOException;
//import com.sun.jna.LastErrorException;
//import com.sun.jna.Native;
//import com.sun.jna.Platform;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.impl.jna.JnaNativePty;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TCSADRAIN;
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TIOCGWINSZ;
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TIOCSWINSZ;
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.termios;
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.winsize;
public class LinuxNativePty extends JnaNativePty {
// private static final CLibrary C_LIBRARY = Native.load(Platform.C_LIBRARY_NAME, CLibrary.class);
private static final CLibrary C_LIBRARY = new CLibraryImpl();
public interface UtilLibrary {// extends com.sun.jna.Library {
void openpty(int[] master, int[] slave, byte[] name, CLibrary.termios t, CLibrary.winsize s) throws LastErrorException;
// UtilLibrary INSTANCE = Native.load("util", UtilLibrary.class);
UtilLibrary INSTANCE = new UtilLibraryImpl();
}
public static LinuxNativePty current(TerminalProvider.Stream consoleStream) throws IOException {
switch (consoleStream) {
case Output:
return new LinuxNativePty(-1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(0));
case Error:
return new LinuxNativePty(-1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(0));
default:
throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream);
}
}
public static LinuxNativePty open(Attributes attr, Size size) throws IOException {
int[] master = new int[1];
int[] slave = new int[1];
byte[] buf = new byte[64];
UtilLibrary.INSTANCE.openpty(master, slave, buf,
attr != null ? new termios(attr) : null,
size != null ? new winsize(size) : null);
int len = 0;
while (buf[len] != 0) {
len++;
}
String name = new String(buf, 0, len);
return new LinuxNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name);
}
public LinuxNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
super(master, masterFD, slave, slaveFD, name);
}
public LinuxNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, int slaveOut, FileDescriptor slaveOutFD, String name) {
super(master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name);
}
@Override
public Attributes getAttr() throws IOException {
termios termios = new termios();
C_LIBRARY.tcgetattr(getSlave(), termios);
return termios.toAttributes();
}
@Override
protected void doSetAttr(Attributes attr) throws IOException {
termios termios = new termios(attr);
termios org = new termios();
C_LIBRARY.tcgetattr(getSlave(), org);
org.c_iflag = termios.c_iflag;
org.c_oflag = termios.c_oflag;
org.c_lflag = termios.c_lflag;
System.arraycopy(termios.c_cc, 0, org.c_cc, 0, termios.c_cc.length);
C_LIBRARY.tcsetattr(getSlave(), TCSADRAIN, org);
}
@Override
public Size getSize() throws IOException {
winsize sz = new winsize();
C_LIBRARY.ioctl(getSlave(), TIOCGWINSZ, sz);
return sz.toSize();
}
@Override
public void setSize(Size size) throws IOException {
winsize sz = new winsize(size);
C_LIBRARY.ioctl(getSlave(), TIOCSWINSZ, sz);
}
public static int isatty(int fd) {
return C_LIBRARY.isatty(fd);
}
public static String ttyname(int slave) {
byte[] buf = new byte[64];
C_LIBRARY.ttyname_r(slave, buf, buf.length);
int len = 0;
while (buf[len] != 0) {
len++;
}
return new String(buf, 0, len);
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.org.jline.terminal.impl.jna.linux;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
import jdk.internal.org.jline.terminal.impl.jna.linux.LinuxNativePty.UtilLibrary;
public final class UtilLibraryImpl implements UtilLibrary {
@Override
public void openpty(int[] master, int[] slave, byte[] name, CLibrary.termios t, CLibrary.winsize s) throws LastErrorException {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl.h"
#include <errno.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
static jclass lastErrorExceptionClass;
static jmethodID lastErrorExceptionConstructor;
static jclass termios_j;
static jfieldID c_iflag;
static jfieldID c_oflag;
static jfieldID c_cflag;
static jfieldID c_lflag;
static jfieldID c_line;
static jfieldID c_cc;
static jfieldID c_ispeed;
static jfieldID c_ospeed;
static jclass winsize_j;
static jfieldID ws_row;
static jfieldID ws_col;
static jfieldID ws_xpixel;
static jfieldID ws_ypixel;
static void throw_errno(JNIEnv *env);
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_initIDs
(JNIEnv *env, jclass unused) {
jclass cls;
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/LastErrorException");
CHECK_NULL(cls);
lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls);
lastErrorExceptionConstructor = env->GetMethodID(lastErrorExceptionClass, "<init>", "(J)V");
CHECK_NULL(lastErrorExceptionConstructor);
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary$termios");
CHECK_NULL(cls);
termios_j = (jclass) env->NewGlobalRef(cls);
c_iflag = env->GetFieldID(termios_j, "c_iflag", "I");
CHECK_NULL(c_iflag);
c_oflag = env->GetFieldID(termios_j, "c_oflag", "I");
CHECK_NULL(c_oflag);
c_cflag = env->GetFieldID(termios_j, "c_cflag", "I");
CHECK_NULL(c_cflag);
c_lflag = env->GetFieldID(termios_j, "c_lflag", "I");
CHECK_NULL(c_lflag);
c_line = env->GetFieldID(termios_j, "c_line", "B");
CHECK_NULL(c_line);
c_cc = env->GetFieldID(termios_j, "c_cc", "[B");
CHECK_NULL(c_cc);
c_ispeed = env->GetFieldID(termios_j, "c_ispeed", "I");
CHECK_NULL(c_ispeed);
c_ospeed = env->GetFieldID(termios_j, "c_ospeed", "I");
CHECK_NULL(c_ospeed);
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary$winsize");
CHECK_NULL(cls);
winsize_j = (jclass) env->NewGlobalRef(cls);
ws_row = env->GetFieldID(winsize_j, "ws_row", "S");
CHECK_NULL(ws_row);
ws_col = env->GetFieldID(winsize_j, "ws_col", "S");
CHECK_NULL(ws_col);
ws_xpixel= env->GetFieldID(winsize_j, "ws_xpixel", "S");
CHECK_NULL(ws_xpixel);
ws_ypixel= env->GetFieldID(winsize_j, "ws_ypixel", "S");
CHECK_NULL(ws_ypixel);
}
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_tcgetattr
(JNIEnv *env, jobject, jint fd, jobject result) {
termios data;
if (tcgetattr(fd, &data) != 0) {
throw_errno(env);
return ;
}
env->SetIntField(result, c_iflag, data.c_iflag);
env->SetIntField(result, c_oflag, data.c_oflag);
env->SetIntField(result, c_cflag, data.c_cflag);
env->SetIntField(result, c_lflag, data.c_lflag);
env->SetIntField(result, c_line, data.c_line);
jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(result, c_cc);
env->SetByteArrayRegion(c_ccValue, 0, NCCS, (signed char *) data.c_cc);//TODO: cast?
env->SetIntField(result, c_ispeed, data.c_ispeed);
env->SetIntField(result, c_ospeed, data.c_ospeed);
}
/*
* Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl
* Method: tcsetattr
* Signature: (IILjdk/internal/org/jline/terminal/impl/jna/linux/CLibrary/termios;)V
*/
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_tcsetattr
(JNIEnv *env, jobject, jint fd, jint cmd, jobject input) {
termios data;
data.c_iflag = env->GetIntField(input, c_iflag);
data.c_oflag = env->GetIntField(input, c_oflag);
data.c_cflag = env->GetIntField(input, c_cflag);
data.c_lflag = env->GetIntField(input, c_lflag);
data.c_line = env->GetIntField(input, c_line);
jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(input, c_cc);
env->GetByteArrayRegion(c_ccValue, 0, NCCS, (jbyte *) data.c_cc);
data.c_ispeed = env->GetIntField(input, c_ispeed);
data.c_ospeed = env->GetIntField(input, c_ospeed);
if (tcsetattr(fd, cmd, &data) != 0) {
throw_errno(env);
}
}
/*
* Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl
* Method: ioctl0
* Signature: (IILjdk/internal/org/jline/terminal/impl/jna/linux/CLibrary/winsize;)V
*/
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_ioctl0
(JNIEnv *env, jobject, jint fd, jint cmd, jobject data) {
winsize ws;
ws.ws_row = env->GetIntField(data, ws_row);
ws.ws_col = env->GetIntField(data, ws_col);
ws.ws_xpixel = env->GetIntField(data, ws_xpixel);
ws.ws_ypixel = env->GetIntField(data, ws_ypixel);
if (ioctl(fd, cmd, &ws) != 0) {
throw_errno(env);
return ;
}
env->SetIntField(data, ws_row, ws.ws_row);
env->SetIntField(data, ws_col, ws.ws_col);
env->SetIntField(data, ws_xpixel, ws.ws_xpixel);
env->SetIntField(data, ws_ypixel, ws.ws_ypixel);
}
/*
* Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl
* Method: isatty
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_isatty
(JNIEnv *, jobject, jint fd) {
return isatty(fd);
}
/*
* Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl
* Method: ttyname_r
* Signature: (I[BI)V
*/
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_ttyname_1r
(JNIEnv *env, jobject, jint fd, jbyteArray buf, jint len) {
char *data = new char[len];
int error = ttyname_r(fd, data, len);
if (error != 0) {
throw_errno(env);
return ;
}
env->SetByteArrayRegion(buf, 0, len, (jbyte *) data);
delete[] data;
}
/*
* Throws LastErrorException based on the errno:
*/
static void throw_errno(JNIEnv *env) {
jobject exc = env->NewObject(lastErrorExceptionClass,
lastErrorExceptionConstructor,
errno);
env->Throw((jthrowable) exc);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.org.jline.terminal.impl.jna;
import java.io.IOException;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.impl.jna.osx.OsXNativePty;
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
class JDKNativePty {
static JnaNativePty current(TerminalProvider.Stream console) throws IOException {
return OsXNativePty.current(console);
}
static JnaNativePty open(Attributes attr, Size size) throws IOException {
return OsXNativePty.open(attr, size);
}
static int isatty(int fd) {
return OsXNativePty.isatty(fd);
}
static String ttyname(int fd) {
return OsXNativePty.ttyname(fd);
}
}

View File

@ -0,0 +1,394 @@
/*
* Copyright (c) 2002-2020, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna.osx;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
//import com.sun.jna.LastErrorException;
//import com.sun.jna.NativeLong;
//import com.sun.jna.Structure;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.Attributes.ControlChar;
import jdk.internal.org.jline.terminal.Attributes.ControlFlag;
import jdk.internal.org.jline.terminal.Attributes.InputFlag;
import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
public interface CLibrary {//extends com.sun.jna.Library {
void tcgetattr(int fd, termios termios) throws LastErrorException;
void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException;
void ioctl(int fd, NativeLong cmd, winsize data) throws LastErrorException;
int isatty(int fd);
void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException;
void openpty(int[] master, int[] slave, byte[] name, termios t, winsize s) throws LastErrorException;
class winsize { //extends Structure {
public short ws_row;
public short ws_col;
public short ws_xpixel;
public short ws_ypixel;
public winsize() {
}
public winsize(Size ws) {
ws_row = (short) ws.getRows();
ws_col = (short) ws.getColumns();
}
public Size toSize() {
return new Size(ws_col, ws_row);
}
// @Override
// protected List<String> getFieldOrder() {
// return Arrays.asList(//
// "ws_row",//
// "ws_col",//
// "ws_xpixel",//
// "ws_ypixel"//
// );
// }
}
class termios { //extends Structure {
public NativeLong c_iflag;
public NativeLong c_oflag;
public NativeLong c_cflag;
public NativeLong c_lflag;
public byte[] c_cc = new byte[20];
public NativeLong c_ispeed;
public NativeLong c_ospeed;
// @Override
// protected List<String> getFieldOrder() {
// return Arrays.asList(//
// "c_iflag",//
// "c_oflag",//
// "c_cflag",//
// "c_lflag",//
// "c_cc",//
// "c_ispeed",//
// "c_ospeed"//
// );
// }
{
c_iflag = new NativeLong(0);
c_oflag = new NativeLong(0);
c_cflag = new NativeLong(0);
c_lflag = new NativeLong(0);
c_ispeed = new NativeLong(0);
c_ospeed = new NativeLong(0);
}
public termios() {
}
public termios(Attributes t) {
// Input flags
setFlag(t.getInputFlag(InputFlag.IGNBRK), IGNBRK, c_iflag);
setFlag(t.getInputFlag(InputFlag.BRKINT), BRKINT, c_iflag);
setFlag(t.getInputFlag(InputFlag.IGNPAR), IGNPAR, c_iflag);
setFlag(t.getInputFlag(InputFlag.PARMRK), PARMRK, c_iflag);
setFlag(t.getInputFlag(InputFlag.INPCK), INPCK, c_iflag);
setFlag(t.getInputFlag(InputFlag.ISTRIP), ISTRIP, c_iflag);
setFlag(t.getInputFlag(InputFlag.INLCR), INLCR, c_iflag);
setFlag(t.getInputFlag(InputFlag.IGNCR), IGNCR, c_iflag);
setFlag(t.getInputFlag(InputFlag.ICRNL), ICRNL, c_iflag);
setFlag(t.getInputFlag(InputFlag.IXON), IXON, c_iflag);
setFlag(t.getInputFlag(InputFlag.IXOFF), IXOFF, c_iflag);
setFlag(t.getInputFlag(InputFlag.IXANY), IXANY, c_iflag);
setFlag(t.getInputFlag(InputFlag.IMAXBEL), IMAXBEL, c_iflag);
setFlag(t.getInputFlag(InputFlag.IUTF8), IUTF8, c_iflag);
// Output flags
setFlag(t.getOutputFlag(OutputFlag.OPOST), OPOST, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.ONLCR), ONLCR, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.OXTABS), OXTABS, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.ONOEOT), ONOEOT, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.OCRNL), OCRNL, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.ONOCR), ONOCR, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.ONLRET), ONLRET, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.OFILL), OFILL, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.NLDLY), NLDLY, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.TABDLY), TABDLY, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.CRDLY), CRDLY, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.FFDLY), FFDLY, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.BSDLY), BSDLY, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.VTDLY), VTDLY, c_oflag);
setFlag(t.getOutputFlag(OutputFlag.OFDEL), OFDEL, c_oflag);
// Control flags
setFlag(t.getControlFlag(ControlFlag.CIGNORE), CIGNORE, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CS5), CS5, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CS6), CS6, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CS7), CS7, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CS8), CS8, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CSTOPB), CSTOPB, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CREAD), CREAD, c_cflag);
setFlag(t.getControlFlag(ControlFlag.PARENB), PARENB, c_cflag);
setFlag(t.getControlFlag(ControlFlag.PARODD), PARODD, c_cflag);
setFlag(t.getControlFlag(ControlFlag.HUPCL), HUPCL, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CLOCAL), CLOCAL, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CCTS_OFLOW), CCTS_OFLOW, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CRTS_IFLOW), CRTS_IFLOW, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CDTR_IFLOW), CDTR_IFLOW, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CDSR_OFLOW), CDSR_OFLOW, c_cflag);
setFlag(t.getControlFlag(ControlFlag.CCAR_OFLOW), CCAR_OFLOW, c_cflag);
// Local flags
setFlag(t.getLocalFlag(LocalFlag.ECHOKE), ECHOKE, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ECHOE), ECHOE, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ECHOK), ECHOK, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ECHO), ECHO, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ECHONL), ECHONL, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ECHOPRT), ECHOPRT, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ECHOCTL), ECHOCTL, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ISIG), ISIG, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ICANON), ICANON, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.ALTWERASE), ALTWERASE, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.IEXTEN), IEXTEN, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.EXTPROC), EXTPROC, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.TOSTOP), TOSTOP, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.FLUSHO), FLUSHO, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.NOKERNINFO), NOKERNINFO, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.PENDIN), PENDIN, c_lflag);
setFlag(t.getLocalFlag(LocalFlag.NOFLSH), NOFLSH, c_lflag);
// Control chars
c_cc[VEOF] = (byte) t.getControlChar(ControlChar.VEOF);
c_cc[VEOL] = (byte) t.getControlChar(ControlChar.VEOL);
c_cc[VEOL2] = (byte) t.getControlChar(ControlChar.VEOL2);
c_cc[VERASE] = (byte) t.getControlChar(ControlChar.VERASE);
c_cc[VWERASE] = (byte) t.getControlChar(ControlChar.VWERASE);
c_cc[VKILL] = (byte) t.getControlChar(ControlChar.VKILL);
c_cc[VREPRINT] = (byte) t.getControlChar(ControlChar.VREPRINT);
c_cc[VINTR] = (byte) t.getControlChar(ControlChar.VINTR);
c_cc[VQUIT] = (byte) t.getControlChar(ControlChar.VQUIT);
c_cc[VSUSP] = (byte) t.getControlChar(ControlChar.VSUSP);
c_cc[VDSUSP] = (byte) t.getControlChar(ControlChar.VDSUSP);
c_cc[VSTART] = (byte) t.getControlChar(ControlChar.VSTART);
c_cc[VSTOP] = (byte) t.getControlChar(ControlChar.VSTOP);
c_cc[VLNEXT] = (byte) t.getControlChar(ControlChar.VLNEXT);
c_cc[VDISCARD] = (byte) t.getControlChar(ControlChar.VDISCARD);
c_cc[VMIN] = (byte) t.getControlChar(ControlChar.VMIN);
c_cc[VTIME] = (byte) t.getControlChar(ControlChar.VTIME);
c_cc[VSTATUS] = (byte) t.getControlChar(ControlChar.VSTATUS);
}
private void setFlag(boolean flag, long value, NativeLong org) {
org.setValue(flag ? org.longValue() | value : org.longValue());
}
public Attributes toAttributes() {
Attributes attr = new Attributes();
// Input flags
EnumSet<InputFlag> iflag = attr.getInputFlags();
addFlag(c_iflag.longValue(), iflag, InputFlag.IGNBRK, IGNBRK);
addFlag(c_iflag.longValue(), iflag, InputFlag.IGNBRK, IGNBRK);
addFlag(c_iflag.longValue(), iflag, InputFlag.BRKINT, BRKINT);
addFlag(c_iflag.longValue(), iflag, InputFlag.IGNPAR, IGNPAR);
addFlag(c_iflag.longValue(), iflag, InputFlag.PARMRK, PARMRK);
addFlag(c_iflag.longValue(), iflag, InputFlag.INPCK, INPCK);
addFlag(c_iflag.longValue(), iflag, InputFlag.ISTRIP, ISTRIP);
addFlag(c_iflag.longValue(), iflag, InputFlag.INLCR, INLCR);
addFlag(c_iflag.longValue(), iflag, InputFlag.IGNCR, IGNCR);
addFlag(c_iflag.longValue(), iflag, InputFlag.ICRNL, ICRNL);
addFlag(c_iflag.longValue(), iflag, InputFlag.IXON, IXON);
addFlag(c_iflag.longValue(), iflag, InputFlag.IXOFF, IXOFF);
addFlag(c_iflag.longValue(), iflag, InputFlag.IXANY, IXANY);
addFlag(c_iflag.longValue(), iflag, InputFlag.IMAXBEL, IMAXBEL);
addFlag(c_iflag.longValue(), iflag, InputFlag.IUTF8, IUTF8);
// Output flags
EnumSet<OutputFlag> oflag = attr.getOutputFlags();
addFlag(c_oflag.longValue(), oflag, OutputFlag.OPOST, OPOST);
addFlag(c_oflag.longValue(), oflag, OutputFlag.ONLCR, ONLCR);
addFlag(c_oflag.longValue(), oflag, OutputFlag.OXTABS, OXTABS);
addFlag(c_oflag.longValue(), oflag, OutputFlag.ONOEOT, ONOEOT);
addFlag(c_oflag.longValue(), oflag, OutputFlag.OCRNL, OCRNL);
addFlag(c_oflag.longValue(), oflag, OutputFlag.ONOCR, ONOCR);
addFlag(c_oflag.longValue(), oflag, OutputFlag.ONLRET, ONLRET);
addFlag(c_oflag.longValue(), oflag, OutputFlag.OFILL, OFILL);
addFlag(c_oflag.longValue(), oflag, OutputFlag.NLDLY, NLDLY);
addFlag(c_oflag.longValue(), oflag, OutputFlag.TABDLY, TABDLY);
addFlag(c_oflag.longValue(), oflag, OutputFlag.CRDLY, CRDLY);
addFlag(c_oflag.longValue(), oflag, OutputFlag.FFDLY, FFDLY);
addFlag(c_oflag.longValue(), oflag, OutputFlag.BSDLY, BSDLY);
addFlag(c_oflag.longValue(), oflag, OutputFlag.VTDLY, VTDLY);
addFlag(c_oflag.longValue(), oflag, OutputFlag.OFDEL, OFDEL);
// Control flags
EnumSet<ControlFlag> cflag = attr.getControlFlags();
addFlag(c_cflag.longValue(), cflag, ControlFlag.CIGNORE, CIGNORE);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CS5, CS5);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CS6, CS6);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CS7, CS7);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CS8, CS8);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CSTOPB, CSTOPB);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CREAD, CREAD);
addFlag(c_cflag.longValue(), cflag, ControlFlag.PARENB, PARENB);
addFlag(c_cflag.longValue(), cflag, ControlFlag.PARODD, PARODD);
addFlag(c_cflag.longValue(), cflag, ControlFlag.HUPCL, HUPCL);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CLOCAL, CLOCAL);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CCTS_OFLOW, CCTS_OFLOW);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CRTS_IFLOW, CRTS_IFLOW);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CDSR_OFLOW, CDSR_OFLOW);
addFlag(c_cflag.longValue(), cflag, ControlFlag.CCAR_OFLOW, CCAR_OFLOW);
// Local flags
EnumSet<LocalFlag> lflag = attr.getLocalFlags();
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOKE, ECHOKE);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOE, ECHOE);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOK, ECHOK);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHO, ECHO);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHONL, ECHONL);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOPRT, ECHOPRT);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOCTL, ECHOCTL);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ISIG, ISIG);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ICANON, ICANON);
addFlag(c_lflag.longValue(), lflag, LocalFlag.ALTWERASE, ALTWERASE);
addFlag(c_lflag.longValue(), lflag, LocalFlag.IEXTEN, IEXTEN);
addFlag(c_lflag.longValue(), lflag, LocalFlag.EXTPROC, EXTPROC);
addFlag(c_lflag.longValue(), lflag, LocalFlag.TOSTOP, TOSTOP);
addFlag(c_lflag.longValue(), lflag, LocalFlag.FLUSHO, FLUSHO);
addFlag(c_lflag.longValue(), lflag, LocalFlag.NOKERNINFO, NOKERNINFO);
addFlag(c_lflag.longValue(), lflag, LocalFlag.PENDIN, PENDIN);
addFlag(c_lflag.longValue(), lflag, LocalFlag.NOFLSH, NOFLSH);
// Control chars
EnumMap<ControlChar, Integer> cc = attr.getControlChars();
cc.put(ControlChar.VEOF, (int) c_cc[VEOF]);
cc.put(ControlChar.VEOL, (int) c_cc[VEOL]);
cc.put(ControlChar.VEOL2, (int) c_cc[VEOL2]);
cc.put(ControlChar.VERASE, (int) c_cc[VERASE]);
cc.put(ControlChar.VWERASE, (int) c_cc[VWERASE]);
cc.put(ControlChar.VKILL, (int) c_cc[VKILL]);
cc.put(ControlChar.VREPRINT, (int) c_cc[VREPRINT]);
cc.put(ControlChar.VINTR, (int) c_cc[VINTR]);
cc.put(ControlChar.VQUIT, (int) c_cc[VQUIT]);
cc.put(ControlChar.VSUSP, (int) c_cc[VSUSP]);
cc.put(ControlChar.VDSUSP, (int) c_cc[VDSUSP]);
cc.put(ControlChar.VSTART, (int) c_cc[VSTART]);
cc.put(ControlChar.VSTOP, (int) c_cc[VSTOP]);
cc.put(ControlChar.VLNEXT, (int) c_cc[VLNEXT]);
cc.put(ControlChar.VDISCARD, (int) c_cc[VDISCARD]);
cc.put(ControlChar.VMIN, (int) c_cc[VMIN]);
cc.put(ControlChar.VTIME, (int) c_cc[VTIME]);
cc.put(ControlChar.VSTATUS, (int) c_cc[VSTATUS]);
// Return
return attr;
}
private <T extends Enum<T>> void addFlag(long value, EnumSet<T> flags, T flag, int v) {
if ((value & v) != 0) {
flags.add(flag);
}
}
}
// CONSTANTS
long TIOCGWINSZ = 0x40087468L;
long TIOCSWINSZ = 0x80087467L;
int TCSANOW = 0x00000000;
int VEOF = 0;
int VEOL = 1;
int VEOL2 = 2;
int VERASE = 3;
int VWERASE = 4;
int VKILL = 5;
int VREPRINT = 6;
int VINTR = 8;
int VQUIT = 9;
int VSUSP = 10;
int VDSUSP = 11;
int VSTART = 12;
int VSTOP = 13;
int VLNEXT = 14;
int VDISCARD = 15;
int VMIN = 16;
int VTIME = 17;
int VSTATUS = 18;
int IGNBRK = 0x00000001;
int BRKINT = 0x00000002;
int IGNPAR = 0x00000004;
int PARMRK = 0x00000008;
int INPCK = 0x00000010;
int ISTRIP = 0x00000020;
int INLCR = 0x00000040;
int IGNCR = 0x00000080;
int ICRNL = 0x00000100;
int IXON = 0x00000200;
int IXOFF = 0x00000400;
int IXANY = 0x00000800;
int IMAXBEL = 0x00002000;
int IUTF8 = 0x00004000;
int OPOST = 0x00000001;
int ONLCR = 0x00000002;
int OXTABS = 0x00000004;
int ONOEOT = 0x00000008;
int OCRNL = 0x00000010;
int ONOCR = 0x00000020;
int ONLRET = 0x00000040;
int OFILL = 0x00000080;
int NLDLY = 0x00000300;
int TABDLY = 0x00000c04;
int CRDLY = 0x00003000;
int FFDLY = 0x00004000;
int BSDLY = 0x00008000;
int VTDLY = 0x00010000;
int OFDEL = 0x00020000;
int CIGNORE = 0x00000001;
int CS5 = 0x00000000;
int CS6 = 0x00000100;
int CS7 = 0x00000200;
int CS8 = 0x00000300;
int CSTOPB = 0x00000400;
int CREAD = 0x00000800;
int PARENB = 0x00001000;
int PARODD = 0x00002000;
int HUPCL = 0x00004000;
int CLOCAL = 0x00008000;
int CCTS_OFLOW = 0x00010000;
int CRTS_IFLOW = 0x00020000;
int CDTR_IFLOW = 0x00040000;
int CDSR_OFLOW = 0x00080000;
int CCAR_OFLOW = 0x00100000;
int ECHOKE = 0x00000001;
int ECHOE = 0x00000002;
int ECHOK = 0x00000004;
int ECHO = 0x00000008;
int ECHONL = 0x00000010;
int ECHOPRT = 0x00000020;
int ECHOCTL = 0x00000040;
int ISIG = 0x00000080;
int ICANON = 0x00000100;
int ALTWERASE = 0x00000200;
int IEXTEN = 0x00000400;
int EXTPROC = 0x00000800;
int TOSTOP = 0x00400000;
int FLUSHO = 0x00800000;
int NOKERNINFO = 0x02000000;
int PENDIN = 0x20000000;
int NOFLSH = 0x80000000;
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.org.jline.terminal.impl.jna.osx;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
public final class CLibraryImpl implements CLibrary {
static {
System.loadLibrary("le");
initIDs();
}
private static native void initIDs();
@Override
public native void tcgetattr(int fd, termios termios) throws LastErrorException;
@Override
public native void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException;
@Override
public void ioctl(int fd, NativeLong cmd, winsize data) throws LastErrorException {
if (cmd.longValue() == CLibrary.TIOCGWINSZ || cmd.longValue() == CLibrary.TIOCSWINSZ) {
ioctl0(fd, cmd.longValue(), data);
} else {
throw new UnsupportedOperationException("Command: " + cmd + ", not supported.");
}
}
private native void ioctl0(int fd, long cmd, winsize data) throws LastErrorException;
@Override
public native int isatty(int fd);
@Override
public native void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException;
@Override
public void openpty(int[] master, int[] slave, byte[] name, termios t, winsize s) throws LastErrorException {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.org.jline.terminal.impl.jna.osx;
class NativeLong {
public long value;
public NativeLong(long value) {
this.value = value;
}
public void setValue(long value) {
this.value = value;
}
public long longValue() {
return value;
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2002-2020, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna.osx;
import java.io.FileDescriptor;
import java.io.IOException;
//import com.sun.jna.Native;
//import com.sun.jna.NativeLong;
//import com.sun.jna.Platform;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.impl.jna.JnaNativePty;
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TCSANOW;
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TIOCGWINSZ;
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TIOCSWINSZ;
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.termios;
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.winsize;
public class OsXNativePty extends JnaNativePty {
// private static final CLibrary C_LIBRARY = Native.load(Platform.C_LIBRARY_NAME, CLibrary.class);
private static final CLibrary C_LIBRARY = new CLibraryImpl();//Native.load(Platform.C_LIBRARY_NAME, CLibrary.class);
public static OsXNativePty current(TerminalProvider.Stream consoleStream) throws IOException {
switch (consoleStream) {
case Output:
return new OsXNativePty(-1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(0));
case Error:
return new OsXNativePty(-1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(0));
default:
throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream);
}
}
public static OsXNativePty open(Attributes attr, Size size) throws IOException {
int[] master = new int[1];
int[] slave = new int[1];
byte[] buf = new byte[64];
C_LIBRARY.openpty(master, slave, buf,
attr != null ? new termios(attr) : null,
size != null ? new winsize(size) : null);
int len = 0;
while (buf[len] != 0) {
len++;
}
String name = new String(buf, 0, len);
return new OsXNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name);
}
public OsXNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
super(master, masterFD, slave, slaveFD, name);
}
public OsXNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, int slaveOut, FileDescriptor slaveOutFD, String name) {
super(master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name);
}
@Override
public Attributes getAttr() throws IOException {
termios termios = new termios();
C_LIBRARY.tcgetattr(getSlave(), termios);
return termios.toAttributes();
}
@Override
protected void doSetAttr(Attributes attr) throws IOException {
termios termios = new termios(attr);
C_LIBRARY.tcsetattr(getSlave(), TCSANOW, termios);
}
@Override
public Size getSize() throws IOException {
winsize sz = new winsize();
C_LIBRARY.ioctl(getSlave(), new NativeLong(TIOCGWINSZ), sz);
return sz.toSize();
}
@Override
public void setSize(Size size) throws IOException {
winsize sz = new winsize(size);
C_LIBRARY.ioctl(getSlave(), new NativeLong(TIOCSWINSZ), sz);
}
public static int isatty(int fd) {
return C_LIBRARY.isatty(fd);
}
public static String ttyname(int fd) {
byte[] buf = new byte[64];
C_LIBRARY.ttyname_r(fd, buf, buf.length);
int len = 0;
while (buf[len] != 0) {
len++;
}
return new String(buf, 0, len);
}
}

View File

@ -0,0 +1,210 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl.h"
#include <errno.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
static jclass lastErrorExceptionClass;
static jmethodID lastErrorExceptionConstructor;
static jclass termios_j;
static jfieldID c_iflag;
static jfieldID c_oflag;
static jfieldID c_cflag;
static jfieldID c_lflag;
static jfieldID c_cc;
static jfieldID c_ispeed;
static jfieldID c_ospeed;
static jclass winsize_j;
static jfieldID ws_row;
static jfieldID ws_col;
static jfieldID ws_xpixel;
static jfieldID ws_ypixel;
static jclass nativelong_j;
static jfieldID nativelong_value;
static void throw_errno(JNIEnv *env);
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_initIDs
(JNIEnv *env, jclass) {
jclass cls;
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/LastErrorException");
CHECK_NULL(cls);
lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls);
lastErrorExceptionConstructor = env->GetMethodID(lastErrorExceptionClass, "<init>", "(J)V");
CHECK_NULL(lastErrorExceptionConstructor);
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary$termios");
CHECK_NULL(cls);
termios_j = (jclass) env->NewGlobalRef(cls);
CHECK_NULL(termios_j);
c_iflag = env->GetFieldID(termios_j, "c_iflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
CHECK_NULL(c_iflag);
c_oflag = env->GetFieldID(termios_j, "c_oflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
CHECK_NULL(c_oflag);
c_cflag = env->GetFieldID(termios_j, "c_cflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
CHECK_NULL(c_cflag);
c_lflag = env->GetFieldID(termios_j, "c_lflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
CHECK_NULL(c_lflag);
c_cc = env->GetFieldID(termios_j, "c_cc", "[B");
CHECK_NULL(c_cc);
c_ispeed = env->GetFieldID(termios_j, "c_ispeed", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
CHECK_NULL(c_ispeed);
c_ospeed = env->GetFieldID(termios_j, "c_ospeed", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
CHECK_NULL(c_ospeed);
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary$winsize");
CHECK_NULL(cls);
winsize_j = (jclass) env->NewGlobalRef(cls);
ws_row = env->GetFieldID(winsize_j, "ws_row", "S");
CHECK_NULL(ws_row);
ws_col = env->GetFieldID(winsize_j, "ws_col", "S");
CHECK_NULL(ws_col);
ws_xpixel= env->GetFieldID(winsize_j, "ws_xpixel", "S");
CHECK_NULL(ws_xpixel);
ws_ypixel= env->GetFieldID(winsize_j, "ws_ypixel", "S");
CHECK_NULL(ws_ypixel);
nativelong_j = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/NativeLong");
CHECK_NULL(nativelong_j);
nativelong_value = env->GetFieldID(nativelong_j, "value", "J");
CHECK_NULL(nativelong_value);
}
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_tcgetattr
(JNIEnv *env, jobject, jint fd, jobject result) {
termios data;
if (tcgetattr(fd, &data) != 0) {
throw_errno(env);
return ;
}
env->SetLongField(env->GetObjectField(result, c_iflag), nativelong_value, data.c_iflag);
env->SetLongField(env->GetObjectField(result, c_oflag), nativelong_value, data.c_oflag);
env->SetLongField(env->GetObjectField(result, c_cflag), nativelong_value, data.c_cflag);
env->SetLongField(env->GetObjectField(result, c_lflag), nativelong_value, data.c_lflag);
jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(result, c_cc);
env->SetByteArrayRegion(c_ccValue, 0, NCCS, (signed char *) data.c_cc);
env->SetLongField(env->GetObjectField(result, c_ispeed), nativelong_value, data.c_ispeed);
env->SetLongField(env->GetObjectField(result, c_ospeed), nativelong_value, data.c_ospeed);
}
/*
* Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl
* Method: tcsetattr
* Signature: (IILjdk/internal/org/jline/terminal/impl/jna/osx/CLibrary/termios;)V
*/
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_tcsetattr
(JNIEnv *env, jobject, jint fd, jint cmd, jobject input) {
termios data;
data.c_iflag = env->GetLongField(env->GetObjectField(input, c_iflag), nativelong_value);
data.c_oflag = env->GetLongField(env->GetObjectField(input, c_oflag), nativelong_value);
data.c_cflag = env->GetLongField(env->GetObjectField(input, c_cflag), nativelong_value);
data.c_lflag = env->GetLongField(env->GetObjectField(input, c_lflag), nativelong_value);
jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(input, c_cc);
env->GetByteArrayRegion(c_ccValue, 0, NCCS, (jbyte *) data.c_cc);
data.c_ispeed = env->GetLongField(env->GetObjectField(input, c_ispeed), nativelong_value);
data.c_ospeed = env->GetLongField(env->GetObjectField(input, c_ospeed), nativelong_value);
if (tcsetattr(fd, cmd, &data) != 0) {
throw_errno(env);
}
}
/*
* Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl
* Method: ioctl0
* Signature: (IILjdk/internal/org/jline/terminal/impl/jna/osx/CLibrary/winsize;)V
*/
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_ioctl0
(JNIEnv *env, jobject, jint fd, jlong cmd, jobject data) {
winsize ws;
ws.ws_row = env->GetIntField(data, ws_row);
ws.ws_col = env->GetIntField(data, ws_col);
ws.ws_xpixel = env->GetIntField(data, ws_xpixel);
ws.ws_ypixel = env->GetIntField(data, ws_ypixel);
if (ioctl(fd, cmd, &ws) != 0) {
throw_errno(env);
return ;
}
env->SetIntField(data, ws_row, ws.ws_row);
env->SetIntField(data, ws_col, ws.ws_col);
env->SetIntField(data, ws_xpixel, ws.ws_xpixel);
env->SetIntField(data, ws_ypixel, ws.ws_ypixel);
}
/*
* Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl
* Method: isatty
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_isatty
(JNIEnv *, jobject, jint fd) {
return isatty(fd);
}
/*
* Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl
* Method: ttyname_r
* Signature: (I[BI)V
*/
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_ttyname_1r
(JNIEnv *env, jobject, jint fd, jbyteArray buf, jint len) {
char *data = new char[len];
int error = ttyname_r(fd, data, len);
if (error != 0) {
throw_errno(env);
return ;
}
env->SetByteArrayRegion(buf, 0, len, (jbyte *) data);
delete[] data;
}
/*
* Throws LastErrorException based on the errno:
*/
static void throw_errno(JNIEnv *env) {
jobject exc = env->NewObject(lastErrorExceptionClass,
lastErrorExceptionConstructor,
errno);
env->Throw((jthrowable) exc);
}

View File

@ -49,7 +49,17 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
*/
@Override
public JdkConsole console(boolean isTTY, Charset charset) {
return new JdkConsoleImpl(charset);
try {
Terminal terminal = TerminalBuilder.builder().encoding(charset)
.exec(false).build();
return new JdkConsoleImpl(terminal);
} catch (IllegalStateException ise) {
//cannot create a non-dumb, non-exec terminal,
//use the standard Console:
return null;
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
/**
@ -119,13 +129,9 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
private final LineReader jline;
private final Terminal terminal;
public JdkConsoleImpl(Charset charset) {
try {
terminal = TerminalBuilder.builder().encoding(charset).build();
jline = LineReaderBuilder.builder().terminal(terminal).build();
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
public JdkConsoleImpl(Terminal terminal) {
this.terminal = terminal;
this.jline = LineReaderBuilder.builder().terminal(terminal).build();
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -22,10 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.org.jline.terminal.impl.jna.win;
package jdk.internal.org.jline.terminal.impl.jna;
@SuppressWarnings("serial")
class LastErrorException extends RuntimeException{
public class LastErrorException extends RuntimeException{
public final long lastError;

View File

@ -0,0 +1,204 @@
/*
* Copyright (c) 2002-2020, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
//import com.sun.jna.Platform;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.impl.AbstractPty;
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
import jdk.internal.org.jline.terminal.spi.Pty;
//import jdk.internal.org.jline.terminal.impl.jna.freebsd.FreeBsdNativePty;
//import jdk.internal.org.jline.terminal.impl.jna.linux.LinuxNativePty;
//import jdk.internal.org.jline.terminal.impl.jna.osx.OsXNativePty;
//import jdk.internal.org.jline.terminal.impl.jna.solaris.SolarisNativePty;
public abstract class JnaNativePty extends AbstractPty implements Pty {
private final int master;
private final int slave;
private final int slaveOut;
private final String name;
private final FileDescriptor masterFD;
private final FileDescriptor slaveFD;
private final FileDescriptor slaveOutFD;
public static JnaNativePty current(TerminalProvider.Stream console) throws IOException {
// if (Platform.isMac()) {
// if (Platform.is64Bit() && Platform.isARM()) {
// throw new UnsupportedOperationException();
// }
// return OsXNativePty.current(console);
// } else if (Platform.isLinux()) {
// return LinuxNativePty.current(console);
// } else if (Platform.isSolaris()) {
// return SolarisNativePty.current(console);
// } else if (Platform.isFreeBSD()) {
// return FreeBsdNativePty.current(console);
// } else {
// throw new UnsupportedOperationException();
// }
return JDKNativePty.current(console);
}
public static JnaNativePty open(Attributes attr, Size size) throws IOException {
// if (Platform.isMac()) {
// return OsXNativePty.open(attr, size);
// } else if (Platform.isLinux()) {
// return LinuxNativePty.open(attr, size);
// } else if (Platform.isSolaris()) {
// return SolarisNativePty.open(attr, size);
// } else if (Platform.isFreeBSD()) {
// return FreeBsdNativePty.open(attr, size);
// } else {
// throw new UnsupportedOperationException();
// }
return JDKNativePty.open(attr, size);
}
protected JnaNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
this(master, masterFD, slave, slaveFD, slave, slaveFD, name);
}
protected JnaNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, int slaveOut, FileDescriptor slaveOutFD, String name) {
this.master = master;
this.slave = slave;
this.slaveOut = slaveOut;
this.name = name;
this.masterFD = masterFD;
this.slaveFD = slaveFD;
this.slaveOutFD = slaveOutFD;
}
@Override
public void close() throws IOException {
if (master > 0) {
getMasterInput().close();
}
if (slave > 0) {
getSlaveInput().close();
}
}
public int getMaster() {
return master;
}
public int getSlave() {
return slave;
}
public int getSlaveOut() {
return slaveOut;
}
public String getName() {
return name;
}
public FileDescriptor getMasterFD() {
return masterFD;
}
public FileDescriptor getSlaveFD() {
return slaveFD;
}
public FileDescriptor getSlaveOutFD() {
return slaveOutFD;
}
public InputStream getMasterInput() {
return new FileInputStream(getMasterFD());
}
public OutputStream getMasterOutput() {
return new FileOutputStream(getMasterFD());
}
protected InputStream doGetSlaveInput() {
return new FileInputStream(getSlaveFD());
}
public OutputStream getSlaveOutput() {
return new FileOutputStream(getSlaveOutFD());
}
protected static FileDescriptor newDescriptor(int fd) {
try {
Constructor<FileDescriptor> cns = FileDescriptor.class.getDeclaredConstructor(int.class);
cns.setAccessible(true);
return cns.newInstance(fd);
} catch (Throwable e) {
throw new RuntimeException("Unable to create FileDescriptor", e);
}
}
@Override
public String toString() {
return "JnaNativePty[" + getName() + "]";
}
public static boolean isPosixSystemStream(TerminalProvider.Stream stream) {
switch (stream) {
case Input: return isatty(0);
case Output: return isatty(1);
case Error: return isatty(2);
default: return false;
}
}
public static String posixSystemStreamName(TerminalProvider.Stream stream) {
switch (stream) {
case Input: return ttyname(0);
case Output: return ttyname(1);
case Error: return ttyname(2);
default: return null;
}
}
private static boolean isatty(int fd) {
// if (Platform.isMac()) {
// return OsXNativePty.isatty(fd) == 1;
// } else if (Platform.isLinux()) {
// return LinuxNativePty.isatty(fd) == 1;
// } else if (Platform.isSolaris()) {
// return SolarisNativePty.isatty(fd) == 1;
// } else if (Platform.isFreeBSD()) {
// return FreeBsdNativePty.isatty(fd) == 1;
// } else {
// return false;
// }
return JDKNativePty.isatty(fd) == 1;
}
private static String ttyname(int fd) {
// if (Platform.isMac()) {
// return OsXNativePty.ttyname(fd);
// } else if (Platform.isLinux()) {
// return LinuxNativePty.ttyname(fd);
// } else if (Platform.isSolaris()) {
// return SolarisNativePty.ttyname(fd);
// } else if (Platform.isFreeBSD()) {
// return FreeBsdNativePty.ttyname(fd);
// } else {
// return null;
// }
return JDKNativePty.ttyname(fd);
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2002-2020, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.Terminal;
import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
//import jdk.internal.org.jline.terminal.impl.jna.win.JnaWinSysTerminal;
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
import jdk.internal.org.jline.terminal.spi.Pty;
import jdk.internal.org.jline.utils.OSUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.function.Function;
public class JnaTerminalProvider implements TerminalProvider
{
@Override
public String name() {
return "jna";
}
public Pty current(TerminalProvider.Stream console) throws IOException {
return JnaNativePty.current(console);
}
public Pty open(Attributes attributes, Size size) throws IOException {
return JnaNativePty.open(attributes, size);
}
@Override
public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
Stream consoleStream, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
// if (OSUtils.IS_WINDOWS) {
// return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream );
// } else {
return posixSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper );
// }
}
// public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
// boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
// Stream console, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
// return JnaWinSysTerminal.createTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, console);
// }
//
public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
Stream consoleStream, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
// Pty pty = jdk.internal.org.jline.terminal.impl.ExecPty.current(consoleStream);
Pty pty = current(consoleStream);
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper);
}
@Override
public Terminal newTerminal(String name, String type, InputStream in, OutputStream out,
Charset encoding, Terminal.SignalHandler signalHandler, boolean paused,
Attributes attributes, Size size) throws IOException
{
Pty pty = open(attributes, size);
return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
}
@Override
public boolean isSystemStream(Stream stream) {
try {
// if (OSUtils.IS_WINDOWS) {
// return isWindowsSystemStream(stream);
// } else {
return isPosixSystemStream(stream);
// }
} catch (Throwable t) {
return false;
}
}
// public boolean isWindowsSystemStream(Stream stream) {
// return JnaWinSysTerminal.isWindowsSystemStream(stream);
// }
public boolean isPosixSystemStream(Stream stream) {
return JnaNativePty.isPosixSystemStream(stream);
}
@Override
public String systemStreamName(Stream stream) {
if (OSUtils.IS_WINDOWS) {
return null;
} else {
return JnaNativePty.posixSystemStreamName(stream);
}
}
}

View File

@ -12,6 +12,7 @@ package jdk.internal.org.jline.terminal.impl.jna.win;
//import com.sun.jna.Pointer;
//import com.sun.jna.ptr.IntByReference;
import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
import java.io.IOException;

View File

@ -22,6 +22,7 @@ import java.util.function.IntConsumer;
import jdk.internal.org.jline.terminal.Cursor;
import jdk.internal.org.jline.terminal.Size;
import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
import jdk.internal.org.jline.utils.InfoCmp;
import jdk.internal.org.jline.utils.OSUtils;

View File

@ -22,6 +22,7 @@ package jdk.internal.org.jline.terminal.impl.jna.win;
//import com.sun.jna.ptr.IntByReference;
//import com.sun.jna.win32.StdCallLibrary;
//import com.sun.jna.win32.W32APIOptions;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
interface Kernel32 {//extends StdCallLibrary {

View File

@ -24,6 +24,7 @@
*/
package jdk.internal.org.jline.terminal.impl.jna.win;
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CHAR_INFO;
import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_SCREEN_BUFFER_INFO;
import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.COORD;

View File

@ -141,7 +141,7 @@ JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel3
pointerValue = env->GetFieldID(cls, "value", "J");
CHECK_NULL(pointerValue);
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/LastErrorException");
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/LastErrorException");
CHECK_NULL(cls);
lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls);
lastErrorExceptionConstructor = env->GetMethodID(cls, "<init>", "(J)V");