Implement the change directory (cd) builtin
authorLukas Jiriste <ljiriste@student.42prague.com>
Fri, 2 Aug 2024 16:43:10 +0000 (18:43 +0200)
committerLukas Jiriste <ljiriste@student.42prague.com>
Fri, 2 Aug 2024 16:43:10 +0000 (18:43 +0200)
It supports the $PWD variable and ~/nothign for home dir.

Makefile
inc/execution.h [new file with mode: 0644]
inc/minishell.h
src/builtins/cd.c [new file with mode: 0644]
src/execution.c
src/vars.c

index 0d8d3ef4d89f2f3600449a599d6cf26bb17bc272..b57362ad9de7c23834b0cfe6c02f2669e2dbe92e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -31,6 +31,8 @@ SOURCES :=    main.c                          \
                        parsing.c                       \
                        execution.c                     \
                        helpers.c                       \
+                                                               \
+                       builtins/cd.c           \
 
 SOURCES := $(addprefix $(SRCDIR)/, $(SOURCES))
 
diff --git a/inc/execution.h b/inc/execution.h
new file mode 100644 (file)
index 0000000..b413c7b
--- /dev/null
@@ -0,0 +1,22 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   execution.h                                        :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/08/02 17:40:19 by ljiriste          #+#    #+#             */
+/*   Updated: 2024/08/02 17:42:18 by ljiriste         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#ifndef EXECUTION_H
+# define EXECUTION_H
+
+const char     *get_env_var_value(const t_execution_env *env,
+                               const char *var_name);
+int                    set_env_var_value(t_execution_env *env, const char *var_name,
+                               const char *new_value);
+int            cd(int argc, char **argv, t_execution_env *env);
+
+#endif // EXECUTION_H
index 2320422b514048d7dc0131513dfb36f96020d59a..4dee16d2c0ad0c878f205801d0c172eb25331502 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/05/02 13:22:57 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/01 15:47:47 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/02 18:35:15 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -52,5 +52,6 @@ int           execute(t_tree *parse_tree, t_execution_env *env);
 int            init_tree(t_tree *tree);
 void   free_tree(t_tree *tree);
 void   free_token(void *token);
+void   free_str(void *str);
 
 #endif // MINISHELL_H
diff --git a/src/builtins/cd.c b/src/builtins/cd.c
new file mode 100644 (file)
index 0000000..3d6c35f
--- /dev/null
@@ -0,0 +1,48 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   cd.c                                               :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/08/02 16:37:48 by ljiriste          #+#    #+#             */
+/*   Updated: 2024/08/02 18:37:45 by ljiriste         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "minishell.h"
+#include "execution.h"
+#include <unistd.h>
+#include <stdlib.h>
+
+int    chdir_wrapper(const char *path, t_execution_env *env)
+{
+       char    *cwd;
+
+       if (!ft_strcmp(path, "~"))
+               path = get_env_var_value(env, "HOME");
+       if (!path || path[0] == '\0')
+               return (0);
+       if (chdir(path))
+               return (3);
+       cwd = getcwd(NULL, 0);
+       if (!cwd)
+               return (1);
+       if (set_env_var_value(env, "PWD", cwd))
+       {
+               chdir(get_env_var_value(env, "PWD"));
+               free(cwd);
+               return (2);
+       }
+       free(cwd);
+       return (0);
+}
+
+int    cd(int argc, char **argv, t_execution_env *env)
+{
+       if (argc == 1)
+               return (chdir_wrapper("~", env));
+       if (argc == 2)
+               return (chdir_wrapper(argv[1], env));
+       return (1);
+}
index c8bcd8352a4e4f2d89e8cdb6a79b1f832aa7ad74..819fcf1ba3de876cacc048e40c75da493b8c9e2a 100644 (file)
@@ -6,11 +6,12 @@
 /*   By: ljiriste <ljiriste@student.42prague.com>   +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/07/21 08:57:54 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/08/01 16:07:38 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/02 18:35:53 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #include "minishell.h"
+#include "execution.h"
 #include "libft.h"
 #include <stdlib.h>
 #include <unistd.h>
@@ -174,23 +175,39 @@ char      *get_var_name(const char *line)
        return (ft_strndup(line, i));
 }
 
-const char     *get_var_value(const t_vec *vars, const char *var_name)
+ssize_t                get_var_index(const t_vec *vars, const char *var_name)
 {
        size_t          len;
-       size_t          i;
+       ssize_t         i;
        const char      *const *line;
 
        len = ft_strlen(var_name);
        i = 0;
-       while (i < vars->size)
+       while ((size_t)i < vars->size)
        {
                line = ft_vec_caccess(vars, i);
                if (!*line)
                        break ;
                if (!ft_strncmp(*line, var_name, len) && (*line)[len] == '=')
-                       return (*line + len + 1);
+                       return (i);
                ++i;
        }
+       return (-1);
+}
+
+const char     *get_var_value(const t_vec *vars, const char *var_name)
+{
+       size_t          len;
+       ssize_t         i;
+       const char      *const *line;
+
+       len = ft_strlen(var_name);
+       i = get_var_index(vars, var_name);
+       if (i >= 0)
+       {
+               line = ft_vec_caccess(vars, i);
+               return (*line + len + 1);
+       }
        return (NULL);
 }
 
@@ -584,6 +601,39 @@ char       **expand(t_parse_tree_node *simple_command, const t_execution_env *env)
        return (fields);
 }
 
+int    set_var_value(t_vec *vars, const char *name, const char *value)
+{
+       ssize_t i;
+       char    *new_entry;
+
+       i = get_var_index(vars, name);
+       new_entry = malloc(ft_strlen(name) + 1 + ft_strlen(value) + 1);
+       if (!new_entry)
+               return (1);
+       ft_memcpy(new_entry, name, ft_strlen(name));
+       new_entry[ft_strlen(name)] = '=';
+       ft_memcpy(new_entry + ft_strlen(name) + 1, value, ft_strlen(value) + 1);
+       if (add_var_line(vars, new_entry))
+       {
+               free(new_entry);
+               return (1);
+       }
+       if (i >= 0)
+               ft_vec_erase(vars, i, free_str);
+       free(new_entry);
+       return (0);
+}
+
+int    set_env_var_value(t_execution_env *env, const char *name, const char *value)
+{
+       if (get_var_value(&env->vars->other, name))
+               return (set_var_value(&env->vars->other, name, value));
+       else if (get_var_value(&env->vars->exported, name))
+               return (set_var_value(&env->vars->exported, name, value));
+       else
+               return (set_var_value(&env->vars->other, name, value));
+}
+
 int    assignments_to_env(const t_vec *assignments, t_execution_env *env)
 {
        return (ft_vec_insert_range(&env->vars->other, assignments->vec, assignments->size, 0) == success);
@@ -705,12 +755,40 @@ int       add_exported(__attribute__((unused)) t_vec *assignments, __attribute__((unus
        return (0);
 }
 
+int    is_builtin(const char *str)
+{
+       if (!ft_strcmp(str, "cd"))
+               return (1);
+       return (0);
+}
+
+size_t count_fields(char **fields)
+{
+       size_t  i;
+
+       i = 0;
+       while (fields[i])
+               ++i;
+       return (i);
+}
+
+int    ex_builtin(char **fields, __attribute__((unused)) t_vec *assignments, __attribute__((unused)) const t_vec *redirections, t_execution_env *env)
+{
+       if (!ft_strcmp(fields[0], "cd"))
+               env->ret_val = cd(count_fields(fields), fields, env);
+       else
+               return (-1);
+       return (0);
+}
+
 int    ex_fields(char **fields, t_vec *assignments, const t_vec *redirections, t_execution_env *env)
 {
        pid_t   pid;
        int             status;
        char    *path;
 
+       if (is_builtin(fields[0]))
+               return (ex_builtin(fields, assignments, redirections, env));
        path = NULL;
        if (contains_path(fields[0]) && file_exists(fields[0]))
                path = ft_strdup(fields[0]);
index 8b11d6db8de9bfbc99513026af72828552692a34..3a11e63f5e3fd1fb148f920cb9aa1dca4a59dab3 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/05/02 13:21:32 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/05/02 13:24:39 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/08/02 18:34:58 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -71,7 +71,7 @@ int   init_vars(t_vars *vars, char **envp)
        return (0);
 }
 
-static void    free_str(void *str)
+void   free_str(void *str)
 {
        free(*(char **)str);
        return ;