⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 work2fuction.h

📁 简单的SHELL编程
💻 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 + -