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

📄 utility.c

📁 用纯C语言编写的一个Linux下的Shell
💻 C
📖 第 1 页 / 共 3 页
字号:
// 支持外部命令#include "myshell.h"

int back_bat=0; //  标志既是后台运行,又是批处理;值为1有效。
int output_num=0; //  批处理的输出重定向个数
char batchfile[MAX_PATH] ; //  当前的批处理文件
int bat_line=0;// 批处理的命令行数
int isbat=0;// 批处理标志int letter; //   used in my_strtok( )   Error( )char *open; //   used in my_strtok( )   Error( )

/* ******************************* 辅助函数 ******************************* */ 

/*   Function "my_strtok" : used to <1> token the input command line(stored in buf[]) into args[], 
                                    <2> record background execute,argc,etc in states[]  
                                    <3> record the indirection files and outdirection filesget */
int my_strtok(char *buf,char **args,int *states,Redirect *Inputs,Redirect *Outputs) // InPut和OutPuts记录重定向
{      
     int i,j,n,m, flag,argc,errortype;   // flag是空白标记;argc是参数个数(不包括重定向和后台运行)
     char c ; 
     states[0]=states[1]=states[2]=states[3]=states[4]=0;// states[0]是后台运行标志;states[1]是输入重定向个数;states[2]是输出重定向个数;                                                         //states[3]是参数个数; states[4]标记输入重定向在键盘输入之前;
     errortype=letter=argc=0;     args[0]=NULL;       open=NULL;// open  是打开方式;
     flag=1;
     i=m=n=-1;  
     while(buf[++i]&&buf[i]!='#')    //扫描命令行,  容许用户把 '#'  用于注释
      {             
    	    c=buf[i]; 
     	    switch(c)             //  字符解析
			{                       
               case '<':  letter++;                            if(flag==0)
						  {   
			                  flag=1;	
		                      buf[i]='\0';	
						  }
                           open="<"; // "r" opentype  
		                   while(buf[++i]==' '|| buf[i]=='\t'); // // 跳过多个连续的空格  
					    
		                  if(buf[i]<32|| buf[i]=='#' ) // invlid argument '<', without inputfile!
						  {                                  errortype=Error(1,NULL,NULL,NULL,"<");//     invlid argument '<', without inputfile! 
			                     break; 
						  }
                          else if(buf[i]=='&'|| buf[i]=='<'|| buf[i]=='>'|| buf[i]=='|'|| buf[i]==';') // can not  be    <&    <;   <<   <>     <|    
						  {
			                           letter++; 
			                           errortype=Error(2,NULL,NULL,NULL,buf+i);
			                           break;
						  }				  
		             
		                  if(argc<2)
		                        states[4]=1;
			              m++;                               
		                  i--;  						  	  
		              	  break; 
                        
	            case '>':  letter++; 
			               if(flag==0)					  
						   {    flag=1;					      
		                        buf[i]='\0'; 
						   }	                           n++;				                      
					       if(buf[i+1]=='>') 					    
						   {    buf[++i]='\0';						       			 
						        open=">>"; // "a" opentype 
						   } 
					       else   open=">";  //  "w" opentype 
					           
					  
					      while(buf[++i]==' '|| buf[i]=='\t'); 	// 跳过多个连续的空格      
					  
					      if(buf[i]<32|| buf[i]=='#' )
						  {    						
						      errortype=Error(1,NULL,NULL,NULL,NULL);
						       break; 
						  }
                           else if(buf[i]=='&'|| buf[i]=='<'|| buf[i]=='>'|| buf[i]=='|' || buf[i]==';') // can not be   >&   <;  ><  <|    
						   {
                              letter++; 						
						      errortype=Error(2,NULL,NULL,NULL,buf+i); 
						      break; 
					      }
                           i--; 
					       break; 
					  
	              case '&':  letter++;
			                 if(flag==0)					  
							 {  flag=1;    
                                buf[i]='\0';
							 }
					         if(states[0]) 					  							 {                                   errortype= Error(0,NULL,NULL,NULL,"Format Error: argument '&' occurs more than once!"); 						
						         break; 
							 }			           
					         states[0]=1; 				           
					         break;
	  
		      case ' ':
	          case '\t': 	 if(flag==0) 
							 {	
					             flag=1; 
						         buf[i]='\0'; 		  
							 } 
					         while(buf[++i]==' '|| buf[i]=='\t');  // 跳过多个连续的空格      
					        i--;
					        break; 

		     case '\n':
		     case '\r':	  buf[i]='\0';
					      i--;
					      break; 					  
		     default: 	 letter++; 
			             if(flag)					   
						 {   flag=0;                             if(open&&m<=MAX_OPEN&&n<=MAX_OPEN)
				 	          {                                   if(m==MAX_OPEN)// too many  input redirections ////////                                                                                                                                      errortype=Error(5,NULL,NULL,NULL,"input");	                                                                                                                               else if(n==MAX_OPEN)// too many  output redirections ////////                                                                                                              errortype=Error(5,NULL,NULL,NULL,"output");                                                                                                        else if( !strcmp(open,"<" ) )
						                   Inputs[m].filename=buf+i;                                                                                                       
					                else  if( !strcmp(open,">>" ) )									{                                        strcpy(Outputs[n].opentype,"a");                                         strcpy(Outputs[n].open,">>");                                         Outputs[n].filename=buf+i;                                     }					                else  if( !strcmp(open,">" ) )                                     {                                          strcpy(Outputs[n].opentype,"w");                                              strcpy(Outputs[n].open,">"); 
                                            Outputs[n].filename=buf+i;                                     }
						           open=NULL;							 }					      
					         else args[argc++]=buf+i;
					    }
				   	    if(c=='\\'  &&buf[i+1]==' ')//转义字符  e.g.   "a\ b"   means "a b"  in filename or directoryname                            {     buf[i]=' ';                                if( ! isspace(buf[i+2]))                                 {                                             j=i+1;                                         while(  buf[++j])  buf[j-1]=buf[j];                                   }                                                                                                                      						}  	
		} // end switch
	 } // end for loop
     args[argc]=NULL; // args end with NULL 
	 states[1]=m+1;//   0,12,...,m
	 states[2]=n+1;//  0,1,2,...,n
	 states[3]=argc;
	 if(errortype||(argc==0&&letter))     // if there's anything there         Error(0,NULL,NULL,NULL,"Warning: nothing will be executed!");//	       
    return errortype;  // errortype==0 is ok ;					
}

