/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* cmd_cd.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: tmaze +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/01/07 16:44:40 by tmaze #+# #+# */ /* Updated: 2019/01/30 17:02:05 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 (exec[0] == '/') { 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); } int cmd_cd_update_env(char *path, t_list **env, char opt) { t_envelem *pwd; char *oldpwd; char *c_path; char p_path[4096]; ft_bzero(p_path, 4096); if (getcwd(p_path, 4096) == NULL) { put_error_cd(path, "error"); return (1); } if ((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 (ft_realpath(path, &c_path) == NULL) { put_error_cd(path, "error"); return (1); } if (env_addupdate("PWD", ((opt == 'P') ? p_path : c_path), env) == NULL || env_addupdate("OLDPWD", oldpwd, env) == NULL) { put_error_cd(path, "error"); ft_strdel(&oldpwd); ft_strdel(&c_path); return (1); } ft_strdel(&oldpwd); ft_strdel(&c_path); return (0); } int cmd_cd_core(char *path, t_list **env, char opt) { t_envelem *pwd; 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); } return (cmd_cd_update_env(path, env, opt)); } char cd_getparams(char **argv, size_t *i) { char ret[2]; size_t j; ret[1] = '\0'; ret[0] = 'L'; *i = 0; while (argv[++(*i)] && argv[*i][0] == '-' && ft_strlen(argv[*i]) > 1) { j = 1; while (argv[*i][j] && (argv[*i][j] == 'L' || argv[*i][j] == 'P')) ret[0] = argv[*i][j++]; if (argv[*i][j] && argv[*i][j] != 'L' && argv[*i][j] != 'P') { ret[0] = argv[*i][j]; put_error_cd(ret, "invalid option"); put_error_cd("usage", "cd [-L|-P] [dir]"); ret[0] = '\0'; break ; } } return (ret[0]); } int cmd_cd(char **argv, t_list **env) { t_envelem *elem; size_t i; char *path; char opt; int ret; i = 0; if ((opt = cd_getparams(argv, &i)) == '\0') return (1); if (!argv[i] && (elem = env_getelemfromkey("HOME", *env)) != NULL && elem->val != NULL) return (cmd_cd_core(elem->val, env, opt)); else if (argv[i] && argv[i][0] == '/') return (cmd_cd_core(argv[i], env, opt)); else if (argv[i] && argv[i][0] == '-' && (elem = env_getelemfromkey("OLDPWD", *env)) != NULL) return (cmd_cd_core(elem->val, env, opt)); else if (argv[i] && argv[i][0] != '/' && (elem = env_getelemfromkey("PWD", *env)) != NULL && elem->val != NULL) { if ((path = ft_strnew(ft_strlen(elem->val) + ft_strlen(argv[i]) + 1)) == NULL) put_error_cd(argv[i], "memory error"); if (path == NULL) return (1); ft_strcpy(path, elem->val); path[ft_strlen(path)] = '/'; ft_strcat(path, argv[i]); ret = cmd_cd_core(path, env, opt); ft_strdel(&path); return (ret); } return (1); }