C:从Stdin读取重置终端属性?

时间:2015-04-04 16:10:09

标签: c unix

我正在开发一个类似于Unix的“更多”命令的C项目。就像“更多”一样,这个程序应该能够从文件(如果指定)或stdin获取其输入(如果没有给出文件)(因此其他程序的输出可以通过管道输入)并将其显示到stdout。也喜欢“更多”,应该禁用回声和规范模式,我已经用以下代码完成了:

  //change terminal attributes
  tcgetattr(0, &info); //Get info
  tcgetattr(0, &orig_inf); //Save original info
  info.c_lflag &= ~ECHO; //Disable echo
  info.c_lflag &= ~ICANON; //Disable canonical mode
  info.c_cc[VMIN] = 1; //Get 1 char at a time
  tcsetattr(0, TCSANOW, &info); //Set attributes

要从键盘读取用户命令,我显式打开“dev / tty”而不是只读取stdin:

//Open cmd stream
if((cmd = fopen("/dev/tty", "r")) == NULL){
  perror("Failure opening command stream");
  tcsetattr(0, TCSANOW, &orig_inf);
  exit(EXIT_FAILURE);
}

用getc(cmd)读取它们。当用户提供要读取的文件时,这可以正常工作,但如果程序正在从stdin接收输入,则似乎正在重置终端属性。我可以看到我尝试输入的每个命令(这意味着回显再次打开)并且命令不会被发送到程序,除非我点击输入(意味着规范模式已经以某种方式再次被重新激活)。我搜索了网络和所有手册页几乎所有我正在使用的系统调用,似乎无法找到原因。

如果有人知道为什么会发生这种情况以及如何解决这个问题,那将非常感谢帮助。

谢谢!

1 个答案:

答案 0 :(得分:3)

似乎缺少的内容(至少在问题中未说明)是您正在打开/dev/tty来读取命令,并通过文件描述符重置原始标准输入。但是没有提到使用fdreopendup2

  • 因为您指的是文件描述符0(FILENO_STDIN),这与fileno(cmd)不是同一个文件描述符 - 除非您使用dup2替换它。
  • 通常会使用open而不是fopen打开设备,因为open可以更好地控制流程。然后,可以使用fdreopen从文件描述符中获取缓冲流。
例如,

fopen上使用/dev/tty,您可能忽略了 流中的实际设置,这些设置不一定与您在文件中重新配置的设置相同描述符0。相关问题可能是:What is the difference between stdin and STDIN_FILENO?