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

📄 shell.c

📁 MIPS下的boottloader yamon 的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
								case '\0' :
									rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
									break;
								case '$' :
								case '\\':
								case '\'':
								case '"' :
								case ' ' :
								default  :
									expanded[len++] = *ch;
									state = STATE_EXP_QUOTE_SINGLE;
									break;
								}
								break;
								case STATE_EXP_QUOTE_DOUBLE_SPECIAL :
									switch( *ch )
									{
									case '\0' :
										rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
										break;
									case '$' :
									case '\\':
									case '\'':
									case '"' :
									case ' ' :
									default  :
										expanded[len++] = *ch;
										state = STATE_EXP_QUOTE_DOUBLE;
										break;
									}
									break;
									case STATE_EXP_QUOTE_DOUBLE_ENV :
										switch( *ch )
										{
										case '\0' :
											rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
											break;
										case '$'  :
											rc = add_env( env_name, env_len, expanded, &len );
											env_len = 0;
											state = STATE_EXP_QUOTE_DOUBLE_ENV;
											break;
										case '\\' :
											rc = add_env( env_name, env_len, expanded, &len );
											expanded[len++] = *ch;
											state = STATE_EXP_QUOTE_DOUBLE_SPECIAL;
											break;
										case '"' :
											rc = add_env( env_name, env_len, expanded, &len );
											expanded[len++] = *ch;		
											state = STATE_EXP_NORMAL;
											break;
										case '\'' :
										case ' '  :
											rc = add_env( env_name, env_len, expanded, &len );
											expanded[len++] = *ch;		
											state = STATE_EXP_QUOTE_DOUBLE;
											break;
										default   :
											env_name[env_len++] = *ch;
											state = STATE_EXP_QUOTE_DOUBLE_ENV;
											break;
										}
										break;
										default : /* Should not happen */
											rc = SHELL_ERROR_STRUCTURE;
											break;
	}
	
	if( (len == SHELL_MAX_COMMAND_LEN + 1) && (state != STATE_EXP_DONE) )
		rc = SHELL_ERROR_PARSE_LONG_LINE;
	
	if( env_len == SHELL_MAX_ENV_LEN + 1 )
		rc = SHELL_ERROR_PARSE_LONG_ENV;
	
	ch++;
    }
    while( (rc == OK) && (state != STATE_EXP_DONE) );
    
    if( rc != OK )
        return rc;
    else
    {
        strcpy( line, expanded );
        return OK;
    }
}


/************************************************************************
*                          add_env
************************************************************************/
static UINT32
add_env(
		char   *env_name,
		UINT32 env_len,
		char   *expanded,
		UINT32 *len_expanded )
{
    char   *env_val;
    UINT32 env_val_len;
    UINT32 i;
	
    env_name[env_len]       = '\0';
    expanded[*len_expanded] = '\0';
	
    /* Lookup env variable */
    if( env_get( env_name, &env_val, NULL, 0 ) )
    {
        *len_expanded += strlen(env_val);
		
        if( *len_expanded > SHELL_MAX_COMMAND_LEN )
            return SHELL_ERROR_PARSE_LONG_LINE;
		else
		{
            strcat( expanded, env_val );
			return OK;
		}
    }
    else
        return SHELL_ERROR_PARSE_UNKNOWN_ENV;
}


