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

📄 xiaow-shell.c

📁 linux下shell解释器的进一步完善 附有完整的代码和实验报告
💻 C
字号:
///////*PragramName: Linux Shell 解释器Author:郭晓威 Date:2007/11/15*///////#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<stdlib.h>#include<string.h>#include<wait.h>#include<fcntl.h>#include<errno.h>#include<signal.h>//#include<direct.h>///////************///////////////////////////////////#define MAXNAME 100           //文件名最大长度#define PIPELINE 20               //使用管道连接的最大命令个数#define MAXARG 20               //命令最大的参数个数#define OPEN_MAX 20          //打开的文件个数上限#define MAXLINE 200             //一次执行的命令最大字符数目#define MAXDIR 50                 //当前工作目录名最大字符数#define MAXSAVE 100              //存储的历史命令最大条数#define MAXLEN   50              //参数的最大长度#define FALSE 0#define TRUE 1#define ERROR 0#define OKAY 1#define QUIT -1#define NEXT 2///////**************/////////////////////////////////struct cmd{    int infd;         //输入文件    int outfd;        //输出文件    char* av[MAXARG]; //参数}cmdlin[PIPELINE];   //命令结构struct cmd historyCmd[MAXSAVE];/*int x,z;for(z=0;z<MAXSAVE;z++){    for(x=0;x<MAXARG;x++)        {                historyCmd[z].av[x]=malloc(20);        }}*/int hisNum=0;//////////******************//////////////////////////////////    int lastpid;	int backgnd;	char *lineptr;	char *avptr;	char infile[MAXNAME+1];	char outfile[MAXNAME+1];    char avline[MAXLINE+1];	char line[MAXLINE+1];   		int append;    char curdir[MAXDIR];//////////********函数声明********////////////////////void command(int i);              //将line[]中第i个命令以命令名+参数的形式存储到cmdlin[i]中void execute(int i);              //执行cmdlin[0]到cmdlin[j-1]中的命令(调用forkexec())void forkexec(struct cmd* ptr);   //执行ptr指向的命令 int check(char* ptr);             //在lineptr指向的字符串中查找ptrvoid getname(char* name);         //将lineptr后面的文件名存入nameint parse();                      //将line[]中的字符串以命令加参数的形式存入cmdlin[]中(调用command())int getinline();                  //获取输入命令行,存储到line[]中void initial();                   //初始化void addCmd(struct cmd newCmd);void printHistory();//////////********使用说明********/////////////////////*1)此shell解释器命令格式为 cmd1[<infileName][|cmd2][|cmd3]...[|cmdn][>or>>outfileName][&]2)cmd为命令名+参数形式的命令,<为输入重定向,后跟输入重定向文件名infileName;  >或>>后跟输出重定向文件名,输出内容将写入outfileName,>>表示以追加方式写入文件,>则表示以覆盖方式写入;3)命令结尾可加后台运行符号& ,表示此命令将以后台运行的方式执行4)实现了cd命令5)exit为退出命令6)history为历史命令,可以显示最近执行的命令,最多100条7)!i为执行历史命令,意为执行第i条历史命令。*///////////////////main////////////////////////////////main(){	//分配空间	int x,z;     for(z=0;z<MAXSAVE;z++)     {        for(x=0;x<MAXARG;x++)        {                historyCmd[z].av[x]=malloc(MAXLEN);        }     }	//    int k;	for(;;)	{//Begin:    initial();                     //初始化    int s=getinline();      //获取输入字符串   	if(s==QUIT)	  break;                   //若为exit命令则退出    if(s==OKAY)	{	  if(k=parse())           execute(k);	}        if(s==ERROR)          continue;	       	}       //return k;         //释放空间	     for(z=0;z<MAXSAVE;z++)     {        for(x=0;x<MAXARG;x++)        {                free(historyCmd[z].av[x]);        }     }	}//////////********函数实现********////////////////void initial(){    int i;	backgnd=FALSE;	lineptr=line;	avptr=avline;	infile[0]='\0';	outfile[0]='\0';	append=FALSE;	    for(i=0;i<PIPELINE;++i)	{	    cmdlin[i].infd = 0;		cmdlin[i].outfd = 1;	}	for(i=3;i<OPEN_MAX;++i)	    close(i);       // curdir=get_current_dir_name();      	getcwd(curdir,MAXDIR);//==NULL) printf("error!");//获取当前工作目录        //curdir=(char*)get_curent_dir_name();         //getwd(curdir);	printf("[xiaow-shell@ %s:]#",curdir);	fflush(stdout);}int getinline(){    int i;       	for(i=0;(line[i]=getchar())!='\n'&&i<MAXLINE;++i); 	if(i==MAXLINE)	{	    fprintf(stderr,"Command line too long\n");	    return(ERROR);	}	line[i+1]='\0';	if(strcmp(line,"exit\n")==0) return QUIT;	return(OKAY);}int parse(){    int i;		command(0);    if(check("<"))	  getname(infile);	for(i=1;i<PIPELINE;++i)	    if(check("|"))		   command(i);		else		   break;		if(check(">"))	{	   if(check(">"))	      append=TRUE;        	    getname(outfile);	}		if(check("&"))	   backgnd=TRUE; 	if(check("\n"))	   return(i);	else	{	  fprintf(stderr,"Command line syntax error\n");	  return(ERROR);	}}void command(int i){    int j,flag,inword;	for(j=0;j<MAXARG-1;++j)	{	   while(*lineptr==' '||*lineptr=='\t')	        ++lineptr;	   cmdlin[i].av[j]=avptr;	   cmdlin[i].av[j+1]=NULL;		for(flag=0;flag==0;)		{		    switch(*lineptr)			{			    case '>':				case '<':				case '|':				case '&':				case '\n':				     if(inword==FALSE)					    cmdlin[i].av[j]=NULL;					 *avptr++='\0';					 return;				case' ':				case'\t':				    inword=FALSE;					*avptr++='\0';					flag=1;					break;				default:				    inword=TRUE;					*avptr++=*lineptr++;					break;			}		}	} }void execute(int j){    int i,fd,fds[2];			if(infile[0]!='\0')	   cmdlin[0].infd=open(infile,O_RDONLY);		if(outfile[0]!='\0')	   if(append==FALSE)	      cmdlin[j-1].outfd=open(outfile,O_WRONLY|O_CREAT|O_TRUNC,0666);	    else	      cmdlin[j-1].outfd=open(outfile,O_WRONLY|O_CREAT|O_APPEND,0666);		if(backgnd==TRUE)	  signal(SIGCHLD,SIG_IGN);	else	  signal(SIGCHLD,SIG_DFL);        if(strcmp(cmdlin[0].av[0],"history")==0)		    {			    printHistory();                           // addCmd(cmdlin[i]);				return;		    } 		for(i=0;i<j;++i)	{	   	   if(i<j-1)	   {	      pipe(fds);		  cmdlin[i].outfd=fds[1];		  cmdlin[i+1].infd=fds[0];			   }           if(strcmp(cmdlin[i].av[0],"cd")==0)              //cd 命令              {                if(chdir(cmdlin[i].av[1])) {printf("cd:error!"); return;}                addCmd(cmdlin[i]);                return;	      }           if(cmdlin[i].av[0][0]=='!')           {           int dex=cmdlin[i].av[0][1]-'0';           if(strcmp(historyCmd[hisNum-dex].av[0],"cd")==0)       //history cd 命令                    {                if(chdir(historyCmd[hisNum-dex].av[1])) {printf("cd:error!"); return;}                return;	          }           }           		  	   forkexec(&cmdlin[i]);           if(cmdlin[i].av[0][0]!='!')              addCmd(cmdlin[i]);	   	  	   if((fd=cmdlin[i].infd)!=0)	      close(fd);	   if((fd=cmdlin[i].outfd)!=1)	      close(fd);	}			if(backgnd==FALSE)	   while(wait(NULL)!=lastpid);}void forkexec(struct cmd* ptr){    int pid;    int i;			if(pid=fork())	{	 	  if(backgnd==TRUE)	    printf("%d\n",pid);	  lastpid=pid;	}	else	{	  	  if(ptr->infd==0&&backgnd==TRUE)	     ptr->infd=open("/dev/null",O_RDONLY);	 	  if(ptr->infd!=0)	  {	    close(0);		dup(ptr->infd);	  }	  if(ptr->outfd!=1)	  {	    close(1);		dup(ptr->outfd);	  }	  		  if(backgnd==FALSE)	  {	    signal(SIGINT,SIG_DFL);	    signal(SIGQUIT,SIG_DFL);	  }	  		  for(i=3;i<OPEN_MAX;++i)	  {close(i);}              if(ptr->av[0][0]=='!')              {                int index=ptr->av[0][1]-'0';                                execvp(historyCmd[hisNum-index].av[0],historyCmd[hisNum-index].av);                return;                }         if(execvp(ptr->av[0],ptr->av)==-1)      {       printf("%s:Cannot find this comond!\n",ptr->av[0]);       exit(1);      }     //addCmd(*ptr);      	}}int check(char* ptr){    char* tptr;	while(*lineptr==' ')	   lineptr++;	tptr=lineptr;	while(*ptr!='\0'&&*ptr==*tptr)	{	   ptr++;	   tptr++;	}	if(*ptr!='\0')	   return(FALSE);	else	{	  lineptr=tptr;	  return(TRUE);	}}void getname(char* name){    int i;	for(i=0;i<MAXNAME;++i)	{	   switch(*lineptr)	   {	     case '>':		 case '<':		 case '|':		 case '&':		 case ' ':		 case '\t':		 case '\n':		      *name='\0';			  return;		default:		      *name++=*lineptr++;			  break;	   }	}	*name='\0';}void addCmd(struct cmd newCmd){   // historyCmd[hisNum++]=newCmd;   int s;   char* p;   char* tp;   /*for(s=MAXSAVE-1;s>0;s--)   {     historyCmd[s]=historyCmd[s-1];   }*/   if(hisNum<MAXSAVE)   {   for(s=0;newCmd.av[s]!=NULL;s++)   {	   tp=historyCmd[hisNum].av[s];	   p=newCmd.av[s];	   while(*p!='\0')	   {            *tp++=*p++;	   }	   *tp='\0';    }  for(;s<MAXARG;s++)     historyCmd[hisNum].av[s]=NULL;  hisNum++;       }  else    printf("Cannot save so much!");}void printHistory(){    int k;    int ps;    for(k=hisNum-1;k>=0;k--)	    {             printf("%d:",hisNum-k);		ps=0;		while(historyCmd[k].av[ps]!=NULL)                printf("%s ",historyCmd[k].av[ps++]);		printf("\n");            }}

⌨️ 快捷键说明

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