myshell(支持管道)

首先总结一下思路:

1. 如果要支持管道就首先需要分析命令中是否包含管道。(使用stringcmp函数)

2.如果包含管道就将管道符号位置为NULL,然后将管道符号前后的命令分到两个指针数组中 即:tmp1[ ]和tmp2[ ]

3.这个时候需要执行两个execvp函数,我们为了保证循环的进程不会被替换,需要fork两次,分别用孙子进程执行tmp1[ ]和子进程执行tmp2[ ]。

4.关于管道创建的位置(很关键),创建的位置要在儿子进程中,并且在孙子进程创建之前。(在其他位置会发生不知名错误)。

父进程等待就行了。

以下是代码

#include
#include
#include
#include
#include
#include
#include
#include

 
void do_parse(char *buf,char* argv[])
  {
    if(buf==NULL)
    {
        return;
    }
    if(argv==NULL)
    {
        return;
    }
    int i;
    int argc=0;
    int status=0;

    for(i=0;buf[i];i++)
   {
      if(  !isspace(buf[i])   &&   status==0)
      {
       argv[argc++]=buf+i;
       status=1;

      }else if( isspace(buf[i]) )
      {

        status=0;
        buf[i]='\0';

     }
   }
    argv[argc]=NULL;

  }

int has_pipe(char* argv[])
{
    
       int i=1;
       //Start form 1 because before '|' should have command.
       while(argv[i]!=NULL)
      {
         if(strcmp(argv[i],"|")==0)
        {
           argv[i]=NULL;
           return i+1;     
        }
      i++; 
      }

  return 0;
    
}



int main()
{
    char* argv[16];
    int argc = 0;
    char buf[1024]={0};

    char* tmp1[8];
    char* tmp2[8];
    int fd[2];
    int ret;
      while(1)
    {

        printf("[myshell~]");

        scanf("%[^\n]%*c",buf);
        
        do_parse(buf,argv);
        
        ret=has_pipe(argv);
        
        if(ret)
        {   
            int i=0;
            int j=ret;
         // divide argv to  tmp1 and tmp2.
            while(argv[i]!=NULL)
           {
             tmp1[i]=argv[i];
             i++;
           }
           
           tmp1[i]=NULL;

             i=0;
            
             while(argv[j]!=NULL)
            {
              tmp2[i++]=argv[j++];
            }
             
             tmp2[i]=NULL;


           // creat son process. 
            pid_t pid_p=fork();

            if(pid_p==-1)
            {
              perror("pid_p");
              exit(EXIT_FAILURE);
            }
            else if(pid_p==0)
            {//son 

             if(pipe(fd)==-1)
            {
             
              perror("pipe");
              exit(EXIT_FAILURE);

            }
           // creat grandson process. 
              pid_t pid_s=fork();
             
              if(pid_s==-1)
              {
                perror("pid_s");
                exit(EXIT_FAILURE);
              }
              else if(pid_s==0)
              {
                  //grand son
                close(fd[0]);    
             
                dup2(fd[1],1);
               
                execvp(tmp1[0],tmp1);


              }
              else
              {
                //son
                
                close(fd[1]);
               
                dup2(fd[0],0);
               
                execvp(tmp2[0],tmp2);
               
              }
          
            

            }else{
            
           //fater
                wait(NULL); 

          
           
            }

          //two execvp to do the work.
        }
        else
       {// no pipe    
            pid_t pid=fork();
            if(pid==-1)
            {
              perror("pid");
              exit(EXIT_FAILURE);
            }
             else if(pid==0)
            {

            execvp(argv[0],argv);

            }else{

                wait(NULL);
            }

       

            
        }

        memset(buf,0,1024);
    }
}

myshell(支持管道)_第1张图片

以上为运行结果。

你可能感兴趣的:(Linux)