10

The case is as follows:

1) I have a script somescript.sh.

2) At the end of the script, there is an eval statement which triggers the execution of a JAR.

3) When the JAR is executed, it will ask the user to provide an a/b/c option as a possible answer - important fact is that this questions come from the JAR application, so the console "logic" regarding the questions is written in Java and not placed in the script itself.

The problem: while executing the JAR program, the user can press the arrow keys and this will result in an ugly outcome such as ^[[A ^[[B ^[[C ^[[D.

This thread clarifies the ugly outcome: Why the terminal shows "^[[A" "^[[B" "^[[C" "^[[D" when pressing the arrow keys in Ubuntu?

Question: How is it possible to disable the arrow keys while the JAR is executed?

Insanovation
  • 337
  • 6
  • 21
  • did you try to execute the JAR with [rlwrap](https://github.com/hanslub42/rlwrap) – Yuri G. Jul 03 '17 at 04:58
  • @YuriG. Didn't know about rlwrap. Maybe that's an option, but I need to obtain this without involving another program. The current state is that JNativeHook may be used in the Java code itself, in order to disable the arrow keys. However, how would you use rlwrap in order to disable the arrow keys? Can you provide this as a full-detailed answer, and if no other update will occur, I will mark it as a Solution. Thanks Yuri! – Insanovation Jul 03 '17 at 08:00

1 Answers1

7

Now this is rather convoluted, but it`s still better than nothing.

The code below is a primitive BASH key filter to bypass cursor keys and halt any input on pressing Enter. Currently it lacks backspace support, but this is also doable if need be.

Requires BASH 4.2 or greater.

while true; do
    read -s -N1          c1
    read -s -N2 -t 0.001 c2
    read -s -N1 -t 0.001 c3
    case "$c1$c2$c3" in
        $'\x0a' | $'') echo "";
                       break ;; # Enter
        $'\x1b\x5b\x41')     ;; # Up arrow
        $'\x1b\x5b\x42')     ;; # Down arrow
        $'\x1b\x5b\x43')     ;; # Right arrow
        $'\x1b\x5b\x44')     ;; # Left arrow
        *) echo -n $c1$c2$c3 ;; # [guaranteed to be non-empty]
    esac
done | tee >(stdbuf -o0 java -jar your_applet.jar)
  • read is a BASH built-in function that captures keyboard input.
  • echo is a BASH built-in function that prints what it`s told.
  • tee redirects the output to both STDOUT and the file provided.
  • >() is the so-called process substitution; it acts like a file for the writer and passes the resulting file`s contents as input to the command inside its brackets.
  • stdbuf disables output buffering, just in case.

Both tee and stdbuf are parts of coreutils, so they have to be present almost everywhere (maybe except Android, but that`s another story).

[UPD.] Last line, adapted:

done | tee >(stdbuf -o0 "$JAVA" $JAVA_OPTS -jar "$JBOSS_HOME/jboss-modules.jar" -mp "$JBOSS_MODULEPATH" org.jboss.as.domain-add-user "$@")

Hopefully that`d work.

[UPD2.] FINALLY! A different solution!

Just add this before eval:

stty=$(stty -g)
stty -ctlecho
trap "stty $stty" HUP INT QUIT PIPE TERM

Okay, this is also not perfect (the user is now able to travel the screen by pressing cursor keys…) but that`s still better than ^[[B^[[A^[[D^[[C

hidefromkgb
  • 5,834
  • 1
  • 13
  • 44
  • I'm trying to apply your method. Currently it says "syntax error near unexpected token `('" regarding the line with >(). Anyway, it's an open source project, so I can provide more details. I'm trying to somehow apply your solution to the eval statement at the end of this: https://github.com/wildfly/wildfly-core/blob/master/core-feature-pack/src/main/resources/content/bin/add-user.sh – Insanovation Jul 07 '17 at 13:17
  • Insanovation, just changing `java -jar your_applet.jar` to `eval ` won\`t help much, as `eval` is not a command but rather a BASH built-in function like `read` and `echo`. Can you try something like `/add-user.sh` instead? – hidefromkgb Jul 07 '17 at 14:21
  • Sorry, I didn't understand your previous suggestion. In the eval statement there is the .jar execution call. Can you please edit the original answer in conjunction with the eval statement from the add-user.sh? – Insanovation Jul 07 '17 at 15:14
  • Insanovation, sure. Updated my answer. – hidefromkgb Jul 07 '17 at 15:41
  • Thank you. But I've tried with your upper update and also with "done | tee >(stdbuf -o0 $JAVA $JAVA_OPTS -jar $JBOSS_HOME/jboss-modules.jar -mp $JBOSS_MODULEPATH org.jboss.as.domain-add-user $@)" - and both throw "syntax error near unexpected token `('". If you wish, you may try it locally yourself; you can clone the repo, build from the top dir with $mvn clean install -DskipTests ; after that you can go to build/target/jboss-some-version/bin and ./add-user.sh. Thanks for the help so far. – Insanovation Jul 07 '17 at 16:03
  • Insanovation, can you please show your BASH version (use `bash --version`)? Mine is as follows: `GNU bash, version 4.3.42(1)-release (x86_64-redhat-linux-gnu)` – hidefromkgb Jul 07 '17 at 16:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/148622/discussion-between-hidefromkgb-and-insanovation). – hidefromkgb Jul 07 '17 at 16:14