/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* ms_exec.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: tmaze +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/09/26 16:25:00 by tmaze #+# #+# */ /* Updated: 2020/01/25 16:46:29 by tmaze ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" int ft_isin(char *str, char c) { int i; i = 0; while (str && str[i]) if (str[i++] == c) return (i - 1); return (-1); } void *put_error(char *file, char *msg) { ft_putstr("minishell: "); ft_putstr(file); ft_putstr(": "); ft_putendl(msg); return (NULL); } char *check_path_slash(char *exec) { int i; struct stat info; if ((i = access(exec, F_OK)) != 0) put_error(exec, "no such file or directory"); if (i != 0) return (NULL); if ((i = stat(exec, &info)) != 0) put_error(exec, "can't determine info"); if (i != 0) return (NULL); if (!S_ISREG(info.st_mode)) { put_error(exec, "not an executable file"); return (NULL); } if ((i = access(exec, X_OK)) != 0) put_error(exec, "permission denied"); if (i != 0) return (NULL); return (exec); } char *check_path_dot(char *exec, t_env *env) { t_env *path; char *tmp; char *ret; if ((path = ft_envgetelem("PWD", env)) == NULL || path->val == NULL || (tmp = ft_strjoin(path->val, "/")) == NULL) return (put_error(exec, "memory error")); if ((ret = ft_strjoin(tmp, exec)) == NULL) put_error(exec, "memory error"); ft_strdel(&tmp); if (ret == NULL) return (NULL); if (access(ret, F_OK) == 0) { if (access(ret, X_OK) == 0) return (exec); ft_strdel(&ret); return (put_error(exec, "permission denied")); } ft_strdel(&ret); return (put_error(exec, "no such file or directory")); } void *ft_strdel_null(char **s) { ft_strdel(s); return (NULL); } char *check_path_elems(char **path_elems, char *exec) { int i; char *tmp; char *ret; i = -1; while (path_elems[++i]) { if ((tmp = ft_strjoin(path_elems[i], "/")) == NULL && !put_error(exec, "memory error")) break ; if ((ret = ft_strjoin(tmp, exec)) == NULL && !put_error(exec, "memory error") && !ft_strdel_null(&tmp)) break ; if (!ft_strdel_null(&tmp) && access(ret, F_OK) == 0) { if (access(ret, X_OK) == 0) break ; ft_strdel(&ret); ft_del_words_tables(&path_elems); return (put_error(exec, "permission denied")); } ft_strdel(&ret); } return (ret); } char *check_path(char *exec, t_env *env) { size_t i; t_env *path; char **path_elems; char *ret; ret = NULL; if (exec) { if (ft_isin(exec, '/') != -1 && ft_isin(exec, '.') == -1) return (check_path_slash(exec)); if (exec[0] == '.') return (check_path_dot(exec, env)); if ((path = ft_envgetelem("PATH", env)) == NULL || path->val == NULL || (path_elems = ft_strsplit(path->val, ':')) == NULL) return (put_error(exec, "could not resolve path")); i = 0; if ((ret = check_path_elems(path_elems, exec)) == NULL) return (NULL); if (path_elems[i] == NULL) put_error(exec, "command not found"); ft_del_words_tables(&path_elems); } return (ret); } void exec_cmd_child(char *path, char **argv, char **env_tab, t_env **env) { execve(path, argv, env_tab); ft_putendl_fd("minishell: error", 1); if (ft_strcmp(path, argv[0]) != 0) ft_strdel(&path); ft_del_words_tables(&env_tab); ft_envdel(env); exit(-1); } int exec_cmd(char **argv, t_env **env) { int ret; char **env_tab; char *path; if ((env_tab = ft_envtotab(*env)) == NULL) return (-1); if ((path = check_path(argv[0], *env)) == NULL) ft_del_words_tables(&env_tab); if (path == NULL) return (-1); if ((ret = fork()) == 0) exec_cmd_child(path, argv, env_tab, env); else if (ret == -1) ft_putendl_fd("minishell: error", 1); if (ret == -1) return (-1); waitpid(ret, NULL, 0); ft_del_words_tables(&env_tab); if (ft_strcmp(path, argv[0]) != 0) ft_strdel(&path); return (0); }