stty -cooked not usable since cygwin-3.1.1-1

Rabbe Fogelholm rabbe@bahnhof.se
Fri Jul 31 06:52:30 GMT 2020


On 2020-07-29 22:03, Rabbe Fogelholm wrote:
> On 2020-07-29 01:30, Thomas Wolff wrote:
>>
>>
>> Am 28.07.2020 um 21:51 schrieb Rabbe Fogelholm:
>>> On 2020-07-28 18:56, Thomas Wolff wrote:
>>>>
>>>>
>>>> Am 28.07.2020 um 18:38 schrieb Takashi Yano via Cygwin:
>>>>> On Tue, 28 Jul 2020 15:56:54 +0200
>>>>> Rabbe Fogelholm wrote:
>>>>>> Rabbe Fogelholm wrote:
>>>>>>> Takashi Yano wrote:
>>>>>>>> On Mon, 13 Jan 2020 11:52:43 +0100
>>>>>>>> Rabbe Fogelholm wrote:
>>>>>>>>> I am running a console Java program that is started from a 
>>>>>>>>> shellscript
>>>>>>>>> wrapper. Before invoking Java the wrapper calls `stty -cooked'. 
>>>>>>>>> The Java
>>>>>>>>> program polls the keyboard using System.in.available() and reads
>>>>>>>>> characters immediately using System.in.read(), without waiting 
>>>>>>>>> for the
>>>>>>>>> Enter key to be pressed.
>>>>>>>>>
>>>>>>>>> This way of combining `stty -cooked' and Java has stopped 
>>>>>>>>> working since
>>>>>>>>> version 3.1.1-1 of the Cygwin package. The Java thread that 
>>>>>>>>> reads the
>>>>>>>>> keyboard hangs until Enter is pressed, which is not desirable.
>>>>>>>>>
>>>>>>>>> I had to downgrade to version 3.0.7-1 to resolve the problem.
>>>>>>>>>
>>>>>>>>> Versioning information:
>>>>>>>>>
>>>>>>>>> java version "1.8.0_202"
>>>>>>>>> Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
>>>>>>>>> Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
>>>>>>>>>
>>>>>>>>> OS Name: Microsoft Windows 10 Pro
>>>>>>>>> Version: 10.0.17763 Build 17763
>>>>>>>>> System Type: x64-based PC
>>>>>>>>>
>>>>>>>>> See also the enclosed cygcheck.out.
>>>>>>>>>
>>>>>>>>> To demonstrate the issue I enclose a small Java program that 
>>>>>>>>> should be
>>>>>>>>> able to read single keystrokes when `stty -cooked' is in effect.
>>>>>>>> Does your java program work in command prompt? cygwin 3.1.x uses
>>>>>>>> pseudo console, so the native (non cygwin) program works as if it
>>>>>>>> is executed in command prompt.
>>>>>>>>
>>>>>>> With cygwin 3.1.x I can't find a way to make my program work.
>>>>>>>
>>>>>>> When running from within a Cygwin64 terminal the `stty -cooked' 
>>>>>>> command
>>>>>>> terminates with exit code 0, but the Java program behaves just as if
>>>>>>> `stty -cooked' is not in effect: It does not handle single 
>>>>>>> keystrokes
>>>>>>> immediately.
>>>>>>>
>>>>>>> When running from a Windows command prompt I can execute the stty
>>>>>>> program as \cygwin64\bin\stty. However, when given the '-cooked'
>>>>>>> argument it complains:
>>>>>>> /usr/bin/stty: 'standard input': unable to perform all requested 
>>>>>>> operations
>>>>>>>
>>>>>>> - and here as well the Java program behaves as if `stty -cooked' 
>>>>>>> is not
>>>>>>> in effect.
>>>>>> Some time has passed; I am just curious if anyone may have found a
>>>>>> solution to the "stty -cooked" issue. With cygwin-3.0.* it was 
>>>>>> possible
>>>>>> to have a Java program act on single keystrokes, with cygwin-3.1 I 
>>>>>> don't
>>>>>> know how to do it. Any ideas welcome!
>>>>> Solution 1:
>>>>> Redesign your java program using JNA with kbhit()/getch() instead of
>>>>> System.in.available()/System.in.read().
>>>>>
>>>>> Solution 2:
>>>>> Add SetConsoleMode() call with ENABLE_LINE_INPUT flag cleared using 
>>>>> JNA.
>>>> Couldn't cygwin clear this flag when it sets up ConPTY while the pty 
>>>> is in raw mode?
>>>> Thomas
>>>>
>>>>>
>>>>> Solution 3:
>>>>> Use a wrappwer instead of stty such as:
>>>>>
>>>>> #include <stdio.h>
>>>>> #include <unistd.h>
>>>>> #include <termios.h>
>>>>> #include <string.h>
>>>>> #include <pthread.h>
>>>>> #include <sys/wait.h>
>>>>>
>>>>> void *fwd(void *param)
>>>>> {
>>>>>      FILE *f = (FILE *) param;
>>>>>      char buf[128];
>>>>>      int len;
>>>>>      while (1) {
>>>>>          if ((len = read(0, buf, sizeof(buf))) <= 0) break;
>>>>>          if (write(fileno(f), buf, len) < len) break;
>>>>>      }
>>>>>      return NULL;
>>>>> }
>>>>>
>>>>> int main(int argc, char *argv[])
>>>>> {
>>>>>      FILE *f;
>>>>>      int i;
>>>>>      pthread_t th;
>>>>>      struct termios t, t_orig;
>>>>>      char cmd[1024] = {0, };
>>>>>      if (argc < 2) return 0;
>>>>>      for (i = 1; i < argc && strlen(cmd)+strlen(argv[i]) < 
>>>>> sizeof(cmd)-2; i++) {
>>>>>          sprintf(cmd + strlen(cmd), (i>1)?" %s":"%s", argv[i]);
>>>>>      }
>>>>>      f = popen(cmd, "w");
>>>>>      tcgetattr(0, &t_orig);
>>>>>      t = t_orig;
>>>>>      cfmakeraw(&t);
>>>>>      tcsetattr(0, TCSANOW, &t);
>>>>>      pthread_create(&th, NULL, fwd, f);
>>>>>      wait(NULL);
>>>>>      tcsetattr(0, TCSANOW, &t_orig);
>>>>>      pclose(f);
>>>>>      return 0;
>>>>> }
>>>>>
>>>>
>>>>
>>> Thanks Takashi for suggesting many ways to solve this! The C wrapper 
>>> solution looks quite powerful.
>> Can you please provide a full test case, as it worked for you in 
>> cygwin 3.0.7, i.e. the Java program and the wrapping commands, for 
>> some experiments.
>> Thomas
>>
>>>
>>> Meanwhile it has occurred to me that bash itself can provide a
>>> workaround. Since I start the Java console application from a bash
>>> wrapper already, I have now changed it so that it does something like
>>> this:
>>>
>>> (while true; do read -s -r -N 1 Key; echo "$Key"; done) | java ...
>>>
>>> With these options to 'read' I get action on every keystroke, and the
>>> Java program gets its input as terminated length-1 lines.
>>> -- 
>>> Problem reports:      https://cygwin.com/problems.html
>>> FAQ:                  https://cygwin.com/faq/
>>> Documentation:        https://cygwin.com/docs.html
>>> Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple
> 
> Hi Thomas, this small program can be used for experiments:
> 
> --- ReadKeystrokes.java ------------
> 
> import java.io.IOException;
> 
> public final class ReadKeystrokes {
> 
>      /**
>       * Read keystrokes and write codes to standard output. The
>           * intention is that writing should occur immediately.
>       * @param args
>       * @throws InterruptedException
>       * @throws IOException
>       */
>      public static void main(String[] args) throws IOException, 
> InterruptedException {
>          System.out.println("Press any keys; to exit press 'q'");
> 
>          for (; true;) {
>              if (System.in.available() > 0) {
>                  final int c = System.in.read();
>                  System.out.println(String.format("key was pressed, 
> code: %d", c));
>                  if (c == 'q') {
>                      break;
>                  }
>              }
>              else {
>                  Thread.sleep(100);
>              }
>          }
>      }
> }
> 
> ------------------------------------
> 
> After compiling, assuming ReadKeystrokes.class is in the current
> directory, launch it with:
> 
> java -classpath ./ ReadKeystrokes
> 
> 
I suppose the behavior of the above test program may depend on the Java 
runtime being used. I am using Oracle Java SE 1.8, version 202.


More information about the Cygwin mailing list