我正在尝试使用ls | wc
或ls /tmp | wc -l
这样的管道处理命令,但我得到的是“wc:标准输入:错误的文件描述符”消息。这是我第一次做这样的事情。任何建议都会有所帮助。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
for(;;)
{
char *cmd, *splitcmd, *splinput, *splipip;
int i, j, nargc = 0, characters;
char **cmdArray;
char **splArray;
char **pipArray;
size_t bufsize = 1024;
int *pipefd;
int pipeArrCount;
pid_t pid, wpid;
int status = 0;
int count = 0;
int metro = 0;
char pr1[40], pr2[40], pr0[40];
char pi0[40], pi1[40], pi2[40];
char pip0[40], pip1[40], pip2[40];
int savestdoutfd = dup(fileno(stdout));
int savestdinfd = dup(fileno(stdin));
char *path;
path = getenv("PATH");
cmd = (char *)malloc(bufsize * sizeof(char));
characters = getline(&cmd, &bufsize, stdin);
printf("cmd == => %s characters == => %d \n", cmd, characters);
if (cmd[characters-1] == '\n')
{
cmd[characters-1]='\0';
characters--;
}
printf("cmd == => %s characters == => %d \n", cmd, characters);
cmdArray = (char**)malloc(bufsize * sizeof(char *) );
for (i = 0; i < bufsize; i++ )
{
cmdArray[i]=(char*)malloc(bufsize * sizeof(char ) );
}
splitcmd = strtok(cmd, "|");
printf(" cmd == == %s\n", cmd);
while((splitcmd))
{
strcpy(cmdArray[nargc], splitcmd);
if (cmdArray[nargc][(strlen(cmdArray[nargc]))-1] == ' ')
cmdArray[nargc][(strlen(cmdArray[nargc]))-1]='\0';
printf(" nargc == == %d cmdArray == =[ %s ] \n", nargc, cmdArray[nargc]);
nargc++;
splitcmd = strtok(NULL, "|");
}
strcpy(pr0, cmdArray[0]);
strcpy(pr1, cmdArray[1]);
strcpy(pr2, cmdArray[2]);
printf(" pr0 %s \n", pr0);
printf(" pr1 %s \n", pr1);
printf(" pr2 %s \n", pr2);
splArray = (char**)malloc(bufsize * sizeof(char *) );
for (i = 0; i < bufsize; i++ )
{
splArray[i]=(char*)malloc(bufsize * sizeof(char ) );
}
splinput = strtok(pr0, " ");
while((splinput))
{
strcpy(splArray[count], splinput);
if (splArray[count][(strlen(splArray[count]))-1] == ' ')
splArray[count][(strlen(splArray[count]))-1]='\0';
printf(" count == == %d splArray == =[ %s ] \n", count, splArray[count]);
count++;
splinput = strtok(NULL, " ");
}
strcpy(pi0, splArray[0]);
strcpy(pi1, splArray[1]);
strcpy(pi2, splArray[2]);
printf(" pi0 %s \n", pi0);
printf(" pi1 %s \n", pi1);
printf(" pi2 %s \n", pi2);
pipArray= (char**)malloc(bufsize * sizeof(char *) );
for (i = 0; i < bufsize; i++ )
{
pipArray[i]=(char*)malloc(bufsize * sizeof(char ) );
}
splipip = strtok(pr1, " ");
while((splipip))
{
strcpy(pipArray[metro], splipip);
if (pipArray[metro][(strlen(pipArray[metro]))-1] == ' ')
pipArray[metro][(strlen(pipArray[metro]))-1]='\0';
printf(" metro == == %d pipArray == =[ %s ] \n", metro, pipArray[metro]);
metro++;
splipip = strtok(NULL, " ");
}
strcpy(pip0, pipArray[0]);
strcpy(pip1, pipArray[1]);
strcpy(pip2, pipArray[2]);
printf(" pip0 %s \n", pip0);
printf(" pip1 %s \n", pip1);
printf(" pip2 %s \n", pip2);
pipefd=(int*)malloc(2 * nargc*sizeof(int));
printf(" nargc == = %d\n", nargc);
pipeArrCount = 2*(nargc-1);
printf("pipeArrCount == = %d\n", pipeArrCount);
//exit(0);
for(i = 0; i < pipeArrCount; i)
{
pipe(pipefd + i);
i = i + 2;
}
for(i = 0; i < nargc; i++)
{
if (i == 0)
{
if ((pid = fork()) == 0)
{
dup2(pipefd[2 * i+1], fileno(stdout));
for(j = 0; j < pipeArrCount; j++)
{
close(pipefd[j]);
}
if (count == 1 )
{
char *argv[] = {path, NULL};
execvp(pi0, argv);
for (i = 0; i < 100; i++)
{
free(cmdArray[i]);
}
free(cmdArray);
}
else if (count == 2)
{
char *argv[] = {pi0, pi1, NULL};
execvp(pi0, argv);
for (i = 0; i < 100; i++)
{
free(cmdArray[i]);
}
free(cmdArray);
}
else
{
char *argv[] = {pi0, pi1, pi2, NULL};
execvp(argv[0], argv);
for (i = 0; i < bufsize; i++)
{
free(cmdArray[i]);
}
free(cmdArray);
}
exit(0);
}
wait(&status);
dup2(savestdoutfd, fileno(stdout));
}
else
{
if (fork() == 0)
{
dup2(pipefd[2 * i-1], fileno(stdin));
for(j = 0; j < pipeArrCount; j++)
{
close(pipefd[j]);
}
dup2(savestdoutfd, fileno(stdout));
close(savestdoutfd);
if (metro == 1 )
{
char *argv[] = {pip0, NULL};
execvp(pip0, argv);
for (i = 0; i < 100; i++)
{
free(cmdArray[i]);
}
free(cmdArray);
}
else if (metro == 2)
{
char *argv[] = {pip0, pip1, NULL};
execvp(argv[0], argv);
for (i = 0; i < 100; i++)
{
free(cmdArray[i]);
}
free(cmdArray);
}
else
{
char *argv[] = {pip0, pip1, pip2, NULL};
execvp(argv[0], argv);
for (i = 0; i < 100; i++)
{
free(cmdArray[i]);
}
free(cmdArray);
}
dup2(savestdinfd, fileno(stdin));
close(savestdinfd);
exit(0);
}
}
}
for (j = 0; j < pipeArrCount; j++)
{
close(pipefd[j]);
}
while ((wpid = wait(&status)) > 0);
}
}
答案 0 :(得分:1)
您的问题可能是运营商优先级。在运行管道中命令的else
循环的for
子句中,您有:
dup2(pipefd[2 * i-1], fileno(stdin));
下标计算的间距是奇数;代码相当于:
dup2(pipefd[2*i - 1], fileno(stdin));
但是,该描述符是管道的写描述符,而不是读描述符,因此wc
在尝试从只写文件描述符中读取时会获得EBADF
。
有效的是:
dup2(pipefd[2 *(i-1)], fileno(stdin));
您应该使用STDIN_FILENO
代替fileno(stdin)
,类似STDOUT_FILENO
。
还有许多其他问题需要解决,但这会让你顺利。