/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* cmd_cd.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: tmaze +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/01/07 16:44:40 by tmaze #+# #+# */ /* Updated: 2019/01/24 17:26:24 by tmaze ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" void put_error_cd(char *file, char *msg) { ft_putstr("cd: "); ft_putstr(file); ft_putstr(": "); ft_putendl(msg); } char *check_path_slash_cd(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_cd(exec, "no such file or directory"); if (i != 0) return (NULL); if ((i = stat(exec, &info)) != 0) put_error_cd(exec, "can't determine info"); if (i != 0) return (NULL); if (!S_ISDIR(info.st_mode)) { put_error_cd(exec, "not a directory"); return (NULL); } if ((i = access(exec, X_OK)) != 0) put_error_cd(exec, "permission denied"); if (i != 0) return (NULL); return (exec); } return (NULL); } char *ft_tabtopath(char **tab_path) { size_t total_size; size_t i; char *ret; i = 0; total_size = 0; while (tab_path[i]) total_size += ft_strlen(tab_path[i++]); if ((ret = ft_strnew(total_size + i)) == NULL) return (NULL); i = 0; while (tab_path[i]) { ft_strcat(ret, "/"); ft_strcat(ret, tab_path[i]); } return (ret); } char *ft_realpath(char *r_path, char **a_path) { char **tab_path; size_t i; size_t j; *a_path = NULL; if ((tab_path = ft_strsplit(r_path, '/')) == NULL) return (*a_path); while (tab_path[i]) { if (tab_path[i] == '.' || (ft_strcmp(tab_path[i], "..") == 0 && i == 1)) { j = i; ft_strdel(tab_path[i]); while (tab_path[++j]) tab_path[j - 1] = tab_path[j]; tab_path[j - 1] = NULL; } else if (ft_strcmp(tab_path[i], "..") == 0) { j = i; i = i - 1; ft_strdel(tab_path[i]); ft_strdel(tab_path[j]); while (tab_path[++j]) tab_path[j - 2] = tab_path[j]; tab_path[j - 2] = NULL; tab_path[j - 1] = NULL; } else i++; } *a_path = ft_tabtopath(tab_path); ft_del_tables_words(&tab_path); return (*a_path); } int cmd_cd_core(char *path, t_list **env) { t_envelem *pwd; char *oldpwd; if (check_path_slash_cd(path) == NULL) { put_error_cd(path, "invalid path"); return (1); } if (chdir(path) == -1 || (pwd = env_getelemfromkey("PWD", *env)) == NULL) { put_error_cd(path, "error"); return (1); } if ((oldpwd = ft_strdup(pwd->val)) == NULL) { put_error_cd(path, "error"); return (1); } if (env_addupdate("PWD", path, env) == NULL || env_addupdate("OLDPWD", oldpwd, env) == NULL) { put_error_cd(path, "error"); ft_strdel(&oldpwd); return (1); } ft_strdel(&oldpwd); return (0); } char cd_getparams(char **argv) { char ret; size_t i; size_t j; i = 0; ret = 'N'; while (argv[++i] && argv[i][0] == '-' && ft_strlen(argv[i]) > 1) { j = 0; while (argv[i][j] && (argv[i][j] == 'L' || argv[i][j] == 'P')) ret = argv[i][j++]; if (argv[i][j] && argv[i][j] != 'L' && argv[i][j] != 'P') { ret = argv[i][j]; put_error_cd(&ret, "invalid option"); put_error_cd("usage", "cd [-L|-P] [dir]"); ret = '\0'; break; } } return (ret); } int cmd_cd(char **argv, t_list **env) { t_envelem *elem; char *path; char *tmp; char opt; int ret; if ((opt = cd_getparams(argv)) == '\0') return (1); if (!argv[1] && (elem = env_getelemfromkey("HOME", *env)) != NULL && elem->val != NULL) return (cmd_cd_core(elem->val, env)); else if (argv[1] && argv[1][0] == '/') return (cmd_cd_core(argv[1], env)); else if (argv[1] && argv[1][0] == '-' && (elem = env_getelemfromkey("OLDPWD", *env)) != NULL) return (cmd_cd_core(elem->val, env)); else if (argv[1] && argv[1][0] == '.' && (elem = env_getelemfromkey("PWD", *env)) != NULL && elem->val != NULL) { if ((tmp = ft_strnew(ft_strlen(elem->val) + ft_strlen(argv[1]) + 1)) == NULL) put_error_cd(argv[1], "memory error"); if (tmp == NULL) return (1); ft_strcpy(tmp, elem->val); tmp[ft_strlen(tmp)] = '/'; ft_strcat(tmp, argv[1]); ft_putendl(tmp); if (ft_realpath(tmp, &path) == NULL) put_error_cd(argv[1], "memory error"); ret = cmd_cd_core(path, env); ft_strdel(&path); return (ret); } return (0); }