Problema com comandos de tubulação em c
Pergunta
Estou tentando criar um shell simples em C para o Unix. Consegui fazer toda a análise de comandos e execução, mas estou tendo um problema com a tubulação. Eu acho que o problema é que não estou conectando o tubo correto para a entrada do segundo comando.
Por exemplo, se eu digitar "LS | WC", ele fará uma pausa após o comando "WC", que eu acho que é porque está esperando a entrada. Eu acho que o problema é quando eu uso o DUP2 (lendo [i], 0), e não está entrando no tubo correto.
Eu sei que isso é uma pergunta ampla, mas se houver algum débito que eu pudesse obter, eu apreciaria. Aqui está o código que cria novos processos e tenta tubá -los.
int fileds[2];
int reading[num_cmds];
int writing[num_cmds];
int p;
for(p=0; p < num_cmds; p++)
{
reading[p] = -1;
writing[p] = -1;
}
int j;
for(j=0; j < num_cmds-1; j++) //Create pipes for commands
{
int fileds[2];
pipe(fileds);
reading[j+1] = fileds[0];
writing[j] = fileds[1];
}
int i = 0;
for(i = 0; i < num_cmds;i++)
{
cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); //Get command and args
pid_t childpid;
int status;
childpid=fork();
if (childpid >= 0)
{
if (childpid == 0)
{
if(writing[i] != -1)
{
dup2(writing[i],1);
close(writing[i]);
}
if(reading[i] != -1)
{
dup2(reading[i],0);
close(reading[i]);
}
int h;
for(h = 0; h < num_cmds; h++)
{
close(writing[h]);
close(reading[h]);
}
if(execvp(cmd_args[0],cmd_args) == -1)
{
perror("Problem with command");
exit(0);
}
}
else
{
wait(&status);
int m;
for(m = 0; m < num_cmds; m++)
{
if( writing[m] != -1) close(writing[m]);
if( reading[m] != -1) close(reading[m]);
}
}
}
else
{
perror("fork");
continue;
}
input_file[0] = 0;
output_file[0] = 0;
run_bg = 0;
}
}
ATUALIZAÇÃO: Consegui descobrir, graças a Richard. Foi uma combinação de fechar os descritores de arquivo na ordem errada e não fechar alguns. Aqui está o código de trabalho.
int fileds[2];
int reading[num_cmds];
int writing[num_cmds];
int p;
for(p=0; p < num_cmds; p++)
{
reading[p] = -1;
writing[p] = -1;
}
int j;
for(j=0; j < num_cmds-1; j++)
{
int fileds[2];
pipe(fileds);
reading[j+1] = fileds[0];
writing[j] = fileds[1];
}
int i = 0;
for(i = 0; i < num_cmds;i++)
{
cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg);
pid_t childpid;
int status;
childpid=fork();
if (childpid >= 0)
{
if (childpid == 0)
{
if(writing[i] != -1)
{
close(1);
dup2(writing[i],1);
}
if(reading[i] != -1)
{
close(0);
dup2(reading[i],0);
}
if(execvp(cmd_args[0],cmd_args) == -1)
{
perror("Problem with command");
exit(0);
}
}
else
{
wait(&status);
close(writing[i]);
if(i > 0)
{
close(reading[i]);
}
}
}
else
{
perror("fork");
}
input_file[0] = 0;
output_file[0] = 0;
run_bg = 0;
}
Solução
Acho que seu problema pode ser que você aguarde cada processo dentro do loop e, em seguida, feche todos os descritores de arquivo. Isso torna os descritores de arquivo inválidos para a próxima chamada para Dup2 () e resulta em Stdin para o próximo processo permanecendo inalterado.
Apenas um palpite, eu não executei o código.
Outras dicas
Quando eu digito "LS | WC", o WC faz o esperado e imprime o número de palavras em saída pelo comando LS. Lembre -se de que quando você está tubulando comandos usando "|" Você não precisa criar tubos em seu aplicativo. O primeiro comando precisa emitir para Stdout e o segundo comando precisa ler essa saída do padrão in.