################################## VARIABLES ###################################
################################################################################
+################################################################################
+################################## VARIABLES ###################################
+################################################################################
+
NAME := minishell
CC = cc
VPATH := src
SRC := main.c debug_tools.c init.c signal_handling.c repl.c new_token.c \
free_token.c new_node.c free_node.c tokenizer.c parser.c \
- parse_cmd.c collect_redirs.c print_ast.c
+ parse_cmd.c collect_redirs.c print_ast.c interpreter.c env.c \
+ get_cmd_path.c env_to_strlst.c execute_cmd.c format_string.c \
+ builtins_part_one.c builtins_part_two.c
OBJ_DIR := _obj
OBJ := $(addprefix $(OBJ_DIR)/, $(SRC:%.c=%.o))
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/08 16:53:39 by dkaiser #+# #+# */
-/* Updated: 2024/10/17 15:37:32 by chuhlig ### ########.fr */
+/* Updated: 2024/12/24 16:21:50 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
+#ifndef ENV_H
+# define ENV_H
+# include "libft.h"
+# include <stdio.h>
+
typedef struct s_env
{
char *name;
void getenvlst(t_env **env, char **en);
void free_envlst(t_env **env);
+char *env_get(t_env *env, char *name);
+char **env_to_strlst(t_env *env);
+void update_oldpwd(t_env **env);
+void update_pwd(t_env **env);
+int unset(char **av, t_env **env);
+int export(char **av, t_env **env);
+int echo(char **av);
+int pwd(t_env *env);
+int cd(t_env **env, char **args);
+int ft_env(t_env *env);
+#endif
\ No newline at end of file
/* ::: :::::::: */
/* minishell.h :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/22 17:14:49 by dkaiser #+# #+# */
-/* Updated: 2024/08/11 12:22:07 by dkaiser ### ########.fr */
+/* Updated: 2025/01/11 16:05:11 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
int init(void);
int init_signal_handling(void);
-void repl(const char *prompt);
+void repl(const char *prompt, t_env **env);
-t_list *parse(t_token *tokens);
-t_node *parse_cmd(t_token *tokens);
+t_list *parse(t_token *tokens, t_env **env);
+t_node *parse_cmd(t_token *tokens, t_env **env);
t_redirection *collect_redirs(t_token **tokens);
void print_ast(t_node *ast);
+int eval(t_node *node, t_env **env);
+char *get_cmd_path(char *cmd, t_env *env);
+int execute_cmd(t_cmd *cmd, t_env **env);
+char *format_string(char *str, t_env *env);
+
+
#endif
ft_strdup.c \
ft_striteri.c \
ft_strjoin.c \
+ ft_strcat.c \
+ ft_strcpy.c \
ft_strlcat.c \
ft_strlcpy.c \
ft_strlen.c \
get_next_line.c \
get_next_line_utils.c \
ft_atol.c \
+ ft_strcmp.c \
ft_lstnew_bonus.c \
ft_lstadd_front_bonus.c \
ft_lstsize_bonus.c \
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_strcat.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/09 13:06:44 by chuhlig #+# #+# */
+/* Updated: 2025/01/09 13:07:15 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+char *ft_strcat(char *dest, char *src)
+{
+ int i;
+ int j;
+
+ j = 0;
+ i = 0;
+ while (dest[i])
+ i++;
+ while (src[j])
+ {
+ dest[i + j] = src[j];
+ j++;
+ }
+ dest[i + j] = '\0';
+ return (dest);
+}
\ No newline at end of file
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_strcmp.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/12/18 19:03:14 by chuhlig #+# #+# */
+/* Updated: 2024/12/18 19:05:01 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "libft.h"
+
+int ft_strcmp(char *s1, char *s2)
+{
+ int i;
+
+ i = 0;
+ while (s1[i] && s1[i] == s2[i])
+ i++;
+ return (s1[i] - s2[i]);
+}
\ No newline at end of file
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_strcpy.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/09 14:38:30 by chuhlig #+# #+# */
+/* Updated: 2025/01/09 14:38:53 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+char *ft_strcpy(char *dest, char *src)
+{
+ int i;
+
+ i = 0;
+ while (src[i] != '\0')
+ {
+ dest[i] = src[i];
+ i++;
+ }
+ dest[i] = '\0';
+ return (dest);
+}
\ No newline at end of file
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/10 16:37:54 by dkaiser #+# #+# */
-/* Updated: 2024/08/11 14:01:57 by chuhlig ### ########.fr */
+/* Updated: 2025/01/09 14:39:28 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
int ft_isprint(int c);
int ft_isspace(char c);
int ft_isascii(int c);
+int ft_strcmp(char *s1, char *s2);
int ft_strlen(const char *str);
void *ft_memset(void *b, int c, size_t len);
void ft_bzero(void *s, size_t n);
void ft_putendl_fd(char *s, int fd);
void ft_putnbr_fd(int n, int fd);
char *ft_strncpy(char *s1, char *s2, int n);
+char *ft_strcat(char *dest, char *src);
+char *ft_strcpy(char *dest, char *src);
typedef struct s_list
{
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* builtins_part_one.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/08/09 17:01:16 by chuhlig #+# #+# */
+/* Updated: 2025/01/10 14:36:55 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "env.h"
+
+int echo(char **av)
+{
+ int i;
+ int f;
+
+ i = 1;
+ f = 1;
+ if (av[1] == NULL || av[1][0] == '\0')
+ {
+ write(1, "\n", 1);
+ return (1);
+ }
+ if (ft_strncmp(av[1], "-n", 3) == 0)
+ {
+ i++;
+ f = 0;
+ }
+ while (av[i])
+ {
+ write(1, av[i], ft_strlen(av[i]));
+ i++;
+ if (av[i])
+ write(1, " ", 1);
+ }
+ if (f)
+ write(1, "\n", 1);
+ return (0);
+}
+
+int pwd(t_env *env)
+{
+ while (env)
+ {
+ if (ft_strncmp(env->name, "PWD", 4) == 0)
+ {
+ ft_printf("%s\n", env->value);
+ break ;
+ }
+ env = env->next;
+ }
+ return (0);
+}
+
+int ft_env(t_env *env)
+{
+ while (env != NULL)
+ {
+ printf("%s", env->name);
+ printf("=%s\n", env->value);
+ env = env->next;
+ }
+ return (0);
+}
+
+// int exit(char *av)
+// {
+// freenode free toke free sequence stop repl free env;
+// clear history;
+// }
+////
+
+void free_env_node(t_env *node)
+{
+ free(node->name);
+ free(node->value);
+ free(node);
+}
+
+int unset(char **av, t_env **env)
+{
+ t_env *current;
+ t_env *prev;
+ int i;
+
+ i = 0;
+ while (av[++i])
+ {
+ current = *env;
+ prev = NULL;
+ while (current)
+ {
+ if (ft_strcmp(current->name, av[i]) == 0)
+ {
+ if (prev)
+ prev->next = current->next;
+ else
+ *env = current->next;
+ free_env_node(current);
+ break ;
+ }
+ prev = current;
+ current = current->next;
+ }
+ }
+ return (0);
+}
+
+t_env *env_new(char *name)
+{
+ t_env *result;
+
+ result = malloc(sizeof(t_env));
+ if (!result)
+ return (NULL);
+ result->name = name;
+ return (result);
+}
+
+t_env *check_existing(t_env *env, char *av)
+{
+ while (env)
+ {
+ if (ft_strcmp(env->name, av) == 0)
+ return (env);
+ env = env->next;
+ }
+ return (NULL);
+}
+
+int export(char **av, t_env **env)
+{
+ char *tmp;
+ t_env *current;
+ int i;
+
+ current = NULL;
+ i = 0;
+ while (av[++i])
+ {
+ if ((ft_strchr(av[i], '=')))
+ {
+ tmp = ft_strchr(av[i], '=');
+ *tmp = '\0';
+ current = check_existing(*env, av[i]);
+ if (current)
+ free(current->value);
+ else
+ {
+ current = env_new(ft_strdup(av[i]));
+ current->next = *env;
+ *env = current;
+ }
+ current->value = ft_strdup(tmp + 1);
+ }
+ }
+ return (0);
+}
\ No newline at end of file
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* builtins_part_two.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/10/25 20:52:16 by chuhlig #+# #+# */
+/* Updated: 2024/12/20 18:53:03 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "env.h"
+
+void update_oldpwd(t_env **env)
+{
+ t_env *current;
+ t_env *prev;
+ char cwd[1028];
+ char *tmp;
+
+ prev = NULL;
+ current = *env;
+ while (current)
+ {
+ if (ft_strncmp(current->name, "OLDPWD", 6) == 0)
+ break ;
+ prev = current;
+ current = current->next;
+ }
+ getcwd(cwd, sizeof(cwd));
+ tmp = ft_strdup(cwd);
+ free(current->value);
+ current->value = tmp;
+}
+
+void update_pwd(t_env **env)
+{
+ t_env *current;
+ t_env *prev;
+ char cwd[1028];
+ char *tmp;
+
+ prev = NULL;
+ current = *env;
+ while (current)
+ {
+ if (ft_strncmp(current->name, "PWD", 3) == 0)
+ break ;
+ prev = current;
+ current = current->next;
+ }
+ getcwd(cwd, sizeof(cwd));
+ tmp = ft_strdup(cwd);
+ free(current->value);
+ current->value = tmp;
+}
+
+int cd(t_env **env, char **av)
+{
+ t_env *current;
+
+ current = *env;
+ if (av[1] == NULL)
+ {
+ update_oldpwd(env);
+ while (current)
+ {
+ if (ft_strncmp(current->name, "HOME", 4) == 0)
+ break ;
+ current = current->next;
+ }
+ if (chdir(current->value) == -1)
+ return (1);
+ }
+ else
+ {
+ update_oldpwd(env);
+ if (chdir(av[1]) == -1)
+ return (1);
+ update_pwd(env);
+ }
+ return (0);
+}
/* ::: :::::::: */
/* collect_redirs.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/02 13:49:31 by dkaiser #+# #+# */
-/* Updated: 2024/09/17 19:48:48 by dkaiser ### ########.fr */
+/* Updated: 2025/01/13 09:52:00 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
-static t_token *collect_redir(t_token **tokens, t_redirection *result,
- t_token *cur);
-static void collect_and_check_redir(t_token **tokens, t_redirection *result,
- t_token **cur);
+static void collect_and_check_redir(t_redirection *result, t_token **cur);
static void set_redir(t_redirection *redir, int type, char *specifier);
-static int is_output_redir(int i);
+
+static char *read_heredoc(char *delimiter)
+{
+ char *line;
+ char *result;
+ char *temp;
+ size_t total_length;
+ size_t line_length;
+
+ total_length = 0;
+ result = NULL;
+ while (1)
+ {
+ line = readline("> ");
+ if (!line || ft_strcmp(line, delimiter) == 0)
+ {
+ free(line);
+ break ;
+ }
+ line_length = ft_strlen(line) + 1;
+ temp = malloc(total_length + line_length + 1);
+ if (!temp)
+ {
+ perror("malloc");
+ free(result);
+ return (NULL);
+ }
+ if (result)
+ {
+ ft_strcpy(temp, result);
+ free(result);
+ }
+ else
+ {
+ temp[0] = '\0';
+ }
+ ft_strcat(temp, line);
+ ft_strcat(temp, "\n");
+ result = temp;
+ total_length += line_length;
+ free(line);
+ }
+ return (result);
+}
t_redirection *collect_redirs(t_token **tokens)
{
while (cur != NULL && cur->next != NULL)
{
if (cur->type == REDIR_TOKEN && cur->next->type == STRING_TOKEN)
- collect_and_check_redir(tokens, result, &cur);
+ collect_and_check_redir(result, &cur);
else if (cur->type == REDIR_TOKEN)
return (free(result), NULL);
else
return (result);
}
-static void collect_and_check_redir(t_token **tokens, t_redirection *result,
- t_token **cur)
-{
- int is_redir_only;
-
- is_redir_only = 0;
- if ((*cur)->previous == NULL && (*cur)->next->next == NULL)
- is_redir_only = 1;
- *cur = collect_redir(tokens, result, *cur);
- if (is_redir_only)
- *tokens = NULL;
-}
-
-static t_token *collect_redir(t_token **tokens, t_redirection *result,
- t_token *cur)
-{
- set_redir(&result[is_output_redir(cur->content.redir_type)],
- cur->content.redir_type, cur->next->content.string);
- cur = cur->next;
- free_token_and_connect(cur->previous);
- if (cur->next != NULL)
- {
- if (cur->previous == NULL)
- *tokens = cur->next;
- cur = cur->next;
- free_token_and_connect(cur->previous);
- }
- else
- {
- free_token(cur);
- return (NULL);
- }
- return (cur);
-}
-
static void set_redir(t_redirection *redir, int type, char *specifier)
{
redir->type = type;
redir->specifier = specifier;
}
-static int is_output_redir(int i)
+static void collect_and_check_redir(t_redirection *result, t_token **cur)
{
- if (i & (INPUT_FILE | INPUT_LIMITER))
- return (0);
- else if (i & (OUTPUT_APPEND | OUTPUT_OVERRIDE))
- return (1);
+ char *heredoc_data;
+ t_token *next_token;
+
+ heredoc_data = NULL;
+ if ((*cur)->content.redir_type == INPUT_LIMITER)
+ {
+ heredoc_data = read_heredoc((*cur)->next->content.string);
+ if (!heredoc_data)
+ {
+ perror("Heredoc allocation failed");
+ return ;
+ }
+ set_redir(&result[0], INPUT_LIMITER, heredoc_data);
+ }
+ else if ((*cur)->content.redir_type == INPUT_FILE)
+ set_redir(&result[0], INPUT_FILE, ft_strdup((*cur)->next->content.string));
+ else if ((*cur)->content.redir_type == OUTPUT_OVERRIDE)
+ set_redir(&result[1], OUTPUT_OVERRIDE, ft_strdup((*cur)->next->content.string));
+ else if ((*cur)->content.redir_type == OUTPUT_APPEND)
+ set_redir(&result[1], OUTPUT_APPEND, ft_strdup((*cur)->next->content.string));
else
+ printf("Unknown redirection type encountered\n");
+ next_token = (*cur)->next;
+ free_token_and_connect(*cur);
+ if (next_token)
{
- panic(UNREACHABLE);
- return (-1);
+ *cur = next_token->next;
+ free_token_and_connect(next_token);
}
+ else
+ *cur = NULL;
}
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/17 14:31:07 by chuhlig #+# #+# */
-/* Updated: 2024/10/17 15:18:44 by chuhlig ### ########.fr */
+/* Updated: 2024/12/17 19:36:14 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "env.h"
+#include <stdlib.h>
void getenvlst(t_env **env, char **en)
{
while (en[i] != NULL)
{
tmp = ft_strchr(en[i], '=');
- tmp = '\0';
+ *tmp = '\0';
current = *env;
current = malloc(sizeof(t_env));
current->name = ft_strdup(en[i]);
free(cur);
cur = new;
}
+}
+
+char *env_get(t_env *env, char *name)
+{
+ while (env != NULL)
+ {
+ if (!ft_strncmp(env->name, name, ft_strlen(name)))
+ return (env->value);
+ env = env->next;
+ }
+ return (NULL);
}
\ No newline at end of file
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* env_to_strlst.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/12/17 19:22:28 by chuhlig #+# #+# */
+/* Updated: 2024/12/17 19:22:36 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "libft.h"
+#include "minishell.h"
+
+static char *get_var_assign(t_env *cur);
+
+char **env_to_strlst(t_env *env)
+{
+ int size;
+ t_env *cur;
+ char **result;
+ int i;
+
+ size = 0;
+ cur = env;
+ while (cur != NULL)
+ {
+ size++;
+ cur = cur->next;
+ }
+ result = malloc(sizeof(char *) * (size + 1));
+ if (result == NULL)
+ return (NULL);
+ i = 0;
+ cur = env;
+ while (i < size)
+ {
+ result[i] = get_var_assign(cur);
+ cur = cur->next;
+ i++;
+ }
+ result[i] = NULL;
+ return (result);
+}
+
+static char *get_var_assign(t_env *cur)
+{
+ char *left_side;
+ char *result;
+
+ left_side = ft_strjoin(cur->name, "=");
+ if (left_side == NULL)
+ return (NULL);
+ result = ft_strjoin(left_side, cur->value);
+ free(left_side);
+ return (result);
+}
\ No newline at end of file
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* execute_cmd.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/12/17 19:21:35 by chuhlig #+# #+# */
+/* Updated: 2025/01/13 09:50:56 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/_types/_pid_t.h>
+#include <sys/_types/_s_ifmt.h>
+#include <sys/fcntl.h>
+#include <unistd.h>
+
+int execute_cmd(t_cmd *cmd, t_env **env)
+{
+ char *cmd_path;
+ pid_t pid;
+ int status;
+ int result;
+ int original_stdout;
+ int original_stdin;
+
+ original_stdout = dup(STDOUT_FILENO);
+ original_stdin = dup(STDIN_FILENO);
+ if (handle_redirections(cmd->redirs) == -1)
+ {
+ dup2(original_stdout, STDOUT_FILENO);
+ dup2(original_stdin, STDIN_FILENO);
+ close(original_stdout);
+ close(original_stdin);
+ return (EXIT_FAILURE);
+ }
+ if (is_builtin(cmd->args[0]))
+ {
+ result = execute_builtin(cmd->args, env);
+ dup2(original_stdout, STDOUT_FILENO);
+ dup2(original_stdin, STDIN_FILENO);
+ close(original_stdout);
+ close(original_stdin);
+ return (result);
+ }
+ pid = fork();
+ if (pid == -1)
+ {
+ perror("fork");
+ dup2(original_stdout, STDOUT_FILENO);
+ dup2(original_stdin, STDIN_FILENO);
+ close(original_stdout);
+ close(original_stdin);
+ return (EXIT_FAILURE);
+ }
+ if (pid == 0)
+ {
+ cmd_path = get_cmd_path(cmd->args[0], *env);
+ if (!cmd_path)
+ {
+ printf("%s: command not found\n", cmd->args[0]);
+ exit(EXIT_FAILURE);
+ }
+ execve(cmd_path, cmd->args, env_to_strlst(*env));
+ perror("execve");
+ exit(EXIT_FAILURE);
+ }
+ waitpid(pid, &status, 0);
+ dup2(original_stdout, STDOUT_FILENO);
+ dup2(original_stdin, STDIN_FILENO);
+ close(original_stdout);
+ close(original_stdin);
+ return (WEXITSTATUS(status));
+}
\ No newline at end of file
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* format_string.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/12/17 19:30:11 by chuhlig #+# #+# */
+/* Updated: 2024/12/17 19:31:54 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "get_next_line.h"
+#include "libft.h"
+#include "minishell.h"
+
+static void append_slice(char **dst, char *src, int start, int end);
+static void append_var(char **dst, char *src, int *pos, t_env *env);
+
+enum e_format_mode
+{
+ LITERAL = 1,
+ VARIABLE = 2,
+};
+
+char *format_string(char *str, t_env *env)
+{
+ char *result;
+ int pos;
+ int start;
+ int mode;
+
+ pos = 0;
+ start = 0;
+ mode = 0;
+ result = NULL;
+ if (str == NULL)
+ return (NULL);
+ while (str[pos] != '\0')
+ {
+ if (str[pos] == '\'')
+ {
+ append_slice(&result, str, start, pos);
+ start = pos + 1;
+ mode ^= LITERAL;
+ }
+ if (str[pos] == '"' && !(mode & LITERAL))
+ {
+ append_slice(&result, str, start, pos);
+ start = pos + 1;
+ }
+ if (str[pos] == '$' && !(mode & LITERAL))
+ {
+ append_slice(&result, str, start, pos);
+ append_var(&result, str, &pos, env);
+ start = pos;
+ continue ;
+ }
+ pos++;
+ }
+ append_slice(&result, str, start, pos);
+ return (result);
+}
+
+static void append_slice(char **dst, char *src, int start, int end)
+{
+ char *result;
+ int len;
+ int i;
+
+ if (*dst != NULL)
+ len = ft_strlen(*dst);
+ else
+ {
+ len = 0;
+ }
+ result = malloc(len + (end - start) + 1);
+ if (!result)
+ return ;
+ ft_strncpy(result, *dst, len);
+ i = 0;
+ while (start + i < end)
+ {
+ result[len + i] = src[start + i];
+ i++;
+ }
+ result[len + i] = '\0';
+ if (*dst != NULL)
+ free(*dst);
+ *dst = result;
+}
+
+static void append_var(char **dst, char *src, int *pos, t_env *env)
+{
+ int i;
+ char *var;
+ char *value;
+ char *result;
+
+ i = 0;
+ *pos += 1;
+ while (src[*pos + i] != '\0' && src[*pos + i] != '\'' && src[*pos
+ + i] != '"' && src[*pos + i] != '$')
+ {
+ i++;
+ }
+ var = malloc(i + 1);
+ if (var == NULL)
+ return ;
+ var[i] = '\0';
+ i--;
+ while (i >= 0)
+ {
+ var[i] = src[*pos + i];
+ i--;
+ }
+ value = env_get(env, var);
+ if (value != NULL)
+ {
+ result = ft_strjoin(*dst, value);
+ free(*dst);
+ *dst = result;
+ }
+ *pos += ft_strlen(var);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* get_cmd_path.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/12/17 19:19:59 by chuhlig #+# #+# */
+/* Updated: 2024/12/17 19:20:08 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "libft.h"
+#include "minishell.h"
+
+static char *get_absolute_cmd_path(char *cmd, t_env *env);
+static char *find_in_path(char *cmd, t_env *env);
+char **get_split_path(t_env *env);
+
+char *get_cmd_path(char *cmd, t_env *env)
+{
+ if (cmd[0] == '/')
+ return (ft_strdup(cmd));
+ else if (ft_strchr(cmd, '/'))
+ return (get_absolute_cmd_path(cmd, env));
+ else
+ return (find_in_path(cmd, env));
+}
+
+static char *get_absolute_cmd_path(char *cmd, t_env *env)
+{
+ char *cur_dir;
+ char *result;
+
+ cur_dir = ft_strjoin(env_get(env, "PWD"), "/");
+ if (!cur_dir)
+ return (NULL);
+ result = ft_strjoin(cur_dir, cmd);
+ free(cur_dir);
+ if (!result)
+ return (NULL);
+ if (access(result, X_OK) == -1)
+ {
+ free(result);
+ return (NULL);
+ }
+ return (result);
+}
+
+static char *find_in_path(char *cmd, t_env *env)
+{
+ char *cur_path;
+ char *cmd_path;
+ char **path;
+
+ path = get_split_path(env);
+ cmd_path = NULL;
+ while (*path)
+ {
+ if (cmd_path)
+ free(cmd_path);
+ cur_path = ft_strjoin(*path, "/");
+ if (!cur_path)
+ return (NULL);
+ cmd_path = ft_strjoin(cur_path, cmd);
+ free(cur_path);
+ if (!cmd_path)
+ return (NULL);
+ if (access(cmd_path, X_OK) != -1)
+ return (cmd_path);
+ path++;
+ }
+ return (NULL);
+}
+
+char **get_split_path(t_env *env)
+{
+ char *path;
+
+ path = env_get(env, "PATH");
+ return (ft_split(path, ':'));
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* interpreter.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/12/17 19:15:49 by chuhlig #+# #+# */
+/* Updated: 2025/01/13 09:53:33 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "debug_tools.h"
+#include "minishell.h"
+#include <stdlib.h>
+#include <sys/_types/_pid_t.h>
+#include <sys/cdefs.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+
+int is_builtin(char *cmd)
+{
+ return ((ft_strcmp(cmd, "export") == 0)
+ || (ft_strcmp(cmd, "unset") == 0)
+ || (ft_strcmp(cmd, "cd") == 0)
+ || (ft_strcmp(cmd, "exit") == 0)
+ || (ft_strcmp(cmd, "echo") == 0)
+ || (ft_strcmp(cmd, "pwd") == 0)
+ || (ft_strcmp(cmd, "env") == 0));
+}
+
+int execute_builtin(char **args, t_env **env)
+{
+ if (ft_strcmp(args[0], "export") == 0)
+ return (export(args, env));
+ else if (ft_strcmp(args[0], "unset") == 0)
+ return (unset(args, env));
+ else if (ft_strcmp(args[0], "cd") == 0)
+ return (cd(env, args));
+ else if (ft_strcmp(args[0], "exit") == 0)
+ return (EXIT_SUCCESS);
+ else if (ft_strcmp(args[0], "echo") == 0)
+ return (echo(args));
+ else if (ft_strcmp(args[0], "pwd") == 0)
+ return (pwd(*env));
+ else if (ft_strcmp(args[0], "env") == 0)
+ return (ft_env(*env));
+ return (1);
+}
+
+static int handle_redirections(t_redirection *redirs)
+{
+ int fd;
+
+ if (redirs[0].type == INPUT_FILE)
+ {
+ fd = open(redirs[0].specifier, O_RDONLY);
+ if (fd < 0)
+ {
+ perror("open");
+ return (-1);
+ }
+ dup2(fd, STDIN_FILENO);
+ close(fd);
+ }
+ else if (redirs[0].type == INPUT_LIMITER)
+ {
+ fd = open("/tmp/heredoc_tmp", O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0)
+ {
+ perror("open");
+ return (-1);
+ }
+ write(fd, redirs[0].specifier, ft_strlen(redirs[0].specifier));
+ close(fd);
+ fd = open("/tmp/heredoc_tmp", O_RDONLY);
+ if (fd < 0)
+ {
+ perror("open");
+ return (-1);
+ }
+ dup2(fd, STDIN_FILENO);
+ close(fd);
+ }
+ if (redirs[1].type == OUTPUT_OVERRIDE)
+ {
+ fd = open(redirs[1].specifier, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0)
+ {
+ perror("open");
+ return (-1);
+ }
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+ }
+ else if (redirs[1].type == OUTPUT_APPEND)
+ {
+ fd = open(redirs[1].specifier, O_WRONLY | O_CREAT | O_APPEND, 0644);
+ if (fd < 0)
+ {
+ perror("open");
+ return (-1);
+ }
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+ }
+ return (0);
+ }
+
+static int eval_rec(t_node *node, t_env **env, int in_fd)
+{
+ pid_t pid;
+ int p[2];
+ int result;
+ int status;
+ int original_stdin;
+
+ if (node->type == PIPE_NODE)
+ {
+ pipe(p);
+ pid = fork();
+ if (pid == 0)
+ {
+ close(p[0]);
+ dup2(in_fd, STDIN_FILENO);
+ dup2(p[1], STDOUT_FILENO);
+ result = eval_rec(node->content.pipe.left, env, in_fd);
+ exit(result);
+ }
+ else
+ {
+ close(p[1]);
+ original_stdin = dup(STDIN_FILENO);
+ dup2(p[0], STDIN_FILENO);
+ result = eval_rec(node->content.pipe.right, env, p[0]);
+ waitpid(pid, &status, 0);
+ dup2(original_stdin, STDIN_FILENO);
+ close(original_stdin);
+ }
+ }
+ else if (node->type == CMD_NODE)
+ {
+ result = execute_cmd(&node->content.cmd, env);
+ }
+ else
+ {
+ printf("Handling unknown node type\n");
+ panic("UNREACHABLE");
+ result = EXIT_FAILURE;
+ }
+ return (result);
+}
+
+int eval(t_node *node, t_env **env)
+{
+ return (eval_rec(node, env, STDIN_FILENO));
+}
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/22 17:14:03 by dkaiser #+# #+# */
-/* Updated: 2024/07/18 16:44:14 by chuhlig ### ########.fr */
+/* Updated: 2024/12/17 19:26:42 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "../include/minishell.h"
-int main(void)
+int main(int argc, char *argv[], char *envp[])
{
+ t_env *env;
+
+ env = NULL;
+ if (!argc && !argv)
+ return (1);
if (init())
return (1);
- repl("Minishell $ ");
+ getenvlst(&env, envp);
+ repl("Minishell $ ", &env);
}
/* ::: :::::::: */
/* parse_cmd.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/07/08 15:06:25 by dkaiser #+# #+# */
-/* Updated: 2024/08/11 12:20:06 by dkaiser ### ########.fr */
+/* Updated: 2025/01/11 16:04:50 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
-static char **collect_args(t_token **tokens);
+static char **collect_args(t_token **tokens, t_env **env);
-t_node *parse_cmd(t_token *tokens)
+t_node *parse_cmd(t_token *tokens, t_env **env)
{
char **args;
t_redirection *redirs;
redirs = collect_redirs(&tokens);
- args = collect_args(&tokens);
+ if (redirs == NULL)
+ return (NULL);
+ args = collect_args(&tokens, env);
+ if (args == NULL)
+ {
+ free(redirs);
+ return (NULL);
+ }
return (new_cmd_node(args, redirs));
}
-static char **collect_args(t_token **tokens)
+static char **collect_args(t_token **tokens, t_env **env)
{
t_token *cur;
char **result;
{
if (cur->previous)
free_token(cur->previous);
- result[i] = cur->content.string;
+ result[i] = format_string(cur->content.string, *env);
i++;
cur = cur->next;
}
/* ::: :::::::: */
/* parser.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/29 15:53:29 by dkaiser #+# #+# */
-/* Updated: 2024/09/17 19:03:48 by dkaiser ### ########.fr */
+/* Updated: 2025/01/11 16:06:54 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
#include "minishell.h"
#include "token.h"
+#include "env.h"
static t_token *find_token_by_type(t_token *tokens, int type);
t_token *split_at_first(t_token **tokens, int type);
-static t_node *parse_statement(t_token *tokens);
+static t_node *parse_statement(t_token *tokens, t_env **env);
-t_list *parse(t_token *tokens)
+t_list *parse(t_token *tokens, t_env **env)
{
t_node *result;
if ((*tokens).type == PIPE_TOKEN)
result = NULL;
else
- result = parse_statement(tokens);
+ result = parse_statement(tokens, env);
if (result == NULL)
printf("Parsing error.\n");
return (ft_lstnew(result));
}
-static t_node *parse_statement(t_token *tokens)
+static t_node *parse_statement(t_token *tokens, t_env **env)
{
t_token *left_side_tokens;
}
else if (tokens != NULL)
{
- return (new_pipe_node(parse_cmd(left_side_tokens),
- parse_statement(tokens)));
+ return (new_pipe_node(parse_cmd(left_side_tokens, env),
+ parse_statement(tokens, env)));
}
else
{
- return (parse_cmd(left_side_tokens));
+ return (parse_cmd(left_side_tokens, env));
}
}
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/24 16:07:04 by dkaiser #+# #+# */
-/* Updated: 2024/09/13 16:26:35 by dkaiser ### ########.fr */
+/* Updated: 2025/01/11 16:01:44 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "../include/minishell.h"
#include "token.h"
-void repl(const char *prompt)
+t_token *reverse_token_list(t_token *head)
+{
+ t_token *prev;
+ t_token *current;
+ t_token *next;
+
+ prev = NULL;
+ current = head;
+ next = NULL;
+ while (current != NULL)
+ {
+ next = current->previous;
+ current->next = prev;
+ current->previous = next;
+ prev = current;
+ current = next;
+ }
+ return (prev);
+}
+
+void repl(const char *prompt, t_env **env)
{
char *input;
t_token *token_list;
add_history(input);
token_list = NULL;
tokenizer(input, &token_list, '\0');
- lines = parse(token_list);
+ token_list = reverse_token_list(token_list);
+ lines = parse(token_list, env);
if (lines)
+ {
print_ast(lines->content);
+ eval(lines->content, env);
+ }
free(input);
}
}
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/28 20:55:50 by chuhlig #+# #+# */
-/* Updated: 2024/08/29 15:26:55 by dkaiser ### ########.fr */
+/* Updated: 2025/01/11 15:22:07 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
pos = i + 1;
}
}
- while ((*token_list)->previous)
- *token_list = (*token_list)->previous;
}