/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* executor.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: sede-san exit_status = 127, msh->exit_status); } if (!is_builtin(cmd.path, msh) && access(cmd.path, X_OK) != EXIT_SUCCESS) { ft_eputstr("minishell: "); perror(cmd.path); return (msh->exit_status = 126, msh->exit_status); } child_pid = 0; if (!is_builtin(cmd.path, msh)) 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, msh)) // return a copy to avoid double free on parent return (ft_strdup(cmd_name)); path = ft_split(get_env("PATH", msh), COLON); if (!path) return (NULL); 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, t_minishell *msh ){ 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) || is_builtin(cmd_name, msh) ); } static void handle_child( t_command *cmd, t_minishell *msh ){ char **envp; t_builtin_func builtin; if (is_builtin(cmd->argv[0], msh)) { builtin = ft_hashmap_get(msh->builtins, cmd->argv[0]); builtin(*cmd, msh); } else { envp = get_envp(msh); execve(cmd->path, cmd->argv, envp); free_envp(envp); } } 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); }