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

📄 utility.c

📁 应用UNIX的fork()等系统调用
💻 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';
						  //n++;						 
						  open=">>"; // "a" opentype 
					  } 
					  else 	{   
						           //  n++; 						            
						              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 ;
       
        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;

⌨️ 快捷键说明

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