/*  Function "my_shell" : keep reading a line from stdin or inputfile and call "Execute()" to execute the command line.  */ 
int my_shell(FILE *inputfile,const Redirect *Outputs,const int *states) // 
{	       
	FILE *outputfile;
	char filepath[MAX_PATH];
	char buf[MAX_BUFFER];
    int done=0;  //

	if(Outputs)
	{
	   get_fullpath(filepath,Outputs->filename);
       outputfile=freopen(filepath,Outputs->opentype,stdout);
	   if(outputfile==NULL)
	   {      Error(-6,NULL,NULL,NULL,Outputs->filename);		
	           return -2;///
	   }
	   fprintf(stderr,"\nThe results will be writen into file \"%s\".\n",Outputs->filename); 
	}
     
	 bat_line=0;
       do    // /* keep reading input until "quit" command or eof of redirected input */
           {        /* get command line from input */
                 if (inputfile==stdin&&Outputs==NULL)  ///////////////////////////////
			     fprintf(stderr,"\n[%s@%s] :) ",getenv("USERNAME"),getenv("PWD"));  // write prompt     		
                  if (fgets(buf, MAX_BUFFER, inputfile))  // read  a  line
				  {  			 
			          bat_line++; 		
		              done=Execute(buf);    //
		              if(done==1) // "quit" command is executed 
                        {  
                           if(Outputs) 
		                       freopen("/dev/tty", "w", stdout);
			               break;//exit(0);  
                         }		                      
				  }		 
	    }  while (!feof(inputfile));  //  do ... while( );    
	if(Outputs) 
		freopen("/dev/tty", "w", stdout);
	return 0; 
}

