diff --git a/src/builtins.c b/src/builtins.c index 8a10a96..fd7ffda 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -88,11 +88,33 @@ void cd_print_error(void) } } +static +int builtins_cd_chdir(char *path, history_t *history, char **args, env_t *env) +{ + bool last_chdir_set = false; + + if (history->last_chdir != NULL && u_strcmp(args[1], "-") == 0) { + path = history->last_chdir; + free(history->last_chdir); + history->last_chdir = u_strdup(get_env_value(env, "PWD")); + last_chdir_set = true; + } + if (chdir(path) < 0) { + write(STDERR_FILENO, path, u_strlen(path)); + cd_print_error(); + return RETURN_FAILURE; + } + if (!last_chdir_set) { + free(history->last_chdir); + history->last_chdir = u_strdup(path); + } + return RETURN_SUCCESS; +} + int builtins_cd(env_t *env, char **args, char *buff __attribute__((unused)), history_t *history __attribute__((unused))) { char *path = args[1]; - int result = RETURN_SUCCESS; if (path == NULL || u_strcmp(args[1], "~") == 0) path = get_env_value(env, "HOME"); @@ -102,10 +124,5 @@ int builtins_cd(env_t *env, char **args, char *buff __attribute__((unused)), WRITE_CONST(STDERR_FILENO, "cd: Too many arguments.\n"); return RETURN_FAILURE; } - if (chdir(path) < 0) { - write(STDERR_FILENO, path, u_strlen(path)); - cd_print_error(); - result = RETURN_FAILURE; - } - return result; + return builtins_cd_chdir(path, history, args, env); } diff --git a/src/shell.c b/src/shell.c index d110dbb..0a026b7 100644 --- a/src/shell.c +++ b/src/shell.c @@ -56,7 +56,7 @@ int shell_loop(env_t *env, int is_a_tty, history_t *history) int shell(char **env_ptr) { env_t env = parse_env(env_ptr); - history_t history = { .cmd_history = NULL, 0 }; + history_t history = { .cmd_history = NULL, 0, .last_chdir = NULL }; int shell_result; if (!env.env) diff --git a/src/shell.h b/src/shell.h index e7d4977..237ad1c 100644 --- a/src/shell.h +++ b/src/shell.h @@ -13,6 +13,7 @@ typedef struct { char **cmd_history; int last_exit_code; + char *last_chdir; } history_t; int shell(char **env); #endif /* SHELL_H */ diff --git a/ulib/str/strdup.c b/ulib/str/strdup.c index cebd182..4eef30b 100644 --- a/ulib/str/strdup.c +++ b/ulib/str/strdup.c @@ -15,6 +15,8 @@ char *u_strdup(char const *src) char *dest; int len = u_strlen(src); + if (!len) + return NULL; dest = malloc(sizeof(char) * (len + 1)); if (dest == NULL) return NULL;