C语言中的重定向/管道错误
在这段代码中,我有两个主要问题 1:父级不等待子级打印,然后返回主级并打印。我包括了一个waitpid(),但它似乎没有按照我的预期工作C语言中的重定向/管道错误,c,redirect,piping,nano,C,Redirect,Piping,Nano,在这段代码中,我有两个主要问题 1:父级不等待子级打印,然后返回主级并打印。我包括了一个waitpid(),但它似乎没有按照我的预期工作 当我重定向时,我很好地创建了文件,但是nano和vim没有“看到”文件,但是Gedit可以(因此我知道我的输出被正确地发送) 此函数的流程: 输入一个字符串,检查该字符串是否有尾随&(如果存在,则删除该字符串并更新背景标志) 然后字符串在“|”上标记化 每个标记都在“”上标记 然后,其中的每个字符串都在“”上标记 根据上述标记化的结果重定向输出/输入,执行结果
每个标记都在“”上标记 然后,其中的每个字符串都在“”上标记 根据上述标记化的结果重定向输出/输入,执行结果字符**
void execute_command(char * s)
{
printf("\n");
int fd[3][2]; // since we are guaranteed each type of redirection will be used only once, I only need 3 pipes: < > and |
//int fd[2];
int res;
pid_t pid;
int status;
int stdin_c = dup(0);
int stdout_c = dup(1);
int i;
int background = 0;
for(i = 0; s[i] != '\0'; i++);
if(s[i-1] == '&')
{
background = 1;
s[i-1] = '\0';
}
char ** piped = token_pipe(s);
char ** left_a;
char ** right_a;
int output = 0;
int input = 0;
for(i = 0; piped[i] != NULL; i++)
{
left_a = token_leftarrow(piped[i]);
right_a = token_rightarrow(piped[i]);
if(left_a[1] != NULL)
{
free(piped[i]);
piped[i] = calloc(strlen(left_a[0]) + 1, sizeof(char));
strcpy(piped[i], left_a[0]);
fd[0][0] = open(left_a[1], O_RDONLY);
input = i;
}
if(right_a[1] != NULL)
{
free(piped[i]);
piped[i] = calloc(strlen(left_a[0]) + 1, sizeof(char));
strcpy(piped[i], right_a[0]);
fd[1][1] = open(right_a[1], O_WRONLY | O_CREAT, 0666);
output = i;
}
}
char ** spaced = token_space(piped[0]);
char ** spaced2 = NULL;
if(piped[1] != NULL)
{
spaced2 = token_space(piped[1]);
res = pipe(fd[2]);
if(res < 0)
{
printf("Pipe Failure\n");
exit(-1);
}// end if
}
if(fork() == 0)
{
if(background == 1)
setpgid(0, 0);
if(piped[1] != NULL)
{
close(fd[2][1]);
close(0);
dup(fd[2][0]);
if(output == 1 && right_a[1] != NULL)
{
dup2(fd[1][1], 1);
close(fd[1][1]);
}
execvp(spaced2[0], spaced2);
perror("Invalid Command");
exit(-1);
}
else
{
if(input == 0 || output == 0)
{
if(right_a[1] != NULL)
{
dup2(fd[1][1], 1);
close(fd[1][1]);
}
if(left_a[1] != NULL)
{
dup2(fd[0][0], 0);
close(fd[0][0]);
}
}
execvp(spaced[0], spaced);
perror("Invalid command\n");
exit(-1);
}
}
else
{
if(piped[1] != NULL)
{
if((pid = fork()) == 0)
{
close(fd[2][0]);
close(1);
dup(fd[2][1]);
if(input == 0 && left_a[1] != NULL)
{
dup2(fd[0][0], 0);
close(fd[0][0]);
}
execvp(spaced[0], spaced);
perror("Invalid Command");
exit(-1);
}
else
if(background == 0)
waitpid(pid, &status, WNOHANG);
}
else
if(background == 0)
wait(NULL);
close(fd[2][0]);
close(fd[2][1]);
close(fd[0][0]);
close(fd[1][1]);
dup2(stdin_c, 0);
dup2(stdout_c, 1);
}
}
void execute_命令(char*s)
{
printf(“\n”);
int fd[3][2];//因为我们保证每种类型的重定向只使用一次,所以我只需要3个管道:<>和|
//int-fd[2];
国际关系;
pid_t pid;
智力状态;
int stdin_c=dup(0);
int stdout_c=dup(1);
int i;
int背景=0;
对于(i=0;s[i]!='\0';i++);
如果(s[i-1]=='&')
{
背景=1;
s[i-1]='\0';
}
字符**管道=令牌管道;
字符**左a;
字符**右a;
int输出=0;
int输入=0;
对于(i=0;管道[i]!=NULL;i++)
{
left_a=令牌_leftarrow(管道[i]);
右箭头a=令牌右箭头(管道[i]);
if(左_a[1]!=NULL)
{
自由(管道[i]);
管道[i]=calloc(strlen(left_a[0])+1,sizeof(char));
strcpy(管道[i],左_a[0]);
fd[0][0]=打开(仅左箭头[1],右箭头);
输入=i;
}
if(right_a[1]!=NULL)
{
自由(管道[i]);
管道[i]=calloc(strlen(left_a[0])+1,sizeof(char));
strcpy(管道[i],右_a[0]);
fd[1][1]=开放(右a[1],O_WRONLY | O_CREAT,0666);
输出=i;
}
}
字符**间隔=令牌空间(管道[0]);
char**spaced2=NULL;
if(管道[1]!=NULL)
{
spaced2=令牌_空间(管道[1]);
res=管道(fd[2]);
如果(res<0)
{
printf(“管道故障”);
出口(-1);
}//如果结束
}
如果(fork()==0)
{
如果(背景==1)
setpgid(0,0);
if(管道[1]!=NULL)
{
关闭(fd[2][1]);
关闭(0);
dup(fd[2][0]);
if(输出=1&&right\u a[1]!=NULL)
{
dup2(fd[1][1],1);
关闭(fd[1][1]);
}
execvp(spaced2[0],spaced2);
perror(“无效命令”);
出口(-1);
}
其他的
{
如果(输入=0 | |输出=0)
{
if(right_a[1]!=NULL)
{
dup2(fd[1][1],1);
关闭(fd[1][1]);
}
if(左_a[1]!=NULL)
{
dup2(fd[0][0],0);
收盘(fd[0][0]);
}
}
execvp(间隔[0],间隔);
perror(“无效命令\n”);
出口(-1);
}
}
其他的
{
if(管道[1]!=NULL)
{
如果((pid=fork())==0)
{
收盘(fd[2][0]);
关闭(1);
dup(fd[2][1]);
if(输入=0&&left_a[1]!=NULL)
{
dup2(fd[0][0],0);
收盘(fd[0][0]);
}
execvp(间隔[0],间隔);
perror(“无效命令”);
出口(-1);
}
其他的
如果(背景==0)
waitpid(pid和状态,WNOHANG);
}
其他的
如果(背景==0)
等待(空);
收盘(fd[2][0]);
关闭(fd[2][1]);
收盘(fd[0][0]);
关闭(fd[1][1]);
dup2(标准值c,0);
dup2(stdout_c,1);
}
}
如果对代码进行了注释,这样我们就知道每个代码块要完成的任务,那么我们可以提供帮助。事实上,我看到(我认为)有很多糟糕的逻辑序列,就像一个简单的开始,对waitpid()的调用有WNOHANG参数,因此它不会等待子函数完成fork()函数有三种退出情况,而不仅仅是两种。也就是说,代码需要始终检查错误情况并考虑到它们,而不是假设一切正常——阅读系统功能描述可能会有所帮助。顺便说一句:有三个标准的文件描述符需要复制,stdin、stdout、stderrI对注释表示歉意,我将尝试不使用WNOHANG参数,在这种情况下我不关心stderr。