blob: 9ed353f46d0b612e376b548bd9528831f2c4298f [file] [log] [blame]
/*
* Copyright (c) 2002-2019, 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;
import jdk.internal.org.jline.terminal.Attributes;
import jdk.internal.org.jline.terminal.spi.Pty;
import jdk.internal.org.jline.utils.NonBlockingInputStream;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_NON_BLOCKING_READS;
public abstract class AbstractPty implements Pty {
private Attributes current;
@Override
public void setAttr(Attributes attr) throws IOException {
current = new Attributes(attr);
doSetAttr(attr);
}
@Override
public InputStream getSlaveInput() throws IOException {
InputStream si = doGetSlaveInput();
if (Boolean.parseBoolean(System.getProperty(PROP_NON_BLOCKING_READS, "true"))) {
return new PtyInputStream(si);
} else {
return si;
}
}
protected abstract void doSetAttr(Attributes attr) throws IOException;
protected abstract InputStream doGetSlaveInput() throws IOException;
protected void checkInterrupted() throws InterruptedIOException {
if (Thread.interrupted()) {
throw new InterruptedIOException();
}
}
class PtyInputStream extends NonBlockingInputStream {
final InputStream in;
int c = 0;
PtyInputStream(InputStream in) {
this.in = in;
}
@Override
public int read(long timeout, boolean isPeek) throws IOException {
checkInterrupted();
if (c != 0) {
int r = c;
if (!isPeek) {
c = 0;
}
return r;
} else {
setNonBlocking();
long start = System.currentTimeMillis();
while (true) {
int r = in.read();
if (r >= 0) {
if (isPeek) {
c = r;
}
return r;
}
checkInterrupted();
long cur = System.currentTimeMillis();
if (timeout > 0 && cur - start > timeout) {
return NonBlockingInputStream.READ_EXPIRED;
}
}
}
}
@Override
public int readBuffered(byte[] b) throws IOException {
return in.read(b);
}
private void setNonBlocking() {
if (current == null
|| current.getControlChar(Attributes.ControlChar.VMIN) != 0
|| current.getControlChar(Attributes.ControlChar.VTIME) != 1) {
try {
Attributes attr = getAttr();
attr.setControlChar(Attributes.ControlChar.VMIN, 0);
attr.setControlChar(Attributes.ControlChar.VTIME, 1);
setAttr(attr);
} catch (IOException e) {
throw new IOError(e);
}
}
}
}
}