3
4
For a long while my understanding about a terminal in unix-like systems has been that it launches the shell process and provides a user interface to it by communicating with it over it's stdin, stdout & stderr.
However recently while looking into a problem with launching a windows console application via a cygwin terminal, I realize it may not be as simple as that.
At http://cygwin.com/1.5/cygwin-ug-net/using-effectively.html I see,
Another issue is receiving output from or giving input to console-based Windows programs. Unfortunately, interacting with Windows console applications is not a simple matter of using a translation utility. Windows console applications are designed to run under command.com or cmd.exe, and some do not deal gracefully with other situations. Cygwin can receive console input only if it is also running in a console (DOS box) since Windows does not provide any way to attach to the backend of the console device. Another traditional Unix input/output method, ptys (pseudo-terminals), is supported by Cygwin but not entirely by Windows. The basic problem is that a Cygwin pty is a pipe and some Windows applications do not like having their input or output redirected to pipes.
I wrote a little C program which I compiled under windows using VC++'s cl.exe -
#include <stdio.h>
int main(int argc, char *argv[]) {
#define BUFFER_LEN 1024
char buffer[BUFFER_LEN];
printf("echo server started\n");
while (fgets(buffer, BUFFER_LEN, stdin) != NULL) {
printf("%s", buffer);
}
return 0;
}
When I run the Cygwin terminal (mintty.exe) and launch this program, I cannot interact with it -
[puneet@freestyle ~]$ /cygdrive/c/echo1.exe
Hello
^-- no response
But when I put it in a pipe, it works -
[puneet@freestyle ~]$ echo -e "1\n2\n3" | /cygdrive/c/echo1.exe | while read line; do echo $line; done
1
2
3
[puneet@freestyle ~]$
Basically it fails to interact with the mintty.exe terminal. However when running bash.exe directly from a windows console, it can be correctly interacted with -
[puneet@freestyle ~]$ /cygdrive/c/echo1.exe
Hello
Hello
^Z
[puneet@freestyle ~]$
I then thought if I ssh'd into my machine and ran this program as a command, it would work as then the terminal wouldn't directly interact with it, but the SSH server will. However that doesn't work too -
[puneet@freestyle ~]$ ssh freestyle /cygdrive/c/echo1.exe
Hello
^-- no response
But putting this in a pipe again works ! -
[puneet@freestyle ~]$ echo -e "1\n2\n3" | ssh freestyle /cygdrive/c/echo1.exe | while read line; do echo $line; done
1
2
3
[puneet@freestyle ~]$
Could someone explain the theory behind all these observations?
Is the interaction between the terminal and the shell more than just using the shell's stdin, stdout and stderr?
How is the windows console different? Why do the windows console programs seem to work fine when in a pipe with the cygwin programs?
thanks for your answer! Output buffering explains a lot! Could you elaborate a little more on why the
^D
doesn't reachecho1.exe
and what is a non-emulated file stream? – 0cd – 2013-05-03T21:26:53.943I just made some edits (last 2 paragraphs). Does that explain the emulation/non-emulation better? – Wandering Logic – 2013-05-04T18:42:24.367
thanks, that makes it more clear! I'm still curious about how bash captures the ^Z? Isn't the DOS program running in foreground? – 0cd – 2013-05-07T21:26:57.233
I'm getting way out of my depth here. My guess is that mintty is capturing the ^Z and (somehow) passing it to bash instead of the foreground program. I think this is somehow part of the way that mintty and cygwin are emulating the notion of a Unix tty. If you run bash under a windows console the ^Z does go to the foreground program. – Wandering Logic – 2013-05-07T21:33:29.093