2013-03-23 143 views
0

我想創建自己的管道,就像在Unix終端(只是爲了練習)。它應該在應用這樣的報價來執行:將參數傳遞給execl

管道 「ls -l命令」 的 「grep」 ......

我知道,我應該使用fork(),EXECL()( exec *)和api重定向stdin和stdout。但是,是否有任何execl的替代品,使用只包含應用程序路徑和參數的一個參數來執行應用程序?有沒有辦法手動解析「ls -l」,但將其作爲一個參數傳遞給execl?

+0

在SO上有很多與此密切相關的問題。從'相關'列表:['execl()'與'execv()'具有未知參數大小](http://stackoverflow.com/questions/13508115/execl-vs-execv-with-unknown-argument-size );該清單中還有其他可能相關的問題,以及該清單中沒有相關的許多問題。 – 2013-03-23 12:04:40

回答

4

如果你只有一個命令行,而不是一個參數向量,讓殼做解析爲您提供:

execl("/bin/sh", "sh", "-c", the_command_line, NULL); 

當然,不要讓不受信任的遠程用戶輸入此命令行。但是,如果您處理的是不可信的遠程用戶輸入,則應該嘗試安排將實際的隔離參數列表傳遞給目標應用程序,正常情況下使用exec[vl]而不是命令行。

2

實際上,只有在編譯時已知該命令的參數數量時,才能真正使用execl()。在shell中,您通常會使用execv()execvp()代替;這些可以處理要執行的命令的任意數量的參數。理論上,當給出命令的路徑名稱時使用execv(),而當它不是時,則使用execvp()(對命令執行基於PATH的搜索)。然而,execvp()處理'路徑給定'的情況下,所以只需使用execvp()

因此,對於您pipeline命令,你會使用的東西等同於結束了一個孩子:

char *args_1[] = { "ls", "-l", 0 }; 
execvp(args_1[0], args_1); 

其他孩子最終會使用的東西等同於:

char *args_2[] = { "grep", "pattern", 0 }; 
execvp(args_2[0], args_2); 

除當然,你會從命令行參數中創建這些字符串,而不是如圖所示的初始化。請注意,grep需要搜索模式。

您仍然需要解決管道問題。確保你關閉了足夠多的管道文件描述符。當您將dup()dup2()管道連接到標準輸入或標準輸出時,可以關閉pipe()函數中的兩個文件描述符。