📄 work2fuction.h
字号:
#include<dulei2head.h>
/*********获得用户输入的命令**********/
int get_string(){
while((ch=getchar())==' ')
; //跳过无用的信息
if(ch=='\n')
return ERROR; //输入为空时结束本次循环
while(ch!='\n'){
buf[input_len++]=ch;
ch=getchar();
}
buf[input_len]='\0'; //加上字符串结束符
//动态分配存储空间,将命令从缓存复制到input中
input=(char *)malloc(sizeof(char)*(input_len+1));
strcpy(input,buf);
return OK; //输入不为空时,返回输入正确
}
/***************判断含不含有管道或者重定向命令,如果有is_pipeorredirect=1****************/
int set_pipeorredirect(char *input, int input_len){
int i;
for(i=0;i<input_len;i++)
if(input[i]=='<'||input[i]=='>'||input[i]=='|'){ if(input[i]=='|')
is_pipe=1; else is_redirect=1;
return OK;
}
return ERROR;
}
/****************判断含不含有后台执行命令,如果有is_background=1,并得到命令参数****************/
int set_background(char *input, int input_len){
int i,j;
for(i=0,j=0,cmdandparameternum=0;i<=input_len;i++){
if(input[i]==' '||input[i]=='\0'){
if(j==0) //省略连在一起的多个空格
continue;
else{
buf[j++]='\0';
arg[cmdandparameternum]=(char *)malloc(sizeof(char)*j);
strcpy(arg[cmdandparameternum++],buf); //将指令和参数存放到arg中 arg[cmdandparameternum]=(char *)malloc(sizeof(char)*j);
arg[cmdandparameternum]=NULL;
j=0; //准备取下一个参数
}
}
else{
//如果字符串最后是&,表明是后台命令,令is_background=1
if(input[i]=='&'&&input[i+1]=='\0'){
is_background=1;
continue;
}
buf[j++]=input[i];
}
} return OK;
}
/*************cd命令***********/
int cd_cmd(char *path){
if(path!=NULL)
if(chdir(path)<0)
printf("cd %s : ERROR file or directory!\n", path);
return OK;}/*************获取PATH中每一个路径********/int getcmdpath(){ char *pathcmd; //存储PATH值 int i=0,j=0; //i表示temp的下标,j表示PATH的下标 char temp[30]={}; //用来存储从PATH中分离出来的一个路径 pathcmd=getenv("PATH"); //获得PATH,存放到pathcmd中 while(pathcmd[j]!='\0'){ while(pathcmd[j]!=':'&&pathcmd[j]!='\0') //如果读取的不是路径分隔符:或者字符串终结符号,则把读到的字符存放在temp中 temp[i++]=pathcmd[j++]; temp[i]='\0'; //如果读取的是路径分隔符:或者字符串终结符号,则添加字符终结符号到temp pathcmdsdirectory[pathcmdsdirectorynum]=(char *)malloc(sizeof(char)*i); strcpy(pathcmdsdirectory[pathcmdsdirectorynum],temp); //将temp中存放的路径,复制到pathcmdsdirectory中 if(pathcmd[j]!='\0'){ //如果刚才读取的不是字符串终结符号,则说明还有路径 j++; //为读取下一个字符做准备 i=0; //temp下标清零,重新存储路径 pathcmdsdirectorynum++; //路径个数+1 } } return OK;}/*************查找PATH中每一个路径下是否含有用户输入的命令*********/int scanfile(){// printf("arg[0]=%s",arg[0]); int i; for(i=0;i<pathcmdsdirectorynum;i++){ strcpy(fullpathcmdfilename,pathcmdsdirectory[i]); strcat(fullpathcmdfilename,"/"); strcat(fullpathcmdfilename,arg[0]); if(access(fullpathcmdfilename,F_OK)==0) return OK; } return ERROR;}/*************搜索命令文件*********/int searchfile(){ getcmdpath(); //获取PATH中每一个路径 if(scanfile()) //查找PATH中每一个路径下是否含有用户输入的命令,如果有进入if返回OK,否则进入else返回ERROR return OK; else{ //没有找到匹配的命令文件,返回错误信息 printf("Sorry! System doesn't have the command you want!\n"); fflush(stdout); int i; for(i=0;i<=cmdandparameternum;i++) free(arg[i]); for(i=0;i<=pathcmdsdirectorynum;i++) free(pathcmdsdirectory[i]); free(input); return ERROR; }}/**************执行命令*************/int execute_cmd(){ if((childpid=fork())==0){ /******子进程*******/ execvp(arg[0],arg); } else{ /*******父进程********/ if(is_background==0) //如果不是后台命令进入if waitpid(childpid,NULL,0); //阻塞父进程,等待子进程结束 }// if(is_background==1)// sleep(1); //等待命令输出后,再打印shell提示符 int i; for(i=0;i<cmdandparameternum;i++) free(arg[i]); free(input); return OK;}/**************I/O重定向****************/int redirect(){ int i,j,k,fd_in,fd_out,is_in=-1,is_out=-1,num=0; int is_back=0,status=0; /****这里是重定向的命令解析过程,其中redirectfilename用于存放重定向文件,is_in,is_out分别是输入重定向标记和输出重定向标记*********/ for(i=0,j=0,k=0;i<=input_len;i++){ // printf("reading %c\n",input[i]); if(input[i]==' '||input[i]=='\t'||input[i]=='\0'||input[i]=='<'||input[i]=='>'){ if(input[i]=='<'||input[i]=='>'){ /*重定向命令最多'<','>'各出现一次,因此num最大为2,否则认为命令错误*/ if(num<3){ num++; if(input[i]=='<') is_in=num-1; else is_out=num-1; /*处理命令和重定向符号相连的情况,例如ls>a*/ if(j>0&&num==1){ buf[j++]='\0'; arg[k]=(char *)malloc(sizeof(char)*j); strcpy(arg[k++],buf); j=0; } } else{ printf("The format is error\n"); return ERROR; } } if(j==0) continue; else{ buf[j++]='\0'; /*尚为遇到重定向符号,字符串是命令或者参数*/ if(num==0){ arg[k]=(char *)malloc(sizeof(char)*j); strcpy(arg[k++],buf); } /*是重定向后符号的字符串,是文件名*/ else{ redirectfilename[status]=(char *)malloc(sizeof(char)*j); strcpy(redirectfilename[status++],buf); } j=0; } } else{ /* if(input[i]=='&'&&input[i+1]=='\0'){ is_background=1; continue; } */ buf[j++]=input[i]; } } arg[k]=(char *)0; searchfile(); if((childredirectpid=fork())==0){ /*存在输出重定向*/ if(is_out!=-1) if((fd_out=open(redirectfilename[is_out],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1){ printf("Open out %s ERROR\n",redirectfilename[is_out]); fflush(stdout); return ERROR; } /*存在输入重定向*/ if(is_in!=-1){ if((fd_in=open(redirectfilename[is_in],O_RDONLY,S_IRUSR|S_IWUSR))==-1){ printf("Open in %s ERROR\n",redirectfilename[is_in]); fflush(stdout); return ERROR; }} if(is_out!=-1) /*实用dup2函数将标准输出重定向到fd_out上,dup2(int oldfd,int newfd)实现的是把oldfd所指的文件 描述符复制到newfd.若newfd为一已打开的文件描述词,则newfd所指的文件会先被关闭, dup2复制的文件描述词与原来的文件描述词共享各文件状态 */ if(dup2(fd_out,STDOUT_FILENO)==-1){ printf("Redirect Standard Out ERROR!\n"); fflush(stdout); exit(1); } if(is_in!=-1) if(dup2(fd_in,STDIN_FILENO)==-1){ printf("Redirect Standard In ERROR!\n"); fflush(stdout); exit(1); } if(is_out!=-1){ close(fd_out);}// close(fd_in); execv(fullpathcmdfilename,arg); } else if(is_background==0) waitpid(childredirectpid,&status,0); for(i=0;i<k;i++) free(arg[i]); if(is_in!=-1){ free(redirectfilename[is_in]); close(fd_in); } if(is_out!=-1){ free(redirectfilename[is_out]); // close(fd_out); // close(fd_in); } return OK;}/*********管道命令**********/int pipel(){ int i,j,k,count; int li_comm=0,fdpipe[2],fpipe[2]; char lc_char, lc_end[1]; /***管道命令的解析过程****/ for(i=0,j=0,k=0;i<=input_len;i++){ // printf("reading %c\n",input[i]); if(input[i]==' '||input[i]=='\t'||input[i]=='\0'||input[i]=='|'){ if(input[i]=='|'){ //如果出现的是管道符号 if(j>0){ buf[j++]='\0'; /*因为管道联接的是两个指令,所以用二维数组指针来存放命令和参数, li_comm是表示第几个指令*/ argpipe[li_comm][k]=(char *)malloc(sizeof(char)*j); strcpy(argpipe[li_comm][k++],buf); } argpipe[li_comm][k++]=(char *)0; /*遇到管道符号,第一个指令完毕,开始准备接收第二个指令*/ li_comm++; count=k; k=0;j=0; } if(j==0) continue; else{ buf[j++]='\0'; argpipe[li_comm][k]=(char *)malloc(sizeof(char)*j); strcpy(argpipe[li_comm][k++],buf); } j=0; } else{ if(input[i]=='&'&&input[i+1]=='\0'){ is_background=1; continue; } buf[j++]=input[i]; } } argpipe[li_comm][k++]=(char *)0; arg[0]=argpipe[0][0]; if(!searchfile()) for(i=0;i<=count;i++) free(argpipe[0][i]); fdpipe[0]=-1; fdpipe[1]=-1; /*建立管道*/ if(pipe(fdpipe)==-1){ printf("Open pipe error!\n"); fflush(stdout); return ERROR; } /*创建第一个子进程执行管道符前的指令,并将输出写到管道*/ if((childpipepid1=fork())==0){ /*关闭读端*/ close(fdpipe[0]); if(fdpipe[1]!=STDOUT_FILENO){ /*将标准输出重定向到管道的写入端,这样该子进程的输出就写入了管道*/ if(dup2(fdpipe[1],STDOUT_FILENO)==-1){ printf("Redirect Standard Out ERROR"); return ERROR; } /*关闭写入端*/ close(fdpipe[1]); } execvp(argpipe[0][0],argpipe[0]); } else{ /*父进程*/ waitpid(childpipepid1,NULL,0); /*然后我们必须写入一个结束标记,告诉管道进程数据到这里就完了*/ lc_end[0]=0x1a; write(fdpipe[1],lc_end,1); close(fdpipe[1]); // printf("CCC:%s %s",argpipe[1][0],argpipe[1][1]); if(!searchfile()){ for(i=0;i<=k;i++) free(argpipe[1][k]); return ERROR; } /*创建第二个子进程执行管道符前的指令,并将输出写到管道*/ if((childpipepid2=fork())==0){ if(fdpipe[0]!=STDIN_FILENO){ /*将标准输入重定向到管道的读入端*/ if(dup2(fdpipe[0],STDIN_FILENO)==-1){ printf("Redirect Standard Out ERROR"); return ERROR; } /*关闭读入端*/ close(fdpipe[0]); } execvp(argpipe[1][0],argpipe[1]); } else //父进程 if(is_background==0) waitpid(childpipepid2,NULL,0); } for(i=0;i<count;i++) free(argpipe[0][i]); for(i=0;i<k;i++) free(argpipe[1][k]); return OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -