【问题标题】:Trying to figure out pty试图弄清楚 pty
【发布时间】:2023-03-15 01:18:01
【问题描述】:

我一直在尝试创建一个伪终端来与mpg123 通信。从我所有的阅读中,我相信我已经正确编写了代码,但我无法弄清楚我应该如何将主端 (PTY) 与外部程序连接起来。

我使用posix_openpt 获得第一个可用的主服务器,并使用grantptunlockpt 启用从服务器。然后我得到带有ptsname 的PTS 名称,它可以与open 一起使用来获取文件描述符。接下来,我将 PTY 的 STDIN、STDOUT 和 STDERR 替换为dup2。然后我可以使用该文件描述符与 PTY 进行通信。但是主端如何连接到我想与之通信的外部程序呢?

到目前为止,这是我的代码:

#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);
}

我不是在寻求帮助,只是一个解释。如何连接到 mpg123?我在哪里连接到 mpg123,在子节点还是父节点?

【问题讨论】:

  • 我记得很久以前就玩过很多 PTY。如果我没记错的话,我通过编写标准script 程序的源代码编写了几个代码。这是一个简短的代码,很容易破解。

标签: c linux pty


【解决方案1】:

通常你会在子进程中调用 execvp 来执行 mpg123。然后,您通过充当终端用户的主文件描述符 (fdm) 进行通信(TTY 用于人类用户)。

您确定需要为此使用 pty 吗?大多数程序只使用标准输入/标准输出的普通管道就可以正常工作。您可以通过在父进程中调用pipesockerpair 创建。更好的是,如果您只需要阅读或只需要编写,您可以使用popen,这大大简化了界面。

【讨论】:

  • 我确实尝试过 popen。 stackoverflow.com/questions/33678441/…
  • 好吧,我仍然想知道是否没有比模拟人类用户更好的界面,但这不是我的决定。
  • 您的第一段是我完成任务所需要的。泰。
  • 还有其他几种方式可以与mpg123 通信。您可以使用 -R 创建一个 fifo 来发送命令,或者您可以尝试使用 libmpg123。我选择模拟人工输入的原因是使用其他两种方法,您必须不断读取输出以找到曲目的结尾。通过人工输入,我可以播放整个播放列表并使用前进和后退键,而无需知道 mpg123 的当前状态。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 2016-10-04
  • 2020-08-27
  • 2023-03-18
  • 1970-01-01
相关资源
最近更新 更多