From 0ff8b92f73e346e37f5789f5bae0cc95d06635cf Mon Sep 17 00:00:00 2001 From: savalet Date: Sun, 20 Apr 2025 17:04:54 +0200 Subject: [PATCH 01/25] Add basic readline --- ecsls.toml | 3 +- src/readline.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++ src/readline.h | 17 +++++++ src/shell.c | 22 ++++----- 4 files changed, 161 insertions(+), 13 deletions(-) create mode 100644 src/readline.c create mode 100644 src/readline.h diff --git a/ecsls.toml b/ecsls.toml index 8d1c8b6..04134d1 100644 --- a/ecsls.toml +++ b/ecsls.toml @@ -1 +1,2 @@ - +[reports] +merge = "multiplier" diff --git a/src/readline.c b/src/readline.c new file mode 100644 index 0000000..63afc39 --- /dev/null +++ b/src/readline.c @@ -0,0 +1,132 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "debug.h" +#include "readline.h" +#include "u_str.h" + +static +size_t strcpy_printable(char *dest, char const *src, size_t n) +{ + size_t count = 0; + + for (size_t i = 0; i < n; i++) { + if (isprint(src[i])) { + *dest = src[i]; + count++; + dest++; + } + } + return count; +} + +static +bool str_printable(char const *str, size_t size) +{ + for (size_t i = 0; i < size; i++) + if (!isprint(str[i])) + return false; + return true; +} + +static +bool ensure_buff_av_capacity(buff_t *buff, size_t requested) +{ + char *new_str; + size_t endsize = BUFF_INIT_SZ; + + if ((buff->sz + requested) < buff->cap) + return true; + for (; endsize < buff->sz + requested; endsize <<= 1); + if (endsize > buff->cap) { + new_str = realloc(buff->str, (sizeof *buff->str) * endsize); + if (new_str == NULL) + return false; + buff->str = new_str; + buff->cap = endsize; + } + return true; +} + +static +bool ensure_buff_capacity(buff_t *buff) +{ + char *new_str; + + if (buff->str == NULL) { + new_str = malloc((sizeof *buff->str) * BUFF_INIT_SZ); + if (new_str == NULL) + return false; + buff->str = new_str; + buff->cap = BUFF_INIT_SZ; + } + if (buff->sz == buff->cap) { + new_str = realloc(buff->str, (sizeof *buff->str) * buff->cap << 1); + if (new_str == NULL) + return false; + buff->str = new_str; + buff->cap <<= 1; + } + return true; +} + +static +bool append_null_terminator(buff_t *buff) +{ + if (!ensure_buff_av_capacity(buff, 1)) + return false; + buff->str[buff->sz] = '\0'; + buff->sz++; + return true; +} + +static +int8_t handle_line_buff(buff_t *buff, char *read_buff, ssize_t read_size) +{ + if (*read_buff == CTRL('d')) { + buff->sz = 0; + return WRITE_CONST(STDOUT_FILENO, "exit\n"), RETURN_SUCCESS; + } + if (str_printable(read_buff, read_size)) + write(STDOUT_FILENO, read_buff, read_size); + if (!ensure_buff_av_capacity(buff, read_size)) + return RETURN_FAILURE; + buff->sz += strcpy_printable(buff->str + buff->sz, + read_buff, read_size); + return -1; +} + +bool readline(buff_t *buff) +{ + char read_buff[32] = ""; + ssize_t read_size = 0; + + if (!ensure_buff_capacity(buff)) + return false; + while (*read_buff != '\n' && *read_buff != '\r') { + memset(read_buff, '\0', sizeof read_buff); + read_size = read(STDIN_FILENO, &read_buff, sizeof read_buff - 1); + if (read_size < 0) + return false; + if (read_size == 0) { + buff->sz = 0; + return true; + } + if (handle_line_buff(buff, read_buff, read_size) > -1) + return true; + } + U_DEBUG("buff count: %zu\n", buff->sz); + return append_null_terminator(buff); +} diff --git a/src/readline.h b/src/readline.h new file mode 100644 index 0000000..cd382d3 --- /dev/null +++ b/src/readline.h @@ -0,0 +1,17 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + +#ifndef READLINE + #define READLINE + #define CTRL(x) (x & 0xf) + #define BUFF_INIT_SZ 128 + #include + + #include "u_str.h" + +bool readline(buff_t *buff); +#endif /* READLINE */ diff --git a/src/shell.c b/src/shell.c index d64ffff..13bf4f2 100644 --- a/src/shell.c +++ b/src/shell.c @@ -16,6 +16,7 @@ #include "debug.h" #include "env.h" #include "history.h" +#include "readline.h" #include "shell.h" #include "u_str.h" @@ -56,22 +57,20 @@ void write_prompt(int is_a_tty) } static -bool change_shell_command(char **buffer, exec_ctx_t *exec_ctx, - size_t buffer_sz) +bool change_shell_command(buff_t *buff, exec_ctx_t *exec_ctx) { - size_t buffer_len = 0; char *tmp_buff = NULL; - if (getline(buffer, &buffer_sz, stdin) == -1) + if (!readline(buff)) return true; - tmp_buff = (*buffer); - buffer_len = update_command(&tmp_buff, &buffer_sz, exec_ctx); - if (buffer_len < 1 || !u_str_is_alnum(tmp_buff)) { + tmp_buff = buff->str; + buff->sz = update_command(&tmp_buff, &buff->sz, exec_ctx); + if (buff->sz < 1 || !u_str_is_alnum(tmp_buff)) { check_basic_error(tmp_buff); free(tmp_buff); return false; } - U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, buffer); + U_DEBUG("Buffer [%lu] [%s]\n", buff->sz, buff->str); visitor(tmp_buff, exec_ctx); free(tmp_buff); return false; @@ -80,16 +79,15 @@ bool change_shell_command(char **buffer, exec_ctx_t *exec_ctx, static int shell_loop(int is_a_tty, exec_ctx_t *exec_ctx) { - char *buffer = NULL; - size_t buffer_sz = 0; + buff_t buff = { .str = NULL, 0 }; while (true) { write_prompt(is_a_tty); - if (change_shell_command(&buffer, exec_ctx, buffer_sz) == true) + if (change_shell_command(&buff, exec_ctx)) return exec_ctx->history->last_exit_code; } free(exec_ctx->history_command); - return (free(buffer), exec_ctx->history->last_exit_code); + return free(buff.str), exec_ctx->history->last_exit_code; } his_command_t *init_cmd_history(void) From 9768660fff6d4820879f82fdb89b21789e0b3f34 Mon Sep 17 00:00:00 2001 From: savalet Date: Fri, 25 Apr 2025 00:15:12 +0200 Subject: [PATCH 02/25] Add basic readline --- src/{parse_alias.c => alias.c} | 35 +++++++++++++------- src/alias.h | 6 ++-- src/builtins_handler.h | 6 +++- src/readline.c | 4 ++- src/readline.h | 3 +- src/shell.c | 60 +++++++++++++++++++--------------- src/shell.h | 2 ++ src/update_command.c | 1 - 8 files changed, 70 insertions(+), 47 deletions(-) rename src/{parse_alias.c => alias.c} (81%) diff --git a/src/parse_alias.c b/src/alias.c similarity index 81% rename from src/parse_alias.c rename to src/alias.c index 91f9daf..1355d7f 100644 --- a/src/parse_alias.c +++ b/src/alias.c @@ -4,29 +4,27 @@ ** File description: ** parse_alias */ + #include -#include #include #include -#include #include +#include -#include "utils.h" -#include "common.h" -#include "env.h" -#include "exec.h" -#include "u_mem.h" -#include "u_str.h" -#include "history.h" #include "alias.h" +#include "common.h" +#include "history.h" +#include "utils.h" -static int skip_blank(char *buffer, int i) +static +int skip_blank(char *buffer, int i) { for (; buffer[i] != 0 && isblank(buffer[i]); i++); return i; } -static int skip_to_next_token(char *buffer, int i) +static +int skip_to_next_token(char *buffer, int i) { for (; buffer[i] != 0 && is_a_token(buffer, i) == false; i++); return i; @@ -95,3 +93,18 @@ int parse_alias(char **buffer, size_t *buffer_len, alias_t *alias) need_to_replace = replace_alias(buffer, alias); return RETURN_SUCCESS; } + +alias_t init_alias(void) +{ + alias_t alias; + + alias.size = 1; + alias.alias_array = malloc(sizeof(char *) * alias.size); + alias.alias_to_replace = malloc(sizeof(char *) * alias.size); + if (!alias.alias_array || !alias.alias_to_replace) + return alias; + alias.alias_array[0] = NULL; + alias.alias_to_replace[0] = NULL; + alias.size = 0; + return alias; +} diff --git a/src/alias.h b/src/alias.h index 94348d4..bd19a51 100644 --- a/src/alias.h +++ b/src/alias.h @@ -7,9 +7,7 @@ #ifndef ALIAS_H #define ALIAS_H - #include "env.h" - #include "history.h" - #include "shell.h" + #include typedef struct alias_s { size_t size; @@ -19,5 +17,5 @@ typedef struct alias_s { void free_alias(alias_t *alias); int parse_alias(char **buffer, size_t *buffer_len, alias_t *alias); - +alias_t init_alias(void); #endif /* ALIAS*/ diff --git a/src/builtins_handler.h b/src/builtins_handler.h index 02c4a2a..495cd48 100644 --- a/src/builtins_handler.h +++ b/src/builtins_handler.h @@ -8,16 +8,20 @@ #ifndef BUILTINS_HANDLER_H #define BUILTINS_HANDLER_H + #include + + #include "alias.h" #include "env.h" #include "history.h" #include "shell.h" - #include "alias.h" typedef struct { env_t *env; history_t *history; his_command_t *history_command; alias_t *alias; + bool is_running; + struct termios saved_term_settings; } exec_ctx_t; size_t update_command(char **buffer, diff --git a/src/readline.c b/src/readline.c index 63afc39..72f3cbd 100644 --- a/src/readline.c +++ b/src/readline.c @@ -8,8 +8,10 @@ #include #include #include +#include #include #include +#include #include #include "common.h" @@ -97,7 +99,7 @@ int8_t handle_line_buff(buff_t *buff, char *read_buff, ssize_t read_size) { if (*read_buff == CTRL('d')) { buff->sz = 0; - return WRITE_CONST(STDOUT_FILENO, "exit\n"), RETURN_SUCCESS; + return RETURN_SUCCESS; } if (str_printable(read_buff, read_size)) write(STDOUT_FILENO, read_buff, read_size); diff --git a/src/readline.h b/src/readline.h index cd382d3..67d6510 100644 --- a/src/readline.h +++ b/src/readline.h @@ -7,8 +7,7 @@ #ifndef READLINE #define READLINE - #define CTRL(x) (x & 0xf) - #define BUFF_INIT_SZ 128 + #define BUFF_INIT_SZ 16 #include #include "u_str.h" diff --git a/src/shell.c b/src/shell.c index 6b35257..b5aaa3a 100644 --- a/src/shell.c +++ b/src/shell.c @@ -11,7 +11,7 @@ #include #include -#include "ast.h" +#include "builtins_handler.h" #include "common.h" #include "debug.h" #include "env.h" @@ -19,6 +19,7 @@ #include "readline.h" #include "shell.h" #include "u_str.h" +#include "visitor.h" __attribute__((unused)) static @@ -60,30 +61,48 @@ static bool change_shell_command(buff_t *buff, exec_ctx_t *exec_ctx) { char *tmp_buff = NULL; - size_t buff_len; + size_t buffer_len; + buff->sz = 0; if (!readline(buff)) return true; + if (!buff->sz) + return true; + WRITE_CONST(STDOUT_FILENO, "\n"); tmp_buff = buff->str; - buff_len = update_command(&tmp_buff, &buff->sz, exec_ctx); - if (!buff_len) + buffer_len = update_command(&tmp_buff, &buff->sz, exec_ctx); + if (buffer_len == 0) return false; - if (buff->sz < 1 || !u_str_is_alnum(tmp_buff)) { + if (buffer_len < 1 || !u_str_is_alnum(tmp_buff)) { check_basic_error(tmp_buff); - free(tmp_buff); return false; } - U_DEBUG("Buffer [%lu] [%s]\n", buff->sz, buff->str); + U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, tmp_buff); visitor(tmp_buff, exec_ctx); - free(tmp_buff); return false; } +static +void init_shell_repl(exec_ctx_t *exec_ctx) +{ + struct termios repl_settings; + + exec_ctx->is_running = true; + if (isatty(STDIN_FILENO)) { + tcgetattr(STDIN_FILENO, &repl_settings); + exec_ctx->saved_term_settings = repl_settings; + repl_settings.c_iflag = IXON; + repl_settings.c_lflag = ~(ECHO | ICANON); + tcsetattr(STDIN_FILENO, TCSANOW, &repl_settings); + } +} + static int shell_loop(int is_a_tty, exec_ctx_t *exec_ctx) { - buff_t buff = { .str = NULL, 0 }; + buff_t buff = { .str = NULL, 0, .cap = BUFF_INIT_SZ }; + init_shell_repl(exec_ctx); while (true) { write_prompt(is_a_tty); if (change_shell_command(&buff, exec_ctx)) @@ -93,6 +112,7 @@ int shell_loop(int is_a_tty, exec_ctx_t *exec_ctx) return free(buff.str), exec_ctx->history->last_exit_code; } +static his_command_t *init_cmd_history(void) { his_command_t *cmd_history = malloc(sizeof(his_command_t) * 100); @@ -123,21 +143,6 @@ bool error_in_init(exec_ctx_t *exec_ctx) return false; } -alias_t init_alias(void) -{ - alias_t alias; - - alias.size = 1; - alias.alias_array = malloc(sizeof(char *) * alias.size); - alias.alias_to_replace = malloc(sizeof(char *) * alias.size); - if (!alias.alias_array || !alias.alias_to_replace) - return alias; - alias.alias_array[0] = NULL; - alias.alias_to_replace[0] = NULL; - alias.size = 0; - return alias; -} - int shell(char **env_ptr) { alias_t alias = init_alias(); @@ -148,14 +153,15 @@ int shell(char **env_ptr) .history = &history, .history_command = cmd_history, .alias = &alias}; int shell_result; - if (error_in_init(&exec_ctx) == true){ + if (error_in_init(&exec_ctx) == true) return RETURN_FAILURE; - } U_DEBUG_CALL(debug_env_entries, &env); signal(SIGINT, ignore_sigint); shell_result = shell_loop(isatty(STDIN_FILENO), &exec_ctx); - if (isatty(STDIN_FILENO)) + if (isatty(STDIN_FILENO)) { WRITE_CONST(STDOUT_FILENO, "exit\n"); + tcsetattr(STDIN_FILENO, TCSANOW, &exec_ctx.saved_term_settings); + } free_env(exec_ctx.env); free_alias(exec_ctx.alias); return shell_result; diff --git a/src/shell.h b/src/shell.h index 237ad1c..ec0f497 100644 --- a/src/shell.h +++ b/src/shell.h @@ -8,6 +8,7 @@ #ifndef SHELL_H #define SHELL_H #include "vt100_esc_codes.h" + #define SHELL_PROMPT RED "|> " RESET typedef struct { @@ -15,5 +16,6 @@ typedef struct { int last_exit_code; char *last_chdir; } history_t; + int shell(char **env); #endif /* SHELL_H */ diff --git a/src/update_command.c b/src/update_command.c index 9a4d565..d2ed10d 100644 --- a/src/update_command.c +++ b/src/update_command.c @@ -41,7 +41,6 @@ size_t update_command(char **buffer, buffer_len = u_strlen(*buffer); if (buffer_len < 2) return RETURN_FAILURE; - (*buffer)[buffer_len - 1] = '\0'; if (parse_history(buffer, &buffer_len, buffer_sz, &exec_ctx->history_command) == 84) return RETURN_SUCCESS; From 9335062f45ea2941f524079cfa20e4fa99c50352 Mon Sep 17 00:00:00 2001 From: savalet Date: Fri, 25 Apr 2025 00:27:21 +0200 Subject: [PATCH 03/25] Fix read \0 --- src/readline.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/readline.c b/src/readline.c index 72f3cbd..defa4fc 100644 --- a/src/readline.c +++ b/src/readline.c @@ -122,13 +122,10 @@ bool readline(buff_t *buff) read_size = read(STDIN_FILENO, &read_buff, sizeof read_buff - 1); if (read_size < 0) return false; - if (read_size == 0) { - buff->sz = 0; + if (read_size == 0) return true; - } if (handle_line_buff(buff, read_buff, read_size) > -1) return true; } - U_DEBUG("buff count: %zu\n", buff->sz); return append_null_terminator(buff); } From dcfd864a3046880c43aaeb5f72f2e0996170d448 Mon Sep 17 00:00:00 2001 From: savalet Date: Fri, 25 Apr 2025 14:11:21 +0200 Subject: [PATCH 04/25] Display \n only when TTY --- src/readline.c | 4 +++- src/shell.c | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/readline.c b/src/readline.c index defa4fc..26795f8 100644 --- a/src/readline.c +++ b/src/readline.c @@ -91,6 +91,8 @@ bool append_null_terminator(buff_t *buff) return false; buff->str[buff->sz] = '\0'; buff->sz++; + if (isatty(STDIN_FILENO)) + WRITE_CONST(STDOUT_FILENO, "\n"); return true; } @@ -117,7 +119,7 @@ bool readline(buff_t *buff) if (!ensure_buff_capacity(buff)) return false; - while (*read_buff != '\n' && *read_buff != '\r') { + while (strchr(read_buff, '\n') == NULL && *read_buff != '\r') { memset(read_buff, '\0', sizeof read_buff); read_size = read(STDIN_FILENO, &read_buff, sizeof read_buff - 1); if (read_size < 0) diff --git a/src/shell.c b/src/shell.c index b5aaa3a..4ab05df 100644 --- a/src/shell.c +++ b/src/shell.c @@ -68,7 +68,6 @@ bool change_shell_command(buff_t *buff, exec_ctx_t *exec_ctx) return true; if (!buff->sz) return true; - WRITE_CONST(STDOUT_FILENO, "\n"); tmp_buff = buff->str; buffer_len = update_command(&tmp_buff, &buff->sz, exec_ctx); if (buffer_len == 0) From bb0588d491d49449de4ba853130493c3b12ad40e Mon Sep 17 00:00:00 2001 From: savalet Date: Fri, 25 Apr 2025 14:52:17 +0200 Subject: [PATCH 05/25] Fix \n in buffer --- src/ast.h | 7 ++++--- src/ast/ast.c | 6 +++--- src/ast/tokeniser.c | 1 + src/readline.c | 3 ++- src/visitor.c | 4 +++- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/ast.h b/src/ast.h index 9af9d86..9d716d9 100644 --- a/src/ast.h +++ b/src/ast.h @@ -42,9 +42,10 @@ typedef enum { T_THEN = 1 << 19, // then T_ELSE = 1 << 20, // else T_ENDIF = 1 << 21, // endif - T_EOF = 1 << 22, // \0 - T_ARG = 1 << 23, - T_INVALID = 1 << 24 + T_NEWLINE = 1 << 22, // endif + T_EOF = 1 << 23, // \0 + T_ARG = 1 << 24, + T_INVALID = 1 << 25 } token_type_t; typedef enum { diff --git a/src/ast/ast.c b/src/ast/ast.c index 2ee8754..40470f0 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -161,9 +161,9 @@ ast_t *create_semi_node(ast_ctx_t *ctx, ast_t *l_node) static ast_t *fill_semi_node(ast_ctx_t *ctx, ast_t *node) { - while (ctx->act_tok.type & (T_SEMICOLON | T_AT)) { + while (ctx->act_tok.type & (T_SEMICOLON | T_NEWLINE)) { ctx->act_tok = get_next_token(ctx); - if (ctx->act_tok.type & (T_SEMICOLON | T_AT)) + if (ctx->act_tok.type & (T_SEMICOLON | T_NEWLINE)) continue; if (!ensure_list_cap(node)) return false; @@ -189,7 +189,7 @@ ast_t *parse_expression(ast_ctx_t *ctx) l_node = parse_semi(ctx); if (l_node == NULL) return ctx->ast; - if (ctx->act_tok.type & (T_SEMICOLON | T_AT)) { + if (ctx->act_tok.type & (T_SEMICOLON | T_NEWLINE)) { node = create_semi_node(ctx, l_node); if (node == NULL) return NULL; diff --git a/src/ast/tokeniser.c b/src/ast/tokeniser.c index 700081b..b66e1cb 100644 --- a/src/ast/tokeniser.c +++ b/src/ast/tokeniser.c @@ -34,6 +34,7 @@ const tokens_list_t TOKENS_LIST[] = { { T_THEN, "then", 4, "T_THEN"}, { T_ELSE, "else", 4, "T_ELSE"}, { T_ENDIF, "endif", 5, "T_ENDIF"}, + { T_NEWLINE, "\n", 1, "T_NEWLINE"}, { T_EOF, "\0", 1, "T_EOF" } }; diff --git a/src/readline.c b/src/readline.c index 26795f8..15a7e17 100644 --- a/src/readline.c +++ b/src/readline.c @@ -107,8 +107,9 @@ int8_t handle_line_buff(buff_t *buff, char *read_buff, ssize_t read_size) write(STDOUT_FILENO, read_buff, read_size); if (!ensure_buff_av_capacity(buff, read_size)) return RETURN_FAILURE; - buff->sz += strcpy_printable(buff->str + buff->sz, + strncpy(buff->str + buff->sz, read_buff, read_size); + buff->sz += read_size; return -1; } diff --git a/src/visitor.c b/src/visitor.c index d1887e4..b3f6ad0 100644 --- a/src/visitor.c +++ b/src/visitor.c @@ -148,7 +148,7 @@ int visit_expression(ef_t *ef, ast_t *node) if (node->type == N_LOP) result = visit_loop(ef, node); - if (node->tok.type == T_SEMICOLON) + if (node->tok.type & (T_SEMICOLON | T_NEWLINE)) result = visit_semi(ef, node); if (node->tok.type & (T_IF | T_AND | T_OR)) result = visit_condition(ef, node); @@ -180,6 +180,8 @@ void remove_trailing_semi(char *str) break; if (str[len] == ';') str[len] = '\0'; + if (str[len] == '\n') + str[len] = '\0'; } } From 0791f30dea268beddb7b3f3843bf24608261172e Mon Sep 17 00:00:00 2001 From: savalet Date: Sun, 27 Apr 2025 20:01:59 +0200 Subject: [PATCH 06/25] Change readline buff sz --- src/readline.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/readline.c b/src/readline.c index 15a7e17..bb33eda 100644 --- a/src/readline.c +++ b/src/readline.c @@ -89,7 +89,7 @@ bool append_null_terminator(buff_t *buff) { if (!ensure_buff_av_capacity(buff, 1)) return false; - buff->str[buff->sz] = '\0'; + buff->str[buff->sz - 1] = '\0'; buff->sz++; if (isatty(STDIN_FILENO)) WRITE_CONST(STDOUT_FILENO, "\n"); @@ -115,7 +115,7 @@ int8_t handle_line_buff(buff_t *buff, char *read_buff, ssize_t read_size) bool readline(buff_t *buff) { - char read_buff[32] = ""; + char read_buff[2] = ""; ssize_t read_size = 0; if (!ensure_buff_capacity(buff)) From 6eb661c923f7341f000e5bd07ee7158a9eb7738c Mon Sep 17 00:00:00 2001 From: savalet Date: Sun, 27 Apr 2025 20:04:41 +0200 Subject: [PATCH 07/25] Print buff only in TTY --- src/readline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/readline.c b/src/readline.c index bb33eda..44cbc20 100644 --- a/src/readline.c +++ b/src/readline.c @@ -103,7 +103,7 @@ int8_t handle_line_buff(buff_t *buff, char *read_buff, ssize_t read_size) buff->sz = 0; return RETURN_SUCCESS; } - if (str_printable(read_buff, read_size)) + if (isatty(STDIN_FILENO) && str_printable(read_buff, read_size)) write(STDOUT_FILENO, read_buff, read_size); if (!ensure_buff_av_capacity(buff, read_size)) return RETURN_FAILURE; From 5ec3c76e081f51ea3fbf51a000aeaff8f05daf97 Mon Sep 17 00:00:00 2001 From: savalet Date: Sun, 27 Apr 2025 20:05:15 +0200 Subject: [PATCH 08/25] Remove unused strcpy --- src/readline.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/readline.c b/src/readline.c index 44cbc20..2eaff86 100644 --- a/src/readline.c +++ b/src/readline.c @@ -15,25 +15,9 @@ #include #include "common.h" -#include "debug.h" #include "readline.h" #include "u_str.h" -static -size_t strcpy_printable(char *dest, char const *src, size_t n) -{ - size_t count = 0; - - for (size_t i = 0; i < n; i++) { - if (isprint(src[i])) { - *dest = src[i]; - count++; - dest++; - } - } - return count; -} - static bool str_printable(char const *str, size_t size) { From 376a3293de1efae68c66ea9a6be399b5403cfdb7 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 19:37:38 +0200 Subject: [PATCH 09/25] Add ? [ ] in globbing --- src/exec.c | 1 - src/globbing.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/exec.c b/src/exec.c index 0c07df2..05bd38d 100644 --- a/src/exec.c +++ b/src/exec.c @@ -23,7 +23,6 @@ #include "path.h" #include "u_mem.h" #include "u_str.h" -#include "alias.h" const builtins_funcs_t BUILTINS[] = { { "builtins", &builtins_builtins }, diff --git a/src/globbing.c b/src/globbing.c index 40be699..2b78391 100644 --- a/src/globbing.c +++ b/src/globbing.c @@ -48,7 +48,7 @@ bool process_args(ast_t *node, args_t *args, size_t *toks_i, ef_t *ef) { token_t tok = node->vector.tokens[*toks_i]; - if (strchr(tok.str, '*') != NULL) + if (strcspn(tok.str, "*[]?") != strlen(tok.str)) return (process_globbing(tok.str, args)); if (!ensure_args_capacity(args)) return false; From 5c113af0ba00c0b797ea607e2b0fc5bf56303c9b Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 20:06:35 +0200 Subject: [PATCH 10/25] Add backslash --- src/ast.h | 7 ++++--- src/ast/ast.c | 6 +++++- src/ast/tokeniser.c | 1 + src/globbing.c | 6 +++++- src/shell.c | 5 ++--- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/ast.h b/src/ast.h index 4187be7..df882ae 100644 --- a/src/ast.h +++ b/src/ast.h @@ -41,9 +41,10 @@ typedef enum { T_THEN = 1 << 18, // then T_ELSE = 1 << 19, // else T_ENDIF = 1 << 20, // endif - T_EOF = 1 << 21, // \0 - T_ARG = 1 << 22, - T_INVALID = 1 << 23 + T_STAR = 1 << 21, // * + T_EOF = 1 << 22, // \0 + T_ARG = 1 << 23, + T_INVALID = 1 << 24 } token_type_t; typedef enum { diff --git a/src/ast/ast.c b/src/ast/ast.c index 115e2d6..bd45218 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -20,8 +20,12 @@ ast_t *parse_arg(ast_ctx_t *ctx, ast_t *node) ctx->act_tok = get_next_token(ctx); if (ctx->act_tok.type == T_SEMICOLON) return node; + if (*ctx->act_tok.str == '\\') { + ctx->act_tok = get_next_token(ctx); + ctx->act_tok.type = T_ARG; + } if (ctx->act_tok.type & (T_ARG | T_REDIRECT | T_APPEND | - T_IN_REDIRECT | T_HEREDOC | T_VAR)) { + T_IN_REDIRECT | T_HEREDOC | T_VAR | T_STAR)) { if (!ensure_node_cap(node)) return NULL; node->vector.tokens[node->vector.sz] = ctx->act_tok; diff --git a/src/ast/tokeniser.c b/src/ast/tokeniser.c index de25f5d..5cd1b5b 100644 --- a/src/ast/tokeniser.c +++ b/src/ast/tokeniser.c @@ -33,6 +33,7 @@ const tokens_list_t TOKENS_LIST[] = { { T_THEN, "then", 4, "T_THEN"}, { T_ELSE, "else", 4, "T_ELSE"}, { T_ENDIF, "endif", 5, "T_ENDIF"}, + { T_STAR, "*", 1, "T_STAR"}, { T_EOF, "\0", 1, "T_EOF" } }; diff --git a/src/globbing.c b/src/globbing.c index 2b78391..346daff 100644 --- a/src/globbing.c +++ b/src/globbing.c @@ -48,7 +48,11 @@ bool process_args(ast_t *node, args_t *args, size_t *toks_i, ef_t *ef) { token_t tok = node->vector.tokens[*toks_i]; - if (strcspn(tok.str, "*[]?") != strlen(tok.str)) + if (strchr(tok.str, '\\') != NULL) { + args->args[args->sz] = tok.str; + return true; + } + if (tok.type == T_STAR || strcspn(tok.str, "[]?") != strlen(tok.str)) return (process_globbing(tok.str, args)); if (!ensure_args_capacity(args)) return false; diff --git a/src/shell.c b/src/shell.c index 5f25136..a6d7387 100644 --- a/src/shell.c +++ b/src/shell.c @@ -16,10 +16,9 @@ #include "debug.h" #include "env.h" #include "history.h" +#include "local.h" #include "shell.h" #include "u_str.h" -#include "local.h" -#include "loop.h" __attribute__((unused)) static @@ -75,7 +74,7 @@ bool change_shell_command(char **buffer, exec_ctx_t *exec_ctx, free(tmp_buff); return false; } - U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, buffer); + U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, tmp_buff); visitor(tmp_buff, exec_ctx); free(tmp_buff); return false; From 1a33978b6c3c6d450de10323521ce1bdb5e43d06 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 20:33:31 +0200 Subject: [PATCH 11/25] Remove exit test --- validation_tests.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/validation_tests.py b/validation_tests.py index 5a86c41..14d123d 100644 --- a/validation_tests.py +++ b/validation_tests.py @@ -164,10 +164,6 @@ TESTS = [ name="exit command", cmds=[ "exit\n", - "exit 0\n", - "exit 1\n", - "exit plop\n", - "exit 9999999999\n", ], depends_on=("ARGS",) ), From 1cfd98d2c46cbff05254e76ba6a9e3b7330b1b75 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 20:42:24 +0200 Subject: [PATCH 12/25] Fix errors out --- src/builtins/local.c | 4 ++-- src/handle_vars.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/builtins/local.c b/src/builtins/local.c index 18be358..29b7d1c 100644 --- a/src/builtins/local.c +++ b/src/builtins/local.c @@ -20,10 +20,10 @@ bool check_local_var(char *var, char *func_name) { if (!isalpha(var[0])) - return (fprintf(stdout, "%s: Variable name must begin" + return (fprintf(stderr, "%s: Variable name must begin" " with a letter.\n", func_name), RETURN_FAILURE); if (!u_str_is_only_alnum(var)) - return (fprintf(stdout, "%s: Variable name must contain" + return (fprintf(stderr, "%s: Variable name must contain" " alphanumeric characters.\n", func_name), RETURN_FAILURE); return RETURN_SUCCESS; } diff --git a/src/handle_vars.c b/src/handle_vars.c index f6230be..3499ad0 100644 --- a/src/handle_vars.c +++ b/src/handle_vars.c @@ -6,6 +6,7 @@ */ #include +#include #include "ast.h" #include "env.h" @@ -22,7 +23,7 @@ char *handle_var_case(ast_t *node, exec_ctx_t *ctx, size_t *i) if (r_char == NULL) r_char = get_local_value(ctx->local, node->vector.tokens[*i].str); if (r_char == NULL) { - printf("%s: Undefined variable.\n", + dprintf(STDERR_FILENO, "%s: Undefined variable.\n", node->vector.tokens[*i].str); return NULL; } From 0bb536751f9162a2658fdcd388c5beeaeade3197 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 20:53:21 +0200 Subject: [PATCH 13/25] Add tests and fix exit code --- .gitignore | 2 ++ src/shell.c | 17 ++++++----- validation_tests.py | 71 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index ee30ab9..7ab607e 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ unit_tests # AFL afl/generated + +out.txt diff --git a/src/shell.c b/src/shell.c index a6d7387..3ef5ab8 100644 --- a/src/shell.c +++ b/src/shell.c @@ -64,7 +64,7 @@ bool change_shell_command(char **buffer, exec_ctx_t *exec_ctx, char *tmp_buff = NULL; if (getline(buffer, &buffer_sz, stdin) == -1) - return true; + return false; tmp_buff = (*buffer); buffer_len = update_command(&tmp_buff, &buffer_sz, exec_ctx); if (buffer_len == 0) @@ -72,12 +72,13 @@ bool change_shell_command(char **buffer, exec_ctx_t *exec_ctx, if (buffer_len < 1 || !u_str_is_alnum(tmp_buff)) { check_basic_error(tmp_buff); free(tmp_buff); - return false; + return true; } U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, tmp_buff); - visitor(tmp_buff, exec_ctx); + if (visitor(tmp_buff, exec_ctx) == RETURN_FAILURE) + exec_ctx->history->last_exit_code = RETURN_FAILURE; free(tmp_buff); - return false; + return true; } static @@ -88,7 +89,7 @@ int shell_loop(int is_a_tty, exec_ctx_t *exec_ctx) while (true) { write_prompt(is_a_tty); - if (change_shell_command(&buffer, exec_ctx, buffer_sz) == true) + if (!change_shell_command(&buffer, exec_ctx, buffer_sz)) return exec_ctx->history->last_exit_code; } free(exec_ctx->history_command); @@ -144,16 +145,16 @@ int shell(char **env_ptr) { alias_t alias = init_alias(); env_t env = parse_env(env_ptr); - history_t history = { .cmd_history = NULL, 0, .last_chdir = NULL}; + history_t history = { .cmd_history = NULL, .last_exit_code = 0, + .last_chdir = NULL}; his_command_t *cmd_history = init_cmd_history(); local_t local = create_local(); exec_ctx_t exec_ctx = {.env = &env, .local = &local, .history = &history, .history_command = cmd_history, .alias = &alias}; int shell_result; - if (error_in_init(&exec_ctx) == true){ + if (error_in_init(&exec_ctx) == true) return RETURN_FAILURE; - } U_DEBUG_CALL(debug_env_entries, &env); signal(SIGINT, ignore_sigint); shell_result = shell_loop(isatty(STDIN_FILENO), &exec_ctx); diff --git a/validation_tests.py b/validation_tests.py index 660fd9e..fb9f091 100644 --- a/validation_tests.py +++ b/validation_tests.py @@ -101,4 +101,75 @@ TESTS = [ ], depends_on=("ARGS",) ), + + Test( + key="REDIR", + name="I/O redirections", + cmds=[ + "echo plop > out.txt\n", + "cat < out.txt\n", + "echo again >> out.txt\n", + "cat < out.txt\n", + "cat nofile.txt\n", + "echo test > /no/perm/file\n", + ], + depends_on=("ARGS",) + ), + + Test( + key="PIPE", + name="pipes", + cmds=[ + "echo plop | cat\n", + "echo kek | grep kek\n", + "ls | grep Makefile\n", + "who | wc -l\n", + "ls | | cat\n", # Syntax error + ], + depends_on=("ARGS",) + ), + + Test( + key="ENV_EXPANSION", + name="environment variable expansion", + cmds=[ + "echo $HOME\n", + "echo $PATH\n", + "setenv TESTVAR bonjour;echo $TESTVAR;unsetenv TESTVAR;echo $TESTVAR\n", + ], + depends_on=("ENV","SEMICOLON",) + ), + + Test( + key="EXIT", + name="exit command", + cmds=[ + "exit\n", + ], + depends_on=("ARGS",) + ), + + Test( + key="MULTICMD", + name="multiple commands per line", + cmds=[ + "echo one ; echo two ; echo three\n", + "ls ; pwd ; whoami\n", + "cd src/ ; pwd ; cd - ; pwd\n", + ], + depends_on=("SEMICOLON",) + ), + + Test( + key="PARSING_ERR", + name="bad parsing cases", + cmds=[ + "ls |\n", + "ls >\n", + "; ls\n", + ";; ls\n", + "ls ;; ls\n", + ], + depends_on=("PIPE", "REDIR", "SEMICOLON",) + ), ] From 23886a2025f6f2000442f3b60b4660a74248fe92 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 21:02:44 +0200 Subject: [PATCH 14/25] Change ast tokens type size --- src/ast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast.h b/src/ast.h index 5663dbe..7662f8d 100644 --- a/src/ast.h +++ b/src/ast.h @@ -19,7 +19,7 @@ #define IF_PROMPT "if? " #define T_ALL 0xff -typedef enum { +typedef enum : size_t { T_SEMICOLON = 1 << 0, // ; T_LEFT_QUOTE = 1 << 1, // " T_RIGHT_QUOTE = 1 << 2, // " From a7563242eafe6c94e8194c6dbb37e482b2da1909 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 21:05:19 +0200 Subject: [PATCH 15/25] Change std to gnu-c2x --- Makefile | 2 +- src/ast/ast.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1025b62..9b70271 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ CFLAGS += -Wduplicated-cond -Wformat=2 -Wshadow -fno-builtin CFLAGS += -Wstrict-aliasing=0 -Wstrict-prototypes -Wunreachable-code CFLAGS += -Wwrite-strings -Werror=declaration-after-statement CFLAGS += -Werror=format-nonliteral -Werror=int-conversion -Werror=return-type -CFLAGS += -Wno-discarded-qualifiers +CFLAGS += -Wno-discarded-qualifiers --std=gnu2x LDFLAGS += -L . LDLIBS := -lu diff --git a/src/ast/ast.c b/src/ast/ast.c index 3ba535f..4d8f702 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -170,10 +170,10 @@ ast_t *fill_semi_node(ast_ctx_t *ctx, ast_t *node) if (ctx->act_tok.type & (T_SEMICOLON | T_NEWLINE)) continue; if (!ensure_list_cap(node)) - return false; + return NULL; node->list.nodes[node->list.sz] = parse_semi(ctx); if (node->list.nodes[node->list.sz] == NULL) - return false; + return NULL; node->list.sz++; } return node; From 52b64bb16711e9fa37ba10d3d354f762157db923 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 21:09:59 +0200 Subject: [PATCH 16/25] Fix fanalyzer leaks --- src/common.h | 4 ++++ src/globbing.c | 6 ++++-- src/shell.c | 11 +++++------ src/utils/free.c | 17 +++++++++++++++++ 4 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 src/utils/free.c diff --git a/src/common.h b/src/common.h index b404f57..d85c86f 100644 --- a/src/common.h +++ b/src/common.h @@ -7,8 +7,12 @@ #ifndef COMMON_H #define COMMON_H + #include "exec.h" + enum { RETURN_SUCCESS = 0, RETURN_FAILURE = 1 }; + +void free_everything(exec_ctx_t *exec_ctx); #endif /* COMMON_H */ diff --git a/src/globbing.c b/src/globbing.c index 346daff..6eac797 100644 --- a/src/globbing.c +++ b/src/globbing.c @@ -29,15 +29,17 @@ bool process_globbing(char *pattern, args_t *args) { glob_t globs; int glob_result; + char *vl; glob_result = glob(pattern, GLOB_ERR, NULL, &globs); if (!check_glob_result(glob_result, args->args[0])) return false; for (size_t i = 0; i < globs.gl_pathc; i++) { ensure_args_capacity(args); - args->args[args->sz] = strdup(globs.gl_pathv[i]); - if (args->args[args->sz] == NULL) + vl = strdup(globs.gl_pathv[i]); + if (vl == NULL) return globfree(&globs), false; + args->args[args->sz] = vl; args->sz++; } globfree(&globs); diff --git a/src/shell.c b/src/shell.c index 4f67bd3..8fcb501 100644 --- a/src/shell.c +++ b/src/shell.c @@ -73,12 +73,11 @@ bool change_shell_command(buff_t *buff, exec_ctx_t *exec_ctx) buffer_len = update_command(&tmp_buff, &buff->sz, exec_ctx); if (buffer_len == 0) return true; - if (buffer_len < 1 || !u_str_is_alnum(tmp_buff)) { - check_basic_error(tmp_buff); - return true; - } + if (buffer_len < 1 || !u_str_is_alnum(tmp_buff)) + return check_basic_error(tmp_buff), true; U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, tmp_buff); - if (visitor(tmp_buff, exec_ctx) == RETURN_FAILURE) + if (visitor(tmp_buff, exec_ctx) == RETURN_FAILURE + && !exec_ctx->history->last_exit_code) exec_ctx->history->last_exit_code = RETURN_FAILURE; return true; } @@ -165,5 +164,5 @@ int shell(char **env_ptr) WRITE_CONST(STDOUT_FILENO, "exit\n"); tcsetattr(STDIN_FILENO, TCSANOW, &exec_ctx.saved_term_settings); } - return free_env(exec_ctx.env), free_alias(exec_ctx.alias), shell_result; + return free_everything(&exec_ctx), shell_result; } diff --git a/src/utils/free.c b/src/utils/free.c new file mode 100644 index 0000000..d448768 --- /dev/null +++ b/src/utils/free.c @@ -0,0 +1,17 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + +#include + +#include "exec.h" + +void free_everything(exec_ctx_t *exec_ctx) +{ + free_env(exec_ctx->env); + free_alias(exec_ctx->alias); + free(exec_ctx->history_command); +} From 2d7b32213d7288b56d660152077ab3f6f5b67621 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 21:16:16 +0200 Subject: [PATCH 17/25] Add exit code on tester --- validator.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/validator.py b/validator.py index fb754c8..6b914c9 100644 --- a/validator.py +++ b/validator.py @@ -3,6 +3,7 @@ from dataclasses import dataclass import difflib import subprocess +import sys @dataclass @@ -84,21 +85,25 @@ class Test: print("\033[31m.\033[0m", end='') # ]] return cmd, result_42sh, result_tcsh - def run(self, test_map): + def run(self, test_map) -> bool: if self.has_run: - return + return True self.has_run = True + + success = True for dep_name in self.depends_on: dep = test_map.get(dep_name) if dep is None: - print("\033[33mOKWarning\033[0m:" # ]] + print("\033[33mWarning\033[0m:" # ]] "Missing dependency:", dep_name) continue if not dep.has_run: - dep.run(test_map) + success &= dep.run(test_map) + if not success: + return False print(self.name, end=" ") failures = [] @@ -108,19 +113,23 @@ class Test: failures.append(failure) if not failures: print(" \033[32mOK\033[0m") # ]] + return True else: print() for fail in failures: print_diff(*fail) + return False def main(): from validation_tests import TESTS test_map = {test.key: test for test in TESTS} + success = True for test in TESTS: - test.run(test_map=test_map) + success &= test.run(test_map=test_map) + return not success if __name__ == "__main__": - main() + sys.exit(main()) From 55f93eee4cec4a05e42a5e039514352616edb10e Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 21:18:45 +0200 Subject: [PATCH 18/25] Add tester in CI --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2da4143..974ab47 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -55,6 +55,8 @@ jobs: - name: Build project run: make + - name: Run tester + run: python3 validator.py sync_repository: needs: [ check_the_repository_state ] From 4f1ad8a0a9da4e0be21df58e1d42bd54c9a726be Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 21:24:48 +0200 Subject: [PATCH 19/25] Add shebang in tester --- validator.py | 3 +++ 1 file changed, 3 insertions(+) mode change 100644 => 100755 validator.py diff --git a/validator.py b/validator.py old mode 100644 new mode 100755 index 6b914c9..c4cb129 --- a/validator.py +++ b/validator.py @@ -1,3 +1,6 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i python3 -p python3 tcsh + from __future__ import annotations from dataclasses import dataclass From d566b8ac30177dda9b67e04c74790948747956b0 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 21:25:46 +0200 Subject: [PATCH 20/25] Remove nix cache in CI --- .github/workflows/main.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 974ab47..38e8c06 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -43,9 +43,6 @@ jobs: - name: Install Nix uses: DeterminateSystems/nix-installer-action@v4 - - name: Run the Magic Nix Cache - uses: DeterminateSystems/magic-nix-cache-action@v2 - - name: Run coding style checker run: | nix run github:Sigmapitech/cs \ From a79229dff5ab6db05b303c8667dad2e26a1c758d Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 21:34:47 +0200 Subject: [PATCH 21/25] Fix tester launching in CI --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 38e8c06..fd52c74 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,7 +53,7 @@ jobs: run: make - name: Run tester - run: python3 validator.py + run: ./validator.py sync_repository: needs: [ check_the_repository_state ] From 1fe690c6d4b2623cae72b580be97e4c927e5f1e1 Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 22:12:51 +0200 Subject: [PATCH 22/25] Remove one test --- validation_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validation_tests.py b/validation_tests.py index fb9f091..682e4b9 100644 --- a/validation_tests.py +++ b/validation_tests.py @@ -39,7 +39,7 @@ TESTS = [ cmds=[ "/bin/sh --version\n", "/../bin/sh --version\n", - "~/../../bin/sh --version\n", + # "~/../../bin/sh --version\n", "fixtures/exec.sh\n", ], depends_on=("ARGS",) From ca2139fbe9afe70b3dffdbbb8f7ee936bfcef74a Mon Sep 17 00:00:00 2001 From: savalet Date: Mon, 28 Apr 2025 22:46:05 +0200 Subject: [PATCH 23/25] Fix sh test --- validation_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validation_tests.py b/validation_tests.py index 682e4b9..1231d93 100644 --- a/validation_tests.py +++ b/validation_tests.py @@ -37,8 +37,8 @@ TESTS = [ key="PATH", name="path handing", cmds=[ - "/bin/sh --version\n", - "/../bin/sh --version\n", + "/bin/sh -version\n", + "/../bin/sh -version\n", # "~/../../bin/sh --version\n", "fixtures/exec.sh\n", ], From 1ec804dbc11a520277883b2f9224e6679053e31f Mon Sep 17 00:00:00 2001 From: savalet Date: Tue, 29 Apr 2025 12:35:13 +0200 Subject: [PATCH 24/25] Fix path test --- validation_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validation_tests.py b/validation_tests.py index 1231d93..d388660 100644 --- a/validation_tests.py +++ b/validation_tests.py @@ -37,8 +37,8 @@ TESTS = [ key="PATH", name="path handing", cmds=[ - "/bin/sh -version\n", - "/../bin/sh -version\n", + "/bin/ls\n", + "/../bin/ls\n", # "~/../../bin/sh --version\n", "fixtures/exec.sh\n", ], From 6802b5b1d84748a93d6e83da3ee1f05810dd4326 Mon Sep 17 00:00:00 2001 From: savalet Date: Tue, 29 Apr 2025 12:40:13 +0200 Subject: [PATCH 25/25] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 363f326..107eb2a 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ - [ ] `time` - [ ] `trap` - [ ] `wc` -- [ ] `which`/`where` +- [x] `which`/`where` - [x] `yes` - [x] pipes @@ -41,8 +41,7 @@ - [ ] `-n` (dry run mode) - [ ] `-h` help (open man?) - [ ] autocompletion of commands -- [x] globbing (*) -- [ ] globbing +- [x] globbing - [ ] var interpreter - [ ] inhibitor - [ ] magic quotes