/************************************************************************
*                          tokenize
************************************************************************/
static UINT32
tokenize( 
		 char *line )
{
    bool	      quote_double = FALSE;
    bool	      quote_single = FALSE;
    bool              special	= FALSE;
    t_tokenize_state  state;
    char	      *s;
    UINT32	      len;
    UINT32	      rc;
	
    state = STATE_TOKENIZE_SEARCH;
    argc  = 0;
    len   = 0;
    s     = argv[argc];
    rc	  = OK;
	
    do
    {
        switch( state )
		{
		case STATE_TOKENIZE_SEARCH :
			switch( *line )
			{
			case '\\' :
				state = STATE_TOKENIZE_SPECIAL;
				break;
			case '\'' :
				state = STATE_TOKENIZE_QUOTE_SINGLE;
				break;
			case '"'  :
				state = STATE_TOKENIZE_QUOTE_DOUBLE;
				break;
			case ' ' :
				state = STATE_TOKENIZE_SEARCH;
				break;
			case '\0' :
				state = STATE_TOKENIZE_DONE;
				break;
			default :
				if( argc == MAX_ARGC )
					rc = SHELL_ERROR_PARSE_ARGCOUNT;
				else
				{
					*s = *line;
					s++;
					len++;
					state = STATE_TOKENIZE_WORD;
				}
				break;
			}
			break;
			case STATE_TOKENIZE_SPECIAL :
				switch( *line )
				{
				case '\0' :
					state = STATE_TOKENIZE_DONE;
					break;
				case '\\' :
				case '\'' :
				case '"'  :
				default   :
					if( argc == MAX_ARGC )
						rc = SHELL_ERROR_PARSE_ARGCOUNT;
					else if( len == SHELL_MAX_TOKEN_LEN )
						rc = SHELL_ERROR_PARSE_LONG_TOKEN;
					else
					{
						*s = *line;
						s++;
						len++;
						state = STATE_TOKENIZE_WORD;
					}
					break;
				}
				break;
				case STATE_TOKENIZE_QUOTE_DOUBLE :
					switch( *line )
					{
					case '\\' :
						state = STATE_TOKENIZE_QUOTE_DOUBLE_SPECIAL;
						break;
					case '"'  :
						state = STATE_TOKENIZE_WORD;
						break;
					case '\0' :  /* Should not happen */
						rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
						break;
					case ' ' :
					case '\'' :
					default  :
						if( argc == MAX_ARGC )
							rc = SHELL_ERROR_PARSE_ARGCOUNT;
						else if( len == SHELL_MAX_TOKEN_LEN )
							rc = SHELL_ERROR_PARSE_LONG_TOKEN;
						else
						{
							*s = *line;
							s++;
							len++;
							state = STATE_TOKENIZE_QUOTE_DOUBLE;
						}
						break;
					}
					break;
					case STATE_TOKENIZE_QUOTE_SINGLE :
						switch( *line )
						{
						case '\\' :
							state = STATE_TOKENIZE_QUOTE_SINGLE_SPECIAL;
							break;
						case '\''  :
							state = STATE_TOKENIZE_WORD;
							break;
						case '\0' :  /* Should not happen */
							rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
							break;
						case ' ' :
						case '"' :
						default  :
							if( argc == MAX_ARGC )
								rc = SHELL_ERROR_PARSE_ARGCOUNT;
							else if( len == SHELL_MAX_TOKEN_LEN )
								rc = SHELL_ERROR_PARSE_LONG_TOKEN;
							else
							{
								*s = *line;
								s++;
								len++;
								state = STATE_TOKENIZE_QUOTE_SINGLE;
							}
							break;
						}
						break;
						case STATE_TOKENIZE_QUOTE_DOUBLE_SPECIAL :
							switch( *line )
							{
							case '\0' :  /* Should not happen */
								rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
								break;
							case '\\' :
							case '\'' :
							case '"'  :
							default   :
								if( argc == MAX_ARGC )
									rc = SHELL_ERROR_PARSE_ARGCOUNT;
								else if( len == SHELL_MAX_TOKEN_LEN )
									rc = SHELL_ERROR_PARSE_LONG_TOKEN;
								else
								{
									*s = *line;
									s++;
									len++;
									state = STATE_TOKENIZE_QUOTE_DOUBLE;
								}
								break;
							}
							break;
							case STATE_TOKENIZE_QUOTE_SINGLE_SPECIAL :
								switch( *line )
								{
								case '\0' :  /* Should not happen */
									rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
									break;
								case '\\' :
								case '\'' :
								case '"'  :
								default   :
									if( argc == MAX_ARGC )
										rc = SHELL_ERROR_PARSE_ARGCOUNT;
									else if( len == SHELL_MAX_TOKEN_LEN )
										rc = SHELL_ERROR_PARSE_LONG_TOKEN;
									else
									{
										*s = *line;
										s++;
										len++;
										state = STATE_TOKENIZE_QUOTE_SINGLE;
									}
									break;
								}
								break;
								case STATE_TOKENIZE_WORD :
									switch( *line )
									{
									case '\\' :
										state = STATE_TOKENIZE_WORD_SPECIAL;
										break;
									case '\'' :
										state = STATE_TOKENIZE_QUOTE_SINGLE;
										break;
									case '"'  :
										state = STATE_TOKENIZE_QUOTE_DOUBLE;
										break;
									case '\0' :
										if( argc == MAX_ARGC )
											rc = SHELL_ERROR_PARSE_ARGCOUNT;
										else
										{
											*s = *line;
											argc++;
											state = STATE_TOKENIZE_DONE;
										}
										break;
									case ' ' :
										if( argc == MAX_ARGC )
											rc = SHELL_ERROR_PARSE_ARGCOUNT;
										else
										{
											*s  = '\0';
											argc++;
											s     = argv[argc];
											len   = 0;
											state = STATE_TOKENIZE_SEARCH;
										}
										break;
									default :
										if( argc == MAX_ARGC )
											rc = SHELL_ERROR_PARSE_ARGCOUNT;
										else if( len == SHELL_MAX_TOKEN_LEN )
											rc = SHELL_ERROR_PARSE_LONG_TOKEN;
										else
										{
											*s = *line;
											s++;
											len++;
											state = STATE_TOKENIZE_WORD;
										}
										break;
									}
									break;
									case STATE_TOKENIZE_WORD_SPECIAL :
										switch( *line )
										{
										case '\0' :
											if( argc == MAX_ARGC )
												rc = SHELL_ERROR_PARSE_ARGCOUNT;
											else
											{
												*s = *line;
												argc++;
												state = STATE_TOKENIZE_DONE;
											}
											break;
										case '\\' :
										case '\'' :
										case '"'  :
										default   :
											if( argc == MAX_ARGC )
												rc = SHELL_ERROR_PARSE_ARGCOUNT;
											else if( len == SHELL_MAX_TOKEN_LEN )
												rc = SHELL_ERROR_PARSE_LONG_TOKEN;
											else
											{	      
												*s = *line;
												s++;
												len++;
												state = STATE_TOKENIZE_WORD;
											}
											break;
										}
										break;
										default : /* Should not happen */
											rc = SHELL_ERROR_STRUCTURE;
											break;
	}
	
	line++;
    }
    while( (rc == OK) && (state != STATE_TOKENIZE_DONE) );
	
    return rc;
}


