/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* exec.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: tmaze +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2018/11/27 15:32:29 by tmaze #+# #+# */ /* Updated: 2019/01/17 17:43:00 by tmaze ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" #define S_BIN 5 char **envlsttotab(t_list *env) { size_t i; size_t env_size; t_list *tmp; char **ret; i = 0; tmp = env; env_size = ft_lstsize(env); if ((ret = (char**)ft_memalloc(sizeof(char*) * (env_size + 1))) == NULL) return (NULL); while (i <= env_size) ret[i++] = NULL; i = 0; while (tmp) { if ((ret[i] = ft_strnew(ft_strlen(((t_envelem*)(tmp->content))->key) + ft_strlen(((t_envelem*)(tmp->content))->val) + 1)) == NULL) { ft_del_words_tables(&ret); return (NULL); } i++; tmp = tmp->next; } return (ret); } /* ** , {"setenv", &cmd_senv}, {"unsetenv", &cmd_senv}, {"env", &cmd_env}}; */ int ft_isin(char *str, char c) { int i; i = 0; while (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); } char *check_path_slash(char *exec) { int i; struct stat info; if (ft_isin(exec, '/') != -1 && ft_isin(exec, '.') == -1) { 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); } return (NULL); } char *check_path_dot(char *exec, t_list *env) { t_envelem *path; char *tmp; char *ret; if (exec[0] == '.') { if ((path = env_getelemfromkey("PWD", env)) == NULL || path->val == NULL) { put_error(exec, "memory error"); return (NULL); } if ((tmp = ft_strjoin(path->val, "/")) == NULL) put_error(exec, "memory error"); if (tmp == NULL) return (NULL); if ((ret = ft_strjoin(tmp, exec)) == NULL) { put_error(exec, "memory error"); ft_strdel(&tmp); return (NULL); } ft_strdel(&tmp); if (access(ret, F_OK) == 0) { if (access(ret, X_OK) == 0) return (ret); put_error(exec, "permission denied"); ft_strdel(&ret); return (NULL); } put_error(exec, "no such file or directory"); ft_strdel(&ret); } return (NULL); } char *check_path(char *exec, t_list *env) { size_t i; t_envelem *path; char **path_elems; char *tmp; char *ret; i = 0; ret = NULL; if ((ret = check_path_slash(exec)) != NULL) return (ret); if ((ret = check_path_dot(exec, env)) != NULL) return (ret); if ((path = env_getelemfromkey("PATH", env)) == NULL || path->val == NULL) return (NULL); if ((path_elems = ft_strsplit(path->val, ':')) == NULL) return (NULL); while (path_elems[i]) { if ((tmp = ft_strjoin(path_elems[i], "/")) == NULL) put_error(exec, "memory error"); if (tmp == NULL) break ; if ((ret = ft_strjoin(tmp, exec)) == NULL) { put_error(exec, "memory error"); ft_strdel(&tmp); break ; } ft_strdel(&tmp); if (access(ret, F_OK) == 0) { if (access(ret, X_OK) == 0) break ; put_error(exec, "permission denied"); } ft_strdel(&ret); i++; } ft_del_words_tables(&path_elems); return (ret); } int exec_cmd(char **argv, t_list **env) { int ret; char **env_tab; char *path; size_t i; static t_builtin builtins[S_BIN] = {{"echo", &cmd_echo}, {"cd", &cmd_cd}, {"setenv", &cmd_setenv}, {"env", &cmd_env}, {"unsetenv", &cmd_unsetenv}}; i = 0; while (i < S_BIN) if (ft_strcmp(argv[0], builtins[i++].cmd) == 0) return ((*(builtins[i - 1].f))(argv, env)); if ((env_tab = envlsttotab(*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) { execve(path, argv, env_tab); ft_putendl_fd("minishell: error", 2); if (ft_strcmp(path, argv[0]) != 0) ft_strdel(&path); ft_del_words_tables(&env_tab); exit(-1); } else if (ret == -1) ft_putendl_fd("minishell: error", 2); 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); }