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
exec() any command in C
提问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 *.txt
since it's typically the shellwhich expands these arguments. Passing that directly to execvp()
will result in a singleargument of literally *.txt
rather 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 exec
family of functions does not take a single string command line like system
does. 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 arguments
array 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. :)
这应该让你朝着正确的方向前进。:)