rmyorston / busybox-w32

WIN32 native port of BusyBox.
https://frippery.org/busybox
Other
697 stars 126 forks source link

Ctrl+d fails to send EOF in ash #444

Closed bharatvaj closed 3 months ago

bharatvaj commented 3 months ago

Programs don't receive EOF when typing ctrl+d, but both awk and busybox awk seems to handle this on Linux ash.

$ awk '{ print $1 }'
hey
hey
you
you
^D

The ^D character is printed on every terminal emulator I tried (Console Host, Windows Terminal, Alacritty), so I assume the error is in win32 ash itself.

avih commented 3 months ago

On windows ^Z is the EOF at the terminal.

rmyorston commented 3 months ago

The EOF character in Windows is ctrl+z.

avih commented 3 months ago

Ninja`d!

rmyorston commented 3 months ago

The shell itself treats ctrl+d as a request to exit, but that's in the line editing code.

bharatvaj commented 3 months ago

Didn't know ctrl+z was the EOF. ctrl+z does successfully close the input, but even then end is not getting called in awk. And the input closes only after pressing <ctrl+z><enter>

$ awk "{ print $1 } end { print \"the end\" }"
hey
hey
^Z
$
bharatvaj commented 3 months ago

The shell itself treats ctrl+d as a request to exit, but that's in the line editing code.

Forgive my ignorance, but why not generalize <ctrl+d> it to send eof and handle eof in both ash and other programs?

rmyorston commented 3 months ago

Yes, you need to hit <enter>. It's just what Windows does.

END is case sensitive in awk:

~ $ awk '{print} END { print "end" }'
yo
yo
^Z
end
~ $
rmyorston commented 3 months ago

why not generalize <ctrl+d> it to send eof and handle eof in both ash and other programs?

The line editing code reads raw keystrokes from the terminal. It can therefore have its own interpretation of ctrl+d or ctrl+z.

Non-interactive programs use C runtime functions to read input. Often this input will come from a file or a pipe. When it comes from the terminal it will have been processed by the terminal. It's the terminal which interprets ctrl+z as end of file and causes the read function to return EOF. The program doesn't see a literal ctrl+z.

If we want non-interactive programs to treat ctrl+d as EOF we'd need to replace all C runtime functions that read input with a wrapper which reads raw input from the terminal. I don't think the additional complexity is justified.

avih commented 3 months ago

If we want non-interactive programs to treat ctrl+d as EOF we'd need to replace all C runtime functions that read input with a wrapper which reads raw input from the terminal

Not only read. I would need to implement editing as well (e.g. backspace deletes last char on the current line, arrow-up recalls the last line, arrow left/right moves the cursor, etc), because that's how the console cooked mode behaves on windows, and it's a different editing than what you get at the shell prompt.

IIRC there were other factors which make this complicated (I did consider it when working on UTF-8 input, or maybe the native busybox W API, and there were some hard problems to solve with this approach, but unfortunately I don't recall what they are).

bharatvaj commented 3 months ago

I get it now, thanks for explaining the problem @avih and @rmyorston. The way I see it, sending EOF is the responsibility of the terminal emulator. I'm using clink with cmd, so hopefully this can be achieved from that end.