C语言实现一个简单的交互式Shell:
1.实现加载普通命令。
难点:通过分析参数字符串,然后利用函数fork()和execvp()来实现。
2.实现重定向的功能。
难点:通过函数dup2()实现
3.实现管道。
难点:学会利用管道实现进程间通信
下面是代码实现:
/************************************************************************* > File Name: myshell.c > Author: lucifer > Mail: [email protected] > Created Time: 2014年11月10日 星期一 18时43分14秒 ************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> void sys_err(const char *str) { perror(str); exit(-1); } void analyse_input(char *s,char *argv[]) { int i = 0; argv[i] = strtok(s," "); while(argv[i]) { i++; argv[i] = strtok(NULL," "); } argv[i] = NULL; } int main(void) { char s[256]={0}; char *argv[10],*argv1[10]; pid_t pid; int status,i; int isredirect = 0; int ispipe = 0; int fd; int pfd[2]; while(1) { printf("myshell#"); fgets(s,256,stdin); if(s[0] == '\n') { continue; } if(s[strlen(s) - 1] == '\n') { s[strlen(s) - 1] ='\0'; } if(strcmp(s,"exit") == 0) { break; } for(i = 0;i < strlen(s);i++) { if(s[i] == '<' || s[i] == '>') { isredirect = 1; break; } if(s[i] == '|') { ispipe = 1; break; } } if(isredirect) { if(s[i] == '>') { char *p1 = strtok(s,">"); char *p2 = strtok(NULL,">"); char *p3 = strtok(p2," "); analyse_input(p1,argv); if((pid = fork()) < 0) { sys_err("fork error"); } else if(pid == 0) { if((fd = open(p3,O_WRONLY | O_TRUNC)) < 0) { sys_err("open failed"); } dup2(fd,STDOUT_FILENO); close(fd); execvp(argv[0],argv); sys_err("excvp error"); } else { memset(s,0,256); isredirect=0;//important waitpid(pid,&status,0); continue; } } else { char *p1 = strtok(s,"<"); char *p2 = strtok(NULL,"<"); char *p3 = strtok(p2," "); analyse_input(p1,argv); if((pid = fork()) < 0) { sys_err("fork error"); } else if(pid == 0) { if((fd = open(p3,O_RDONLY)) < 0) { sys_err("open failed"); } dup2(fd,STDIN_FILENO); close(fd); execvp(argv[0],argv); sys_err("execvp error"); } else { memset(s,0,256); isredirect = 0; waitpid(pid,&status,0); continue; } } } else if(ispipe) { char *p1 = strtok(s,"|"); char *p2 = strtok(NULL,"|"); analyse_input(p1,argv); analyse_input(p2,argv1); if((pid = fork()) < 0) { sys_err("fork error"); } else if(pid == 0) { if(pipe(pfd) < 0) { sys_err("pipe error"); } pid = fork(); switch(pid) { case -1 : sys_err("fork error"); case 0 : close(pfd[0]); dup2(pfd[1],STDOUT_FILENO); close(pfd[1]); execvp(argv[0],argv); sys_err("execvp error"); exit(-1); default: close(pfd[1]); dup2(pfd[0],STDIN_FILENO); close(pfd[0]); execvp(argv1[0],argv1); sys_err("execvp error"); exit(-1); } } else { memset(s,0,256); waitpid(pid,&status,0); ispipe = 0; continue; } } else { analyse_input(s,argv); if((pid = fork()) < 0) { sys_err("fork error"); } else if(pid == 0) { execvp(argv[0],argv); sys_err("execvp error"); } else { waitpid(pid,&status,0); } } } return 0; }