2013-03-30 45 views
1

我有一個程序來命令從輸入,然後將其用execl(它必須是從execvp家庭功能)執行使用。現在,假設輸入行是in,我可以簡單地使用execl(allBeforeFirstSpaceFromIn, in);,還是必須將in分成較小的字符串?如果是這樣,我可以簡單地將所有空格更改爲\0分裂Unix命令用於與EXEC

+0

'NULL'爲空*指針*常量。你可能是指空字符''\ 0''。 –

+0

是的,對不起:) – Xyzk

+0

如果您已經閱讀我的答案,請再閱讀一次;我在最近幾分鐘內更新了幾次。 –

回答

4

所以你輸入一個字符串,是這樣的:

"/bin/cat file1 file2" 

不,你不能僅僅通過"/bin/cat"作爲一個參數execl,並"file1 file2"的另一種說法。這會導致/bin/cat嘗試打開名爲file1 file2的文件。您希望它打開兩個文件,即file1file2,這意味着您需要傳遞三個單獨的參數。

execl可能是不適合你在做什麼。這是一個可變的功能;要調用它,在編寫代碼時必須知道要傳遞給它的多少個參數。所以這個:

execl("/bin/cat", "file1", "file2"); 

應該工作,但是你不能從一個字符串建立這個調用。

你想用的execv*()功能之一代替。例如:

int execv(const char *path, char *const argv[]); 

argv參數是一個指向到指針到炭,其應指向char*元件的陣列,其中的每一個指向一個'\0'的第一個字符的第一個元素終止的字符串。

所以你必須建立指針數組,並初始化每一個指向一個字符串參數。

現在,如果你有一個包含字符串數組:

"/bin/cat file1 file2" 

一個辦法是用空字符來代替空格:

"/bin/cat\0file1\0file2\0" 

(去年\0已經在那裏了)。然後,您可以構建char*的數組,以便每個元素都指向數組的開頭或剛剛創建的'\0'字符之一。每個這樣的指針都是一個指向字符串的有效指針。

但我不一定會推薦這種方法。如果您的輸入字符串恰好包含單詞之間的多個空格(您可能希望將其視爲單個空格),或者您想要像擴展通配符那樣進行一些操作,那麼您將遇到問題。我建議你自己分配陣列並將適當的數據複製到它們中。通過重新使用輸入字符串而節省的空間是不值得的。

當然最簡單的方法是:

char command[] = "/bin/cat file1 file2"; 
system(command); 
exit(0); 

其傳遞命令字符串/bin/sh,這確實所有的工作適合你。但是,那麼你將不會學習如何使用exec*()函數,我認爲這是本練習的要點。

+0

如果該命令包含''',就像在'/ bin/echo「Hello World」'中一樣,它會被拆分成'/ bin/echo',''Hello'和'World''。 – David

+0

@DavidCzihak:是,它會 - 這是否是正確的做法取決於你的要求。通常,shell不會*在空白處分割命令行;'echo「hello world」'傳遞單個參數'hello world'(包括空間,但不包括引號)到echo命令,但我認爲這比OP現在要處理的要多。 –

+0

也許,但我認爲無論多麼明顯,都應該指出可能的陷阱。 – David

1

是的,你需要傳遞的參數作爲單獨的字符串。

對於execlX功能則需要每個參數作爲參數傳遞:

execl(prog, arg1, arg2,...); 

對於execvX功能需要傳遞c樣式字符串數組:

char **argv = /* ... */; 
argv[0] = "arg1"; 
argv[1] = "arg2"; 
execv(prog, args); 

要分割的輸入字符串可以使用strtok,或者只是做類似的事情:

char **argv = /* malloc stuff */; 
char *prev = in; 
cnt = 0; 
while (in[0]) { 
    if (in[0] == ' ') { 
    in[0] = 0; 
    argv[cnt++] = prev; 
    prev = in + 1; 
    } 
    in++; 
} 
argv[cnt++] = prev; 
argv[cnt] = NULL; 
1

基本上有兩種方法來調用EXEC,無論是由一個(EXECL)提供所有的參數的一個或提供的參數的陣列(execv)。

如果您提供一個長字符串,其所有參數用\0分隔exec不會理解其他參數在第一個之後存在。

所以你要麼

  • 使用EXECL和提供的參數列表,例如(...,在,在+ X,在+ Y,NULL)
  • 或進行各指向in元素(char *)字符串,in+x,陣列in+y,...,並使用execv

xy(...)是參數的長字符串中的索引,例如, in

command\0arg1\0arg2\0 
^0  ^8 ^13 

x是8和y是13你可以創建字符串

char *args[] = { in, in+x, in+y, NULL }; 

的數組,然後使用execvexecv(in, args);

+0

事實上,一個「所有參數以'\ 0'分隔的長字符串」不是一個字符串,它由第一個「\ 0」字符定義。例如,任何期望指向一個字符串的函數,如果你通過'echo \ 0hello \ 0world'''只會看到''echo「'。 (這基本上就是你說的。) –