xterm does not perform its input with the shell and utilities via pipe(7)s. Instead, it uses the Unix PTY framework (see pty(7), openpty(3), forkpty(3), posix_openpt(3), pts(4) manpages for some information). The PTY framework allows any process to serve as a terminal "master" (e.g., telnetd(8), sshd(8), xterm(1), etc.) and any process can connect to the terminal slave to provide an interactive environment just like sitting at the console.
Why do I have different output between a terminal and a file when
forking?
C standard library functions use internal buffering for speed up. Most implementations use fully buffered IO for file streams, line buffered for stdin/stdout and unbuffered for stderr.
So your problem can be solved in number of ways:
Use explicit buffer flush before fork via fflush(3)
Set buffer type manually via setvbuf(3)
Use write(2) instead of stdlib's printf(3)
Output to stderr by default via fprintf(3)*
Exit with _exit(2) in forked processes instead of exit(3)**
Last two may not work as expected if:
* your implementation does not use unbuffered writes to stderr by default (Which is required by ISO C)
** you have written more than default buffer size in child and if was automatically flushed.
xterm
does not perform its input with the shell and utilities viapipe(7)
s. Instead, it uses the Unix PTY framework (seepty(7)
,openpty(3)
,forkpty(3)
,posix_openpt(3)
,pts(4)
manpages for some information). The PTY framework allows any process to serve as a terminal "master" (e.g.,telnetd(8)
,sshd(8)
,xterm(1)
, etc.) and any process can connect to the terminal slave to provide an interactive environment just like sitting at the console.The Advanced Programming in the Unix Environment, 2nd edition book by Stevens and Rago has an excellent chapter on using pseudo-terminal devices to control slave programs -- including an excellent little
pty
program that allows driving "interactive" programs in a manner similar toexpect(1)
, but in C rather thantcl
.If your primary motive is to learn network programming and writing daemons, then I would recommend reading Beej's Guide to Network Programming and Advanced Programming in the Unix Environment. These don't provide straight up SMTP implementations but will give a good foundation to implement any protocol.
C standard library functions use internal buffering for speed up. Most implementations use fully buffered IO for file streams, line buffered for stdin/stdout and unbuffered for stderr.
So your problem can be solved in number of ways:
fflush(3)
setvbuf(3)
write(2)
instead of stdlib'sprintf(3)
stderr
by default viafprintf(3)
*_exit(2)
in forked processes instead ofexit(3)
**Last two may not work as expected if:
* your implementation does not use unbuffered writes to stderr by default (Which is required by ISO C)
** you have written more than default buffer size in child and if was automatically flushed.
PS. Yet again, if you need deeper knowledge of standard library functions and buffering I recommend reading Advanced Programming in the UNIX Environment (2nd Edition) by W. Richard Stevens and Stephen A. Rago.
PPS. btw, your question is a very popular interview question for C/C++ programmer position.