aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/builtins_part_one.c172
-rw-r--r--src/builtins_part_three.c85
-rw-r--r--src/builtins_part_two.c55
-rw-r--r--src/collect_redirs.c118
-rw-r--r--src/create_files.c61
-rw-r--r--src/debug_tools.c6
-rw-r--r--src/env.c25
-rw-r--r--src/env_to_strlst.c30
-rw-r--r--src/env_tools.c21
-rw-r--r--src/error.c30
-rw-r--r--src/execute_cmd.c130
-rw-r--r--src/format_string.c125
-rw-r--r--src/free_token.c7
-rw-r--r--src/get_cmd_path.c73
-rw-r--r--src/handle_redir.c103
-rw-r--r--src/init.c4
-rw-r--r--src/interpreter.c79
-rw-r--r--src/main.c12
-rw-r--r--src/new_node.c9
-rw-r--r--src/new_token.c27
-rw-r--r--src/parse_cmd.c31
-rw-r--r--src/parser.c21
-rw-r--r--src/praise_the_norme.c30
-rw-r--r--src/read_heredoc.c76
-rw-r--r--src/repl.c19
-rw-r--r--src/signal_handling.c4
-rw-r--r--src/tokenizer.c25
27 files changed, 1006 insertions, 372 deletions
diff --git a/src/builtins_part_one.c b/src/builtins_part_one.c
index 6b92d9c..11989cc 100644
--- a/src/builtins_part_one.c
+++ b/src/builtins_part_one.c
@@ -6,147 +6,115 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/09 17:01:16 by chuhlig #+# #+# */
-/* Updated: 2024/10/25 20:52:36 by chuhlig ### ########.fr */
+/* Updated: 2025/01/20 19:07:18 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "env.h"
+#include <stdio.h>
-int echo(char **av)
+int unset(char **av, t_env **env)
{
- int i;
- int f;
+ t_env *current;
+ t_env *prev;
+ int i;
- i = 1;
- f = 1;
- if (av[1][0] == '\0')
- {
- write(1, "\n", 1);
- return (1);
- }
- if (ft_strcmp(av[1], "-n"))
- {
- i++;
- f = 0;
- }
- while (av[i])
+ i = 0;
+ while (av[++i])
{
- write(1, &av[1], ft_strlen(av[i]));
- 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;
+ }
}
- if (f)
- write(1, "\n", 1);
return (0);
}
-int pwd(t_env **env, char *av)
+t_env *check_existing(t_env *env, char *av)
{
- t_env *current;
- t_env *prev;
- char *tmp;
-
- current = env;
- prev = NULL;
- while (current)
+ while (env)
{
- if (ft_strcmp(current->name, av == 0))
- break ;
- prev = current;
- current = current->next;
+ if (ft_strcmp("$", av) == 0)
+ return (NULL);
+ if (ft_strcmp(env->name, av) == 0)
+ return (env);
+ env = env->next;
}
- ft_printf("%s\n", current->value);
- return (0);
+ return (NULL);
}
-int env(t_env **env)
+void export_export(char *av, t_env **env)
{
+ char *tmp;
t_env *current;
- t_env *prev;
- current = env;
- prev = NULL;
- while (current)
+ current = NULL;
+ tmp = ft_strchr(av, '=');
+ *tmp = '\0';
+ current = check_existing(*env, av);
+ if (current)
+ free(current->value);
+ else
{
- ft_printf("%s", current->name);
- ft_printf("=%s\n", current->value);
- prev = current;
- current = current->next;
+ current = env_new(ft_strdup(av));
+ current->next = *env;
+ *env = current;
}
- return (0);
+ current->value = ft_strdup(tmp + 1);
}
-int exit(char *av)
+int is_valid_identifier(char *str)
{
- freenode free toke free sequence stop repl free env;
- clear history;
-}
-
-int export(char **av, t_env **env)
-{
- char *tmp;
- t_env *current;
- int i;
+ int i;
- i = i;
- while (av[i])
+ i = 0;
+ if (!ft_isalpha(str[0]) && str[0] != '_')
+ return (0);
+ while (str[i] && str[i] != '=')
{
- if (t_strchr(av[i], '='))
- {
- tmp = ft_strchr(av[i], '=');
- tmp = '\0';
- current = *env;
- while (current)
- {
- if (ft_strcmp(current->name, tmp[i]) == 0)
- {
- free(current->value);
- current->value = ft_strdup(tmp + 1);
- break ;
- }
- current = current->next;
- }
- if (!current)
- {
- current = malloc(sizeof(t_env));
- current->name = ft_strdup(av[i]);
- current->value = ft_strdup(tmp + 1);
- current->next = *env;
- *env = current;
- }
- }
+ if (!ft_isalnum(str[i]) && str[i] != '_')
+ return (0);
i++;
}
return (1);
}
-int unset(char **av, t_env **env)
+int export(char **av, t_env **env, int f)
{
- t_env *current;
- t_env *prev;
+ char *equal_sign;
int i;
i = 0;
- current = env;
- prev = NULL;
- while (av[i])
+ while (av[++i])
{
- while (current)
+ equal_sign = ft_strchr(av[i], '=');
+ if (equal_sign)
+ *equal_sign = '\0';
+ if (!is_valid_identifier(av[i]))
{
- if (ft_strcmp(current->name, av[i] == 0))
- break ;
- prev = current;
- current = current->next;
+ write(1, "Minishell $ export: not a valid identifier\n", 43);
+ if (equal_sign)
+ *equal_sign = '=';
+ f++;
+ continue ;
}
- if (current)
+ if (equal_sign)
{
- if (prev)
- prev->next = current->next;
- else
- *env = current->next;
- free(current->value);
- free(current);
+ *equal_sign = '=';
+ export_export(av[i], env);
}
- i++;
}
- return (0);
-} \ No newline at end of file
+ return (check_flag(f));
+}
diff --git a/src/builtins_part_three.c b/src/builtins_part_three.c
new file mode 100644
index 0000000..5f6fa31
--- /dev/null
+++ b/src/builtins_part_three.c
@@ -0,0 +1,85 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* builtins_part_three.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/18 18:29:24 by chuhlig #+# #+# */
+/* Updated: 2025/01/20 17:08:17 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "env.h"
+
+void exit_shell(t_env **env, int exit_status)
+{
+ free_envlst(env);
+ exit(exit_status);
+}
+
+int builtin_exit(char **av, t_env **env)
+{
+ int exit_status;
+
+ if (av[1] && !av[2])
+ exit_status = ft_atoi(av[1]);
+ else if (av[2])
+ exit_status = 1;
+ else
+ exit_status = 0;
+ exit_shell(env, exit_status);
+ return (exit_status);
+}
+
+void set_return_code(int return_code, t_env **env)
+{
+ t_env *cur;
+
+ cur = check_existing(*env, "?");
+ if (cur)
+ free(cur->value);
+ else
+ {
+ cur = env_new(ft_strdup("?"));
+ cur->next = *env;
+ *env = cur;
+ }
+ cur->value = ft_itoa(return_code);
+}
+
+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 (0);
+ }
+ 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 check_flag(int f)
+{
+ if (f)
+ return (1);
+ return (0);
+}
diff --git a/src/builtins_part_two.c b/src/builtins_part_two.c
index 94ef258..e461861 100644
--- a/src/builtins_part_two.c
+++ b/src/builtins_part_two.c
@@ -6,7 +6,7 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/25 20:52:16 by chuhlig #+# #+# */
-/* Updated: 2024/10/25 20:52:46 by chuhlig ### ########.fr */
+/* Updated: 2025/01/20 19:12:33 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
@@ -19,6 +19,8 @@ void update_oldpwd(t_env **env)
char cwd[1028];
char *tmp;
+ prev = NULL;
+ current = *env;
while (current)
{
if (ft_strncmp(current->name, "OLDPWD", 6) == 0)
@@ -39,6 +41,8 @@ void update_pwd(t_env **env)
char cwd[1028];
char *tmp;
+ prev = NULL;
+ current = *env;
while (current)
{
if (ft_strncmp(current->name, "PWD", 3) == 0)
@@ -55,28 +59,57 @@ void update_pwd(t_env **env)
int cd(t_env **env, char **av)
{
t_env *current;
- t_env *prev;
- t_env *pwd;
- current = env;
+ current = *env;
if (av[1] == NULL)
{
- update_oldpwd(&env);
+ update_oldpwd(env);
while (current)
{
if (ft_strncmp(current->name, "HOME", 4) == 0)
break ;
- prev = current;
current = current->next;
}
if (chdir(current->value) == -1)
- return ;
+ return (1);
+ update_pwd(env);
}
else
{
- update_oldpwd(&env);
+ update_oldpwd(env);
if (chdir(av[1]) == -1)
- return ;
- update_pwd(&env);
+ return (1);
+ update_pwd(env);
+ }
+ 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;
}
-} \ No newline at end of file
+ return (0);
+}
+
+int ft_env(t_env *env)
+{
+ while (env != NULL)
+ {
+ if (ft_strchr(env->name, '?'))
+ {
+ env = env->next;
+ continue ;
+ }
+ printf("%s", env->name);
+ printf("=%s\n", env->value);
+ env = env->next;
+ }
+ return (0);
+}
diff --git a/src/collect_redirs.c b/src/collect_redirs.c
index 9ac1605..f274053 100644
--- a/src/collect_redirs.c
+++ b/src/collect_redirs.c
@@ -3,37 +3,42 @@
/* ::: :::::::: */
/* 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/20 18:39:24 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
+#include <stdlib.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 set_redir(t_redirection *redir, int type, char *specifier);
-static int is_output_redir(int i);
+static void collect_and_check_redir(t_redirection *result,
+ t_token **cur, t_minidata *data, t_token **tokens);
+static t_redirection *set_redir(t_redirection *redir, int type, char *spec,
+ t_env *env);
+static int set_heredoc_data(t_token *cur, t_redirection *result,
+ t_env *env);
-t_redirection *collect_redirs(t_token **tokens)
+t_redirection *collect_redirs(t_token **tokens, t_env *env,
+ t_list **create_files)
{
t_redirection *result;
t_token *cur;
+ t_minidata data;
cur = *tokens;
result = malloc(sizeof(t_redirection) * 2);
if (result == NULL)
return (free_tokens(*tokens), NULL);
- set_redir(&result[0], 0, NULL);
- set_redir(&result[1], 0, NULL);
- while (cur != NULL && cur->next != NULL)
+ set_redir(&result[0], 0, NULL, env);
+ set_redir(&result[1], 0, NULL, env);
+ data.create_files = create_files;
+ data.env = env;
+ while (cur != NULL)
{
if (cur->type == REDIR_TOKEN && cur->next->type == STRING_TOKEN)
- collect_and_check_redir(tokens, result, &cur);
+ collect_and_check_redir(result, &cur, &data, tokens);
else if (cur->type == REDIR_TOKEN)
return (free(result), NULL);
else
@@ -44,56 +49,67 @@ t_redirection *collect_redirs(t_token **tokens)
return (result);
}
-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,
+ t_minidata *data, t_token **tokens)
{
- int is_redir_only;
+ char *str;
- 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;
+ if ((*cur)->content.redir_type != INPUT_LIMITER)
+ str = ft_strdup((*cur)->next->content.string);
+ if ((*cur)->content.redir_type == INPUT_LIMITER)
+ {
+ if (!set_heredoc_data(*cur, result, data->env))
+ return ;
+ }
+ else if ((*cur)->content.redir_type == INPUT_FILE)
+ q4fc(data->create_files, set_redir(&result[0], INPUT_FILE,
+ format_string(str, data->env, 0), data->env));
+ else if ((*cur)->content.redir_type == OUTPUT_OVERRIDE)
+ q4fc(data->create_files, set_redir(&result[1], OUTPUT_OVERRIDE,
+ format_string(str, data->env, 0), data->env));
+ else if ((*cur)->content.redir_type == OUTPUT_APPEND)
+ q4fc(data->create_files, set_redir(&result[1], OUTPUT_APPEND,
+ format_string(str, data->env, 0), data->env));
+ i_love_the_norme(cur, tokens);
}
-static t_token *collect_redir(t_token **tokens, t_redirection *result,
- t_token *cur)
+static t_redirection *set_redir(t_redirection *redir, int type, char *spec,
+ t_env *env)
{
- 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);
- }
+ t_redirection *result;
+
+ redir->type = type;
+ if (spec != NULL)
+ redir->specifier = format_string(spec, env, ft_atoi("0"));
else
+ redir->specifier = spec;
+ if (redir->type != INPUT_LIMITER)
{
- free_token(cur);
- return (NULL);
+ result = malloc(sizeof(t_redirection));
+ if (!result)
+ return (NULL);
+ result->type = type;
+ result->specifier = spec;
+ return (result);
}
- return (cur);
+ return (NULL);
}
-static void set_redir(t_redirection *redir, int type, char *specifier)
+static int set_heredoc_data(t_token *cur, t_redirection *result, t_env *env)
{
- redir->type = type;
- redir->specifier = specifier;
-}
+ char *heredoc_data;
-static int is_output_redir(int i)
-{
- if (i & (INPUT_FILE | INPUT_LIMITER))
- return (0);
- else if (i & (OUTPUT_APPEND | OUTPUT_OVERRIDE))
- return (1);
- else
+ heredoc_data = NULL;
+ if (cur->content.redir_type == INPUT_LIMITER)
{
- panic(UNREACHABLE);
- return (-1);
+ heredoc_data = read_heredoc(cur->next->content.string);
+ if (!heredoc_data)
+ {
+ perror("Heredoc allocation failed");
+ return (0);
+ }
+ set_redir(&result[0], INPUT_LIMITER, heredoc_data, env);
}
+ set_redir(&result[0], INPUT_LIMITER, heredoc_data, env);
+ return (1);
}
diff --git a/src/create_files.c b/src/create_files.c
new file mode 100644
index 0000000..eee2860
--- /dev/null
+++ b/src/create_files.c
@@ -0,0 +1,61 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* create_files.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/16 16:23:51 by dkaiser #+# #+# */
+/* Updated: 2025/01/20 18:30:40 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+#include <sys/fcntl.h>
+#include <unistd.h>
+
+static int cant_write(char *filename);
+static void create_file(char *filename, int mode);
+
+int create_files(t_list *files)
+{
+ t_redirection *file;
+
+ while (files)
+ {
+ if (files->content != NULL)
+ {
+ file = (t_redirection *)files->content;
+ if (file->type == INPUT_FILE && (access(file->specifier, F_OK) == -1
+ || access(file->specifier, R_OK) == -1))
+ return (EXIT_FAILURE);
+ if (cant_write(file->specifier))
+ break ;
+ if (file->type == OUTPUT_OVERRIDE)
+ create_file(file->specifier, O_TRUNC);
+ else if (file->type == OUTPUT_APPEND)
+ create_file(file->specifier, O_APPEND);
+ if (files->next == NULL)
+ break ;
+ if (((t_redirection *)files->next->content)->type == 0)
+ break ;
+ }
+ files = files->next;
+ }
+ return (EXIT_SUCCESS);
+}
+
+static int cant_write(char *filename)
+{
+ return (access(filename, F_OK) != -1 && access(filename, W_OK) == -1);
+}
+
+static void create_file(char *filename, int mode)
+{
+ close(open(filename, O_WRONLY | O_CREAT | mode, 0644));
+}
+
+void q4fc(t_list **queue, t_redirection *redir)
+{
+ ft_lstadd_back(queue, ft_lstnew(redir));
+}
diff --git a/src/debug_tools.c b/src/debug_tools.c
index de59703..6bee1b0 100644
--- a/src/debug_tools.c
+++ b/src/debug_tools.c
@@ -3,14 +3,16 @@
/* ::: :::::::: */
/* debug_tools.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/24 15:34:14 by dkaiser #+# #+# */
-/* Updated: 2024/06/28 15:04:43 by dkaiser ### ########.fr */
+/* Updated: 2025/01/20 12:50:36 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "debug_tools.h"
+#include <stdio.h>
+#include <stdarg.h>
void dbg(char *msg)
{
diff --git a/src/env.c b/src/env.c
index 3110965..572040c 100644
--- a/src/env.c
+++ b/src/env.c
@@ -6,13 +6,12 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/17 14:31:07 by chuhlig #+# #+# */
-/* Updated: 2024/10/25 19:17:54 by chuhlig ### ########.fr */
+/* Updated: 2025/01/20 19:12:43 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "env.h"
-#include "get_next_line.h"
-#include "libft.h"
+#include "minishell.h"
#include <stdlib.h>
void getenvlst(t_env **env, char **en)
@@ -56,9 +55,27 @@ char *env_get(t_env *env, char *name)
{
while (env != NULL)
{
- if (!ft_strncmp(env->name, name, ft_strlen(name)))
+ if (!ft_strncmp(env->name, name, ft_strlen(env->name)))
return (env->value);
env = env->next;
}
return (NULL);
}
+
+t_env *env_new(char *name)
+{
+ t_env *result;
+
+ result = malloc(sizeof(t_env));
+ if (!result)
+ return (NULL);
+ result->name = name;
+ return (result);
+}
+
+void free_env_node(t_env *node)
+{
+ free(node->name);
+ free(node->value);
+ free(node);
+}
diff --git a/src/env_to_strlst.c b/src/env_to_strlst.c
index 3a58df9..5806d96 100644
--- a/src/env_to_strlst.c
+++ b/src/env_to_strlst.c
@@ -3,10 +3,10 @@
/* ::: :::::::: */
/* env_to_strlst.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
-/* Created: 2024/10/21 14:52:08 by dkaiser #+# #+# */
-/* Updated: 2024/10/21 15:07:33 by dkaiser ### ########.fr */
+/* Created: 2024/12/17 19:22:28 by chuhlig #+# #+# */
+/* Updated: 2025/01/18 18:50:49 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
@@ -15,20 +15,32 @@
static char *get_var_assign(t_env *cur);
-char **env_to_strlst(t_env *env)
+static int getsize(t_env *env)
{
int size;
t_env *cur;
- char **result;
- int i;
size = 0;
cur = env;
- while (cur != NULL)
+ while (cur)
{
- size++;
+ if (!ft_strchr(cur->name, '?'))
+ size++;
cur = cur->next;
}
+ return (size);
+}
+
+char **env_to_strlst(t_env *env)
+{
+ int size;
+ t_env *cur;
+ char **result;
+ int i;
+
+ size = 0;
+ cur = env;
+ size = getsize(env);
result = malloc(sizeof(char *) * (size + 1));
if (result == NULL)
return (NULL);
@@ -36,6 +48,8 @@ char **env_to_strlst(t_env *env)
cur = env;
while (i < size)
{
+ if (ft_strchr(cur->name, '?'))
+ cur = cur->next;
result[i] = get_var_assign(cur);
cur = cur->next;
i++;
diff --git a/src/env_tools.c b/src/env_tools.c
new file mode 100644
index 0000000..25e21ce
--- /dev/null
+++ b/src/env_tools.c
@@ -0,0 +1,21 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* env_tools.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/15 16:14:31 by dkaiser #+# #+# */
+/* Updated: 2025/01/15 16:15:10 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+char **get_split_path(t_env *env)
+{
+ char *path;
+
+ path = env_get(env, "PATH");
+ return (ft_split(path, ':'));
+}
diff --git a/src/error.c b/src/error.c
new file mode 100644
index 0000000..2ca60b2
--- /dev/null
+++ b/src/error.c
@@ -0,0 +1,30 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* error.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/15 16:35:53 by dkaiser #+# #+# */
+/* Updated: 2025/01/20 18:12:40 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+#include <errno.h>
+
+void *error(int err_code, char *err_text, int exit_code, int *ret_code)
+{
+ errno = err_code;
+ perror(err_text);
+ if (ret_code != NULL)
+ *ret_code = exit_code;
+ return (NULL);
+}
+
+void command_not_found_error(char *cmd)
+{
+ ft_printf("%s:", cmd);
+ ft_putstr_fd(" command not found", 2);
+ ft_printf("\n");
+}
diff --git a/src/execute_cmd.c b/src/execute_cmd.c
index 6386fc0..1438f9c 100644
--- a/src/execute_cmd.c
+++ b/src/execute_cmd.c
@@ -5,72 +5,100 @@
/* +:+ +:+ +:+ */
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
-/* Created: 2024/10/21 13:58:56 by dkaiser #+# #+# */
-/* Updated: 2024/10/25 20:59:22 by chuhlig ### ########.fr */
+/* Created: 2024/12/17 19:21:35 by chuhlig #+# #+# */
+/* Updated: 2025/01/20 20:04:31 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
+#include <stdio.h>
#include <stdlib.h>
-#include <sys/_types/_pid_t.h>
-#include <sys/_types/_s_ifmt.h>
-#include <sys/fcntl.h>
-#include <unistd.h>
-#include <fcntl.h>
-int execute_cmd(t_cmd *cmd, t_env *env)
+static void establish_pipeline(int original_stdin, int original_stdout);
+static int exec_cmd(t_cmd *cmd, t_env **env, int original_std[2], int result);
+
+int is_builtin(char *cmd)
{
- int result;
- char *cmd_path;
- int fd;
+ 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));
+}
- cmd_path = get_cmd_path(cmd->args[0], env);
- cmd->args[0] = cmd_path;
+int execute_builtin(char **args, t_env **env)
+{
+ if (ft_strcmp(args[0], "export") == 0)
+ return (export(args, env, ft_atoi("0")));
+ 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], "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));
+ else if (ft_strcmp(args[0], "exit") == 0)
+ return (builtin_exit(args, env));
+ return (1);
+}
- if (cmd->redirs[0].type == INPUT_FILE)
+int execute_cmd(t_cmd *cmd, t_env **env)
+{
+ int original_std[2];
+ int result;
+
+ original_std[1] = dup(STDOUT_FILENO);
+ original_std[0] = dup(STDIN_FILENO);
+ create_files(cmd->create_files);
+ if (handle_redirections(cmd->redirs) == -1)
{
- fd = open(cmd->redirs[0].specifier, O_RDONLY);
- if (fd < 0)
- return (EXIT_FAILURE);
- dup2(fd, STDIN_FILENO);
+ establish_pipeline(original_std[0], original_std[1]);
+ return (EXIT_FAILURE);
}
- else if (cmd->redirs[0].type == INPUT_LIMITER)
+ if (is_builtin(cmd->args[0]))
{
- dbg("INPUT_LIMITER");
+ result = execute_builtin(cmd->args, env);
+ establish_pipeline(original_std[0], original_std[1]);
+ return (result);
}
- if (cmd->redirs[1].type == OUTPUT_APPEND)
+ return (exec_cmd(cmd, env, original_std, EXIT_SUCCESS));
+}
+
+static void establish_pipeline(int original_stdin, int original_stdout)
+{
+ dup2(original_stdout, STDOUT_FILENO);
+ dup2(original_stdin, STDIN_FILENO);
+ close(original_stdout);
+ close(original_stdin);
+}
+
+static int exec_cmd(t_cmd *cmd, t_env **env, int original_std[2], int result)
+{
+ int i;
+ int status;
+ char *cmd_path;
+ pid_t pid;
+
+ pid = fork();
+ if (pid == -1)
{
- dbg("OUTPUT_APPEND");
- fd = open(cmd->redirs[1].specifier, O_WRONLY | O_CREAT | O_APPEND);
- if (fd < 0)
- return (EXIT_FAILURE);
- dup2(fd, STDOUT_FILENO);
+ perror("fork");
+ establish_pipeline(original_std[0], original_std[1]);
+ return (EXIT_FAILURE);
}
- else if (cmd->redirs[1].type == OUTPUT_OVERRIDE)
+ if (pid == 0)
{
- fd = open(cmd->redirs[1].specifier, O_WRONLY | O_CREAT | O_TRUNC);
- if (fd < 0)
- return (EXIT_FAILURE);
- dup2(fd, STDOUT_FILENO);
- dbg("OUTPUT_OVERRIDE");
+ i = 0;
+ while (cmd->args[i][0] == '\0')
+ i++;
+ cmd_path = get_cmd_path(cmd->args[i], *env, &result);
+ if (cmd_path != NULL)
+ execve(cmd_path, &(cmd->args[i]), env_to_strlst(*env));
+ exit(result);
}
- result = execve(cmd->args[0], cmd->args, env_to_strlst(env));
- return (result);
+ waitpid(pid, &status, 0);
+ establish_pipeline(original_std[0], original_std[1]);
+ return ((status >> 8) & 255);
}
-
-static int eval_cmd(t_cmd *cmd, t_env **env)
-{
- if (ft_strncmp(cmd->args[0], "pwd", 4) == 0)
- pwd(*env);
- else if (ft_strncmp(cmd->args[0], "echo", 5) == 0)
- echo(cmd->args);
- else if (ft_strncmp(cmd->args[0], "env", 4) == 0)
- ft_env(*env);
- else if (ft_strncmp(cmd->args[0], "cd", 3) == 0)
- cd(env, cmd->args);
- else if (ft_strncmp(cmd->args[0], "unset", 6) == 0)
- unset(cmd->args, env);
- else if (ft_strncmp(cmd->args[0], "export", 7) == 0)
- export(cmd->args, env);
- return (0);
-} \ No newline at end of file
diff --git a/src/format_string.c b/src/format_string.c
new file mode 100644
index 0000000..7e64039
--- /dev/null
+++ b/src/format_string.c
@@ -0,0 +1,125 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* format_string.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/12/17 19:30:11 by chuhlig #+# #+# */
+/* Updated: 2025/01/19 20:24:05 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "get_next_line.h"
+#include "libft.h"
+#include "minishell.h"
+
+void append_var_exit_code(char **dst, t_env *env)
+{
+ char *exit_code;
+ char *result;
+
+ exit_code = env_get(env, "?");
+ if (exit_code)
+ {
+ result = ft_strjoin(*dst, exit_code);
+ free(*dst);
+ *dst = 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 (ft_isalnum(src[*pos + i]) || src[*pos + i] == '_')
+ i++;
+ if (i == 0)
+ return ;
+ var = ft_substr(src, *pos, i);
+ value = env_get(env, var);
+ if (value)
+ {
+ result = ft_strjoin(*dst, value);
+ free(*dst);
+ *dst = result;
+ }
+ *pos += i;
+ free(var);
+}
+
+static void handle_dollar_sign(char **result, char *str, int *pos, t_env *env)
+{
+ if (str[*pos + 1] == '?')
+ {
+ append_var_exit_code(result, env);
+ *pos += 2;
+ }
+ else if (ft_isalnum(str[*pos + 1]) || str[*pos + 1] == '_')
+ append_var(result, str, pos, env);
+ else
+ {
+ append_slice(result, str, *pos, *pos + 1);
+ (*pos)++;
+ }
+}
+
+char *format_string(char *str, t_env *env, int is_literal)
+{
+ char *result;
+ int pos;
+ int start;
+
+ pos = 0;
+ start = 0;
+ result = NULL;
+ if (!str)
+ return (NULL);
+ while (str[pos])
+ {
+ if (str[pos] == '\'' || (str[pos] == '\"' && !is_literal)
+ || (str[pos] == '$' && !is_literal))
+ {
+ append_slice(&result, str, start, pos);
+ if (str[pos] == '$')
+ handle_dollar_sign(&result, str, &pos, env);
+ else
+ is_literal ^= (str[pos++] == '\'');
+ start = pos;
+ continue ;
+ }
+ pos++;
+ }
+ return (append_slice(&result, str, start, pos), result);
+}
diff --git a/src/free_token.c b/src/free_token.c
index 9b035ac..512ba23 100644
--- a/src/free_token.c
+++ b/src/free_token.c
@@ -3,14 +3,15 @@
/* ::: :::::::: */
/* free_token.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/27 14:38:57 by dkaiser #+# #+# */
-/* Updated: 2024/08/02 14:23:56 by dkaiser ### ########.fr */
+/* Updated: 2025/01/20 12:49:48 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
#include "token.h"
+#include "debug_tools.h"
void free_token(t_token *token)
{
@@ -19,6 +20,7 @@ void free_token(t_token *token)
if (token->next != NULL)
token->next->previous = NULL;
free(token);
+ token = NULL;
}
void free_token_and_connect(t_token *token)
@@ -28,6 +30,7 @@ void free_token_and_connect(t_token *token)
if (token->next != NULL)
token->next->previous = token->previous;
free(token);
+ token = NULL;
}
void free_tokens(t_token *tokens)
diff --git a/src/get_cmd_path.c b/src/get_cmd_path.c
index 1ecf393..70043a7 100644
--- a/src/get_cmd_path.c
+++ b/src/get_cmd_path.c
@@ -3,31 +3,38 @@
/* ::: :::::::: */
/* get_cmd_path.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
-/* Created: 2024/10/17 16:45:47 by dkaiser #+# #+# */
-/* Updated: 2024/10/17 17:11:27 by dkaiser ### ########.fr */
+/* Created: 2024/12/17 19:19:59 by chuhlig #+# #+# */
+/* Updated: 2025/01/20 18:12:33 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
#include "minishell.h"
+#include <errno.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/unistd.h>
+#include <unistd.h>
-static char *get_absolute_cmd_path(char *cmd, t_env *env);
-static char *find_in_path(char *cmd, t_env *env);
+static char *get_simple_cmd_path(char *cmd, int *return_code);
+static char *get_absolute_cmd_path(char *cmd, t_env *env, int *return_code);
+static char *find_in_path(char *cmd, t_env *env, int *return_code);
char **get_split_path(t_env *env);
+static int is_directory(char *path);
-char *get_cmd_path(char *cmd, t_env *env)
+char *get_cmd_path(char *cmd, t_env *env, int *return_code)
{
if (cmd[0] == '/')
- return (ft_strdup(cmd));
+ return (get_simple_cmd_path(cmd, return_code));
else if (ft_strchr(cmd, '/'))
- return (get_absolute_cmd_path(cmd, env));
+ return (get_absolute_cmd_path(cmd, env, return_code));
else
- return (find_in_path(cmd, env));
+ return (find_in_path(cmd, env, return_code));
}
-static char *get_absolute_cmd_path(char *cmd, t_env *env)
+static char *get_absolute_cmd_path(char *cmd, t_env *env, int *return_code)
{
char *cur_dir;
char *result;
@@ -38,16 +45,23 @@ static char *get_absolute_cmd_path(char *cmd, t_env *env)
result = ft_strjoin(cur_dir, cmd);
free(cur_dir);
if (!result)
- return (NULL);
+ return (error(ENOENT, cmd, 127, return_code));
+ if (access(result, F_OK) == -1)
+ {
+ free(result);
+ return (error(ENOENT, cmd, 127, return_code));
+ }
if (access(result, X_OK) == -1)
{
free(result);
- return (NULL);
+ return (error(EACCES, cmd, 126, return_code));
}
+ if (is_directory(cmd))
+ return (error(EISDIR, cmd, 126, return_code));
return (result);
}
-static char *find_in_path(char *cmd, t_env *env)
+static char *find_in_path(char *cmd, t_env *env, int *return_code)
{
char *cur_path;
char *cmd_path;
@@ -70,13 +84,38 @@ static char *find_in_path(char *cmd, t_env *env)
return (cmd_path);
path++;
}
+ *return_code = 127;
+ command_not_found_error(cmd);
return (NULL);
}
-char **get_split_path(t_env *env)
+static char *get_simple_cmd_path(char *cmd, int *return_code)
+{
+ char *result;
+
+ result = ft_strdup(cmd);
+ if (access(result, F_OK) == -1)
+ {
+ free(result);
+ return (error(ENOENT, cmd, 127, return_code));
+ }
+ else if (access(result, X_OK) == -1)
+ {
+ free(result);
+ return (error(EACCES, cmd, 126, return_code));
+ }
+ if (is_directory(cmd))
+ return (error(EISDIR, cmd, 126, return_code));
+ return (result);
+}
+
+static int is_directory(char *path)
{
- char *path;
+ struct stat path_stat;
- path = env_get(env, "PATH");
- return (ft_split(path, ':'));
+ stat(path, &path_stat);
+ if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
+ return (1);
+ else
+ return (0);
}
diff --git a/src/handle_redir.c b/src/handle_redir.c
new file mode 100644
index 0000000..e8a1010
--- /dev/null
+++ b/src/handle_redir.c
@@ -0,0 +1,103 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* handle_redir.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/18 18:34:51 by chuhlig #+# #+# */
+/* Updated: 2025/01/20 14:59:38 by chuhlig ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+int handle_input_redirection(t_redirection *redir)
+{
+ int fd;
+
+ if (redir->type == INPUT_FILE)
+ {
+ fd = open_file(redir->specifier, O_RDONLY, 0);
+ if (fd < 0)
+ return (-1);
+ dup2(fd, STDIN_FILENO);
+ close(fd);
+ }
+ else if (redir->type == INPUT_LIMITER)
+ {
+ fd = open_file("/tmp/heredoc_tmp", O_WRONLY | O_TRUNC, 0644);
+ if (fd < 0)
+ return (-1);
+ write(fd, redir->specifier, ft_strlen(redir->specifier));
+ close(fd);
+ fd = open_file("/tmp/heredoc_tmp", O_RDONLY, 0);
+ if (fd < 0)
+ return (-1);
+ dup2(fd, STDIN_FILENO);
+ close(fd);
+ }
+ return (0);
+}
+
+int handle_output_redirection(t_redirection *redir)
+{
+ int fd;
+
+ if (redir->type == OUTPUT_OVERRIDE)
+ {
+ fd = open_file(redir->specifier, O_WRONLY | O_TRUNC, 0644);
+ if (fd < 0)
+ return (-1);
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+ }
+ else if (redir->type == OUTPUT_APPEND)
+ {
+ fd = open_file(redir->specifier, O_WRONLY | O_APPEND, 0644);
+ if (fd < 0)
+ return (-1);
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+ }
+ return (0);
+}
+
+int handle_redirections(t_redirection *redirs)
+{
+ if (redirs[0].type == INPUT_FILE || redirs[0].type == INPUT_LIMITER)
+ {
+ if (handle_input_redirection(&redirs[0]) < 0)
+ return (-1);
+ }
+ if (redirs[1].type == OUTPUT_OVERRIDE || redirs[1].type == OUTPUT_APPEND)
+ {
+ if (handle_output_redirection(&redirs[1]) < 0)
+ return (-1);
+ }
+ return (0);
+}
+
+int handle_pipe_parent(int p[2], t_node *node, t_env **env)
+{
+ int original_stdin;
+ int result;
+
+ close(p[1]);
+ original_stdin = dup(STDIN_FILENO);
+ dup2(p[0], STDIN_FILENO);
+ result = eval_rec(node->content.pipe.right, env, p[0]);
+ dup2(original_stdin, STDIN_FILENO);
+ close(original_stdin);
+ close(p[0]);
+ return (result);
+}
+
+int handle_pipe_child(int p[2], t_node *node, t_env **env, int in_fd)
+{
+ close(p[0]);
+ dup2(in_fd, STDIN_FILENO);
+ dup2(p[1], STDOUT_FILENO);
+ close(p[1]);
+ exit(eval_rec(node->content.pipe.left, env, in_fd));
+}
diff --git a/src/init.c b/src/init.c
index fd2c8ac..f41e64a 100644
--- a/src/init.c
+++ b/src/init.c
@@ -3,10 +3,10 @@
/* ::: :::::::: */
/* init.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/24 15:02:24 by dkaiser #+# #+# */
-/* Updated: 2024/06/24 15:25:57 by dkaiser ### ########.fr */
+/* Updated: 2025/01/13 17:45:46 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
diff --git a/src/interpreter.c b/src/interpreter.c
index c6a4a00..9cd5292 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -5,86 +5,51 @@
/* +:+ +:+ +:+ */
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
-/* Created: 2024/08/05 13:15:24 by dkaiser #+# #+# */
-/* Updated: 2024/10/25 20:59:16 by chuhlig ### ########.fr */
+/* Created: 2024/12/17 19:15:49 by chuhlig #+# #+# */
+/* Updated: 2025/01/20 20:07:11 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>
-static int eval_rec(t_node *node, t_env *env, int in_fd);
+int eval_rec(t_node *node, t_env **env, int in_fd);
-int eval(t_node *node, t_env *env)
+int open_file(char *path, int flags, int mode)
{
- pid_t pid;
- int result;
+ int fd;
- if (node == NULL)
- return (EXIT_FAILURE);
- result = 0;
- pid = fork();
- if (pid < 0)
- {
- return (EXIT_FAILURE);
- }
- if (pid == 0)
- {
- result = eval_rec(node, env, STDIN_FILENO);
- exit(result);
- }
- else
- {
- waitpid(pid, &result, 0);
- }
- return (result);
+ fd = open(path, flags, mode);
+ if (fd < 0)
+ perror(path);
+ return (fd);
}
-static int eval_rec(t_node *node, t_env *env, int in_fd)
+int eval_rec(t_node *node, t_env **env, int in_fd)
{
+ int p[2];
pid_t pid;
int result;
- int p[2];
- result = pipe(p);
- if (result == -1)
- return (EXIT_FAILURE);
if (node->type == PIPE_NODE)
{
+ if (pipe(p) == -1)
+ return (perror("pipe"), EXIT_FAILURE);
pid = fork();
- if (pid < 0)
- {
- return (EXIT_FAILURE);
- }
+ if (pid == -1)
+ return (perror("fork"), close(p[0]), close(p[1]), EXIT_FAILURE);
if (pid == 0)
- {
- close(p[0]);
- dup2(in_fd, STDIN_FILENO);
- dup2(p[1], STDOUT_FILENO);
- result = execute_cmd(&node->content.pipe.left->content.cmd, env);
- exit(result);
- }
- else
- {
- close(p[1]);
- dup2(p[0], STDIN_FILENO);
- result = eval_rec(node->content.pipe.right, env, p[0]);
- }
+ handle_pipe_child(p, node, env, in_fd);
+ result = handle_pipe_parent(p, node, env);
}
else if (node->type == CMD_NODE)
- {
result = execute_cmd(&node->content.cmd, env);
- }
else
- {
- panic(UNREACHABLE);
- return (EXIT_FAILURE);
- }
+ result = EXIT_FAILURE;
return (result);
}
+int eval(t_node *node, t_env **env)
+{
+ return (eval_rec(node, env, STDIN_FILENO));
+}
diff --git a/src/main.c b/src/main.c
index 4e1d9da..a2aad22 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,8 +6,7 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/22 17:14:03 by dkaiser #+# #+# */
-/* Updated: 2024/08/26 19:55:57 by chuhlig ### ########.fr */
-/* Updated: 2024/10/25 16:06:32 by chuhlig ### ########.fr */
+/* Updated: 2025/01/14 18:41:15 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
@@ -15,13 +14,18 @@
int main(int argc, char *argv[], char *envp[])
{
- t_env *env;
+ t_env *env;
+ static int promptflag;
env = NULL;
+ promptflag = 0;
if (!argc && !argv)
return (1);
if (init())
return (1);
getenvlst(&env, envp);
- repl("Minishell $ ", &env);
+ set_return_code(0, &env);
+ repl("Minishell $ ", &env, &promptflag);
+ free_envlst(&env);
+ return (0);
}
diff --git a/src/new_node.c b/src/new_node.c
index c58d291..b2ab7ea 100644
--- a/src/new_node.c
+++ b/src/new_node.c
@@ -3,10 +3,10 @@
/* ::: :::::::: */
/* new_node.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/27 11:21:03 by dkaiser #+# #+# */
-/* Updated: 2024/09/17 18:46:35 by dkaiser ### ########.fr */
+/* Updated: 2025/01/20 17:59:01 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
@@ -37,7 +37,8 @@ t_node *new_pipe_node(t_node *left, t_node *right)
return (node);
}
-t_node *new_cmd_node(char **args, t_redirection redirs[2])
+t_node *new_cmd_node(char **args, t_redirection redirs[2],
+ t_list *create_files)
{
t_node *node;
@@ -49,7 +50,9 @@ t_node *new_cmd_node(char **args, t_redirection redirs[2])
{
node->content.cmd.redirs[0] = redirs[0];
node->content.cmd.redirs[1] = redirs[1];
+ node->content.cmd.create_files = create_files;
free(redirs);
+ redirs = NULL;
return (node);
}
return (NULL);
diff --git a/src/new_token.c b/src/new_token.c
index 6431c7d..bd65b9d 100644
--- a/src/new_token.c
+++ b/src/new_token.c
@@ -6,7 +6,7 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/27 14:29:44 by dkaiser #+# #+# */
-/* Updated: 2024/08/29 15:30:52 by chuhlig ### ########.fr */
+/* Updated: 2025/01/20 19:12:57 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
@@ -50,28 +50,3 @@ t_token *new_redir_token(int type, t_token *previous, t_token *next)
token->content.redir_type = type;
return (token);
}
-
-// void ft_append_token(int type, t_token **list)// but we need somewhere token/node head initialize with nul
-// {
-// t_token *node;
-// t_token *last_node;
-
-// if (!list)
-// return ;
-// node = malloc(sizeof(t_token));
-// if (!node)
-// return ;
-// node->next = NULL;
-// node->type = type;
-// if (!*list)
-// {
-// *list = node;
-// node->previous = NULL;
-// }
-// else
-// {
-// last_node = ft_lstlast(*list);
-// last_node->next = node;
-// node->previous = last_node;
-// }
-// } \ No newline at end of file
diff --git a/src/parse_cmd.c b/src/parse_cmd.c
index 2755cae..6505384 100644
--- a/src/parse_cmd.c
+++ b/src/parse_cmd.c
@@ -3,32 +3,42 @@
/* ::: :::::::: */
/* 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/20 19:09:21 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;
+ t_list *create_files;
- redirs = collect_redirs(&tokens);
- args = collect_args(&tokens);
- return (new_cmd_node(args, redirs));
+ create_files = NULL;
+ redirs = collect_redirs(&tokens, *env, &create_files);
+ if (redirs == NULL)
+ return (NULL);
+ args = collect_args(&tokens, env);
+ if (args == NULL)
+ {
+ free(redirs);
+ return (NULL);
+ }
+ return (new_cmd_node(args, redirs, create_files));
}
-static char **collect_args(t_token **tokens)
+static char **collect_args(t_token **tokens, t_env **env)
{
t_token *cur;
char **result;
int i;
+ t_token *next;
cur = *tokens;
i = 0;
@@ -41,11 +51,12 @@ static char **collect_args(t_token **tokens)
i = 0;
while (cur != NULL && cur->type == STRING_TOKEN)
{
+ next = cur->next;
if (cur->previous)
free_token(cur->previous);
- result[i] = cur->content.string;
+ result[i] = format_string(cur->content.string, *env, ft_atoi("0"));
i++;
- cur = cur->next;
+ cur = next;
}
result[i] = NULL;
return (result);
diff --git a/src/parser.c b/src/parser.c
index 06c1df7..13ab10d 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -3,35 +3,36 @@
/* ::: :::::::: */
/* 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/20 19:13:31 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;
@@ -39,16 +40,17 @@ static t_node *parse_statement(t_token *tokens)
if (left_side_tokens == NULL)
{
free_tokens(tokens);
+ tokens = NULL;
return (NULL);
}
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));
}
}
@@ -69,6 +71,7 @@ t_token *split_at_first(t_token **tokens, int type)
if (result == split)
result = NULL;
free_token(split);
+ split = NULL;
return (result);
}
diff --git a/src/praise_the_norme.c b/src/praise_the_norme.c
new file mode 100644
index 0000000..a22843b
--- /dev/null
+++ b/src/praise_the_norme.c
@@ -0,0 +1,30 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* praise_the_norme.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/20 18:35:41 by dkaiser #+# #+# */
+/* Updated: 2025/01/20 18:39:31 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+void i_love_the_norme(t_token **cur, t_token **tokens)
+{
+ t_token *next_token;
+
+ next_token = (*cur)->next;
+ free_token_and_connect(*cur);
+ if (next_token)
+ {
+ if (next_token->previous == NULL)
+ *tokens = next_token->next;
+ *cur = next_token->next;
+ free_token_and_connect(next_token);
+ }
+ else
+ *cur = NULL;
+}
diff --git a/src/read_heredoc.c b/src/read_heredoc.c
new file mode 100644
index 0000000..53633e8
--- /dev/null
+++ b/src/read_heredoc.c
@@ -0,0 +1,76 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* read_heredoc.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/01/15 18:22:09 by dkaiser #+# #+# */
+/* Updated: 2025/01/15 19:08:07 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+#include <errno.h>
+#include <stdio.h>
+#include <sys/errno.h>
+
+static char *concat_str(char *temp, char *line);
+static char *get_result(char *temp, char *result, char *line);
+static void *print_error_and_free(char *result);
+
+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)
+ return (print_error_and_free(result));
+ result = get_result(temp, result, line);
+ total_length += line_length;
+ }
+ return (result);
+}
+
+static char *concat_str(char *temp, char *line)
+{
+ ft_strcat(temp, line);
+ ft_strcat(temp, "\n");
+ free(line);
+ return (temp);
+}
+
+static char *get_result(char *temp, char *result, char *line)
+{
+ if (result)
+ {
+ ft_strcpy(temp, result);
+ free(result);
+ }
+ else
+ temp[0] = '\0';
+ return (concat_str(temp, line));
+}
+
+static void *print_error_and_free(char *result)
+{
+ errno = ENOMEM;
+ perror("heredoc");
+ free(result);
+ return (NULL);
+}
diff --git a/src/repl.c b/src/repl.c
index 9fae849..16c8e95 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -6,35 +6,38 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/24 16:07:04 by dkaiser #+# #+# */
-/* Updated: 2024/10/22 17:05:14 by chuhlig ### ########.fr */
+/* Updated: 2025/01/20 17:58:43 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "../include/minishell.h"
#include "token.h"
-void repl(const char *prompt, t_env **env)
+void repl(const char *prompt, t_env **env, int *promptflag)
{
char *input;
t_token *token_list;
t_list *lines;
+ (*promptflag)++;
while (1)
{
input = readline(prompt);
if (input == NULL)
- return ;
+ {
+ if (*promptflag > 1)
+ (*promptflag)--;
+ printf("exit\n");
+ break ;
+ }
if (input[0] == '\0')
continue ;
add_history(input);
token_list = NULL;
tokenizer(input, &token_list, '\0');
- lines = parse(token_list);
+ lines = parse(token_list, env);
if (lines)
- {
- print_ast(lines->content);
- eval(lines->content, env);
- }
+ set_return_code(eval(lines->content, env), env);
free(input);
}
}
diff --git a/src/signal_handling.c b/src/signal_handling.c
index a19fa94..6c6ca1e 100644
--- a/src/signal_handling.c
+++ b/src/signal_handling.c
@@ -3,10 +3,10 @@
/* ::: :::::::: */
/* signal_handling.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/24 15:08:43 by dkaiser #+# #+# */
-/* Updated: 2024/06/25 13:33:26 by dkaiser ### ########.fr */
+/* Updated: 2025/01/20 12:15:32 by chuhlig ### ########.fr */
/* */
/* ************************************************************************** */
diff --git a/src/tokenizer.c b/src/tokenizer.c
index d7a96f7..e202de6 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -13,6 +13,26 @@
#include "minishell.h"
#include "token.h"
+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 print_token(t_token *token)
{
if (DEBUG)
@@ -77,11 +97,11 @@ void handle_special_chars(char *s, int *i, int *start, t_token **token_list)
*token_list = new_token(PIPE_TOKEN, *token_list, NULL);
else if (s[*i] == '\n')
*token_list = new_token(NEWLINE_TOKEN, *token_list, NULL);
- print_token(*token_list);
if (s[*i] == '<' && s[*i + 1] == '<')
(*i)++;
if (s[*i] == '>' && s[*i + 1] == '>')
(*i)++;
+ print_token(*token_list);
*start = *i + 1;
}
@@ -111,6 +131,5 @@ void tokenizer(char *s, t_token **token_list, char quote_check)
pos = i + 1;
}
}
- while ((*token_list)->previous)
- *token_list = (*token_list)->previous;
+ *token_list = reverse_token_list(*token_list);
}