/************************************************************************
*                          execute_command
************************************************************************/
static UINT32
execute_command( 
				t_cmd  **cmd )
{
    bool   ambivalent;
    UINT32 rc;
    
    if( argc != 0 )
    {
        *cmd = shell_lookup_cmd( argv[0], &ambivalent, NULL,
			command_list, command_count );
		
        if( !(*cmd) )
        {
            shell_error_data = argv[0];
            return SHELL_ERROR_COMMAND_NOT_FOUND;
        }
		
        if( ambivalent )
		{
            shell_error_data = argv[0];
			return SHELL_ERROR_AMBIVALENT;
        }
		
        SHELL_ENABLE_MORE;
		
        if( !newline_after_prompt )
		{
			SHELL_PUTC( '\n' );
			newline_after_prompt = TRUE;
		}
		
        if( (strlen((*cmd)->name) == 1) && (*(*cmd)->name != '.') )
        {
		/* Notify that this is a special Microsoft
		* SDB command.
			*/
            SHELL_PUTS( "Microsoft SDB Command\n" );
        }
		
        /* We detect whether ctrl-c is typed during command execution */
        ctrl_c_flag = FALSE;
		
        /* Execute command */
        rc = (*cmd)->func( argc, &argv[0] );
		
        SHELL_DISABLE_MORE;
		
        if( rc != OK )
			return rc;
    }
    else
        ctrl_c_flag = FALSE;
	
    /*  Test for CTRL-C in case command did not call shell_putc/s. */
    if( !ctrl_c_flag )
        ctrl_c_flag = GETCHAR_CTRLC( DEFAULT_PORT );
	
    return ctrl_c_flag ? SHELL_ERROR_CONTROL_C_DETECTED : OK;
}


/************************************************************************
*                          execute_line
************************************************************************/
static UINT32
execute_line( 
			 char *line,		/* Command line					*/
			 bool first )	/* First call (ie not recursively called)	*/
{
    char   buffer[SHELL_MAX_COMMAND_LEN + 1];
    char   subcommand[SHELL_MAX_COMMAND_LEN + 1];
    char   *line_copy;
    char   *first_subcommand;
    UINT32 count, subcommand_count;
    UINT32 repeat_count = 1;
    UINT32 rc;
    UINT32 len;
    t_cmd  *cmd;
	
    line_copy = buffer;
	
    strcpy( line_copy, line );
	
    /* Separate line in subcommands based on ';' characters */
    separate( line_copy, &subcommand_count );
	
    if( first )
    {
        if( subcommand_count > 1 )
		{
			/* Determine repeat (+<n>) count */
			len = strlen(line_copy);
			
			if( get_repeat( line_copy, &repeat_count ) )
			{
				line_copy = &line_copy[len + 1];
				subcommand_count--;
			}
		}
    }
	
    first_subcommand = line_copy;
	
    do		     /* Loop based on repeat (+<n>) count */
    {
        line_copy = first_subcommand;
		count     = subcommand_count;
		
		do	     /* Perform each subcommand */
		{
            strcpy( subcommand, line_copy );
			cmd = NULL;
			
			if( first )
			{
				/* Perform expansion of environment variables */
				rc = expand_line( subcommand );
				
				if( rc == OK ) 
				{
					/* Execute the line */
					rc = execute_line( subcommand, FALSE );
					
					if( rc != OK ) 
						return rc;
				}
			}
			else
			{
				rc = tokenize( subcommand );
				
				if( rc == OK )
					rc = execute_command( &cmd );
            }
			
			if( rc != OK )
			{
				if( !newline_after_prompt )
					printf( "\n" );
				
                shell_command_error( cmd, rc );
                shell_error_data = NULL;
				shell_error_hint = NULL;
			}
			
			line_copy = &line_copy[strlen(line_copy) + 1];
		}
		while( --count && (rc == OK) );
    }
    while( ((repeat_count == 0) || --repeat_count) && (rc == OK) );
	
    return rc;
}


/************************************************************************
*                          error_lookup
************************************************************************/
static INT32 
error_lookup( 
			 t_sys_error_string *param )
{
    UINT32 index = SYSERROR_ID( param->syserror );
	
    if( index >= SHELL_ERROR_MSG_COUNT )
        index = SHELL_ERROR_MSG_COUNT - 1;
	
    shell_error_msg[0] = '\0';
	
    add2error( shell_err[index] );
	
    if( shell_error_data )
    {
        add2error( " : " );
		add2error( shell_error_data );
		shell_error_data = NULL;
    }
	
    if( (param->syserror == SHELL_ERROR_SYNTAX) && failing_cmd && (failing_cmd->syntax) )
    {
		add2error( "\nSyntax : " );
		add2error( failing_cmd->syntax );
    }
	
    param->strings[SYSCON_ERRORMSG_IDX] = shell_error_msg;
	
    if( shell_error_hint )
    {
        param->strings[SYSCON_DIAGMSG_IDX] = NULL;
        param->strings[SYSCON_HINTMSG_IDX] = shell_error_hint;       
        param->count = 2;
    }
    else
        param->count = 1;
	
    return OK;
}


/************************************************************************
*                          add2error
************************************************************************/
static void
add2error(
		  char *s )
{
    UINT32 len, count;
	
    len   = strlen( shell_error_msg );
    count = strlen(s);
	
    if( len + count + 1 > MAX_SHELL_ERR_MSG )
        count = MAX_SHELL_ERR_MSG - len - 1;
	
    strncpy( &shell_error_msg[len], s, count );
	
    shell_error_msg[len+count] = '\0';
}

⌨️ 快捷键说明

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