#define _GNU_SOURCE #include #include #include #include #include #include #include #include #ifdef __sun__ /* Once Solaris has openpty(), this is going to be removed. */ int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { const char *slave; int mfd, sfd = -1; *amaster = *aslave = -1; mfd = sfd = -1; mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY); if (mfd < 0) goto err; if (grantpt(mfd) == -1 || unlockpt(mfd) == -1) goto err; if ((slave = ptsname(mfd)) == NULL) { fprintf(stderr, "foo\n"); goto err; } sfd = open(slave, O_RDONLY | O_NOCTTY); if (sfd == -1) { fprintf(stderr, "failed open\n"); goto err; } if (ioctl(sfd, I_PUSH, "ptem") == -1 || (termp != NULL && tcgetattr(sfd, termp) < 0)) { fprintf(stderr, "failed!"); goto err; } if (amaster) *amaster = mfd; if (aslave) *aslave = sfd; if (winp) ioctl(sfd, TIOCSWINSZ, winp); return 0; err: if (sfd != -1) close(sfd); close(mfd); return -1; } void cfmakeraw (struct termios *termios_p) { termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); termios_p->c_oflag &= ~OPOST; termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); termios_p->c_cflag &= ~(CSIZE|PARENB); termios_p->c_cflag |= CS8; termios_p->c_cc[VMIN] = 0; termios_p->c_cc[VTIME] = 0; } #endif int main() { const char *slave; struct termios term; int master, slavefd; char buf[1]; fd_set readfds; if (openpty(&master, &slavefd, NULL, &term, NULL) < 0) { fprintf(stderr, "failed openpty %d\n", errno); exit(1); } slave = ptsname(master); printf("terminal is %s\n", slave); fflush(stdout); if (fcntl(master, F_SETFL, O_NONBLOCK) == -1) { fprintf(stderr, "failed to set non block\n"); exit(1); } cfmakeraw(&term); if (tcsetattr(slavefd, TCSAFLUSH, &term) < 0) { fprintf(stderr, "tcsetattr failed %d\n", errno); exit(1); } close(slavefd); for (;;) { int ret; FD_ZERO(&readfds); FD_SET(master, &readfds); ret = select(master + 1, &readfds, NULL,NULL, NULL); if (ret == -1) { fprintf(stderr, "select got -1 %d\n", errno); } else { fprintf(stderr, "select returned\n"); } if (!FD_ISSET(master, &readfds)) { fprintf(stderr, "huh? master isn't set?\n"); } ret = read(master, buf, 1); if (ret == 0) { fprintf(stderr, "got 0 read: slave was closed\n"); } else if (ret > 0) { fprintf(stderr, "got %d bytes from master: %c\n", ret, buf[0]); } else if (ret != -1 || errno != EAGAIN) { fprintf(stderr, "read of master: %d %d\n", ret, errno); } } }