繁体   English   中英

C,输入和管道中的外壳

[英]shell in C, input & pipes

我一直在用C制作一个迷你外壳,该外壳必须接收带有至少3个参数的命令,然后解析它们,然后应用fork()和exec(),如果您只按Enter,它应该再次打印提示。 它还必须接受多个管道,这就是我被卡住的地方。 这是我的代码

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>

int main(){

char command[50];
char* token;
char* param[50][50];
int i,j,k;


 while(1){
        printf("shell:~");
        fgets(command, sizeof(command), stdin);

        i=0,j=0;                        
        token = strtok(command," \n\0\t");      
    while(1){
        if(token==NULL) break;  
        else if(strcmp(token,"|")==0){
            param[i][j]=0;
            i = i+1;
            j=0;
            token = strtok(NULL," \n\0\t");
        }
        else{
            param[i][j]=token;                      
            token = strtok(NULL," \n\0\t");
            j = j+1;
        }
        }
        param[i][j]=0;

直到这里,每个人都能正常工作。

    pid_t pid1,pid2;
    int fd1[2],fd2[2];
    //int numpipe = i-1;

    pipe(fd1);
    pipe(fd2);
    int status;

    pid1 = fork();
    if(pid1==0){
        k=0;
        while(k<i+1){
            pid2 = fork();
            if(pid2==0){

                if(k==0){// if it is first
                    if(k==i){//and last one
                        execvp(param[k][0],param[k]);

                    }else{
                        dup2(fd1[1],STDOUT_FILENO);
                        close(fd1[0]);
                        execvp(param[k][0],param[k]);

                        }                       
                }else if(0<k<i){//if it is in the middle
                    if(k%2==0){ // position odd
                        dup2(fd2[0],STDIN_FILENO);
                        close(fd2[1]);
                        dup2(fd1[1],STDOUT_FILENO);
                        close(fd1[0]);
                        execvp(param[k][0],param[k]);
                    }else{ //position 
                        dup2(fd1[0],STDIN_FILENO);
                        close(fd1[1]);
                        dup2(fd2[1],STDOUT_FILENO);
                        close(fd2[0]);
                        execvp(param[k][0],param[k]);   
                    }   
                }else{//if it is lasts
                    if(k%2==0){
                        dup2(fd2[0],STDIN_FILENO);
                        close(fd2[1]);
                        execvp(param[k][0],param[k]);
                    }else{
                        dup2(fd1[1],STDIN_FILENO);
                        close(fd1[1]);
                        execvp(param[k][0],param[k]);
                    }
                }                                   
            }else{
                k++;
                wait(NULL);
            }
    }
}
    else{
        wait(NULL);
    }
}
return 0;
}

如果我仅使用1条命令,则代码效果很好,但是当我放置管道时,它无法获得输入,例如:

    shell:~ls -l
    total 112
    -rw-r--r-- 1 cristian cristian 72018 mar 28 13:25 (107315)proyecto1-SO2017-1.pdf
    -rw-rw-r-- 1 cristian cristian     0 abr  2 12:23 a.out
    -rw-rw-r-- 1 cristian cristian  1082 abr  1 23:47 reaspaldo2
    -rw-rw-r-- 1 cristian cristian  1217 abr  2 03:00 reaspaldo2.c
    -rw-rw-r-- 1 cristian cristian   962 abr  1 19:40 respaldo1
    -rw-rw-r-- 1 cristian cristian   636 abr  2 01:10 respaldo1.c
    -rwxrwxr-x 1 cristian cristian 13200 abr  2 12:35 shell
    -rw-r--r-- 1 cristian cristian  1984 abr  2 12:36 shell.c
    -rw-r--r-- 1 cristian cristian   807 mar 29 11:41 shell.c~
    shell:~ls -l | wc
    wc: 'standard input': Bad file descriptor
          0       0       0
    shell:~

它与STDIN_FILE有关,但是我也不能很好地实现管道和fork。

将您的问题减少到最小的可重现情况:

#include <unistd.h>
#include <stdio.h>

int main(void) 
{
        char *argv[] = {"wc", NULL};
        int fd1[2];
        pipe(fd1);
        dup2(fd1[1],STDIN_FILENO); /* Wrong end of the pipe !! */
        close(fd1[1]);
        execvp(argv[0], argv);
        perror(argv[0]);
        return 1;
}

问题是fd1[1]是管道的写端,但是wc试图从中读取。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM