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

📄 wxly.c.svn-base

📁 大学操作系统课程实验:Linux下实现的一个shell解释器。能够比较完整完好地执行Linux下的普通命令、重定向命令、管道命令等多种命令。
💻 SVN-BASE
字号:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <math.h>
#include <signal.h>
#include <stdlib.h>

#include "analysis.c"

int main()
{
	init();										//初始化运行环境
	
	while(1)
	{
		char c,*arg[PARANUM+1];
		int i=0,j=0,k=0,is_pr=0,is_bg=0,input_len=0,path,pid=0,status=0;
		
		/*初始化操作符*/
		cmd_flag=SIMPLE_CMD;
		io_flag=NO_IO;
		pipe_len=0;

		/*设置signal信号*/
		struct sigaction action;
		action.sa_sigaction=delNode;
		sigfillset(&action.sa_mask);
		action.sa_flags=SA_SIGINFO;
		sigaction(SIGCHLD,&action,NULL);
		signal(SIGTSTP,ctrl_z_cmd);
		
		/*打印提示符*/
		path=get_current_dir_name();
		printf("wxly@%s> ",path);
		yyparse();

		if(cmd_flag==SIMPLE_CMD)
		{
			if(cmdStr.cmd==NULL)
				continue;
			
			addHistory(cmdStr);
			cmdStr.io_flag=io_flag;
			
			if(strcmp(cmdStr.cmd,"cd")==0)
			{
				cd_cmd(cmdStr.para[0]);
				freeSpace(&cmdStr);
				continue;
			}
			else if(strcmp(cmdStr.cmd,"history")==0)
			{
				history_cmd();
				freeSpace(&cmdStr);
				continue;
			}
			else if(strcmp(cmdStr.cmd,"jobs")==0)
			{
				jobs_cmd();
				freeSpace(&cmdStr);
				continue;
			}
			else if(strcmp(cmdStr.cmd,"fg")==0)
			{
				fg_cmd(atoi(&(cmdStr.para[0][1])));
				freeSpace(&cmdStr);
				continue;
			}
			else if(strcmp(cmdStr.cmd,"bg")==0)
			{
				bg_cmd(atoi(&(cmdStr.para[0][1])));
				freeSpace(&cmdStr);
				continue;
			}
			else if(strcmp(cmdStr.cmd,"exit")==0)
			{
				printf("Thanks for your support! Bye~\n");
				freeSpace(&cmdStr);
				break;
			}
			else
			{
				/*寻找命令文件*/
				if(isFounded(cmdStr.cmd)==0)
				{
					printf("This command is not founded!\n");
					freeSpace(&cmdStr);
					continue;
				}

				/*执行命令*/
				if((pid=fork())==0)
				{
					if(is_back==1)
						while(sig_flag==0)
							signal(SIGUSR1,setFlag);
					sig_flag=0;

					arg[0]=(char *)malloc(sizeof(char)*(strlen(cmdStr.cmd)+1));
					strcpy(arg[0],cmdStr.cmd);
					for(i=1;i<PARANUM+1&&cmdStr.para[i-1]!=NULL;i++)
					{
						arg[i]=(char *)malloc(sizeof(strlen(cmdStr.para[i-1])+1));
						strcpy(arg[i],cmdStr.para[i-1]);
					}
					arg[i]=NULL;
					execv(buf,arg);
					
					for(i=0;i<PARANUM+1&&arg[i]!=NULL;i++)
					{
							free(arg[i]);
							arg[i]=NULL;
					}
				}
				else
				{
					pid1=pid;
					if(is_back==1)
					{
						addNode(cmdStr,pid1);
						kill(pid,SIGUSR1);
						pid1=0;
					}
					else if(is_back==0)
						waitpid(pid,&status,0);
				}
				if(is_back==1)
					sleep(1);

				freeSpace(&cmdStr);
			}
		}
		else if(cmd_flag==REDIRECT_CMD)
		{
			addHistory(cmdStr);
			redirect();
			freeSpace(&cmdStr);
		}
		else if(cmd_flag==PIPE_CMD)
		{
			addPHistory(pipeStr);

			pipel();
			for(i=0;i<pipe_len;i++)
			{
				freeSpace(&pipeStr[i]);
			}
		}

		
	}
	
	return 0;
}

/*初始化环境*/
void init()
{
	int fd,n,i;
	char buff[80];
	
	if((fd=open("wxly_profile",O_RDONLY,660))==-1)
	{
		printf("Init environment variable error!\n");
		exit(1);
	}
	while(n=getLine(fd,buff))
		getEnvironment(n,buff);
	hRec.start=0;					//初始化历史记录
	for(i=0;i<HISNUM;i++)
		mallocSpace(&(hRec.cList[i]));
	hRec.end=0;
	head=end=NULL;					//初始化jobs链表头尾结点
}

int getLine(int fd,char *buff)
{
	int i=0;
	char c;
	while(read(fd,&c,1))
	{
		buff[i++]=c;
		if(c=='\n')
		{
			buff[i-1]='\0';
			return i;
		}
	}
	return i;
}

void getEnvironment(int n,char *s)
{
	int i=0,j=0,k=0;
	char c,buff[80],*p;
	while((c=s[i])!='=')
		buff[i++]=c;
	buff[i++]='\0';
	if(strcmp(buff,"PATH")==0)
	{
		while(s[i]!='\0')
		{
			if(s[i]==':')
			{
				buff[j++]='/';
				buff[j]='\0';
				p=(char *)malloc(sizeof(char)*(strlen(buff)+1));
				strcpy(p,buff);
				envpath[k++]=p;
				envpath[k]=NULL;
				j=0;
				i++;
			}	
			else
			{
				buff[j]=s[i];
				j++;
				i++;
			}
		}
	}
	else
		fprintf(stderr,"Not match");
}

/*重定向的处理 */
void redirect()
{
	char *arg[PARANUM+1];
	int fd_in,fd_out;
	int status=0,i=0;
	pid_t pid;

	/*寻找命令文件*/
	if(isFounded(cmdStr.cmd)==0)
	{
		printf("This command is not founded!\n");
		return;
	}
	
	/*命令的执行*/
	if((pid=fork())==0)
	{
		if(io_flag==FD_WRITE)
		{
			if((fd_out=open(cmdStr.filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1)
			{
				printf("Can't open %s \n",cmdStr.filename);
				return;
			}
			if(dup2(fd_out,STDOUT_FILENO)==-1)
			{
				printf("Redirect standard out error!\n");
				exit(1);
			}
			
			close(fd_out);
		}
		if(io_flag==FD_READ)
		{
			if((fd_in=open(cmdStr.filename,O_RDONLY,S_IRUSR|S_IWUSR))==-1)
			{
				printf("Can't open %s \n",cmdStr.filename);
				return;
			}
			if(dup2(fd_in,STDIN_FILENO)==-1)
			{
				printf("Redirect standard in error!\n");
			}
			
			close(fd_in);
			
		}
		arg[0]=(char *)malloc(sizeof(char)*(strlen(cmdStr.cmd)+1));
		strcpy(arg[0],cmdStr.cmd);
		for(i=1;i<PARANUM+1&&cmdStr.para[i-1]!=NULL;i++)
		{
			arg[i]=(char *)malloc(sizeof(char)*(strlen(cmdStr.para[i-1])+1));
			strcpy(arg[i],cmdStr.para[i-1]);
		}
		arg[i]=(char *)malloc(sizeof(char));
		arg[i]=(char *)0;

		execv(buf,arg);
		for(i=0;i<PARANUM+1&&arg[i]!=NULL;i++)
		{
			free(arg[i]);
			arg[i]=NULL;
		}
	}
	else
	{
		if(is_back==0)
			waitpid(pid,&status,0);
	}
	return;
}

/*管道的处理*/
int pipel()
{
 
	char *argv[PIPENUM][30],*filename[10];
	int i,j,k;
	int fd[PIPENUM][2],pipe_in=-1,pipe_out=-1;
	pid_t pid;
	
	for(i=0;i<pipe_len;i++)
	{
		argv[i][0]=(char *)malloc(sizeof(char)*(strlen(pipeStr[i].cmd)+1));
		strcpy(argv[i][0],pipeStr[i].cmd);
		for(j=1;j<PARANUM+1&&pipeStr[i].para[j-1]!=NULL;j++)
		{
			argv[i][j]=(char *)malloc(sizeof(char)*(strlen(pipeStr[i].para[j-1])+1));
			strcpy(argv[i][j],pipeStr[i].para[j-1]);
		}
		argv[i][j]=NULL;
	}
	argv[i][0]=NULL;
	for(i=0;i<PIPENUM;i++)
	{
		fd[i][FD_READ]=NO_PIPE;
		fd[i][FD_WRITE]=NO_PIPE;
	}
	
	for(i=0;i<pipe_len;i++)
	{
		if(pipe(fd[i])==-1)
		{
			printf("Can't open pipe!\n");
			return 0;
		}
	}
	
	/*寻找命令文件*/
	for(i=0;i<pipe_len;i++)
  	{
		if(isFounded(pipeStr[i].cmd)==0)
		{
			printf("Can't found command!\n");
			break;
		}

		if(i!=0)
		{
			pipe_in=fd[i-1][FD_READ];
		}
		else
		{
			if(pipeStr[i].io_flag==FD_READ)
			{
				if((pipe_in=open(pipeStr[i].filename,O_RDONLY,S_IRUSR|S_IWUSR))==-1)
				{
					printf("Can't open %s \n",pipeStr[i].filename);
					break;
				}
			}
			else
				pipe_in=NO_PIPE;
		}
	
		if(i!=pipe_len-1)
		{
			pipe_out=fd[i][FD_WRITE];
		}
		else
		{      
			if(pipeStr[i].io_flag==FD_WRITE)
			{       
				if((pipe_out=open(pipeStr[i].filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1)
				{
					printf("Can't open %s \n",pipeStr[i].filename);
					break;
				}
			}
			else
			{
				pipe_out=NO_PIPE;
			}
		}
		if((pid=fork())<0)
		{
			printf("Fork failed!\n");
			return 0;
		}
		if(pid==0)
		{
			if(pipe_in==NO_PIPE)
				close(pipe_in);
			if(pipe_out==NO_PIPE)
				close(pipe_out);
			if(pipe_out!=NO_PIPE)
			{
				dup2(pipe_out,1);
				close(pipe_out);
			}
			if(pipe_in!=NO_PIPE)
			{
				dup2(pipe_in,0);
				close(pipe_in);
			}
			execv(buf,argv[i]);
		}
		else
		{
			if(is_back==0)
			{
				waitpid(pid,NULL,0);
				close(pipe_in);
				close(pipe_out);
			}
		}
	}
	return 0;
}

/*查找命令文件*/
int isFounded(char *cmd)
{
	int k=0;
	while(envpath[k]!=NULL)
	{
		strcpy(buf,envpath[k]);
		strcat(buf,cmd);
		if(access(buf,F_OK)==0)
			return 1;
		k++;
	}
	return 0;
}

/*增加一条历史记录*/
void addHistory(CmdStr cStr)
{
	int i=0;
	hRec.end=(hRec.end+1)%HISNUM;
	if(hRec.end==hRec.start)
		hRec.start=(hRec.start+1)%HISNUM;
	mallocSpace(&(hRec.cList[hRec.end]));
	strcpy(hRec.cList[hRec.end].cmd,cStr.cmd);
	for(i=0;i<PARANUM;i++)
	{
		if(cStr.para[i]!=NULL)
			strcpy(hRec.cList[hRec.end].para[i],cStr.para[i]);
		else
			hRec.cList[hRec.end].para[i]=NULL;
	}
	if(io_flag!=NO_IO)
	{
		strcpy(hRec.cList[hRec.end].filename,cStr.filename);
		hRec.cList[hRec.end].io_flag=io_flag;
	}	
	else
	{
		hRec.cList[hRec.end].filename=NULL;
		hRec.cList[hRec.end].io_flag=NO_IO;		
	}
	hRec.p_len[hRec.end]=0;
}

void addPHistory(CmdStr *pStr)
{
	int i=0,j=0;
	hRec.end=(hRec.end+1)%HISNUM;
	if(hRec.end==hRec.start)
		hRec.start=(hRec.start+1)%HISNUM;

	for(i=0;i<pipe_len;i++)
	{
		mallocSpace(&(hRec.pList[hRec.end][i]));
		strcpy(hRec.pList[hRec.end][i].cmd,pStr[i].cmd);
		for(j=0;j<PARANUM;j++)
		{
			if(pStr[i].para[j]!=NULL)
				strcpy(hRec.pList[hRec.end][i].para[j],pStr[i].para[j]);
			else
				hRec.pList[hRec.end][i].para[j]=NULL;
		}
		if(pStr[i].io_flag!=NO_IO)
		{
			strcpy(hRec.pList[hRec.end][i].filename,pStr[i].filename);
			hRec.pList[hRec.end][i].io_flag=pStr[i].io_flag;
		}		
		else
		{
			hRec.pList[hRec.end][i].filename=NULL;
			hRec.pList[hRec.end][i].io_flag=NO_IO;
		}
	}

	hRec.p_len[hRec.end]=pipe_len;
}
/*history命令*/
void history_cmd()
{
	int i=0,j=0,k=0;
	if(hRec.start==hRec.end)
		return;
	else if(hRec.start<hRec.end)
	{
		for(i=hRec.start+1;i<=hRec.end;i++)
		{
			printf("%d\t",k++);
			if(hRec.p_len[i]==0)
			{
				printCmd(hRec.cList[i]);
				printf("\n");
			}			
			else
			{
				for(j=0;j<hRec.p_len[i]-1;j++)
				{
					printCmd(hRec.pList[i][j]);
					printf(" | ");
				}
				printCmd(hRec.pList[i][hRec.p_len[i]-1]);	
				printf("\n");
			}
		}
	}
	else
	{
		for(i=hRec.start;i<HISNUM;i++)
		{
			printf("%d\t",k++);
			if(hRec.p_len[i]==0)
			{
				printCmd(hRec.cList[i]);
				printf("\n");
			}
			else
			{
				for(j=0;j<hRec.p_len[i]-1;j++)
				{
					printCmd(hRec.pList[i][j]);
					printf(" | ");
				}
				printCmd(hRec.pList[i][hRec.p_len[i]-1]);
				printf("\n");
			}
		}
		for(i=0,j=0;i<=hRec.end;i++)
		{
			printf("%d\t",k++);
			if(hRec.p_len[i]==0)
			{
				printCmd(hRec.cList[i]);
				printf("\n");
			}
			else
			{
				for(j=0;j<hRec.p_len[i]-1;j++)
				{
					printCmd(hRec.pList[i][j]);
					printf(" | ");
				}
				printCmd(hRec.pList[i][hRec.p_len[i]-1]);
				printf("\n");
			}
		}
	}
}

/*cd命令*/
void cd_cmd(char *route)
{
	if(route!=NULL)
		if(chdir(route)<0)
			printf("cd:%s Error file or directory!\n",route);
}

/*jobs命令*/
void jobs_cmd()
{
	JobsNode *p;
	int i=1,j=0;
	p=head;
	
	if(head!=NULL)
	{
		do
		{
			printf("%d %d %s\t",i++,p->pid,p->state);
			printCmd(p->cStr);
			printf("\n");
			p=p->link;
		}while(p!=NULL);
	}
	else
		printf("No jobs!\n");
}

void addNode(CmdStr cStr,int node_pid)
{
	int i;
	JobsNode *p;
	p=(JobsNode *)malloc(sizeof(JobsNode));
	p->pid=node_pid;
	mallocSpace(&(p->cStr));
	memcpy(&(p->cStr),&cStr,sizeof(p->cStr));

	strcpy(p->state,"running");
	p->link=NULL;
	if(head==NULL)
	{
		head=p;
		end=p;
	}
	else
	{
		end->link=p;
		end=p;
	}
}
void delNode(int sig,siginfo_t *sip)
{
	JobsNode *q,*p;
	int id;
	if(sig_z==1)
	{
		sig_z=0;
		return;
	}
	id=sip->si_pid;
	p=q=head;
	if(head==NULL)
		return;
	while(p->pid!=id&&p->link!=NULL)
		p=p->link;
	if(p->pid!=id)
		return;
	if(p==head)
		head=head->link;
	else
	{
		while(q->link!=p)
			q=q->link;
		if(p==end)
		{
			end=q;
			q->link=NULL;
		}
		else
			q->link=p->link;
	}
	free(p);
	return;
}

void setFlag()
{
	sig_flag=1;
}

void ctrl_z_cmd()
{
	JobsNode *p;
	int i=1;
	if(pid1==0)
		return;
	if(head!=NULL)
	{
		p=head;
		while(p->pid!=pid1&&p->link!=NULL)
			p=p->link;
		if(p->pid==pid1)
			strcpy(p->state,"stopped");
		else
		{
			addNode(cmdStr,pid1);
			strcpy(end->state,"stopped");
		}
	}
	else
	{
		addNode(cmdStr,pid1);
		strcpy(end->state,"stopped");
	}
	sig_z=1;
	kill(pid1,SIGSTOP);
	for(p=head;p->pid!=pid1;p=p->link)
		i++;
	printf("[%d]\t%s\t",i,end->state);
	printCmd(end->cStr);
	printf("\n");
	pid1=0;
	return;
}

/*前后台切换命令*/

void bg_cmd(int job_num)
{
	JobsNode *p;
	int i=0;

	p=head;
	for(i=1;i<job_num;i++)
		p=p->link;

	kill(p->pid,SIGCONT);
	strcpy(p->state,"running");
}

void fg_cmd(int job_num)
{
	JobsNode *p;
	int i=0;
	p=head;
	for(i=1;i<job_num;i++)
		p=p->link;
	strcpy(p->state,"running");
	mallocSpace(&(p->cStr));
	memcpy(&cmdStr,&(p->cStr),sizeof(CmdStr));
	/*
	strcpy(cmdStr.cmd,p->cStr.cmd);
	for(i=0;i<PARANUM;i++)
	{
		if(p->cStr.para[i]!=NULL)
			strcpy(cmdStr.para[i],p->cStr.para[i]);
		else
			cmdStr.para[i]=NULL;
	}
	*/		

	pid1=p->pid;
	signal(SIGTSTP,ctrl_z_cmd);
	kill(p->pid,SIGCONT);
	waitpid(p->pid,NULL,0);
}

/*打印一条命令到屏幕上*/
void printCmd(CmdStr cStr)
{
	int i=0;
	printf("%s ",cStr.cmd);
	for(i=0;i<PARANUM&&cStr.para[i]!=NULL;i++)
		printf("%s ",cStr.para[i]);
	if(cStr.io_flag==FD_READ)
		printf(" < %s ",cStr.filename);
	else if(cStr.io_flag==FD_WRITE)
		printf(" > %s ",cStr.filename);
}

/*为命令结构体中相应字段分配空间*/
void mallocSpace(CmdStr *cStr)
{
	int i=0;
	cStr->cmd=(char *)malloc(sizeof(char)*10);
	cStr->filename=(char *)malloc(sizeof(char *)*10);
	for(i=0;i<PARANUM;i++)
		cStr->para[i]=(char *)malloc(sizeof(char)*10);
}

/*释放命令结构体占用的空间*/
void freeSpace(CmdStr *cStr)
{
	int i=0;
	free(cStr->cmd);
	free(cStr->filename);
	for(i=0;i<PARANUM;i++)
	{
		free(cStr->para[i]);
		cStr->para[i]=NULL;
	}
	cStr->cmd=NULL;
	cStr->filename=NULL;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -