📄 shell.c
字号:
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 + -