8

用 C 语言说,我想调用execvp()任何字符串命令。命令可以是:

char command[] = "ls -l";
char command[] = "rm *.txt";
char command[] = "cat makefile";

我想把这个命令变量放在execvp(). 因此,exec()风味函数可以使用任何类型的任意命令运行。

我怎样才能做到这一点?谢谢。

注意:system()不允许。

4

5 回答 5

11

如果必须调用execvp(),则需要将这些字符串拆分为可执行名称和参数数组(第一个是程序的“名称”,最后一个是 NULL 指针)。

这意味着类似:

char cmd1[] = "ls";  char *args1[] = {"ls", "-l", NULL};
char cmd1[] = "rm";  char *args1[] = {"rm", "*.txt", NULL}; // but see
                                                            // globbing below.
char cmd1[] = "cat"; char *args1[] = {"cat", "makefile", NULL};

这是一个非常重要的练习,特别是如果您想允许引用、通配符、转义等。

引用意味着您必须小心使用以下命令:

rm "file with spaces.txt"

因为你不能简单地打破空格 - 你必须像 shell 一样解释命令中的项目。对空格进行简单的破坏将为您提供一个带有上述字符串三个参数的命令,而不是正确的一个。

通过 globbing,我的意思是你几乎肯定会遇到类似*.txt的问题,因为它通常是扩展这些参数的shell 。直接将其传递给execvp()将导致单个参数字面意思,*.txt而不是与当前目录中的所有文本文件匹配的多个参数。

引用意味着您必须处理以下事情:

ls -l "file with spaces and \" quote in it"

这将使您的解析器更加复杂。

不要误会我的意思,它可以做到,但使用system().

如果您仍在考虑走这execvp()条路,则必须:

  • 将字符串拆分为单独的标记(相当困难,因为您必须处理引号和转义)。
  • glob 所有参数,这意味着其中带有通配符的那些(并且只有那些没有因为引号内而被转义或保护的参数)被扩展为多个参数。
  • 构造参数数组,命令在前面,NULL 结尾。
  • 调用execvp()参数是该数组中的第一个元素和数组的地址。
于 2011-11-11T03:37:52.947 回答
5

不,exec函数系列不像那样采用单个字符串命令行system。相反,它使用argv-like 字符串数组:

char *command = "/path/to/command";
char *arguments[] = { "command", "first argument", "second argument", NULL };
execvp(command, arguments);

请注意,arguments数组中的第一个条目是命令本身,并且数组以 . 结尾NULL

你检查手册页了吗?

于 2011-11-11T03:37:54.703 回答
3

要使用任何 execve 风格的函数,您需要自己解析命令行并构建一个 argv 向量。这些函数采用 char**,其中最后一个元素为 null - 您需要为所有这些分配足够的内存。那么你的 execve 风格的调用应该可以工作。

(ps你没有提到任何关于fork的东西......)

于 2011-11-11T03:38:00.123 回答
1

您需要在这里做的是让 shell 解析命令。所以考虑一下:

/bin/sh -c 'rm *.txt'

这应该让你朝着正确的方向前进。:)

于 2011-11-11T05:46:50.607 回答
1

为了让“*”、“>”、“<”、“&”等内容正常工作,您需要执行“/bin/sh”并将命令行作为参数传入。所以,它归结为标记你的字符串。

于 2011-11-11T03:39:13.053 回答