#include"apue.h" // Returns: file descriptor of PTY master if OK, −1 on error intptym_open(char *pts_name, int pts_namesz); // Returns: file descriptor of PTY slave if OK, −1 on error intptys_open(char *pts_name);
int ptym_open(char *pts_name, int pts_namesz) { char *ptr; int fdm, err;
if ((fdm = posix_openpt(O_RDWR)) < 0) return(-1); if (grantpt(fdm) < 0) /* grant access to slave */ goto errout; if (unlockpt(fdm) < 0) /* clear slave's lock flag */ goto errout; if ((ptr = ptsname(fdm)) == NULL) /* get slave's name */ goto errout;
/* * Return name of slave. Null terminate to handle * case where strlen(ptr) > pts_namesz. */ strncpy(pts_name, ptr, pts_namesz); pts_name[pts_namesz - 1] = '\0'; return(fdm); /* return fd of master */ errout: err = errno; close(fdm); errno = err; return(-1); }
int ptys_open(char *pts_name) { int fds; #if defined(SOLARIS) int err, setup; #endif
if ((fds = open(pts_name, O_RDWR)) < 0) return(-1);
#if defined(SOLARIS) /* * Check if stream is already set up by autopush facility. */ if ((setup = ioctl(fds, I_FIND, "ldterm")) < 0) goto errout;
#include"apue.h" #include<termios.h> // Returns: 0 in child, process ID of child in parent, −1 on error pid_tpty_fork(int *ptrfdm, char *slave_name, int slave_namesz, conststruct termios *slave_termios, conststruct winsize *slave_winsize);
/* * System V acquires controlling terminal on open(). */ if ((fds = ptys_open(pts_name)) < 0) err_sys("can't open slave pty"); close(fdm); /* all done with master in child */
#if defined(BSD) /* * TIOCSCTTY is the BSD way to acquire a controlling terminal. */ if (ioctl(fds, TIOCSCTTY, (char *)0) < 0) err_sys("TIOCSCTTY error"); #endif /* * Set slave's termios and window size. */ if (slave_termios != NULL) { if (tcsetattr(fds, TCSANOW, slave_termios) < 0) err_sys("tcsetattr error on slave pty"); } if (slave_winsize != NULL) { if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0) err_sys("TIOCSWINSZ error on slave pty"); }
/* * Slave becomes stdin/stdout/stderr of child. */ if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) err_sys("dup2 error to stdin"); if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) err_sys("dup2 error to stdout"); if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) err_sys("dup2 error to stderr"); if (fds != STDIN_FILENO && fds != STDOUT_FILENO && fds != STDERR_FILENO) close(fds); return(0); /* child returns 0 just like fork() */ } else { /* parent */ *ptrfdm = fdm; /* return fd of master */ return(pid); /* parent returns pid of child */ } }