2010-02-02 77 views
1

我正在嘗試編寫一個應用程序,它可以通過使用僞終端以密碼登錄到SSH。但是,如果我將()寫入主設備,那麼數據不會在從設備中出現。這裏有一個簡單的測試用例:子進程無法從創建的僞終端讀取

#include <sys/wait.h> 
#include <sys/types.h> 
#include <stdio.h> 
#include <unistd.h> 
#ifdef __linux__ 
    #include <pty.h> 
#else 
    #include <util.h> 
#endif 

int 
main() { 
    int master; 
    pid_t pid = forkpty(&master, NULL, NULL, NULL); 
    if (pid == 0) { 
     int ch; 
     read(0, &ch, 1); 
     _exit(1); 
    } else { 
     printf("Press Enter to send a byte.\n"); 
     getchar(); 
     write(master, "1", 1); 
     printf("Done. Waiting for process to exit...\n"); 
     waitpid(pid, NULL, 0); 
     return 0; 
    } 
} 

該應用程序將首先輸出「按Enter鍵發送一個字節」。按Enter後,我期望子進程的read()返回。但是read()似乎無限地阻塞,即使master的write()成功了,所以master在waitpid()上永遠等待。這是怎麼回事?

+0

我不確定你在用什麼,但是我會用'expect'這樣的東西。它在大多數發行版上都可用。 http://expect.nist.gov/ – 2010-02-02 19:02:52

+0

我正在編寫的應用程序將分發給可能沒有「期望」或可能不想安裝它的用戶。除此之外,我還想知道如何做僞終端,以防將來需要它們用於其他任何事情。 – Hongli 2010-02-02 19:08:34

+0

試試這個:寫(master,「1 \ n」,2); – sambowry 2010-02-02 19:25:36

回答

2

問題是你沒有修改PTY的行紀律。默認的行規則是面向行的,所以在讀取換行符之前,不會有任何輸入發送到從屬進程。 (您可以通過發送一個「\ n」給從機而不是「1」來看到這一點)。您可以在子進程中通過調用tcgetattr,cfmakerawtcsetattr來運行PTY RAW模式,如下所示:

if (pid == 0) { 
     int ch; 
     struct termios t; 
     tcgetattr(0, &t); 
     cfmakeraw(&t); 
     tcsetattr(0, TCSANOW, &t); 
     read(0, &ch, 1); 
     _exit(1); 
    } else { 

這似乎適用於我。

1

this blog post的示例代碼應該可能有幫助。作者給出了一個可用的spawn (char *argv[]);函數的更新(與您的原始問題非常相似)。