diff options
Diffstat (limited to 'userland/minibox/utilities/sh')
| -rw-r--r-- | userland/minibox/utilities/sh/ast.c | 57 | ||||
| -rw-r--r-- | userland/minibox/utilities/sh/ast.h | 1 | ||||
| -rw-r--r-- | userland/minibox/utilities/sh/lexer.c | 3 | ||||
| -rw-r--r-- | userland/minibox/utilities/sh/lexer.h | 1 | ||||
| -rw-r--r-- | userland/minibox/utilities/sh/sh.c | 18 | 
5 files changed, 77 insertions, 3 deletions
| diff --git a/userland/minibox/utilities/sh/ast.c b/userland/minibox/utilities/sh/ast.c index 2a8d775..d4dc400 100644 --- a/userland/minibox/utilities/sh/ast.c +++ b/userland/minibox/utilities/sh/ast.c @@ -26,6 +26,60 @@ struct AST *allocate_ast(void) {    return r;  } +int token_get(struct TOKEN **token_ptr, token_type_t type) { +  struct TOKEN *token = *token_ptr; +  token = token->next; +  if (!token) { +    return 0; +  } + +  if (type != token->type) { +    return 0; +  } +  *token_ptr = token; +  return 1; +} + +int parse_set(struct TOKEN **token_ptr, struct AST *cur) { +  struct TOKEN *token = *token_ptr; +  if (TOKEN_CHARS != token->type) { +    return 0; +  } + +  if (!sv_eq(C_TO_SV("export"), token->string_rep)) { +    return 0; +  } + +  if (!token_get(&token, TOKEN_CHARS)) { +    return 0; +  } +  struct TOKEN *name = token; +  if (!token_get(&token, TOKEN_EQUAL)) { +    return 0; +  } +  if (!token_get(&token, TOKEN_CHARS)) { +    return 0; +  } +  struct TOKEN *value = token; +  if (!token_get(&token, TOKEN_NEWLINE)) { +    return 0; +  } +  token = token->next; + +  cur->type = AST_SET; +  cur->val.type = AST_VALUE_STRING; +  cur->val.string = name->string_rep; + +  cur->children = allocate_ast(); +  struct AST *child = cur->children; +  child->type = AST_EXPRESSION; +  child->val.type = AST_VALUE_STRING; +  child->val.string = value->string_rep; + +  *token_ptr = token; +  return 1; +} +  int parse_command(struct TOKEN **token_ptr, struct AST *cur) {    struct TOKEN *token = *token_ptr;    if (TOKEN_CHARS != token->type) { @@ -94,7 +148,8 @@ struct AST *generate_ast(struct TOKEN *token) {      if (prev) {        prev->next = cur;      } -    if (parse_command(&token, cur)) { +    if (parse_set(&token, cur)) { +    } else if (parse_command(&token, cur)) {      } else if (TOKEN_AND == token->type) {        cur->type = AST_CONDITIONAL_AND;        token = token->next; diff --git a/userland/minibox/utilities/sh/ast.h b/userland/minibox/utilities/sh/ast.h index 0c5768f..f0a1b2b 100644 --- a/userland/minibox/utilities/sh/ast.h +++ b/userland/minibox/utilities/sh/ast.h @@ -15,6 +15,7 @@ struct AST_VALUE {  typedef enum {    AST_COMMAND, +  AST_SET,    AST_EXPRESSION,    AST_CONDITIONAL_AND,    AST_CONDITIONAL_NOT, diff --git a/userland/minibox/utilities/sh/lexer.c b/userland/minibox/utilities/sh/lexer.c index 09fc2ff..52126b4 100644 --- a/userland/minibox/utilities/sh/lexer.c +++ b/userland/minibox/utilities/sh/lexer.c @@ -24,7 +24,7 @@ int is_special_char(char c) {    if (isalnum(c)) {      return 0;    } -  return !(('>' != c && '|' != c && '&' != c)); +  return !(('>' != c && '|' != c && '&' != c && '=' != c));  }  int parse_chars(struct sv *code_ptr, struct TOKEN *cur) { @@ -54,6 +54,7 @@ int parse_operand(struct sv *code_ptr, struct TOKEN *cur) {    TRY_PARSE_STRING(">", TOKEN_STREAM);    TRY_PARSE_STRING("|", TOKEN_PIPE);    TRY_PARSE_STRING("&", TOKEN_BACKGROUND); +  TRY_PARSE_STRING("=", TOKEN_EQUAL);    TRY_PARSE_STRING("\n", TOKEN_NEWLINE);    // Failed to parse diff --git a/userland/minibox/utilities/sh/lexer.h b/userland/minibox/utilities/sh/lexer.h index 4a7e61c..65366dc 100644 --- a/userland/minibox/utilities/sh/lexer.h +++ b/userland/minibox/utilities/sh/lexer.h @@ -12,6 +12,7 @@ typedef enum {    TOKEN_STREAM,    TOKEN_STREAM_APPEND,    TOKEN_BACKGROUND, +  TOKEN_EQUAL,    TOKEN_NEWLINE,  } token_type_t; diff --git a/userland/minibox/utilities/sh/sh.c b/userland/minibox/utilities/sh/sh.c index 3643d99..e4a701c 100644 --- a/userland/minibox/utilities/sh/sh.c +++ b/userland/minibox/utilities/sh/sh.c @@ -128,10 +128,26 @@ int execute_command(struct AST *ast, int input_fd) {    return execute_binary(ast, input_fd);  } +void set_env_from_ast(struct AST *ast) { +  assert(AST_VALUE_STRING == ast->val.type); +  char *name = SV_TO_C(ast->val.string); + +  struct AST *child = ast->children; +  assert(AST_VALUE_STRING == child->val.type); +  char *value = SV_TO_C(child->val.string); + +  setenv(name, value, 1); + +  free(value); +  free(name); +} +  void execute_ast(struct AST *ast) {    int rc = -1;    for (; ast;) { -    if (AST_COMMAND == ast->type) { +    if (AST_SET == ast->type) { +      set_env_from_ast(ast); +    } else if (AST_COMMAND == ast->type) {        rc = execute_command(ast, STDIN_FILENO);      } else if (AST_CONDITIONAL_AND == ast->type) {        if (0 != rc) { |