我想在Unix终端中创建自己的管道(只是为了练习)。它应该使应用程序在这样的引号中执行:
管道“ls -l”“grep”....
我知道我应该使用fork(),execl()(exec *)和api重定向stdin和stdout。但有没有替代execl使用一个参数执行带有参数的应用程序,其中包含应用程序路径和参数?有没有办法不手动解析“ls -l”,而是将其作为一个参数传递给execl?
答案 0 :(得分:4)
如果你只有一个命令行而不是参数向量,那么让shell为你做解析:
execl("/bin/sh", "sh", "-c", the_command_line, NULL);
当然,不要让不受信任的远程用户输入到此命令行。但是,如果您要处理不受信任的远程用户输入,那么您应该尝试按照exec[vl]
的正常用法,将实际的隔离参数列表传递给目标应用程序,而不是命令行。
答案 1 :(得分:2)
实际上,只有在编译时知道命令的参数个数时,才能真正使用execl()
。在shell中,您通常会使用execv()
或execvp()
代替;这些可以处理要执行的命令的任意数量的参数。理论上,在给出命令的路径名时使用execv()
,而在{1}}(对命令执行基于PATH的搜索)时使用execvp()
。但是,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()
函数中的两个文件描述符。