2011-12-14 38 views
10

我有以下示例程序:execve(「/ bin/sh」,0,0);在管道

#include <stdio.h> 

int 
main(int argc, char ** argv){ 
    char buf[100]; 

    printf("Please enter your name: "); 
    fflush(stdout); 
    gets(buf); 
    printf("Hello \"%s\"\n", buf); 

    execve("/bin/sh", 0, 0); 
} 

我,當我運行沒有它的作品,因爲它應該任何管道,並返回一個sh PROMT:

bash$ ./a.out 
Please enter your name: warning: this program uses gets() which is unsafe. 
testName 
Hello "testName" 
$ exit 
bash$ 

但這不起作用在管道中,我想我知道這是爲什麼,但我無法找出解決方案。示例運行波紋管。

bash$ echo -e "testName\npwd" | ./a.out 
Please enter your name: warning: this program uses gets() which is unsafe. 
Hello "testName" 
bash$ 

我估計這事做與gets/bin/sh收到EOF和promtly沒有一條錯誤信息退出這樣的方式清空stdin的事實。

但是我怎樣才能解決這個問題(如果可能的話,不要修改程序,如果不能刪除gets),這樣即使我通過管道提供輸入,我也能得到一個提示?

P.S.我在一臺FreeBSD(4.8)機器上運行這個程序DS

+6

***從不使用`gets`。它總是**打開緩衝區溢出安全漏洞。 – ThiefMaster 2011-12-14 17:53:21

+5

我知道;)...這是我大學安全實驗室計算機上緩衝區溢出嘗試的一部分。純粹的學術。 = D – 2011-12-14 17:58:15

回答

10

你可以不喜歡這個任何修改運行程序:

(echo -e 'testName\n'; cat) | ./a.out 

這樣可以確保你的程序的標準輸入後不什麼echo輸出端。相反,cat將繼續爲您的程序提供輸入。隨後輸入的來源是您的終端,因爲這是cat讀取的地方。

下面是一個例子會話:

bash-3.2$ cc stdin_shell.c 
bash-3.2$ (echo -e 'testName\n'; cat) | ./a.out 
Please enter your name: warning: this program uses gets(), which is unsafe. 
Hello "testName" 
pwd 
/home/user/stackoverflow/stdin_shell_question 
ls -l 
total 32 
-rwxr-xr-x 1 user group 9024 Dec 14 18:53 a.out 
-rw-r--r-- 1 user group 216 Dec 14 18:52 stdin_shell.c 
ps -p $$ 
    PID TTY   TIME CMD 
93759 ttys000 0:00.01 (sh) 
exit 

bash-3.2$ 

注意,由於殼的標準輸入不連接到一個終端,sh認爲它不是交互執行,因此不顯示提示。不過,您可以正常輸入命令。

+0

啊..是的,你是對的,(我確實設法在看到你的帖子之前找到這個解決方案,但是謝謝你把它放在這裏)。 – 2011-12-14 18:20:53

1

不是100%確定的(使用精確的shell和操作系統可能會引發這些問題;我相信FreeBSD默認使用GNU bash作爲/bin/sh? ),但是

  • sh可能正在檢測到其輸入不是tty。

  • 你的sh版本可能會進入非交互模式一樣,也好象叫爲sh,預計login會在前面加上一個-argv[0]它。設置execve ("/bin/sh", { "-sh", NULL}, NULL)可能會說服它正在作爲登錄shell運行。
3

使用execve("/bin/sh", 0, 0);對殼來說是一種殘忍和不尋常的懲罰。它根本沒有任何參數或環境 - 甚至沒有自己的程序名稱,甚至沒有像PATH或HOME這樣的強制性環境變量。