📄 shell.c
字号:
/************************************************************************
* get_next
************************************************************************/
static bool
get_next(
t_shell_line_buf *buf,
UINT32 *current_from_buf,
char *line )
{
if( buf->first == BUFFER_NU )
return FALSE;
if( *current_from_buf == buf->free )
return FALSE;
/* Move forward */
do
{
INCWRAP(*current_from_buf, BUFFERSIZE);
}
while( buf->data[*current_from_buf] != '\0' );
INCWRAP(*current_from_buf, BUFFERSIZE);
if( *current_from_buf == buf->free )
{
line[0] = '\0';
}
else
{
/* Do the copy */
copybuf( line, buf->data, *current_from_buf, BUFFERSIZE );
}
return TRUE;
}
/************************************************************************
* copy_buf
************************************************************************/
static void
copybuf(
char *dst,
char *src,
UINT32 pos,
UINT32 bufsize )
{
do
{
*dst = src[pos];
INCWRAP(pos, bufsize );
}
while( *(dst++) != '\0' );
}
/************************************************************************
* decode_option
************************************************************************/
static bool
decode_option(
t_shell_option *decode,
UINT32 *type,
char *token )
{
if( *token == '-' )
{
decode->option = &token[1];
*type = SHELL_TOKEN_OPTION;
return TRUE;
}
else
return FALSE;
}
/************************************************************************
* decode_ip
************************************************************************/
static bool
decode_ip(
t_shell_option *decode,
UINT32 *type,
char *token )
{
if( env_ip_s2num( token, (void *)&decode->ip, sizeof(decode->ip)) )
{
*type = SHELL_TOKEN_IP;
return TRUE;
}
else
return FALSE;
}
/************************************************************************
* insert_char
************************************************************************/
static void
insert_char(
char *line,
UINT32 *cursor,
UINT32 *eol,
char ch )
{
UINT32 i;
/* Move characters after cursor and insert new character */
for( i = *eol; i > *cursor; i-- )
line[i] = line[i-1];
line[i] = ch;
/* Increase line length and add new termination */
(*eol)++;
line[*eol] = '\0';
/* Print line from cursor */
printf( &line[*cursor] );
/* Increase cursor */
(*cursor)++;
/* Move cursor back */
moveleft(*eol - *cursor);
}
/************************************************************************
* delete_char
************************************************************************/
static void
delete_char(
char *line,
UINT32 *cursor,
UINT32 *eol )
{
UINT32 i;
/* Move characters after cursor and insert new character */
for( i = *cursor; i < *eol; i++ )
line[i] = line[i+1];
/* Print line from cursor, add space */
printf( "%s ", &line[*cursor] );
/* Move cursor back */
moveleft( *eol - *cursor );
/* Decrease line length */
(*eol)--;
}
/************************************************************************
* delete_from_cursor
************************************************************************/
static void
delete_from_cursor(
UINT32 cursor,
UINT32 *eol)
{
char spaces[SHELL_MAX_LINE_LEN + 1];
UINT32 i;
/* Replace characters to the right of cursor with spaces */
for(i=0; i < (*eol - cursor); i++)
spaces[i] = ' ';
spaces[i] = '\0';
printf( spaces );
/* Move cursor back */
moveleft( *eol - cursor );
/* Move eol to cursor location */
*eol = cursor;
}
/************************************************************************
* delete_line
************************************************************************/
static void
delete_line(
UINT32 *cursor,
UINT32 *eol )
{
moveleft( *cursor );
*cursor = 0;
delete_from_cursor(*cursor, eol );
}
/************************************************************************
* add2buf
************************************************************************/
static void
add2buf(
t_shell_line_buf *buf,
char *line )
{
UINT32 current_from_buf;
char previous_line[SHELL_MAX_COMMAND_LEN + 1];
UINT32 len, i;
current_from_buf = buf->free;
/* Check for identical command on stack */
if( get_previous( buf, ¤t_from_buf, previous_line ) &&
strcmp( line, previous_line ) == 0 )
{
return;
}
/* Copy line to buffer */
for( i=0, len = strlen(line); i<=len; i++ )
{
/* Before inserting character, we check if we are about
* to overwrite an old line.
*/
if( buf->free == buf->first )
{
/* We are about to overwrite an old line,
* so obsolete the old line
*/
while(buf->data[buf->first] != '\0')
{
INCWRAP(buf->first, BUFFERSIZE);
}
INCWRAP(buf->first, BUFFERSIZE);
}
/* Now we are ready to insert the character */
buf->data[buf->free] = line[i];
INCWRAP(buf->free, BUFFERSIZE);
/* After moving the free pointer forward, we need to check
* again if 'free' has caught up with 'first'.
*/
if( buf->free == buf->first )
{
/* free did catch up with first, so obsolete the old line. */
while(buf->data[buf->first] != '\0')
{
INCWRAP(buf->first, BUFFERSIZE);
}
INCWRAP(buf->first, BUFFERSIZE);
}
}
/* Buffer is no longer unused */
if( buf->first == BUFFER_NU )
buf->first = 0;
}
/************************************************************************
* command_loop
************************************************************************/
static void
command_loop(
t_shell_line_buf *buf )
{
char line[SHELL_MAX_COMMAND_LEN + 1];
while( TRUE )
{
// print_prompt( PROMPT_TARGET_DISPLAY, PROMPT_TEXT_ENV );
if( !start )
print_prompt( PROMPT_TARGET_TERMINAL, PROMPT_TEXT_ENV );
if( !shell_get_line( line, SHELL_MAX_COMMAND_LEN, TRUE, TRUE, buf ) )
{
printf( "\n" );
}
else
{
/* Remove excess spaces */
remove_space( line );
if( strlen(line) == 0 )
printf( "\n" );
else
{
/* Add line to stack (only "single" lines) */
if( !start && (strlen( line ) <= max_line_len) )
add2buf( buf, line );
/* Recursively split line in ";" separated commands and expand
* environment variables.
* Execute command(s).
*/
newline_after_prompt = FALSE;
execute_line( line, TRUE );
}
}
start = NULL;
}
}
/************************************************************************
* remove_space
************************************************************************/
static void
remove_space(
char *line )
{
char clean[SHELL_MAX_COMMAND_LEN + 1];
UINT32 len = 0;
bool skip;
bool found_char = FALSE;
char *start = line;
bool quote_double = FALSE;
bool quote_single = FALSE;
bool special = FALSE;
while( line[0] != '\0' )
{
skip = FALSE;
/* Remove excess whitespace, unless within single or
* double quotes.
*/
if( line[0] == ' ' )
{
if( !found_char || /* Leading spaces */
(line[1] == ' ') || /* Multiple spaces */
(line[1] == '\0') ) /* Trailing spaces */
{
/* Keep spaces within quotes */
if( !quote_double && !quote_single )
{
skip = TRUE;
}
}
}
else if( line[0] == '\\' )
{
special = !special;
}
else if( (line[0] == '\'') && !special )
{
if( !quote_double )
{
quote_single = !quote_single;
}
}
else if( (line[0] == '"') && !special )
{
if( !quote_single )
{
quote_double = !quote_double;
}
}
else
special = FALSE;
if( !skip )
{
clean[len++] = line[0];
found_char = TRUE;
}
line++;
}
clean[len] = '\0';
strcpy( start, clean );
}
/************************************************************************
* separate
************************************************************************/
static void
separate(
char *line,
UINT32 *subcommand_count )
{
bool quote_double = FALSE;
bool quote_single = FALSE;
bool special = FALSE;
*subcommand_count = 1;
/* Find ';' not within single or double quotes and substitute
* with '\0'
*/
while( line[0] != '\0' )
{
if( (*line == ';') && !quote_double && !quote_single )
{
*line = '\0';
(*subcommand_count)++;
}
else if( *line == '\\' )
{
special = !special;
}
else if( (*line == '\'') && !special )
{
if( !quote_double )
{
quote_single = !quote_single;
}
}
else if( (*line == '"') && !special )
{
if( !quote_single )
{
quote_double = !quote_double;
}
}
else
special = FALSE;
line++;
}
}
/************************************************************************
* get_repeat
************************************************************************/
static bool
get_repeat(
char *line,
UINT32 *loop_count )
{
t_shell_option decode;
UINT32 len;
if( *line == '+' )
{
line++;
/* Remove trailing spaces */
len = strlen( line );
while( len && line[len-1] == ' ' )
{
line[len-1] = '\0';
len--;
}
/* Decode number */
if( shell_decode_number(
&decode,
NULL,
line ) )
{
*loop_count = decode.number;
return TRUE;
}
}
return FALSE;
}
/************************************************************************
* expand_line
************************************************************************/
static UINT32
expand_line(
char *line )
{
char env_name[SHELL_MAX_ENV_LEN + 2];
char expanded[SHELL_MAX_COMMAND_LEN + 1];
UINT32 len, env_len;
t_expand_state state;
char *ch;
UINT32 rc;
state = STATE_EXP_NORMAL;
ch = line;
len = 0;
env_len = 0;
rc = OK;
do
{
switch( state )
{
case STATE_EXP_NORMAL :
switch( *ch )
{
case '\0' :
expanded[len++] = *ch;
state = STATE_EXP_DONE;
break;
case '$' :
env_len = 0;
state = STATE_EXP_ENV;
break;
case '\\' :
expanded[len++] = *ch;
state = STATE_EXP_SPECIAL;
break;
case '\'' :
expanded[len++] = *ch;
state = STATE_EXP_QUOTE_SINGLE;
break;
case '"' :
expanded[len++] = *ch;
state = STATE_EXP_QUOTE_DOUBLE;
break;
case ' ' :
default :
expanded[len++] = *ch;
state = STATE_EXP_NORMAL;
break;
}
break;
case STATE_EXP_ENV :
switch( *ch )
{
case '\0' :
rc = add_env( env_name, env_len, expanded, &len );
expanded[len++] = *ch;
state = STATE_EXP_DONE;
break;
case '$' :
rc = add_env( env_name, env_len, expanded, &len );
env_len = 0;
state = STATE_EXP_ENV;
break;
case '\\' :
rc = add_env( env_name, env_len, expanded, &len );
expanded[len++] = *ch;
state = STATE_EXP_SPECIAL;
break;
case '\'' :
rc = add_env( env_name, env_len, expanded, &len );
expanded[len++] = *ch;
state = STATE_EXP_QUOTE_SINGLE;
break;
case '"' :
rc = add_env( env_name, env_len, expanded, &len );
expanded[len++] = *ch;
state = STATE_EXP_QUOTE_DOUBLE;
break;
case ' ' :
rc = add_env( env_name, env_len, expanded, &len );
expanded[len++] = *ch;
state = STATE_EXP_NORMAL;
break;
default :
env_name[env_len++] = *ch;
state = STATE_EXP_ENV;
break;
}
break;
case STATE_EXP_SPECIAL :
switch( *ch )
{
case '\0' :
expanded[len++] = *ch;
state = STATE_EXP_DONE;
break;
case '$' :
case '\\' :
case '\'' :
case '"' :
case ' ' :
default :
expanded[len++] = *ch;
state = STATE_EXP_NORMAL;
break;
}
break;
case STATE_EXP_QUOTE_SINGLE :
switch( *ch )
{
case '\0' :
rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
break;
case '\\' :
expanded[len++] = *ch;
state = STATE_EXP_QUOTE_SINGLE_SPECIAL;
break;
case '\'' :
expanded[len++] = *ch;
state = STATE_EXP_NORMAL;
break;
case '"' :
case '$' :
case ' ' :
default :
expanded[len++] = *ch;
state = STATE_EXP_QUOTE_SINGLE;
break;
}
break;
case STATE_EXP_QUOTE_DOUBLE :
switch( *ch )
{
case '\0' :
rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
break;
case '$' :
env_len = 0;
state = STATE_EXP_QUOTE_DOUBLE_ENV;
break;
case '\\' :
expanded[len++] = *ch;
state = STATE_EXP_QUOTE_DOUBLE_SPECIAL;
break;
case '"' :
expanded[len++] = *ch;
state = STATE_EXP_NORMAL;
break;
case '\'' :
case ' ' :
default :
expanded[len++] = *ch;
state = STATE_EXP_QUOTE_DOUBLE;
break;
}
break;
case STATE_EXP_QUOTE_SINGLE_SPECIAL :
switch( *ch )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -