diff --git a/42sh/.tags b/42sh/.tags new file mode 100644 index 00000000..00b0c496 --- /dev/null +++ b/42sh/.tags @@ -0,0 +1,13 @@ +Mmain src/main.c /^int main(void)$/ +builtin_cd src/builtin.c /^int builtin_cd(char **av, char **env)$/ +builtin_echo src/builtin.c /^int builtin_echo(char **av, char **env)$/ +builtin_env src/lib_builtin_env.c /^int builtin_env(char **av, char **env)$/ +builtin_exit src/builtin.c /^int builtin_exit(char **av, char **env)$/ +builtin_setenv src/lib_builtin_env.c /^int builtin_setenv(char **av, char **env)$/ +builtin_unsetenv src/lib_builtin_env.c /^int builtin_unsetenv(char **av, char **env)$/ +ft_builtin_exec src/builtin.c /^int ft_builtin_exec(char **av, char **env)$/ +ft_cmd_exec src/ft_cmd.c /^int ft_cmd_exec(char *cmd)$/ +ft_cmd_getav src/ft_cmd.c /^char **ft_cmd_getav(char *cmd)$/ +ft_env_getval src/lib_env.c /^char *ft_env_getval(char **env, char *key)$/ +ft_format_vars src/lib_format.c /^void ft_format_vars(char **av, char **env)$/ +ft_path_findexec src/lib_path.c /^char *ft_path_findexec(char **path, char *execname/ diff --git a/42sh/Makefile b/42sh/Makefile new file mode 100644 index 00000000..5b589139 --- /dev/null +++ b/42sh/Makefile @@ -0,0 +1,47 @@ +NAME = minishell +CC = gcc +TAGFILE = .tags + +D_SRC = src +F_SRC := $(shell ls -1 $(D_SRC) | grep "\.c$$") +DF_SRC := $(addprefix $(D_SRC)/, $(F_SRC)) + +D_OBJ = obj +F_OBJ = $(F_SRC:.c=.o) +DF_OBJ := $(addprefix $(D_OBJ)/, $(F_OBJ)) + +D_INC = includes libft/includes +O_INC = $(addprefix -I, $(D_INC)) + +W_FLAGS = -Wall -Wextra -Werror +D_FLAGS = + +MKDIR = mkdir -p +RM = /bin/rm -rf + +.PHONY: all clean fclean re tags test libft + +all: libft $(NAME) $(TAGFILE) + +$(TAGFILE): $(D_SRC)/*.c + @ctags -f $(TAGFILE) $(addprefix $(D_SRC)/, $(F_SRC)) + @echo "Making tags..." + +$(D_OBJ)/%.o: $(D_SRC)/%.c $(D_INC) + @$(MKDIR) $(D_OBJ) + @$(CC) $(O_INC) $(W_FLAGS) -c $< -o $@ $(D_FLAGS) + @echo "Compiling "$<"..." + +libft: + @$(MAKE) -C libft/ 2>/dev/null + +$(NAME): $(DF_OBJ) libft/libft.a + $(CC) $(O_INC) -Llibft -lft $(W_FLAGS) $(DF_OBJ) -o $@ $(D_FLAGS) + +clean: + $(RM) $(D_OBJ) + +fclean: clean + $(RM) $(NAME) + +re: fclean all diff --git a/42sh/includes/minishell.h b/42sh/includes/minishell.h new file mode 100644 index 00000000..4ac2a327 --- /dev/null +++ b/42sh/includes/minishell.h @@ -0,0 +1,33 @@ +#ifndef MINISHELL_H +# define MINISHELL_H + +# include "libft.h" +# include +# include +# include +# define SHELL_PROMPT "$> " + +typedef struct s_builtin +{ + char *name; + int (*f)(); +} t_builtin; + +extern t_builtin g_builtin[]; + +int ft_cmd_exec(char *cmd); +char **ft_cmd_getav(char *cmd); + +int ft_builtin_exec(char **av, char **env); +int builtin_echo(char **av, char **env); +int builtin_cd(char **av, char **env); +int builtin_exit(char **av, char **env); +int builtin_setenv(char **av, char **env); +int builtin_unsetenv(char **av, char **env); +int builtin_env(char **av, char **env); + +void ft_format_vars(char **av, char **env); +char *ft_env_getval(char **env, char *key); +char *ft_path_findexec(char **path, char *execname); + +#endif diff --git a/42sh/libft b/42sh/libft index aef08a51..cac01336 160000 --- a/42sh/libft +++ b/42sh/libft @@ -1 +1 @@ -Subproject commit aef08a51be352de39c7698d6a40f4512c9d11769 +Subproject commit cac01336ab4f970ee4da9beb033fd2063dfc9367 diff --git a/42sh/minishell.fr.pdf b/42sh/minishell.fr.pdf new file mode 100644 index 00000000..f685854b Binary files /dev/null and b/42sh/minishell.fr.pdf differ diff --git a/42sh/src/builtin.c b/42sh/src/builtin.c new file mode 100644 index 00000000..6b10da42 --- /dev/null +++ b/42sh/src/builtin.c @@ -0,0 +1,57 @@ +#include "minishell.h" + +t_builtin g_builtin[] = { + {"echo", &builtin_echo}, + {"cd", &builtin_cd}, + {"setenv", &builtin_setenv}, + {"unsetenv", &builtin_unsetenv}, + {"env", &builtin_env}, + {"exit", &builtin_exit}, + {NULL, NULL}, +}; + +int ft_builtin_exec(char **av, char **env) +{ + int i; + + i = 0; + while (g_builtin[i].name) + { + if (ft_strcmp(g_builtin[i].name, *av) == 0) + { + (g_builtin[i].f)(av, env); + return (0); + } + i++; + } + return (1); +} + +int builtin_echo(char **av, char **env) +{ + (void)env; + av++; + while (*av) + { + ft_printf("%s", *av); + av++; + if (*av) + ft_putstr(" "); + } + ft_putendl(""); + return (0); +} + +int builtin_cd(char **av, char **env) +{ + (void)env; + ft_printf("builtin: %s\n", av[0]); + return (0); +} + +int builtin_exit(char **av, char **env) +{ + (void)env; + ft_printf("builtin: %s\n", av[0]); + return (0); +} diff --git a/42sh/src/ft_cmd.c b/42sh/src/ft_cmd.c new file mode 100644 index 00000000..dd3f529b --- /dev/null +++ b/42sh/src/ft_cmd.c @@ -0,0 +1,37 @@ +#include "minishell.h" +extern char **environ; + +int ft_cmd_exec(char *cmd) +{ + pid_t pid; + int status; + char **path; + char *execpath; + char **argv; + + path = ft_strsplit(ft_env_getval(environ, "PATH"), ':'); + argv = ft_cmd_getav(cmd); + ft_format_vars(argv, environ); + if (ft_builtin_exec(argv, environ) == 0) + return (0); + else if (ft_strchr(argv[0], '/')) + execpath = cmd; + else if (!(execpath = ft_path_findexec(path, argv[0]))) + return (-1); + /* ft_printf("%s @ %s\n", argv[0], execpath); */ + if ((pid = fork()) == -1) + return (-1); + if (pid == 0) + execve(execpath, argv, environ); + else + { + wait(&status); + ft_printf("child process exited with %i\n", status); + } + return (0); +} + +char **ft_cmd_getav(char *cmd) +{ + return (ft_split_whitespaces(cmd)); +} diff --git a/42sh/src/lib_builtin_env.c b/42sh/src/lib_builtin_env.c new file mode 100644 index 00000000..5582431f --- /dev/null +++ b/42sh/src/lib_builtin_env.c @@ -0,0 +1,22 @@ +#include "minishell.h" + +int builtin_setenv(char **av, char **env) +{ + (void)env; + ft_printf("builtin: %s\n", av[0]); + return (0); +} + +int builtin_unsetenv(char **av, char **env) +{ + (void)env; + ft_printf("builtin: %s\n", av[0]); + return (0); +} + +int builtin_env(char **av, char **env) +{ + (void)env; + ft_printf("builtin: %s\n", av[0]); + return (0); +} diff --git a/42sh/src/lib_env.c b/42sh/src/lib_env.c new file mode 100644 index 00000000..eef9656f --- /dev/null +++ b/42sh/src/lib_env.c @@ -0,0 +1,13 @@ +#include "minishell.h" + +char *ft_env_getval(char **env, char *key) +{ + while (*env) + { + /* ft_printf("%s\n", env[i]); */ + if (ft_strcmp(*env, key) == '=') + return (*env + ft_strlen(key) + 1); + env++; + } + return (NULL); +} diff --git a/42sh/src/lib_format.c b/42sh/src/lib_format.c new file mode 100644 index 00000000..de6335d3 --- /dev/null +++ b/42sh/src/lib_format.c @@ -0,0 +1,11 @@ +#include "minishell.h" + +void ft_format_vars(char **av, char **env) +{ + while (*av) + { + if (**av == '$') + *av = ft_env_getval(env, *av + 1); + av++; + } +} diff --git a/42sh/src/lib_path.c b/42sh/src/lib_path.c new file mode 100644 index 00000000..455fa302 --- /dev/null +++ b/42sh/src/lib_path.c @@ -0,0 +1,38 @@ +#include "minishell.h" + +char *ft_path_findexec(char **path, char *execname) +{ + int i; + DIR *dir; + char *execpath; + struct dirent *dirent; + struct stat statbuf; + + i = 0; + while (path[i]) + { + if ((dir = opendir(path[i]))) + { + while ((dirent = readdir(dir))) + { + if (ft_strcmp(dirent->d_name, execname) == 0) + { + if (path[i][ft_strlen(path[i])] != '/') + ft_strcat(path[i], "/"); + execpath = ft_strjoin(path[i], dirent->d_name); + if (stat(execpath, &statbuf) == -1) + return (NULL); + if (access(execpath, statbuf.st_mode) == -1) + { + ft_printf("minishell: permission denied: %s\n", execname); + return (NULL); + } + return (execpath); + } + } + } + i++; + } + ft_printf("minishell: command not found: %s\n", execname); + return (NULL); +} diff --git a/42sh/src/main.c b/42sh/src/main.c new file mode 100644 index 00000000..fc29fb75 --- /dev/null +++ b/42sh/src/main.c @@ -0,0 +1,20 @@ +#include "minishell.h" + +int main(void) +{ + char *line; + + while (1) + { + ft_printf(SHELL_PROMPT); + /* if (get_next_line(0, &line) == 1) */ + /* continue ; */ + /* if (get_next_line(0, &line) == 0) */ + /* ft_cmd_exec(line); */ + if (get_next_line(0, &line) == -1) + return (1); + ft_cmd_exec(line); + } + return (0); +} +