#include "apue.h"
#include <errno.h>
#include <fcntl.h>
#if defined(SOLARIS)
#include <stropts.h>
#endif
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)
goto errout;
if(unlock(fdm)<0)
goto errout;
if((ptr=ptsname(fdm))==NULL)
goto errout;
strncpy(pts_name, ptr, pts_namesz);
pst_namep[pts_namesz-1]='\0';
retur (fdm);
errout:
err=errno;
close(fdm);
errnor=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)
if((setup=ioctl(fds, I_FIND, "ldterm"))<0)
goto errout;
if(setup==0)
{
if(ioctl(fds, I_PUSH, "ptem")<0)
goto errout;
if(ioctl(fds, I_PUSH, "ldterm")<0)
goto errout;
if(ioctl(fds, I_PUSH,"ttcompt")<0)
{
errout:
err=errno;
close(fds);
errno=err;
return -1;
}
}
#endif
return fds;
}
Pseudo-terminal open functions
On Solaris, after opening the slave device, we might need to push three STREAMS modules onto the slave’s stream. Together, the pseudo terminal emulation module (ptem) and the terminal line discipline module (ldterm) act like a real terminal. The ttcompat module provides compatibility for older V7, 4BSD, and Xenix ioctl calls. It’s an optional module, but since it’s automatically pushed for network logins, we push it onto the slave’s stream.
Linux, Mac OS X, and Solaris follow the historical System V behavior: if the caller is a session leader that does not already have a controlling terminal, the call to open allocates the PTY slave as the controlling terminal. If we didn’t want this to happen, we could specify the O_NOCTTY flag for open. However, on FreeBSD, the open of the slave PTY does not have the side effect of allocating the device as the controlling terminal. In the next section, we’ll see how to allocate the controlling terminal when running on FreeBSD.
pty_fork Function
We now use the two functions from the previous section, ptym_open and ptys_open, to write a new function that we call pty_fork. This new function combines the opening of the master and the slave with a call to fork, establishing the child as a session leader with a controlling terminal.
#include "apue.h"
#include <termios.h>
pid_t pty_fork(int *ptrfdm, char *slave_name, int slave_namesz, const struct termios *slave_termios, const struct winsize *slave_winsize);
The file descriptor of the PTY master is returned through the ptrfdm pointer.