public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Rabbe Fogelholm <rabbe@bahnhof.se>
To: cygwin@cygwin.com
Subject: Re: stty -cooked not usable since cygwin-3.1.1-1
Date: Wed, 29 Jul 2020 22:03:34 +0200	[thread overview]
Message-ID: <e12b1d54-3037-2b05-77ca-bec1bb3acbf5@bahnhof.se> (raw)
In-Reply-To: <f935b0f6-1de3-e2d1-285e-f26cd945985a@towo.net>

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


  reply	other threads:[~2020-07-29 20:03 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-13 10:53 Rabbe Fogelholm
2020-01-13 11:02 ` Takashi Yano
2020-01-13 11:36   ` Rabbe Fogelholm
2020-07-28 13:56     ` Rabbe Fogelholm
2020-07-28 16:38       ` Takashi Yano
2020-07-28 16:56         ` Thomas Wolff
2020-07-28 17:40           ` Takashi Yano
2020-07-28 19:51           ` Rabbe Fogelholm
2020-07-28 23:30             ` Thomas Wolff
2020-07-29 20:03               ` Rabbe Fogelholm [this message]
2020-07-31  6:52                 ` Rabbe Fogelholm
2020-07-29  0:02             ` Takashi Yano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e12b1d54-3037-2b05-77ca-bec1bb3acbf5@bahnhof.se \
    --to=rabbe@bahnhof.se \
    --cc=cygwin@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).