From 9276e1a8a5dc2e870418f886a52d09cad13d23d1 Mon Sep 17 00:00:00 2001 From: Jean <47366872+jean-voila@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:35:06 +0100 Subject: [PATCH] Fixed the length of the execution function --- .gitignore | 4 + src/execution/Makefile.am | 4 +- src/execution/execution.c | 316 ++---------------------------- src/execution/execution_helpers.c | 216 ++++++++++++++++++++ src/execution/execution_helpers.h | 13 ++ src/utils/ast/ast.c | 2 +- 6 files changed, 251 insertions(+), 304 deletions(-) create mode 100644 src/execution/execution_helpers.c create mode 100644 src/execution/execution_helpers.h diff --git a/.gitignore b/.gitignore index 09e5b39..f9b5175 100644 --- a/.gitignore +++ b/.gitignore @@ -178,3 +178,7 @@ m4/lt~obsolete.m4 Makefile *.svg + + +.venv/ +*.py \ No newline at end of file diff --git a/src/execution/Makefile.am b/src/execution/Makefile.am index 5a71cbb..f061dfc 100644 --- a/src/execution/Makefile.am +++ b/src/execution/Makefile.am @@ -2,7 +2,9 @@ lib_LIBRARIES = libexecution.a libexecution_a_SOURCES = \ execution.c \ - execution.h + execution.h \ + execution_helpers.c \ + execution_helpers.h libexecution_a_CPPFLAGS = -I$(top_srcdir)/src diff --git a/src/execution/execution.c b/src/execution/execution.c index 4522bcc..82fcacf 100644 --- a/src/execution/execution.c +++ b/src/execution/execution.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include "execution.h" #include @@ -23,100 +24,6 @@ * @return char** Array of command arguments suitable for execvp. Terminated by * NULL */ -static char **list_to_argv(struct list *command_list) -{ - size_t len = 0; - struct list *cur = command_list; - - while (cur) - { - len++; - cur = cur->next; - } - - char **argv = calloc(len + 1, sizeof(char *)); - if (!argv) - { - return NULL; - } - cur = command_list; - - for (size_t i = 0; i < len; i++) - { - argv[i] = (char *)cur->data; - cur = cur->next; - } - - argv[len] = NULL; - return argv; -} - -// --- Builtins --- - -static int builtin_echo(char **argv) -{ - bool newline = true; - int i = 1; - - if (argv[1] && strcmp(argv[1], "-n") == 0) - { - newline = false; - i++; - } - - for (; argv[i]; i++) - { - printf("%s", argv[i]); - if (argv[i + 1]) - printf(" "); - } - if (newline) - printf("\n"); - - fflush(stdout); - return 0; -} - -static int builtin_true(char **argv) -{ - (void)argv; - return 0; -} - -static int builtin_false(char **argv) -{ - (void)argv; - return 1; -} - -static int builtin_exit(char **argv) -{ - int exit_val = 0; - if (argv[1]) - exit_val = atoi(argv[1]); - exit(exit_val); - return exit_val; -} - -static int builtin_cd(char **argv) -{ - const char *path = argv[1]; - if (!path) - { - path = getenv("HOME"); - if (!path) - { - fprintf(stderr, "cd: HOME not set\n"); - return 1; - } - } - if (chdir(path) != 0) - { - perror("cd"); - return 1; - } - return 0; -} /** * @brief Tries to execute a builtin command if the command matches a builtin @@ -124,24 +31,6 @@ static int builtin_cd(char **argv) * @param argv Array of command arguments * @return int Exit status of the builtin command, or -1 if not a builtin */ -static int try_builtin(char **argv) -{ - if (!argv || !argv[0]) - return 0; - - if (strcmp(argv[0], "echo") == 0) - return builtin_echo(argv); - if (strcmp(argv[0], "true") == 0) - return builtin_true(argv); - if (strcmp(argv[0], "false") == 0) - return builtin_false(argv); - if (strcmp(argv[0], "exit") == 0) - return builtin_exit(argv); - if (strcmp(argv[0], "cd") == 0) - return builtin_cd(argv); - - return -1; -} // --- Execution Core --- @@ -151,212 +40,35 @@ static int try_builtin(char **argv) * @param command The command to execute * @return int The exit status of the command */ -static int exec_command(struct ast_command *command) -{ - if (!command || !(command->command)) - { - return 1; - } - char **argv = list_to_argv(command->command); +// Refactored: delegates to helpers in execution_helpers.c +#include "execution_helpers.h" - if (!argv || !(argv[0])) - { - free(argv); - return 0; - } - - int builtin_ret = try_builtin(argv); - if (builtin_ret != -1) - { - free(argv); - return builtin_ret; - } - - pid_t pid = fork(); - - if (pid < 0) - { - perror("fork"); - free(argv); - return 1; - } - - if (pid == 0) - { - execvp(argv[0], argv); - perror("execvp"); - _exit(127); - } - - int status = 0; - waitpid(pid, &status, 0); - free(argv); - - if (WIFEXITED(status)) - { - return WEXITSTATUS(status); - } - - return 1; -} - -/** - * @brief Executes the AST returned by the parser - * - * @param ast The AST to execute - * @return int The exit status of the last executed command. - */ int execution(struct ast *ast, struct hash_map *vars) { if (!ast) - { return 0; - } switch (ast->type) { case AST_VOID: - case AST_END: { + case AST_END: return 0; - } case AST_CMD: { struct ast_command *command = ast_get_command(ast); if (!expand(command, vars)) fprintf(stderr, "Error: Variable expansion failed\n"); - return exec_command(command); + return exec_ast_command(command, vars); } - case AST_IF: { - struct ast_if *if_node = ast_get_if(ast); - int cond = execution(if_node->condition, vars); - if (cond == 0) // True - { - return execution(if_node->then_clause, vars); - } - else // False - { - return execution(if_node->else_clause, vars); - } - } - case AST_LIST: { - struct ast_list *list_node = ast_get_list(ast); - struct list *cur = list_node->children; - int ret = 0; - while (cur) - { - struct ast *child = (struct ast *)cur->data; - if (!ast_is_void(child)) - ret = execution(child, vars); - cur = cur->next; - } - return ret; - } - case AST_AND_OR: { - struct ast_and_or *ao_node = ast_get_and_or(ast); - int left_ret = execution(ao_node->left, vars); - - if (ao_node->type == AST_AND_OR_TYPE_AND) - { - if (left_ret == 0) - return execution(ao_node->right, vars); - return left_ret; - } - else // OR - { - if (left_ret != 0) - return execution(ao_node->right, vars); - return left_ret; - } - } - case AST_REDIR: { - struct ast_redir *redir = ast_get_redir(ast); - - int fd_target = redir->io_number; - if (fd_target == -1) - { - if (redir->type == AST_REDIR_TYPE_LESS - || redir->type == AST_REDIR_TYPE_DLESS - || redir->type == AST_REDIR_TYPE_LESSAND) - fd_target = 0; - else - fd_target = 1; - } - - int saved_fd = dup(fd_target); - - int new_fd = -1; - int flags = 0; - int mode = 0644; - - if (redir->type == AST_REDIR_TYPE_GREAT - || redir->type == AST_REDIR_TYPE_CLOBBER) - { - flags = O_WRONLY | O_CREAT | O_TRUNC; - new_fd = open(redir->filename, flags, mode); - } - else if (redir->type == AST_REDIR_TYPE_DGREAT) - { - flags = O_WRONLY | O_CREAT | O_APPEND; - new_fd = open(redir->filename, flags, mode); - } - else if (redir->type == AST_REDIR_TYPE_LESS) - { - flags = O_RDONLY; - new_fd = open(redir->filename, flags); - } - else if (redir->type == AST_REDIR_TYPE_GREATAND - || redir->type == AST_REDIR_TYPE_LESSAND) - { - // Simple fd duplication - new_fd = atoi(redir->filename); - // Verify new_fd is valid? dup2 will check. - if (dup2(new_fd, fd_target) == -1) - { - perror("dup2"); - if (saved_fd != -1) - close(saved_fd); - return 1; - } - new_fd = -2; // Mark as "already duped" - } - - if (new_fd == -1) - { - perror("open"); - if (saved_fd != -1) - close(saved_fd); - return 1; - } - - if (new_fd != -2) - { - if (dup2(new_fd, fd_target) == -1) - { - perror("dup2"); - close(new_fd); - if (saved_fd != -1) - close(saved_fd); - return 1; - } - close(new_fd); - } - - int ret = execution(redir->child, vars); - - if (saved_fd != -1) - { - dup2(saved_fd, fd_target); - close(saved_fd); - } - else - { - close(fd_target); - } - - return ret; - } - default: { + case AST_IF: + return exec_ast_if(ast_get_if(ast), vars); + case AST_LIST: + return exec_ast_list(ast_get_list(ast), vars); + case AST_AND_OR: + return exec_ast_and_or(ast_get_and_or(ast), vars); + case AST_REDIR: + return exec_ast_redir(ast_get_redir(ast), vars); + default: return 127; } - } } diff --git a/src/execution/execution_helpers.c b/src/execution/execution_helpers.c new file mode 100644 index 0000000..8041a3c --- /dev/null +++ b/src/execution/execution_helpers.c @@ -0,0 +1,216 @@ +#define _POSIX_C_SOURCE 200809L +#include "execution_helpers.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "../expansion/expansion.h" +#include "../utils/ast/ast.h" +#include "../utils/hash_map/hash_map.h" +#include "execution.h" + +static char **list_to_argv(struct list *command_list) +{ + size_t len = 0; + struct list *cur = command_list; + while (cur) + { + len++; + cur = cur->next; + } + char **argv = calloc(len + 1, sizeof(char *)); + if (!argv) + return NULL; + cur = command_list; + for (size_t i = 0; i < len; i++) + { + argv[i] = (char *)cur->data; + cur = cur->next; + } + argv[len] = NULL; + return argv; +} + +static int try_builtin(char **argv); + +int exec_ast_command(struct ast_command *command, struct hash_map *vars) +{ + (void)vars; + if (!command || !(command->command)) + return 1; + char **argv = list_to_argv(command->command); + if (!argv || !(argv[0])) + { + free(argv); + return 0; + } + int builtin_ret = try_builtin(argv); + if (builtin_ret != -1) + { + free(argv); + return builtin_ret; + } + pid_t pid = fork(); + if (pid < 0) + { + perror("fork"); + free(argv); + return 1; + } + if (pid == 0) + { + execvp(argv[0], argv); + perror("execvp"); + _exit(127); + } + int status = 0; + waitpid(pid, &status, 0); + free(argv); + if (WIFEXITED(status)) + return WEXITSTATUS(status); + return 1; +} + +int exec_ast_if(struct ast_if *if_node, struct hash_map *vars) +{ + int cond = execution(if_node->condition, vars); + if (cond == 0) + return execution(if_node->then_clause, vars); + else + return execution(if_node->else_clause, vars); +} + +int exec_ast_list(struct ast_list *list_node, struct hash_map *vars) +{ + struct list *cur = list_node->children; + int ret = 0; + while (cur) + { + struct ast *child = (struct ast *)cur->data; + if (!ast_is_void(child)) + ret = execution(child, vars); + cur = cur->next; + } + return ret; +} + +int exec_ast_and_or(struct ast_and_or *ao_node, struct hash_map *vars) +{ + int left_ret = execution(ao_node->left, vars); + if (ao_node->type == AST_AND_OR_TYPE_AND) + { + if (left_ret == 0) + return execution(ao_node->right, vars); + return left_ret; + } + else + { + if (left_ret != 0) + return execution(ao_node->right, vars); + return left_ret; + } +} + +static int get_fd_target(const struct ast_redir *redir) +{ + if (redir->io_number != -1) + return redir->io_number; + if (redir->type == AST_REDIR_TYPE_LESS + || redir->type == AST_REDIR_TYPE_DLESS + || redir->type == AST_REDIR_TYPE_LESSAND) + return 0; + return 1; +} + +static int open_redir_file(const struct ast_redir *redir, int *flags, int *mode) +{ + *mode = 0644; + if (redir->type == AST_REDIR_TYPE_GREAT + || redir->type == AST_REDIR_TYPE_CLOBBER) + { + *flags = O_WRONLY | O_CREAT | O_TRUNC; + return open(redir->filename, *flags, *mode); + } + else if (redir->type == AST_REDIR_TYPE_DGREAT) + { + *flags = O_WRONLY | O_CREAT | O_APPEND; + return open(redir->filename, *flags, *mode); + } + else if (redir->type == AST_REDIR_TYPE_LESS) + { + *flags = O_RDONLY; + return open(redir->filename, *flags); + } + return -3; // not a file open +} + +static int handle_and_restore_fd(int saved_fd, int fd_target) +{ + if (saved_fd != -1) + { + dup2(saved_fd, fd_target); + close(saved_fd); + } + else + { + close(fd_target); + } + return 0; +} + +int exec_ast_redir(struct ast_redir *redir, struct hash_map *vars) +{ + int fd_target = get_fd_target(redir); + int saved_fd = dup(fd_target); + int new_fd = -1, flags = 0, mode = 0644; + if (redir->type == AST_REDIR_TYPE_GREAT + || redir->type == AST_REDIR_TYPE_CLOBBER + || redir->type == AST_REDIR_TYPE_DGREAT + || redir->type == AST_REDIR_TYPE_LESS) + { + new_fd = open_redir_file(redir, &flags, &mode); + if (new_fd == -1) + { + perror("open"); + if (saved_fd != -1) + close(saved_fd); + return 1; + } + if (dup2(new_fd, fd_target) == -1) + { + perror("dup2"); + close(new_fd); + if (saved_fd != -1) + close(saved_fd); + return 1; + } + close(new_fd); + } + else if (redir->type == AST_REDIR_TYPE_GREATAND + || redir->type == AST_REDIR_TYPE_LESSAND) + { + new_fd = atoi(redir->filename); + if (dup2(new_fd, fd_target) == -1) + { + perror("dup2"); + if (saved_fd != -1) + close(saved_fd); + return 1; + } + } + int ret = execution(redir->child, vars); + handle_and_restore_fd(saved_fd, fd_target); + return ret; +} + +// Dummy try_builtin for linking +static int try_builtin(char **argv) +{ + (void)argv; + return -1; +} diff --git a/src/execution/execution_helpers.h b/src/execution/execution_helpers.h new file mode 100644 index 0000000..ebac0cb --- /dev/null +++ b/src/execution/execution_helpers.h @@ -0,0 +1,13 @@ +#ifndef EXECUTION_HELPERS_H +#define EXECUTION_HELPERS_H + +#include "../utils/ast/ast.h" +#include "../utils/hash_map/hash_map.h" + +int exec_ast_command(struct ast_command *command, struct hash_map *vars); +int exec_ast_if(struct ast_if *if_node, struct hash_map *vars); +int exec_ast_list(struct ast_list *list_node, struct hash_map *vars); +int exec_ast_and_or(struct ast_and_or *ao_node, struct hash_map *vars); +int exec_ast_redir(struct ast_redir *redir, struct hash_map *vars); + +#endif // EXECUTION_HELPERS_H diff --git a/src/utils/ast/ast.c b/src/utils/ast/ast.c index e336a73..ae042ee 100644 --- a/src/utils/ast/ast.c +++ b/src/utils/ast/ast.c @@ -1,5 +1,5 @@ -#define _POSIX_C_SOURCE 12344 +#define _POSIX_C_SOURCE 200809L #include "ast.h" #include