Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
exec()是C语言中的任意命令_C_Linux_Shell_Execvp - Fatal编程技术网

exec()是C语言中的任意命令

exec()是C语言中的任意命令,c,linux,shell,execvp,C,Linux,Shell,Execvp,比如在C语言中,我想对任何字符串命令调用execvp()。命令可以是: char command[] = "ls -l"; char command[] = "rm *.txt"; char command[] = "cat makefile"; 我想将此命令变量放入execvp()中。因此exec()风味函数可以使用任意命令运行 我该怎么做?谢谢 注意:system()是不允许的。如果必须调用execvp(),则需要将这些字符串拆分为可执行名称和参数数组(第一个是程序的“名称”,最后一个是空

比如在C语言中,我想对任何字符串命令调用
execvp()
。命令可以是:

char command[] = "ls -l";
char command[] = "rm *.txt";
char command[] = "cat makefile";
我想将此命令变量放入
execvp()
中。因此
exec()
风味函数可以使用任意命令运行

我该怎么做?谢谢

注意:
system()
是不允许的。

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

这意味着:

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()
    ,参数为该数组中的第一个元素和数组的地址

否,
exec
函数系列不像
system
那样使用单个字符串命令行。相反,它使用类似于argv的字符串数组:

char *command = "/path/to/command";
char *arguments[] = { "command", "first argument", "second argument", NULL };
execvp(command, arguments);
请注意,
arguments
数组中的第一个条目是命令本身,数组以
NULL
终止


您是否查看了手册页面?

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


(P.S.你没有提到任何关于叉子…)

为了得到像“*”“>”之类的东西,你需要做的是让shell解析命令。所以考虑一下:

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

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

为什么不允许使用
system()
“大概是因为他在上操作系统课,他们不允许吗?是的,作业中最后一件事我想不出来。显然,这是作业。”。以后请这样标记。虽然使用
/bin/sh
很方便,但他的作业规则明确规定“no
system(3)
”,这实际上与no
/bin/sh
/相同。很抱歉,麻烦了,我不得不问我是否可以使用
/bin/sh
。如果我使用
/bin/sh
,我可以做
char*const parmList[]={“sh”,“ls-l”,NULL};execvp(“/bin/sh”,parmList)但它似乎不正确。语法错误?应该是
char*const parmList[]={“sh”、“-c”、“ls-l”、NULL};execvp(“/bin/sh”,parmList)是的,我的代码中有fork。我想我必须解析字符串。谢谢。是的,很遗憾。这就是shell所做的,真的,因为要处理的事情太多了是的,你说的是
char*command=“/path/to/command”我可以只做
char*command=“command”
在所有可能的情况下?这是否意味着如果我实现一个以null结尾的字符串数组
{“rm”、“*foo”、“*bar”}
,则
execvp
应该执行
“*foo”
“*bar”
的所有匹配组合?比如说,组合应该是
rm*foo[0]*foo[n-1]*bar[0]*bar[n-1]
。或者,它不是嵌套循环中的
execvp
,而是包含扩展(全局)参数的单个命令。比如说,
{rm,afoo,bfoo,abar,…,NULL}