minishell

This commit is contained in:
Ladebeze66 2023-12-12 17:32:54 +01:00
commit 196e143285
92 changed files with 4905 additions and 0 deletions

124
Makefile Executable file
View File

@ -0,0 +1,124 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# Makefile :+: :+: :+: #
# +:+ +:+ +:+ #
# By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2023/11/07 16:09:37 by fgras-ca #+# #+# #
# Updated: 2023/12/09 17:20:03 by fgras-ca ### ########.fr #
# #
# **************************************************************************** #
RST = \033[0m
GRAY = \033[0;90m
RED = \033[0;91m
GREEN = \033[0;92m
YELLOW = \033[0;93m
BLUE = \033[0;94m
MAGENTA = \033[0;95m
CYAN = \033[0;96m
WHITE = \033[0;97m
ORANGE = \033[38;5;214m
# Nom du binaire à produire
NAME = minishell
LIBFT = libft.a
# Liste des fichiers sources
SRCS = prompt/history.c \
prompt/prompt.c \
prompt/main.c \
utils/utils.c \
builtins/builtins.c \
extern/extern.c \
extern/extern_utils.c \
builtins/export.c \
builtins/export_utils.c \
builtins/echo.c \
builtins/unset.c \
builtins/env.c \
builtins/builtins_utils.c \
signal/ctrl.c \
tokenize/tokenize_symbol.c \
tokenize/tokenize_utils.c \
tokenize/tokenize.c \
prompt/init_shell.c \
parsing/parse_error.c \
parsing/redirection_utils.c \
parsing/variable_utils.c \
parsing/parse_utils.c \
parsing/herodoc.c \
parsing/variable.c \
command/command_array.c \
command/command_utils.c \
parsing/parse.c \
command/command.c \
tokenize/quotes.c \
parsing/parse_redirections.c \
parsing/redirection.c \
parsing/pipe_utils.c \
parsing/pipe.c \
parsing/tree.c \
builtins/export_env.c \
# Ajoutez ici les autres fichiers .c
SRC_DIR_LIBFT = libft/
SRC_LIBFT = $(addprefix $(SRC_DIR_LIBFT), $(LIBFT))
# Liste des fichiers objets correspondants aux fichiers sources
OBJS = $(SRCS:.c=.o)
# Compilateur
CC = gcc
# Flags de compilation
CFLAGS = -Wall -Wextra -Werror
# Règle par défaut
all: $(NAME)
# Règle pour créer le binaire
$(NAME): $(OBJS)
@echo "$(RED)Loading Libft...$(RST)"
@make -C libft
@echo "$(GREEN)Libft...Done. $(RST)"
@echo "$(RED)Compilation minishell... $(RST)"
@$(CC) $(CFLAGS) $(OBJS) $(SRC_LIBFT) -o $(NAME) -lreadline -g
@echo "$(GREEN)Compilation complete. $(ORANGE)Type "./minishell" for execute the program!!$(RST)"
@echo "\n$(RED)# Ⓛⓐⓓⓔⓑⓔⓩⓔ ⓐⓝⓓ Ⓒⓥⓤ #$(RST)\n"
# Règle pour créer les fichiers objets à partir des fichiers sources
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Règle pour nettoyer les fichiers objets
clean:
@echo "$(RED)Cleaning Libft... $(RST)"
@make -C libft clean
@echo "$(GREEN)Libft cleaned!! $(RST)"
@echo "$(RED)Deleating files objects... $(RST)"
rm -f $(OBJS)
@echo "$(GREEN)files deleted!! $(RST)"
@echo "\n$(RED)# Ⓛⓐⓓⓔⓑⓔⓩⓔ ⓐⓝⓓ Ⓒⓥⓤ #$(RST)\n"
# Règle pour nettoyer les fichiers objets et le binaire
fclean: clean
@echo "$(RED)fclean Libft... $(RST)"
@make -C libft fclean
@echo "$(GREEN)Libft cleaned!! $(RST)"
@echo "$(RED)Delete program name... $(RST)"
rm -f $(NAME)
@echo "$(GREEN)File program deleted!! $(RST)"
@echo "\n$(RED)# Ⓛⓐⓓⓔⓑⓔⓩⓔ ⓐⓝⓓ Ⓒⓥⓤ #$(RST)\n"
# Règle pour recompiler le projet entièrement
re: fclean all
# Règle pour exécuter les tests
test: re
./$(NAME)
# Empêcher make d'être confus avec un fichier nommé comme une règle
.PHONY: all clean fclean re test

116
builtins/builtins.c Executable file
View File

@ -0,0 +1,116 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* builtins.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/12 11:51:11 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 14:06:48 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
int builtin_cd(char **args, t_minishell *shell)
{
(void)shell;
if (args[1] == NULL)
{
write(2, RED"minishell: expected argument to \"cd\"\n"RST, 44);
}
else
{
if (chdir(args[1]) != 0)
{
perror(RED"minishell"RST);
}
}
return (0);
}
int builtin_exit(char **args, t_minishell *shell)
{
long exit_code;
char *endptr;
char *error_message;
(void)shell;
if (args[1])
{
errno = 0;
exit_code = strtol(args[1], &endptr, 10);
if ((errno == ERANGE && (exit_code == LONG_MAX
|| exit_code == LONG_MIN)) || (errno != 0 && exit_code == 0)
|| (*endptr != '\0')
|| (exit_code < 0 || exit_code > 255))
{
error_message = "bash: exit: ";
write(STDERR_FILENO, error_message, strlen(error_message));
write(STDERR_FILENO, args[1], strlen(args[1]));
error_message = ": numeric argument required\n";
write(STDERR_FILENO, error_message, strlen(error_message));
return (1);
}
exit((int)exit_code);
}
exit(0);
}
int builtin_pwd(char **args, t_minishell *shell)
{
char cwd[1024];
(void)shell;
(void)args;
if (getcwd(cwd, sizeof(cwd)) != NULL)
{
printf("%s\n", cwd);
}
else
{
perror(RED"minishell"RST);
}
return (0);
}
int num_builtins(t_minishell *shell)
{
int count;
count = 0;
while (shell->builtin_str[count])
{
count++;
}
return (count);
}
int execute_builtin(char **args, t_minishell *shell)
{
int i;
int exit_status;
if (!args || !shell || !shell->builtin_str || !shell->builtin_func)
return (-1);
if (!args[0])
{
write(2, RED"Command not found: No such file or directory\n", 52);
return (-1);
}
i = 0;
while (i < num_builtins(shell))
{
if (shell->builtin_str[i] && ft_strcmp(args[0],
shell->builtin_str[i]) == 0)
{
if (shell->builtin_func[i])
{
exit_status = (*shell->builtin_func[i])(args, shell);
return (exit_status);
}
}
i++;
}
return (-1);
}

48
builtins/builtins_utils.c Executable file
View File

@ -0,0 +1,48 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* builtins_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/27 20:33:11 by fgras-ca #+# #+# */
/* Updated: 2023/12/08 23:02:49 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
char *extract_name(char *env_entry)
{
int len;
char *name;
len = 0;
while (env_entry[len] && env_entry[len] != '=')
len++;
name = malloc(len + 1);
if (!name)
return (NULL);
ft_strncpy(name, env_entry, len);
name[len] = '\0';
return (name);
}
char *extract_value(char *env_entry)
{
int i;
char *value;
i = 0;
while (env_entry[i] && env_entry[i] != '=')
i++;
if (!env_entry[i])
return (NULL);
value = ft_strdup(&env_entry[i + 1]);
return (value);
}
int builtin_echo_wrapper(char **args, t_minishell *shell)
{
return (builtin_echo(args, shell, STDOUT_FILENO));
}

58
builtins/echo.c Executable file
View File

@ -0,0 +1,58 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* echo.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/11 18:27:30 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 18:57:20 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static int check_option(char *s)
{
int i;
i = 1;
if (s[0] != '-')
return (0);
while (s[i])
{
if (s[i] != 'n')
return (0);
i++;
}
return (1);
}
int builtin_echo(char **args, t_minishell *shell, int fd)
{
int i;
int newline;
char *output;
i = 1;
newline = 1;
(void)shell;
if (args[i] != NULL && check_option(args[i]))
{
newline = 0;
i++;
}
while (args[i] != NULL)
{
output = args[i];
write(fd, output, ft_strlen(output));
if (args[i + 1] != NULL)
{
write(fd, " ", 1);
}
i++;
}
if (newline)
write(fd, "\n", 1);
return (0);
}

29
builtins/env.c Executable file
View File

@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* env.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/15 17:36:35 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 12:10:09 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
int builtin_env(char **args, t_minishell *shell)
{
int i;
char *env_var;
(void)args;
i = 0;
while (shell->environ[i])
{
env_var = shell->environ[i];
printf("%s\n", env_var);
i++;
}
return (0);
}

65
builtins/export.c Executable file
View File

@ -0,0 +1,65 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* export.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/11 18:20:32 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 12:11:19 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static void print_env(char **env, int env_size)
{
int i;
char *name;
char *value;
i = 0;
while (i < env_size)
{
name = extract_name(env[i]);
value = extract_value(env[i]);
if (value)
{
printf("declare -x %s=\"%s\"\n", name, value);
free(value);
}
else
{
printf("declare -x %s\n", name);
}
free(name);
i++;
}
}
static void print_sorted_env(t_minishell *shell)
{
int env_size;
char **sorted_env;
env_size = count_env_vars(shell->environ);
sorted_env = copy_env(shell->environ, env_size);
if (!sorted_env)
return ;
sort_env(sorted_env, env_size);
print_env(sorted_env, env_size);
free(sorted_env);
}
int builtin_export(char **args, t_minishell *shell)
{
if (args[1] == NULL)
{
print_sorted_env(shell);
return (0);
}
else
{
return (export_set_env(args, shell));
}
}

66
builtins/export_env.c Executable file
View File

@ -0,0 +1,66 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* export_env.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 10:49:41 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 12:19:27 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
int count_env_vars(char **environ)
{
int count;
count = 0;
while (environ[count])
count++;
return (count);
}
char **copy_env(char **environ, int env_size)
{
char **env_copy;
int i;
env_copy = malloc((env_size + 1) * sizeof(char *));
if (!env_copy)
return (NULL);
i = 0;
while (i < env_size)
{
env_copy[i] = environ[i];
i++;
}
env_copy[env_size] = NULL;
return (env_copy);
}
void sort_env(char **env, int env_size)
{
int sorted;
int i;
char *temp;
sorted = 0;
while (!sorted)
{
sorted = 1;
i = 0;
while (i < env_size - 1)
{
if (strcmp(env[i], env[i + 1]) > 0)
{
temp = env[i];
env[i] = env[i + 1];
env[i + 1] = temp;
sorted = 0;
}
i++;
}
}
}

102
builtins/export_utils.c Executable file
View File

@ -0,0 +1,102 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* export_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/15 18:26:09 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 15:01:53 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static char *create_env_entry(char **args)
{
char *new_env_entry;
char *name;
char *value;
name = ft_strtok(args[1], "=");
value = ft_strtok(NULL, "");
if (name == NULL || value == NULL)
{
write(2, RED"minishell: invalid format for export. "
"Use NAME=\"value\".\n"RST, 63);
return (NULL);
}
new_env_entry = malloc(strlen(name) + strlen(value) + 2);
if (!new_env_entry)
{
exit(EXIT_FAILURE);
}
ft_strcpy(new_env_entry, name);
ft_strcat(new_env_entry, "=");
ft_strcat(new_env_entry, value);
return (new_env_entry);
}
int add_new_env_entry(t_minishell *shell, char *new_env_entry)
{
int env_size;
size_t oldsize;
env_size = 0;
oldsize = 0;
while (shell->environ[env_size] != NULL)
{
env_size++;
}
oldsize = (env_size + 1) * sizeof(char *);
shell->environ = ft_reallocarray(shell->environ, env_size + 2,
sizeof(char *), oldsize);
if (!shell->environ)
{
perror(RED"minishell: error reallocating environment"RST);
free(new_env_entry);
return (1);
}
shell->environ[env_size] = new_env_entry;
shell->environ[env_size + 1] = NULL;
return (0);
}
int replace_env_entry(t_minishell *shell, char *new_env_entry)
{
int i;
size_t name_length;
i = 0;
name_length = ft_strchr(new_env_entry, '=') - new_env_entry;
while (shell->environ[i] != NULL)
{
if (ft_strncmp(shell->environ[i], new_env_entry, name_length) == 0)
{
free(shell->environ[i]);
shell->environ[i] = new_env_entry;
return (1);
}
i++;
}
return (0);
}
static int update_env(t_minishell *shell, char *new_env_entry)
{
if (replace_env_entry(shell, new_env_entry) == 0)
{
return (add_new_env_entry(shell, new_env_entry));
}
return (0);
}
int export_set_env(char **args, t_minishell *shell)
{
char *new_env_entry;
new_env_entry = create_env_entry(args);
if (new_env_entry == NULL)
return (0);
return (update_env(shell, new_env_entry));
}

42
builtins/unset.c Executable file
View File

@ -0,0 +1,42 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* unset.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/14 21:15:04 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 12:10:47 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
int builtin_unset(char **args, t_minishell *shell)
{
int i;
int j;
i = 0;
if (args[1] == NULL)
{
write(2, RED"minishell: expected argument to \"unset\"\n", 48);
return (1);
}
while (shell->environ[i] != NULL)
{
if (ft_strncmp(shell->environ[i], args[1], ft_strlen(args[1]))
== 0 && shell->environ[i][ft_strlen(args[1])] == '=')
{
j = i;
while (shell->environ[j] != NULL)
{
shell->environ[j] = shell->environ[j + 1];
j++;
}
break ;
}
i++;
}
return (0);
}

83
command/command.c Executable file
View File

@ -0,0 +1,83 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* command.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/29 21:21:23 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 18:55:48 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
int execute_builtin_and_free(char **args, t_minishell *shell, int fd)
{
int status;
if (ft_strcmp(args[0], "echo") == 0)
{
status = builtin_echo(args, shell, fd);
}
else
{
status = execute_builtin(args, shell);
}
free_args_array(args);
shell->last_exit_status = status;
return (status);
}
static int execute_external_and_free(char **args, t_minishell *shell)
{
pid_t pid;
int status;
status = 0;
pid = execute_external_command(args, shell->environ);
free_args_array(args);
if (pid > 0)
{
waitpid(pid, &status, WUNTRACED);
if (WIFEXITED(status))
{
shell->last_exit_status = WEXITSTATUS(status);
}
}
else
{
shell->last_exit_status = 127;
}
return (status);
}
static int process_command(t_command *command, t_minishell *shell, int fd)
{
char **args;
int status;
status = 0;
args = build_args_array(command);
if (args != NULL)
{
if (is_builtin_command(command->command, shell))
{
status = execute_builtin_and_free(args, shell, fd);
}
else
{
status = execute_external_and_free(args, shell);
}
}
return (status);
}
void execute_command(t_command *command, t_minishell *shell, int fd)
{
if (command == NULL || command->command == NULL)
{
return ;
}
process_command(command, shell, fd);
}

80
command/command_array.c Executable file
View File

@ -0,0 +1,80 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* command_array.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 11:26:25 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 18:56:21 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static char **allocate_args_array(t_command *command)
{
char **args;
args = malloc(sizeof(char *) * (command->arg_count + 2));
if (!args)
{
return (NULL);
}
return (args);
}
static int duplicate_command_arg(char **args, t_command *command, int i)
{
args[i + 1] = ft_strdup(command->args[i]);
if (!args[i + 1])
{
while (--i >= 0)
free(args[i + 1]);
free(args[0]);
free(args);
return (0);
}
return (1);
}
char **build_args_array(t_command *command)
{
char **args;
int i;
args = allocate_args_array(command);
if (!args)
return (NULL);
args[0] = ft_strdup(command->command);
if (!args[0])
{
free(args);
return (NULL);
}
i = 0;
while (i < command->arg_count)
{
if (!duplicate_command_arg(args, command, i))
return (NULL);
i++;
}
args[command->arg_count + 1] = NULL;
return (args);
}
void free_args_array(char **args)
{
int i;
i = 0;
if (args)
{
while (args[i] != NULL)
{
free(args[i]);
i++;
}
free(args);
}
}

83
command/command_utils.c Executable file
View File

@ -0,0 +1,83 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* command_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 11:03:59 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 12:21:17 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void free_command(t_command *command)
{
int i;
if (!command)
return ;
free(command->command);
if (command->args)
{
i = 0;
while (i < command->arg_count)
{
free(command->args[i]);
i++;
}
free(command->args);
}
}
void reset_command(t_command *command)
{
if (!command)
return ;
free_command(command);
command->command = NULL;
command->args = NULL;
command->arg_count = 0;
}
t_command *create_new_command(void)
{
t_command *new_command;
new_command = malloc(sizeof(t_command));
if (new_command == NULL)
return (NULL);
new_command->command = NULL;
new_command->args = NULL;
new_command->arg_count = 0;
return (new_command);
}
void add_token_to_command(t_command *command, char *token)
{
char **new_args;
char *new_token;
if (!token || *token == '\0' || !command)
return ;
new_token = ft_strdup(token);
if (!new_token)
return ;
if (command->command == NULL)
command->command = new_token;
else
{
new_args = ft_realloc(command->args,
sizeof(char *) * (command->arg_count + 2),
sizeof(char *) * command->arg_count);
if (!new_args)
{
free(new_token);
return ;
}
command->args = new_args;
command->args[command->arg_count++] = new_token;
command->args[command->arg_count] = NULL;
}
}

232
en.subject.pdf Normal file
View File

@ -0,0 +1,232 @@
Minishell
As beautiful as a shell
Summary:
This project is about creating a simple shell.
Yes, your own little bash.
You will learn a lot about processes and file descriptors.
Version: 7.1
Contents
I Introduction 2
II Common Instructions 3
III Mandatory part 5
IV Bonus part 8
V Submission and peer-evaluation 9
1
Chapter I
Introduction
The existence of shells is linked to the very existence of IT.
At the time, all developers agreed that communicating with a computer using aligned
1/0 switches was seriously irritating.
It was only logical that they came up with the idea of creating a software to com-
municate with a computer using interactive lines of commands in a language somewhat
close to the human language.
Thanks to Minishell, youll be able to travel through time and come back to problems
people faced when Windows didnt exist.
2
Chapter II
Common Instructions
• Your project must be written in C.
• Your project must be written in accordance with the Norm. If you have bonus
files/functions, they are included in the norm check and you will receive a 0 if there
is a norm error inside.
• Your functions should not quit unexpectedly (segmentation fault, bus error, double
free, etc) apart from undefined behaviors. If this happens, your project will be
considered non functional and will receive a 0 during the evaluation.
• All heap allocated memory space must be properly freed when necessary. No leaks
will be tolerated.
• If the subject requires it, you must submit a Makefile which will compile your
source files to the required output with the flags -Wall, -Wextra and -Werror, use
cc, and your Makefile must not relink.
• Your Makefile must at least contain the rules $(NAME), all, clean, fclean and
re.
• To turn in bonuses to your project, you must include a rule bonus to your Makefile,
which will add all the various headers, librairies or functions that are forbidden on
the main part of the project. Bonuses must be in a different file _bonus.{c/h} if
the subject does not specify anything else. Mandatory and bonus part evaluation
is done separately.
• If your project allows you to use your libft, you must copy its sources and its
associated Makefile in a libft folder with its associated Makefile. Your projects
Makefile must compile the library by using its Makefile, then compile the project.
• We encourage you to create test programs for your project even though this work
wont have to be submitted and wont be graded. It will give you a chance
to easily test your work and your peers work. You will find those tests especially
useful during your defence. Indeed, during defence, you are free to use your tests
and/or the tests of the peer you are evaluating.
• Submit your work to your assigned git repository. Only the work in the git reposi-
tory will be graded. If Deepthought is assigned to grade your work, it will be done
3
Minishell As beautiful as a shell
after your peer-evaluations. If an error happens in any section of your work during
Deepthoughts grading, the evaluation will stop.
4
Chapter III
Mandatory part
Program name minishell
Turn in files Makefile, *.h, *.c
Makefile NAME, all, clean, fclean, re
Arguments
External functs. readline, rl_clear_history, rl_on_new_line,
rl_replace_line, rl_redisplay, add_history,
Libft authorized printf, malloc, free, write, access, open, read,
Description close, fork, wait, waitpid, wait3, wait4, signal,
sigaction, sigemptyset, sigaddset, kill, exit,
getcwd, chdir, stat, lstat, fstat, unlink, execve,
dup, dup2, pipe, opendir, readdir, closedir,
strerror, perror, isatty, ttyname, ttyslot, ioctl,
getenv, tcsetattr, tcgetattr, tgetent, tgetflag,
tgetnum, tgetstr, tgoto, tputs
Yes
Write a shell
Your shell should:
• Display a prompt when waiting for a new command.
• Have a working history.
• Search and launch the right executable (based on the PATH variable or using a
relative or an absolute path).
• Avoid using more than one global variable to indicate a received signal. Consider
the implications: this approach ensures that your signal handler will not access your
main data structures.
Be careful. This global variable cannot provide any other
information or data access than the number of a received signal.
Therefore, using "norm" type structures in the global scope is
forbidden.
5
Minishell As beautiful as a shell
• Not interpret unclosed quotes or special characters which are not required by the
subject such as \ (backslash) or ; (semicolon).
• Handle (single quote) which should prevent the shell from interpreting the meta-
characters in the quoted sequence.
• Handle " (double quote) which should prevent the shell from interpreting the meta-
characters in the quoted sequence except for $ (dollar sign).
• Implement redirections:
◦ < should redirect input.
◦ > should redirect output.
◦ << should be given a delimiter, then read the input until a line containing the
delimiter is seen. However, it doesnt have to update the history!
◦ >> should redirect output in append mode.
• Implement pipes (| character). The output of each command in the pipeline is
connected to the input of the next command via a pipe.
• Handle environment variables ($ followed by a sequence of characters) which
should expand to their values.
• Handle $? which should expand to the exit status of the most recently executed
foreground pipeline.
• Handle ctrl-C, ctrl-D and ctrl-\ which should behave like in bash.
• In interactive mode:
◦ ctrl-C displays a new prompt on a new line.
◦ ctrl-D exits the shell.
◦ ctrl-\ does nothing.
• Your shell must implement the following builtins:
◦ echo with option -n
◦ cd with only a relative or absolute path
◦ pwd with no options
◦ export with no options
◦ unset with no options
◦ env with no options or arguments
◦ exit with no options
6
Minishell As beautiful as a shell
The readline() function can cause memory leaks. You dont have to fix them. But
that doesnt mean your own code, yes the code you wrote, can have memory
leaks.
You should limit yourself to the subject description. Anything that
is not asked is not required.
If you have any doubt about a requirement, take bash as a reference.
7
Chapter IV
Bonus part
Your program has to implement:
• && and || with parenthesis for priorities.
• Wildcards * should work for the current working directory.
The bonus part will only be assessed if the mandatory part is
PERFECT. Perfect means the mandatory part has been integrally done
and works without malfunctioning. If you have not passed ALL the
mandatory requirements, your bonus part will not be evaluated at all.
8
Chapter V
Submission and peer-evaluation
Turn in your assignment in your Git repository as usual. Only the work inside your
repository will be evaluated during the defense. Dont hesitate to double check the
names of your files to ensure they are correct.
M LQ* d z Ok v P
: )? e Q 6 u nk] R *
f *q lV - O , ?ZP
7 c 1V H
e 9 () 8
U
> D s / w
; E >M
q < >
zb H ( 3
l 6
X 0g E
9

56
extern/extern.c vendored Executable file
View File

@ -0,0 +1,56 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* extern.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/11 17:45:14 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 12:23:50 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
pid_t create_process(char *path, char **args, char **environ)
{
pid_t pid;
pid = fork();
if (pid == 0)
{
execve(path, args, environ);
perror(RED"Command execution failed"RST);
exit(EXIT_FAILURE);
}
else if (pid < 0)
{
perror(RED"Fork failed"RST);
}
return (pid);
}
pid_t execute_external_command(char **args, char **environ)
{
pid_t pid;
char *path;
pid = -1;
if (!args || !args[0])
return (-1);
path = find_executable(args[0], environ);
if (!path)
{
write(2, args[0], ft_strlen(args[0]));
write(2, ": ", 2);
perror(RED "Command not found" RST);
return (-1);
}
pid = create_process(path, args, environ);
if (pid < 0)
{
perror(RED"Fork failed"RST);
}
free(path);
return (pid);
}

87
extern/extern_utils.c vendored Executable file
View File

@ -0,0 +1,87 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* extern_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/27 19:48:07 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 12:24:31 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static char *check_relative_path(const char *cmd)
{
if (cmd == NULL)
return (NULL);
if (ft_strncmp(cmd, "./", 2) == 0
|| ft_strncmp(cmd, "../", 3) == 0 || cmd[0] == '/')
{
if (access(cmd, X_OK) == 0)
return (ft_strdup(cmd));
}
return (NULL);
}
static char *build_full_path(const char *token, const char *cmd)
{
char *temp;
if (cmd == NULL)
return (NULL);
temp = malloc(ft_strlen(token) + ft_strlen(cmd) + 2);
if (temp == NULL)
return (NULL);
ft_strcpy(temp, token);
ft_strcat(temp, "/");
ft_strcat(temp, cmd);
return (temp);
}
static char *search_path(char *path, const char *cmd)
{
char *path_copy;
char *token;
char *temp;
char *full_path;
if (cmd == NULL)
return (NULL);
full_path = NULL;
path_copy = ft_strdup(path);
token = ft_strtok(path_copy, ":");
while (token != NULL)
{
temp = build_full_path(token, cmd);
if (temp && access(temp, X_OK) == 0)
{
full_path = ft_strdup(temp);
free(temp);
break ;
}
free(temp);
token = ft_strtok(NULL, ":");
}
free(path_copy);
return (full_path);
}
char *find_executable(const char *cmd, char **environ)
{
char *path;
char *relative_path_check;
char *full_path;
if (cmd == NULL)
return (NULL);
relative_path_check = check_relative_path(cmd);
if (relative_path_check != NULL)
return (relative_path_check);
path = get_env_value("PATH", environ);
if (!path || ft_strlen(path) == 0)
return (NULL);
full_path = search_path(path, cmd);
return (full_path);
}

111
libft/Makefile Executable file
View File

@ -0,0 +1,111 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# Makefile :+: :+: :+: #
# +:+ +:+ +:+ #
# By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2023/02/06 12:19:21 by fgras-ca #+# #+# #
# Updated: 2023/12/07 11:25:50 by fgras-ca ### ########.fr #
# #
# **************************************************************************** #
RST = \033[0m
GRAY = \033[0;90m
RED = \033[0;91m
GREEN = \033[0;92m
YELLOW = \033[0;93m
BLUE = \033[0;94m
MAGENTA = \033[0;95m
CYAN = \033[0;96m
WHITE = \033[0;97m
ORANGE = \033[38;5;214m
NAME = libft.a
SOURCES = ft_atoi.c \
ft_isalpha.c \
ft_memchr.c \
ft_memset.c \
ft_strlcat.c \
ft_strnstr.c \
ft_toupper.c \
ft_bzero.c \
ft_isascii.c \
ft_memcmp.c \
ft_strchr.c \
ft_strlcpy.c \
ft_strrchr.c \
ft_calloc.c \
ft_isdigit.c \
ft_memcpy.c \
ft_strdup.c \
ft_strlen.c \
ft_substr.c \
ft_isalnum.c \
ft_isprint.c \
ft_memmove.c \
ft_strjoin.c \
ft_strncmp.c \
ft_tolower.c\
ft_strtrim.c \
ft_putchar_fd.c \
ft_putstr_fd.c \
ft_putendl_fd.c \
ft_putnbr_fd.c \
ft_strmapi.c \
ft_striteri.c \
ft_split.c \
ft_itoa.c \
ft_strcmp.c \
ft_strstr.c \
ft_reallocarray.c \
ft_strcat.c \
ft_strcpy.c \
ft_realloc.c \
ft_strncpy.c \
ft_strtol.c \
ft_strtok.c \
SRCBONUS = ft_lstnew.c \
ft_lstadd_front.c \
ft_lstsize.c \
ft_lstlast.c \
ft_lstadd_back.c \
ft_lstdelone.c \
ft_lstclear.c \
ft_lstiter.c \
ft_lstiter.c \
ft_lstmap.c \
OBJECTS = $(SOURCES:.c=.o)
BONUS_OBJ = $(SRCBONUS:.c=.o)
CC = gcc
RM = rm -f
CFLAGS = -Wall -Werror -Wextra
all: $(NAME)
$(NAME): $(OBJECTS)
@ar rcs $(NAME) $(OBJECTS)
bonus: $(OBJECTS) $(BONUS_OBJ)
@ar rcs $(NAME) $(OBJECTS) $(BONUS_OBJ)
main.o:
gcc -c main.c
ccmainlib:
$(CC) $(CFLAGS) main.c -L -lft
clean:
@$(RM) $(OBJECTS) $(BONUS_OBJ)
fclean: clean
@$(RM) $(NAME)
re: fclean all

38
libft/ft_atoi.c Executable file
View File

@ -0,0 +1,38 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_atoi.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/11 16:16:54 by fgras-ca #+# #+# */
/* Updated: 2023/02/21 09:57:55 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_atoi(const char *nptr)
{
int i;
int sign;
int res;
i = 0;
sign = 1;
res = 0;
while (nptr[i] == 32 || (nptr[i] >= 9 && nptr[i] <= 13))
i++;
if (nptr[i] == '-' || nptr[i] == '+')
{
if (nptr[i] == '-')
sign = - (1);
i++;
}
while (nptr[i] >= 48 && nptr[i] <= 57)
{
res = res * 10 + nptr[i] - 48;
i++;
}
return (res * sign);
}

25
libft/ft_bzero.c Executable file
View File

@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_bzero.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/04 11:37:30 by fgras-ca #+# #+# */
/* Updated: 2023/02/20 16:07:19 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_bzero(void *ptr, size_t len)
{
size_t i;
i = 0;
while (i < len)
{
*(char *)(ptr + i) = 0;
i++;
}
}

28
libft/ft_calloc.c Executable file
View File

@ -0,0 +1,28 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_calloc.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/11 17:47:38 by fgras-ca #+# #+# */
/* Updated: 2023/02/21 10:45:58 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void *ft_calloc(size_t nmemb, size_t size)
{
void *ptr;
if (!nmemb || !size)
return (malloc(0));
if ((nmemb * size) / size != nmemb)
return (NULL);
ptr = malloc(size * nmemb);
if (!ptr)
return (0);
ft_bzero(ptr, size * nmemb);
return (ptr);
}

21
libft/ft_isalnum.c Executable file
View File

@ -0,0 +1,21 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_isalnum.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/01 16:21:11 by fgras-ca #+# #+# */
/* Updated: 2023/02/01 16:24:23 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_isalnum(int c)
{
if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122) || (c >= 48 && c <= 57))
return (1);
else
return (0);
}

21
libft/ft_isalpha.c Executable file
View File

@ -0,0 +1,21 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_isalpha.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/01 13:36:34 by fgras-ca #+# #+# */
/* Updated: 2023/02/01 13:58:21 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_isalpha(int c)
{
if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122))
return (1);
else
return (0);
}

20
libft/ft_isascii.c Executable file
View File

@ -0,0 +1,20 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_isascii.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/01 16:40:31 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:07:04 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_isascii(int c)
{
if (c >= 0 && c <= 127)
return (1);
return (0);
}

21
libft/ft_isdigit.c Executable file
View File

@ -0,0 +1,21 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_isdigit.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/01 14:46:59 by fgras-ca #+# #+# */
/* Updated: 2023/02/01 15:55:00 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_isdigit(int c)
{
if (c >= 48 && c <= 57)
return (1);
else
return (0);
}

20
libft/ft_isprint.c Executable file
View File

@ -0,0 +1,20 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_isprint.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/03 12:43:03 by fgras-ca #+# #+# */
/* Updated: 2023/02/03 13:25:31 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_isprint(int c)
{
if (c >= 32 && c <= 126)
return (1);
return (0);
}

56
libft/ft_itoa.c Executable file
View File

@ -0,0 +1,56 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_itoa.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/17 15:53:35 by fgras-ca #+# #+# */
/* Updated: 2023/02/21 10:21:07 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
static size_t ft_len_nb(int nb)
{
int len;
len = 0;
if (nb <= 0)
len++;
while (nb)
{
len++;
nb = nb / 10;
}
return (len);
}
char *ft_itoa(int n)
{
int len;
char *str;
long nb;
len = ft_len_nb(n);
nb = n;
str = malloc(sizeof(char) * len +1);
if (!str)
return (0);
if (nb < 0)
{
str[0] = '-';
nb = -nb;
}
if (nb == 0)
str[0] = '0';
str[len--] = '\0';
while (nb)
{
str[len] = nb % 10 + '0';
len--;
nb = nb / 10;
}
return (str);
}

29
libft/ft_lstadd_back.c Executable file
View File

@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstadd_back.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/23 18:08:00 by fgras-ca #+# #+# */
/* Updated: 2023/02/23 18:15:14 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_lstadd_back(t_list **lst, t_list *new)
{
t_list *temp;
if (new && lst)
{
if (*lst)
{
temp = ft_lstlast(*lst);
temp->next = new;
}
else
*lst = new;
}
}

22
libft/ft_lstadd_front.c Executable file
View File

@ -0,0 +1,22 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstadd_front.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/22 18:06:54 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:06:52 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_lstadd_front(t_list **lst, t_list *new)
{
if (new)
{
new->next = *lst;
*lst = new;
}
}

25
libft/ft_lstclear.c Executable file
View File

@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstclear.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/23 18:19:42 by fgras-ca #+# #+# */
/* Updated: 2023/02/23 18:22:17 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_lstclear(t_list **lst, void (*del)(void*))
{
t_list *temp;
while (*lst && lst)
{
temp = (*lst)->next;
ft_lstdelone(*lst, (*del));
*lst = temp;
}
}

21
libft/ft_lstdelone.c Executable file
View File

@ -0,0 +1,21 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstdelone.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/23 18:17:06 by fgras-ca #+# #+# */
/* Updated: 2023/02/23 18:33:01 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_lstdelone(t_list *lst, void (*del)(void*))
{
if (!lst || !del)
return ;
del(lst->content);
free(lst);
}

24
libft/ft_lstiter.c Executable file
View File

@ -0,0 +1,24 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstiter.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/23 18:22:52 by fgras-ca #+# #+# */
/* Updated: 2023/02/23 18:24:51 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_lstiter(t_list *lst, void (*f)(void *))
{
if (!lst || !f)
return ;
while (lst)
{
f(lst->content);
lst = lst->next;
}
}

24
libft/ft_lstlast.c Executable file
View File

@ -0,0 +1,24 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstlast.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/23 17:48:29 by fgras-ca #+# #+# */
/* Updated: 2023/02/23 18:02:44 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
t_list *ft_lstlast(t_list *lst)
{
while (lst)
{
if (lst->next == NULL)
return (lst);
lst = lst->next;
}
return (lst);
}

35
libft/ft_lstmap.c Executable file
View File

@ -0,0 +1,35 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstmap.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/23 18:25:24 by fgras-ca #+# #+# */
/* Updated: 2023/02/23 18:29:44 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *))
{
t_list *tmp;
t_list *res;
if (!lst || !f)
return (NULL);
res = 0;
while (lst)
{
tmp = ft_lstnew((*f)(lst->content));
if (!tmp)
{
ft_lstclear(&res, del);
return (NULL);
}
ft_lstadd_back(&res, tmp);
lst = lst->next;
}
return (res);
}

25
libft/ft_lstnew.c Executable file
View File

@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstnew.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/22 17:09:25 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:06:38 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
t_list *ft_lstnew(void *content)
{
t_list *new;
new = malloc(sizeof(t_list));
if (!new)
return (0);
new->content = content;
new->next = 0;
return (new);
}

28
libft/ft_lstsize.c Executable file
View File

@ -0,0 +1,28 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lstsize.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/23 17:17:36 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:06:24 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_lstsize(t_list *lst)
{
int i;
t_list *tmp;
tmp = lst;
i = 0;
while (tmp)
{
tmp = tmp->next;
i++;
}
return (i);
}

27
libft/ft_memchr.c Executable file
View File

@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_memchr.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/10 13:42:10 by fgras-ca #+# #+# */
/* Updated: 2023/02/14 13:03:28 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void *ft_memchr(const void *s, int c, size_t n)
{
size_t i;
i = 0;
while (i < n)
{
if (((unsigned char *)s)[i] == (unsigned char)c)
return ((void *)(s + i));
i++;
}
return (0);
}

27
libft/ft_memcmp.c Executable file
View File

@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_memcmp.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/10 14:45:56 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:18:05 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_memcmp(const void *s1, const void *s2, size_t n)
{
size_t i;
i = 0;
while (i < n)
{
if (((unsigned char *)s1)[i] != ((unsigned char *)s2)[i])
return (((unsigned char *)s1)[i] - ((unsigned char *)s2)[i]);
i++;
}
return (0);
}

32
libft/ft_memcpy.c Executable file
View File

@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_memcpy.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/04 14:43:15 by fgras-ca #+# #+# */
/* Updated: 2023/02/20 16:13:43 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void *ft_memcpy(void *dest, const void *src, size_t n)
{
char *destmov;
char *srcmov;
size_t i;
destmov = (char *)dest;
srcmov = (char *)src;
if (!dest && !src)
return (0);
i = 0;
while (i < n)
{
destmov[i] = srcmov[i];
i++;
}
return (dest);
}

42
libft/ft_memmove.c Executable file
View File

@ -0,0 +1,42 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_memmove.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/07 11:11:49 by fgras-ca #+# #+# */
/* Updated: 2023/02/07 16:04:25 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void *ft_memmove(void *dest, const void *src, size_t n)
{
char *destmov;
char *srcmov;
size_t i;
if (!dest && !src)
return (0);
destmov = (char *)dest;
srcmov = (char *)src;
i = 0;
if (destmov > srcmov)
{
while (n--)
{
destmov[n] = srcmov[n];
}
}
else
{
while (n--)
{
destmov[i] = srcmov[i];
i++;
}
}
return (destmov);
}

26
libft/ft_memset.c Executable file
View File

@ -0,0 +1,26 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_memset.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/03 15:49:51 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:07:29 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void *ft_memset(void *s, int c, size_t n)
{
size_t i;
i = 0;
while (i < n)
{
*(unsigned char *)(s + i) = (unsigned char)c;
i++;
}
return (s);
}

18
libft/ft_putchar_fd.c Executable file
View File

@ -0,0 +1,18 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_putchar_fd.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/15 11:23:07 by fgras-ca #+# #+# */
/* Updated: 2023/02/15 11:30:37 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_putchar_fd(char c, int fd)
{
write(fd, &c, 1);
}

28
libft/ft_putendl_fd.c Executable file
View File

@ -0,0 +1,28 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_putendl_fd.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/15 13:33:49 by fgras-ca #+# #+# */
/* Updated: 2023/02/21 10:19:05 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_putendl_fd(char *s, int fd)
{
int i;
i = 0;
if (!s)
return ;
while (s[i])
{
write(fd, &s[i], 1);
i++;
}
write(fd, "\n", 1);
}

36
libft/ft_putnbr_fd.c Executable file
View File

@ -0,0 +1,36 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_putnbr_fd.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/15 13:53:25 by fgras-ca #+# #+# */
/* Updated: 2023/02/15 14:00:06 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_putnbr_fd(int n, int fd)
{
if (n == -2147483648)
{
write(fd, "-2147483648", 11);
}
else if (n >= 0 && n < 10)
{
n += 48;
ft_putchar_fd(n, fd);
}
else if (n < 0)
{
ft_putchar_fd('-', fd);
ft_putnbr_fd((n * (-1)), fd);
}
else
{
ft_putnbr_fd(n / 10, fd);
ft_putnbr_fd(n % 10, fd);
}
}

27
libft/ft_putstr_fd.c Executable file
View File

@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_putstr_fd.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/15 12:29:14 by fgras-ca #+# #+# */
/* Updated: 2023/02/15 19:02:37 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void ft_putstr_fd(char *s, int fd)
{
int i;
i = 0;
if (!s || !fd)
return ;
while (s[i])
{
write(fd, &s[i], 1);
i++;
}
}

35
libft/ft_realloc.c Executable file
View File

@ -0,0 +1,35 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_realloc.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/15 16:31:35 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 13:59:12 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
void *ft_realloc(void *ptr, size_t newsize, size_t oldsize)
{
char *newptr;
if (ptr == NULL)
{
return (malloc(newsize));
}
if (newsize <= oldsize)
{
return (ptr);
}
newptr = malloc(newsize);
if (newptr == NULL)
{
return (NULL);
}
ft_memcpy(newptr, ptr, oldsize);
free(ptr);
return (newptr);
}

32
libft/ft_reallocarray.c Executable file
View File

@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_reallocarray.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/15 15:52:29 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 11:46:15 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
static size_t get_mul_no_overflow(void)
{
return ((size_t)1 << (sizeof(size_t) * 4));
}
void *ft_reallocarray(void *optr, size_t nmemb, size_t size, size_t oldsize)
{
size_t mul_no_overflow;
mul_no_overflow = get_mul_no_overflow();
if ((nmemb >= mul_no_overflow || size >= mul_no_overflow)
&& nmemb > 0 && SIZE_MAX / nmemb < size)
{
errno = ENOMEM;
return (NULL);
}
return (ft_realloc(optr, nmemb * size, oldsize));
}

75
libft/ft_split.c Executable file
View File

@ -0,0 +1,75 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_split.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/17 13:12:04 by fgras-ca #+# #+# */
/* Updated: 2023/02/21 11:04:10 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
static int count_words(const char *s, char c)
{
int count;
int trigger;
count = 0;
trigger = 0;
while (*s)
{
if (*s != c && trigger == 0)
{
trigger = 1;
count++;
}
else if (*s == c)
trigger = 0;
s++;
}
return (count);
}
static char *word_cpy(const char *s, int start, int end)
{
char *word;
int i;
i = 0;
word = malloc(sizeof(char) * (end - start + 1));
while (start < end)
word[i++] = s[start++];
word[i] = '\0';
return (word);
}
char **ft_split(char const *s, char c)
{
size_t i;
size_t j;
int index;
char **split;
split = malloc(sizeof(char *) * (count_words(s, c) + 1));
if (!s || !split)
return (0);
i = 0;
j = 0;
index = -1;
while (i <= ft_strlen(s))
{
if (s[i] != c && index < 0)
index = i;
else if ((s[i] == c || i == ft_strlen(s)) && index >= 0)
{
split[j++] = word_cpy(s, index, i);
index = -1;
}
i++;
}
split[j] = 0;
return (split);
}

32
libft/ft_strcat.c Executable file
View File

@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strcat.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/21 19:20:36 by fgras-ca #+# #+# */
/* Updated: 2023/11/21 19:28:29 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strcat(char *dest, const char *src)
{
char *save;
save = dest;
while (*dest)
{
dest++;
}
while (*src)
{
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return (save);
}

32
libft/ft_strchr.c Executable file
View File

@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strchr.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/09 14:27:10 by fgras-ca #+# #+# */
/* Updated: 2023/02/21 10:54:39 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strchr(const char *s, int c)
{
int i;
char *str;
str = (char *)s;
i = 0;
while (str[i])
{
if (str[i] == (char)c)
return (&str[i]);
i++;
}
if (str[i] == (char)c)
return (&str[i]);
return (0);
}

23
libft/ft_strcmp.c Executable file
View File

@ -0,0 +1,23 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strcmp.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/14 16:57:42 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:10:27 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_strcmp(const char *s1, const char *s2)
{
while (*s1 && (*s1 == *s2))
{
s1++;
s2++;
}
return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
}

28
libft/ft_strcpy.c Executable file
View File

@ -0,0 +1,28 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strcpy.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/21 19:23:08 by fgras-ca #+# #+# */
/* Updated: 2023/11/21 19:26:36 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strcpy(char *dest, const char *src)
{
char *save;
save = dest;
while (*src)
{
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return (save);
}

31
libft/ft_strdup.c Executable file
View File

@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strdup.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/11 18:40:02 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 12:25:07 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strdup(const char *s)
{
char *str;
size_t i;
str = (char *)malloc(sizeof(char) * (ft_strlen(s) + 1));
if (!str)
return (NULL);
i = 0;
while (s[i])
{
str[i] = s[i];
i++;
}
str[i] = 0;
return (str);
}

25
libft/ft_striteri.c Executable file
View File

@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_striteri.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/16 14:25:00 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:08:02 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
void ft_striteri(char *s, void (*f)(unsigned int, char*))
{
unsigned int i;
if (!s)
return ;
i = 0;
while (s[i])
{
f(i, &s[i]);
i++;
}
}

39
libft/ft_strjoin.c Executable file
View File

@ -0,0 +1,39 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strjoin.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/13 16:54:51 by fgras-ca #+# #+# */
/* Updated: 2023/03/13 13:58:13 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strjoin(char const *s1, char const *s2)
{
char *new_s;
size_t i;
size_t j;
if (!s1 || !s2)
return (0);
new_s = (char *)malloc(sizeof(char) * (ft_strlen(s1) + ft_strlen(s2) + 1));
if (!new_s)
return (0);
i = 0;
j = 0;
while (s1[i])
{
new_s[j] = s1[i];
i++;
j++;
}
i = 0;
while (s2[i])
new_s[j++] = s2[i++];
new_s[j] = '\0';
return (new_s);
}

33
libft/ft_strlcat.c Executable file
View File

@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strlcat.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/08 14:10:58 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:09:41 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
size_t ft_strlcat(char *dst, const char *src, size_t size)
{
size_t i;
size_t dst_len;
i = 0;
if (!dst && !size)
return (0);
dst_len = ft_strlen(dst);
if (size <= dst_len)
return (size + ft_strlen(src));
while (src[i] && i < size - dst_len -1)
{
dst[dst_len + i] = src[i];
i++;
}
dst[dst_len + i] = 0;
return (dst_len + ft_strlen(src));
}

32
libft/ft_strlcpy.c Executable file
View File

@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strlcpy.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/08 13:24:31 by fgras-ca #+# #+# */
/* Updated: 2023/02/08 13:33:32 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
size_t ft_strlcpy(char *dst, const char *src, size_t size)
{
size_t i;
i = 0;
if (size > 0)
{
while (src[i] && i < (size - 1))
{
dst[i] = src[i];
i++;
}
dst[i] = 0;
}
while (src[i])
i++;
return (i);
}

23
libft/ft_strlen.c Executable file
View File

@ -0,0 +1,23 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strlen.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/03 14:10:21 by fgras-ca #+# #+# */
/* Updated: 2023/02/03 14:17:21 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
size_t ft_strlen(const char *s)
{
size_t i;
i = 0;
while (s[i])
i++;
return (i);
}

33
libft/ft_strmapi.c Executable file
View File

@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strmapi.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/16 13:38:52 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:04:43 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strmapi(const char *s, char (*f)(unsigned int, char))
{
char *result;
unsigned int i;
if (!s)
return (0);
result = malloc(sizeof(char) * (ft_strlen(s) + 1));
if (!result)
return (0);
i = 0;
while (s[i])
{
result[i] = f(i, s[i]);
i++;
}
result[i] = 0;
return (result);
}

29
libft/ft_strncmp.c Executable file
View File

@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strncmp.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/09 17:12:38 by fgras-ca #+# #+# */
/* Updated: 2023/02/14 13:26:15 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_strncmp(const char *s1, const char *s2, size_t n)
{
size_t i;
i = 0;
if (n == 0)
{
return (0);
}
while (s1[i] == s2[i] && (s1[i] != '\0' || s2[i] != '\0') && i < (n - 1))
{
i++;
}
return ((unsigned char)s1[i] - (unsigned char)s2[i]);
}

31
libft/ft_strncpy.c Executable file
View File

@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strncpy.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/27 20:03:19 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 11:56:51 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strncpy(char *dest, char *src, unsigned int n)
{
unsigned int i;
i = 0;
while (src[i] != '\0' && i < n)
{
dest[i] = src[i];
++i;
}
while (i < n)
{
dest[i] = '\0';
i++;
}
return (dest);
}

41
libft/ft_strnstr.c Executable file
View File

@ -0,0 +1,41 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strnstr.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/11 14:31:40 by fgras-ca #+# #+# */
/* Updated: 2023/02/21 10:08:36 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strnstr(const char *haystack, const char *needle, size_t len)
{
size_t i;
size_t j;
i = 0;
if (needle == haystack)
return ((char *)haystack);
if (!len && !haystack)
return (0);
while (haystack[i] != '\0')
{
j = 0;
while (haystack[i + j] == needle[j] && (i + j) < len)
{
if (haystack[i + j] == '\0' && needle[j] == '\0')
{
return ((char *)&haystack[j]);
}
j++;
}
if (needle[j] == '\0')
return ((char *)(haystack + i));
i++;
}
return (NULL);
}

29
libft/ft_strrchr.c Executable file
View File

@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strrchr.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/09 16:10:11 by fgras-ca #+# #+# */
/* Updated: 2023/02/14 15:36:23 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strrchr(const char *s, int c)
{
int i;
i = 0;
while (s[i])
i++;
while (i >= 0)
{
if (s[i] == (char)c)
return ((char *)(s + i));
i--;
}
return (0);
}

42
libft/ft_strstr.c Executable file
View File

@ -0,0 +1,42 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strstr.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/14 20:54:44 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 21:08:57 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_strstr(const char *haystack, const char *needle)
{
const char *p;
const char *beginning;
const char *n;
p = haystack;
if (*needle == '\0')
return ((char *)haystack);
while (*p != '\0')
{
if (*p == *needle)
{
beginning = p;
n = needle;
while (*p == *n && *n != '\0' && *p != '\0')
{
p++;
n++;
}
if (*n == '\0')
return ((char *)beginning);
p = beginning;
}
p++;
}
return (NULL);
}

83
libft/ft_strtok.c Executable file
View File

@ -0,0 +1,83 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strtok.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/14 17:14:45 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 11:41:34 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
static char *init_str_and_lasts(char **lasts, char *str)
{
if (str == NULL)
{
str = *lasts;
if (str == NULL)
return (NULL);
}
else
{
*lasts = str;
}
return (str);
}
static char *find_token_start(char **lasts, const char *delim)
{
int ch;
ch = **lasts;
while (ch != '\0' && ft_strchr(delim, ch) != NULL)
{
(*lasts)++;
ch = **lasts;
}
if (**lasts == '\0')
{
*lasts = NULL;
return (NULL);
}
return (*lasts);
}
static char *find_token_end(char **lasts, const char *delim)
{
int ch;
char *str;
str = *lasts;
ch = **lasts;
while (ch != '\0' && ft_strchr(delim, ch) == NULL)
{
(*lasts)++;
ch = **lasts;
}
if (**lasts != '\0')
{
**lasts = '\0';
(*lasts)++;
}
else
{
*lasts = NULL;
}
return (str);
}
char *ft_strtok(char *str, const char *delim)
{
static char *lasts;
str = init_str_and_lasts(&lasts, str);
if (str == NULL)
return (NULL);
str = find_token_start(&lasts, delim);
if (str == NULL)
return (NULL);
return (find_token_end(&lasts, delim));
}

115
libft/ft_strtol.c Executable file
View File

@ -0,0 +1,115 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strtol.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 14:00:32 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 11:56:12 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
static int skip_whitespaces_and_sign(const char *str, int *sign)
{
int i;
i = 0;
while (str[i] == ' ' || (str[i] >= '\t' && str[i] <= '\r'))
i++;
if (str[i] == '+' || str[i] == '-')
{
if (str[i] == '-')
*sign = -1;
i++;
}
return (i);
}
static int determine_base(const char *str, int *base, int index)
{
if ((*base == 0 || *base == 16) && str[index] == '0'
&& (str[index + 1] == 'x' || str[index + 1] == 'X'))
{
*base = 16;
index += 2;
}
else if (*base == 0)
{
if (str[index] == '0')
*base = 8;
else
*base = 10;
}
return (index);
}
static int check_base(const char *str, int *base, int *sign)
{
int i;
*sign = 1;
i = skip_whitespaces_and_sign(str, sign);
i = determine_base(str, base, i);
return (i);
}
static long convert_strtol(const char *str, int base, int sign)
{
long result;
int digit;
result = 0;
while (*str)
{
digit = 0;
if (*str >= '0' && *str <= '9')
digit = *str - '0';
else if (*str >= 'A' && *str <= 'Z')
digit = *str - 'A' + 10;
else if (*str >= 'a' && *str <= 'z')
digit = *str - 'a' + 10;
else
break ;
if (digit >= base)
break ;
if (sign > 0 && result > (LONG_MAX - digit) / base)
return (errno = ERANGE, LONG_MAX);
if (sign < 0 && result < (LONG_MIN + digit) / base)
return (errno = ERANGE, LONG_MIN);
result = result * base + digit;
str++;
}
return (result * sign);
}
long ft_strtol(const char *str, char **endptr, int base)
{
int sign;
int i;
long result;
if (base < 0 || base == 1 || base > 36)
{
if (endptr)
*endptr = (char *)str;
return (0);
}
i = check_base(str, &base, &sign);
result = convert_strtol(str + i, base, sign);
if (endptr)
*endptr = (char *)(str + i);
while (*str)
{
if ((*str >= '0' && *str <= '9' && *str - '0' < base)
|| (*str >= 'A' && *str <= 'Z' && *str - 'A' + 10 < base)
|| (*str >= 'a' && *str <= 'z' && *str - 'a' + 10 < base))
*endptr = (char *)(str + 1);
else
break ;
str++;
}
return (result);
}

52
libft/ft_strtrim.c Executable file
View File

@ -0,0 +1,52 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strtrim.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/14 16:30:26 by fgras-ca #+# #+# */
/* Updated: 2023/03/13 14:12:41 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
static int char_in_set(char c, char const *set)
{
size_t i;
i = 0;
while (set[i])
{
if (set[i] == c)
return (1);
i++;
}
return (0);
}
char *ft_strtrim(char const *s1, char const *set)
{
char *str;
size_t i;
size_t start;
size_t end;
if (!s1)
return (0);
start = 0;
while (s1[start] && char_in_set(s1[start], set))
start++;
end = ft_strlen(s1);
while (end > start && char_in_set(s1[end - 1], set))
end--;
str = (char *)malloc(sizeof(*s1) * (end - start + 1));
if (!str)
return (0);
i = 0;
while (start < end)
str[i++] = s1[start++];
str[i] = 0;
return (str);
}

37
libft/ft_substr.c Executable file
View File

@ -0,0 +1,37 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_substr.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/13 15:40:49 by fgras-ca #+# #+# */
/* Updated: 2023/11/14 17:07:20 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
char *ft_substr(char const *s, unsigned int start, size_t len)
{
char *new_s;
size_t i;
size_t j;
new_s = (char *)malloc(sizeof(char) * (len + 1));
if (!s || !new_s)
return (NULL);
i = 0;
j = 0;
while (s[i])
{
if (i >= start && j < len)
{
new_s[j] = s[i];
j++;
}
i++;
}
new_s[j] = '\0';
return (new_s);
}

20
libft/ft_tolower.c Executable file
View File

@ -0,0 +1,20 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_tolower.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/09 14:09:59 by fgras-ca #+# #+# */
/* Updated: 2023/02/14 13:36:02 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_tolower(int c)
{
if (c >= 65 && c <= 90)
c += 32;
return (c);
}

20
libft/ft_toupper.c Executable file
View File

@ -0,0 +1,20 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_toupper.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/08 16:02:00 by fgras-ca #+# #+# */
/* Updated: 2023/02/14 13:36:40 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
int ft_toupper(int c)
{
if (c >= 97 && c <= 122)
c -= 32;
return (c);
}

85
libft/libft.h Executable file
View File

@ -0,0 +1,85 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* libft.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/02/12 10:46:53 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 11:47:27 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef LIBFT_H
# define LIBFT_H
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# include <unistd.h>
# include <sys/types.h>
# include <errno.h>
# include <stdint.h>
# include <limits.h>
typedef struct s_list
{
void *content;
struct s_list *next;
} t_list;
int ft_isalpha(int c);
int ft_isdigit(int c);
int ft_isalnum(int c);
int ft_isascii(int c);
int ft_isprint(int c);
int ft_toupper(int c);
int ft_tolower(int c);
int ft_strcmp(const char *s1, const char *s2);
int ft_strncmp(const char *s1, const char *s2, size_t n);
int ft_strcmp(const char *s1, const char *s2);
int ft_memcmp(const void *s1, const void *s2, size_t n);
int ft_atoi(const char *nptr);
int ft_lstsize(t_list *lst);
void *ft_memset(void *s, int c, size_t n);
void ft_bzero(void *ptr, size_t len);
void *ft_memcpy(void *dest, const void *src, size_t n);
void *ft_memmove(void *dest, const void *src, size_t n);
void *ft_memchr(const void *s, int c, size_t n);
void *ft_calloc(size_t nmemb, size_t size);
void ft_putchar_fd(char c, int fd);
void ft_putstr_fd(char *s, int fd);
void ft_putendl_fd(char *s, int fd);
void ft_putnbr_fd(int n, int fd);
void ft_striteri(char *s, void (*f)(unsigned int, char*));
void ft_lstadd_front(t_list **lst, t_list *new);
void ft_lstadd_back(t_list **lst, t_list *new);
void ft_lstdelone(t_list *lst, void (*del)(void *));
void ft_lstclear(t_list **lst, void (*del)(void *));
void ft_lstiter(t_list *lst, void (*f)(void *));
size_t ft_strlen(const char *s);
size_t ft_strlcpy(char *dst, const char *src, size_t size);
size_t ft_strlcat(char *dst, const char *src, size_t size);
char *ft_strchr(const char *s, int c);
char *ft_strrchr(const char *s, int c);
char *ft_strtok(char *str, const char *delim);
char *ft_strnstr(const char *haystack, const char *needle, size_t len);
char *ft_strdup(const char *s);
char *ft_strstr(const char *haystack, const char *needle);
char *ft_substr(char const *s, unsigned int start, size_t len);
char *ft_strjoin(char const *s1, char const *s2);
char *ft_strtrim(char const *s1, char const *set);
char *ft_strmapi(const char *s, char (*f)(unsigned int, char));
char *ft_strncpy(char *dest, char *src, unsigned int n);
char **ft_split(char const *s, char c);
void *ft_reallocarray(void *optr, size_t nmemb, size_t size, size_t oldsize);
void *ft_realloc(void *ptr, size_t newsize, size_t oldsize);
char *ft_itoa(int n);
char *ft_strcat(char *dest, const char *src);
char *ft_strcpy(char *dest, const char *src);
t_list *ft_lstnew(void *content);
t_list *ft_lstlast(t_list *lst);
t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *));
long ft_strtol(const char *str, char **endptr, int base);
#endif

271
minishell.h Executable file
View File

@ -0,0 +1,271 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* minishell.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/07 16:11:33 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 14:08:16 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MINISHELL_H
# define MINISHELL_H
# include "libft/libft.h"
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <sys/types.h>
# include <errno.h>
# include <sys/wait.h>
# include <signal.h>
# include <readline/readline.h>
# include <readline/history.h>
# include <fcntl.h>
# include <limits.h>
# include <stdbool.h>
# include <stddef.h>
# define RST "\033[0m"
# define GRAY "\033[0;90m"
# define RED "\033[0;91m"
# define GREEN "\033[0;92m"
# define YELLOW "\033[0;93m"
# define BLUE "\033[0;94m"
# define MAGENTA "\033[0;95m"
# define CYAN "\033[0;96m"
# define WHITE "\033[0;97m"
# define ORANGE "\033[38;5;214m"
# define MAX_ARGS 10000
# define DELIM " \t\r\n\a"
# define CONTINUE_SHELL 0
# define EXIT_SHELL 1
typedef enum s_redirection_mode
{
REDIRECT_IN,
REDIRECT_OUT,
REDIRECT_APPEND,
REDIRECT_HEREDOC,
REDIRECT_UNKNOWN
} t_redirection_mode;
typedef enum s_state
{
NORMAL,
SINGLE_QUOTE,
DOUBLE_QUOTE
} t_State;
typedef struct s_tokenizer
{
t_State state;
char **tokens;
char *token;
int token_length;
int input_pos;
int token_pos;
bool in_quotes;
bool within_single_quotes;
bool within_double_quotes;
bool variable;
bool symbol;
} t_Tokenizer;
typedef struct s_minishell
{
char **builtin_str;
char **environ;
int (**builtin_func)(char **, struct s_minishell *);
int last_exit_status;
t_Tokenizer *tokenizer;
bool is_piped;
int exit_status;
} t_minishell;
typedef struct s_command
{
char *command;
char **args;
int arg_count;
} t_command;
typedef struct s_redirection
{
int stdin_backup;
int stdout_backup;
} t_redirection;
typedef struct s_pipe_struct
{
int fds[2];
} t_pipe_struct;
typedef struct s_command_node
{
t_command *command;
struct s_command_node *left;
struct s_command_node *right;
} t_command_node;
typedef struct s_process_token_params
{
char **tokens;
int *token_index;
t_command **current_command;
t_command_node **root;
t_minishell *shell;
int command_count;
} t_process_token_params;
typedef struct s_child_process_params
{
int i;
int *pipe_fds;
int command_count;
int fd;
t_command **commands;
t_minishell *shell;
} t_child_process_params;
typedef struct s_process_params
{
int *pipe_fds;
t_command **commands;
t_minishell *shell;
int command_count;
int fd;
} t_process_params;
typedef int (*t_builtin_func_t)(char **, t_minishell *);
//prompt
void prompt_loop(t_minishell *shell, int fd);
t_minishell init_minishell(char **envp, char **builtin_str,
int (**builtin_func)(char **, t_minishell *));
//history
void display_history_entry(HIST_ENTRY **the_history_list, int i);
void display_history_list(void);
void search_in_history(HIST_ENTRY **the_history_list,
const char *search_string);
void search_history(void);
//builtins
int builtin_echo_wrapper(char **args, t_minishell *shell);
int builtin_cd(char **args, t_minishell *shell);
int builtin_echo(char **args, t_minishell *shell, int fd);
int builtin_exit(char **args, t_minishell *shell);
int builtin_env(char **args, t_minishell *shell);
int builtin_pwd(char **args, t_minishell *shell);
int builtin_export(char **args, t_minishell *shell);
int num_builtins(t_minishell *shell);
int execute_builtin(char **args, t_minishell *shell);
int builtin_unset(char **args, t_minishell *shell);
int export_set_env(char **args, t_minishell *shell);
int count_env_vars(char **environ);
char **copy_env(char **environ, int env_size);
void sort_env(char **env, int env_size);
int add_new_env_entry(t_minishell *shell, char *new_env_entry);
int replace_env_entry(t_minishell *shell, char *new_env_entry);
char *extract_name(char *env_entry);
char *extract_value(char *env_entry);
t_builtin_func_t *initialize_builtin_func(void);
//Exécutions
pid_t create_process(char *path, char **args, char **environ);
pid_t execute_external_command(char **args, char **environ);
char *find_executable(const char *cmd, char **environ);
//tokenize
char **tokenize_and_parse_input(char *input,
t_minishell *shell, int fd);
void tokenize_loop(char *input, t_Tokenizer *tk);
void init_vars(t_Tokenizer *tk, char *input);
void process_char(char input_char, t_Tokenizer *tk);
void add_token_to_list(t_Tokenizer *tk);
void free_tokens(char **tokens);
void add_special_symbol(char *input, t_Tokenizer *tk);
void handle_spaces_and_tabs(char *input, t_Tokenizer *tk);
void handle_empty_quotes(char *input, t_Tokenizer *tk);
bool is_special_symbol(char c, char next_c);
bool is_simple_symbol(char c);
void process_input_char(char *input, t_Tokenizer *tk);
void handle_other_chars(char *input, t_Tokenizer *tk);
void handle_special_symbol(char *input, t_Tokenizer *tk);
void handle_spaces_or_tabs(char *input, t_Tokenizer *tk);
bool is_space_or_tab(char current_char);
void handle_quote_transition(char *input, t_Tokenizer *tk);
bool is_quote_transition(char current_char, t_Tokenizer *tk);
char *replace_env_vars_in_string(const char *str,
t_minishell *shell);
//quotes
void handle_normal_state(char input_char, t_Tokenizer *tk);
void handle_single_quote_state(char input_char, t_Tokenizer *tk);
void handle_double_quote_state(char input_char, t_Tokenizer *tk);
char **handle_unclosed_quotes(char ***tokens, int token_pos);
int are_only_quotes(char **tokens);
//var $
char *get_variable_value(const char *variable_name,
t_minishell *shell);
const char *skip_dollar(const char *variable_name);
void reverse_str(char *str, int length);
char *search_env_variable(const char *name_to_search,
t_minishell *shell);
//utils
char *get_env_value(const char *key, char **environ);
int is_only_spaces(const char *str);
//gestions signaux ctrl-c ctrl-D ctrl-
void handle_sigint(int sig);
void handle_sigquit(int sig);
void setup_signal_handlers(void);
//parsing
void parse_tokens(char **tokens, t_minishell *shell, int fd);
bool is_pipe_token(char *token, t_minishell *shell);
bool is_redirection_token(char *token);
bool is_variable_token(char *token);
void add_token_to_command_wrapper(t_command **command,
char *token);
int is_variable_resolvable(char *token, t_State current_state);
void handle_variable_and_other_tokens(
t_process_token_params *params);
void handle_pipe_and_redirection(t_process_token_params *params,
int fd);
void execute_and_free_tree(t_command_node *root,
t_minishell *shell, int command_count, int fd);
int check_syntax_error(char **tokens, int token_index,
bool in_quotes, t_minishell *shell);
//redirections
void process_redirection(t_process_token_params *params,
t_command *commands, t_minishell *shell, int fd);
void save_standard_descriptors(t_redirection *redir);
void restore_standard_descriptors(t_redirection *redir);
void heredoc_input(const char *delimiter);
void configure_redirection(char *file, int mode);
//pipes
void process_pipe(t_command **command, t_minishell *shell,
int command_count, int fd);
void heredoc_input(const char *delimiter);
void close_all_pipes(int *pipe_fds, int count);
void setup_child_process(t_child_process_params *params);
//command
void reset_command(t_command *command);
void free_command(t_command *command);
void add_token_to_command(t_command *command, char *token);
void execute_command(t_command *command,
t_minishell *shell, int fd);
bool is_builtin_command(const char *command, t_minishell *shell);
t_command *create_new_command(void);
char **build_args_array(t_command *command);
void free_args_array(char **args);
int execute_builtin_and_free(char **args,
t_minishell *shell, int fd);
//tree
t_command_node *create_command_node(t_command *command);
void add_node_to_tree(t_command_node **root,
t_command_node *new_node);
void execute_command_tree(t_command_node *node,
t_minishell *shell, int command_count, int fd);
void free_command_tree(t_command_node *node);
#endif

78
parsing/herodoc.c Executable file
View File

@ -0,0 +1,78 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* herodoc.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 15:49:41 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 14:16:55 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static void read_and_write_input(int write_end, const char *delimiter)
{
char buffer[1024];
ssize_t num_read;
char *newline;
while (1)
{
printf("> ");
fflush(stdout);
num_read = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
if (num_read <= 0)
break ;
buffer[num_read] = '\0';
if (ft_strncmp(buffer, delimiter, ft_strlen(delimiter)) == 0)
{
newline = ft_strchr(buffer, '\n');
if (newline != NULL && newline - buffer
== (ptrdiff_t)ft_strlen(delimiter))
break ;
}
write(write_end, buffer, num_read);
}
}
static void child_process(int *pipe_fds, const char *delimiter)
{
close(pipe_fds[0]);
read_and_write_input(pipe_fds[1], delimiter);
close(pipe_fds[1]);
exit(EXIT_SUCCESS);
}
static void parent_process(int *pipe_fds)
{
close(pipe_fds[1]);
dup2(pipe_fds[0], STDIN_FILENO);
close(pipe_fds[0]);
}
void heredoc_input(const char *delimiter)
{
int pipe_fds[2];
pid_t pid;
if (pipe(pipe_fds) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
pid = fork();
if (pid == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0)
child_process(pipe_fds, delimiter);
else
{
parent_process(pipe_fds);
waitpid(pid, NULL, 0);
}
}

113
parsing/parse.c Executable file
View File

@ -0,0 +1,113 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parse.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/29 21:03:27 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 14:00:23 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static void finalize_command(t_command **current_command, t_command_node **root)
{
t_command_node *new_node;
if (*current_command && (*current_command)->command)
{
new_node = create_command_node(*current_command);
add_node_to_tree(root, new_node);
}
else if (*current_command)
{
free_command(*current_command);
}
}
static bool handle_syntax_error_and_free(t_process_token_params *params,
t_minishell *shell)
{
char *current_token;
bool sb;
current_token = params->tokens[*params->token_index];
sb = shell->tokenizer->symbol;
if (sb && (is_pipe_token(current_token, shell)
|| is_redirection_token(current_token)))
{
if (check_syntax_error(params->tokens,
*params->token_index, shell->tokenizer->in_quotes, shell))
{
if (*(params->current_command) != NULL)
{
free_command(*(params->current_command));
*(params->current_command) = NULL;
}
return (true);
}
}
return (false);
}
static void process_single_token(t_process_token_params *params,
t_minishell *shell, int fd)
{
char *current_token;
current_token = params->tokens[*params->token_index];
if (shell->tokenizer->symbol && (is_pipe_token(current_token, shell)
|| is_redirection_token(current_token)))
{
handle_pipe_and_redirection(params, fd);
}
else
{
handle_variable_and_other_tokens(params);
}
}
static void process_tokens(t_process_token_params *params,
t_minishell *shell, int fd)
{
while (params->tokens[*params->token_index] != NULL)
{
if (handle_syntax_error_and_free(params, shell))
{
return ;
}
process_single_token(params, shell, fd);
(*params->token_index)++;
}
}
void parse_tokens(char **tokens, t_minishell *shell, int fd)
{
t_command_node *root;
t_command *current_command;
int token_index;
int error_detected;
t_process_token_params params;
token_index = 0;
current_command = NULL;
root = NULL;
error_detected = 0;
params.tokens = tokens;
params.token_index = &token_index;
params.current_command = &current_command;
params.root = &root;
params.shell = shell;
params.command_count = 1;
process_tokens(&params, shell, fd);
if (current_command && current_command->command)
{
finalize_command(&current_command, &root);
if (!error_detected)
execute_and_free_tree(root, shell, params.command_count, fd);
}
else if (current_command)
free_command(current_command);
}

45
parsing/parse_error.c Executable file
View File

@ -0,0 +1,45 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parse_error.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/07 13:00:24 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 19:25:39 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void execute_and_free_tree(t_command_node *root,
t_minishell *shell, int command_count, int fd)
{
if (root)
{
execute_command_tree(root, shell, command_count, fd);
free_command_tree(root);
}
}
int check_syntax_error(char **tokens, int token_index,
bool in_quotes, t_minishell *shell)
{
if (in_quotes)
{
return (0);
}
if (is_redirection_token(tokens[token_index])
|| is_pipe_token(tokens[token_index], shell))
{
if (token_index == 0 || tokens[token_index + 1] == NULL)
{
write(2, RED"bash: erreur de syntaxe près du symbole inattendu "
RST, 58);
write(2, tokens[token_index], ft_strlen(tokens[token_index]));
write(2, "\n", 1);
return (1);
}
}
return (0);
}

87
parsing/parse_redirections.c Executable file
View File

@ -0,0 +1,87 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parse_redirections.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 15:25:07 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 13:55:02 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void handle_pipe_and_redirection(t_process_token_params *params, int fd)
{
t_command_node *new_node;
if (is_pipe_token(params->tokens[*params->token_index], params->shell))
{
if (*params->current_command && (*params->current_command)->command)
{
new_node = create_command_node(*params->current_command);
add_node_to_tree(params->root, new_node);
*params->current_command = create_new_command();
params->command_count++;
}
}
else if (is_redirection_token(params->tokens[*params->token_index]))
{
if (*params->current_command && (*params->current_command)->command)
{
process_redirection
(params, *params->current_command, params->shell, fd);
}
}
}
void resolve_variable_and_add_to_command(t_process_token_params *params,
char *token)
{
char *resolved_value;
resolved_value = get_variable_value(token, params->shell);
add_token_to_command_wrapper(params->current_command, resolved_value);
free(resolved_value);
}
static void handle_variable_token(t_process_token_params *params)
{
char *token;
t_State current_state;
token = params->tokens[*params->token_index];
current_state = params->shell->tokenizer->state;
if (is_variable_resolvable(token, current_state))
{
resolve_variable_and_add_to_command(params, token);
}
else
{
add_token_to_command_wrapper(params->current_command, token);
}
}
static void handle_non_variable_token(t_process_token_params *params)
{
add_token_to_command_wrapper(params->current_command,
params->tokens[*params->token_index]);
}
void handle_variable_and_other_tokens(t_process_token_params *params)
{
char *current_token;
bool variable;
current_token = params->tokens[*params->token_index];
variable = params->shell->tokenizer->variable;
if (!variable && is_variable_token(current_token))
{
handle_variable_token(params);
}
else
{
handle_non_variable_token(params);
}
}

54
parsing/parse_utils.c Executable file
View File

@ -0,0 +1,54 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parse_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/07 09:58:11 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 19:09:08 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
bool is_pipe_token(char *token, t_minishell *shell)
{
(void)shell;
return (strcmp(token, "|") == 0);
}
bool is_redirection_token(char *token)
{
static const char *redirections[] = {">", "<", ">>", "<<", NULL};
int i;
i = 0;
while (redirections[i] != NULL)
{
if (ft_strcmp(token, redirections[i]) == 0)
return (true);
i++;
}
return (false);
}
bool is_variable_token(char *token)
{
return (token[0] == '$' && token[1] != '\0');
}
void add_token_to_command_wrapper(t_command **command, char *token)
{
if (!*command)
{
*command = create_new_command();
}
add_token_to_command(*command, token);
}
int is_variable_resolvable(char *token, t_State current_state)
{
return ((current_state == DOUBLE_QUOTE || (token[0] == '$'))
&& (current_state != SINGLE_QUOTE));
}

92
parsing/pipe.c Executable file
View File

@ -0,0 +1,92 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pipe.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/28 19:21:38 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 19:21:39 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static void create_and_handle_processes(t_process_params *params)
{
int i;
pid_t pid;
t_child_process_params child_params;
i = 0;
while (i < params->command_count)
{
pid = fork();
if (pid == 0)
{
child_params = (t_child_process_params){i, params->pipe_fds,
params->command_count, params->fd,
params->commands, params->shell};
setup_child_process(&child_params);
}
else if (pid < 0)
{
perror("fork");
exit(EXIT_FAILURE);
}
i++;
}
}
static void initialize_pipes(int *pipe_fds, int command_count)
{
int i;
i = 0;
while (i < command_count - 1)
{
if (pipe(pipe_fds + i * 2) < 0)
{
perror("pipe");
exit(EXIT_FAILURE);
}
i++;
}
}
static void wait_for_all_processes(int command_count)
{
int i;
i = 0;
while (i < command_count)
{
wait(NULL);
i++;
}
}
void process_pipe(t_command **commands,
t_minishell *shell, int command_count, int fd)
{
int *pipe_fds;
t_process_params params;
if (command_count == 1)
{
execute_command(commands[0], shell, fd);
return ;
}
pipe_fds = malloc(2 * (command_count - 1) * sizeof(int));
if (!pipe_fds)
{
perror("malloc");
exit(EXIT_FAILURE);
}
initialize_pipes(pipe_fds, command_count);
params = (t_process_params){pipe_fds, commands, shell, command_count, fd};
create_and_handle_processes(&params);
close_all_pipes(pipe_fds, 2 * (command_count - 1));
wait_for_all_processes(command_count);
free(pipe_fds);
}

40
parsing/pipe_utils.c Executable file
View File

@ -0,0 +1,40 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pipe_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/09 17:16:52 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 18:45:08 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void close_all_pipes(int *pipe_fds, int count)
{
int i;
i = 0;
while (i < count)
{
close(pipe_fds[i]);
i++;
}
}
void setup_child_process(t_child_process_params *params)
{
if (params->i != 0)
{
dup2(params->pipe_fds[(params->i - 1) * 2], STDIN_FILENO);
}
if (params->i != params->command_count - 1)
{
dup2(params->pipe_fds[params->i * 2 + 1], STDOUT_FILENO);
}
close_all_pipes(params->pipe_fds, 2 * (params->command_count - 1));
execute_command(params->commands[params->i], params->shell, params->fd);
exit(EXIT_SUCCESS);
}

82
parsing/redirection.c Executable file
View File

@ -0,0 +1,82 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* redirection.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/28 18:42:58 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 13:56:12 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void configure_redirection(char *file, int mode)
{
int fd;
if (mode == REDIRECT_IN)
{
fd = open(file, O_RDONLY);
dup2(fd, STDIN_FILENO);
close(fd);
}
else if (mode == REDIRECT_OUT)
{
fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
dup2(fd, STDOUT_FILENO);
close(fd);
}
else if (mode == REDIRECT_APPEND)
{
fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0644);
dup2(fd, STDOUT_FILENO);
close(fd);
}
else if (mode == REDIRECT_HEREDOC)
{
heredoc_input(file);
}
}
static t_redirection_mode get_redirection_mode(char *token)
{
if (ft_strcmp(token, ">") == 0)
return (REDIRECT_OUT);
if (ft_strcmp(token, "<") == 0)
return (REDIRECT_IN);
if (ft_strcmp(token, ">>") == 0)
return (REDIRECT_APPEND);
if (ft_strcmp(token, "<<") == 0)
return (REDIRECT_HEREDOC);
perror(RED"Redirection non reconnue"RST);
return (REDIRECT_UNKNOWN);
}
static void handle_redirection(char *token, t_redirection_mode redirection_mode)
{
if (redirection_mode == REDIRECT_HEREDOC)
heredoc_input(token);
else
configure_redirection(token, redirection_mode);
}
void process_redirection(t_process_token_params *params, t_command *commands,
t_minishell*shell, int fd)
{
t_redirection redir;
t_redirection_mode redirection_mode;
save_standard_descriptors(&redir);
redirection_mode
= get_redirection_mode(params->tokens[*(params->token_index)]);
if (redirection_mode == REDIRECT_UNKNOWN)
return ;
(*(params->token_index))++;
handle_redirection
(params->tokens[*(params->token_index)], redirection_mode);
execute_command(commands, shell, fd);
restore_standard_descriptors(&redir);
reset_command(*params->current_command);
}

33
parsing/redirection_utils.c Executable file
View File

@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* redirection_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/07 12:33:34 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 13:29:36 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void save_standard_descriptors(t_redirection *redir)
{
redir->stdin_backup = dup(STDIN_FILENO);
redir->stdout_backup = dup(STDOUT_FILENO);
}
void restore_standard_descriptors(t_redirection *redir)
{
if (redir->stdin_backup != -1)
{
dup2(redir->stdin_backup, STDIN_FILENO);
close(redir->stdin_backup);
}
if (redir->stdout_backup != -1)
{
dup2(redir->stdout_backup, STDOUT_FILENO);
close(redir->stdout_backup);
}
}

82
parsing/tree.c Executable file
View File

@ -0,0 +1,82 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* tree.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/30 12:03:54 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 13:56:39 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
t_command_node *create_command_node(t_command *command)
{
t_command_node *node;
node = malloc(sizeof(t_command_node));
if (node == NULL)
{
return (NULL);
}
node->command = command;
node->left = NULL;
node->right = NULL;
return (node);
}
void add_node_to_tree(t_command_node **root, t_command_node *new_node)
{
t_command_node *current;
if (*root == NULL)
{
*root = new_node;
}
else
{
current = *root;
while (current->right != NULL)
{
current = current->right;
}
current->right = new_node;
}
}
void execute_command_tree(t_command_node *node, t_minishell *shell,
int command_count, int fd)
{
t_command **commands_array;
t_command_node *current_node;
int i;
i = 0;
current_node = node;
commands_array = malloc(sizeof(t_command *) * command_count);
while (current_node != NULL && i < command_count)
{
commands_array[i] = current_node->command;
current_node = current_node->right;
i++;
}
process_pipe(commands_array, shell, command_count, fd);
free(commands_array);
}
void free_command_tree(t_command_node *node)
{
if (node == NULL)
{
return ;
}
free_command_tree(node->left);
free_command_tree(node->right);
if (node->command)
{
free(node->command);
}
free(node);
}

105
parsing/variable.c Executable file
View File

@ -0,0 +1,105 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* variable.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/29 21:41:34 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 14:10:45 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static char *allocate_exit_status_str(void)
{
char *exit_status_str;
exit_status_str = malloc(sizeof(char) * 12);
if (exit_status_str == NULL)
{
perror("Erreur d'allocation mémoire $");
return (NULL);
}
return (exit_status_str);
}
static int num_to_str(int num, char *str, int base)
{
int i;
int rem;
i = 0;
if (num == 0)
{
str[i++] = '0';
}
else
{
while (num != 0)
{
rem = num % base;
if (rem > 9)
str[i++] = (rem - 10) + 'a';
else
str[i++] = rem + '0';
num /= base;
}
}
str[i] = '\0';
return (i);
}
static void int_to_str(int num, char *str, int base)
{
int isnegative;
int length;
isnegative = 0;
if (num == 0)
{
str[0] = '0';
str[1] = '\0';
return ;
}
if (num < 0 && base == 10)
{
isnegative = 1;
num = -num;
}
length = num_to_str(num, str, base);
if (isnegative)
{
str[length] = '-';
str[length + 1] = '\0';
length++;
}
reverse_str(str, length);
}
static char *get_exit_status_str(t_minishell *shell)
{
char *exit_status_str;
exit_status_str = allocate_exit_status_str();
if (exit_status_str == NULL)
return (NULL);
int_to_str(shell->last_exit_status, exit_status_str, 10);
return (exit_status_str);
}
char *get_variable_value(const char *variable_name, t_minishell *shell)
{
const char *name_to_search;
char *value;
name_to_search = skip_dollar(variable_name);
if (ft_strcmp(name_to_search, "?") == 0)
{
value = get_exit_status_str(shell);
return (value);
}
value = search_env_variable(name_to_search, shell);
return (value);
}

57
parsing/variable_utils.c Executable file
View File

@ -0,0 +1,57 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* variable_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/07 10:46:07 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 14:11:44 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
const char *skip_dollar(const char *variable_name)
{
if (variable_name[0] == '$')
return (variable_name + 1);
return (variable_name);
}
void reverse_str(char *str, int length)
{
int start;
int end;
char temp;
start = 0;
end = length - 1;
while (start < end)
{
temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
char *search_env_variable(const char *name_to_search, t_minishell *shell)
{
int i;
char *env_entry;
size_t name_len;
name_len = ft_strlen(name_to_search);
i = 0;
while (shell->environ[i])
{
env_entry = shell->environ[i];
if (ft_strncmp(env_entry, name_to_search, name_len) == 0
&& env_entry[name_len] == '=')
return (ft_strdup(env_entry + name_len + 1));
i++;
}
return (ft_strdup(""));
}

71
prompt/history.c Executable file
View File

@ -0,0 +1,71 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* history.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 17:14:12 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 15:55:33 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void display_history_entry(HIST_ENTRY **the_history_list, int i)
{
printf("%d: %s\n", i + history_base, the_history_list[i]->line);
}
void display_history_list(void)
{
int i;
HIST_ENTRY **the_history_list;
i = 0;
the_history_list = history_list();
if (the_history_list)
{
while (the_history_list[i])
{
display_history_entry(the_history_list, i);
i++;
}
}
}
void search_in_history(HIST_ENTRY **the_history_list
, const char *search_string)
{
int i;
i = 0;
while (the_history_list[i])
{
if (ft_strstr(the_history_list[i]->line, search_string))
{
printf("%d: %s\n", i + history_base, the_history_list[i]->line);
}
i++;
}
}
void search_history(void)
{
char *search_string;
HIST_ENTRY **the_history_list;
search_string = readline("Rechercher dans l'historique: ");
if (search_string && *search_string)
{
the_history_list = history_list();
if (the_history_list)
{
search_in_history(the_history_list, search_string);
}
}
if (search_string)
{
free(search_string);
}
}

111
prompt/init_shell.c Executable file
View File

@ -0,0 +1,111 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* init_shell.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/21 20:21:25 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 15:47:18 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
static char *create_new_env_entry(char *name, char *value)
{
char *new_env_entry;
int name_len;
int value_len;
name_len = ft_strlen(name);
if (value)
{
value_len = ft_strlen(value);
}
else
{
value_len = 0;
}
new_env_entry = malloc(name_len + value_len + 2);
if (!new_env_entry)
exit(EXIT_FAILURE);
ft_strcpy(new_env_entry, name);
ft_strcat(new_env_entry, "=");
if (value)
ft_strcat(new_env_entry, value);
return (new_env_entry);
}
static char *process_env_entry(char *env_entry)
{
char *name;
char *value;
char *new_env_entry;
name = extract_name(env_entry);
value = extract_value(env_entry);
new_env_entry = create_new_env_entry(name, value);
free(name);
free(value);
return (new_env_entry);
}
static void init_environ(t_minishell *shell, char **envp)
{
int count;
int i;
count = 0;
while (envp[count])
count++;
shell->environ = malloc((count + 1) * sizeof(char *));
if (!shell->environ)
exit(EXIT_FAILURE);
i = 0;
while (envp[i])
{
shell->environ[i] = process_env_entry(envp[i]);
i++;
}
shell->environ[count] = NULL;
}
t_minishell init_minishell(char **envp, char **builtin_str,
int (**builtin_func)(char **, t_minishell *))
{
t_minishell shell;
shell.builtin_str = builtin_str;
shell.builtin_func = builtin_func;
init_environ(&shell, envp);
shell.last_exit_status = 0;
shell.tokenizer = malloc(sizeof(t_Tokenizer));
if (!shell.tokenizer)
return (shell);
shell.tokenizer->state = NORMAL;
shell.tokenizer->tokens = NULL;
shell.tokenizer->token = NULL;
shell.tokenizer->token_length = 0;
shell.tokenizer->input_pos = 0;
shell.tokenizer->token_pos = 0;
shell.tokenizer->in_quotes = false;
shell.tokenizer->variable = 0;
shell.tokenizer->symbol = true;
shell.is_piped = false;
return (shell);
}
bool is_builtin_command(const char *command, t_minishell *shell)
{
int i;
i = 0;
while (shell->builtin_str[i] != NULL)
{
if (ft_strcmp(command, shell->builtin_str[i]) == 0)
return (true);
i++;
}
return (false);
}

73
prompt/main.c Executable file
View File

@ -0,0 +1,73 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/14 19:37:18 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 18:52:00 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
char **initialize_builtin_str(void)
{
char **local_builtin_str;
local_builtin_str = malloc(8 * sizeof(char *));
if (!local_builtin_str)
return (NULL);
local_builtin_str[0] = "cd";
local_builtin_str[1] = "echo";
local_builtin_str[2] = "exit";
local_builtin_str[3] = "export";
local_builtin_str[4] = "env";
local_builtin_str[5] = "pwd";
local_builtin_str[6] = "unset";
local_builtin_str[7] = NULL;
return (local_builtin_str);
}
t_builtin_func_t *initialize_builtin_func(void)
{
t_builtin_func_t *local_builtin_func;
local_builtin_func = malloc(8 * sizeof(int (*)(char **, t_minishell *)));
if (!local_builtin_func)
return (NULL);
local_builtin_func[0] = &builtin_cd;
local_builtin_func[1] = &builtin_echo_wrapper;
local_builtin_func[2] = &builtin_exit;
local_builtin_func[3] = &builtin_export;
local_builtin_func[4] = &builtin_env;
local_builtin_func[5] = &builtin_pwd;
local_builtin_func[6] = &builtin_unset;
local_builtin_func[7] = NULL;
return (local_builtin_func);
}
int main(int argc, char **argv, char **envp)
{
t_minishell shell;
char **local_builtin_str;
int (**local_builtin_func)(char **, t_minishell *);
int fd;
(void)argc;
(void)argv;
fd = STDOUT_FILENO;
local_builtin_str = initialize_builtin_str();
local_builtin_func = initialize_builtin_func();
if (!local_builtin_str || !local_builtin_func)
{
return (1);
}
rl_bind_key('\t', rl_complete);
shell = init_minishell(envp, local_builtin_str, local_builtin_func);
prompt_loop(&shell, fd);
free(local_builtin_str);
free(local_builtin_func);
return (0);
}

57
prompt/prompt.c Executable file
View File

@ -0,0 +1,57 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* prompt.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/07 15:51:21 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 18:49:47 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void disable_tab_completion(void)
{
rl_bind_key('\t', rl_insert);
}
static void process_input_line(t_minishell *shell, char *line, int fd)
{
if (ft_strcmp(line, "history") == 0)
{
display_history_list();
}
else
{
tokenize_and_parse_input(line, shell, fd);
}
}
void prompt_loop(t_minishell *shell, int fd)
{
char *line;
int status;
setup_signal_handlers();
status = 1;
using_history();
disable_tab_completion();
while (status)
{
line = readline("\001"ORANGE"\002Minishell$> \001"RST"\002");
if (!line)
{
write(STDOUT_FILENO, "\n", 1);
break ;
}
if (!is_only_spaces(line) && ft_strcmp(line, "") != 0)
{
add_history(line);
process_input_line(shell, line, fd);
}
free(line);
}
clear_history();
}

43
signal/ctrl.c Executable file
View File

@ -0,0 +1,43 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ctrl.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/15 17:55:28 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 16:43:19 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void handle_sigint(int sig)
{
(void)sig;
write(STDOUT_FILENO, "\n", 1);
rl_on_new_line();
rl_replace_line("", 0);
rl_redisplay();
}
void handle_sigquit(int sig)
{
(void)sig;
printf("\b\b \b\b");
}
void setup_signal_handlers(void)
{
struct sigaction sa_int;
struct sigaction sa_quit;
sa_int.sa_handler = handle_sigint;
sigemptyset(&sa_int.sa_mask);
sa_int.sa_flags = SA_RESTART;
sigaction(SIGINT, &sa_int, NULL);
sa_quit.sa_handler = handle_sigquit;
sigemptyset(&sa_quit.sa_mask);
sa_quit.sa_flags = SA_RESTART;
sigaction(SIGQUIT, &sa_quit, NULL);
}

121
tokenize/quotes.c Executable file
View File

@ -0,0 +1,121 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* quotes.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/26 10:40:11 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 16:19:24 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
int are_only_quotes(char **tokens)
{
int i;
i = 0;
while (tokens && tokens[i])
{
if (ft_strcmp(tokens[i], "\"\"") != 0
&& ft_strcmp(tokens[i], "''") != 0)
return (0);
i++;
}
return (1);
}
void handle_normal_state(char input_char, t_Tokenizer *tk)
{
if (input_char == '\'')
{
tk->state = SINGLE_QUOTE;
}
else if (input_char == '\"')
{
tk->state = DOUBLE_QUOTE;
}
else
{
tk->token[(tk->token_length)++] = input_char;
tk->symbol = true;
}
}
void handle_double_quote_state(char input_char, t_Tokenizer *tk)
{
if (input_char != '\"')
{
tk->token[(tk->token_length)++] = input_char;
if (input_char == '$')
{
tk->variable = 0;
}
if (is_simple_symbol(input_char) == true)
tk->symbol = false;
}
else
{
if (tk->token_length > 0 && tk->token[tk->token_length - 1] == ' ')
{
tk->token[(tk->token_length)++] = input_char;
}
else
{
tk->state = NORMAL;
tk->symbol = true;
}
}
}
void handle_single_quote_state(char input_char, t_Tokenizer *tk)
{
if (input_char != '\'')
{
tk->token[(tk->token_length)++] = input_char;
if (input_char == '$')
{
tk->variable = 1;
}
if (is_simple_symbol(input_char) == true)
{
tk->symbol = false;
}
}
else
{
if (tk->token_length > 0 && tk->token[tk->token_length - 1] == ' ')
{
tk->token[(tk->token_length)++] = input_char;
}
else
{
tk->state = NORMAL;
}
}
}
char **handle_unclosed_quotes(char ***tokens, int token_pos)
{
int i;
i = 0;
if (tokens == NULL || *tokens == NULL)
{
return (NULL);
}
write(2, RED"Error: quote not closed\n"RST, 32);
if (token_pos > 0)
{
while (i < token_pos)
{
free((*tokens)[i]);
i++;
}
free(*tokens);
}
*tokens = NULL;
return (NULL);
}

112
tokenize/tokenize.c Executable file
View File

@ -0,0 +1,112 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* tokenize.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/21 20:09:39 by fgras-ca #+# #+# */
/* Updated: 2023/12/09 01:03:54 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
bool handle_quotes(char current_char, t_Tokenizer *tk)
{
if ((tk->state == NORMAL && (current_char == '\'' || current_char == '\"'))
|| (tk->state == SINGLE_QUOTE && current_char == '\'')
|| (tk->state == DOUBLE_QUOTE && current_char == '\"'))
{
if (tk->state == NORMAL)
{
if (current_char == '\'')
{
tk->state = SINGLE_QUOTE;
}
else
{
tk->state = DOUBLE_QUOTE;
}
}
else
tk->state = NORMAL;
tk->input_pos++;
return (true);
}
return (false);
}
void process_remaining_chars(char current_char, char *input, t_Tokenizer *tk)
{
if (tk->state != NORMAL)
{
process_char(current_char, tk);
tk->input_pos++;
return ;
}
if (current_char == ' ' || current_char == '\t')
{
if (tk->token_length > 0)
{
add_token_to_list(tk);
}
handle_spaces_and_tabs(input, tk);
}
else if (is_special_symbol(current_char, input[tk->input_pos + 1]))
add_special_symbol(input, tk);
else
{
process_char(current_char, tk);
tk->variable = 0;
tk->input_pos++;
}
}
void process_input_char(char *input, t_Tokenizer *tk)
{
char current_char;
current_char = input[tk->input_pos];
if (!handle_quotes(current_char, tk))
{
process_remaining_chars(current_char, input, tk);
}
}
void tokenize_loop(char *input, t_Tokenizer *tk)
{
while (input[tk->input_pos] != '\0')
{
process_input_char(input, tk);
}
if (tk->token_length > 0)
{
add_token_to_list(tk);
}
}
char **tokenize_and_parse_input(char *input, t_minishell *shell, int fd)
{
char **result;
if (is_only_spaces(input))
return (NULL);
init_vars(shell->tokenizer, input);
tokenize_loop(input, shell->tokenizer);
if (shell->tokenizer->state == SINGLE_QUOTE
|| shell->tokenizer->state == DOUBLE_QUOTE)
{
result = handle_unclosed_quotes(&shell->tokenizer->tokens,
shell->tokenizer->token_pos);
free(shell->tokenizer->token);
return (result);
}
add_token_to_list(shell->tokenizer);
if (shell->tokenizer->tokens != NULL)
shell->tokenizer->tokens[shell->tokenizer->token_pos] = NULL;
parse_tokens(shell->tokenizer->tokens, shell, fd);
free(shell->tokenizer->token);
free_tokens(shell->tokenizer->tokens);
return (NULL);
}

89
tokenize/tokenize_symbol.c Executable file
View File

@ -0,0 +1,89 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* tokenize_symbol.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/03 17:34:50 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 16:19:24 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void handle_spaces_and_tabs(char *input, t_Tokenizer *tk)
{
while (input[tk->input_pos] == ' ' || input[tk->input_pos] == '\t')
{
tk->input_pos++;
}
}
void add_special_symbol(char *input, t_Tokenizer *tk)
{
if (tk->token_length > 0)
{
add_token_to_list(tk);
}
tk->token[0] = input[tk->input_pos++];
tk->token_length = 1;
if ((tk->token[0] == '>' && input[tk->input_pos] == '>')
|| (tk->token[0] == '<' && input[tk->input_pos] == '<'))
{
tk->token[tk->token_length++] = input[tk->input_pos++];
}
tk->token[tk->token_length] = '\0';
add_token_to_list(tk);
}
void handle_empty_quotes(char *input, t_Tokenizer *tk)
{
char quote_type;
int start_pos;
int i;
quote_type = input[tk->input_pos];
start_pos = tk->input_pos;
tk->input_pos++;
while (input[tk->input_pos] != quote_type && input[tk->input_pos] != '\0')
{
tk->input_pos++;
}
if (input[tk->input_pos] == quote_type)
{
if (tk->input_pos - start_pos > 1)
{
i = start_pos + 1;
while (i < tk->input_pos)
{
tk->token[tk->token_length++] = input[i];
i++;
}
add_token_to_list(tk);
}
tk->input_pos++;
}
}
bool is_special_symbol(char c, char next_c)
{
if (c == '|' || c == '<' || c == '>')
{
return (true);
}
if ((c == '>' && next_c == '>') || (c == '<' && next_c == '<'))
{
return (true);
}
return (false);
}
bool is_simple_symbol(char c)
{
if (c == '|' || c == '<' || c == '>')
{
return (true);
}
return (false);
}

87
tokenize/tokenize_utils.c Executable file
View File

@ -0,0 +1,87 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* tokenize_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 17:41:31 by fgras-ca #+# #+# */
/* Updated: 2023/12/10 11:23:56 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
void free_tokens(char **tokens)
{
int i;
if (tokens != NULL)
{
i = 0;
while (tokens[i] != NULL)
{
free(tokens[i]);
i++;
}
free(tokens);
}
}
void add_token_to_list(t_Tokenizer *tk)
{
char *token_to_add;
if (tk->token_length > 0)
{
tk->token[tk->token_length] = '\0';
token_to_add = strdup(tk->token);
if (token_to_add != NULL)
{
tk->tokens[tk->token_pos++] = token_to_add;
}
tk->token_length = 0;
tk->within_single_quotes = false;
tk->within_double_quotes = false;
}
if (tk->token != NULL)
{
free(tk->token);
}
tk->token = malloc(1000);
if (tk->token != NULL)
{
ft_memset(tk->token, 0, 1000);
}
}
void process_char(char input_char, t_Tokenizer *tk)
{
if (tk->state == NORMAL)
{
handle_normal_state(input_char, tk);
}
else if (tk->state == SINGLE_QUOTE)
{
handle_single_quote_state(input_char, tk);
}
else if (tk->state == DOUBLE_QUOTE)
{
handle_double_quote_state(input_char, tk);
}
}
void init_vars(t_Tokenizer *tk, char *input)
{
tk->state = NORMAL;
tk->tokens = malloc(MAX_ARGS * sizeof(char *));
tk->token = malloc(ft_strlen(input) + 1);
tk->token_length = 0;
tk->input_pos = 0;
tk->token_pos = 0;
if (!(tk->tokens) || !(tk->token))
{
write(STDERR_FILENO, "Minishell: allocation error\n", 29);
exit(EXIT_FAILURE);
}
}

49
utils/utils.c Executable file
View File

@ -0,0 +1,49 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/01 17:49:16 by fgras-ca #+# #+# */
/* Updated: 2023/12/07 16:00:03 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minishell.h"
int is_only_spaces(const char *str)
{
while (*str)
{
if (*str != ' ' && *str != '\t')
return (0);
str++;
}
return (1);
}
char *get_env_value(const char *key, char **environ)
{
int i;
char *entry;
char *delim;
if (!key || !environ)
return (NULL);
i = 0;
entry = environ[i];
while (entry != NULL)
{
delim = strchr(entry, '=');
if (delim != NULL)
{
if (ft_strncmp(entry, key, delim - entry)
== 0 && ft_strlen(key) == (size_t)(delim - entry))
return (delim + 1);
}
i++;
entry = environ[i];
}
return (NULL);
}