/*  Function "Execute" : used as the function system( ), it  interpret the input, and call function "my_spawn" to  execute the all the commands.  */ 
int Execute(char *buffer) // ,const int line,const int isBatchMode)
{      
	pid_t pid ;
	char *args[MAX_ARGS];  /// pointers to arg strings
	int error ;
	int states[5]; // states[0] is back exec; states[1] is inputfile num; states[2] is outputfile num ;
	                          // states[3] is priority of inputfile(not args); states[4] is argc ; 
    Redirect  Inputs [MAX_OPEN];  //   input    redirection (10个) 
    Redirect  Outputs[MAX_OPEN]; //   output   redirection   (10)

     error=my_strtok(buffer,args,states,Inputs,Outputs);// tokenize  input, last  entry  will  be  NULL
	 if(error||args[0]==NULL) return -1; // 如果出现输入格式错误	or  if there's anything there 

	 if ( !strcmp(args[0],"quit") || !strcmp(args[0],"exit"))   // "quit" command
		  {
             if(args[1])   //   no argument is needed after "quit"                  Error(-2,args+1,NULL,NULL,args[0]); ///
			
			 if(output_num>1)// e.g.  myshell a.bat >m.txt >n.txt 						 
             {   fprintf(stderr,"Exit!\n");
				   return 1; 
			 }
			 
             if(isbat)   // /
				 fprintf(stderr,"Execution of batch file \"%s\" is finished!\n",batchfile);
			 else fprintf(stderr,"Exit MyShell, Goodbye!\n\n"); 
			 exit (0);      // break out of 'while (!feof(stdin))' loop in "main" function			               
		  }

	     else if(states[0])// states[0]==1  后台执行
		 {                    
              switch (pid=fork( ))
				   {
                        case -1:   Error(-9,NULL,NULL,states,"fork");
                        case  0:  // child   //sleep(1); 
                                    my_delay(12);                                                
                                     fprintf(stderr,"\n");                                                                       
                                     my_spawn(args,Inputs,Outputs,states);                                            exit(1);                   
	                     default:  if(isbat==0) // 
					                   fprintf(stderr,"pid=%d\n",pid);
				}// end switch	     
		 }
	     else // states[0]==0  前台执行  
                  my_spawn(args,Inputs,Outputs,states);                          

   return 0;     
}

/*  Function "my_spawn"  :  used to exeute the command   */
int my_spawn(char **args, const Redirect *Inputs,const Redirect *Outputs,int *states)
{        
        char filepath[MAX_PATH] , parent[MAX_ARGS] ;   
        FILE * outputfile=NULL,* inputfile;    
         pid_t newpid;
        int flag; //, //external=0 ;
       
        if (!strcmp(args[0],"myshell")||!strcmp(args[0],"shell"))   // "myshell" command 
		{
			flag=0; 
			if(isbat)//     e.g.   在  a.bat里执行  myshell b.txt
			{
				switch(newpid=fork( ))
				{  case -1:  Error(-9,NULL,NULL,states,"fork");
				   case 0:	                              if(states[0] &&(args[1]|| states[1]))
							 {  back_bat++;	
					             flag=1;
							 }                                                                  
					        output_num=states[2];                                                       
			                 my_bat(args,Inputs,Outputs,states);   //     
		                     if(flag)   back_bat--;
							 output_num=0;
							 exit (0);
				   default:  waitpid(newpid, NULL, WUNTRACED); 
				}
			}
			else 
			{   

⌨️ 快捷键说明

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