Terminal 终端宽度IOCTL(当管道连接到以下位置时)

Terminal 终端宽度IOCTL(当管道连接到以下位置时),terminal,ioctl,less-unix,Terminal,Ioctl,Less Unix,我有一个使用 ioctl(file_descriptor_of_stdout, TIOCGWINSZ, &w); 获取终端宽度(用于打印阵列)。如果我直接在终端上运行我的程序,这工作得很好;然而,我经常通过较少的管道输出,用于分页和搜索。为了便于讨论,假设stderr也是通过管道传输的,所以我不能通过期望它实际到达终端来“欺骗” 现在,less本身确实考虑了终端的宽度——用于断开或切断线路。它不会以某种方式将此信息进一步传递给通过它传输的任何东西吗?您有多种选择: 有三个流(stdi

我有一个使用

ioctl(file_descriptor_of_stdout, TIOCGWINSZ, &w);
获取终端宽度(用于打印阵列)。如果我直接在终端上运行我的程序,这工作得很好;然而,我经常通过较少的管道输出,用于分页和搜索。为了便于讨论,假设stderr也是通过管道传输的,所以我不能通过期望它实际到达终端来“欺骗”


现在,less本身确实考虑了终端的宽度——用于断开或切断线路。它不会以某种方式将此信息进一步传递给通过它传输的任何东西吗?

您有多种选择:

  • 有三个流(stdin、stdout和stderr),您的程序可以使用
    isatty(fileno(stdin))
    等进行检查。重定向交互式程序的输出比重定向输入更常见,因此值得检查
  • 如果没有任何流是终端,则可以打开与每个交互进程关联的
    tty
    。这不一定是
    /dev/tty
    ,如运行在
    xterm
    中的shell的快速检查所示:
$ls-l/dev/tty;tty;ls-l`tty` crw rw rw-1根根目录5,3月10日15:46/dev/tty /dev/pts/1 crw--w---1 tom tty 136,3月1日10:16:09/dev/pts/1
  • POSIX记录了这个程序,这似乎是一个很好的开始。但是,您的程序必须从管道读取路径名(比应用于标准流的
    isatty
    稍微复杂一些)。文件还说

    当没有从标准输入读取输入时,应检查标准输入,以确定其是否为终端,如果是,则确定终端名称

    也就是说,如果程序的标准输入被重定向(不是终端),
    tty
    对查找真正的终端没有帮助。
    @einpoklum的评论提醒我POSIX还记录了库调用。顺便说一句,通常当一个程序通过一个特定的函数调用实现时,POSIX会记录该程序,说如果它使用该调用,它的行为“就好像”。但它并没有在
    tty
    中提到这一点

  • 如果没有标准流是终端,您可以尝试打开
    /dev/tty
    。如果您的程序不是交互式的,则可能会失败,例如在
    cron
    或后台运行。为了避免这似乎是一种奇怪的批评,偶尔会有人请求从
    cron
    打开X应用程序。同样,POSIX记录了

你能修改程序使用
/dev/tty
fd
而不是
stdout
的fd吗?@MarkSetchell:Hmm./dev/tty对于每个进程来说都是不同的,这取决于它在哪个终端上?是的,这是正确的。它针对每个进程。POSIX tty不是一个好的起点,它只是让
ttyname()
library调用并打印结果(我检查了源代码)。但是尝试所有3个文件描述符不是一个坏主意。 $ ls -l /dev/tty;tty;ls -l `tty` crw-rw-rw- 1 root root 5, 0 Mar 10 15:46 /dev/tty /dev/pts/1 crw--w---- 1 tom tty 136, 1 Mar 10 16:09 /dev/pts/1