diff --git a/include/executor.h b/include/executor.h new file mode 100644 index 0000000..b65aafa --- /dev/null +++ b/include/executor.h @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* executor.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: sede-san exit_status = 127, msh->exit_status); + } + if (access(cmd.path, X_OK) != EXIT_SUCCESS) + { + // permission denied + ft_eputstr("minishell: "); + perror(cmd.path); + return (msh->exit_status = 126, msh->exit_status); + } + child_pid = fork(); + if (child_pid == -1) + perror("minishell"); + else if (child_pid == 0) + handle_child(&cmd, msh); + else + handle_parent(child_pid, &cmd, msh); + return (msh->exit_status); +} + +static char *solve_path( + char *cmd_name, + t_minishell *msh +){ + char *cmd_path; + char **path; + size_t i; + + if (path_is_solved(cmd_name)) + // return a copy to avoid double free on parent + return (ft_strdup(cmd_name)); + //TODO substitute getenv call for own getenv + path = ft_split(getenv("PATH"), COLON); + if (!path) + return (NULL); + (void)msh; + cmd_path = NULL; + i = -1; + while (!cmd_path && path[++i]) + { + cmd_path = ft_strnjoin(3, path[i], "/", cmd_name); + if (!cmd_path) + return (NULL); + /** + * If a command exists but user has no execution permission + * the command is shown as non existant instead of showing the + * last ocurrence found + * + * TLDR: bash shows 'Permission denied' + * and minishell 'command not found' + * + * TEST: execute an existing command without permission to do so + */ + if (access(cmd_path, X_OK) != EXIT_SUCCESS) + ft_free((void **)&cmd_path); + } + ft_free_split((char **)path); + if (!cmd_path) + return (NULL); + return (cmd_path); +} + +static u_int8_t path_is_solved( + char *cmd_name +){ + return (ft_strncmp(cmd_name, "/", 1) == 0 + || (cmd_name[1] && ft_strncmp(cmd_name, "./", 2) == 0) + || (cmd_name[2] && ft_strncmp(cmd_name, "../", 3) == 0) + ); +} + +static void handle_child( + t_command *cmd, + t_minishell *msh +){ + execve(cmd->path, cmd->argv, msh->variables.environment); +} + +static void handle_parent( + pid_t child_pid, + t_command *cmd, + t_minishell *msh +){ + if (waitpid(child_pid, (int *)&msh->exit_status, 0) == EXIT_SUCCESS) + { + // handle success + } + else + { + // handle error + } + ft_free((void **)&cmd->path); + ft_free_split(cmd->argv); +}