为什么这个linux伪终端程序不起作用?

时间:2016-01-10 03:37:45

标签: c linux unix terminal posix

Master从stdin读取输入并写入pty-master,slave从pty-slave读取输入并写入stdout。

但是这个代码/程序似乎不起作用。 主写入pty-master是正常的,但是当从pty-slave读取时,从属挂起。

谁能帮帮我? thx提前。

#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

/*
 * copy from apue
 */
int ptym_open(char *pts_name, int pts_namesz)
{
    char *ptr;
    int fdm, err;
    if ((fdm = posix_openpt(O_RDWR)) < 0) {
        assert(0);
        return -1;
    }
    if (grantpt(fdm) < 0) {
        assert(0);
        return -1;
    }
    if (unlockpt(fdm) < 0) {
        assert(0);
        return -1;
    }
    if ((ptr = ptsname(fdm)) == NULL) {
        assert(0);
        return -1;
    }
    strncpy(pts_name, ptr, pts_namesz);
    pts_name[pts_namesz - 1] = 0;
    printf("pts_name:%s\n", pts_name);
    return fdm;
}

int ptys_open(char *pts_name)
{
    int fds;
    if ((fds = open(pts_name, O_RDWR)) < 0) {
        return -1;
    }
    return fds;
}

int pty_fork(int *ptrfdm, char *slave_name, int slave_namesz)
{
    int fdm, fds;
    pid_t pid;
    char pts_name[1024];
    if ((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0) {
        assert(0);
        return -1;
    }
    if (slave_name != NULL) {
        strncpy(slave_name, pts_name, slave_namesz);
        slave_name[slave_namesz - 1] = 0;
    }
    if ((pid = fork()) < 0) {
        assert(0);
        return -1;
    } else if (pid == 0) {
        if (setsid() < 0) {
            assert(0);
        }
        if ((fds = ptys_open(pts_name)) < 0) {
            assert(0);
        }
        close(fdm);
        if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) {
            assert(0);
        }
        //if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) {
        //  assert(0);
        //}
        //if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) {
        //  assert(0);
        //}
        if ((fds != STDIN_FILENO) && (fds != STDOUT_FILENO) && (fds != STDERR_FILENO)) {
            close(fds);
        }
        return 0;
    } else {
        *ptrfdm = fdm;
        return pid;
    }
}

int loop(int ptym)
{
    pid_t pid;
    int nread;
#define BUFFSIZE 512
    char buf[BUFFSIZE];

    if ((pid = fork()) < 0) {
        assert(0);
    } else if (pid == 0) {
        while (1) {
            if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0) {
                int errr = errno;
                printf("%s\n", strerror(errr));
                assert(0);
            } else if (nread = 0) {
                break;
            }
            if (write(ptym, buf, nread) != nread) {
                int errr = errno;
                printf("%s\n", strerror(errr));
                assert(0);
            }
            fsync(ptym);
        }
        exit(0); // child
    }

    while (1) {
        if ((nread = read(ptym, buf, BUFFSIZE)) <= 0) {
            printf("%d break read\n", getpid());
            break;
        }
        if (write(STDOUT_FILENO, buf, nread) != nread) {
            assert(0);
        }
    }
}

int main(void)
{
    int fdm;
    char slave_name[1024];
    pid_t pid = pty_fork(&fdm, slave_name, sizeof(slave_name));
    if (pid < 0) {
        assert(0);
    } else if (pid == 0) {
        int nread;
        char buf[1024];
        while(1){
            if ((nread = read(STDIN_FILENO, buf, 3)) < 0) {
                break;
            }
            printf("buf:%s\n", buf);
        }
    } else {
        printf("child:%d@%s\n", pid, slave_name);
        loop(fdm);
    }
    return 0;
}

1 个答案:

答案 0 :(得分:1)

除了打开伪终端外,您还必须对其进行初始化(称为线路规则)。我在你的例子中没有看到任何相关内容。您可以与执行此操作的luit进行比较(例如,查看openTty中的sys.c函数)。

进一步阅读: