2015-04-04 69 views
2

我正在開發一個類似Unix的「更多」命令的C項目。像「更多」一樣,如果沒有給出文件(因此可以將其他程序的輸出傳送給它)並將其顯示到標準輸出,則該程序應該能夠從文件(如果指定)或標準輸入中獲得輸入。另外像「更多」,呼應和規範模式都應該被禁止,我已經用下面的代碼完成:C:從Stdin讀取重置終端屬性?

//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 

讀取從鍵盤,我打開「開發/ 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接收輸入,似乎終端屬性被重置。我可以看到我嘗試鍵入的每個命令(這意味着再次顯示回顯),並且命令不會發送到程序,除非我按下Enter鍵(意味着規範模式已經以某種方式再次被重新激活)。我在網上搜索了幾乎所有的系統調用手冊,並且似乎無法找到原因。

如果有人知道爲什麼會發生這種情況,以及如何解決它,幫助將不勝感激。

謝謝!

+1

你的評論說「改變終端屬性」,但這不是你在做什麼。您正在更改文件描述符零的屬性,當您將標準輸入重定向爲從文件中讀取時,它不是終端! – 2015-04-04 16:45:02

+0

您應該檢查'tcgetattr()'和'tcsetattr()'的返回值。您不會說代碼是通過文件('yourprog 2015-04-04 17:18:31

回答

3

什麼似乎缺失(至少在問題中沒有說明)是,您打開/dev/tty來讀取命令,並通過文件描述符重置原始標準輸入。但沒有提及使用fdreopendup2的:

  • ,因爲你是指文件描述符0(FILENO_STDIN),這是不一樣的文件描述符fileno(cmd) - 除非你使用dup2來替換。
  • 通常會使用open而不是fopen打開設備,只是因爲open提供了對該過程的更多控制。然後使用fdreopen從文件描述符中獲取緩衝流。

使用上/dev/ttyfopen,例如,你可能已經在流,這是不一定相同,你文件描述符0重新忽視的實際設置。相關的問題可能是:What is the difference between stdin and STDIN_FILENO?