Advanced Programming in UNIX Environment Episode 124

pty_fork函数用于在父进程中创建一个子进程,并为子进程分配一个伪终端(PTY)。子进程通过setsid建立新会话,并将PTY设置为控制终端。在子进程中,PTY的slave被初始化并连接到标准输入、输出和错误。在不同的操作系统上,如Linux、FreeBSD等,使用不同的方法来使PTY成为控制终端。
摘要由CSDN通过智能技术生成

After opening the PTY master, fork is called. As we mentioned before, we want to wait to call ptys_open until in the child and after calling setsid to establish a new session. When it calls setsid, the child is not a process group leader, so the three steps listed in Section 9.5 occur: (a) a new session is created with the child as the session leader, (b) a new process group is created for the child, and © the child loses any association it might have had with its previous controlling terminal. Under Linux, Mac OS X, and Solaris, the slave becomes the controlling terminal of this new session when ptys_open is called. Under FreeBSD, we have to use the TIOCSCTTY ioctl command to allocate the controlling terminal. (Recall Figure 9.8 — the other three platforms also support TIOCSCTTY, but we need to call it only on FreeBSD.)

The two structures termios and winsize are then initialized in the child. Finally, the slave file descriptor is duplicated onto standard input, standard output, and standard error in the child. This means that whatever process the caller execs from the child will have these three descriptors connected to the slave PTY (its controlling terminal).

After the call to fork, the parent just returns the PTY master descriptor and the process ID of the child. In the next section, we use the pty_fork function in the pty program.

#include "apue.h"
#include <termios.h>

pid_t pty_fork(int *ptrfm, char *slave_name, int slave_namesz, 
                const struct termios *slave_termios,
                const struct winsize *slave_winsize)
{
    int fdm, fds;

    pid_t pid;
    char pts_name[20];

    if((fdm=ptym_open(pts_name, sizeof(pts_name)))<0)
        err_sys("can't open master pty: %s, error %d", pts_name, fdm);
    
    if(slave_name!=NULL)
    {
        strncpy(slave_name, pts_name, slave_namesz);
        slave_name[slave_namesz-1]='\0';
    }

    if((pid=fork())<0)
    {
        return -1;
    }
    else if(pid==0)
    {
        if(setsid()<0)
            err_sys("setid error");
        
        if((fds=ptys_open(pts_name))<0)
            err_sy("can't open slave pty");
        close(fdm);
    
#if defined(BSD)

        if(ioctl(fds, TIOCSCTTY, (char *)0)<0)
            err_sys("TIOCSCTTY error");
#endif
        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_sy("TIOCSWINSZ error on slave pty");
        }
        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;
    }
    else
    {
        *ptrfdm=fdm;
        retur pid;
    }

}

The pty_fork function

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值