• 血的教训!希望还没备份自己重要文件的朋友们抓紧备份一份


    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <unistd.h>
    #include <sys/wait.h>
    #include<sys/stat.h>
    #include <fcntl.h>  //O_CREAT
    
    
    #define Miku_RL_BUFFERSIZE 1024
    #define MAXPATH 256
    #define Miku_SEC_BUFFER    64
    #define Miku_SEC_DELIM  " 	
    "
    // 	 的意思是 横向跳到下一制表符位置 
     的意思是 回车 
     的意思是回车换行
    
    char *Miku_read_line(void)
    {
        int buffersize = Miku_RL_BUFFERSIZE ;                  //空间大小
        int position  =0 ;                                  //存入buffer的位置index
        
        int c ;                                             //每次所读取的 字符! 注意是字符!不是整数
                                                            //因为之后要判断EOF 这是一个int类型
    
        char * buffer = malloc(sizeof(char)* buffersize );  //创建一个数组 指向空间 的指针
        
        //检查缓冲区是否创建成功
        if(!buffer){
            printf("Miku: memoery allocation wrong !");
            exit(EXIT_FAILURE);
        }
        
        while(1){
            //字符获取
            c = getchar();
            //判断终止符EOF 和 换行符?
            if(c=='"'){
                continue;
            }
            else if(c == EOF || c =='
    '){
                buffer[position] = '';
                return buffer ;
            }
            else{
                buffer[position]= c ;
                position++;
            }
            
            //如果超出了我们限定的数组大小。
            if( position >= buffersize ){
                //扩大数组容量
                buffersize += Miku_RL_BUFFERSIZE;
                buffer = realloc(buffer, buffersize);
                
                if(!buffer ){
                    printf("Miku: memoery allocation wrong !");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }
    
    char **Miku_split_line( char* line ){
        
        int bufsize = Miku_SEC_BUFFER;
        int position = 0;
        char **total_sec = malloc( sizeof(char*)*bufsize );
        char *sec ;
        
        if( !total_sec ){
            printf("Miku: memoery allocation wrong !");
            exit(EXIT_FAILURE);
        }
        
        sec =strtok( line , Miku_SEC_DELIM );
        while( sec!=NULL ){
            total_sec[position] = sec ;
            position++ ;
            //容量监控
            if(position >=bufsize){
                bufsize  +=Miku_SEC_BUFFER;
                total_sec = realloc(total_sec, bufsize);
                if(total_sec==NULL){
                    printf("Miku: memoery allocation wrong !");
                    exit(EXIT_FAILURE);
                }
            }
            sec = strtok(NULL ,Miku_SEC_DELIM );
            // 这个地方的参数NULL 表示接着上一个被找到的 位置继续往后查找。
        }
        total_sec[position] = NULL ; //封上
        return total_sec;
    }
    
    
    
    /*        内置函数         */
    int Miku_cd(char **args);
    int Miku_help(char **args);
    int Miku_exit(char **args);
    int Miku_info(char **args);
    int Miku_pwd(char **args);
    
    
    //一个数组 其中的元素类型为 char型指针(即指向字符串首字符)
    char *builtin_str[] = {
      "cd",
      "help",
      "exit",
      "info",
      "pwd"
    };
    
    int (*builtin_func[]) (char **) = {
      &Miku_cd,
      &Miku_help,
      &Miku_exit,
      &Miku_info,
      &Miku_pwd
    };
    
    
    int number_of_bulidins (){
        return sizeof(builtin_str)/sizeof(char*);
    }
    
    
    int Miku_cd(char** args){
        if(args[1] == NULL ){
            printf("please enter a dirctory ");
        }
        else {
            if(chdir(args[1]) != 0){
                  perror("Miku_shell"); //返回值:成功返回0 ,失败返回-1
            }
        }
        
        return 1;
    }
    
    
    int Miku_help(char **args){
        int i;
        printf("*********************Miku Shell*********************
    ");
        printf("The bulidin functions are as follows
    ");
    
        for (i = 0; i < number_of_bulidins(); i++) {
          printf("  %s
    ", builtin_str[i]);
        }
    
        return 1;
    }
    
    
    int Miku_exit (char **args){
        return 0;
    }
    
    
    int Miku_info(char **args){
        printf("“COMP2211 Simplified Shell by Luo Ruidi sc17rl@leeds.ac.uk.”
    ");
        return 1;
    }
    
    int Miku_pwd(char **args){
        char buffer[MAXPATH];
        getcwd(buffer,MAXPATH);
        printf("The current directoryis:%s
    ",buffer);
        return 1;
    }
    
    
    
    // *************系统调用,  //
    
    
    int Miku_launch(char** args){
        
        pid_t pid ;  //进程 ID
      
        int status;
        
        pid = fork();  /*
                        在父进程中返回 >0
                        在子进程中返回  0
                        错误返回。     <0   由其返回值 可判断实在 父 还是在子
                        */
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            //返回-1 表示失败
            if(  execvp(args[0], args)  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        
        return 1;
        
    }
    
    /*
       输入ex + 可执行文件名 + 传递的参数
     */
    
    int Miku_Ex(char** args){
        
        pid_t pid ;
        int status;
        pid = fork();
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            if(  execvp(args[1], args)  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        return 1;
        
    }
    
    
    
    /*
     
     */
    
    int Miku_grep(char** args){
        pid_t pid ;
        int status;
        pid = fork();
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            if(  execlp("grep","grep" ,args[1],args[2],args[3])  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        return 1;
    
    }
    
    char readmes[25] ;
    int Miku_pipeline(char** args){
       int chidB ,chidC;
        int pipefd[2];
        
        //创建 管道
        if( pipe(pipefd)==-1 ){
            printf("pipe fault
    ");
            return 1;
        }
        if(!(chidB =fork() ) ){
            close(pipefd[1]);  //在B中 关闭他的写pipe权限 只让他读
            close(0)  ;// 0 -> stdin
            dup2(pipefd[0], 0); //将B的读区位置 设为 管道的0 口
           
            read(pipefd[0], readmes, 25);
            char *args1[] = {readmes, NULL};
            close(pipefd[0]);
            execve(args[4],args1,NULL);
        }
        close(pipefd[0]); // 在A 主程序中
        if(!(chidC =fork() ) ){
                 close(pipefd[0]);  //在C中 关闭他的读pipe权限 只让他输出
                 close(1)  ;// 1 -> stdout
                 dup2(pipefd[1], 1); //将C的输出位置 设为 管道的1 口
                 execve(args[1],NULL,NULL);
             }
        close(pipefd[1]); // 在主程序中
        wait4(chidB, NULL, 0, NULL);
      //  printf("%s
    ", "OVER!");
       
    
        return 1;
    }
    
    int Miku_redirection(char **args){
        int fd = open("a.txt",O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
          if(fd<0){
              printf("Open Error!
    ");
              return 0;
          }
        //  write(fd, "miku", strlen("miku"));
          pid_t pid;
          pid = fork();
          if(pid<0){
                 printf("fork wrong
    ");
             }
          else if(pid==0){   // 子进程
             close(1)  ;// 1 -> stdout
             dup2(fd, 1); //将C的输出位置 设为 管道的1 口
             execve(args[1],NULL,NULL);
              
             }
          else{
              
          }
          close(fd);
        return 1;
    }
    
    
    int Miku_execute(char **args){
        int i= 0 ;
        
        if(args[0] == NULL ){
            return 1;
        }
        
        for(i=0 ;i<number_of_bulidins() ;i++)
        {
            if (strcmp(args[0], builtin_str[i]) == 0 )
                return (*builtin_func[i])(args);
        }
        
       
       if( strcmp(args[0], "ex") == 0 ){
    
            if( strcmp(args[2], "|") == 0){
                   Miku_pipeline(args);
                   return 1;
               }
            else if (strcmp(args[2], ">") == 0){
               return Miku_redirection(args);
            }
            else{
            return Miku_Ex(args);
            }
        }
        else if (strcmp(args[0], "mygrep") == 0 ){
            return Miku_grep(args);
        }
        
        
        return Miku_launch(args);
        
    }
    
    
    
    void Miku_loop(void){
        
        
        //全都是 指针型。目的是啥?
        char *line  ;  //读取用户输入
        char **args ; //转译 输入?
        
        int  status = 0 ; //状态显示
        
        do{
            printf("Miku_Shell> "); //打出一个提示符 告知用户输入
            line = Miku_read_line();
            args = Miku_split_line(line);
            status = Miku_execute(args);
      
            free(line);
            free(args);
        }while(status);
        
    
    }
    
    
    
    int main(int argc, const char * argv[]) {
    
    
        Miku_loop();
        
        return 0;
        
    }
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <unistd.h>
    #include <sys/wait.h>
    
    
    #define Miku_RL_BUFFERSIZE 1024
    #define Miku_SEC_BUFFER    64
    #define Miku_SEC_DELIM  " 	
    "
    // 	 的意思是 横向跳到下一制表符位置 
     的意思是 回车 
     的意思是回车换行
    
    char *Miku_read_line(void)
    {
        int buffersize = Miku_RL_BUFFERSIZE ;                  //空间大小
        int position  =0 ;                                  //存入buffer的位置index
        
        int c ;                                             //每次所读取的 字符! 注意是字符!不是整数
                                                            //因为之后要判断EOF 这是一个int类型
    
        char * buffer = malloc(sizeof(char)* buffersize );  //创建一个数组 指向空间 的指针
        
        //检查缓冲区是否创建成功
        if(!buffer){
            printf("Miku: memoery allocation wrong !");
            exit(EXIT_FAILURE);
        }
        
        while(1){
            //字符获取
            c = getchar();
            //判断终止符EOF 和 换行符?
            if(c=='"'){
                continue;
            }
            else if(c == EOF || c =='
    '){
                buffer[position] = '';
                return buffer ;
            }
            else{
                buffer[position]= c ;
                position++;
            }
            
            //如果超出了我们限定的数组大小。
            if( position >= buffersize ){
                //扩大数组容量
                buffersize += Miku_RL_BUFFERSIZE;
                buffer = realloc(buffer, buffersize);
                
                if(!buffer ){
                    printf("Miku: memoery allocation wrong !");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }
    
    char **Miku_split_line( char* line ){
        
        int bufsize = Miku_SEC_BUFFER;
        int position = 0;
        char **total_sec = malloc( sizeof(char*)*bufsize );
        char *sec ;
        
        if( !total_sec ){
            printf("Miku: memoery allocation wrong !");
            exit(EXIT_FAILURE);
        }
        
        sec =strtok( line , Miku_SEC_DELIM );
        while( sec!=NULL ){
            total_sec[position] = sec ;
            position++ ;
            //容量监控
            if(position >=bufsize){
                bufsize  +=Miku_SEC_BUFFER;
                total_sec = realloc(total_sec, bufsize);
                if(total_sec==NULL){
                    printf("Miku: memoery allocation wrong !");
                    exit(EXIT_FAILURE);
                }
            }
            sec = strtok(NULL ,Miku_SEC_DELIM );
            // 这个地方的参数NULL 表示接着上一个被找到的 位置继续往后查找。
        }
        total_sec[position] = NULL ; //封上
        return total_sec;
    }
    
    
    
    /*        内置函数         */
    int Miku_cd(char **args);
    int Miku_help(char **args);
    int Miku_exit(char **args);
    int Miku_info(char **args);
    
    
    //一个数组 其中的元素类型为 char型指针(即指向字符串首字符)
    char *builtin_str[] = {
      "cd",
      "help",
      "exit",
      "info"
    };
    
    int (*builtin_func[]) (char **) = {
      &Miku_cd,
      &Miku_help,
      &Miku_exit,
      &Miku_info
    };
    
    
    int number_of_bulidins (){
        return sizeof(builtin_str)/sizeof(char*);
    }
    
    
    int Miku_cd(char** args){
        if(args[1] == NULL ){
            printf("please enter a dirctory ");
        }
        else {
            if(chdir(args[1]) != 0){
                  perror("Miku_shell"); //返回值:成功返回0 ,失败返回-1
            }
        }
        
        return 1;
    }
    
    
    int Miku_help(char **args){
        int i;
        printf("*********************Miku Shell*********************
    ");
        printf("The bulidin functions are as follows
    ");
    
        for (i = 0; i < number_of_bulidins(); i++) {
          printf("  %s
    ", builtin_str[i]);
        }
    
        return 1;
    }
    
    
    int Miku_exit (char **args){
        return 0;
    }
    
    
    int Miku_info(char **args){
        printf("“COMP2211 Simplified Shell by Luo Ruidi sc17rl@leeds.ac.uk.”
    ");
        return 1;
    }
    
    
    
    // *************系统调用,  //
    
    
    int Miku_launch(char** args){
        
        pid_t pid ;  //进程 ID
      
        int status;
        
        pid = fork();  /*
                        在父进程中返回 >0
                        在子进程中返回  0
                        错误返回。     <0   由其返回值 可判断实在 父 还是在子
                        */
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            //返回-1 表示失败
            if(  execvp(args[0], args)  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        
        return 1;
        
    }
    
    /*
       输入ex + 可执行文件名 + 传递的参数
     */
    
    int Miku_Ex(char** args){
        
        pid_t pid ;
        int status;
        pid = fork();
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            if(  execvp(args[1], args)  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        return 1;
        
    }
    
    
    
    /*
     
     */
    
    int Miku_grep(char** args){
        pid_t pid ;
        int status;
        pid = fork();
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            if(  execlp("grep","grep" ,args[1],args[2],args[3])  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        return 1;
    
    }
    
    char readmes[25] ;
    int Miku_pipeline(char** args){
       int chidB ,chidC;
        int pipefd[2];
        
        //创建 管道
        if( pipe(pipefd)==-1 ){
            printf("pipe fault
    ");
            return 1;
        }
        if(!(chidB =fork() ) ){
            close(pipefd[1]);  //在B中 关闭他的写pipe权限 只让他读
            close(0)  ;// 0 -> stdin
            dup2(pipefd[0], 0); //将B的读区位置 设为 管道的0 口
           
            read(pipefd[0], readmes, 25);
            char *args1[] = {readmes, NULL};
            close(pipefd[0]);
            execve(args[4],args1,NULL);
        }
        close(pipefd[0]); // 在A 主程序中
        if(!(chidC =fork() ) ){
                 close(pipefd[0]);  //在C中 关闭他的读pipe权限 只让他输出
                 close(1)  ;// 1 -> stdout
                 dup2(pipefd[1], 1); //将C的输出位置 设为 管道的1 口
                 execve(args[1],NULL,NULL);
             }
        close(pipefd[1]); // 在主程序中
        wait4(chidB, NULL, 0, NULL);
      //  printf("%s
    ", "OVER!");
       
    
        return 1;
    }
    
    
    
    
    int Miku_execute(char **args){
        int i= 0 ;
        
        if(args[0] == NULL ){
            return 1;
        }
        
        for(i=0 ;i<number_of_bulidins() ;i++)
        {
            if (strcmp(args[0], builtin_str[i]) == 0 )
                return (*builtin_func[i])(args);
        }
        
       
       if( strcmp(args[0], "ex") == 0 ){
    
            if( strcmp(args[2], "|") == 0){
                   Miku_pipeline(args);
                   return 1;
               }
            else{
            return Miku_Ex(args);
            }
        }
        else if (strcmp(args[0], "mygrep") == 0 ){
            return Miku_grep(args);
        }
        
        
        return Miku_launch(args);
        
    }
    
    
    
    void Miku_loop(void){
        
        
        //全都是 指针型。目的是啥?
        char *line  ;  //读取用户输入
        char **args ; //转译 输入?
        
        int  status = 0 ; //状态显示
        
        do{
            printf("Miku_Shell> "); //打出一个提示符 告知用户输入
            line = Miku_read_line();
            args = Miku_split_line(line);
            status = Miku_execute(args);
      
            free(line);
            free(args);
        }while(status);
        
    
    }
    
    
    
    int main(int argc, const char * argv[]) {
    
    
        Miku_loop();
        
        return 0;
        
    }

    个人觉得macOS Mojave 应该是这个世界上最不稳定的操作系统了,今天试着跑了跑自己写的shell 结果 直接编译过程中就把我的main文件直接杀掉了,真的不知道苹果是怎么想的?自己主打的OS都不尽善尽美,你卖NM电脑? 估计以后还是会转回Windos。奉劝各位一句 要么linux 要么windos !Macos 不易久留。
    最后贴出一份自己写的shell 作为备份,以后得多多注意。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <unistd.h>
    
    
    #define Miku_RL_BUFFERSIZE 1024
    #define Miku_SEC_BUFFER    64
    #define Miku_SEC_DELIM  " 	
    "
    // 	 的意思是 横向跳到下一制表符位置 
     的意思是 回车 
     的意思是回车换行
    
    char *Miku_read_line(void)
    {
        int buffersize = Miku_RL_BUFFERSIZE ;                  //空间大小
        int position  =0 ;                                  //存入buffer的位置index
        
        int c ;                                             //每次所读取的 字符! 注意是字符!不是整数
                                                            //因为之后要判断EOF 这是一个int类型
    
        char * buffer = malloc(sizeof(char)* buffersize );  //创建一个数组 指向空间 的指针
        
        //检查缓冲区是否创建成功
        if(!buffer){
            printf("Miku: memoery allocation wrong !");
            exit(EXIT_FAILURE);
        }
        
        while(1){
            //字符获取
            c = getchar();
            //判断终止符EOF 和 换行符?
            if(c=='"'){
                continue;
            }
            else if(c == EOF || c =='
    '){
                buffer[position] = '';
                return buffer ;
            }
            else{
                buffer[position]= c ;
                position++;
            }
            
            //如果超出了我们限定的数组大小。
            if( position >= buffersize ){
                //扩大数组容量
                buffersize += Miku_RL_BUFFERSIZE;
                buffer = realloc(buffer, buffersize);
                
                if(!buffer ){
                    printf("Miku: memoery allocation wrong !");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }
    
    char **Miku_split_line( char* line ){
        
        int bufsize = Miku_SEC_BUFFER;
        int position = 0;
        char **total_sec = malloc( sizeof(char*)*bufsize );
        char *sec ;
        
        if( !total_sec ){
            printf("Miku: memoery allocation wrong !");
            exit(EXIT_FAILURE);
        }
        
        sec =strtok( line , Miku_SEC_DELIM );
        while( sec!=NULL ){
            total_sec[position] = sec ;
            position++ ;
            //容量监控
            if(position >=bufsize){
                bufsize  +=Miku_SEC_BUFFER;
                total_sec = realloc(total_sec, bufsize);
                if(total_sec==NULL){
                    printf("Miku: memoery allocation wrong !");
                    exit(EXIT_FAILURE);
                }
            }
            sec = strtok(NULL ,Miku_SEC_DELIM );
            // 这个地方的参数NULL 表示接着上一个被找到的 位置继续往后查找。
        }
        total_sec[position] = NULL ; //封上
        return total_sec;
    }
    
    
    
    /*        内置函数         */
    int Miku_cd(char **args);
    int Miku_help(char **args);
    int Miku_exit(char **args);
    int Miku_info(char **args);
    
    
    //一个数组 其中的元素类型为 char型指针(即指向字符串首字符)
    char *builtin_str[] = {
      "cd",
      "help",
      "exit",
      "info"
    };
    
    int (*builtin_func[]) (char **) = {
      &Miku_cd,
      &Miku_help,
      &Miku_exit,
      &Miku_info
    };
    
    
    int number_of_bulidins (){
        return sizeof(builtin_str)/sizeof(char*);
    }
    
    
    int Miku_cd(char** args){
        if(args[1] == NULL ){
            printf("please enter a dirctory ");
        }
        else {
            if(chdir(args[1]) != 0){
                  perror("Miku_shell"); //返回值:成功返回0 ,失败返回-1
            }
        }
        
        return 1;
    }
    
    
    int Miku_help(char **args){
        int i;
        printf("*********************Miku Shell*********************
    ");
        printf("The bulidin functions are as follows
    ");
    
        for (i = 0; i < number_of_bulidins(); i++) {
          printf("  %s
    ", builtin_str[i]);
        }
    
        return 1;
    }
    
    
    int Miku_exit (char **args){
        return 0;
    }
    
    
    int Miku_info(char **args){
        printf("“COMP2211 Simplified Shell by Luo Ruidi sc17rl@leeds.ac.uk.”
    ");
        return 1;
    }
    
    
    
    // *************系统调用,  //
    
    
    int Miku_launch(char** args){
        
        pid_t pid ;  //进程 ID
      
        int status;
        
        pid = fork();  /*
                        在父进程中返回 >0
                        在子进程中返回  0
                        错误返回。     <0   由其返回值 可判断实在 父 还是在子
                        */
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            //返回-1 表示失败
            if(  execvp(args[0], args)  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        
        return 1;
        
    }
    
    /*
       输入ex + 可执行文件名 + 传递的参数
     */
    
    int Miku_Ex(char** args){
        
        pid_t pid ;
        int status;
        pid = fork();
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            if(  execvp(args[1], args)  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        return 1;
        
    }
    
    
    
    /*
     
     */
    
    int Miku_grep(char** args){
        pid_t pid ;
        int status;
        pid = fork();
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            if(  execlp("grep","grep" ,args[1],args[2],args[3])  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        return 1;
    
    }
    
    
    
    
    
    
    int Miku_execute(char **args){
        int i= 0 ;
        
        if(args[0] == NULL ){
            return 1;
        }
        
        for(i=0 ;i<number_of_bulidins() ;i++)
        {
            if (strcmp(args[0], builtin_str[i]) == 0 )
                return (*builtin_func[i])(args);
        }
        
        
        if( strcmp(args[0], "ex") == 0 ){
            return Miku_Ex(args);
        }
        else if (strcmp(args[0], "mygrep") == 0 ){
            return Miku_grep(args);
        }
        
        
        return Miku_launch(args);
        
    }
    
    
    
    void Miku_loop(void){
        
        
        //全都是 指针型。目的是啥?
        char *line  ;  //读取用户输入
        char **args ; //转译 输入?
        
        int  status = 0 ; //状态显示
        
        do{
            printf("Miku_Shell> "); //打出一个提示符 告知用户输入
            line = Miku_read_line();
            args = Miku_split_line(line);
            status = Miku_execute(args);
      
            free(line);
            free(args);
        }while(status);
        
    
    }
    
    
    
    int main(int argc, const char * argv[]) {
    
    
        Miku_loop();
        return 0;
        
    }
    
    
    /* if( c =='"' ){
               continue;
           }
           else*/

     今天的份 终于用C语言实现了 pipe!! 太难了 有时候真的觉得国内的资源太少了,什么东西查半天! 等过几天 我一定详细 整理一遍我最近搞得东西!保证 大白话讲的明明白白!

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    
    /*
     管道对于管道两端的进程而言,就是一个文件,
     但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在于内存中
     写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
     FILO  queue
     
     pipe 可以看作两端各有2个端口的  管子
     
     pipe(int fd[2]) ; 这个函数被调用成功后会直接返回两个数值 fd【0】->r  fd【1】->w   文件描述符
     之后在进程中可以通过。open和close 达到控制 pipe的输入和输出权限 控制。
     比如close(fd【0】) 在父进程中调用的话  关闭管道读端口
    
     */
    void pipeline (char *args ){
        
    }
    
    
    int main(int argc, const char * argv[]) {
       
    
        char readmes[25] ;
        int fd[2];
        pid_t pid;
        
        //创建 管道
        if( pipe(fd)==-1 ){
            printf("pipe fault
    ");
            return 1;
        }
        
        pid = fork();
        if(pid<0){
            printf("fork wrong
    ");
        }
        else if(pid==0){   // 子进程
            close(fd[1]) ; //关闭子进程的 写 权限
            read(fd[0], readmes, 25);  //第一个参数表明从哪里读区 这里给的是 pipe的read端口 ((write                                         端口被我们关闭了
                                       //第二个参数 表示我们要把读出来的东西放到哪里(这里我要读一个字符串)
                                       //第三个参数 表示我们的
           // printf("%s
    ",readmes);
            char *args1[] = {readmes, NULL};
            execve("./B",args1,NULL);
            close(fd[0]);            //读取完成后 关闭该端口
        }
        else{ // 父进程
            close(fd[0])  ;//关闭父进程的 读 权限
            execve("./A",NULL,NULL);
            dup2(fd[1], 1);
           // write(fd[1], args1, strlen(args1)+1 );
            close(fd[0]);
            
        }
    
        return 0;
    }
    
    
    
    /*
     for(int i=0 ; i<argc ; i++){
            if (  strcmp("|", argv[i]) ==0){
                flag =1;
            }
        }
      int flag =1 ;
     */

     最终全部实现了!!!!爽死了 ,今晚好好记录一下整个过程!

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <unistd.h>
    #include <sys/wait.h>
    #include<sys/stat.h>
    #include <fcntl.h>  //O_CREAT
    
    
    #define Miku_RL_BUFFERSIZE 1024
    #define Miku_SEC_BUFFER    64
    #define Miku_SEC_DELIM  " 	
    "
    // 	 的意思是 横向跳到下一制表符位置 
     的意思是 回车 
     的意思是回车换行
    
    char *Miku_read_line(void)
    {
        int buffersize = Miku_RL_BUFFERSIZE ;                  //空间大小
        int position  =0 ;                                  //存入buffer的位置index
        
        int c ;                                             //每次所读取的 字符! 注意是字符!不是整数
                                                            //因为之后要判断EOF 这是一个int类型
    
        char * buffer = malloc(sizeof(char)* buffersize );  //创建一个数组 指向空间 的指针
        
        //检查缓冲区是否创建成功
        if(!buffer){
            printf("Miku: memoery allocation wrong !");
            exit(EXIT_FAILURE);
        }
        
        while(1){
            //字符获取
            c = getchar();
            //判断终止符EOF 和 换行符?
            if(c=='"'){
                continue;
            }
            else if(c == EOF || c =='
    '){
                buffer[position] = '';
                return buffer ;
            }
            else{
                buffer[position]= c ;
                position++;
            }
            
            //如果超出了我们限定的数组大小。
            if( position >= buffersize ){
                //扩大数组容量
                buffersize += Miku_RL_BUFFERSIZE;
                buffer = realloc(buffer, buffersize);
                
                if(!buffer ){
                    printf("Miku: memoery allocation wrong !");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }
    
    char **Miku_split_line( char* line ){
        
        int bufsize = Miku_SEC_BUFFER;
        int position = 0;
        char **total_sec = malloc( sizeof(char*)*bufsize );
        char *sec ;
        
        if( !total_sec ){
            printf("Miku: memoery allocation wrong !");
            exit(EXIT_FAILURE);
        }
        
        sec =strtok( line , Miku_SEC_DELIM );
        while( sec!=NULL ){
            total_sec[position] = sec ;
            position++ ;
            //容量监控
            if(position >=bufsize){
                bufsize  +=Miku_SEC_BUFFER;
                total_sec = realloc(total_sec, bufsize);
                if(total_sec==NULL){
                    printf("Miku: memoery allocation wrong !");
                    exit(EXIT_FAILURE);
                }
            }
            sec = strtok(NULL ,Miku_SEC_DELIM );
            // 这个地方的参数NULL 表示接着上一个被找到的 位置继续往后查找。
        }
        total_sec[position] = NULL ; //封上
        return total_sec;
    }
    
    
    
    /*        内置函数         */
    int Miku_cd(char **args);
    int Miku_help(char **args);
    int Miku_exit(char **args);
    int Miku_info(char **args);
    
    
    //一个数组 其中的元素类型为 char型指针(即指向字符串首字符)
    char *builtin_str[] = {
      "cd",
      "help",
      "exit",
      "info"
    };
    
    int (*builtin_func[]) (char **) = {
      &Miku_cd,
      &Miku_help,
      &Miku_exit,
      &Miku_info
    };
    
    
    int number_of_bulidins (){
        return sizeof(builtin_str)/sizeof(char*);
    }
    
    
    int Miku_cd(char** args){
        if(args[1] == NULL ){
            printf("please enter a dirctory ");
        }
        else {
            if(chdir(args[1]) != 0){
                  perror("Miku_shell"); //返回值:成功返回0 ,失败返回-1
            }
        }
        
        return 1;
    }
    
    
    int Miku_help(char **args){
        int i;
        printf("*********************Miku Shell*********************
    ");
        printf("The bulidin functions are as follows
    ");
    
        for (i = 0; i < number_of_bulidins(); i++) {
          printf("  %s
    ", builtin_str[i]);
        }
    
        return 1;
    }
    
    
    int Miku_exit (char **args){
        return 0;
    }
    
    
    int Miku_info(char **args){
        printf("“COMP2211 Simplified Shell by Luo Ruidi sc17rl@leeds.ac.uk.”
    ");
        return 1;
    }
    
    
    
    // *************系统调用,  //
    
    
    int Miku_launch(char** args){
        
        pid_t pid ;  //进程 ID
      
        int status;
        
        pid = fork();  /*
                        在父进程中返回 >0
                        在子进程中返回  0
                        错误返回。     <0   由其返回值 可判断实在 父 还是在子
                        */
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            //返回-1 表示失败
            if(  execvp(args[0], args)  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        
        return 1;
        
    }
    
    /*
       输入ex + 可执行文件名 + 传递的参数
     */
    
    int Miku_Ex(char** args){
        
        pid_t pid ;
        int status;
        pid = fork();
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            if(  execvp(args[1], args)  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        return 1;
        
    }
    
    
    
    /*
     
     */
    
    int Miku_grep(char** args){
        pid_t pid ;
        int status;
        pid = fork();
        if(pid < 0 ){
            perror("Miku_shell");
        }
        else if (pid == 0){
            if(  execlp("grep","grep" ,args[1],args[2],args[3])  == -1 )
            {
                 perror("Miku_shell");
            }
        }
        else {
            do {
                waitpid(pid ,&status ,WUNTRACED);
            }while(!WIFEXITED(status) && !WIFSIGNALED(status));
        }
        return 1;
    
    }
    
    char readmes[25] ;
    int Miku_pipeline(char** args){
       int chidB ,chidC;
        int pipefd[2];
        
        //创建 管道
        if( pipe(pipefd)==-1 ){
            printf("pipe fault
    ");
            return 1;
        }
        if(!(chidB =fork() ) ){
            close(pipefd[1]);  //在B中 关闭他的写pipe权限 只让他读
            close(0)  ;// 0 -> stdin
            dup2(pipefd[0], 0); //将B的读区位置 设为 管道的0 口
           
            read(pipefd[0], readmes, 25);
            char *args1[] = {readmes, NULL};
            close(pipefd[0]);
            execve(args[4],args1,NULL);
        }
        close(pipefd[0]); // 在A 主程序中
        if(!(chidC =fork() ) ){
                 close(pipefd[0]);  //在C中 关闭他的读pipe权限 只让他输出
                 close(1)  ;// 1 -> stdout
                 dup2(pipefd[1], 1); //将C的输出位置 设为 管道的1 口
                 execve(args[1],NULL,NULL);
             }
        close(pipefd[1]); // 在主程序中
        wait4(chidB, NULL, 0, NULL);
      //  printf("%s
    ", "OVER!");
       
    
        return 1;
    }
    
    int Miku_redirection(char **args){
        int fd = open("a.txt",O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
          if(fd<0){
              printf("Open Error!
    ");
              return 0;
          }
        //  write(fd, "miku", strlen("miku"));
          pid_t pid;
          pid = fork();
          if(pid<0){
                 printf("fork wrong
    ");
             }
          else if(pid==0){   // 子进程
             close(1)  ;// 1 -> stdout
             dup2(fd, 1); //将C的输出位置 设为 管道的1 口
             execve(args[1],NULL,NULL);
              
             }
          else{
              
          }
          close(fd);
        return 1;
    }
    
    
    int Miku_execute(char **args){
        int i= 0 ;
        
        if(args[0] == NULL ){
            return 1;
        }
        
        for(i=0 ;i<number_of_bulidins() ;i++)
        {
            if (strcmp(args[0], builtin_str[i]) == 0 )
                return (*builtin_func[i])(args);
        }
        
       
       if( strcmp(args[0], "ex") == 0 ){
    
            if( strcmp(args[2], "|") == 0){
                   Miku_pipeline(args);
                   return 1;
               }
            else if (strcmp(args[2], ">") == 0){
               return Miku_redirection(args);
            }
            else{
            return Miku_Ex(args);
            }
        }
        else if (strcmp(args[0], "mygrep") == 0 ){
            return Miku_grep(args);
        }
        
        
        return Miku_launch(args);
        
    }
    
    
    
    void Miku_loop(void){
        
        
        //全都是 指针型。目的是啥?
        char *line  ;  //读取用户输入
        char **args ; //转译 输入?
        
        int  status = 0 ; //状态显示
        
        do{
            printf("Miku_Shell> "); //打出一个提示符 告知用户输入
            line = Miku_read_line();
            args = Miku_split_line(line);
            status = Miku_execute(args);
      
            free(line);
            free(args);
        }while(status);
        
    
    }
    
    
    
    int main(int argc, const char * argv[]) {
    
    
        Miku_loop();
        
        return 0;
        
    }
  • 相关阅读:
    VC++文件操作之最全篇
    MFC六大核心机制之五、六:消息映射和命令传递
    MFC六大核心机制之四:永久保存(串行化)
    MFC六大核心机制之三:动态创建
    MFC六大核心机制之二:运行时类型识别(RTTI)
    MFC六大核心机制之一:MFC程序的初始化
    VS2010/MFC编程入门之五十四(Ribbon界面开发:使用更多控件并为控件添加消息处理函数)
    VS2010/MFC编程入门之五十三(Ribbon界面开发:为Ribbon Bar添加控件)
    java并发系列(四)-----源码角度彻底理解ReentrantLock(重入锁)、AQS
    java并发系列(三)-----ReentrantLock(重入锁)功能详解和应用演示
  • 原文地址:https://www.cnblogs.com/LuoRuidiLoveMiku/p/11620349.html
Copyright © 2020-2023  润新知