我有一个程序从输入中获取命令,然后使用execl
执行它(它必须是来自execvp
系列的函数)。现在,假设输入行是in
,我可以简单地使用execl(allBeforeFirstSpaceFromIn, in);
,还是必须将in
分成更小的字符串?如果是这样,我可以简单地将所有空格更改为\0
吗?
答案 0 :(得分:4)
所以你的输入是一个单独的字符串,如:
"/bin/cat file1 file2"
不,您不能将"/bin/cat"
作为一个参数传递给execl
,而"file1 file2"
作为另一个参数传递。这会导致/bin/cat
尝试打开名为file1 file2
的文件。您希望它打开两个文件file1
和file2
,这意味着您需要传递三个单独的参数。
execl
可能不适合您正在做的事情。它是一种可变函数;要调用它,您必须在编写代码时知道 要传递给它的参数数量。所以这个:
execl("/bin/cat", "file1", "file2");
应该可以工作,但你不能从字符串构建该调用。
您想要使用其中一个execv*()
功能。例如:
int execv(const char *path, char *const argv[]);
argv
参数是一个指向char的指针,它应该指向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*()
函数,我认为这是本练习的重点。
答案 1 :(得分: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;
答案 2 :(得分:1)
基本上有两种方法可以调用 exec ,或者逐个提供所有参数( execl )或者提供一个参数数组( execv )。
如果你提供一个长字符串,所有参数都以\0
分隔,那么 将不会理解在第一个参数之后存在其他参数。
所以你要么
(char *)
字符串数组,每个元素指向in
,in+x
,in+y
,...,并使用 execv x
和y
(...)是参数的长字符串中的索引,例如in
正在
command\0arg1\0arg2\0
^0 ^8 ^13
x
为8,y
为13.你可以创建一个字符串数组
char *args[] = { in, in+x, in+y, NULL };
然后使用 execv execv(in, args);