如何检测分配的终端设备进行交互式工作

Pav*_*ule 5 c unix tty pty

我正在写寻呼机pspg.我必须解决以下问题.读完之后,stdin我应该stdin从之前的阅读管道重新分配到终端阅读.

我用了

freopen("/dev/tty", "r", stdin) 
Run Code Online (Sandbox Code Playgroud)

但是,当从命令中使用寻呼机时,它不起作用

su - someuser -c 'export PAGER=pspg psql somedb'
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我收到一个错误:没有这样的设备或地址.

我找到了一个解决方法 - 现在,代码看起来像:

if (freopen("/dev/tty", "r", stdin) == NULL)
{
    /*
     * try to reopen pty.
     * Workaround from:
     * https://cboard.cprogramming.com/c-programming/172533-how-read-pipe-while-keeping-interactive-keyboard-c.html
     */
    if (freopen(ttyname(fileno(stdout)), "r", stdin) == NULL)
    {
        fprintf(stderr, "cannot to reopen stdin: %s\n", strerror(errno));
        exit(1);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,检测分配的终端设备的正确方法是什么?

但这种解决方法不正确.它解决了一个问题,但接下来就要来了.当某个用户与当前用户不同时,重新打开失败,并显示" 权限被拒绝"错误.因此,此解决方法不能用于我的目的.

小智 2

在这种情况下,会less回退到 fd 2 (stderr)。如果 stderr 已从 tty 重定向,它会放弃尝试获取键盘输入,而只打印整个输入流而不进行分页。

的设计su不允许有任何更好的事情。新用户正在原始用户拥有的 tty 上运行命令,而这个令人不快的事实无法完全隐藏。

这是一个很好的替代品,su没有这个问题:

ssh -t localhost -l username sh -c 'command'
Run Code Online (Sandbox Code Playgroud)

当然,它有更多的开销。