#include #include #include #include #include #include #include int openpty(int* amaster, int* aslave, char* name, const struct termios* termp, const struct winsize* winp) { char buf[512]; int master = open("/dev/ptmx", O_RDWR); if (master == -1) return -1; if (grantpt(master) || unlockpt(master) || ptsname_r(master, buf, sizeof buf)) goto fail; int slave = open(buf, O_RDWR | O_NOCTTY); if (slave == -1) goto fail; /* XXX Should we ignore errors here? */ if (termp) tcsetattr(slave, TCSAFLUSH, termp); if (winp) ioctl(slave, TIOCSWINSZ, winp); *amaster = master; *aslave = slave; if (name != NULL) strcpy(name, buf); return 0; fail: close(master); return -1; } int login_tty(int fd) { setsid(); if (ioctl(fd, TIOCSCTTY, NULL) == -1) return -1; dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); if (fd > 2) close(fd); return 0; } int forkpty(int* amaster, char* name, const struct termios* termp, const struct winsize* winp) { int master, slave; if (openpty(&master, &slave, name, termp, winp) == -1) { return -1; } int pid; switch (pid = fork()) { case -1: return -1; case 0: close(master); if (login_tty(slave)) _exit(1); return 0; default: *amaster = master; close (slave); return pid; } }