简体   繁体   中英

Trying to figure out pty

I have been trying to create a pseudo terminal to communicate with mpg123 . From all my readings I believe I have written the code properly, but I can't figure out how I'm supposed to connect the master side (PTY) with the external program.

I get the first available master with posix_openpt , and enable the slave with grantpt and unlockpt . Then I get the PTS name with ptsname which can be used with open to get a file descriptor. Next, I replace STDIN, STDOUT and STDERR of PTY with dup2 . Then I can use that file descriptor to communicate with the PTY. But how does the master end connect to the external program that I wish to communicate with?

Here is my code so far:

#define _XOPEN_SOURCE 600
#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <termios.h>
#include <sys/wait.h>

int main (int argc, char *argv[])
{
    int fdm;
    int fds;
    pid_t pid;
    char *slave_name;
    char *program_name;

    program_name = basename(argv[0]);

    if(argc != 1)
    {
        fprintf(stderr, "usage: %s\n", program_name);
        exit(EXIT_FAILURE);
    }

    if((fdm = posix_openpt(O_RDWR)) == -1)
    {
        fprintf(stderr, "%s: posix_openpt failed (%s)\n", program_name, strerror(errno));
        exit(EXIT_FAILURE);
    }

    if(grantpt(fdm) == -1)
    {
        fprintf(stderr, "%s: grantpt failed (%s)\n", program_name, strerror(errno));
        close(fdm);
        exit(EXIT_FAILURE);
    }

    if(unlockpt(fdm) == -1)
    {
        fprintf(stderr, "%s: unlockpt failed (%s)\n", program_name, strerror(errno));
        close(fdm);
        exit(EXIT_FAILURE);
    }

    if((slave_name = ptsname(fdm)) == NULL)
    {
        fprintf(stderr, "%s: ptsname failed\n", program_name);
        close(fdm);
        exit(EXIT_FAILURE);
    }

    if((pid = fork()) == -1)
    {
        fprintf(stderr, "%s: fork failed (%s)\n", program_name, strerror(errno));
        close(fdm);
        exit(EXIT_FAILURE);
    }

    if(pid == 0)    // Child
    {
        if(setsid() == -1)
        {
            fprintf(stderr, "%s: setsid failed (%s)\n", program_name, strerror(errno));
            close(fdm);
            exit(EXIT_FAILURE);
        }

        if((fds = open(slave_name, O_RDWR)) == -1)
        {
            fprintf(stderr, "%s: open failed (%s)\n", program_name, strerror(errno));
            close(fdm);
            exit(EXIT_FAILURE);
        }

        close(fdm);

        if(dup2(fds, STDIN_FILENO) == -1)
        {
            fprintf(stderr, "%s: dup2(1) failed (%s)\n", program_name, strerror(errno));
            close(fds);
            exit(EXIT_FAILURE);
        }

        if(dup2(fds, STDOUT_FILENO) == -1)
        {
            fprintf(stderr, "%s: dup2(2) failed (%s)\n", program_name, strerror(errno));
            close(fds);
            exit(EXIT_FAILURE);
        }

        if(dup2(fds, STDERR_FILENO) == -1)
        {
            fprintf(stderr, "%s: dup2(3) failed (%s)\n", program_name, strerror(errno));
            close(fds);
            exit(EXIT_FAILURE);
        }

        close(fds);
        exit(EXIT_SUCCESS);
    }
    else        // Parent
    {
        wait(&pid);
    }

    exit(EXIT_SUCCESS);
}

I'm not looking for a hand out, just an explaination. How do I connect to mpg123? Where do I connect to mpg123, in the child or the parent?

Typically you would call execvp in the child to execute mpg123. You then communicate through the master file descriptor ( fdm ) which acts as the user of the terminal (TTYs are meant for human users).

Are you certain you need to use a pty for this? Most programs work fine with just normal pipes for stdin/stdout. Those you can create by calling pipe or sockerpair in the parent process. Even better, if you only need to read or only to write you can use popen which simplifies the interface a lot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM