fix(execution): Reimplemented the redirection logic

This commit is contained in:
Jean 2026-01-29 18:18:04 +01:00
parent a98161d885
commit ec63be42e5
4 changed files with 75 additions and 32 deletions

View file

@ -14,8 +14,6 @@
#include "../utils/ast/ast.h" #include "../utils/ast/ast.h"
#include "../utils/hash_map/hash_map.h" #include "../utils/hash_map/hash_map.h"
// Refactored: delegates to helpers in execution_helpers.c // Refactored: delegates to helpers in execution_helpers.c
#include "execution_helpers.h" #include "execution_helpers.h"
@ -33,6 +31,7 @@ int execution(struct ast *ast, struct hash_map *vars)
struct ast_command *command = ast_get_command(ast); struct ast_command *command = ast_get_command(ast);
if (!expand(command, vars)) if (!expand(command, vars))
fprintf(stderr, "Error: Variable expansion failed\n"); fprintf(stderr, "Error: Variable expansion failed\n");
return exec_ast_command(command, vars); return exec_ast_command(command, vars);
} }
case AST_IF: case AST_IF:
@ -41,8 +40,6 @@ int execution(struct ast *ast, struct hash_map *vars)
return exec_ast_list(ast_get_list(ast), vars); return exec_ast_list(ast_get_list(ast), vars);
case AST_AND_OR: case AST_AND_OR:
return exec_ast_and_or(ast_get_and_or(ast), vars); return exec_ast_and_or(ast_get_and_or(ast), vars);
case AST_REDIR:
return exec_ast_redir(ast_get_redir(ast), vars);
default: default:
return 127; return 127;
} }

View file

@ -12,6 +12,7 @@
#include "../expansion/expansion.h" #include "../expansion/expansion.h"
#include "../utils/ast/ast.h" #include "../utils/ast/ast.h"
#include "../utils/hash_map/hash_map.h" #include "../utils/hash_map/hash_map.h"
#include "../utils/lists/lists.h"
#include "../utils/vars/vars.h" #include "../utils/vars/vars.h"
#include "execution.h" #include "execution.h"
@ -42,40 +43,56 @@ static int try_builtin(char **argv, struct hash_map *vars);
int exec_ast_command(struct ast_command *command, struct hash_map *vars) int exec_ast_command(struct ast_command *command, struct hash_map *vars)
{ {
(void)vars; (void)vars;
set_all_redir(command->redirections);
if (!command || !(command->command)) if (!command || !(command->command))
{
return 1; return 1;
}
char **argv = list_to_argv(command->command); char **argv = list_to_argv(command->command);
if (!argv || !(argv[0])) if (!argv || !(argv[0]))
{ {
free(argv); free(argv);
unset_all_redir();
return 0; return 0;
} }
int builtin_ret = try_builtin(argv, vars); int builtin_ret = try_builtin(argv, vars);
if (builtin_ret != -1) if (builtin_ret != -1)
{ {
free(argv); free(argv);
unset_all_redir();
return builtin_ret; return builtin_ret;
} }
pid_t pid = fork(); pid_t pid = fork();
if (pid < 0) if (pid < 0)
{ {
perror("fork"); perror("fork");
free(argv); free(argv);
unset_all_redir();
return 1; return 1;
} }
if (pid == 0) if (pid == 0)
{ {
execvp(argv[0], argv); execvp(argv[0], argv);
perror("execvp"); perror("execvp");
unset_all_redir();
_exit(127); _exit(127);
} }
int status = 0; int status = 0;
waitpid(pid, &status, 0); waitpid(pid, &status, 0);
free(argv); free(argv);
unset_all_redir();
if (WIFEXITED(status)) if (WIFEXITED(status))
{ {
return WEXITSTATUS(status); return WEXITSTATUS(status);
} }
return 1; return 1;
} }
@ -166,42 +183,71 @@ static int handle_and_restore_fd(int saved_fd, int fd_target)
return 0; return 0;
} }
/* static int set_all_redir(struct list *redir_list)
static open_all_redir(const struct ast_list redir_list)
{ {
while (redir_list){ while (redir_list)
struct ast_redir *redir = (struct ast_redir*)redir_list->data; {
struct ast_redir *redir = (struct ast_redir *)redir_list->data;
int target_fd; int target_fd;
if (redir->io_number != -1) if (redir->io_number != -1)
{ {
target_fd = redir->io_number; target_fd = redir->io_number;
}
else
{
// assign target_fd depending on redir type
if (redir->type == AST_REDIR_TYPE_LESS
|| redir->type == AST_REDIR_TYPE_LESSGREAT
|| redir->type == AST_REDIR_TYPE_LESSAND)
{
target_fd = 0;
}
else
{
target_fd = 1;
}
} }
else
{
// assign target_fd depending on redir type
}
int saved_fd = dup(target_fd); redir->saved_fd = dup(target_fd);
int new_fd = -1;
// if redir type is not with '&' int flags = 0;
// then we open("filename") int mode = 0644;
// else, no need to open, just new_fd = atoi(filename) if (redir->type == AST_REDIR_TYPE_GREAT
|| redir->type == AST_REDIR_TYPE_CLOBBER
open(); || redir->type == AST_REDIR_TYPE_DGREAT
|| redir->type == AST_REDIR_TYPE_LESS)
dup2(target_fd, new_fd); {
new_fd = open_redir_file(redir, &flags, &mode);
close(new_fd); if (new_fd == -1)
{
// append target_fd and saved_fd to a list perror("open");
// in order to be able to restore all the fds return -1;
}
}
else if (redir->type == AST_REDIR_TYPE_GREATAND
|| redir->type == AST_REDIR_TYPE_LESSAND)
{
new_fd = atoi(redir->filename);
}
if (dup2(new_fd, target_fd) == -1)
{
perror("dup2");
if (new_fd != -1)
{
close(new_fd);
}
return -1;
}
if (new_fd != -1)
{
close(new_fd);
}
redir_list = redir_list->next;
} }
return 0;
} }
*/
/* /*
int exec_ast_redir(struct ast_redir *redir, struct hash_map *vars) int exec_ast_redir(struct ast_redir *redir, struct hash_map *vars)
{ {

View file

@ -8,6 +8,5 @@ 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_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_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_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 #endif // EXECUTION_HELPERS_H

View file

@ -21,6 +21,7 @@ struct ast_redir
int io_number; // The FD being redirected (default -1 if not specified, int io_number; // The FD being redirected (default -1 if not specified,
// implies 0 or 1 based on type) // implies 0 or 1 based on type)
enum ast_redir_type type; enum ast_redir_type type;
int saved_fd; // To store the original FD for restoration (-1 before save)
}; };
bool ast_is_redir(struct ast *node); bool ast_is_redir(struct ast *node);