我正在尝试在c中以及运行时创建自定义外壳程序
pwd | ./show
它将获取pwd输出并将其作为./show的命令行参数传递,并且必须使用管道。
我已阅读我可以找到的任何相关问题,但我无法使其正常工作。
到目前为止,我认为我已将输出成功定向到管道中,但是我不知道如何将其传递到./show。我一直在打印它,只是为了验证它是否通过管道。
if(option == 2){
getArgs(&A,args,directory,&size);
pipe(fd);
pid = fork();
if(!pid){
dup2(fd[1],STDOUT_FILENO); //output into pipe
close(fd[0]);
close(fd[1]);
com=args[0];
for(i=1;i<(size-2);i++){
com=concat(com," ");
com=concat(com,args[i]);
}
readCommand(args,directory,com,(size-1));
return 1;
}
close(fd[1]);
int nbytes = read(fd[0], foo, sizeof(foo));
printf("Output: (%.*s)\n", nbytes, foo);
}
exec发生在readCommand内部,所以在这里
void readCommand(char *args[10],char *directory,char *com, int i){
if(execl(directory, args[i],args[i+1], NULL)==-1){
execl("/bin/sh", "/bin/sh", "-c", com, NULL);
perror("execlp");
}
else{
execl(directory, args[0],args[1],args[2],args[3],args[4], NULL); //max number of args=4
perror("execlp");
}
}
我以前曾尝试使它与两个fork一起工作,但是后来我不确定我是否正确重定向了输出,并且似乎更难了。如果有帮助,我也可以包含该代码。
感谢您的帮助,我的截止日期为几个小时...
更新:阅读答案后,我更新了代码
if(option == 2){
getArgs(&A,args,directory,&size);
pipe(fd);
if (!fork()) {
pipe(fd);
if(!fork()) {
dup2(fd[1], 1);
close(fd[0]);
close(fd[1]);
execlp(args[0], args[0], NULL);
}
else {
dup2(fd[0], 0);
close(fd[0]);
close(fd[1]);
execlp(args[size-1], args[size-1], NULL);
}
}
wait(NULL);
}
现在我打印出一个空行,然后提示输入新命令。
答案 0 :(得分:0)
您需要派生两个进程,并在它们之间使用管道。您的外壳程序不应尝试读取或写入管道。
这是一个完整的示例,该示例对管道进行了硬编码以演示如何进行设置:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
char* producer="pwd";
char* consumer="./show";
int fds[2];
printf("Going to run the equivalent of '%s | %s'\n", producer, consumer);
// Create a child that will become the consumer
if (!fork()) {
pipe(fds);
// Create another child to be the producer
if(!fork()) {
// Set up stdout to be the pipe
dup2(fds[1], 1);
close(fds[0]);
close(fds[1]);
// Execute the producer
execlp(producer, producer, NULL);
} else {
// Set up stdin to be the pipe
dup2(fds[0], 0);
close(fds[0]);
close(fds[1]);
// Execute the consumer
execlp(consumer, consumer, NULL);
}
}
// Wait for the consumer to finish
wait(NULL);
printf("The pipeline is done, the \"shell\" is exiting\n");
}
这是show
的实现:
#!/bin/sh
echo "Here's the data $0 read: $(cat)"
这是来自真实外壳的结果:
$ pwd
/tmp
$ pwd | ./show
Here's the data ./show read: /tmp
这是运行此示例时的结果:
$ gcc foo.c -o foo && ./foo
Going to run the equivalent of 'pwd | ./show'
Here's the data ./show read: /tmp
The pipeline is done, the "shell" is exiting