📄 shell.cpp
字号:
/*****************************************************************************//*作者:王伟*//*班级:自42*//*学号:2004011443*//*程序功能:模拟linux下shell环境,实现shell功能*//*日期:2007.6.1*//*****************************************************************************/#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <string.h>#include <stdlib.h>#include <unistd.h> #include <sys/wait.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#define BUFFERSIZE 80int main(void) { char *read_order(char *buffer); //从键盘中读取命令 char **order_name(const char *input); //返回每条命令 int pipel(char * input); int pipe_number(const char *input);//统计管道数量 int redirect(char *input);//输入输出重定向 int order_number(const char *input); //统计命令数量,以;相隔 char *path,*buffer; char *all_order,**every_order; int i,pipe,k,number; if((buffer=(char *)malloc(BUFFERSIZE*(sizeof(char))))==0) { printf("error! can't malloc enough space for buffer\n"); return (0); } while(1) { path=getcwd(NULL,0); //取得当前所在路径 printf("%s > $", path); all_order=read_order(buffer); //读取命令 if(all_order==NULL) continue; number=order_number(all_order); if (number<0) continue; every_order=order_name(all_order); i=0; while (i<number) { if(strlen(every_order[i])!=0) { k=pipe_number(every_order[i]); //是否有管道 if(k!=0) pipel(every_order[i]); else redirect(every_order[i]); //输入输出重定向或普通命令 //for debug //printf("%s\n",every_order[i]); } i++; } //释放申请的空间 for(i=0;i<number;i++) free(every_order[i]); free(every_order); free(all_order); free(path); }}char **order_name(const char *input) //返回每条命令{ int order_number(const char *input); //统计命令数量,以;相隔 int i,j,k,max_len; char **order; max_len=strlen(input); k=order_number(input); order=(char **)malloc(k*sizeof(char *)); for(i=0;i<k;i++) { order[i]=(char *)malloc((max_len+1)*sizeof(char)); order[i][0]='\0'; } //分别取出被";"分割开的命令 k=0; j=0; for (i=0;i<=max_len;i++) { if (input[i]!=';') { order[k][j]=input[i]; j++; } else { order[k][j]='\0'; k++; j=0; } } //show the orders that are departed by ';' /*for(i=0;i<k+1;i++) printf("%s\n",order[i]);*/ return order;}int order_number(const char *input) //统计命令数量,以;相隔{ int sum=0,i=0,len; len=strlen(input); while(i<len&&(input[i]==' '||input[i]==' ')) i++; if(input[i]==';') //发生错误,出现;; { fprintf(stderr," syntax error near unexpected token: ;\n"); return -1; } if (i==len) //命令参数中只有空格或tab return -1; for (i=0;i<len;i++) if(input[i]==';') { while(i<strlen(input)&&(input[i+1]==' '||input[i+1]==' ')) i++; if(input[i+1]==';') //发生错误,出现;; { fprintf(stderr," syntax error near unexpected token: ;;\n"); return -1; } else sum++; } sum=sum+1; return sum;}int pipel(char * input){ int redirect(char *input); int is_back(char *order); //分析是否为后台进程,并且将字符&去掉 int pipe_number(const char *input); //统计管道数量 int status,i,j,k,**fd,back=0,len; char **order; int *child; back=is_back(input); len=strlen(input); k=pipe_number(input); order=(char **)malloc((k+1)*sizeof(char *)); for(i=0;i<k+1;i++) order[i]=(char *)malloc((len+1)*sizeof(char)); child=(int *)malloc((k+1)*sizeof(char *)); fd=(int **)malloc(k*sizeof(int *)); for(i=0;i<k;i++) fd[i]=(int *)malloc(2*sizeof(int)); //分别取出被管道分割开的命令 k=0; j=0; for (i=0;i<=len;i++) { if (input[i]!='|') { order[k][j]=input[i]; j++; } else { order[k][j]='\0'; k++; j=0; } } //test /*for(i=0;i<k+1;i++) printf("%s\n",order[i]);*/ /*分析完毕*/ //create the pipe for(i=0;i<k;i++) if(pipe(fd[i]) == -1) { fprintf(stderr, "Open pipe error !\n"); //printf("Open pipe error !\n"); return 0; } //create the first child i=0; if((child[i]=fork())==0) { close(fd[i][0]); if(fd[i][1] != STDOUT_FILENO) { // 将标准的输出重定向到管道的写入端,这样该子进程的输出就写入了管道 if(dup2(fd[i][1], STDOUT_FILENO) == -1) { fprintf(stderr, "Redirect Standard Out error !\n"); //printf("Redirect Standard Out error !\n"); return -1; } //关闭写入端 close(fd[i][1]); } redirect(order[i]); exit(1); //child1 exit } else { //wait for child waitpid(child[i],&status,0); close(fd[i][1]); } i++; while(i<k) { if ((child[i]=fork())==0) { if(fd[i][0] != STDIN_FILENO) { // 将标准的输入重定向到管道的读入端 if(dup2(fd[i-1][0], STDIN_FILENO) == -1) { fprintf(stderr, "Redirect Standard In error !\n"); //printf("Redirect Standard In Error !\n"); return -1; } close(fd[i-1][0]); // 将标准的输出重定向到管道的写入端,这样该子进程的输出就写入了管道 if(dup2(fd[i][1], STDOUT_FILENO) == -1) { fprintf(stderr, "Redirect Standard Out error !\n"); //printf("Redirect Standard Out error !\n"); return -1; } close(fd[i][1]); } redirect(order[i]); exit(1); } else { //wait for child waitpid(child[i],&status,0); close(fd[i][1]); i++; } } //create the last child if((child[i] = fork()) == 0) { close(fd[i-1][1]); if(fd[i-1][0] != STDIN_FILENO) { // 将标准的输入重定向到管道的读入端 if(dup2(fd[i-1][0], STDIN_FILENO) == -1) { fprintf(stderr, "Redirect Standard In error !\n"); //printf("Redirect Standard In Error !\n"); return -1; } close(fd[i-1][0]); } redirect(order[i]); exit(1); } else if(back==0) { waitpid(child[i], NULL, 0); close(fd[i-1][1]); } //释放申请的空间 for(i=0;i<k;i++) free(fd[i]); free(fd); for(i=0;i<k+1;i++) free(order[i]); free(order); free(child); return 1; /**************************************************/}int pipe_number(const char *input)//统计管道数量{ int sum=0,i; for (i=0;i<strlen(input);i++) if(input[i]=='|') sum++; return sum;}void do_cd(char *argv[]) //专门用于cd命令{ if(argv[1]!=NULL) { if(chdir(argv[1])<0) switch(errno) { case ENOENT: fprintf(stderr,"DIRECTORY NOT FOUND\n"); break; case ENOTDIR: fprintf(stderr,"NOT A DIRECTORY NAME\n"); break; case EACCES: fprintf(stderr,"YOU DO NOT HAVE RIGHT TO ACCESS\n"); break; default: fprintf(stderr,"SOME ERROR HAPPENED IN CHDIR\n"); } }} int redirect(char *input) //重定向处理{ char **analize(const char *input); //分析键入的命令,获取命令和参数并保存在arg中 char *is_file_exist(const char *order); //判断命令是否存在 void do_cd(char *argv[]); //专门用于cd命令 int number(const char *input); //分析命令和参数数量,来划分相应字符串 int is_back(char *order); //分析是否为后台进程,并且将字符&去掉 int pipe_number(const char *input); //统计管道数量 char *order_path,*real_order; char *out_filename,*in_filename; char **analized_order; int len,status,i,j,k,back=0,fd_out,fd_in,flag_out=0,flag_in=0; pid_t pid; back=is_back(input); len=strlen(input); out_filename=(char *)malloc((len+1)*(sizeof(char))); in_filename=(char *)malloc((len+1)*(sizeof(char))); real_order=(char *)malloc((len+1)*(sizeof(char))); //读取字符串中的命令,并存放于real_order中 for(i=0;i<len;i++) { if (input[i]!='>'&&input[i]!='<') real_order[i]=input[i]; else { if (input[i]=='>') flag_out=1; if (input[i]=='<') flag_in=1; break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -