fix(execution): Reimplemented the redirection logic
This commit is contained in:
parent
a98161d885
commit
ec63be42e5
4 changed files with 75 additions and 32 deletions
|
|
@ -14,8 +14,6 @@
|
|||
#include "../utils/ast/ast.h"
|
||||
#include "../utils/hash_map/hash_map.h"
|
||||
|
||||
|
||||
|
||||
// Refactored: delegates to helpers in execution_helpers.c
|
||||
#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);
|
||||
if (!expand(command, vars))
|
||||
fprintf(stderr, "Error: Variable expansion failed\n");
|
||||
|
||||
return exec_ast_command(command, vars);
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "../expansion/expansion.h"
|
||||
#include "../utils/ast/ast.h"
|
||||
#include "../utils/hash_map/hash_map.h"
|
||||
#include "../utils/lists/lists.h"
|
||||
#include "../utils/vars/vars.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)
|
||||
{
|
||||
(void)vars;
|
||||
set_all_redir(command->redirections);
|
||||
|
||||
if (!command || !(command->command))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char **argv = list_to_argv(command->command);
|
||||
if (!argv || !(argv[0]))
|
||||
{
|
||||
free(argv);
|
||||
unset_all_redir();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int builtin_ret = try_builtin(argv, vars);
|
||||
if (builtin_ret != -1)
|
||||
{
|
||||
free(argv);
|
||||
unset_all_redir();
|
||||
return builtin_ret;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0)
|
||||
{
|
||||
perror("fork");
|
||||
free(argv);
|
||||
unset_all_redir();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
execvp(argv[0], argv);
|
||||
perror("execvp");
|
||||
unset_all_redir();
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
waitpid(pid, &status, 0);
|
||||
free(argv);
|
||||
unset_all_redir();
|
||||
|
||||
if (WIFEXITED(status))
|
||||
{
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -166,42 +183,71 @@ static int handle_and_restore_fd(int saved_fd, int fd_target)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
static open_all_redir(const struct ast_list redir_list)
|
||||
static int set_all_redir(struct list *redir_list)
|
||||
{
|
||||
while (redir_list){
|
||||
struct ast_redir *redir = (struct ast_redir*)redir_list->data;
|
||||
while (redir_list)
|
||||
{
|
||||
struct ast_redir *redir = (struct ast_redir *)redir_list->data;
|
||||
int target_fd;
|
||||
|
||||
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);
|
||||
|
||||
// if redir type is not with '&'
|
||||
// then we open("filename")
|
||||
// else, no need to open, just new_fd = atoi(filename)
|
||||
|
||||
open();
|
||||
|
||||
dup2(target_fd, new_fd);
|
||||
|
||||
close(new_fd);
|
||||
|
||||
// append target_fd and saved_fd to a list
|
||||
// in order to be able to restore all the fds
|
||||
redir->saved_fd = dup(target_fd);
|
||||
int new_fd = -1;
|
||||
int flags = 0;
|
||||
int 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");
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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_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
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ struct ast_redir
|
|||
int io_number; // The FD being redirected (default -1 if not specified,
|
||||
// implies 0 or 1 based on 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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue