Linux exec() C 中的任何命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8089351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 07:08:27  来源:igfitidea点击:

exec() any command in C

clinuxshellexecvp

提问by JJ Liu

Say in C, I want to call execvp()on any string command. Command can just be:

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

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

I want to put this command variable inside execvp(). So the exec()flavored function can just run with any kind of arbitrary command.

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

How can I do that? Thanks.

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

NOTE: system()is not allowed.

注意:system()不允许。

采纳答案by paxdiablo

If you haveto call execvp(), then you will need to split up those strings into an executable name and an array of arguments (the first being the "name" of the program and the last being a NULL pointer).

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

That means something like:

这意味着:

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};

This is a non-trivial exercise, especially if you want to allow for quoting, globbing, escaping and so forth.

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

Quoting means you'll have to be careful with commands like:

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

rm "file with spaces.txt"

in that you can't simply break on the spaces - you'll have to interpret items in the command much the same as the shell does. Simplistic breaking on spaces would give you a command with three arguments for that string above, rather than the correct one.

因为你不能简单地打破空格 - 你必须像 shell 一样解释命令中的项目。简单地打破空格会给你一个命令,上面那个字符串的三个参数,而不是正确的一个。

By globbing, I mean you'll almost certainly have problems with something like *.txtsince it's typically the shellwhich expands these arguments. Passing that directly to execvp()will result in a singleargument of literally *.txtrather than many arguments matching all the text files in your current directory.

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

Quoting means that you'll have to handle things like:

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

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

which will further complicate your parser.

这将使您的解析器进一步复杂化。

Don't get me wrong, it can be done, but it's probably a damn sight easier just using system().

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

If you're still thinking of going the execvp()route, you'll have to:

如果你还在考虑走这execvp()条路,你必须:

  • split the string into separate tokens (rather hard, since you have to handle quotes and escapes).
  • glob all the arguments, meaning that those with wildcards in them (and only ones that aren't escaped or protected by virtue of being inside quotes) are expanded into multiple arguments.
  • construct the argument array, with the command at the front and a NULL at the end.
  • call execvp()with the parameters being first element in that array and the address of the array.
  • 将字符串拆分为单独的标记(相当困难,因为您必须处理引号和转义符)。
  • glob 所有参数,这意味着那些带有通配符的参数(只有那些没有被转义或由于被引号保护的)被扩展为多个参数。
  • 构造参数数组,前面是命令,最后是 NULL。
  • 调用execvp()时参数是该数组中的第一个元素和该数组的地址。

回答by Some programmer dude

No, the execfamily of functions does not take a single string command line like systemdoes. Instead it uses an argv-like array of strings:

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

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

Note that the first entry in the argumentsarray is the command itself, and that the array is terminated by NULL.

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

Did you check the manual page?

你检查手册页了吗?

回答by Robert

To use any of the execve-style functions, you'll need to parse the command line yourself and build an argv vector. The functions take a char**, where the last element is null - you'll need to allocate enough memory for all this. Then your execve-style call should work.

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

(p.s. You haven't mentioned anything about fork...)

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

回答by Arvid

In order to have things like "*" ">", "<", "&" etc. to work, you need to execute "/bin/sh" and pass in your command line as arguments. So, it comes down to tokenizing your string.

为了让 "*" ">"、"<"、"&" 等东西工作,你需要执行 "/bin/sh" 并将你的命令行作为参数传递。因此,它归结为标记您的字符串。

回答by duskwuff -inactive-

What you need to do here is make the shell parse the command. So consider this:

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

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

That should get you going in the right direction. :)

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