From: xetum on
For testing, I've coded this simple forkpty
example in linux (ubuntu 9.10):

#define BUF_SIZE 128
#define max(i, j) ((i > j) ? (i) : (j))

void selector (int fd) {
char buf[BUF_SIZE];
int n;

fd_set ss, ret;
FD_ZERO(&ss);
FD_SET(fd, &ss);
FD_SET(STDIN_FILENO, &ss);

while (true) {
ret = ss;
if (select(fd+1, &ret, NULL, NULL, NULL) == -1)
SysError("selector:select");
if (FD_ISSET(fd, &ret)) {
if ((n = read(fd, buf, BUF_SIZE)) > 0) {
write(STDOUT_FILENO, buf, n);
printf("n = %d writing to STDOUT\n",
n);
} else if (n == 0) {
printf("fd closed\n");
break;
} else {
printf("errno = %d\n", errno);
SysError("selector:read:fd");
}
} else if (FD_ISSET(STDIN_FILENO, &ret)) {
if ((n = read(STDIN_FILENO, buf, BUF_SIZE)) >
0) {
write(fd, buf, n);
printf("n = %d writing to fd\n", n);
} else if (n == 0) {
printf("STDIN closed\n");
break;
} else

SysError("selector:read:STDIN_FILENO");
}
}

}

int main(int argc, char *const argv[])
{
int pty;
tty_raw(STDIN_FILENO);
if (atexit(tty_reset) != 0)
RTError("atexit: can't register tty_reset");
switch(forkpty(&pty, NULL, NULL, NULL)) {
case -1: SysError("pty:forkpty");
case 0:
//console();
_exit(EXIT_SUCCESS);
default:
selector(pty);
}
return 0;

}

Client attached to pty slave just exits. select in father awakes with
fd (pty) ready, and read should return 0, shouldn't it? to indicate
EOF (stdout closed at pty slave), but returns -1 with errno=EIO (I/O
error). All pty example codes I've seen don't handle this read == -1
as an error but as a program finalization, but then how to tell
between EOF and a true error?

According to http://www.opengroup.org/onlinepubs/000095399/functions/close.html,
it seems that STREAMS based pty implementations return 0:

"If fildes refers to the slave side of a STREAMS-based pseudo-
terminal, a zero-length message may be sent to the master."

Regards, Francesc Oller