2013-03-23 145 views
0

我想创建自己的管道,就像在Unix终端(只是为了练习)。它应该在应用这样的报价来执行:将参数传递给execl

管道 “ls -l命令” 的 “grep” ......

我知道,我应该使用fork(),EXECL()( exec *)和api重定向stdin和stdout。但是,是否有任何execl的替代品,使用只包含应用程序路径和参数的一个参数来执行应用程序?有没有办法手动解析“ls -l”,但将其作为一个参数传递给execl?

+0

在SO上有很多与此密切相关的问题。从'相关'列表:['execl()'与'execv()'具有未知参数大小](http://stackoverflow.com/questions/13508115/execl-vs-execv-with-unknown-argument-size );该清单中还有其他可能相关的问题,以及该清单中没有相关的许多问题。 – 2013-03-23 12:04:40

回答

4

如果你只有一个命令行,而不是一个参数向量,让壳做解析为您提供:

execl("/bin/sh", "sh", "-c", the_command_line, NULL); 

当然,不要让不受信任的远程用户输入此命令行。但是,如果您处理的是不可信的远程用户输入,则应该尝试安排将实际的隔离参数列表传递给目标应用程序,正常情况下使用exec[vl]而不是命令行。

2

实际上,只有在编译时已知该命令的参数数量时,才能真正使用execl()。在shell中,您通常会使用execv()execvp()代替;这些可以处理要执行的命令的任意数量的参数。理论上,当给出命令的路径名称时使用execv(),而当它不是时,则使用execvp()(对命令执行基于PATH的搜索)。然而,execvp()处理'路径给定'的情况下,所以只需使用execvp()

因此,对于您pipeline命令,你会使用的东西等同于结束了一个孩子:

char *args_1[] = { "ls", "-l", 0 }; 
execvp(args_1[0], args_1); 

其他孩子最终会使用的东西等同于:

char *args_2[] = { "grep", "pattern", 0 }; 
execvp(args_2[0], args_2); 

除当然,你会从命令行参数中创建这些字符串,而不是如图所示的初始化。请注意,grep需要搜索模式。

您仍然需要解决管道问题。确保你关闭了足够多的管道文件描述符。当您将dup()dup2()管道连接到标准输入或标准输出时,可以关闭pipe()函数中的两个文件描述符。