getFieldOrder() {
+ return Arrays.asList(
+ "c_iflag",
+ "c_oflag",
+ "c_cflag",
+ "c_lflag",
+ "c_line",
+ "c_cc",
+ "c_ispeed",
+ "c_ospeed"
+ );
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/input/posix/UnixTerminal.java b/Dorkbox-Util/src/dorkbox/util/input/posix/UnixTerminal.java
new file mode 100644
index 0000000..6d738b5
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/input/posix/UnixTerminal.java
@@ -0,0 +1,167 @@
+package dorkbox.util.input.posix;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import com.sun.jna.Native;
+
+import dorkbox.util.input.Terminal;
+
+/**
+ * Terminal that is used for unix platforms. Terminal initialization
+ * is handled via JNA and ioctl/tcgetattr/tcsetattr/cfmakeraw.
+ *
+ * This implementation should work for an reasonable POSIX system.
+ */
+public class UnixTerminal extends Terminal {
+
+ private volatile TermiosStruct termInfoDefault = new TermiosStruct();
+ private volatile TermiosStruct termInfo = new TermiosStruct();
+
+ private PosixTerminalControl term;
+ private ByteBuffer windowSizeBuffer = ByteBuffer.allocate(8);
+
+ public UnixTerminal() throws Exception {
+ this.term = (PosixTerminalControl) Native.loadLibrary("c", PosixTerminalControl.class);
+
+ // save off the defaults
+ if (this.term.tcgetattr(0, this.termInfoDefault) !=0) {
+ throw new IOException("Failed to get terminal info");
+ }
+ }
+
+ @Override
+ public void init() throws IOException {
+
+ // COMPARABLE TO (from upstream)
+ //settings.set("-icanon min 1 -ixon");
+ //settings.set("dsusp undef");
+
+ /*
+ * NOT done in constructor, since our unit test DOES NOT use this!
+ *
+ * Set the console to be character-buffered instead of line-buffered.
+ * Allow ctrl-s and ctrl-q keypress to be used (as forward search)
+ */
+
+// raw mode
+// t->c_iflag &= ~(IMAXBEL|IXOFF|INPCK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IGNPAR);
+// t->c_iflag |= IGNBRK;
+// t->c_oflag &= ~OPOST;
+// t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|NOFLSH|TOSTOP|PENDIN);
+// t->c_cflag &= ~(CSIZE|PARENB);
+// t->c_cflag |= CS8|CREAD;
+// t->c_cc[VMIN] = 1;
+// t->c_cc[VTIME] = 0;
+
+
+ if (this.term.tcgetattr(0, this.termInfo) !=0) {
+ throw new IOException("Failed to get terminal info");
+ }
+
+ this.termInfo.c_iflag &= ~PosixTerminalControl.IXON; // DISABLE - flow control mediated by ^S and ^Q
+// struct.c_iflag |= PosixTerminalControl.IUTF8; // DISABLE - flow control mediated by ^S and ^Q
+
+ this.termInfo.c_lflag &= ~PosixTerminalControl.ICANON; // DISABLE - canonical mode (pass chars straight through to terminal)
+// struct.c_lflag &= ~PosixTerminalControl.ISIG; // DISABLE - When any of the characters INTR, QUIT, SUSP, or DSUSP are received, generate the corresponding signal.
+
+
+ // If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before the read is satisfied. As TIME is zero, the timer is not used.
+ this.termInfo.c_cc[PosixTerminalControl.VMIN] = 1; // Minimum number of characters for noncanonical read (MIN).
+ this.termInfo.c_cc[PosixTerminalControl.VTIME] = 0; // Timeout in deciseconds for noncanonical read (TIME).
+
+ this.termInfo.c_cc[PosixTerminalControl.VSUSP] = 0; // suspend disabled
+ this.termInfo.c_cc[PosixTerminalControl.VEOF] = 0; // eof disabled
+ this.termInfo.c_cc[PosixTerminalControl.VEOL] = 0; // eol disabled
+
+
+ if (this.term.tcsetattr(0, PosixTerminalControl.TCSANOW, this.termInfo) != 0) {
+ throw new IOException("Can not set terminal flags");
+ }
+ }
+
+ /**
+ * Restore the original terminal configuration, which can be used when
+ * shutting down the console reader. The ConsoleReader cannot be
+ * used after calling this method.
+ */
+ @Override
+ public void restore() throws IOException {
+ if (this.term.tcsetattr(0, PosixTerminalControl.TCSANOW, this.termInfoDefault) != 0) {
+ throw new IOException("Can not reset terminal to defaults");
+ }
+ }
+
+ /**
+ * Returns number of columns in the terminal.
+ */
+ @Override
+ public int getWidth() {
+ if (this.term.ioctl(0, PosixTerminalControl.TIOCGWINSZ, this.windowSizeBuffer) != 0) {
+ return DEFAULT_WIDTH;
+ }
+
+ short columns = (short)(0x000000FF &this.windowSizeBuffer.get(2) + (0x000000FF & this.windowSizeBuffer.get(3)) * 256);
+ return columns;
+ }
+
+ /**
+ * Returns number of rows in the terminal.
+ */
+ @Override
+ public int getHeight() {
+ if (this.term.ioctl(0, PosixTerminalControl.TIOCGWINSZ, this.windowSizeBuffer) != 0) {
+ return DEFAULT_HEIGHT;
+ }
+
+ short rows = (short)(0x000000FF &this.windowSizeBuffer.get(0) + (0x000000FF & this.windowSizeBuffer.get(1)) * 256);
+ return rows;
+ }
+
+ @Override
+ public synchronized void setEchoEnabled(final boolean enabled) {
+ // have to reget them, since flags change everything
+ if (this.term.tcgetattr(0, this.termInfo) !=0) {
+ this.logger.error("Failed to get terminal info");
+ }
+
+ if (enabled) {
+ this.termInfo.c_lflag |= PosixTerminalControl.ECHO; // ENABLE Echo input characters.
+ }
+ else {
+ this.termInfo.c_lflag &= ~PosixTerminalControl.ECHO; // DISABLE Echo input characters.
+ }
+
+ if (this.term.tcsetattr(0, PosixTerminalControl.TCSANOW, this.termInfo) != 0) {
+ this.logger.error("Can not set terminal flags");
+ }
+
+ super.setEchoEnabled(enabled);
+ }
+
+ public void disableInterruptCharacter() {
+ // have to re-get them, since flags change everything
+ if (this.term.tcgetattr(0, this.termInfo) !=0) {
+ this.logger.error("Failed to get terminal info");
+ }
+
+ this.termInfo.c_cc[PosixTerminalControl.VINTR] = 0; // interrupt disabled
+
+ if (this.term.tcsetattr(0, PosixTerminalControl.TCSANOW, this.termInfo) != 0) {
+ this.logger.error("Can not set terminal flags");
+ }
+ }
+
+ public void enableInterruptCharacter() {
+ // have to re-get them, since flags change everything
+ if (this.term.tcgetattr(0, this.termInfo) !=0) {
+ this.logger.error("Failed to get terminal info");
+ }
+
+ this.termInfo.c_cc[PosixTerminalControl.VINTR] = 3; // interrupt is ctrl-c
+
+ if (this.term.tcsetattr(0, PosixTerminalControl.TCSANOW, this.termInfo) != 0) {
+ this.logger.error("Can not set terminal flags");
+ }
+ }
+}
diff --git a/Dorkbox-Util/src/dorkbox/util/input/unsupported/UnsupportedTerminal.java b/Dorkbox-Util/src/dorkbox/util/input/unsupported/UnsupportedTerminal.java
new file mode 100644
index 0000000..54affae
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/input/unsupported/UnsupportedTerminal.java
@@ -0,0 +1,30 @@
+package dorkbox.util.input.unsupported;
+
+import java.io.IOException;
+
+import dorkbox.util.input.Terminal;
+
+public class UnsupportedTerminal extends Terminal {
+ public UnsupportedTerminal() {
+// setAnsiSupported(false);
+ setEchoEnabled(true);
+ }
+
+ @Override
+ public void init() throws IOException {
+ }
+
+ @Override
+ public void restore() {
+ }
+
+ @Override
+ public int getWidth() {
+ return 0;
+ }
+
+ @Override
+ public int getHeight() {
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/input/windows/ConsoleMode.java b/Dorkbox-Util/src/dorkbox/util/input/windows/ConsoleMode.java
new file mode 100644
index 0000000..428ef17
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/input/windows/ConsoleMode.java
@@ -0,0 +1,71 @@
+package dorkbox.util.input.windows;
+
+/**
+ * Console mode
+ *
+ * Constants copied wincon.h.
+ */
+public enum ConsoleMode {
+ /**
+ * The ReadFile or ReadConsole function returns only when a carriage return
+ * character is read. If this mode is disable, the functions return when one
+ * or more characters are available.
+ */
+ ENABLE_LINE_INPUT(2),
+
+ /**
+ * Characters read by the ReadFile or ReadConsole function are written to
+ * the active screen buffer as they are read. This mode can be used only if
+ * the ENABLE_LINE_INPUT mode is also enabled.
+ */
+ ENABLE_ECHO_INPUT(4),
+
+ /**
+ * CTRL+C is processed by the system and is not placed in the input buffer.
+ * If the input buffer is being read by ReadFile or ReadConsole, other
+ * control keys are processed by the system and are not returned in the
+ * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also
+ * enabled, backspace, carriage return, and linefeed characters are handled
+ * by the system.
+ */
+ ENABLE_PROCESSED_INPUT(1),
+
+ /**
+ * User interactions that change the size of the console screen buffer are
+ * reported in the console's input buffee. Information about these events
+ * can be read from the input buffer by applications using
+ * theReadConsoleInput function, but not by those using ReadFile
+ * orReadConsole.
+ */
+ ENABLE_WINDOW_INPUT(8),
+
+ /**
+ * If the mouse pointer is within the borders of the console window and the
+ * window has the keyboard focus, mouse events generated by mouse movement
+ * and button presses are placed in the input buffer. These events are
+ * discarded by ReadFile or ReadConsole, even when this mode is enabled.
+ */
+ ENABLE_MOUSE_INPUT(16),
+
+ /**
+ * When enabled, text entered in a console window will be inserted at the
+ * current cursor location and all text following that location will not be
+ * overwritten. When disabled, all following text will be overwritten. An OR
+ * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS
+ * flag to enable this functionality.
+ */
+ ENABLE_PROCESSED_OUTPUT(1),
+
+ /**
+ * This flag enables the user to use the mouse to select and edit text. To
+ * enable this option, use the OR to combine this flag with
+ * ENABLE_EXTENDED_FLAGS.
+ */
+ ENABLE_WRAP_AT_EOL_OUTPUT(2),;
+
+ public final int code;
+
+ ConsoleMode(final int code) {
+ this.code = code;
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/input/windows/WindowsTerminal.java b/Dorkbox-Util/src/dorkbox/util/input/windows/WindowsTerminal.java
new file mode 100644
index 0000000..25cc950
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/input/windows/WindowsTerminal.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2002-2012, 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.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package dorkbox.util.input.windows;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.fusesource.jansi.internal.WindowsSupport;
+
+import dorkbox.util.input.Terminal;
+
+/**
+ * Terminal implementation for Microsoft Windows. Terminal initialization in
+ * {@link #init} is accomplished by calling the Win32 APIs SetConsoleMode and
+ * GetConsoleMode to
+ * disable character echoing.
+ *
+ *
+ * By default, the {@link #wrapInIfNeeded(java.io.InputStream)} method will attempt
+ * to test to see if the specified {@link InputStream} is {@link System#in} or a wrapper
+ * around {@link FileDescriptor#in}, and if so, will bypass the character reading to
+ * directly invoke the readc() method in the JNI library. This is so the class
+ * can read special keys (like arrow keys) which are otherwise inaccessible via
+ * the {@link System#in} stream. Using JNI reading can be bypassed by setting
+ * the jline.WindowsTerminal.directConsole
system property
+ * to false
.
+ *
+ *
+ * @author Marc Prud'hommeaux
+ * @author Jason Dillon
+ * @since 2.0
+ */
+public class WindowsTerminal extends Terminal
+{
+ public static final String DIRECT_CONSOLE = WindowsTerminal.class.getName() + ".directConsole";
+
+ private int originalMode;
+
+ public WindowsTerminal() {
+ }
+
+ @Override
+ public void init() throws IOException {
+ this.originalMode = WindowsSupport.getConsoleMode();
+ WindowsSupport.setConsoleMode(this.originalMode & ~ConsoleMode.ENABLE_ECHO_INPUT.code);
+ setEchoEnabled(false);
+ }
+
+ /**
+ * Restore the original terminal configuration, which can be used when
+ * shutting down the console reader. The ConsoleReader cannot be
+ * used after calling this method.
+ */
+ @Override
+ public void restore() throws IOException {
+ // restore the old console mode
+ WindowsSupport.setConsoleMode(this.originalMode);
+ }
+
+ @Override
+ public int getWidth() {
+ int w = WindowsSupport.getWindowsTerminalWidth();
+ return w < 1 ? DEFAULT_WIDTH : w;
+ }
+
+ @Override
+ public int getHeight() {
+ int h = WindowsSupport.getWindowsTerminalHeight();
+ return h < 1 ? DEFAULT_HEIGHT : h;
+ }
+
+ @Override
+ public void setEchoEnabled(final boolean enabled) {
+ // Must set these four modes at the same time to make it work fine.
+ if (enabled) {
+ WindowsSupport.setConsoleMode(WindowsSupport.getConsoleMode() |
+ ConsoleMode.ENABLE_ECHO_INPUT.code |
+ ConsoleMode.ENABLE_LINE_INPUT.code |
+ ConsoleMode.ENABLE_PROCESSED_INPUT.code |
+ ConsoleMode.ENABLE_WINDOW_INPUT.code);
+ }
+ else {
+ WindowsSupport.setConsoleMode(WindowsSupport.getConsoleMode() &
+ ~(ConsoleMode.ENABLE_LINE_INPUT.code |
+ ConsoleMode.ENABLE_ECHO_INPUT.code |
+ ConsoleMode.ENABLE_PROCESSED_INPUT.code |
+ ConsoleMode.ENABLE_WINDOW_INPUT.code));
+ }
+ super.setEchoEnabled(enabled);
+ }
+
+
+ @Override
+ public InputStream wrapInIfNeeded(InputStream in) throws IOException {
+ if (isSystemIn(in)) {
+ return new InputStream() {
+ @Override
+ public int read() throws IOException {
+ return WindowsSupport.readByte();
+ }
+ };
+ } else {
+ return in;
+ }
+ }
+
+ private boolean isSystemIn(final InputStream in) throws IOException {
+ if (in == null) {
+ return false;
+ }
+ else if (in == System.in) {
+ return true;
+ }
+ else if (in instanceof FileInputStream && ((FileInputStream) in).getFD() == FileDescriptor.in) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/Dorkbox-Util/src/dorkbox/util/process/ShellProcessBuilder.java b/Dorkbox-Util/src/dorkbox/util/process/ShellProcessBuilder.java
index 89adc68..5ac78c2 100644
--- a/Dorkbox-Util/src/dorkbox/util/process/ShellProcessBuilder.java
+++ b/Dorkbox-Util/src/dorkbox/util/process/ShellProcessBuilder.java
@@ -115,7 +115,10 @@ public class ShellProcessBuilder {
} else {
// *nix
executableName = "/bin/bash";
- // executableName = "/bin/sh";
+ File file = new File(executableName);
+ if (!file.canExecute()) {
+ executableName = "/bin/sh";
+ }
arguments.add(0, "-c");
}
} else if (workingDirectory != null) {