血的教训!希望还没备份自己重要文件的朋友们抓紧备份一份
#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 " \t\r\n" // \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行 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 =='\n'){ buffer[position] = '\0'; 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*********************\n"); printf("The bulidin functions are as follows\n"); for (i = 0; i < number_of_bulidins(); i++) { printf(" %s\n", 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.”\n"); return 1; } int Miku_pwd(char **args){ char buffer[MAXPATH]; getcwd(buffer,MAXPATH); printf("The current directoryis:%s\n",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\n"); 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\n", "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!\n"); return 0; } // write(fd, "miku", strlen("miku")); pid_t pid; pid = fork(); if(pid<0){ printf("fork wrong\n"); } 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 " \t\r\n" // \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行 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 =='\n'){ buffer[position] = '\0'; 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*********************\n"); printf("The bulidin functions are as follows\n"); for (i = 0; i < number_of_bulidins(); i++) { printf(" %s\n", 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.”\n"); 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\n"); 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\n", "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 " \t\r\n" // \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行 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 =='\n'){ buffer[position] = '\0'; 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*********************\n"); printf("The bulidin functions are as follows\n"); for (i = 0; i < number_of_bulidins(); i++) { printf(" %s\n", 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.”\n"); 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\n"); return 1; } pid = fork(); if(pid<0){ printf("fork wrong\n"); } else if(pid==0){ // 子进程 close(fd[1]) ; //关闭子进程的 写 权限 read(fd[0], readmes, 25); //第一个参数表明从哪里读区 这里给的是 pipe的read端口 ((write 端口被我们关闭了 //第二个参数 表示我们要把读出来的东西放到哪里(这里我要读一个字符串) //第三个参数 表示我们的 // printf("%s\n",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 " \t\r\n" // \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行 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 =='\n'){ buffer[position] = '\0'; 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*********************\n"); printf("The bulidin functions are as follows\n"); for (i = 0; i < number_of_bulidins(); i++) { printf(" %s\n", 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.”\n"); 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\n"); 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\n", "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!\n"); return 0; } // write(fd, "miku", strlen("miku")); pid_t pid; pid = fork(); if(pid<0){ printf("fork wrong\n"); } 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; }