diff --git a/.gitignore b/.gitignore index 293add1..9d1f841 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ a.out *.o obj/ .minishell_history +.ms_heredoc +pipetester.c +pipetest diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..21672c5 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug minishell", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/debug/minishell", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "Build minishell debug", + "miDebuggerPath": "/usr/bin/gdb", + "logging": { + "engineLogging": true + } + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 828d5ed..98bea1c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,14 @@ { "files.associations": { - "minishell.h": "c" + "minishell.h": "c", + "signal.h": "c", + "optional": "c", + "ostream": "c", + "system_error": "c", + "array": "c", + "functional": "c", + "tuple": "c", + "type_traits": "c", + "utility": "c" } -} \ No newline at end of file +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..eb91ccb --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,46 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build minishell", + "type": "shell", + "command": "make", + "args": [], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": ["$gcc"], + "detail": "Generated task for building minishell" + }, + { + "label": "Build minishell debug", + "type": "shell", + "command": "make debug", + "args": [], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": ["$gcc"], + "detail": "Generated task for building minishell in debug mode" + }, + { + "label": "Run minishell", + "type": "shell", + "command": "./minishell", + "args": [], + "group": { + "kind": "test", + "isDefault": true + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared" + }, + "problemMatcher": [] + } + ] +} diff --git a/Makefile b/Makefile index 9108b49..1546611 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ # **************************************************************************** # # # -# ::: :::::::: # -# Makefile :+: :+: :+: # -# +:+ +:+ +:+ # -# By: qmennen +#+ +:+ +#+ # -# +#+#+#+#+#+ +#+ # -# Created: 2024/10/15 11:48:46 by whaffman #+# #+# # -# Updated: 2025/02/11 15:06:22 by qmennen ### ########.fr # +# :::::::: # +# Makefile :+: :+: # +# +:+ # +# By: qmennen +#+ # +# +#+ # +# Created: 2024/10/15 11:48:46 by whaffman #+# #+# # +# Updated: 2025/02/25 18:15:50 by whaffman ######## odam.nl # # # # **************************************************************************** # @@ -15,62 +15,166 @@ NAME = minishell SRC_PATH = src INC_PATH = inc LIB_PATH = lib +BUILD_PATH = build LIBFT_PATH = $(LIB_PATH)/libft LIBFT_INC_PATH = $(LIBFT_PATH)/inc LIBFT = $(LIBFT_PATH)/libft.a -OBJ_PATH = obj - -VPATH = src:src/environment:src/prompt:src/lexer:src/token:src/utils:src/executor:src/parser -SOURCES = $(shell basename -a $(shell find $(SRC_PATH) -type f -name "*.c")) - -OBJECTS = $(addprefix $(OBJ_PATH)/, $(SOURCES:.c=.o)) -DEPENDS = ${OBJECTS:.o=.d} - CC = cc RM = rm -rf INCLUDES = -I./$(INC_PATH) -I./$(LIBFT_INC_PATH) -CFLAGS = -Wall -Wextra -Werror -fsanitize=address,undefined -MMD UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux) - LDLIBS := -L$(LIBFT_PATH) -lft -lreadline + LDLIBS := -L$(LIBFT_PATH) -lft -lreadline endif -all: $(NAME) - echo $(SOURCES) +# Include sources.mk if it exists +-include sources.mk -$(NAME): $(LIBFT) $(OBJECTS) - $(CC) $(CFLAGS) $(OBJECTS) $(LDLIBS) -o $(NAME) +# Build configurations +BUILD_CONFIGS = release debug asan tsan --include ${DEPENDS} +release_CFLAGS = -Wall -Werror -Werror -O2 +debug_CFLAGS = -Wall -Werror -Werror -g3 -DDEBUG +asan_CFLAGS = -Wall -Werror -Werror -fsanitize=address,leak,undefined -g3 +tsan_CFLAGS = -Wall -Werror -Werror -fsanitize=thread -g3 -$(LIBFT): $(LIBFT_PATH) +# Targets for each build configuration +define BUILD_TARGETS +$(1)_OBJ_PATH = $(BUILD_PATH)/$(1)/obj +$(1)_DEPENDS = $$(addprefix $$($(1)_OBJ_PATH)/, $$(SOURCES:.c=.d)) +$(1)_OBJECTS = $$(addprefix $$($(1)_OBJ_PATH)/, $$(SOURCES:.c=.o)) + +.PHONY: $(1) +$(1): CFLAGS = $$($(1)_CFLAGS) +$(1): $(BUILD_PATH)/$(1)/$(NAME) + +.PHONY: run_$(1) +run_$(1): $(1) + $$(info $$(bold)$$(green)Running $(1)$$(reset)) + ./$(BUILD_PATH)/$(1)/$(NAME) + +$(BUILD_PATH)/$(1)/$(NAME): $(LIBFT) $$($(1)_OBJECTS) + $$(info $$(bold)$$(green)Linking $(1) config$$(reset)) + $$(CC) $$(CFLAGS) $$($(1)_OBJECTS) $$(LDLIBS) -o $$@ + +-include $$($(1)_DEPENDS) + +$$($(1)_OBJ_PATH)/%.o: %.c $(LIBFT) | $$($(1)_OBJ_PATH) + $$(CC) $$(CFLAGS) $$(INCLUDES) -MMD -MP -c $$< -o $$@ + +$$($(1)_OBJ_PATH): + $$(info $$(bold)$$(green)Creating $(1) object directory$$(reset)) + mkdir -p $$@ +endef + +# Copy the release build configuration to the root +$(NAME): $(BUILD_PATH)/release/$(NAME) + $(info $(bold)$(green)Copying release build to root$(reset)) + cp $< $@ + +$(foreach config,$(BUILD_CONFIGS),$(eval $(call BUILD_TARGETS,$(config)))) + +# Build all configurations +all: release debug asan tsan + $(info $(bold)$(green)All builc config have been build$(reset)) + +# Build libft +$(LIBFT): $(LIBFT_PATH) submodules + $(info $(bold)$(green)Building libft$(reset)) $(MAKE) -C $(LIBFT_PATH) $(LIBFT_PATH): + $(info $(bold)$(green)Adding libft submodule$(reset)) git submodule add https://gitea.duinvoetje.nl/willem/libft.git $(LIBFT_PATH) -$(OBJ_PATH): - mkdir -p $@ - -$(OBJ_PATH)/%.o: %.c $(LIBFT) | $(OBJ_PATH) - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ +# Generate sources.mk +sources.mk: + $(info $(bold)$(green)Generating sources.mk$(reset)) + @echo "VPATH = $$(find $(SRC_PATH) -type d | tr '\n' ':')" > sources.mk + @echo "SOURCES = $$(find $(SRC_PATH) -type f -name '*.c' -exec basename {} \; | tr '\n' ' ' | fold -s -w 70 | sed 's/$$/ \\/')" >> sources.mk +# Remove build artifacts clean: - $(RM) $(OBJECTS) $(OBJ_PATH) + $(info $(bold)$(red)Cleaning$(reset)) + find $(BUILD_PATH) -type d -name 'obj' -exec $(RM) {} + $(MAKE) -C $(LIBFT_PATH) clean - +# Remove build artifacts and the executable fclean: clean + $(info $(bold)$(red)Full cleaning$(reset)) + $(RM) $(BUILD_PATH) $(RM) $(NAME) $(MAKE) -C $(LIBFT_PATH) fclean -re: fclean all +# Rebuild the project +re: fclean + $(info $(bold)$(green)Rebuilding$(reset)) + $(MAKE) all $(NAME) -run: all - ./$(NAME) +# Run the project with the release build configuration +run: run_release + +# Remove sources.mk to force regeneration +srcs: + $(info $(bold)$(green)Regenerating sources.mk on next make$(reset)) + $(RM) sources.mk + +# Show this help. +help: + @echo "Usage: make [target]" + @echo "" + @echo "Targets:" + @echo " $(green)$(bold)all $(reset)- Build all configurations (release, debug, asan, tsan)" + @echo " $(green)$(bold)clean $(reset)- Remove build artifacts" + @echo " $(green)$(bold)fclean $(reset)- Remove build artifacts and the executable" + @echo " $(green)$(bold)re $(reset)- Rebuild the project" + @echo " $(green)$(bold)run $(reset)- Run the release build" + @echo " $(green)$(bold)srcs $(reset)- Remove sources.mk" + @echo " $(green)$(bold)help $(reset)- Show this help message" + @echo "" + @echo "Build configurations:" + @echo " $(green)$(bold)release $(reset)- Build with release configuration" + @echo " $(green)$(bold)debug $(reset)- Build with debug configuration" + @echo " $(green)$(bold)asan $(reset)- Build with AddressSanitizer configuration" + @echo " $(green)$(bold)tsan $(reset)- Build with ThreadSanitizer configuration" + @echo "" + @echo "Run configurations:" + @echo " $(green)$(bold)run_release $(reset)- Run the release build" + @echo " $(green)$(bold)run_debug $(reset)- Run the debug build" + @echo " $(green)$(bold)run_asan $(reset)- Run the AddressSanitizer build" + @echo " $(green)$(bold)run_tsan $(reset)- Run the ThreadSanitizer build" + @echo "" + @echo "Other targets:" + @echo " $(green)$(bold)submodules $(reset)- Check and reinitialize git submodules" + @echo " $(green)$(bold)libft $(reset)- Build libft" + @echo " $(green)$(bold)sources.mk $(reset)- Generate sources.mk" + @echo "" + + +.PHONY: submodules +submodules: + $(info $(bold)$(green)Checking and reinitializing submodules$(reset)) + @if git submodule status | egrep -q '^[-+]' ; then \ + echo "INFO: Need to reinitialize git submodules"; \ + git submodule update --init; \ + fi + +.PHONY: all clean fclean re srcs run help + +red:=$(shell tput setaf 1) +green:=$(shell tput setaf 2) +yellow:=$(shell tput setaf 3) +blue:=$(shell tput setaf 4) +magenta:=$(shell tput setaf 5) +cyan:=$(shell tput setaf 6) +white:=$(shell tput setaf 7) + +bold:=$(shell tput bold) +underline:=$(shell tput smul) + +reset:=$(shell tput sgr0) -.PHONY: all clean fclean re run diff --git a/Makefile.old b/Makefile.old new file mode 100644 index 0000000..634f3cc --- /dev/null +++ b/Makefile.old @@ -0,0 +1,77 @@ +# **************************************************************************** # +# # +# :::::::: # +# Makefile :+: :+: # +# +:+ # +# By: qmennen +#+ # +# +#+ # +# Created: 2024/10/15 11:48:46 by whaffman #+# #+# # +# Updated: 2025/02/20 11:10:42 by whaffman ######## odam.nl # +# # +# **************************************************************************** # + +NAME = minishell + +SRC_PATH = src +INC_PATH = inc +LIB_PATH = lib + +LIBFT_PATH = $(LIB_PATH)/libft +LIBFT_INC_PATH = $(LIBFT_PATH)/inc +LIBFT = $(LIBFT_PATH)/libft.a + +OBJ_PATH = obj + +VPATH = src:src/environment:src/prompt:src/lexer:src/token:src/utils: +VPATH += src/executor:src/parser:src/expander:src/debug:src/signal:src/builtin +SOURCES = $(shell basename -a $(shell find $(SRC_PATH) -type f -name "*.c")) + +OBJECTS = $(addprefix $(OBJ_PATH)/, $(SOURCES:.c=.o)) +DEPENDS = ${OBJECTS:.o=.d} + +CC = cc +RM = rm -rf + +INCLUDES = -I./$(INC_PATH) -I./$(LIBFT_INC_PATH) +CFLAGS = -Wall -Wextra -Werror -fsanitize=address,undefined -MMD -g3 + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + LDLIBS := -L$(LIBFT_PATH) -lft -lreadline +endif + +all: $(NAME) + echo $(SOURCES) + +$(NAME): $(LIBFT) $(OBJECTS) + $(CC) $(CFLAGS) $(OBJECTS) $(LDLIBS) -o $(NAME) + +-include ${DEPENDS} + +$(LIBFT): $(LIBFT_PATH) + $(MAKE) -C $(LIBFT_PATH) + +$(LIBFT_PATH): + git submodule add https://gitea.duinvoetje.nl/willem/libft.git $(LIBFT_PATH) + +$(OBJ_PATH): + mkdir -p $@ + +$(OBJ_PATH)/%.o: %.c $(LIBFT) | $(OBJ_PATH) + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +clean: + $(RM) $(OBJECTS) $(OBJ_PATH) + $(MAKE) -C $(LIBFT_PATH) clean + + +fclean: clean + $(RM) $(NAME) + $(MAKE) -C $(LIBFT_PATH) fclean + +re: fclean all + +run: all + ./$(NAME) + +.PHONY: all clean fclean re run diff --git a/README.md b/README.md index d6fecff..bb574cb 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,32 @@ A lot of amazing shell stuff - libreadline-dev - libncurses-dev +## Comments on work +- Checked if path is a directory and send appropriate message +- `executor_absolute_path` => extracted some code into helpers to make it norminette compliant +- `executor_child` => refactored putstr_fd into error_msg | checked if file on path is exectuable to show permission denied where applicable +- `lexer_token_next` => extracted code for norminette +- `parser` => **A LOT** of work in all files for norminette compliancy +- `expander_parse_string` => Fixed so that $HOME/test.txt returns the correct path and file + +## Edge Cases +- `cat $PWD/test` should expand, +- `cd -` : `bash: cd: OLDPWD not set` +- `cd ~` : does not expand ? + + + + ## TODO --[x] Find absolute path for command input ('/', './', 'cmd') -- Add heredoc to tokenizer --[x] Environment to `t_list` --[x] Get environment array (export) --[x] Set environment variable (export) --[x] Simple builtin export -- Preliminary signals -- Define struct for commands, something like ( +- [x] Find absolute path for command input ('/', './', 'cmd') +- [x]Add heredoc to tokenizer +- [x] Environment to `t_list` +- [x] Get environment array (export) +- [x] Set environment variable (export) +- [x] Simple builtin export +- [x] builtins +- [x] Preliminary signals +- [x] Define struct for commands, something like ( ```c typedef struct s_command { @@ -24,13 +41,38 @@ A lot of amazing shell stuff } t_command; ``` ) -- Make the `executor`, run a command -- Make a parser to create a command list -- Add redirects, appends, pipe etc. File descriptor functions -- Expand \$ vars & support \$? +- [x] Make the `executor`, run a command +- [x] Make a parser to create a command list +- [x] Add redirects, appends, pipe etc. File descriptor functions + a command can have multiple redirects but only the last is used for stdout + Redirects take precedence over pipes, but pipes are still created and managed. + should it close the unused pipe-end? + all redirects are opened and closed, but only last fd is used. + multiple HEREDOCs can be nested, only last is used. +- [x] Expand \$ vars & support \$? + * [x] $var + * [0] $? - CB command to change banner - __Bonus:__ Command tree for &&, ||, * +## Signals +### In interactive mode +- `ctrl - C` redisplay prompt status 130 +- `ctrl - D` exit shell +- `ctrl - \` +-- Done + +### During process +- `ctrl - C` SIGINT to processs status 130 +- `ctrl - D` +- `ctrl - \` SIGQUIT to process core dumped status 131 +-- Shows ^C + +### During HEREDOC +- `ctrl - C` redisplay prompt status 130 +- `ctrl - D` SEND EOF error displayed but still works status:0 +- `ctrl - \` nothing + ## Allowed Functions ### `` diff --git a/inc/allowed.h b/inc/allowed.h index e562c19..7b2859f 100644 --- a/inc/allowed.h +++ b/inc/allowed.h @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/04 16:13:11 by whaffman #+# #+# */ -/* Updated: 2025/02/06 16:14:44 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 16:36:39 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,6 +26,7 @@ # include # include # include +# include # include # include diff --git a/inc/builtin.h b/inc/builtin.h new file mode 100644 index 0000000..1ceac33 --- /dev/null +++ b/inc/builtin.h @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin.h :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:09:02 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:44:47 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#ifndef BUILTIN_H +# define BUILTIN_H +# include "minishell.h" + +int is_builtin(char *cmd); +int builtin_router(t_minishell *msh, t_command *cmd); +int builtin_echo(t_minishell *msh, t_command *cmd); +int builtin_cd(t_minishell *msh, t_command *cmd); +int builtin_pwd(t_minishell *msh, t_command *cmd); +int builtin_export(t_minishell *msh, t_command *cmd); +int builtin_unset(t_minishell *msh, t_command *cmd); +int builtin_env(t_minishell *msh, t_command *cmd); +int builtin_exit(t_minishell *msh, t_command *cmd); + +#endif // BUILTIN_H diff --git a/inc/debug.h b/inc/debug.h new file mode 100644 index 0000000..fc287f5 --- /dev/null +++ b/inc/debug.h @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* debug.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/18 20:06:53 by qmennen #+# #+# */ +/* Updated: 2025/02/18 20:10:49 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef DEBUG_H +# define DEBUG_H + +# include "minishell.h" + +void print_commands(void *param); +void token_print(void *param); +void print_redirects(void *param); +void print_freelist(t_minishell *msh); + +#endif diff --git a/inc/environment.h b/inc/environment.h index d98c3c3..6d0e160 100644 --- a/inc/environment.h +++ b/inc/environment.h @@ -6,7 +6,7 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/04 16:26:35 by whaffman #+# #+# */ -/* Updated: 2025/02/11 15:39:15 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 15:44:49 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -15,13 +15,14 @@ # include "minishell.h" -void environment_add(t_list **environment, char *name, char *value); -void environment_print(t_list *environment); -t_environment *environment_get(t_list *environment, char *name); -void environment_free_list(t_list **environment); -int environment_parse(char **envp, t_list **environment); -char **environment_get_arr(t_list *environment); -void environment_del(t_list **environment, char *name); -void environment_free(void *content); +void environment_add(t_minishell *msh, + char *name, char *value); +void environment_print(t_minishell *msh); +t_environment *environment_get(t_minishell *msh, char *name); +void environment_free_list(t_minishell *msh); +int environment_parse(t_minishell *msh, char **envp); +char **environment_get_arr(t_minishell *msh); +void environment_del(t_minishell *msh, char *name); +void environment_free(t_minishell *msh, void *content); #endif // ENVIRONMENT_H diff --git a/inc/executor.h b/inc/executor.h index 1c256de..6799399 100644 --- a/inc/executor.h +++ b/inc/executor.h @@ -6,7 +6,7 @@ /* By: willem +#+ */ /* +#+ */ /* Created: 2025/02/08 17:06:07 by willem #+# #+# */ -/* Updated: 2025/02/11 17:06:54 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 15:45:17 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -15,6 +15,14 @@ # include "minishell.h" -char *executor_absolute_path(t_list *env, char *cmd); +char *executor_absolute_path(t_minishell *msh, char *cmd); +void executor_child(t_minishell *msh, t_command *command); +pid_t executor_fork(t_minishell *msh, t_command *command); +void executor_create_pipes(t_minishell *msh); +int executor_execute_pipeline(t_minishell *msh); +void executor_close_fds(int n_fds); +int executor_count_fds(t_minishell *msh); +int executor_open_fds(t_list *redirect_list, int og_fd); +void executor_create_redirects(t_minishell *msh); #endif // EXECUTOR_H diff --git a/inc/expander.h b/inc/expander.h new file mode 100644 index 0000000..82f4b4b --- /dev/null +++ b/inc/expander.h @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* expander.h :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/18 19:00:51 by qmennen #+# #+# */ +/* Updated: 2025/02/26 15:45:19 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#ifndef EXPANDER_H +# define EXPANDER_H + +# include "minishell.h" + +t_environment *expander_get_var(const char *s, int idx, + t_minishell *msh); +t_list *expander_parse_variables(const char *s, + t_minishell *msh); +char *expander_allocate_memory( + t_minishell *msh, + const char *s, + t_list *variables); +char *expander_parse_string(char *s, t_minishell *msh); +int expander_character_valid(const char c); +int expander_expand_dollar(char *src, char *dest, + int *j, t_list *variables); + +#endif diff --git a/inc/minishell.h b/inc/minishell.h index d67e2fe..1697e7f 100644 --- a/inc/minishell.h +++ b/inc/minishell.h @@ -1,42 +1,56 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* minishell.h :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/02/04 16:13:13 by whaffman #+# #+# */ -/* Updated: 2025/02/11 15:50:21 by whaffman ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#ifndef MINISHELL_H -# define MINISHELL_H - -# include "allowed.h" -# include "libft.h" -# include "typedef.h" -# include "environment.h" -# include "prompt.h" -# include "tokenizer.h" -# include "executor.h" -# include "parser.h" -# include "utils.h" - -# define TRUE 1 -# define FALSE 0 - -# define SUCCESS 1 -# define FAILURE 0 - -# define BOLD "\001\033[1m\002" -# define RED "\001\033[0;31m\002" -# define GREEN "\001\033[0;32m\002" -# define YELLOW "\001\033[0;33m\002" -# define BLUE "\001\033[0;34m\002" -# define MAGENTA "\001\033[0;35m\002" -# define CYAN "\001\033[0;36m\002" -# define RESET "\001\033[0m\002" -# define PROMPT RESET "🐚" GREEN "minishell" RESET ": " - -#endif +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* minishell.h :+: :+: */ +/* +:+ */ +/* By: marvin +#+ */ +/* +#+ */ +/* Created: 2025/02/04 16:13:13 by whaffman #+# #+# */ +/* Updated: 2025/02/23 12:28:23 by Quinten ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#ifndef MINISHELL_H +# define MINISHELL_H + +# include "allowed.h" +# include "libft.h" +# include "typedef.h" +# include "signals.h" +# include "environment.h" +# include "prompt.h" +# include "tokenizer.h" +# include "builtin.h" +# include "executor.h" +# include "parser.h" +# include "expander.h" +# include "redirect.h" +# include "debug.h" +# include "utils.h" + +# define TRUE 1 +# define FALSE 0 + +# define SUCCESS 1 +# define FAILURE 0 + +# define BOLD "\001\033[1m\002" +# define RED "\001\033[0;31m\002" +# define GREEN "\001\033[0;32m\002" +# define YELLOW "\001\033[0;33m\002" +# define BLUE "\001\033[0;34m\002" +# define MAGENTA "\001\033[0;35m\002" +# define CYAN "\001\033[0;36m\002" +# define RESET "\001\033[0m\002" +# define PROMPT RESET "🐚" GREEN "minishell" RESET ": " +# define PROMPT_LEN 51 + +# ifdef DEBUG +# define DEBUG 1 +# else +# define DEBUG 0 +# endif // DEBUG + +void token_print(void *param); + +#endif diff --git a/inc/parser.h b/inc/parser.h index 8caaa0a..a3d0483 100644 --- a/inc/parser.h +++ b/inc/parser.h @@ -15,8 +15,11 @@ # include "minishell.h" -t_command *parser_command_new(char *cmd); -char **parser_get_arguments(t_list *list); -t_list *parser_get_commands(t_list *list); +t_command *parser_alloc_command(t_minishell *msh, char *cmd); +t_list *parser_get_commands(t_minishell *msh); +t_list *parser_get_input_redirects(t_list *list); +void parser_create_command(t_minishell *msh, t_command *cmd, t_list **l_tkn); +char **parser_get_arguments(t_list *list, t_minishell *msh); +int parser_validate_command(t_command *command); #endif diff --git a/inc/prompt.h b/inc/prompt.h index 155de23..efdb11a 100644 --- a/inc/prompt.h +++ b/inc/prompt.h @@ -6,7 +6,7 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/04 16:35:35 by whaffman #+# #+# */ -/* Updated: 2025/02/05 17:05:32 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 15:45:22 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -16,8 +16,8 @@ # include "minishell.h" void print_banner(void); -char *ft_prompt(t_minishell *minishell); -void ft_write_history(char *line); -void ft_load_history(void); +char *ft_prompt(t_minishell *msh); +void history_write(char *line); +void history_load(void); #endif // PROMPT_H diff --git a/inc/redirect.h b/inc/redirect.h new file mode 100644 index 0000000..3a1e568 --- /dev/null +++ b/inc/redirect.h @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/23 12:26:29 by Quinten #+# #+# */ +/* Updated: 2025/02/27 18:09:47 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef REDIRECT_H +# define REDIRECT_H +# include "minishell.h" + +t_redirect *redirect_new(t_minishell *msh, t_token_type type, char *value); +void redirect_new_error(t_minishell *msh, t_list **redirects, int flag); +int redirect_create(t_minishell *msh, t_list **tokens, t_list **redirects, t_token_type type); +t_list *redirect_get_inputs(t_minishell *msh, t_list *list); +t_list *redirect_get_outputs(t_minishell *msh, t_list *list); +int redirect_is_valid(t_list *lst, t_token *token, int mode); +int redirect_token_type(t_token *token); +int redirect_is_delimiter(t_token *token); +int process_heredoc(t_minishell *msh, t_token *heredoc, t_token *delim); + +#endif diff --git a/inc/signals.h b/inc/signals.h new file mode 100644 index 0000000..3d9ae46 --- /dev/null +++ b/inc/signals.h @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* signals.h :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/19 12:26:09 by whaffman #+# #+# */ +/* Updated: 2025/02/19 17:30:12 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#ifndef SIGNALS_H +# define SIGNALS_H + +# include "minishell.h" + +void sigint_heredoc_handler(int signum); +void sigint_minishell_handler(int signum); +void sig_parent_handler(int signum); +void signal_init_child(void); +void signal_init_parent(void); +void signal_init_minishell(void); + +#endif // SIGNALS_H diff --git a/inc/tokenizer.h b/inc/tokenizer.h index 1e8d893..bab22bf 100644 --- a/inc/tokenizer.h +++ b/inc/tokenizer.h @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* tokenizer.h :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/02/05 12:36:00 by whaffman #+# #+# */ -/* Updated: 2025/02/05 12:36:01 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* tokenizer.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/05 12:36:00 by whaffman #+# #+# */ +/* Updated: 2025/02/27 19:03:09 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,18 +16,21 @@ /** * Lexer */ -t_lexer *ft_lexer_new(const char *input); -void ft_lexer_free(t_lexer *lexer); -void ft_lexer_readchar(t_lexer *lexer); -char *ft_lexer_readword(t_lexer *lexer); -t_list *ft_parse_input(t_lexer *lexer); +t_lexer *ft_lexer_new(t_minishell *msh); +void ft_lexer_free(t_minishell *msh, t_lexer *lexer); +void lexer_readchar(t_lexer *lexer); +char *lexer_readword(t_minishell *msh, t_lexer *lexer); +t_list *ft_parse_input(t_minishell *msh); +char *lexer_parse_quotes(t_minishell *msh, t_lexer *lexer); /** * Token */ -t_token *ft_token_next(t_lexer *lexer); -t_token *ft_token_new(t_token_type type, char *c, int pos); -void ft_token_free(t_token *token); -void ft_clear_tokenlist(void *content); -t_token *ft_parse_token(t_lexer *lexer); +t_token *ft_token_next(t_minishell *msh, t_lexer *lexer); +t_token *token_new(t_minishell *msh, t_token_type type, char *c, int pos); +void ft_token_free(t_minishell *msh, t_token *token); +void ft_clear_tokenlist(t_minishell *msh, void *content); +t_token *token_parse(t_minishell *msh, t_lexer *lexer); +char *token_type_convert(t_token_type type); +t_token_type token_char_convert(char c, int is_double); #endif // TOKENIZER_H diff --git a/inc/typedef.h b/inc/typedef.h index 6b6a6f2..292ed84 100644 --- a/inc/typedef.h +++ b/inc/typedef.h @@ -3,10 +3,10 @@ /* :::::::: */ /* typedef.h :+: :+: */ /* +:+ */ -/* By: whaffman +#+ */ +/* By: qmennen +#+ */ /* +#+ */ /* Created: 2025/02/05 12:36:08 by whaffman #+# #+# */ -/* Updated: 2025/02/05 15:25:40 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 17:26:27 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -16,9 +16,13 @@ typedef enum e_token_type { T_WORD, + T_DQWORD, + T_SQWORD, T_PIPE, T_REDIRECT_IN, T_REDIRECT_OUT, + T_AND, + T_OR, T_APPEND_OUT, T_HEREDOC, T_EOF, @@ -46,12 +50,23 @@ typedef struct s_lexer char current_char; } t_lexer; +typedef struct s_redirect +{ + enum e_token_type type; + char *value; +} t_redirect; + typedef struct s_command { char *command; char **args; + t_list *environment; + t_list *redirect_in; + t_list *redirect_out; int fd_in; int fd_out; + int n_fds; + int exit_status; } t_command; typedef struct s_minishell @@ -61,5 +76,9 @@ typedef struct s_minishell t_lexer *lexer; t_list *tokens; t_list *commands; + t_list *freelist; + int exit_status; } t_minishell; + +typedef int (*t_builtin_fn)(t_minishell *, t_command *); #endif // TYPEDEF_H diff --git a/inc/utils.h b/inc/utils.h index d374f75..0b2c726 100644 --- a/inc/utils.h +++ b/inc/utils.h @@ -1,24 +1,37 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* utils.h :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/02/05 16:06:35 by whaffman #+# #+# */ -/* Updated: 2025/02/05 16:23:21 by whaffman ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#ifndef UTILS_H -# define UTILS_H - -void free_minishell_line(t_minishell *minishell); -void free_minishell(t_minishell *minishell); -void free_command_list(void *content); -t_minishell *init_minishell(void); -void print_banner(void); -void print_list(void *content); -void simple_builtins(t_minishell *minishell); - -#endif // UTILS_H +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* utils.h :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/05 16:06:35 by whaffman #+# #+# */ +/* Updated: 2025/02/20 18:07:19 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#ifndef UTILS_H +# define UTILS_H + +void free_minishell_line(t_minishell *msh); +void free_minishell(t_minishell **msh); +void free_command_list(t_minishell *msh, void *content); +t_minishell *init_minishell(void); +void print_banner(void); +void print_list(void *content); +void simple_builtins(t_minishell *msh); +void error_msg(char *func, char *msg); +void check_malloc(t_minishell *msh, void *ptr); +char *ft_strdup_safe(t_minishell *msh, const char *str); +char *ft_substr_safe(t_minishell *msh, const char *str, + unsigned int start, size_t len); +char *ft_strjoin_safe(t_minishell *msh, + const char *s1, const char *s2); +void *malloc_safe(t_minishell *msh, size_t size); +void free_safe(t_minishell *msh, void **ptr); +void free_freelist(t_minishell *msh); +void ft_lstclear_safe(t_minishell *msh, t_list **lst, + void (*del)(t_minishell *msh, void *)); +t_list *ft_lstnew_safe(t_minishell *msh, void *content); + +#endif // UTILS_H diff --git a/sources.mk b/sources.mk new file mode 100644 index 0000000..e85d1ea --- /dev/null +++ b/sources.mk @@ -0,0 +1,24 @@ +VPATH = src:src/prompt:src/utils:src/lexer:src/token:src/environment:src/executor:src/parser:src/debug:src/expander:src/builtin:src/signal:src/redirect: +SOURCES = history_load.c history_write.c prompt.c print_banner.c check_malloc.c \ +free_command_list.c free_freelist.c free_lexer.c free_minishell.c \ +free_safe.c free_token.c free_token_list.c ft_lstclear_safe.c \ +ft_lstnew_safe.c ft_strdup_safe.c ft_strjoin_safe.c malloc_safe.c \ +error_msg.c free_minishell_line.c ft_substr_safe.c init_minishell.c \ +lexer_read_char.c lexer_new.c lexer_parse_input.c lexer_read_word.c \ +lexer_token_next.c token_new.c token_parse.c environment_add.c \ +environment_del.c environment_free.c environment_free_list.c \ +environment_get.c environment_get_arr.c environment_parse.c \ +environment_print.c executor_close_fds.c executor_absolute_path.c \ +executor_count_fds.c executor_create_pipes.c \ +executor_create_redirects.c executor_open_fds.c \ +executor_execute_pipeline.c executor_fork.c executor_child.c \ +parser_create_command.c parser_get_arguments.c parser_alloc_command.c \ +parser_get_commands.c parser_validate_command.c print_commands.c \ +print_freelist.c expander_is_character.c expander_expand_dollar.c \ +expander_allocate_memory.c expander_get_variable.c \ +expander_parse_variables.c expander_parse_string.c is_builtin.c \ +simple_builtins.c builtin_cd.c builtin_echo.c builtin_env.c \ +builtin_exit.c builtin_export.c builtin_pwd.c builtin_router.c \ +builtin_unset.c signal.c signal_init.c.c redirect_get_inputs.c \ +redirect_get_outputs.c redirect_new.c redirect_new_error.c \ +redirect_process_heredoc.c redirect_valid_type.c main.c \ diff --git a/src/builtin/builtin_cd.c b/src/builtin/builtin_cd.c new file mode 100644 index 0000000..f2a5006 --- /dev/null +++ b/src/builtin/builtin_cd.c @@ -0,0 +1,41 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin_cd.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:33:07 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:45:55 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int builtin_cd(t_minishell *msh, t_command *cmd) +{ + t_environment *env; + char *path; + + if (cmd->args[1] == NULL) + { + env = environment_get(msh, "HOME"); + if (env == NULL || env->value == NULL) + { + ft_putendl_fd("minishell: cd: HOME not set", STDERR_FILENO); + return (FAILURE); + } + path = env->value; + } + else + path = cmd->args[1]; + if (chdir(path) == -1) + { + ft_putstr_fd("minishell: cd: ", STDERR_FILENO); + ft_putstr_fd(path, STDERR_FILENO); + ft_putstr_fd(": ", STDERR_FILENO); + ft_putendl_fd(strerror(errno), STDERR_FILENO); + return (FAILURE); + } + return (SUCCESS); +} diff --git a/src/builtin/builtin_echo.c b/src/builtin/builtin_echo.c new file mode 100644 index 0000000..8a2da83 --- /dev/null +++ b/src/builtin/builtin_echo.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin_echo.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:33:05 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:46:29 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int builtin_echo(t_minishell *msh, t_command *cmd) +{ + int i; + int n_flag; + + (void)msh; + i = 1; + n_flag = 0; + if (cmd->args[i] != NULL && ft_strncmp(cmd->args[i], "-n", 3) == 0) + { + n_flag = 1; + i++; + } + while (cmd->args[i] != NULL) + { + printf("%s", cmd->args[i]); + if (cmd->args[i + 1] != NULL) + printf(" "); + i++; + } + if (!n_flag) + printf("\n"); + return (SUCCESS); +} diff --git a/src/builtin/builtin_env.c b/src/builtin/builtin_env.c new file mode 100644 index 0000000..2b92fa8 --- /dev/null +++ b/src/builtin/builtin_env.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin_env.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:33:02 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:46:55 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int builtin_env(t_minishell *msh, t_command *cmd) +{ + (void)cmd; + environment_print(msh); + return (SUCCESS); +} diff --git a/src/builtin/builtin_exit.c b/src/builtin/builtin_exit.c new file mode 100644 index 0000000..adf39cf --- /dev/null +++ b/src/builtin/builtin_exit.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin_exit.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:32:59 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:47:14 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +//TODO EXIT last exit status r:20 +int builtin_exit(t_minishell *msh, t_command *cmd) +{ + int exit_status; + + exit_status = 0; + if (ft_count_arr(cmd->args) > 2) + { + ft_putstr_fd("exit\n", STDERR_FILENO); + ft_putstr_fd("minishell: exit: too many arguments\n", STDERR_FILENO); + return (FAILURE); + } + if (ft_count_arr(cmd->args) == 2 && cmd->args[1] != NULL) + { + if (ft_isdigit_str(cmd->args[1]) == FALSE) + { + ft_putstr_fd("exit\n", STDERR_FILENO); + ft_putstr_fd("minishell: exit: ", STDERR_FILENO); + ft_putstr_fd(cmd->args[1], STDERR_FILENO); + ft_putstr_fd(": numeric argument required\n", STDERR_FILENO); + return (FAILURE); + } + exit_status = ft_atoi(cmd->args[1]); + } + free_minishell(&msh); + rl_clear_history(); + exit(exit_status); + return (FAILURE); +} diff --git a/src/builtin/builtin_export.c b/src/builtin/builtin_export.c new file mode 100644 index 0000000..74714c7 --- /dev/null +++ b/src/builtin/builtin_export.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin_export.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:32:53 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:49:16 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int builtin_export(t_minishell *msh, t_command *cmd) +{ + t_environment *env; + char **arr; + int i; + + i = 0; + while (cmd->args[++i] != NULL) + { + arr = ft_split(cmd->args[i], '='); + if (arr[1] == NULL) + { + ft_free_arr(arr); + i++; + continue ; + } + env = environment_get(msh, arr[0]); + if (env != NULL) + { + free_safe(msh, (void **)&(env->value)); + env->value = ft_strdup_safe(msh, arr[1]); + } + else + environment_add(msh, arr[0], arr[1]); + ft_free_arr(arr); + } + return (SUCCESS); +} diff --git a/src/builtin/builtin_pwd.c b/src/builtin/builtin_pwd.c new file mode 100644 index 0000000..480086b --- /dev/null +++ b/src/builtin/builtin_pwd.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin_pwd.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:32:28 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:06:09 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int builtin_pwd(t_minishell *msh, t_command *cmd) +{ + char *cwd; + + (void)msh; + (void)cmd; + cwd = getcwd(NULL, 0); + printf("%s\n", cwd); + free_safe(msh, (void **)&(cwd)); + return (SUCCESS); +} diff --git a/src/builtin/builtin_router.c b/src/builtin/builtin_router.c new file mode 100644 index 0000000..5e5aa8c --- /dev/null +++ b/src/builtin/builtin_router.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin_router.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:12:38 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:06:18 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int builtin_router(t_minishell *msh, t_command *cmd) +{ + const t_builtin_fn builtin_fn[] = { + builtin_echo, + builtin_cd, + builtin_pwd, + builtin_export, + builtin_unset, + builtin_env, + builtin_exit}; + + if (!is_builtin(cmd->args[0])) + return (FALSE); + builtin_fn[is_builtin(cmd->args[0])](msh, cmd); + return (TRUE); +} diff --git a/src/builtin/builtin_unset.c b/src/builtin/builtin_unset.c new file mode 100644 index 0000000..8dae319 --- /dev/null +++ b/src/builtin/builtin_unset.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* builtin_unset.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:25:43 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:07:21 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int builtin_unset(t_minishell *msh, t_command *cmd) +{ + int i; + + i = 1; + while (cmd->args[i] != NULL) + { + if (environment_get(msh, cmd->args[i]) != NULL) + environment_del(msh, cmd->args[i]); + i++; + } + return (SUCCESS); +} diff --git a/src/builtin/is_builtin.c b/src/builtin/is_builtin.c new file mode 100644 index 0000000..05cb3f9 --- /dev/null +++ b/src/builtin/is_builtin.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* is_builtin.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 11:03:33 by whaffman #+# #+# */ +/* Updated: 2025/02/26 14:42:49 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int is_builtin(char *cmd) +{ + const char *builtins[] = {"echo", "cd", "pwd", "export", + "unset", "env", "exit", NULL}; + int i; + + i = 0; + while (builtins[i]) + { + if (ft_strcmp(cmd, builtins[i]) == 0) + return (i); + i++; + } + return (FALSE); +} diff --git a/src/builtin/simple_builtins.c b/src/builtin/simple_builtins.c new file mode 100644 index 0000000..296ddf9 --- /dev/null +++ b/src/builtin/simple_builtins.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* simple_builtins.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/05 16:21:39 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:08:49 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void simple_builtins(t_minishell *msh) +{ + if (msh->commands == NULL) + return ; + if (!builtin_router(msh, msh->commands->content)) + executor_execute_pipeline(msh); +} diff --git a/src/debug/print_commands.c b/src/debug/print_commands.c new file mode 100644 index 0000000..2092b8d --- /dev/null +++ b/src/debug/print_commands.c @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* print_commands.c :+: :+: */ +/* +:+ */ +/* By: marvin +#+ */ +/* +#+ */ +/* Created: 2025/02/18 20:06:37 by qmennen #+# #+# */ +/* Updated: 2025/02/23 12:43:35 by Quinten ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void print_commands(void *param) +{ + t_command *command; + int i; + + if (!DEBUG) + return ; + command = (t_command *)param; + if (!command) + return ; + printf("command: %s\n", command->command); + printf("-- Args: "); + i = 0; + while (command->args[i]) + printf("%s ", command->args[i++]); + printf("\n"); + printf("-- Input redirects:\n"); + ft_lstiter(command->redirect_in, print_redirects); + printf("-- Output redirects:\n"); + ft_lstiter(command->redirect_out, print_redirects); +} + +void print_redirects(void *param) +{ + t_redirect *redirect; + + redirect = (t_redirect *)param; + if (!redirect) + return ; + printf(" Redirect %i value %s\n", redirect->type, redirect->value); +} + +void token_print(void *param) +{ + t_token *token; + + if (!DEBUG) + return ; + token = (t_token *)param; + printf("token type %i, value %s\n", token->type, token->value); +} diff --git a/src/debug/print_freelist.c b/src/debug/print_freelist.c new file mode 100644 index 0000000..2cce7e9 --- /dev/null +++ b/src/debug/print_freelist.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* print_freelist.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/25 15:46:03 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:08:53 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void print_freelist(t_minishell *msh) +{ + t_list *freelist; + int i; + + if (!DEBUG) + return ; + i = 0; + freelist = msh->freelist; + while (freelist) + { + printf("%d: %p\n", i, freelist->content); + i++; + freelist = freelist->next; + } +} diff --git a/src/environment/environment_add.c b/src/environment/environment_add.c index 03c9cc9..32049d0 100644 --- a/src/environment/environment_add.c +++ b/src/environment/environment_add.c @@ -6,32 +6,32 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/04 16:13:33 by whaffman #+# #+# */ -/* Updated: 2025/02/11 17:15:45 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:07 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void environment_add(t_list **environment, char *name, char *value) +void environment_add(t_minishell *msh, char *name, char *value) { t_environment *new_environment; t_list *new_node; + t_list **environment; + environment = &msh->environment; if (name != NULL && value != NULL) { - new_environment = malloc(sizeof(t_environment)); + new_environment = malloc_safe(msh, sizeof(t_environment)); if (new_environment == NULL) return (perror("malloc")); - new_environment->name = ft_strdup(name); - new_environment->value = ft_strdup(value); - new_node = ft_lstnew(new_environment); + new_environment->name = ft_strdup_safe(msh, name); + new_environment->value = ft_strdup_safe(msh, value); + new_node = ft_lstnew_safe(msh, new_environment); if (new_node == NULL || new_environment->name == NULL || new_environment->value == NULL) { - free(new_environment->name); - free(new_environment->value); - free(new_environment); + environment_free(msh, new_environment); return (perror("malloc")); } ft_lstadd_back(environment, new_node); diff --git a/src/environment/environment_del.c b/src/environment/environment_del.c index 6a7fd35..3f5f85b 100644 --- a/src/environment/environment_del.c +++ b/src/environment/environment_del.c @@ -6,13 +6,13 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/11 14:17:53 by whaffman #+# #+# */ -/* Updated: 2025/02/11 17:20:26 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:12 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void environment_del(t_list **environment, char *name) +void environment_del(t_minishell *msh, char *name) { t_list *prev; t_list *current; @@ -21,17 +21,17 @@ void environment_del(t_list **environment, char *name) prev = NULL; next = NULL; - current = *environment; + current = msh->environment; while (current != NULL) { env = (t_environment *)current->content; if (ft_strncmp(env->name, name, ft_strlen(name) + 1) == 0) { next = current->next; - environment_free(current->content); - free(current); + environment_free(msh, current->content); + free_safe(msh, (void **)&(current)); if (prev == NULL) - *environment = next; + msh->environment = next; else prev->next = next; return ; diff --git a/src/environment/environment_free.c b/src/environment/environment_free.c index 6680cb1..d00187a 100644 --- a/src/environment/environment_free.c +++ b/src/environment/environment_free.c @@ -6,18 +6,18 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/11 15:38:43 by whaffman #+# #+# */ -/* Updated: 2025/02/11 15:38:48 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:17 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void environment_free(void *content) +void environment_free(t_minishell *msh, void *content) { t_environment *env; env = (t_environment *)content; - free(env->name); - free(env->value); - free(env); + free_safe(msh, (void **)&(env->name)); + free_safe(msh, (void **)&(env->value)); + free_safe(msh, (void **)&(env)); } diff --git a/src/environment/environment_free_list.c b/src/environment/environment_free_list.c index 2e1905c..bb35108 100644 --- a/src/environment/environment_free_list.c +++ b/src/environment/environment_free_list.c @@ -6,13 +6,28 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/04 16:13:59 by whaffman #+# #+# */ -/* Updated: 2025/02/11 17:18:27 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:15 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void environment_free_list(t_list **environment) +void environment_free_list(t_minishell *msh) { - ft_lstclear(environment, environment_free); + t_list **lst; + t_list *next; + + lst = &msh->environment; + if (!lst) + return ; + while (*lst) + { + if ((*lst)->next) + next = (*lst)->next; + else + next = NULL; + environment_free(msh, (*lst)->content); + free(*lst); + *lst = next; + } } diff --git a/src/environment/environment_get.c b/src/environment/environment_get.c index 280698e..882d082 100644 --- a/src/environment/environment_get.c +++ b/src/environment/environment_get.c @@ -6,16 +6,18 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/04 16:15:05 by whaffman #+# #+# */ -/* Updated: 2025/02/11 17:04:28 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:22 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -t_environment *environment_get(t_list *environment, char *name) +t_environment *environment_get(t_minishell *msh, char *name) { t_environment *env; + t_list *environment; + environment = msh->environment; while (environment != NULL) { env = (t_environment *)environment->content; diff --git a/src/environment/environment_get_arr.c b/src/environment/environment_get_arr.c index 8052e04..d9d2034 100644 --- a/src/environment/environment_get_arr.c +++ b/src/environment/environment_get_arr.c @@ -6,28 +6,28 @@ /* By: willem +#+ */ /* +#+ */ /* Created: 2025/02/08 13:59:48 by willem #+# #+# */ -/* Updated: 2025/02/11 17:18:15 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:20 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -char **environment_get_arr(t_list *environment) +char **environment_get_arr(t_minishell *msh) { char **arr; t_environment *env; int i; + t_list *environment; - arr = malloc(sizeof(char *) * (ft_lstsize(environment) + 1)); - if (arr == NULL) - return (NULL); + environment = msh->environment; + arr = malloc_safe(msh, + sizeof(char *) * (ft_lstsize(environment) + 1)); i = 0; while (environment != NULL) { env = (t_environment *)environment->content; - arr[i] = malloc(ft_strlen(env->name) + ft_strlen(env->value) + 2); - if (arr[i] == NULL) - return (ft_free_arr(arr), NULL); + arr[i] = malloc_safe(msh, + ft_strlen(env->name) + ft_strlen(env->value) + 2); ft_strlcpy(arr[i], env->name, ft_strlen(env->name) + 1); ft_strlcat(arr[i], "=", ft_strlen(env->name) + 2); ft_strlcat(arr[i], env->value, diff --git a/src/environment/environment_parse.c b/src/environment/environment_parse.c index 3abd042..ba2e5e7 100644 --- a/src/environment/environment_parse.c +++ b/src/environment/environment_parse.c @@ -3,26 +3,27 @@ /* :::::::: */ /* environment_parse.c :+: :+: */ /* +:+ */ -/* By: whaffman +#+ */ +/* By: qmennen +#+ */ /* +#+ */ /* Created: 2025/02/05 15:52:33 by whaffman #+# #+# */ -/* Updated: 2025/02/11 17:18:43 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:26 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -int environment_parse(char **envp, t_list **environment) +int environment_parse(t_minishell *msh, char **envp) { char **env; - *environment = NULL; if (envp == NULL) return (FAILURE); while (*envp != NULL) { env = ft_split(*envp, '='); - environment_add(environment, env[0], env[1]); + if (!env) + return (FAILURE); + environment_add(msh, env[0], env[1]); ft_free_arr(env); envp++; } diff --git a/src/environment/environment_print.c b/src/environment/environment_print.c index e5c7b52..d76c7d5 100644 --- a/src/environment/environment_print.c +++ b/src/environment/environment_print.c @@ -6,23 +6,18 @@ /* By: willem +#+ */ /* +#+ */ /* Created: 2025/02/08 13:52:08 by willem #+# #+# */ -/* Updated: 2025/02/11 17:05:10 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:35 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void environment_print(t_list *environment) +void environment_print(t_minishell *msh) { char **arr; int i; - arr = environment_get_arr(environment); - if (arr == NULL) - { - perror("malloc"); - return ; - } + arr = environment_get_arr(msh); i = 0; while (arr[i] != NULL) { diff --git a/src/executor/executor_absolute_path.c b/src/executor/executor_absolute_path.c index 396dbb2..a876e87 100644 --- a/src/executor/executor_absolute_path.c +++ b/src/executor/executor_absolute_path.c @@ -6,13 +6,41 @@ /* By: willem +#+ */ /* +#+ */ /* Created: 2025/02/08 17:00:24 by willem #+# #+# */ -/* Updated: 2025/02/11 17:20:17 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:09:42 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -char *executor_absolute_path(t_list *env, char *cmd) +static char *resolve_relative(t_minishell *msh, char *cmd) +{ + char *executable; + + if (access(cmd, F_OK) == 0) + { + executable = ft_strdup_safe(msh, cmd); + if (!executable) + return (NULL); + return (executable); + } + return (NULL); +} + +static char *resolve_path(t_minishell *msh, char *path, char *cmd) +{ + char *executable; + + executable = malloc_safe(msh, ft_strlen(path) + ft_strlen(cmd) + 2); + ft_strlcpy(executable, path, ft_strlen(path) + 1); + ft_strlcat(executable, "/", ft_strlen(path) + 2); + ft_strlcat(executable, cmd, ft_strlen(path) + ft_strlen(cmd) + 2); + if (access(executable, F_OK) == 0) + return (executable); + free_safe(msh, (void **)&executable); + return (NULL); +} + +char *executor_absolute_path(t_minishell *msh, char *cmd) { char **path; t_environment *path_env; @@ -20,35 +48,17 @@ char *executor_absolute_path(t_list *env, char *cmd) int i; if (cmd[0] == '/' || cmd[0] == '.') - { - if (access(cmd, F_OK) == 0) - { - executable = ft_strdup(cmd); - if (!executable) - return (NULL); - return (executable); - } - return (NULL); - } - path_env = environment_get(env, "PATH"); + return (resolve_relative(msh, cmd)); + path_env = environment_get(msh, "PATH"); if (!path_env) return (NULL); path = ft_split(path_env->value, ':'); i = 0; while (path[i] != NULL) { - executable = malloc(ft_strlen(path[i]) + ft_strlen(cmd) + 2); - if (!executable) - return (ft_free_arr(path), NULL); - ft_strlcpy(executable, path[i], ft_strlen(path[i]) + 1); - ft_strlcat(executable, "/", ft_strlen(path[i]) + 2); - ft_strlcat(executable, cmd, ft_strlen(path[i]) + ft_strlen(cmd) + 2); - if (access(executable, F_OK) == 0) - { - ft_free_arr(path); + executable = resolve_path(msh, path[i], cmd); + if (executable) return (executable); - } - free(executable); i++; } return (ft_free_arr(path), NULL); diff --git a/src/executor/executor_child.c b/src/executor/executor_child.c new file mode 100644 index 0000000..1e64f47 --- /dev/null +++ b/src/executor/executor_child.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* executor_child.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/12 21:25:10 by willem #+# #+# */ +/* Updated: 2025/02/27 18:12:48 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static int is_dir(char *path) +{ + struct stat path_stats; + + if (stat(path, &path_stats) < 0) + { + error_msg("is_dir", "path could not be read"); + return (0); + } + return (S_ISDIR(path_stats.st_mode)); +} + +void executor_child(t_minishell *msh, t_command *command) +{ + char *path; + + if (command->fd_in != 0) + dup2(command->fd_in, 0); + if (command->fd_out != 1) + dup2(command->fd_out, 1); + executor_close_fds(command->n_fds); + path = executor_absolute_path(msh, command->args[0]); + if (path == NULL || access(path, F_OK | X_OK) != 0) + { + error_msg("minishell", "command not found"); + return ; + } + if (is_dir(path)) + { + ft_putstr_fd(RED BOLD, 2); + ft_putstr_fd("minishell: ", 2); + ft_putstr_fd(command->args[0], 2); + ft_putstr_fd(": " RESET "Is a directory\n", 2); + } + execve(path, command->args, environment_get_arr(msh)); +} diff --git a/src/executor/executor_close_fds.c b/src/executor/executor_close_fds.c new file mode 100644 index 0000000..2c38dbc --- /dev/null +++ b/src/executor/executor_close_fds.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* executor_close_fds.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/13 13:31:25 by whaffman #+# #+# */ +/* Updated: 2025/02/13 15:04:15 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void executor_close_fds(int n_fds) +{ + int i; + + i = 3; + while (i < n_fds + 3) + { + close(i); + i++; + } +} diff --git a/src/executor/executor_count_fds.c b/src/executor/executor_count_fds.c new file mode 100644 index 0000000..a2d72be --- /dev/null +++ b/src/executor/executor_count_fds.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* executor_count_fds.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/21 12:42:26 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:09:45 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int executor_count_fds(t_minishell *msh) +{ + int count; + t_list *current; + t_command *command; + + current = msh->commands; + count = (ft_lstsize(current) - 1) * 2; + while (current) + { + command = (t_command *)current->content; + count += ft_lstsize(command->redirect_in); + count += ft_lstsize(command->redirect_out); + current = current->next; + } + return (count); +} diff --git a/src/executor/executor_create_pipes.c b/src/executor/executor_create_pipes.c new file mode 100644 index 0000000..4a9eb45 --- /dev/null +++ b/src/executor/executor_create_pipes.c @@ -0,0 +1,52 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* executor_create_pipes.c :+: :+: */ +/* +:+ */ +/* By: willem +#+ */ +/* +#+ */ +/* Created: 2025/02/12 21:25:22 by willem #+# #+# */ +/* Updated: 2025/02/26 16:10:19 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +/** + * @brief Creates pipes for the executor in the minishell. + * + * This function sets up the necessary pipes for inter-process communication + * within the minishell. It initializes the pipes based on the requirements + * of the minishell structure. + * + * @param minishell A pointer to the t_minishell structure containing the + * necessary information for pipe creation. + */ + +void executor_create_pipes(t_minishell *minishell) +{ + t_list *current; + t_command *command; + int fd[2]; + int fd_in; + const int n_fds = executor_count_fds(minishell); + + fd_in = 0; + current = minishell->commands; + while (current) + { + command = (t_command *)current->content; + if (current->next) + { + if (pipe(fd) == -1) + error_msg("pipe", "pipe creation failed"); + command->fd_out = fd[1]; + } + else + command->fd_out = 1; + command->fd_in = fd_in; + command->n_fds = n_fds; + fd_in = fd[0]; + current = current->next; + } +} diff --git a/src/executor/executor_create_redirects.c b/src/executor/executor_create_redirects.c new file mode 100644 index 0000000..eb8087b --- /dev/null +++ b/src/executor/executor_create_redirects.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* executor_create_redirects.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/21 13:00:00 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:10:35 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void executor_create_redirects(t_minishell *msh) +{ + t_list *current; + t_command *cmd; + + current = msh->commands; + while (current) + { + cmd = (t_command *)current->content; + cmd->fd_in = executor_open_fds(cmd->redirect_in, cmd->fd_in); + cmd->fd_out = executor_open_fds(cmd->redirect_out, cmd->fd_out); + current = current->next; + } +} diff --git a/src/executor/executor_execute_pipeline.c b/src/executor/executor_execute_pipeline.c new file mode 100644 index 0000000..166eece --- /dev/null +++ b/src/executor/executor_execute_pipeline.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* executor_execute_pipeline.c :+: :+: */ +/* +:+ */ +/* By: willem +#+ */ +/* +#+ */ +/* Created: 2025/02/12 21:25:02 by willem #+# #+# */ +/* Updated: 2025/02/26 17:42:46 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int executor_execute_pipeline(t_minishell *msh) +{ + t_list *current; + t_command *command; + pid_t last_pid; + int exit_status; + + executor_create_pipes(msh); + executor_create_redirects(msh); + current = msh->commands; + last_pid = 0; + while (current) + { + command = (t_command *)current->content; + command->environment = msh->environment; + last_pid = executor_fork(msh, command); + current = current->next; + } + waitpid(last_pid, &exit_status, 0); + msh->exit_status = ((exit_status) & 0xff00) >> 8; + signal_init_minishell(); + return (((exit_status) & 0xff00) >> 8); +} diff --git a/src/executor/executor_fork.c b/src/executor/executor_fork.c new file mode 100644 index 0000000..4b359e6 --- /dev/null +++ b/src/executor/executor_fork.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* executor_fork.c :+: :+: */ +/* +:+ */ +/* By: willem +#+ */ +/* +#+ */ +/* Created: 2025/02/12 21:24:52 by willem #+# #+# */ +/* Updated: 2025/02/26 17:44:36 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +//TODO should parent close the fds? +pid_t executor_fork(t_minishell *msh, t_command *command) +{ + pid_t pid; + + pid = fork(); + if (pid > 0) + { + if (command->fd_in != 0) + close(command->fd_in); + if (command->fd_out != 1) + close(command->fd_out); + signal_init_parent(); + } + else if (pid == 0) + { + signal_init_child(); + executor_child(msh, command); + exit(127); + } + else + error_msg("minishell", "fork failed"); + return (pid); +} diff --git a/src/executor/executor_open_fds.c b/src/executor/executor_open_fds.c new file mode 100644 index 0000000..ace0aa4 --- /dev/null +++ b/src/executor/executor_open_fds.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* executor_open_fds.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/21 12:50:42 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:21:56 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int executor_open_fds(t_list *redirect_list, int og_fd) +{ + t_redirect *redirect; + int fd; + + fd = og_fd; + while (redirect_list) + { + redirect = (t_redirect *)redirect_list->content; + if (redirect->type == T_REDIRECT_IN) + fd = open(redirect->value, O_RDONLY); + else if (redirect->type == T_REDIRECT_OUT) + fd = open(redirect->value, O_WRONLY | O_CREAT | O_TRUNC, 0644); + else if (redirect->type == T_APPEND_OUT) + fd = open(redirect->value, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (fd < 0) + { + error_msg("executor_open_fds", "can't open file"); + return (og_fd); + } + redirect_list = redirect_list->next; + } + return (fd); +} diff --git a/src/expander/expander_allocate_memory.c b/src/expander/expander_allocate_memory.c new file mode 100644 index 0000000..bd92a16 --- /dev/null +++ b/src/expander/expander_allocate_memory.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expander_allocate_memory.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/19 13:57:19 by qmennen #+# #+# */ +/* Updated: 2025/02/26 18:05:17 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +char *expander_allocate_memory( + t_minishell *msh, + const char *s, + t_list *variables) +{ + int size; + t_list *current; + t_environment *env; + char *string; + + size = 1; + current = variables; + while (current) + { + if (current->content == NULL) + { + current = current->next; + continue ; + } + env = (t_environment *)current->content; + size += (ft_strlen(env->value) - ft_strlen(env->name)); + current = current->next; + } + size += ft_strlen(s); + string = malloc_safe(msh, size); + string[0] = 0; + return (string); +} diff --git a/src/expander/expander_expand_dollar.c b/src/expander/expander_expand_dollar.c new file mode 100644 index 0000000..1bf29a9 --- /dev/null +++ b/src/expander/expander_expand_dollar.c @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expander_expand_dollar.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/19 15:05:58 by qmennen #+# #+# */ +/* Updated: 2025/02/19 15:22:40 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static int get_var_len(const char *source) +{ + int i; + + i = 1; + while (expander_character_valid(source[i])) + i++; + return (i); +} + +int expander_expand_dollar(char *src, char *dest, int *j, t_list *variables) +{ + int i; + int v_len; + t_environment *env; + + i = 0; + v_len = 0; + if (variables && variables->content) + { + env = (t_environment *)variables->content; + v_len = ft_strlen(env->name); + while (env->value[i]) + { + dest[(*j)++] = env->value[i++]; + } + } + else + { + v_len = get_var_len(src); + } + return (v_len); +} diff --git a/src/expander/expander_get_variable.c b/src/expander/expander_get_variable.c new file mode 100644 index 0000000..79ff55c --- /dev/null +++ b/src/expander/expander_get_variable.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* expander_get_variable.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/19 13:59:03 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:12:29 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +t_environment *expander_get_var(const char *s, int idx, t_minishell *msh) +{ + int i; + t_environment *env; + char *name; + + i = 0; + while (expander_character_valid(s[idx + i])) + i++; + name = ft_substr_safe(msh, s, idx, i); + if (!name || !*name) + return (NULL); + env = environment_get(msh, name); + free_safe(msh, (void **)&name); + return (env); +} diff --git a/src/expander/expander_is_character.c b/src/expander/expander_is_character.c new file mode 100644 index 0000000..161a0c8 --- /dev/null +++ b/src/expander/expander_is_character.c @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expander_is_character.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/19 13:15:11 by qmennen #+# #+# */ +/* Updated: 2025/02/19 13:15:55 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int expander_character_valid(const char c) +{ + return (ft_isalnum(c) || c == '_'); +} diff --git a/src/expander/expander_parse_string.c b/src/expander/expander_parse_string.c new file mode 100644 index 0000000..1b2d213 --- /dev/null +++ b/src/expander/expander_parse_string.c @@ -0,0 +1,57 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* expander_parse_string.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/18 19:00:35 by qmennen #+# #+# */ +/* Updated: 2025/02/26 22:56:05 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static void free_variables(t_minishell *msh, t_list *variables) +{ + t_list *current; + t_list *last; + + current = variables; + while (current) + { + last = current; + current = current->next; + free_safe(msh, (void **)&last); + } +} + +//TODO: Figure out why echo "> echo "\as"" breaks +char *expander_parse_string(char *s, t_minishell *msh) +{ + t_list *variables; + t_list *current; + char *string; + int i; + int j; + + variables = expander_parse_variables(s, msh); + string = expander_allocate_memory(msh, s, variables); + current = variables; + i = 0; + j = 0; + while (s[i]) + { + if (s[i] == '$' && s[i + 1] && current) + { + i++; + i += expander_expand_dollar(s + i, string, &j, current); + current = current->next; + } + else + string[j++] = s[i++]; + } + string[j] = 0; + free_variables(msh, variables); + return (string); +} diff --git a/src/expander/expander_parse_variables.c b/src/expander/expander_parse_variables.c new file mode 100644 index 0000000..7bb70b6 --- /dev/null +++ b/src/expander/expander_parse_variables.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* expander_parse_variables.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/19 13:58:13 by qmennen #+# #+# */ +/* Updated: 2025/02/26 17:41:14 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static char *ft_itoa_safe(t_minishell *msh, int n) +{ + char *str; + + str = ft_itoa(n); + check_malloc(msh, str); + return (str); +} + +static t_list *create_exit_status_env(t_minishell *msh) +{ + t_environment *env; + + env = malloc_safe(msh, sizeof(t_environment)); + env->name = ft_strdup_safe(msh, "?"); + env->value = ft_itoa_safe(msh, msh->exit_status); + return (ft_lstnew_safe(msh, env)); +} + +t_list *expander_parse_variables(const char *s, t_minishell *msh) +{ + int i; + t_list *var_list; + t_environment *env; + + i = 0; + var_list = NULL; + while (s[i]) + { + if (s[i] == '$') + { + env = expander_get_var(s, i + 1, msh); + if (env) + ft_lstadd_back(&var_list, ft_lstnew_safe(msh, env)); + else + { + if (s[i + 1] == '?') + ft_lstadd_back(&var_list, create_exit_status_env(msh)); + else + ft_lstadd_back(&var_list, ft_lstnew_safe(msh, NULL)); + } + } + i++; + } + return (var_list); +} diff --git a/src/lexer/lexer_new.c b/src/lexer/lexer_new.c index bbdc7c4..062d8c9 100644 --- a/src/lexer/lexer_new.c +++ b/src/lexer/lexer_new.c @@ -1,28 +1,25 @@ /* ************************************************************************** */ /* */ -/* ::: :::::::: */ -/* lexer_new.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: qmennen +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/05 19:03:01 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:08:41 by qmennen ### ########.fr */ +/* :::::::: */ +/* lexer_new.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/05 19:03:01 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:13:50 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -t_lexer *ft_lexer_new(const char *input) +t_lexer *ft_lexer_new(t_minishell *msh) { + char *input; t_lexer *lexer; - lexer = malloc(sizeof(t_lexer)); - if (!lexer) - { - perror("failed assigning lexer memory"); - exit(EXIT_FAILURE); - } - lexer->input = ft_strdup(input); + input = msh->line; + lexer = malloc_safe(msh, sizeof(t_lexer)); + lexer->input = ft_strdup_safe(msh, input); lexer->pos = 0; lexer->n_pos = 1; lexer->current_char = '\0'; diff --git a/src/lexer/lexer_parse_input.c b/src/lexer/lexer_parse_input.c index 861e4eb..1fd02a1 100644 --- a/src/lexer/lexer_parse_input.c +++ b/src/lexer/lexer_parse_input.c @@ -1,16 +1,17 @@ /* ************************************************************************** */ /* */ -/* ::: :::::::: */ -/* lexer_parse_input.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: qmennen +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/05 19:09:20 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:09:26 by qmennen ### ########.fr */ +/* :::::::: */ +/* lexer_parse_input.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/05 19:09:20 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:13:54 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" +//TODO: Check if unicode support is viable /** * @brief Parses the input from the lexer and returns a list of tokens. @@ -23,19 +24,21 @@ * the input to be parsed. * @return A linked list of tokens parsed from the input. */ -t_list *ft_parse_input(t_lexer *lexer) +t_list *ft_parse_input(t_minishell *msh) { t_list *list; t_token *token; + t_lexer *lexer; + lexer = msh->lexer; list = NULL; while (TRUE) { - token = ft_token_next(lexer); - if (token->type == T_EOF) + token = ft_token_next(msh, lexer); + if (token->type == T_EOF || token->type == T_ERROR) break ; - ft_lstadd_back(&list, ft_lstnew(token)); + ft_lstadd_back(&list, ft_lstnew_safe(msh, token)); } - ft_token_free(token); + ft_token_free(msh, token); return (list); } diff --git a/src/lexer/lexer_parse_quotes.c b/src/lexer/lexer_parse_quotes.c new file mode 100644 index 0000000..09010f9 --- /dev/null +++ b/src/lexer/lexer_parse_quotes.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* lexer_parse_quotes.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 19:02:37 by qmennen #+# #+# */ +/* Updated: 2025/02/27 19:26:35 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +char *lexer_parse_quotes(t_minishell *msh, t_lexer *lexer) +{ + int start; + int len; + char qc; + char *word; + + qc = lexer->current_char; + word = NULL; + lexer_readchar(lexer); + start = lexer->pos; + while (lexer->current_char != '\0' && lexer->current_char != qc) + lexer_readchar(lexer); + len = lexer->pos - start; + word = malloc_safe(msh, sizeof(char) * len + 1); + ft_strlcpy(word, lexer->input + start, len + 1); + if (lexer->current_char == qc) + lexer_readchar(lexer); + else + { + free_safe(msh, (void **)&word); + return (NULL); + } + return (word); +} diff --git a/src/lexer/lexer_read_char.c b/src/lexer/lexer_read_char.c index 6f62b34..4b67351 100644 --- a/src/lexer/lexer_read_char.c +++ b/src/lexer/lexer_read_char.c @@ -1,18 +1,18 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* lexer_readchar.c :+: :+: :+: */ +/* lexer_read_char.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/05 19:04:53 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:05:06 by qmennen ### ########.fr */ +/* Updated: 2025/02/18 17:02:17 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -void ft_lexer_readchar(t_lexer *lexer) +void lexer_readchar(t_lexer *lexer) { if ((size_t)lexer->n_pos > ft_strlen(lexer->input)) { diff --git a/src/lexer/lexer_read_word.c b/src/lexer/lexer_read_word.c index 2738be8..bb12c8d 100644 --- a/src/lexer/lexer_read_word.c +++ b/src/lexer/lexer_read_word.c @@ -6,58 +6,79 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/05 19:03:47 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:28:17 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 19:30:09 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static char *parse_quotes(t_lexer *lexer) +static int match_quotes(t_minishell *msh, t_lexer *lexer) { - int start; - int len; - char qc; - char *word; + char c; + int i; + int d_qts; + int s_qts; - qc = lexer->current_char; - word = NULL; - ft_lexer_readchar(lexer); - start = lexer->pos; - while (lexer->current_char != '\0' && lexer->current_char != qc) - ft_lexer_readchar(lexer); - len = lexer->pos - start; - word = malloc(sizeof(char) * len + 1); - ft_strlcpy(word, lexer->input + start, len + 1); - if (lexer->current_char == qc) - ft_lexer_readchar(lexer); - else + i = lexer->pos; + c = lexer->input[i]; + d_qts = 0; + s_qts = 0; + //TODO: Normalize this validation. Happens a lot + while (ft_isprint(c) && c != '<' && c != '>' && c != '|' && c != '\0' && !ft_isspace(c)) { - free(word); - return (NULL); + if (lexer->input[i] == '\'') + s_qts++; + if (lexer->input[i] == '\'') + d_qts++; + i++; + c = lexer->input[i]; } - return (word); + return ((s_qts % 2) == 0 && (d_qts % 2) == 0); } -char *ft_lexer_readword(t_lexer *lexer) +static int calculate_word_len(t_minishell *msh, t_lexer *lexer) +{ + int i; + int len; + + len = 1; + i = lexer->pos; + while (ft_isprint(lexer->input[i]) && lexer->input[i] != '<' && lexer->input[i]!= '>' && lexer->input[i] != '|' && lexer->input[i] != '\0' && !ft_isspace(lexer->input[i])) + { + if(lexer->input[i] != '\'' && lexer->input[i] != '"') + len++; + i++; + } + return (len); +} + +char *lexer_readword(t_minishell *msh, t_lexer *lexer) { int start; int len; char *word; + char c; start = lexer->pos; + if (lexer->current_char == '"' || lexer->current_char == '\'') { - return (parse_quotes(lexer)); + return (lexer_parse_quotes(msh, lexer)); + } - while (ft_isprint(lexer->current_char) && lexer->current_char != '<' - && lexer->current_char != '>' && lexer->current_char != '|' - && lexer->current_char != '\0' && !ft_isspace(lexer->current_char) - && lexer->current_char != '"' && lexer->current_char != '\'') + if (!match_quotes(msh, lexer)) + return (NULL); + len = calculate_word_len(msh, lexer); + word = malloc_safe(msh, sizeof(char) * len); + c = lexer->current_char; + len = 0; + while (ft_isprint(c) && c != '<' && c != '>' && c != '|' && c != '\0' && !ft_isspace(c)) { - ft_lexer_readchar(lexer); + if(c != '\'' && c != '"') + word[len++] = lexer->current_char; + lexer_readchar(lexer); + c = lexer->current_char; } - len = lexer->pos - start; - word = malloc(sizeof(char) * len + 1); - ft_strlcpy(word, lexer->input + start, len + 1); + word[len] = 0; return (word); } diff --git a/src/lexer/lexer_token_next.c b/src/lexer/lexer_token_next.c index aa57eae..12d571c 100644 --- a/src/lexer/lexer_token_next.c +++ b/src/lexer/lexer_token_next.c @@ -1,17 +1,42 @@ /* ************************************************************************** */ /* */ -/* ::: :::::::: */ -/* lexer_token_next.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: qmennen +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/04 16:07:58 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:25:35 by qmennen ### ########.fr */ +/* :::::::: */ +/* lexer_token_next.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/04 16:07:58 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:14:10 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" +static t_token_type get_word_type(char c) +{ + if (c == '\'') + return (T_SQWORD); + else if (c == '"') + return (T_DQWORD); + else + return (T_WORD); +} + +static t_token *process_word(t_minishell *msh, t_lexer *lexer, int pos) +{ + t_token_type word_type; + t_token *token; + char *word; + + word_type = get_word_type(lexer->current_char); + word = lexer_readword(msh, lexer); + if (!word) + return (token_new(msh, T_ERROR, &(lexer->current_char), pos)); + token = token_new(msh, word_type, word, pos); + free_safe(msh, (void **)&word); + return (token); +} + /** * @brief Retrieves the next token from the lexer. * @@ -31,30 +56,26 @@ * - If it is a printable character, reads the word and creates a word token. * - Otherwise, creates an error token. */ -t_token *ft_token_next(t_lexer *lexer) +t_token *ft_token_next(t_minishell *msh, t_lexer *lexer) { - t_token *token; - char *word; - int current_pos; + t_token *token; + int current_pos; + char c; token = NULL; while (ft_isspace(lexer->current_char)) - ft_lexer_readchar(lexer); + lexer_readchar(lexer); current_pos = lexer->pos; - if (lexer->current_char == '\0') - token = ft_token_new(T_EOF, NULL, current_pos); - else if (lexer->current_char == '<' || lexer->current_char == '>' - || lexer->current_char == '|') - token = ft_parse_token(lexer); + c = lexer->current_char; + if (c == '\0') + token = token_new(msh, T_EOF, NULL, current_pos); + else if (c == '<' || c == '>' + || c == '|') + token = token_parse(msh, lexer); else if (ft_isprint(lexer->current_char)) - { - word = ft_lexer_readword(lexer); - if (!word) - return (ft_token_new(T_ERROR, &lexer->current_char, current_pos)); - token = ft_token_new(T_WORD, word, current_pos); - free(word); - } + token = process_word(msh, lexer, current_pos); else - token = ft_token_new(T_ERROR, NULL, current_pos); + token = token_new(msh, T_ERROR, NULL, current_pos); + c = lexer->current_char; return (token); } diff --git a/src/main.c b/src/main.c index 5944a3f..515c243 100644 --- a/src/main.c +++ b/src/main.c @@ -1,48 +1,44 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* main.c :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/02/04 16:19:22 by whaffman #+# #+# */ -/* Updated: 2025/02/08 14:09:11 by willem ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#include "libft.h" -#include "minishell.h" -#include "utils.h" - -static void token_print(void *param) -{ - t_token *token; - - token = (t_token *)param; - printf("token type %i, value %s\n", token->type, token->value); -} - -int main(int argc, char **argv, char **envp) -{ - t_minishell *minishell; - - (void)argc; - (void)argv; - print_banner(); - ft_load_history(); - minishell = init_minishell(); - environment_parse(envp, &(minishell->environment)); - while (TRUE) - { - minishell->line = ft_prompt(minishell); - minishell->lexer = ft_lexer_new(minishell->line); - minishell->tokens = ft_parse_input(minishell->lexer); - ft_lstiter(minishell->tokens, token_print); - // minishell->commands = parser_get_commands(minishell->tokens); - simple_builtins(minishell); - free_minishell_line(minishell); - ft_lstclear(&minishell->commands, free_command_list); - } - free_minishell(minishell); - return (EXIT_SUCCESS); -} +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* main.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/04 16:19:22 by whaffman #+# #+# */ +/* Updated: 2025/02/19 17:59:24 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" +#include "minishell.h" +#include "utils.h" + +int main(int argc, char **argv, char **envp) +{ + t_minishell *msh; + + (void)argc; + (void)argv; + print_banner(); + history_load(); + msh = init_minishell(); + signal_init_minishell(); + environment_parse(msh, envp); + while (TRUE) + { + msh->line = ft_prompt(msh); + if (msh->line == NULL) + break ; + msh->lexer = ft_lexer_new(msh); + msh->tokens = ft_parse_input(msh); + ft_lstiter(msh->tokens, token_print); + msh->commands = parser_get_commands(msh); + simple_builtins(msh); + free_minishell_line(msh); + } + ft_lstclear_safe(msh, &msh->commands, free_command_list); + free_minishell(&msh); + rl_clear_history(); + return (EXIT_SUCCESS); +} diff --git a/src/parser/parser_alloc_command.c b/src/parser/parser_alloc_command.c new file mode 100644 index 0000000..fc49925 --- /dev/null +++ b/src/parser/parser_alloc_command.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* parser_new_command.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/11 16:18:21 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:14:31 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +t_command *parser_alloc_command(t_minishell *msh, char *cmd) +{ + t_command *command; + + command = malloc_safe(msh, sizeof(t_command)); + command->args = NULL; + command->fd_in = 0; + command->fd_out = 1; + command->redirect_in = NULL; + command->redirect_out = NULL; + command->environment = NULL; + command->n_fds = 0; + command->command = cmd; + return (command); +} diff --git a/src/parser/parser_create_command.c b/src/parser/parser_create_command.c new file mode 100644 index 0000000..723f860 --- /dev/null +++ b/src/parser/parser_create_command.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser_create_command.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 13:35:02 by qmennen #+# #+# */ +/* Updated: 2025/02/27 13:36:48 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void parser_create_command(t_minishell *msh, t_command *cmd, t_list **l_tkn) +{ + cmd->args = parser_get_arguments(*l_tkn, msh); + cmd->redirect_in = redirect_get_inputs(msh, *l_tkn); + cmd->redirect_out = redirect_get_outputs(msh, *l_tkn); +} diff --git a/src/parser/parser_get_arguments.c b/src/parser/parser_get_arguments.c index 8fa4fa8..1ce6230 100644 --- a/src/parser/parser_get_arguments.c +++ b/src/parser/parser_get_arguments.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/11 16:20:09 by qmennen #+# #+# */ -/* Updated: 2025/02/11 16:26:41 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 18:58:48 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,20 +16,45 @@ static int count_cmds(t_list *list) { int cmds; t_list *current; + t_token *token; cmds = 0; current = list; while (current) { - if (((t_token *)current->content)->type != T_WORD) + token = ((t_token *)current->content); + if (token->type >= 3) break ; cmds++; current = current->next; } - return (cmds - 1); + return (cmds); } -char **parser_get_arguments(t_list *list) +static int parser_should_expand(t_list *value) +{ + t_token *token; + int i; + + token = (t_token *)value->content; + if (!token) + return (0); + i = 0; + if (token->type == T_DQWORD) + { + while (token->value[i]) + { + if (token->value[i] == '$' && !expander_character_valid(token->value[i + 1])) + return (0); + i++; + } + return (1); + } + return ((token->type == T_WORD && token->value[0] == '$' + && token->value[1])); +} + +char **parser_get_arguments(t_list *list, t_minishell *msh) { t_list *current; char **args; @@ -37,18 +62,17 @@ char **parser_get_arguments(t_list *list) int i; cmds = count_cmds(list); - args = malloc((cmds + 1) * sizeof(char *)); - if (!args) - { - perror("malloc"); - exit(EXIT_FAILURE); - } - current = list->next; + args = malloc_safe(msh, (cmds + 1) * sizeof(char *)); + current = list; i = -1; while ((++i) < cmds && current) { - if (((t_token *)current->content)->type == T_WORD) - args[i] = ft_strdup(((t_token *)current->content)->value); + if (parser_should_expand(current)) + args[i] = expander_parse_string( + ((t_token *)current->content)->value, msh); + else if (((t_token *)current->content)->type < 3) + args[i] = ft_strdup_safe(msh, + ((t_token *)current->content)->value); current = current->next; } args[i] = 0; diff --git a/src/parser/parser_get_commands.c b/src/parser/parser_get_commands.c index 6e9fab9..31ec57d 100644 --- a/src/parser/parser_get_commands.c +++ b/src/parser/parser_get_commands.c @@ -6,30 +6,18 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/11 14:06:02 by qmennen #+# #+# */ -/* Updated: 2025/02/11 16:25:36 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 16:07:54 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static void print_cmds(void *content) +static int is_command_token(t_token *token) { - t_command *cmd; - int i; - - cmd = (t_command *)content; - printf("cmd: %s\n", cmd->command); - printf("args: "); - i = 0; - while (cmd->args[i]) - { - printf("%s ", cmd->args[i]); - i++; - } - printf("\n"); + return (token->type < 3 || redirect_token_type(token)); } -t_list *parser_get_commands(t_list *list) +t_list *parser_get_commands(t_minishell *msh) { t_list *command_list; t_list *current; @@ -37,20 +25,22 @@ t_list *parser_get_commands(t_list *list) t_token *token; command_list = NULL; - if (!list) + if (!msh->tokens) return (NULL); - current = list; + current = msh->tokens; while (current) { token = (t_token *) current->content; - command = parser_command_new(ft_strdup(token->value)); - command->args = parser_get_arguments(current); - ft_lstadd_back(&command_list, ft_lstnew(command)); - while (current && ((t_token *)current->content)->type == T_WORD) + command = parser_alloc_command(msh, ft_strdup_safe(msh, token->value)); + parser_create_command(msh, command, ¤t); + if (! parser_validate_command(command)) + break ; + ft_lstadd_back(&command_list, ft_lstnew_safe(msh, command)); + while (current && is_command_token((t_token *)current->content)) current = current->next; - if (current && ((t_token *)current->content)->type != T_WORD) + if (current && ((t_token *)current->content)->type >= 3) current = current->next; } - ft_lstiter(command_list, print_cmds); + ft_lstiter(command_list, print_commands); return (command_list); } diff --git a/src/parser/parser_validate_command.c b/src/parser/parser_validate_command.c new file mode 100644 index 0000000..e15e38d --- /dev/null +++ b/src/parser/parser_validate_command.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser_validate_command.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 16:06:33 by qmennen #+# #+# */ +/* Updated: 2025/02/27 16:08:49 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static int validate_redirects(t_list *lst) +{ + t_list *token; + + token = lst; + while (token) + { + if (((t_redirect *)token->content)->type == T_ERROR) + return (0); + token = token->next; + } + return (1); +} + +int parser_validate_command(t_command *command) +{ + int r_in; + int r_out; + + r_in = validate_redirects(command->redirect_in); + r_out = validate_redirects(command->redirect_out); + return (r_in && r_out); +} diff --git a/src/prompt/ft_load_history.c b/src/prompt/history_load.c similarity index 87% rename from src/prompt/ft_load_history.c rename to src/prompt/history_load.c index cd1816e..2094bec 100644 --- a/src/prompt/ft_load_history.c +++ b/src/prompt/history_load.c @@ -1,18 +1,18 @@ /* ************************************************************************** */ /* */ /* :::::::: */ -/* ft_load_history.c :+: :+: */ +/* history_load.c :+: :+: */ /* +:+ */ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/05 16:44:51 by whaffman #+# #+# */ -/* Updated: 2025/02/05 17:11:59 by whaffman ######## odam.nl */ +/* Updated: 2025/02/12 12:54:04 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void ft_load_history(void) +void history_load(void) { int fd; char *line; diff --git a/src/prompt/ft_write_history.c b/src/prompt/history_write.c similarity index 84% rename from src/prompt/ft_write_history.c rename to src/prompt/history_write.c index 38f9901..86caf61 100644 --- a/src/prompt/ft_write_history.c +++ b/src/prompt/history_write.c @@ -1,21 +1,22 @@ /* ************************************************************************** */ /* */ /* :::::::: */ -/* ft_write_history.c :+: :+: */ +/* history_write.c :+: :+: */ /* +:+ */ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/05 17:12:17 by whaffman #+# #+# */ -/* Updated: 2025/02/05 17:12:23 by whaffman ######## odam.nl */ +/* Updated: 2025/02/12 12:53:42 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void ft_write_history(char *line) +void history_write(char *line) { int fd; + add_history(line); fd = open(".minishell_history", O_WRONLY | O_APPEND | O_CREAT, 0644); if (fd < 0) return ; diff --git a/src/prompt/prompt.c b/src/prompt/prompt.c index 26a5fbe..45a5e2e 100644 --- a/src/prompt/prompt.c +++ b/src/prompt/prompt.c @@ -6,13 +6,13 @@ /* By: qmennen +#+ */ /* +#+ */ /* Created: 2025/02/04 16:13:08 by whaffman #+# #+# */ -/* Updated: 2025/02/11 16:06:17 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:15:04 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -char *get_user(t_list *environment) +char *get_user(t_minishell *msh) { const char guest[] = "guest"; int len; @@ -20,73 +20,94 @@ char *get_user(t_list *environment) char *username; char *result; - user = environment_get(environment, "USER"); + user = environment_get(msh, "USER"); if (user == NULL) username = (char *)guest; else username = user->value; - len = ft_strlen(username) + ft_strlen(PROMPT) + ft_strlen(GREEN) + 1; - result = (char *)malloc(len); - if (result == NULL) - { - perror("malloc"); - return (NULL); - } + len = ft_strlen(username) + ft_strlen(PROMPT GREEN) + 1; + result = (char *)malloc_safe(msh, len); ft_strlcpy(result, GREEN, ft_strlen(GREEN) + 1); ft_strlcat(result, username, ft_strlen(GREEN) + ft_strlen(username) + 1); ft_strlcat(result, PROMPT, len); return (result); } -char *get_path(t_list *environment) +int get_home_len(t_minishell *msh, char *cwd) { - char *home; - char *temp; - char *cwd; + t_environment *home; + int home_len; - cwd = getcwd(NULL, 0); - home = environment_get(environment, "HOME")->value; - if (cwd == NULL) - { - perror("getcwd"); - return (NULL); - } - if (home && ft_strncmp(cwd, home, ft_strlen(home)) == 0) - { - temp = ft_strjoin("~", cwd + ft_strlen(home)); - free(cwd); - cwd = temp; - } - temp = ft_strjoin(BLUE, cwd); - free(cwd); - cwd = ft_strjoin(temp, RESET); - free(temp); - return (cwd); + home = environment_get(msh, "HOME"); + home_len = 0; + if (home && !ft_strncmp(cwd, home->value, ft_strlen(home->value))) + home_len = ft_strlen(home->value) - 1; + return (home_len); } -char *ft_prompt(t_minishell *minishell) +char *get_path_with_home(t_minishell *msh) +{ + char *result; + char *cwd; + int len; + int home_len; + + cwd = getcwd(NULL, 0); + if (cwd == NULL) + return (perror("getcwd"), NULL); + home_len = get_home_len(msh, cwd); + len = ft_strlen(cwd) - home_len + 1; + result = malloc_safe(msh, len); + if (home_len) + { + ft_strlcpy(result, "~", 2); + ft_strlcat(result, cwd + home_len + 1, len); + } + else + ft_strlcpy(result, cwd, len); + free(cwd); + return (result); +} + +char *get_path(t_minishell *msh) +{ + char *result; + char *cwd; + int len; + + cwd = get_path_with_home(msh); + if (cwd == NULL) + return (NULL); + len = ft_strlen(cwd) + ft_strlen(BLUE RESET "> ") + 1; + result = malloc_safe(msh, len); + ft_strlcpy(result, BLUE, len); + ft_strlcat(result, cwd, len); + ft_strlcat(result, RESET "> ", len); + free_safe(msh, (void **) &cwd); + return (result); +} + +char *ft_prompt(t_minishell *msh) { char *line; char *cwd; char *prompt; char *user; - char *temp; - cwd = get_path(minishell->environment); + cwd = get_path(msh); if (cwd == NULL) return (NULL); - user = get_user(minishell->environment); - temp = ft_strjoin(user, cwd); - free(user); - free(cwd); - prompt = ft_strjoin(temp, "> "); - free(temp); + user = get_user(msh); + if (user == NULL) + return (free(cwd), NULL); + prompt = ft_strjoin_safe(msh, user, cwd); + free_safe(msh, (void **)&user); + free_safe(msh, (void **)&cwd); + rl_on_new_line(); line = readline(prompt); - free(prompt); - if (line != NULL) - { - add_history(line); - ft_write_history(line); - } + free_safe(msh, (void **)&prompt); + if (line == NULL) + return (NULL); + history_write(line); return (line); } diff --git a/src/redirect/redirect_get_inputs.c b/src/redirect/redirect_get_inputs.c new file mode 100644 index 0000000..75d0a10 --- /dev/null +++ b/src/redirect/redirect_get_inputs.c @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_get_inputs.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/23 12:29:05 by Quinten #+# #+# */ +/* Updated: 2025/02/27 18:09:15 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "redirect.h" + +static void check_heredoc(t_minishell *msh, t_list *current, t_token *token) +{ + if (token->type == T_HEREDOC && redirect_is_valid(current, token, -1)) + process_heredoc(msh, token, current->next->content); +} + +t_list *redirect_get_inputs(t_minishell *msh, t_list *list) +{ + t_list *current; + t_list *redirects; + t_token *token; + int flag; + + redirects = NULL; + current = list; + flag = 1; + token = (t_token *)current->content; + while (current && flag && !redirect_is_delimiter(token)) + { + token = (t_token *)current->content; + if (token->type != T_REDIRECT_IN && token->type != T_HEREDOC) + { + current = current->next; + continue ; + } + check_heredoc(msh, current, token); + flag = redirect_is_valid(current, token, F_OK | R_OK); + flag && (redirect_create(msh, ¤t, &redirects, token->type)); + current = current->next; + } + redirect_new_error(msh, &redirects, flag); + return (redirects); +} diff --git a/src/redirect/redirect_get_outputs.c b/src/redirect/redirect_get_outputs.c new file mode 100644 index 0000000..0ad2f2d --- /dev/null +++ b/src/redirect/redirect_get_outputs.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_get_outputs.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/23 12:37:24 by Quinten #+# #+# */ +/* Updated: 2025/02/27 18:12:04 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +t_list *redirect_get_outputs(t_minishell *msh, t_list *list) +{ + t_list *current; + t_list *redirects; + t_token *token; + int flag; + + flag = 1; + redirects = NULL; + current = list; + token = (t_token *)current->content; + while (current && !redirect_is_delimiter(token)) + { + token = (t_token *)current->content; + if (token->type != T_REDIRECT_OUT && token->type != T_APPEND_OUT) + { + current = current->next; + continue ; + } + flag = redirect_is_valid(current, token, -1); + flag && (redirect_create(msh, ¤t, &redirects, token->type)); + current = current->next; + } + redirect_new_error(msh, &redirects, flag); + return (redirects); +} diff --git a/src/redirect/redirect_new.c b/src/redirect/redirect_new.c new file mode 100644 index 0000000..79c0951 --- /dev/null +++ b/src/redirect/redirect_new.c @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_new.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/23 12:27:33 by Quinten #+# #+# */ +/* Updated: 2025/02/27 18:11:25 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +t_redirect *redirect_new(t_minishell *msh, t_token_type type, char *value) +{ + t_redirect *result; + + result = malloc_safe(msh, sizeof(t_redirect)); + result->type = type; + result->value = NULL; + if (value) + result->value = value; + return (result); +} + +int redirect_create(t_minishell *msh, t_list **tokens, t_list **redirects, +t_token_type type) +{ + t_list *new; + t_redirect *redir; + t_token *file_token; + char *file_name; + + file_token = (t_token *)((*tokens)->next->content); + file_name = NULL; + if (file_token) + file_name = ft_strdup_safe(msh, file_token->value); + redir = redirect_new(msh, type, file_name); + new = ft_lstnew_safe(msh, redir); + ft_lstadd_back(redirects, new); + if (tokens) + *tokens = (*tokens)->next; + return (1); +} diff --git a/src/parser/parser_new_command.c b/src/redirect/redirect_new_error.c similarity index 60% rename from src/parser/parser_new_command.c rename to src/redirect/redirect_new_error.c index d2780a7..24cf75c 100644 --- a/src/parser/parser_new_command.c +++ b/src/redirect/redirect_new_error.c @@ -1,30 +1,25 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* parser_new_command.c :+: :+: :+: */ +/* redirect_new_error.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/11 16:18:21 by qmennen #+# #+# */ -/* Updated: 2025/02/11 16:25:12 by qmennen ### ########.fr */ +/* Created: 2025/02/26 17:37:12 by qmennen #+# #+# */ +/* Updated: 2025/02/27 18:07:25 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -t_command *parser_command_new(char *cmd) +void redirect_new_error(t_minishell *msh, t_list **redirects, int flag) { - t_command *command; + t_list *new; + t_redirect *redir; - command = malloc(sizeof(t_command)); - if (!command) - { - perror("minishell malloc error"); - exit(EXIT_FAILURE); - } - command->args = NULL; - command->fd_in = 0; - command->fd_out = 1; - command->command = cmd; - return (command); + if (flag) + return ; + redir = redirect_new(msh, T_ERROR, NULL); + new = ft_lstnew_safe(msh, redir); + ft_lstadd_back(redirects, new); } diff --git a/src/redirect/redirect_process_heredoc.c b/src/redirect/redirect_process_heredoc.c new file mode 100644 index 0000000..d13aaab --- /dev/null +++ b/src/redirect/redirect_process_heredoc.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_process_heredoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/26 16:46:32 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:54:09 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +/** + * process_heredoc - Handles the processing of a heredoc in a minishell. + * @msh: Pointer to the minishell structure. + * @heredoc: Pointer to the token representing the heredoc. + * @delim: Pointer to the token representing the delimiter. + * + * This function reads lines from the standard input until a line matching + * the delimiter is encountered or an end-of-file (EOF) is reached. Each + * line is expanded and written to a temporary file named ".ms_heredoc". + * The function sets the type of the heredoc token to T_REDIRECT_IN and + * updates the delimiter token's value to the temporary file's name. + * + * Return: 1 on success, or a negative value on failure. + */ +int process_heredoc(t_minishell *msh, t_token *heredoc, t_token *delim) +{ + char *line; + char *expand; + const int fd = open(".ms_heredoc", O_WRONLY | O_CREAT | O_TRUNC, 0644); + + if (fd < 0) + { + error_msg("heredoc", "unable to write to temp file"); + return (fd); + } + while (TRUE) + { + line = readline(">"); + if ((*line && ft_strcmp(line, delim->value) == 0) || !line) + break ; + if (!*line) + ft_strlcat(line, "\n", 1); + expand = expander_parse_string(line, msh); + ft_putendl_fd(expand, fd); + free_safe(msh, (void **)&expand); + free(line); + } + close(fd); + heredoc->type = T_REDIRECT_IN; + delim->value = ft_strdup_safe(msh, ".ms_heredoc"); + return (free(line), 1); +} diff --git a/src/redirect/redirect_valid_type.c b/src/redirect/redirect_valid_type.c new file mode 100644 index 0000000..8d232d0 --- /dev/null +++ b/src/redirect/redirect_valid_type.c @@ -0,0 +1,49 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_valid_type.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/23 12:30:18 by Quinten #+# #+# */ +/* Updated: 2025/02/26 17:40:44 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int redirect_token_type(t_token *token) +{ + return (token->type == T_REDIRECT_IN + || token->type == T_HEREDOC + || token->type == T_REDIRECT_OUT + || token->type == T_APPEND_OUT); +} + +int redirect_is_valid(t_list *lst, t_token *token, int mode) +{ + t_token *next; + + if (!lst->next) + return (0); + next = (t_token *)lst->next->content; + if (!next) + { + return (0); + } + if (mode >= 0 && access(next->value, mode) != 0) + { + error_msg("minishell", "unable to write to temp file"); + return (0); + } + return (redirect_token_type(token) && next->type < 3); +} + +int redirect_is_delimiter(t_token *token) +{ + return (token->type == T_PIPE + || token->type == T_AND + || token->type == T_OR + || token->type == T_EOF + || token->type == T_ERROR); +} diff --git a/src/signal/signal.c b/src/signal/signal.c new file mode 100644 index 0000000..edc72ca --- /dev/null +++ b/src/signal/signal.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* signal.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/19 12:18:47 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:42:30 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void sigint_minishell_handler(int signum) +{ + (void)signum; + ft_putstr_fd("\n", 1); + rl_on_new_line(); + rl_replace_line("", 0); + rl_redisplay(); +} + +void sigint_heredoc_handler(int signum) +{ + (void)signum; + ft_putstr_fd("\n", 1); + rl_on_new_line(); + rl_replace_line("", 0); + exit(130); +} + +void sig_parent_handler(int signum) +{ + (void)signum; + ft_putstr_fd("\n", 1); +} diff --git a/src/signal/signal_init.c.c b/src/signal/signal_init.c.c new file mode 100644 index 0000000..0f5133c --- /dev/null +++ b/src/signal/signal_init.c.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* signal_init.c.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/26 15:39:01 by whaffman #+# #+# */ +/* Updated: 2025/02/26 15:39:46 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void signal_init_minishell(void) +{ + signal(SIGINT, sigint_minishell_handler); + signal(SIGQUIT, SIG_IGN); +} + +void signal_init_parent(void) +{ + signal(SIGINT, sig_parent_handler); + signal(SIGQUIT, sig_parent_handler); +} + +void signal_init_child(void) +{ + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); +} + +void signal_init_heredoc(void) +{ + signal(SIGINT, sigint_heredoc_handler); + signal(SIGQUIT, SIG_IGN); +} diff --git a/src/token/token_char_convert.c b/src/token/token_char_convert.c new file mode 100644 index 0000000..fbfd1f5 --- /dev/null +++ b/src/token/token_char_convert.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* token_char_convert.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 18:25:34 by qmennen #+# #+# */ +/* Updated: 2025/02/27 18:28:13 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +# include "minishell.h" + +t_token_type token_char_convert(char c, int is_double) +{ + if (c == '<') + { + if (is_double) + return (T_HEREDOC); + return (T_REDIRECT_IN); + } + else if (c == '>') + { + if (is_double) + return (T_APPEND_OUT); + return (T_REDIRECT_OUT); + } + else if (c == '&' && is_double) + return (T_AND); + else if (c == '|') + { + if (is_double) + return (T_OR); + return (T_PIPE); + } + return (T_ERROR); +} diff --git a/src/token/token_new.c b/src/token/token_new.c index 6529b1b..24a7a4c 100644 --- a/src/token/token_new.c +++ b/src/token/token_new.c @@ -1,31 +1,26 @@ /* ************************************************************************** */ /* */ -/* ::: :::::::: */ -/* token_new.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: qmennen +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/05 19:10:49 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:11:32 by qmennen ### ########.fr */ +/* :::::::: */ +/* token_new.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/05 19:10:49 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:15:17 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -t_token *ft_token_new(t_token_type type, char *c, int pos) +t_token *token_new(t_minishell *msh, t_token_type type, char *c, int pos) { t_token *token; - token = malloc(sizeof(t_token)); - if (!token) - { - perror("failed assigning token memory"); - exit(EXIT_FAILURE); - } + token = malloc_safe(msh, sizeof(t_token)); token->type = type; token->position = pos; if (c) - token->value = ft_strdup(c); + token->value = ft_strdup_safe(msh, c); else token->value = NULL; return (token); diff --git a/src/token/token_parse.c b/src/token/token_parse.c index 5ce93aa..5974479 100644 --- a/src/token/token_parse.c +++ b/src/token/token_parse.c @@ -6,39 +6,25 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/05 19:10:17 by qmennen #+# #+# */ -/* Updated: 2025/02/11 17:38:51 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 18:27:40 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -t_token *ft_parse_token(t_lexer *lexer) +t_token *token_parse(t_minishell *msh, t_lexer *lexer) { - t_token *token; + int is_double; + char c; + t_token *token; + t_token_type type; - token = NULL; - if (lexer->current_char == '|') - { - token = ft_token_new(T_PIPE, "|", lexer->pos); - } - else if (lexer->current_char == '<' && lexer->input[lexer->pos + 1] == '<') - { - token = ft_token_new(T_HEREDOC, "<<", lexer->pos); - ft_lexer_readchar(lexer); - } - else if (lexer->current_char == '<') - { - token = ft_token_new(T_REDIRECT_IN, "<", lexer->pos); - } - else if (lexer->current_char == '>' && lexer->input[lexer->pos + 1] == '>') - { - token = ft_token_new(T_APPEND_OUT, ">>", lexer->pos); - ft_lexer_readchar(lexer); - } - else if (lexer->current_char == '>') - { - token = ft_token_new(T_REDIRECT_OUT, ">", lexer->pos); - } - ft_lexer_readchar(lexer); + c = lexer->current_char; + is_double = lexer->input[lexer->pos + 1] == c; + type = token_char_convert(c, is_double); + token = token_new(msh, type, token_type_convert(type), lexer->pos); + if (is_double) + lexer_readchar(lexer); + lexer_readchar(lexer); return (token); } diff --git a/src/token/token_type_convert.c b/src/token/token_type_convert.c new file mode 100644 index 0000000..c42e681 --- /dev/null +++ b/src/token/token_type_convert.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* token_type_convert.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 18:25:34 by qmennen #+# #+# */ +/* Updated: 2025/02/27 18:26:40 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +# include "minishell.h" + +char *token_type_convert(t_token_type type) +{ + if (type == T_HEREDOC) + return ("<<"); + else if (type == T_REDIRECT_IN) + return ("<"); + else if (type == T_APPEND_OUT) + return (">>"); + else if (type == T_REDIRECT_OUT) + return (">"); + else if (type == T_AND) + return ("&&"); + else if (type == T_OR) + return ("||"); + else if (type == T_PIPE) + return ("|"); + return (NULL); +} diff --git a/src/utils/check_malloc.c b/src/utils/check_malloc.c new file mode 100644 index 0000000..eaa1504 --- /dev/null +++ b/src/utils/check_malloc.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* check_malloc.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 18:00:10 by whaffman #+# #+# */ +/* Updated: 2025/02/20 18:01:08 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void check_malloc(t_minishell *msh, void *ptr) +{ + t_list *new; + + if (ptr == NULL) + { + error_msg("malloc", "can't allocate memory"); + ft_lstclear(&(msh->freelist), free); + exit(1); + } + else + { + new = ft_lstnew(ptr); + if (new == NULL) + { + error_msg("malloc", "can't allocate memory"); + ft_lstclear(&(msh->freelist), free); + exit(1); + } + else + ft_lstadd_front(&(msh->freelist), new); + } +} diff --git a/src/utils/error_msg.c b/src/utils/error_msg.c new file mode 100644 index 0000000..2ce1ed1 --- /dev/null +++ b/src/utils/error_msg.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* error_msg.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 17:03:13 by whaffman #+# #+# */ +/* Updated: 2025/02/20 17:59:36 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void error_msg(char *func, char *msg) +{ + if (errno) + perror(RED BOLD "minishell" RESET); + else + { + ft_putstr_fd(RED BOLD "minishell" RESET ": ", 2); + if (func != NULL) + { + ft_putstr_fd(func, 2); + ft_putstr_fd(": ", 2); + } + if (msg != NULL) + ft_putstr_fd(msg, 2); + else + ft_putstr_fd("general error", 2); + ft_putstr_fd("\n", 2); + } +} diff --git a/src/utils/free_command_list.c b/src/utils/free_command_list.c index 684f713..2ca7ce8 100644 --- a/src/utils/free_command_list.c +++ b/src/utils/free_command_list.c @@ -1,38 +1,62 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* free_command_list.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: qmennen +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/11 14:24:05 by qmennen #+# #+# */ -/* Updated: 2025/02/11 14:27:02 by qmennen ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -static void free_args(char **args) -{ - int i; - - i = 0; - while (args[i]) - { - free(args[i]); - i++; - } - free(args); -} - -void free_command_list(void *content) -{ - t_command *command; - - command = (t_command *)content; - if (command->command) - free(command->command); - if (command->args) - free_args(command->args); - free(command); -} +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* free_command_list.c :+: :+: */ +/* +:+ */ +/* By: marvin +#+ */ +/* +#+ */ +/* Created: 2025/02/11 14:24:05 by qmennen #+# #+# */ +/* Updated: 2025/02/23 12:40:17 by Quinten ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static void free_args(t_minishell *msh, char **args) +{ + int i; + + i = 0; + while (args[i]) + { + free_safe(msh, (void **)&args[i]); + i++; + } + free_safe(msh, (void **)&args); +} + +static void free_redirects(t_minishell *msh, t_list *lst) +{ + t_redirect *redir; + t_list *current; + t_list *last; + + current = lst; + while (current) + { + last = current; + redir = (t_redirect *)current->content; + if (redir && redir->value) + free_safe(msh, (void **)&redir->value); + if (redir) + free_safe(msh, (void **)&redir); + current = current->next; + free_safe(msh, (void **)&last); + } +} + +void free_command_list(t_minishell *msh, void *content) +{ + t_command *command; + + command = (t_command *)content; + if (command->command) + free_safe(msh, (void **)&(command->command)); + if (command->args) + free_args(msh, command->args); + if (command->redirect_in) + free_redirects(msh, command->redirect_in); + if (command->redirect_out) + free_redirects(msh, command->redirect_out); + free_safe(msh, (void **)&command); +} diff --git a/src/utils/free_freelist.c b/src/utils/free_freelist.c new file mode 100644 index 0000000..34f5048 --- /dev/null +++ b/src/utils/free_freelist.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* free_freelist.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/25 13:23:30 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:15:29 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void free_freelist(t_minishell *msh) +{ + t_list *freelist; + t_list *next; + + freelist = msh->freelist; + while (freelist) + { + next = freelist->next; + free(freelist->content); + free(freelist); + freelist = next; + } + msh->freelist = NULL; +} diff --git a/src/utils/free_lexer.c b/src/utils/free_lexer.c index d15f1dd..5c88980 100644 --- a/src/utils/free_lexer.c +++ b/src/utils/free_lexer.c @@ -1,20 +1,20 @@ /* ************************************************************************** */ /* */ -/* ::: :::::::: */ -/* free_lexer.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: qmennen +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/05 19:07:01 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:07:18 by qmennen ### ########.fr */ +/* :::::::: */ +/* free_lexer.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/05 19:07:01 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:15:31 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void ft_lexer_free(t_lexer *lexer) +void ft_lexer_free(t_minishell *msh, t_lexer *lexer) { if (lexer->input) - free(lexer->input); - free(lexer); + free_safe(msh, (void **)&(lexer->input)); + free_safe(msh, (void **)&lexer); } diff --git a/src/utils/free_minishell.c b/src/utils/free_minishell.c index 9bb5dc3..3044ee9 100644 --- a/src/utils/free_minishell.c +++ b/src/utils/free_minishell.c @@ -6,17 +6,15 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/05 16:03:57 by whaffman #+# #+# */ -/* Updated: 2025/02/11 15:36:24 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 16:15:42 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void free_minishell(t_minishell *minishell) +void free_minishell(t_minishell **msh) { - if (minishell->line) - free_minishell_line(minishell); - if (minishell->environment) - environment_free_list(&minishell->environment); - free(minishell); + free_freelist(*msh); + free(*msh); + *msh = NULL; } diff --git a/src/utils/free_minishell_line.c b/src/utils/free_minishell_line.c index 22487a9..92c88b0 100644 --- a/src/utils/free_minishell_line.c +++ b/src/utils/free_minishell_line.c @@ -1,25 +1,25 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* free_minishell_line.c :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/02/05 16:01:44 by whaffman #+# #+# */ -/* Updated: 2025/02/05 16:02:07 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* free_minishell_line.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/05 16:01:44 by whaffman #+# #+# */ +/* Updated: 2025/02/26 14:24:20 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -void free_minishell_line(t_minishell *minishell) +void free_minishell_line(t_minishell *msh) { - if (minishell->line) - free(minishell->line); - if (minishell->lexer) - ft_lexer_free(minishell->lexer); - if (minishell->tokens) - ft_lstclear(&minishell->tokens, ft_clear_tokenlist); - if (minishell->commands) - ft_lstclear(&minishell->commands, free_command_list); + if (msh->line) + free(msh->line); + if (msh->lexer) + ft_lexer_free(msh, msh->lexer); + if (msh->tokens) + ft_lstclear_safe(msh, &msh->tokens, ft_clear_tokenlist); + if (msh->commands) + ft_lstclear_safe(msh, &msh->commands, free_command_list); } diff --git a/src/utils/free_safe.c b/src/utils/free_safe.c new file mode 100644 index 0000000..58f5a48 --- /dev/null +++ b/src/utils/free_safe.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* free_safe.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/25 15:09:34 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:20:46 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void free_safe(t_minishell *msh, void **ptr) +{ + t_list *prev; + t_list *current; + + prev = NULL; + current = msh->freelist; + if (*ptr) + { + while (current) + { + if (current->content == *ptr) + { + if (prev) + prev->next = current->next; + else + msh->freelist = current->next; + free(*ptr); + free(current); + return ; + } + prev = current; + current = current->next; + } + error_msg("free_safe", "pointer not found in freelist"); + } + *ptr = NULL; +} diff --git a/src/utils/free_token.c b/src/utils/free_token.c index c641787..7c295f6 100644 --- a/src/utils/free_token.c +++ b/src/utils/free_token.c @@ -1,20 +1,20 @@ /* ************************************************************************** */ /* */ -/* ::: :::::::: */ -/* free_token.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: qmennen +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/05 19:07:45 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:07:54 by qmennen ### ########.fr */ +/* :::::::: */ +/* free_token.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/05 19:07:45 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:16:01 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void ft_token_free(t_token *token) +void ft_token_free(t_minishell *msh, t_token *token) { if (token->value) - free(token->value); - free(token); + free_safe(msh, (void **)&token->value); + free_safe(msh, (void **)&token); } diff --git a/src/utils/free_token_list.c b/src/utils/free_token_list.c index db06843..0e7b501 100644 --- a/src/utils/free_token_list.c +++ b/src/utils/free_token_list.c @@ -1,21 +1,21 @@ /* ************************************************************************** */ /* */ -/* ::: :::::::: */ -/* free_token_list.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: qmennen +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/02/05 19:08:14 by qmennen #+# #+# */ -/* Updated: 2025/02/05 19:08:31 by qmennen ### ########.fr */ +/* :::::::: */ +/* free_token_list.c :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/05 19:08:14 by qmennen #+# #+# */ +/* Updated: 2025/02/26 16:15:58 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #include "minishell.h" -void ft_clear_tokenlist(void *content) +void ft_clear_tokenlist(t_minishell *msh, void *content) { t_token *token; token = (t_token *)content; - ft_token_free(token); + ft_token_free(msh, token); } diff --git a/src/utils/ft_lstclear_safe.c b/src/utils/ft_lstclear_safe.c new file mode 100644 index 0000000..5aa5913 --- /dev/null +++ b/src/utils/ft_lstclear_safe.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* ft_lstclear_safe.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/25 16:21:16 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:16:21 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void ft_lstclear_safe(t_minishell *msh, t_list **lst, + void (*del)(t_minishell *msh, void *)) +{ + t_list *current; + t_list *next; + + current = *lst; + while (current) + { + next = current->next; + del(msh, current->content); + free_safe(msh, (void **)¤t); + current = next; + } + *lst = NULL; +} diff --git a/src/utils/ft_lstnew_safe.c b/src/utils/ft_lstnew_safe.c new file mode 100644 index 0000000..f83d6b6 --- /dev/null +++ b/src/utils/ft_lstnew_safe.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* ft_lstnew_safe.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/25 16:47:09 by whaffman #+# #+# */ +/* Updated: 2025/02/26 16:16:29 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +t_list *ft_lstnew_safe(t_minishell *msh, void *content) +{ + t_list *new; + + new = malloc_safe(msh, sizeof(t_list)); + new->content = content; + new->next = NULL; + return (new); +} diff --git a/src/utils/ft_strdup_safe.c b/src/utils/ft_strdup_safe.c new file mode 100644 index 0000000..99bbf95 --- /dev/null +++ b/src/utils/ft_strdup_safe.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* ft_strdup_safe.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 18:01:27 by whaffman #+# #+# */ +/* Updated: 2025/02/20 18:04:53 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +char *ft_strdup_safe(t_minishell *msh, const char *str) +{ + char *new_str; + + new_str = ft_strdup(str); + check_malloc(msh, new_str); + return (new_str); +} diff --git a/src/utils/ft_strjoin_safe.c b/src/utils/ft_strjoin_safe.c new file mode 100644 index 0000000..cae7585 --- /dev/null +++ b/src/utils/ft_strjoin_safe.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* ft_strjoin_safe.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 18:02:31 by whaffman #+# #+# */ +/* Updated: 2025/02/20 18:04:23 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +char *ft_strjoin_safe(t_minishell *msh, const char *s1, const char *s2) +{ + char *new_str; + + new_str = ft_strjoin(s1, s2); + check_malloc(msh, new_str); + return (new_str); +} diff --git a/src/utils/ft_substr_safe.c b/src/utils/ft_substr_safe.c new file mode 100644 index 0000000..2c50548 --- /dev/null +++ b/src/utils/ft_substr_safe.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* ft_strdup_safe.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 18:01:27 by whaffman #+# #+# */ +/* Updated: 2025/02/20 18:04:53 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +char *ft_substr_safe(t_minishell *minishell, const char *str, + unsigned int start, size_t len) +{ + char *new_str; + + new_str = ft_substr(str, start, len); + check_malloc(minishell, new_str); + return (new_str); +} diff --git a/src/utils/init_minishell.c b/src/utils/init_minishell.c index 75a24b9..016be86 100644 --- a/src/utils/init_minishell.c +++ b/src/utils/init_minishell.c @@ -6,7 +6,7 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/05 16:03:03 by whaffman #+# #+# */ -/* Updated: 2025/02/05 16:03:15 by whaffman ######## odam.nl */ +/* Updated: 2025/02/26 17:39:41 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -14,18 +14,20 @@ t_minishell *init_minishell(void) { - t_minishell *minishell; + t_minishell *msh; - minishell = malloc(sizeof(t_minishell)); - if (!minishell) + msh = malloc(sizeof(t_minishell)); + if (!msh) { - perror("failed assigning minishell memory"); + perror("failed assigning msh memory"); exit(EXIT_FAILURE); } - minishell->environment = NULL; - minishell->line = NULL; - minishell->lexer = NULL; - minishell->tokens = NULL; - minishell->commands = NULL; - return (minishell); + msh->environment = NULL; + msh->line = NULL; + msh->lexer = NULL; + msh->tokens = NULL; + msh->commands = NULL; + msh->freelist = NULL; + msh->exit_status = 0; + return (msh); } diff --git a/src/utils/malloc_safe.c b/src/utils/malloc_safe.c new file mode 100644 index 0000000..5485afd --- /dev/null +++ b/src/utils/malloc_safe.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* malloc_safe.c :+: :+: */ +/* +:+ */ +/* By: whaffman +#+ */ +/* +#+ */ +/* Created: 2025/02/20 18:06:46 by whaffman #+# #+# */ +/* Updated: 2025/02/20 18:07:00 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void *malloc_safe(t_minishell *msh, size_t size) +{ + void *ptr; + + ptr = malloc(size); + check_malloc(msh, ptr); + return (ptr); +} diff --git a/src/utils/print_banner.c b/src/utils/print_banner.c index 7914508..ba33208 100644 --- a/src/utils/print_banner.c +++ b/src/utils/print_banner.c @@ -6,7 +6,7 @@ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/02/05 16:04:44 by whaffman #+# #+# */ -/* Updated: 2025/02/05 16:05:07 by whaffman ######## odam.nl */ +/* Updated: 2025/02/25 17:27:28 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ @@ -15,7 +15,8 @@ void print_banner(void) { printf("%s\n", - "\033[2J\033[1;1H" GREEN + // "\033[2J\033[1;1H" GREEN + GREEN " • • ┓ ┓┓\n" " ┏┳┓┓┏┓┓┏┣┓┏┓┃┃\n" " ┛┗┗┗┛┗┗┛┛┗┗ ┗┗\n" diff --git a/src/utils/simple_builtins.c b/src/utils/simple_builtins.c deleted file mode 100644 index 11169fb..0000000 --- a/src/utils/simple_builtins.c +++ /dev/null @@ -1,112 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* simple_builtins.c :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/02/05 16:21:39 by whaffman #+# #+# */ -/* Updated: 2025/02/11 17:11:16 by whaffman ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -void builtin_export(t_minishell *minishell) -{ - t_list *tmp; - t_environment *env; - char **arr; - - tmp = minishell->tokens->next; - while (tmp != NULL) - { - arr = ft_split(((t_token *)tmp->content)->value, '='); - if (arr[1] == NULL) - { - ft_free_arr(arr); - tmp = tmp->next; - continue ; - } - env = environment_get(minishell->environment, arr[0]); - if (env != NULL) - { - free(env->value); - env->value = ft_strdup(arr[1]); - } - else - environment_add(&(minishell->environment), arr[0], arr[1]); - ft_free_arr(arr); - tmp = tmp->next; - } -} - -static int cmp_value(t_list *list, char *str) -{ - if (list != NULL - && ft_strncmp( - ((t_token *)list->content)->value, - str, - ft_strlen(str) + 1) == 0) - return (TRUE); - return (FALSE); -} - -void fork_execve(t_minishell *minishell, char *path, char **argv) -{ - pid_t pid; - int status; - - pid = fork(); - if (pid == 0) - { - execve(path, argv, environment_get_arr(minishell->environment)); - while (*argv != NULL) - printf("%s\n", *argv++); - printf("minishell->: %s: %s\n", path, strerror(errno)); - exit(EXIT_FAILURE); - } - else if (pid < 0) - { - printf("minishell: %s\n", strerror(errno)); - } - else - { - free(path); - ft_free_arr(argv); - waitpid(pid, &status, 0); - printf("exit status of pid(%d): %d\n", pid, (((status) & 0xff00) >> 8)); - } -} - -void simple_builtins(t_minishell *minishell) -{ - char *path; - - if (!minishell->tokens) - return ; - if (cmp_value(minishell->tokens, "clear")) - printf("\033[2J\033[1;1H"); - else if (cmp_value(minishell->tokens, "env")) - environment_print(minishell->environment); - else if (cmp_value(minishell->tokens, "exit")) - { - free_minishell(minishell); - exit(EXIT_SUCCESS); - } - else if (cmp_value(minishell->tokens, "export")) - builtin_export(minishell); - else if (cmp_value(minishell->tokens, "unset")) - environment_del(&(minishell->environment), ((t_token *)minishell->tokens->next->content)->value); - else - { - path = executor_absolute_path(minishell->environment, ((t_token *)minishell->tokens->content)->value); - if (path == NULL) - printf("minishell: %s: command not found\n", ((t_token *)minishell->tokens->content)->value); - else - { - printf("found excutable: %s\n", path); - fork_execve(minishell, path, ft_split(((t_token *)minishell->tokens->content)->value, ' ')); - } - } -}