diff --git a/includes/exec/builtins.h b/includes/exec/builtins.h index 70a06dc..0b6ffc3 100644 --- a/includes/exec/builtins.h +++ b/includes/exec/builtins.h @@ -23,21 +23,23 @@ # include # include +# define UNSET_ARG "not enough arguments" # define EXPRT_INV "not a valid identifier" // void echo(char *msg, int flag); int builtin_echo(t_ast_n *node, char **envp); int builtin_exit(char **arg, bool depth, t_ast_n *node); int builtin_pwd(char **arg); int builtin_env(char **arg, char **envp); -int builtin_unset(char **arg, t_ast_n *head); -int builtin_cd(char **arg, t_ast_n *head); -int builtin_export(char **arg, t_ast_n *head); +int builtin_unset(char **arg, t_ast_n *head); +int builtin_cd(char **arg, t_ast_n *head); +int builtin_export(char **arg, t_ast_n *head); //UTILS -int count_char(char *str); -int count_args(char **tab); -int extractenv(char *str, char **envp); +int count_char(char *str); +int count_args(char **tab); +int extractenv(char *str, char **envp); char *ft_getenv(char *str, char **envp); -int err_msg_cmd(char *cmd, char *arg, char *msg, int code); +int err_msg_cmd(char *cmd, char *arg, char *msg, int code); +void char_swap(char **s1, char **s2); #endif diff --git a/includes/exec/exec.h b/includes/exec/exec.h index b915f81..a96cf5a 100644 --- a/includes/exec/exec.h +++ b/includes/exec/exec.h @@ -11,7 +11,7 @@ /* ************************************************************************** */ #ifndef EXEC_H -#define EXEC_H +# define EXEC_H # include "../minishell.h" # include @@ -19,7 +19,50 @@ # include # include # include +# include -int execute_command(t_ast_n *node); +int execute_command(t_ast_n *node); + +//EXEC_REDIR +void handle_file(t_ast_n *node, int check, int i); +void handle_redir(t_ast_n *node); +void reset_redir(t_ast_n *node); +int err_fork_pline(int *pipes); + +//EXEC_BUILTIN +int is_builtin(char *str); +int exec_builtin(t_ast_n *node); + +//EXEC_PLINE +void exec_pcmd(t_ast_n *pcmd); +void exec_pchild(int *pipes, int index, t_ast_n *pcmd, int cmds); +int end_pline(pid_t last_pid, t_ast_n **pline); +int exec_pline(t_ast_n **pline); + +//EXEC_SUBSH +int exec_shcmd(t_ast_n *node); +int execute_shcommand(t_ast_n *node); +int exec_subsh(t_ast_n *node); + +//EXEC_HEREDOC +void expander_here(char **str, t_ast_n *node); +void here_remove_quote(t_ast_n *node, int j, char c); +int ifhere_remove_quote(t_ast_n *node, int j); +void read_input(t_ast_n *node, int j); +void here_doc(t_ast_n *node, int i); + +//EXEC_UTILS +int execis_validchar(char c); +int execget_var_len(char *str, t_ast_n *node, int *j); +int get_dup_len(char *str, t_ast_n *node); +int execvalid_next(char c); +char *execextract_env(char *str, char **envp); + +//EXEC_CMD +int count_cmds(t_ast_n **pline); +char *find_path(char *cmd, char **env); +void return_error(char *arg, char *msg, int code, t_ast_n *node); +int exec(t_ast_n *node); +int exec_scmd(t_ast_n *node); #endif diff --git a/includes/exec/expander.h b/includes/exec/expander.h index b67c270..ce6ffe4 100644 --- a/includes/exec/expander.h +++ b/includes/exec/expander.h @@ -31,4 +31,12 @@ int in_dquote(char *str, char *ch); int is_exvalidchar(char c); int exvalid_next(char c); +//EXPANDER_VAR_UTILS +int expand_exit(t_ast_n *node, int j, int k); +int get_new_len(t_ast_n *node, int j); +int valid_expand(t_ast_n *node, int j, int k); +char *create_new(t_ast_n *node, int j, int *len); +void handle_copy(t_ast_n *node, int j, char **new); +void cat_exit(t_ast_n *node, char **new, int i, int *k); + #endif diff --git a/srcs/builtins/cd.c b/srcs/builtins/cd.c index b4f54c0..47f2484 100644 --- a/srcs/builtins/cd.c +++ b/srcs/builtins/cd.c @@ -37,7 +37,8 @@ int builtin_cd(char **arg, t_ast_n *head) { char *path; - if (count_var(arg) == 1 || (count_var(arg) == 2 && ft_strncmp(arg[1], "~", 1) == 0)) + if (count_var(arg) == 1 || (count_var(arg) == 2 + && ft_strncmp(arg[1], "~", 1) == 0)) { path = get_var_value("HOME", head->msh->env); if (!path) diff --git a/srcs/builtins/echo.c b/srcs/builtins/echo.c index c4653bd..56c6db9 100644 --- a/srcs/builtins/echo.c +++ b/srcs/builtins/echo.c @@ -46,27 +46,9 @@ char *ft_getenv(char *str, char **envp) return (&envp[j][len]); } -int extractenv(char *str, char **envp) +int print_exit(char **arg, t_ast_n *node) { - int i; - char *var; - char *tmp; - - i = 0; - while (str[i] && str[i] != ' ') - i++; - if (i >= 1) - tmp = ft_substr(str, 1, i - 1); - var = get_var_value(tmp, envp); - free(tmp); - if (var) - ft_printf("%s", var); - return (i); -} - -int print_exit(char *arg, t_ast_n *node) -{ - if (arg && ft_strncmp(arg, "$?", 2) == 0) + if (*arg && ft_strncmp(*arg, "$?", 2) == 0) { ft_fprintf(1, "%d", node->msh->ex_code); return (1); @@ -84,15 +66,8 @@ static void echo_print(t_ast_n *node, int j, char **envp) i = 0; while (node->args[j][i]) { - if (print_exit(node->args[j], node)) - break ; - // if (node->args[j][i] == '$') - // { - // if (!node->args[j][i + 1] || node->args[j][i + 1] == ' ') - // ft_put_c(node->args[j][i++]); - // else - // i += extractenv(&node->args[j][i], envp); - // } + if (print_exit(&node->args[j], node)) + i += 2; else ft_put_c(node->args[j][i++]); } diff --git a/srcs/builtins/export.c b/srcs/builtins/export.c index b70278f..acbe360 100644 --- a/srcs/builtins/export.c +++ b/srcs/builtins/export.c @@ -19,7 +19,7 @@ int is_export_valid(char *str) if (!ft_isalpha(*str) && str[0] != '_') return (0); equal = ft_strchr(str, '='); - if(!equal) + if (!equal) { while (*(++str)) { @@ -43,7 +43,7 @@ char **key_value(char *str) { char **tmp; char *save; - char *equal; + char *equal; tmp = malloc(sizeof(char *) * (2 + 1)); if (!tmp) @@ -85,7 +85,6 @@ int print_export(char **envp) { int i; int j; - char *tmp; int len; i = -1; @@ -97,12 +96,9 @@ int print_export(char **envp) j = 0; while (j < len - i - 1) { - if (ft_strncmp(envp[j], envp[j + 1], ft_strchr(envp[j], '=') - envp[j]) > 0) - { - tmp = envp[j]; - envp[j] = envp[j + 1]; - envp[j + 1] = tmp; - } + if (ft_strncmp(envp[j], envp[j + 1], + ft_strchr(envp[j], '=') - envp[j]) > 0) + char_swap(&envp[j], &(envp[j + 1])); j++; } } @@ -112,7 +108,7 @@ int print_export(char **envp) int builtin_export(char **arg, t_ast_n *head) { - int i; + int i; char **tmp; i = 0; diff --git a/srcs/builtins/pwd.c b/srcs/builtins/pwd.c index 409560f..2e04b80 100644 --- a/srcs/builtins/pwd.c +++ b/srcs/builtins/pwd.c @@ -24,7 +24,7 @@ int builtin_pwd(char **arg) free(cwd); return (0); } - else + else { perror("pwd"); return (1); diff --git a/srcs/builtins/unset.c b/srcs/builtins/unset.c index 009e0e9..fe6746a 100644 --- a/srcs/builtins/unset.c +++ b/srcs/builtins/unset.c @@ -12,27 +12,6 @@ #include "../../includes/minishell.h" -// void builtin_unset(char *str, char **envp) -// { -// int i; -// char *var; -// -// if (count_char(str) == 5) -// { -// ft_putendl_fd("unset: not enough arguments", 2); -// // exit(1); -// } -// i = 0; -// while(str[5 + i] && str[5 + i] == ' ') -// i++; -// var = &str[5 + i]; -// i = 0; -// while (ft_strnstr(envp[i], var, ft_strlen(var)) == NULL) -// i++; -// if (envp[i]) -// envp[i][0] = '\0'; -// } -// int builtin_unset(char **arg, t_ast_n *head) { int i; @@ -40,8 +19,8 @@ int builtin_unset(char **arg, t_ast_n *head) i = 0; if (count_args(arg) == 1) - return (err_msg_cmd("unset", NULL, "not enough arguments", EXIT_FAILURE)); + return (err_msg_cmd("unset", NULL, UNSET_ARG, EXIT_FAILURE)); while (++i < count_args(arg)) - ret = remove_env_var(arg[i], head->msh); + ret = remove_env_var(arg[i], head->msh); return (!ret); } diff --git a/srcs/builtins/utils.c b/srcs/builtins/utils.c index 57555af..57d9b76 100644 --- a/srcs/builtins/utils.c +++ b/srcs/builtins/utils.c @@ -32,3 +32,12 @@ int count_args(char **tab) i++; return (i); } + +void char_swap(char **s1, char **s2) +{ + char *tmp; + + tmp = *s1; + *s1 = *s2; + *s2 = tmp; +} diff --git a/srcs/execution/exec.c b/srcs/execution/exec.c index 1af006a..b30bf5f 100644 --- a/srcs/execution/exec.c +++ b/srcs/execution/exec.c @@ -10,579 +10,7 @@ /* */ /* ************************************************************************** */ -#include "../../includes/minishell.h" -#include -#include -#include - -void handle_file(t_ast_n *node, int check, int i) -{ - int fd; - - if (check == 1) - fd = open(node->files[i], O_RDONLY); - else if (check == 2) - fd = open(node->files[i], O_WRONLY | O_CREAT | O_TRUNC, 0666); - else if (check == 3) - fd = open(node->files[i], O_WRONLY | O_CREAT | O_APPEND, 0666); - if (fd == -1) - { - perror("open"); - exit(1); - } - if (check == 1) - node->_stdin = fd; - else if (check == 2 || check == 3) - node->_stdout = fd; -} - -static int is_validchar(char c) -{ - if (ft_isalnum(c) || c == '_') - return (1); - return (0); -} - -static int get_var_len(char *str, t_ast_n *node, int *j) -{ - int len; - int ret; - char *var; - - len = *j + 1; - while (str[len] && is_validchar(str[len])) - len++; - var = ft_substr(str, *j + 1, (size_t)len - (*j + 1)); - *j = len; - ret = ft_strlen(get_var_value(var, node->msh->env)); - ft_free(&var); - return (ret - (len - (*j + 1))); -} - -int get_dup_len(char *str, t_ast_n *node) -{ - int i; - int len; - - i = 0; - len = ft_strlen(str); - while (str[i]) - { - if (str[i] == '$') - { - len += get_var_len(str, node, &i); - i--; - } - i++; - } - return (len); -} - -static int valid_next(char c) -{ - if (c != '\0' && is_validchar(c)) - return (1); - return (0); -} - -static char *extract_env(char *str, char **envp) -{ - int i; - char *var; - char *tmp; - - i = 1; - while (str[i] && is_validchar(str[i])) - i++; - if (i > 1) - tmp = ft_substr(str, 1, i - 1); - var = get_var_value(tmp, envp); - ft_free(&tmp); - return (var); -} - -void expander_here(char **str, t_ast_n *node) -{ - char *new; - int i; - int j; - int len; - - i = -1; - len = get_dup_len(*str, node); - new = ft_calloc(len + 1, sizeof(char)); - if (!new) - return ; - j = 0; - while ((*str)[j] && ++i < len) - { - if ((*str)[j] != '$') - new[i] = (*str)[j++]; - else if ((*str)[j] == '$' && valid_next((*str)[j + 1])) - { - ft_strlcat(new, extract_env(&((*str)[j]), node->msh->env), -1); - i = ft_strlen(new) - 1; - while ((*str)[++j] && is_validchar((*str)[j])) - continue ; - } - } - ft_free(str); - *str = new; -} - -void here_remove_quote(t_ast_n *node, int j, char c) -{ - char *new; - int i; - int k; - int len; - - i = 0; - k = 0; - len = ft_strlen(node->files[j]); - new = ft_calloc(len - 1, sizeof(char)); - while (i < len - 2) - { - if ((&(node->files[j][k]) == ft_strchr(node->files[j], c)) || - (&(node->files[j][k]) == ft_strrchr(node->files[j], c))) - { - k++; - } - else - new[i++] = node->files[j][k++]; - } - ft_free(&node->files[j]); - node->files[j] = new; -} - -int ifhere_remove_quote(t_ast_n *node, int j) -{ - char c; - int ret; - - ret = 0; - if (!ft_strchr(node->files[j], '\'') && !ft_strchr(node->files[j], '\"')) - c = 0; - else if (!ft_strchr(node->files[j], '\"')) - c = '\''; - else if (!ft_strchr(node->files[j], '\'')) - c = '\"'; - else if (ft_strchr(node->files[j], '\'') < ft_strchr(node->files[j], '\"')) - c = '\''; - else - c = '\"'; - if (c && (ft_strchr(node->files[j], c) != ft_strrchr(node->files[j], c))) - here_remove_quote(node, j, c); - if (c) - ret = 1; - return (ret); -} - -void read_input(t_ast_n *node, int j) -{ - char *str; - int len; - int check; - - check = ifhere_remove_quote(node, j); - len = ft_strlen(node->files[j]); - str = get_next_line(node->msh->here_fd, 0); - while (str && ft_strncmp(str, node->files[j], len) != 0) - { - if (!check) - expander_here(&str, node); - write(1, str, ft_strlen(str)); - ft_free(&str); - str = get_next_line(node->msh->here_fd, 0); - } - if (!str) - get_next_line(node->msh->here_fd, 1); - ft_free(&str); -} - -void here_doc(t_ast_n *node, int i) -{ - pid_t pid; - - pipe(node->fds); - pid = fork(); - if (pid == 0) - { - dup2(node->fds[1], STDOUT_FILENO); - close(node->fds[0]); - close(node->fds[1]); - read_input(node, i); - free_child(node->msh); - exit(EXIT_SUCCESS); - } - else if (pid > 0) - { - close(node->fds[1]); - dup2(node->fds[0], STDIN_FILENO); - close(node->fds[0]); - waitpid(pid, NULL, 0); - } - else if (pid < 0) - exit (err_msg_cmd("fork", NULL, "failed to fork", 1)); -} - -void save_stds(t_ast_n *node) -{ - node->save_stdo = dup(STDOUT_FILENO); - node->save_stdi = dup(STDIN_FILENO); -} - -void handle_redir(t_ast_n *node) -{ - int i; - - i = -1; - if (node->state == _PLINE || node->redir[0] != _NR) - save_stds(node); - while (node->state != _PLINE && node->redir[++i] && node->redir[i] != _NR) - { - if (node->redir[i] == _RED_L) - handle_file(node, 1, i); - else if (node->redir[i] == _RED_R) - handle_file(node, 2, i); - else if (node->redir[i] == _RED_DR) - handle_file(node, 3, i); - else if (node->redir[i] == _RED_DL) - here_doc(node, i); - if (node->redir[i] == _RED_L) - { - dup2(node->_stdin, STDIN_FILENO); - close(node->_stdin); - } - else if (node->redir[i] == _RED_R || node->redir[i] == _RED_DR) - { - dup2(node->_stdout, STDOUT_FILENO); - close(node->_stdout); - } - } -} - -int is_builtin(char *str) -{ - if (ft_strncmp(str, "exit", -1) == 0) - return (1); - else if (ft_strncmp(str, "pwd", -1) == 0) - return (1); - else if (ft_strncmp(str, "echo", -1) == 0) - return (1); - else if (ft_strncmp(str, "env", -1) == 0) - return (1); - else if (ft_strncmp(str, "unset", -1) == 0) - return (1); - else if (ft_strncmp(str, "cd", -1) == 0) - return (1); - else if (ft_strncmp(str, "export", -1) == 0) - return (1); - else - return (0); -} - -void reset_redir(t_ast_n *node) -{ - if (node->state == _PLINE || node->redir[0] != _NR) - { - dup2(node->save_stdo, STDOUT_FILENO); - close(node->save_stdo); - dup2(node->save_stdi, STDIN_FILENO); - close(node->save_stdi); - } -} - -int exec_builtin(t_ast_n *node) -{ - int ret; - - expand_node(node); - if (ft_strncmp(node->cmd, "exit", -1) == 0) - ret = builtin_exit(node->args, node->sh, node); - else if (ft_strncmp(node->cmd, "pwd", -1) == 0) - ret = builtin_pwd(node->args); - else if (ft_strncmp(node->cmd, "echo", -1) == 0) - ret = builtin_echo(node, node->msh->env); - else if (ft_strncmp(node->cmd, "env", -1) == 0) - ret = builtin_env(node->args, node->msh->env); - else if (ft_strncmp(node->cmd, "unset", -1) == 0) - ret = builtin_unset(node->args, node); - else if (ft_strncmp(node->cmd, "cd", -1) == 0) - ret = builtin_cd(node->args, node); - else - ret = builtin_export(node->args, node); - return (ret); -} - -int count_cmds(t_ast_n **pline) -{ - int i; - - i = 0; - if (!pline || !*pline) - return (0); - while (pline[i]) - i++; - return (i); -} - -char *find_path(char *cmd, char **env) -{ - char *tmp; - char *path; - char **paths; - int i; - - if (access(cmd, F_OK) == 0 && access(cmd, X_OK) == 0) - return (cmd); - i = 0; - while (env[i] && ft_strnstr(env[i], "PATH=", 5) == NULL) - i++; - if (!env[i]) - return (NULL); - paths = ft_split(env[i] + 5, ":"); - i = -1; - while (paths[++i]) - { - tmp = ft_strjoin(paths[i], "/"); - path = ft_strjoin(tmp, cmd); - free(tmp); - if (access(path, F_OK) == 0) - return (free_tab(paths), path); - free(path); - } - free_tab(paths); - return (NULL); -} - -void return_error(char *arg, char *msg, int code, t_ast_n *node) -{ - ft_fprintf(2, "%s: %s\n", arg, msg); - free_child(node->msh); - exit(code); -} - -int exec(t_ast_n *node) -{ - char *path; - - expand_node(node); - path = find_path(node->cmd, node->msh->env); - if (!path) - return_error(node->cmd, "command not found", 127, node); - if (access(path, X_OK) != 0) - return_error(path, "Permission denied", 126, node); - if (execve(path, node->args, node->msh->env) == -1) - { - free_child(node->msh); - perror("execve"); - exit(1); - } - return (0); -} - -int exec_scmd(t_ast_n *node) -{ - pid_t pid; - int status; - - if (is_builtin(node->cmd)) - return (exec_builtin(node)); - else - { - pid = fork(); - if (pid == 0) - exec(node); - else if (pid > 0) - { - waitpid(pid, &status, 0); - if (WIFEXITED(status)) - return (WEXITSTATUS(status)); - else - return (1); - } - else - perror("fork"); - return (1); - } -} - -int err_fork_pline(int *pipes) -{ - close(pipes[0]); - close(pipes[1]); - perror("fork"); - return (1); -} - -void exec_pcmd(t_ast_n *pcmd) -{ - int ret; - - if (!pcmd->cmd) - exit(0); - if (is_builtin(pcmd->cmd)) - { - ret = exec_builtin(pcmd); - free_child(pcmd->msh); - exit(ret); - } - else - exec(pcmd); -} - -int exec_subsh(t_ast_n *node); -int execute_shcommand(t_ast_n *node); - -void exec_pchild(int *pipes, int index, t_ast_n *pcmd, int cmds) -{ - int ret; - - ret = 0; - if (index < cmds - 1) - dup2(pipes[1], STDOUT_FILENO); - close(pipes[0]); - close(pipes[1]); - handle_redir(pcmd); - if (pcmd->state == _CMD) - exec_pcmd(pcmd); - else if (pcmd->state == _SUBSH) - { - ret = execute_shcommand(pcmd->left); - free_child(pcmd->msh); - exit(ret); - } -} - -int end_pline(pid_t last_pid, t_ast_n **pline) -{ - int status; - int i; - - i = -1; - waitpid(last_pid, &status, 0); - while (++i < count_cmds(pline) - 1) - wait(NULL); - reset_redir(pline[0]->parent); - if (WIFEXITED(status)) - return (WEXITSTATUS(status)); - else - return (1); -} - -int exec_pline(t_ast_n **pline) -{ - int i; - pid_t pid; - pid_t last_pid; - - i = -1; - while (pline[++i]) - { - if (i == 0) - handle_redir(pline[0]->parent); - pipe(pline[i]->fds); - pid = fork(); - if (pid == 0) - exec_pchild(pline[i]->fds, i, pline[i], count_cmds(pline)); - else if (pid > 0) - { - dup2(pline[i]->fds[0], STDIN_FILENO); - close(pline[i]->fds[0]); - close(pline[i]->fds[1]); - if (i == count_cmds(pline) - 1) - last_pid = pid; - } - else if (pid < 0) - return (err_fork_pline(pline[i]->fds)); - } - return (end_pline(last_pid, pline)); -} - -int exec_shcmd(t_ast_n *node) -{ - pid_t pid; - int status; - - if (is_builtin(node->cmd)) - return (exec_builtin(node)); - else - { - pid = fork(); - if (pid == 0) - exec(node); - else if (pid > 0) - { - waitpid(pid, &status, 0); - if (WIFEXITED(status)) - return (WEXITSTATUS(status)); - else - return (1); - } - else - perror("fork"); - return (1); - } -} - -int exec_subsh(t_ast_n *node); - -int execute_shcommand(t_ast_n *node) -{ - if (node->state == _CMD) - handle_redir(node); - if (node->state == _CMD) - node->msh->ex_code = exec_shcmd(node); - else if (node->state == _AND) - { - node->msh->ex_code = execute_shcommand(node->left); - if (node->msh->ex_code == 0) - node->msh->ex_code = execute_shcommand(node->right); - } - else if (node->state == _OR) - { - node->msh->ex_code = execute_shcommand(node->left); - if (node->msh->ex_code != 0) - node->msh->ex_code = execute_shcommand(node->right); - } - else if (node->state == _PLINE) - node->msh->ex_code = exec_pline(node->pline); - else if (node->state == _SUBSH) - node->msh->ex_code = exec_subsh(node->left); - if (node->state == _CMD) - reset_redir(node); - return (node->msh->ex_code); -} - -int exec_subsh(t_ast_n *node) -{ - int status; - pid_t pid; - int ret; - - pid = fork(); - if (pid == 0) - { - handle_redir(node->parent); - ret = execute_shcommand(node); - free_child(node->msh); - exit(ret); - } - else if (pid > 0) - { - waitpid(pid, &status, 0); - if (WIFEXITED(status) && node->parent->state != _PLINE) - return (WEXITSTATUS(status)); - else - return (1); - } - else - { - perror("fork"); - return (1); - } -} +#include "../../includes/exec/exec.h" int execute_command(t_ast_n *node) { diff --git a/srcs/execution/exec_builtin.c b/srcs/execution/exec_builtin.c new file mode 100644 index 0000000..5710edd --- /dev/null +++ b/srcs/execution/exec_builtin.c @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_builtin.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lderidde +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 09:48:21 by lderidde #+# #+# */ +/* Updated: 2025/02/12 09:48:21 by lderidde ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/exec/exec.h" + +int is_builtin(char *str) +{ + if (ft_strncmp(str, "exit", -1) == 0) + return (1); + else if (ft_strncmp(str, "pwd", -1) == 0) + return (1); + else if (ft_strncmp(str, "echo", -1) == 0) + return (1); + else if (ft_strncmp(str, "env", -1) == 0) + return (1); + else if (ft_strncmp(str, "unset", -1) == 0) + return (1); + else if (ft_strncmp(str, "cd", -1) == 0) + return (1); + else if (ft_strncmp(str, "export", -1) == 0) + return (1); + else + return (0); +} + +int exec_builtin(t_ast_n *node) +{ + int ret; + + expand_node(node); + if (ft_strncmp(node->cmd, "exit", -1) == 0) + ret = builtin_exit(node->args, node->sh, node); + else if (ft_strncmp(node->cmd, "pwd", -1) == 0) + ret = builtin_pwd(node->args); + else if (ft_strncmp(node->cmd, "echo", -1) == 0) + ret = builtin_echo(node, node->msh->env); + else if (ft_strncmp(node->cmd, "env", -1) == 0) + ret = builtin_env(node->args, node->msh->env); + else if (ft_strncmp(node->cmd, "unset", -1) == 0) + ret = builtin_unset(node->args, node); + else if (ft_strncmp(node->cmd, "cd", -1) == 0) + ret = builtin_cd(node->args, node); + else + ret = builtin_export(node->args, node); + return (ret); +} diff --git a/srcs/execution/exec_cmd.c b/srcs/execution/exec_cmd.c new file mode 100644 index 0000000..8440839 --- /dev/null +++ b/srcs/execution/exec_cmd.c @@ -0,0 +1,106 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lderidde +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 10:00:08 by lderidde #+# #+# */ +/* Updated: 2025/02/12 10:00:08 by lderidde ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/exec/exec.h" + +int count_cmds(t_ast_n **pline) +{ + int i; + + i = 0; + if (!pline || !*pline) + return (0); + while (pline[i]) + i++; + return (i); +} + +char *find_path(char *cmd, char **env) +{ + char *tmp; + char *path; + char **paths; + int i; + + if (access(cmd, F_OK) == 0 && access(cmd, X_OK) == 0) + return (cmd); + i = 0; + while (env[i] && ft_strnstr(env[i], "PATH=", 5) == NULL) + i++; + if (!env[i]) + return (NULL); + paths = ft_split(env[i] + 5, ":"); + i = -1; + while (paths[++i]) + { + tmp = ft_strjoin(paths[i], "/"); + path = ft_strjoin(tmp, cmd); + free(tmp); + if (access(path, F_OK) == 0) + return (free_tab(paths), path); + free(path); + } + free_tab(paths); + return (NULL); +} + +void return_error(char *arg, char *msg, int code, t_ast_n *node) +{ + ft_fprintf(2, "%s: %s\n", arg, msg); + free_child(node->msh); + exit(code); +} + +int exec(t_ast_n *node) +{ + char *path; + + expand_node(node); + path = find_path(node->cmd, node->msh->env); + if (!path) + return_error(node->cmd, "command not found", 127, node); + if (access(path, X_OK) != 0) + return_error(path, "Permission denied", 126, node); + if (execve(path, node->args, node->msh->env) == -1) + { + free_child(node->msh); + perror("execve"); + exit(1); + } + return (0); +} + +int exec_scmd(t_ast_n *node) +{ + pid_t pid; + int status; + + if (is_builtin(node->cmd)) + return (exec_builtin(node)); + else + { + pid = fork(); + if (pid == 0) + exec(node); + else if (pid > 0) + { + waitpid(pid, &status, 0); + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); + else + return (1); + } + else + perror("fork"); + return (1); + } +} diff --git a/srcs/execution/exec_heredoc.c b/srcs/execution/exec_heredoc.c new file mode 100644 index 0000000..9cd8a62 --- /dev/null +++ b/srcs/execution/exec_heredoc.c @@ -0,0 +1,138 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_heredoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lderidde +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 09:53:26 by lderidde #+# #+# */ +/* Updated: 2025/02/12 09:53:26 by lderidde ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/exec/exec.h" + +void expander_here(char **str, t_ast_n *node) +{ + char *new; + int i; + int j; + int len; + + i = -1; + len = get_dup_len(*str, node); + new = ft_calloc(len + 1, sizeof(char)); + if (!new) + return ; + j = 0; + while ((*str)[j] && ++i < len) + { + if ((*str)[j] != '$') + new[i] = (*str)[j++]; + else if ((*str)[j] == '$' && execvalid_next((*str)[j + 1])) + { + ft_strlcat(new, execextract_env(&((*str)[j]), node->msh->env), -1); + i = ft_strlen(new) - 1; + while ((*str)[++j] && execis_validchar((*str)[j])) + continue ; + } + } + ft_free(str); + *str = new; +} + +void here_remove_quote(t_ast_n *node, int j, char c) +{ + char *new; + int i; + int k; + int len; + + i = 0; + k = 0; + len = ft_strlen(node->files[j]); + new = ft_calloc(len - 1, sizeof(char)); + while (i < len - 2) + { + if ((&(node->files[j][k]) == ft_strchr(node->files[j], c)) || + (&(node->files[j][k]) == ft_strrchr(node->files[j], c))) + { + k++; + } + else + new[i++] = node->files[j][k++]; + } + ft_free(&node->files[j]); + node->files[j] = new; +} + +int ifhere_remove_quote(t_ast_n *node, int j) +{ + char c; + int ret; + + ret = 0; + if (!ft_strchr(node->files[j], '\'') && !ft_strchr(node->files[j], '\"')) + c = 0; + else if (!ft_strchr(node->files[j], '\"')) + c = '\''; + else if (!ft_strchr(node->files[j], '\'')) + c = '\"'; + else if (ft_strchr(node->files[j], '\'') < ft_strchr(node->files[j], '\"')) + c = '\''; + else + c = '\"'; + if (c && (ft_strchr(node->files[j], c) != ft_strrchr(node->files[j], c))) + here_remove_quote(node, j, c); + if (c) + ret = 1; + return (ret); +} + +void read_input(t_ast_n *node, int j) +{ + char *str; + int len; + int check; + + check = ifhere_remove_quote(node, j); + len = ft_strlen(node->files[j]); + str = get_next_line(node->msh->here_fd, 0); + while (str && ft_strncmp(str, node->files[j], len) != 0) + { + if (!check) + expander_here(&str, node); + write(1, str, ft_strlen(str)); + ft_free(&str); + str = get_next_line(node->msh->here_fd, 0); + } + if (!str) + get_next_line(node->msh->here_fd, 1); + ft_free(&str); +} + +void here_doc(t_ast_n *node, int i) +{ + pid_t pid; + + pipe(node->fds); + pid = fork(); + if (pid == 0) + { + dup2(node->fds[1], STDOUT_FILENO); + close(node->fds[0]); + close(node->fds[1]); + read_input(node, i); + free_child(node->msh); + exit(EXIT_SUCCESS); + } + else if (pid > 0) + { + close(node->fds[1]); + dup2(node->fds[0], STDIN_FILENO); + close(node->fds[0]); + waitpid(pid, NULL, 0); + } + else if (pid < 0) + exit (err_msg_cmd("fork", NULL, "failed to fork", 1)); +} diff --git a/srcs/execution/exec_pline.c b/srcs/execution/exec_pline.c new file mode 100644 index 0000000..3ad7e0b --- /dev/null +++ b/srcs/execution/exec_pline.c @@ -0,0 +1,94 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_pline.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lderidde +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 09:50:12 by lderidde #+# #+# */ +/* Updated: 2025/02/12 09:50:12 by lderidde ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/exec/exec.h" + +void exec_pcmd(t_ast_n *pcmd) +{ + int ret; + + if (!pcmd->cmd) + exit(0); + if (is_builtin(pcmd->cmd)) + { + ret = exec_builtin(pcmd); + free_child(pcmd->msh); + exit(ret); + } + else + exec(pcmd); +} + +void exec_pchild(int *pipes, int index, t_ast_n *pcmd, int cmds) +{ + int ret; + + ret = 0; + if (index < cmds - 1) + dup2(pipes[1], STDOUT_FILENO); + close(pipes[0]); + close(pipes[1]); + handle_redir(pcmd); + if (pcmd->state == _CMD) + exec_pcmd(pcmd); + else if (pcmd->state == _SUBSH) + { + ret = execute_shcommand(pcmd->left); + free_child(pcmd->msh); + exit(ret); + } +} + +int end_pline(pid_t last_pid, t_ast_n **pline) +{ + int status; + int i; + + i = -1; + waitpid(last_pid, &status, 0); + while (++i < count_cmds(pline) - 1) + wait(NULL); + reset_redir(pline[0]->parent); + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); + else + return (1); +} + +int exec_pline(t_ast_n **pline) +{ + int i; + pid_t pid; + pid_t last_pid; + + i = -1; + while (pline[++i]) + { + if (i == 0) + handle_redir(pline[0]->parent); + pipe(pline[i]->fds); + pid = fork(); + if (pid == 0) + exec_pchild(pline[i]->fds, i, pline[i], count_cmds(pline)); + else if (pid > 0) + { + dup2(pline[i]->fds[0], STDIN_FILENO); + close(pline[i]->fds[0]); + close(pline[i]->fds[1]); + if (i == count_cmds(pline) - 1) + last_pid = pid; + } + else if (pid < 0) + return (err_fork_pline(pline[i]->fds)); + } + return (end_pline(last_pid, pline)); +} diff --git a/srcs/execution/exec_redir.c b/srcs/execution/exec_redir.c new file mode 100644 index 0000000..d055a1d --- /dev/null +++ b/srcs/execution/exec_redir.c @@ -0,0 +1,91 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_redir.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lderidde +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 09:42:31 by lderidde #+# #+# */ +/* Updated: 2025/02/12 09:42:31 by lderidde ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/exec/exec.h" + +void handle_file(t_ast_n *node, int check, int i) +{ + int fd; + + if (check == 1) + fd = open(node->files[i], O_RDONLY); + else if (check == 2) + fd = open(node->files[i], O_WRONLY | O_CREAT | O_TRUNC, 0666); + else if (check == 3) + fd = open(node->files[i], O_WRONLY | O_CREAT | O_APPEND, 0666); + if (fd == -1) + { + perror("open"); + exit(1); + } + if (check == 1) + node->_stdin = fd; + else if (check == 2 || check == 3) + node->_stdout = fd; +} + +static void save_stds(t_ast_n *node) +{ + if (node->state == _PLINE || node->redir[0] != _NR) + { + node->save_stdo = dup(STDOUT_FILENO); + node->save_stdi = dup(STDIN_FILENO); + } +} + +void handle_redir(t_ast_n *node) +{ + int i; + + i = -1; + save_stds(node); + while (node->state != _PLINE && node->redir[++i] && node->redir[i] != _NR) + { + if (node->redir[i] == _RED_L) + handle_file(node, 1, i); + else if (node->redir[i] == _RED_R) + handle_file(node, 2, i); + else if (node->redir[i] == _RED_DR) + handle_file(node, 3, i); + else if (node->redir[i] == _RED_DL) + here_doc(node, i); + if (node->redir[i] == _RED_L) + { + dup2(node->_stdin, STDIN_FILENO); + close(node->_stdin); + } + else if (node->redir[i] == _RED_R || node->redir[i] == _RED_DR) + { + dup2(node->_stdout, STDOUT_FILENO); + close(node->_stdout); + } + } +} + +void reset_redir(t_ast_n *node) +{ + if (node->state == _PLINE || node->redir[0] != _NR) + { + dup2(node->save_stdo, STDOUT_FILENO); + close(node->save_stdo); + dup2(node->save_stdi, STDIN_FILENO); + close(node->save_stdi); + } +} + +int err_fork_pline(int *pipes) +{ + close(pipes[0]); + close(pipes[1]); + perror("fork"); + return (1); +} diff --git a/srcs/execution/exec_subsh.c b/srcs/execution/exec_subsh.c new file mode 100644 index 0000000..38169fb --- /dev/null +++ b/srcs/execution/exec_subsh.c @@ -0,0 +1,95 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_subsh.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lderidde +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 09:52:04 by lderidde #+# #+# */ +/* Updated: 2025/02/12 09:52:04 by lderidde ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/exec/exec.h" + +int exec_shcmd(t_ast_n *node) +{ + pid_t pid; + int status; + + if (is_builtin(node->cmd)) + return (exec_builtin(node)); + else + { + pid = fork(); + if (pid == 0) + exec(node); + else if (pid > 0) + { + waitpid(pid, &status, 0); + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); + else + return (1); + } + else + perror("fork"); + return (1); + } +} + +int execute_shcommand(t_ast_n *node) +{ + if (node->state == _CMD) + handle_redir(node); + if (node->state == _CMD) + node->msh->ex_code = exec_shcmd(node); + else if (node->state == _AND) + { + node->msh->ex_code = execute_shcommand(node->left); + if (node->msh->ex_code == 0) + node->msh->ex_code = execute_shcommand(node->right); + } + else if (node->state == _OR) + { + node->msh->ex_code = execute_shcommand(node->left); + if (node->msh->ex_code != 0) + node->msh->ex_code = execute_shcommand(node->right); + } + else if (node->state == _PLINE) + node->msh->ex_code = exec_pline(node->pline); + else if (node->state == _SUBSH) + node->msh->ex_code = exec_subsh(node->left); + if (node->state == _CMD) + reset_redir(node); + return (node->msh->ex_code); +} + +int exec_subsh(t_ast_n *node) +{ + int status; + pid_t pid; + int ret; + + pid = fork(); + if (pid == 0) + { + handle_redir(node->parent); + ret = execute_shcommand(node); + free_child(node->msh); + exit(ret); + } + else if (pid > 0) + { + waitpid(pid, &status, 0); + if (WIFEXITED(status) && node->parent->state != _PLINE) + return (WEXITSTATUS(status)); + else + return (1); + } + else + { + perror("fork"); + return (1); + } +} diff --git a/srcs/execution/exec_utils.c b/srcs/execution/exec_utils.c new file mode 100644 index 0000000..67ad748 --- /dev/null +++ b/srcs/execution/exec_utils.c @@ -0,0 +1,78 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lderidde +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 09:57:39 by lderidde #+# #+# */ +/* Updated: 2025/02/12 09:57:39 by lderidde ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/exec/exec.h" + +int execis_validchar(char c) +{ + if (ft_isalnum(c) || c == '_') + return (1); + return (0); +} + +int execget_var_len(char *str, t_ast_n *node, int *j) +{ + int len; + int ret; + char *var; + + len = *j + 1; + while (str[len] && execis_validchar(str[len])) + len++; + var = ft_substr(str, *j + 1, (size_t)len - (*j + 1)); + *j = len; + ret = ft_strlen(get_var_value(var, node->msh->env)); + ft_free(&var); + return (ret - (len - (*j + 1))); +} + +int get_dup_len(char *str, t_ast_n *node) +{ + int i; + int len; + + i = 0; + len = ft_strlen(str); + while (str[i]) + { + if (str[i] == '$') + { + len += execget_var_len(str, node, &i); + i--; + } + i++; + } + return (len); +} + +int execvalid_next(char c) +{ + if (c != '\0' && execis_validchar(c)) + return (1); + return (0); +} + +char *execextract_env(char *str, char **envp) +{ + int i; + char *var; + char *tmp; + + i = 1; + while (str[i] && execis_validchar(str[i])) + i++; + if (i > 1) + tmp = ft_substr(str, 1, i - 1); + var = get_var_value(tmp, envp); + ft_free(&tmp); + return (var); +} diff --git a/srcs/expander/expand_tilde.c b/srcs/expander/expand_tilde.c index 3a987ad..bb92140 100644 --- a/srcs/expander/expand_tilde.c +++ b/srcs/expander/expand_tilde.c @@ -12,7 +12,7 @@ #include "../../includes/minishell.h" -static int get_new_len(t_ast_n *node, int j) +static int get_nw_len(t_ast_n *node, int j) { int i; int len; @@ -56,7 +56,7 @@ void expander_tilde(t_ast_n *node, int j) char *new; i = -1; - len = get_new_len(node, j); + len = get_nw_len(node, j); new = ft_calloc(len + 1, sizeof(char)); if (!new) return ; diff --git a/srcs/expander/expand_var.c b/srcs/expander/expand_var.c index f5e23fb..35506cd 100644 --- a/srcs/expander/expand_var.c +++ b/srcs/expander/expand_var.c @@ -6,7 +6,7 @@ /* By: lderidde +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/07 12:58:25 by lderidde #+# #+# */ -/* Updated: 2025/02/11 15:31:05 by lderidde ### ########.fr */ +/* Updated: 2025/02/12 09:06:11 by lderidde ### ########.fr */ /* */ /* ************************************************************************** */ @@ -44,7 +44,7 @@ static char *extract_env(char *str, char **envp) return (var); } -static int get_new_len(t_ast_n *node, int j) +int get_new_len(t_ast_n *node, int j) { int i; int len; @@ -53,7 +53,14 @@ static int get_new_len(t_ast_n *node, int j) len = ft_strlen(node->args[j]); while (node->args[j][i]) { - if (node->args[j][i] == '$') + if (node->args[j][i] == '$' && (node->args[j][i + 1] + && node->args[j][i + 1] == '?') + && !in_squote(node->args[j], &node->args[j][i])) + { + len -= 1; + } + else if (node->args[j][i] == '$' && + !in_squote(node->args[j], &node->args[j][i])) { len += get_var_len(node, j, &i); i--; @@ -63,7 +70,7 @@ static int get_new_len(t_ast_n *node, int j) return (len); } -void expander_var(t_ast_n *node, int j) +void expander_var(t_ast_n *nd, int j) { int i; int k; @@ -71,25 +78,25 @@ void expander_var(t_ast_n *node, int j) char *new; i = -1; - len = get_new_len(node, j); - new = ft_calloc(len + 1, sizeof(char)); + new = create_new(nd, j, &len); if (!new) return ; k = 0; - while (node->args[j][k] && ++i < len) + while (nd->args[j][k] && ++i < len) { - if (node->args[j][k] != '$') - new[i] = node->args[j][k++]; - else if (node->args[j][k] == '$' && exvalid_next(node->args[j][k + 1])) + if (nd->args[j][k] != '$' || in_squote(nd->args[j], &nd->args[j][k])) + new[i] = nd->args[j][k++]; + else if (expand_exit(nd, j, k)) + cat_exit(nd, &new, i, &k); + else if (valid_expand(nd, j, k)) { - ft_strlcat(new, extract_env(&node->args[j][k], node->msh->env), -1); + ft_strlcat(new, extract_env(&nd->args[j][k], nd->msh->env), -1); i = ft_strlen(new) - 1; - while (node->args[j][++k] && is_exvalidchar(node->args[j][k])) + while (nd->args[j][++k] && is_exvalidchar(nd->args[j][k])) continue ; } } - ft_free(&node->args[j]); - node->args[j] = new; + handle_copy(nd, j, &new); } int expand_var(t_ast_n *node, int j) diff --git a/srcs/expander/expander_var_utils.c b/srcs/expander/expander_var_utils.c new file mode 100644 index 0000000..30efd6e --- /dev/null +++ b/srcs/expander/expander_var_utils.c @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expander_var_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lderidde +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 09:17:28 by lderidde #+# #+# */ +/* Updated: 2025/02/12 09:17:28 by lderidde ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../../includes/exec/expander.h" + +int expand_exit(t_ast_n *node, int j, int k) +{ + if (node->args[j][k] == '$' && (node->args[j][k + 1] + && node->args[j][k + 1] == '?') + && !in_squote(node->args[j], &node->args[j][k])) + { + return (1); + } + return (0); +} + +int valid_expand(t_ast_n *node, int j, int k) +{ + if (node->args[j][k] == '$' && exvalid_next(node->args[j][k + 1]) + && !in_squote(node->args[j], &node->args[j][k])) + { + return (1); + } + return (0); +} + +char *create_new(t_ast_n *node, int j, int *len) +{ + char *new; + + *len = get_new_len(node, j); + new = ft_calloc(*len + 1, sizeof(char)); + return (new); +} + +void handle_copy(t_ast_n *node, int j, char **new) +{ + ft_free(&node->args[j]); + node->args[j] = *new; +} + +void cat_exit(t_ast_n *node, char **new, int i, int *k) +{ + (*new)[i] = node->msh->ex_code + '0'; + *k += 2; +}