From 581dad01464ee08cfc27148eba174ad0e04f6c4a Mon Sep 17 00:00:00 2001 From: mcolonna Date: Fri, 26 Apr 2024 14:19:31 +0200 Subject: [PATCH 01/12] [ADD] clear screen at start of minishell --- src/main.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index 0b5483d..1c8448b 100644 --- a/src/main.c +++ b/src/main.c @@ -6,15 +6,23 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:33:45 by mcolonna #+# #+# */ -/* Updated: 2024/04/26 12:24:58 by mcolonna ### ########.fr */ +/* Updated: 2024/04/26 14:11:46 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "include.h" -// Clean the screen (TODO) -static void execclear(void) +// Clean the screen +static void execclear(char *const envp[]) { + const t_memclass mc = mem_newclass(fatal_error); + t_command command; + + command = parse_command(mc, "clear"); + if (command.error) + return ; + execute_command(mc, command, envp); + mem_freeall(mc); } // Print hi :D @@ -55,7 +63,7 @@ int main(const int argc, const char *argv[], char *const envp[]) (void)argv; (void)path; (void)command; - execclear(); + execclear(envp); print_hi(); errorstatus = 0; while (true) From 3a85b1a195bf88cea7ffd405a18a24a854ffeba7 Mon Sep 17 00:00:00 2001 From: mcolonna Date: Fri, 26 Apr 2024 14:23:37 +0200 Subject: [PATCH 02/12] [FIX] wait all programs to end before prompting --- include/include.h | 3 ++- src/exec_command.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/include.h b/include/include.h index c17a69f..47104c6 100644 --- a/include/include.h +++ b/include/include.h @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:15:12 by mcolonna #+# #+# */ -/* Updated: 2024/04/26 12:33:20 by mcolonna ### ########.fr */ +/* Updated: 2024/04/26 14:21:43 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,7 @@ # include # include # include +# include # include "libft.h" # include "libtf.h" diff --git a/src/exec_command.c b/src/exec_command.c index 50c83ca..7a28b44 100644 --- a/src/exec_command.c +++ b/src/exec_command.c @@ -6,7 +6,7 @@ /* By: jschaft +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:48:00 by jschaft #+# #+# */ -/* Updated: 2024/04/26 12:31:49 by mcolonna ### ########.fr */ +/* Updated: 2024/04/26 14:21:15 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -58,6 +58,15 @@ static int execute_call(t_memclass mc, t_call call, const int inout[2], int execute_command(t_memclass mc, t_command command, char *const envp[]) { const int inout[] = {0, 1}; + int nb_calls; + int r; - return (execute_call(mc, command.calls[0], inout, envp)); + nb_calls = 1; + r = execute_call(mc, command.calls[0], inout, envp); + while (nb_calls) + { + wait(NULL); + nb_calls--; + } + return (r); } From 78f6fcc82f7272dc56a276e163fcf7a1a362ad00 Mon Sep 17 00:00:00 2001 From: mcolonna Date: Mon, 29 Apr 2024 13:52:25 +0200 Subject: [PATCH 03/12] [FIX] error in libtf --- .gitignore | 2 +- libtf/Makefile | 2 +- libtf/src/mem.c | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index c5d6576..2f49f62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -./minishell +/minishell # Prerequisites *.d diff --git a/libtf/Makefile b/libtf/Makefile index 889a1eb..843f733 100644 --- a/libtf/Makefile +++ b/libtf/Makefile @@ -11,7 +11,7 @@ PRINTF_CODE = \ ft_strjoin stream1 stream2 utils1 utils2 PRINTF_SRCS = tf_printf/src/ PRINTF_INCLUDES = ./ tf_printf/include/ -WHAT = LIBTF v11 +WHAT = LIBTF v12 USED = malloc() free() write() # It works and I probably won't change it for the rest of my life diff --git a/libtf/src/mem.c b/libtf/src/mem.c index bde9c62..b57c8d3 100644 --- a/libtf/src/mem.c +++ b/libtf/src/mem.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/12/18 11:08:16 by mcolonna #+# #+# */ -/* Updated: 2024/03/12 16:05:15 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 13:47:37 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -60,6 +60,7 @@ void mem_freeall(t_memclass mc) el = ((t_memclass_in *) mc)->first; while (el) { + el->previous = NULL; next = el->next; free_address_with_element(el->address); if (el->subclass) From 117631d50e77a71c791313f2b2330b0b48ab54c2 Mon Sep 17 00:00:00 2001 From: mcolonna Date: Mon, 29 Apr 2024 15:49:12 +0200 Subject: [PATCH 04/12] manage errors --- include/include.h | 11 ++++++---- src/ask_command.c | 6 +++--- src/error.c | 21 ++++++++++--------- src/main.c | 13 ++++++------ src/parse_command.c | 49 ++++++++++++++++++++++++++++----------------- 5 files changed, 60 insertions(+), 40 deletions(-) diff --git a/include/include.h b/include/include.h index 47104c6..338de2b 100644 --- a/include/include.h +++ b/include/include.h @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:15:12 by mcolonna #+# #+# */ -/* Updated: 2024/04/26 14:21:43 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 15:48:25 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -46,7 +46,7 @@ typedef struct s_call // Represents a command given by the user. typedef struct s_command { - bool error; // true if an error occured in interpret_command(). + int error; // 0 if parse_command() succeded, error status if not const t_call *calls; // all calls to programs (ended by .program == NULL) int input_fd; // fd to use with '<' redirection (0 by default) int output_fd; // fd to use with '>' redirection (1 by default) @@ -65,10 +65,10 @@ int execute_command(t_memclass mc, t_command command, ///// ERROR ///// // Call to show an error. -// If msg == "errno", use strerror(errno) +// If msg == "errno", use perror() void minishell_error(const char *msg); -// Call to write the error and exit the program. +// Call perror() and exit the program. void fatal_error(const char *msg); ///// PATH ///// @@ -82,4 +82,7 @@ char **get_path(char *const envp[]); const char *search_path( const t_memclass mc, const char **path, const char *prog); +///// MAIN ///// +extern t_memclass g_mc; + #endif diff --git a/src/ask_command.c b/src/ask_command.c index 66c1cd2..5652910 100644 --- a/src/ask_command.c +++ b/src/ask_command.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 15:03:23 by mcolonna #+# #+# */ -/* Updated: 2024/04/24 13:19:42 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 15:11:06 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,8 +16,8 @@ const char *ask_command(const t_memclass mc) { const char *r; - print_str(minishell_error, 1, "( ^.^)> "); - r = read_line(minishell_error, mc, 0); + print_str(fatal_error, 1, "( ^.^)> "); + r = read_line(fatal_error, mc, 0); if (r) return (r); else diff --git a/src/error.c b/src/error.c index 4316050..ac0246b 100644 --- a/src/error.c +++ b/src/error.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 15:51:56 by mcolonna #+# #+# */ -/* Updated: 2024/04/25 13:41:57 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 15:39:56 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,16 +15,19 @@ void minishell_error(const char *msg) { if (str_eq(msg, "errno")) - msg = strerror(errno); - print_str(err_remember, 2, "minishell: "); - print_str(err_remember, 2, msg); - err_get(); + perror("minishell"); + else + { + print_str(err_remember, 2, "minishell: "); + print_line(err_remember, 2, msg); + err_get(); + } } -// TODO adapt for msg == errno void fatal_error(const char *msg) { - print_str(err_remember, 2, "Fatal error: "); - print_line(err_remember, 2, msg); - exit(1); + (void)msg; + minishell_error("errno"); + mem_freeall(g_mc); + exit(errno); } diff --git a/src/main.c b/src/main.c index 1c8448b..944584b 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:33:45 by mcolonna #+# #+# */ -/* Updated: 2024/04/26 14:11:46 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 15:40:08 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,7 +15,7 @@ // Clean the screen static void execclear(char *const envp[]) { - const t_memclass mc = mem_newclass(fatal_error); + const t_memclass mc = mem_subclass(fatal_error, g_mc); t_command command; command = parse_command(mc, "clear"); @@ -51,9 +51,10 @@ static void print_hi(void) printf("|_____________________________________________|\n\n"); } +t_memclass g_mc; + int main(const int argc, const char *argv[], char *const envp[]) { - char **const path = get_path(envp); t_memclass mc; const char *command_str; t_command command; @@ -61,14 +62,14 @@ int main(const int argc, const char *argv[], char *const envp[]) (void)argc; (void)argv; - (void)path; - (void)command; + g_mc = NULL; + g_mc = mem_newclass(fatal_error); execclear(envp); print_hi(); errorstatus = 0; while (true) { - mc = mem_newclass(minishell_error); + mc = mem_subclass(fatal_error, g_mc); command_str = ask_command(mc); command = parse_command(mc, command_str); if (command.error) diff --git a/src/parse_command.c b/src/parse_command.c index 0370d36..8233fa2 100644 --- a/src/parse_command.c +++ b/src/parse_command.c @@ -6,17 +6,18 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:47:40 by mcolonna #+# #+# */ -/* Updated: 2024/04/25 17:58:54 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 15:48:43 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "include.h" -// To call when a parse error occurs (TODO) -static void parse_error(const char *msg) +// To call when a parse error occurs. +// Always returns 1 (parse error's status). +static int parse_error(void) { - (void)msg; - fatal_error("parse error"); + minishell_error("parse error"); + return (1); } // Global variables for all the parsing functions @@ -62,7 +63,7 @@ static const char *get_string(t_parsing_args *args, const char *stop_charset) } // Get a program call (program names & its arguments) until stop_charset. -static void get_call(t_parsing_args *args, const char *stop_charset) +static int get_call(t_parsing_args *args, const char *stop_charset) { t_call *r; t_list arguments; @@ -76,57 +77,69 @@ static void get_call(t_parsing_args *args, const char *stop_charset) skip_blank(&args->stream); } r = mem_alloc(fatal_error, args->mc, sizeof(t_call)); - r->program = (char *)list_get(parse_error, &arguments, 0); + r->program = (char *)list_get(err_remember, &arguments, 0); + if (err_get()) + return (parse_error()); r->argc = list_getsize(&arguments); r->argv = (char *const *)list_convert( fatal_error, args->mc, &arguments); list_add(fatal_error, &args->calls, (t_call *)r); args->got_first_call = true; + return (0); } // Read an element (a call to a program, a '< FILE' or a '> FILE') +// On success, return 0. On error, return the error status. // (TODO redirections) -static void get_element(t_parsing_args *args) +static int get_element(t_parsing_args *args) { char c; + int error; - while (stream_read(&args->stream)) + error = 0; + while (!error && stream_read(&args->stream)) { c = stream_read(&args->stream); if (c == '|') { if (!args->got_first_call) - parse_error(NULL); + return (parse_error()); stream_pop(&args->stream); skip_blank(&args->stream); - get_call(args, "<>|"); + error = get_call(args, "<>|"); } else if (!args->got_first_call) - get_call(args, "<>|"); + error = get_call(args, "<>|"); else - parse_error(NULL); + return (parse_error()); skip_blank(&args->stream); } + return (error); } t_command parse_command(const t_memclass mc, const char *command) { t_parsing_args args; + int error; + error = 0; args.mc = mc; - args.r.error = false; + args.r.error = 0; args.r.input_fd = 0; args.r.output_fd = 1; args.calls = list_createempty(mc); args.got_first_call = false; streamstr_init(&args.stream, command); skip_blank(&args.stream); - while (stream_read(&args.stream)) + while (!error && stream_read(&args.stream)) { - get_element(&args); + error = get_element(&args); skip_blank(&args.stream); } - args.r.calls = (t_call *)list_convert_type( - fatal_error, args.mc, &args.calls, sizeof(t_call)); + if (!error) + args.r.calls = (t_call *)list_convert_type( + fatal_error, args.mc, &args.calls, sizeof(t_call)); + if (error) + args.r.error = error; return (args.r); } From 8d5ccfeb82417d093096f33a50fa700178857800 Mon Sep 17 00:00:00 2001 From: mcolonna Date: Mon, 29 Apr 2024 15:56:49 +0200 Subject: [PATCH 05/12] check some TODOs - "is t_call.argv ended by NULL?" - "does it return the good path if there is several possibilities?" --- include/include.h | 6 ++++-- src/exec_command.c | 3 +-- src/path.c | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/include.h b/include/include.h index 338de2b..81ed7fd 100644 --- a/include/include.h +++ b/include/include.h @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:15:12 by mcolonna #+# #+# */ -/* Updated: 2024/04/29 15:48:25 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 15:56:26 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -77,8 +77,10 @@ void fatal_error(const char *msg); // Return a list of strings ended by NULL. char **get_path(char *const envp[]); -// Search the program in PATH. +// Search the program in $PATH. // Returns the path of the program to use, or NULL if there is none. +// If there is several possibilities, it returns the one from the first path +// given in $PATH. const char *search_path( const t_memclass mc, const char **path, const char *prog); diff --git a/src/exec_command.c b/src/exec_command.c index 7a28b44..1440798 100644 --- a/src/exec_command.c +++ b/src/exec_command.c @@ -6,7 +6,7 @@ /* By: jschaft +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:48:00 by jschaft #+# #+# */ -/* Updated: 2024/04/26 14:21:15 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 15:51:00 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,7 +26,6 @@ static void free_tab(char **tab) free(tab); } -// TODO is t_call.argv ended by NULL? static void fork_exec(const char *path, t_call call, const int inout[2], char *const envp[]) { diff --git a/src/path.c b/src/path.c index 8283163..be44a0e 100644 --- a/src/path.c +++ b/src/path.c @@ -6,7 +6,7 @@ /* By: jschaft +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/11/16 12:07:26 by jschaft #+# #+# */ -/* Updated: 2024/04/26 12:24:41 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 15:54:40 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,7 +27,6 @@ char **get_path(char *const envp[]) return (re); } -// TODO does it return the good path if there is several possibilities? const char *search_path( const t_memclass mc, const char **path, const char *prog) { From 8d9ed896a28e6912db701f9569112d0df64c952a Mon Sep 17 00:00:00 2001 From: mcolonna Date: Mon, 29 Apr 2024 16:44:48 +0200 Subject: [PATCH 06/12] [ADD] quotes --- .gitignore | 1 - src/parse_command.c | 54 +++++++++++++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 2f49f62..8979ded 100644 --- a/.gitignore +++ b/.gitignore @@ -37,7 +37,6 @@ *.i*86 *.x86_64 *.hex -./minishell # Debug files *.dSYM/ diff --git a/src/parse_command.c b/src/parse_command.c index 8233fa2..8a9a93d 100644 --- a/src/parse_command.c +++ b/src/parse_command.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:47:40 by mcolonna #+# #+# */ -/* Updated: 2024/04/29 15:48:43 by mcolonna ### ########.fr */ +/* Updated: 2024/04/29 16:45:13 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,27 +36,45 @@ static void skip_blank(t_stream *stream) stream_skip(stream, " \r\n\t"); } +// Add 'c' at the end of 'str' and return the result. +// Also mem_free() 'str'. +static char *str_addchar(t_err err, t_memclass mc, const char *str, char c) +{ + char *s; + char *r; + + s = str_dup(fatal_error, mc, "-"); + s[0] = c; + r = str_join(err, mc, str, s); + mem_free(s); + mem_free((void *)str); + return (r); +} + // Read the string, stop if the char is in stop_charset -// TODO quotes +// TODO variables if using " static const char *get_string(t_parsing_args *args, const char *stop_charset) { + char quote; const t_memclass mc = mem_subclass(fatal_error, args->mc); - const char *stop_charset_2 - = str_join(fatal_error, mc, stop_charset, " \n"); + const char *stop_charset_2; char *str; - char str2[2]; - char *str3; + quote = '\0'; + if (char_isin(stream_read(&args->stream), "\"'")) + quote = stream_pop(&args->stream); + if (!quote) + stop_charset_2 = str_join(fatal_error, mc, stop_charset, " \n"); + else + stop_charset_2 = str_addchar(fatal_error, mc, + str_dup(fatal_error, mc, ""), quote); str = str_dup(fatal_error, mc, ""); - str2[1] = '\0'; while (stream_read(&args->stream) && !char_isin(stream_read(&args->stream), stop_charset_2)) - { - str2[0] = stream_pop(&args->stream); - str3 = str; - str = str_join(fatal_error, mc, str, str2); - mem_free(str3); - } + str = str_addchar(fatal_error, mc, str, stream_pop(&args->stream)); + if (quote) + if (!stream_pop(&args->stream)) + return (NULL); str = str_dup(fatal_error, args->mc, str); mem_freeall(mc); return (str); @@ -65,15 +83,19 @@ static const char *get_string(t_parsing_args *args, const char *stop_charset) // Get a program call (program names & its arguments) until stop_charset. static int get_call(t_parsing_args *args, const char *stop_charset) { - t_call *r; - t_list arguments; + t_call *r; + t_list arguments; + const char *str; arguments = list_createempty(args->mc); while (stream_read(&args->stream) && !char_isin(stream_read(&args->stream), stop_charset)) { + str = get_string(args, stop_charset); + if (!str) + return (parse_error()); list_add(fatal_error, &arguments, - (char *)get_string(args, stop_charset)); + (char *)str); skip_blank(&args->stream); } r = mem_alloc(fatal_error, args->mc, sizeof(t_call)); From d7b4631701cac2ff450fb473fea6c18bdf248826 Mon Sep 17 00:00:00 2001 From: mcolonna Date: Tue, 30 Apr 2024 14:34:15 +0200 Subject: [PATCH 07/12] redirections, empty command, parse errors++ --- include/include.h | 6 ++- src/error.c | 9 +++- src/exec_command.c | 4 +- src/main.c | 15 +++++- src/parse_command.c | 114 ++++++++++++++++++++++++++++++++++---------- 5 files changed, 118 insertions(+), 30 deletions(-) diff --git a/include/include.h b/include/include.h index 81ed7fd..678e891 100644 --- a/include/include.h +++ b/include/include.h @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:15:12 by mcolonna #+# #+# */ -/* Updated: 2024/04/29 15:56:26 by mcolonna ### ########.fr */ +/* Updated: 2024/04/30 15:00:48 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -47,6 +47,7 @@ typedef struct s_call typedef struct s_command { int error; // 0 if parse_command() succeded, error status if not + bool empty; // true if there isn't anything to do const t_call *calls; // all calls to programs (ended by .program == NULL) int input_fd; // fd to use with '<' redirection (0 by default) int output_fd; // fd to use with '>' redirection (1 by default) @@ -71,6 +72,9 @@ void minishell_error(const char *msg); // Call perror() and exit the program. void fatal_error(const char *msg); +// Call strerror() and exit the program. +void fatal_error_msg(const char *msg); + ///// PATH ///// // Get the PATH values. diff --git a/src/error.c b/src/error.c index ac0246b..d67e423 100644 --- a/src/error.c +++ b/src/error.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 15:51:56 by mcolonna #+# #+# */ -/* Updated: 2024/04/29 15:39:56 by mcolonna ### ########.fr */ +/* Updated: 2024/04/30 15:01:27 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -31,3 +31,10 @@ void fatal_error(const char *msg) mem_freeall(g_mc); exit(errno); } + +void fatal_error_msg(const char *msg) +{ + minishell_error(msg); + mem_freeall(g_mc); + exit(errno); +} diff --git a/src/exec_command.c b/src/exec_command.c index 1440798..6ae9086 100644 --- a/src/exec_command.c +++ b/src/exec_command.c @@ -6,7 +6,7 @@ /* By: jschaft +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:48:00 by jschaft #+# #+# */ -/* Updated: 2024/04/29 15:51:00 by mcolonna ### ########.fr */ +/* Updated: 2024/04/30 13:58:04 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -56,7 +56,7 @@ static int execute_call(t_memclass mc, t_call call, const int inout[2], // TODO works with only one call (no pipe). int execute_command(t_memclass mc, t_command command, char *const envp[]) { - const int inout[] = {0, 1}; + const int inout[] = {command.input_fd, command.output_fd}; int nb_calls; int r; diff --git a/src/main.c b/src/main.c index 944584b..c004707 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:33:45 by mcolonna #+# #+# */ -/* Updated: 2024/04/29 15:40:08 by mcolonna ### ########.fr */ +/* Updated: 2024/04/30 16:06:11 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -53,6 +53,16 @@ static void print_hi(void) t_memclass g_mc; +static void close_fds(const t_command *command) +{ + if (command->input_fd != 0) + if (close(command->input_fd) != -1) + minishell_error("errno"); + if (command->output_fd != 1) + if (close(command->output_fd) != -1) + minishell_error("errno"); +} + int main(const int argc, const char *argv[], char *const envp[]) { t_memclass mc; @@ -72,10 +82,11 @@ int main(const int argc, const char *argv[], char *const envp[]) mc = mem_subclass(fatal_error, g_mc); command_str = ask_command(mc); command = parse_command(mc, command_str); - if (command.error) + if (command.error || command.empty) continue ; errorstatus = execute_command(mc, command, envp); mem_freeall(mc); + close_fds(&command); } return (errorstatus); } diff --git a/src/parse_command.c b/src/parse_command.c index 8a9a93d..310cc71 100644 --- a/src/parse_command.c +++ b/src/parse_command.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:47:40 by mcolonna #+# #+# */ -/* Updated: 2024/04/29 16:45:13 by mcolonna ### ########.fr */ +/* Updated: 2024/04/30 16:22:08 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,9 +14,12 @@ // To call when a parse error occurs. // Always returns 1 (parse error's status). -static int parse_error(void) +static int parse_error(const char *msg) { - minishell_error("parse error"); + const t_memclass mc = mem_subclass(fatal_error, g_mc); + + minishell_error(str_join(fatal_error, mc, "parse error: ", msg)); + mem_freeall(mc); return (1); } @@ -67,7 +70,7 @@ static const char *get_string(t_parsing_args *args, const char *stop_charset) stop_charset_2 = str_join(fatal_error, mc, stop_charset, " \n"); else stop_charset_2 = str_addchar(fatal_error, mc, - str_dup(fatal_error, mc, ""), quote); + str_dup(fatal_error, mc, ""), quote); str = str_dup(fatal_error, mc, ""); while (stream_read(&args->stream) && !char_isin(stream_read(&args->stream), stop_charset_2)) @@ -93,7 +96,7 @@ static int get_call(t_parsing_args *args, const char *stop_charset) { str = get_string(args, stop_charset); if (!str) - return (parse_error()); + return (parse_error("EOF unexpected")); list_add(fatal_error, &arguments, (char *)str); skip_blank(&args->stream); @@ -101,7 +104,7 @@ static int get_call(t_parsing_args *args, const char *stop_charset) r = mem_alloc(fatal_error, args->mc, sizeof(t_call)); r->program = (char *)list_get(err_remember, &arguments, 0); if (err_get()) - return (parse_error()); + return (parse_error("program name expected")); r->argc = list_getsize(&arguments); r->argv = (char *const *)list_convert( fatal_error, args->mc, &arguments); @@ -110,49 +113,112 @@ static int get_call(t_parsing_args *args, const char *stop_charset) return (0); } +static int get_inputfile(t_parsing_args *args, const char *stop_charset) +{ + const char *str; + + if (args->r.input_fd != 0) + return (parse_error("several input files")); + if (!stream_read(&args->stream)) + return (parse_error("EOF unexpected")); + str = get_string(args, stop_charset); + if (!str) + return (parse_error("EOF unexpected")); + args->r.input_fd = open(str, O_RDONLY); + if (args->r.input_fd == -1) + return (perror(str), errno); + return (0); +} + +static int get_outputfile(t_parsing_args *args, const char *stop_charset) +{ + const char *str; + + if (args->r.output_fd != 1) + return (parse_error("several output files")); + if (!stream_read(&args->stream)) + return (parse_error("EOF unexpected")); + str = get_string(args, stop_charset); + if (!str) + return (parse_error("EOF unexpected")); + args->r.output_fd = open( + str, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (args->r.output_fd == -1) + return (perror(str), errno); + return (0); +} + +static void get_element2(t_parsing_args *args, int *error, char c) +{ + stream_pop(&args->stream); + skip_blank(&args->stream); + if (c == '|') + { + if (!args->got_first_call) + *error = parse_error("'|', '>' or '<' expected"); + *error = get_call(args, "<>|"); + } + else if (c == '>') + *error = get_outputfile(args, "<>|"); + else if (c == '<') + *error = get_inputfile(args, "<>|"); + else + fatal_error_msg("internal error u.u"); +} + // Read an element (a call to a program, a '< FILE' or a '> FILE') // On success, return 0. On error, return the error status. -// (TODO redirections) static int get_element(t_parsing_args *args) { - char c; - int error; + char c; + int error; error = 0; while (!error && stream_read(&args->stream)) { c = stream_read(&args->stream); - if (c == '|') - { - if (!args->got_first_call) - return (parse_error()); - stream_pop(&args->stream); - skip_blank(&args->stream); - error = get_call(args, "<>|"); - } + if (char_isin(c, "|><")) + get_element2(args, &error, c); else if (!args->got_first_call) error = get_call(args, "<>|"); else - return (parse_error()); + return (parse_error("'|', '>' or '<'' expected")); skip_blank(&args->stream); } return (error); } +t_parsing_args init_parsing_args(const t_memclass mc) +{ + const t_parsing_args r = { + .mc = mc, + .r = { + .error = 0, + .empty = false, + .input_fd = 0, + .output_fd = 1, + }, + .calls = list_createempty(mc), + .got_first_call = false, + }; + + return (r); +} + t_command parse_command(const t_memclass mc, const char *command) { t_parsing_args args; int error; error = 0; - args.mc = mc; - args.r.error = 0; - args.r.input_fd = 0; - args.r.output_fd = 1; - args.calls = list_createempty(mc); - args.got_first_call = false; + args = init_parsing_args(mc); streamstr_init(&args.stream, command); skip_blank(&args.stream); + if (!stream_read(&args.stream)) + { + args.r.empty = true; + return (args.r); + } while (!error && stream_read(&args.stream)) { error = get_element(&args); From f8c50143d6603db10d584549a9d3608e46023ff9 Mon Sep 17 00:00:00 2001 From: mcolonna Date: Wed, 1 May 2024 12:48:12 +0200 Subject: [PATCH 08/12] [ADD] too much colors (and change header) --- dev/lolcat.sh | 1 + header | 21 +++++++++++++ header.nocolor | 21 +++++++++++++ src/ask_command.c | 4 +-- src/main.c | 76 +++++++++++++++++------------------------------ 5 files changed, 72 insertions(+), 51 deletions(-) create mode 100755 dev/lolcat.sh create mode 100644 header create mode 100644 header.nocolor diff --git a/dev/lolcat.sh b/dev/lolcat.sh new file mode 100755 index 0000000..c12be90 --- /dev/null +++ b/dev/lolcat.sh @@ -0,0 +1 @@ +COLORTERM= lolcat -p 1 -F 0.3 -S 0 -f header.nocolor > header diff --git a/header b/header new file mode 100644 index 0000000..d3ec095 --- /dev/null +++ b/header @@ -0,0 +1,21 @@ + Welcome to__________________________________ +||  ___        ___                           || +|| |   \      /   |                          || +|| | |\ \    / /| |   _    __     _    _     || +|| | | \ \  / / | |  |_|  |  \   | |  |_|    || +|| | |  \ \/ /  | |   _   |   \  | |   _     || +|| | |   \  /   | |  | |  | |\ \ | |  | |    || +|| | |    \/    | |  | |  | | \ \| |  | |    || +|| | |          | |  | |  | |  \   |  | |    || +|| |_|          |_|  |_|  |_|   \__|  |_|    || +||                                           || +||       =====     By: Mylan COLONNA         || +||      //            And: Joris SCHAFT      || +||     //                                    || +||     \\                                    || +||      =====  ||  ||  ==== ||    ||         || +||          \\ ||  || ||    ||    ||         || +||          // |====| |===  ||    ||         || +||         //  ||  || ||    ||    ||         || +||     =====   ||  ||  ====  ====  ====      || +||___________________________________________|| diff --git a/header.nocolor b/header.nocolor new file mode 100644 index 0000000..bf43ad5 --- /dev/null +++ b/header.nocolor @@ -0,0 +1,21 @@ + Welcome to__________________________________ +|| ___ ___ || +|| | \ / | || +|| | |\ \ / /| | _ __ _ _ || +|| | | \ \ / / | | |_| | \ | | |_| || +|| | | \ \/ / | | _ | \ | | _ || +|| | | \ / | | | | | |\ \ | | | | || +|| | | \/ | | | | | | \ \| | | | || +|| | | | | | | | | \ | | | || +|| |_| |_| |_| |_| \__| |_| || +|| || +|| ===== By: Mylan COLONNA || +|| // And: Joris SCHAFT || +|| // || +|| \\ || +|| ===== || || ==== || || || +|| \\ || || || || || || +|| // |====| |=== || || || +|| // || || || || || || +|| ===== || || ==== ==== ==== || +||___________________________________________|| diff --git a/src/ask_command.c b/src/ask_command.c index 5652910..5b7719a 100644 --- a/src/ask_command.c +++ b/src/ask_command.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 15:03:23 by mcolonna #+# #+# */ -/* Updated: 2024/04/29 15:11:06 by mcolonna ### ########.fr */ +/* Updated: 2024/05/01 12:46:34 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,7 +16,7 @@ const char *ask_command(const t_memclass mc) { const char *r; - print_str(fatal_error, 1, "( ^.^)> "); + print_str(fatal_error, 1, "\e[1m\e[38;5;45m( ^.^)> \e[0m"); r = read_line(fatal_error, mc, 0); if (r) return (r); diff --git a/src/main.c b/src/main.c index c004707..0182151 100644 --- a/src/main.c +++ b/src/main.c @@ -6,53 +6,15 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:33:45 by mcolonna #+# #+# */ -/* Updated: 2024/04/30 16:06:11 by mcolonna ### ########.fr */ +/* Updated: 2024/05/01 11:35:54 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "include.h" -// Clean the screen -static void execclear(char *const envp[]) -{ - const t_memclass mc = mem_subclass(fatal_error, g_mc); - t_command command; - - command = parse_command(mc, "clear"); - if (command.error) - return ; - execute_command(mc, command, envp); - mem_freeall(mc); -} - -// Print hi :D -static void print_hi(void) -{ - printf("Welcome to____________________________________\n"); - printf("|| ___ ___ ||\n"); - printf("|| | \\ / | ||\n"); - printf("|| | |\\ \\ / /| | __ __ __ __ ||\n"); - printf("|| | | \\ \\ / / | | |__| ||\\ || |__| ||\n"); - printf("|| | | \\ \\/ / | | __ || \\ || __ ||\n"); - printf("|| | | \\ / | | || || \\ || || ||\n"); - printf("|| | | \\/ | | || || \\ || || ||\n"); - printf("|| | | | | || || \\ || || ||\n"); - printf("|| |_| |_| || || \\|| || ||\n"); - printf("|| _____ ||\n"); - printf("|| / ___| By: Mylan COLONNA ||\n"); - printf("|| \\ \\ And: Joris SCHAFT ||\n"); - printf("|| \\ \\ ||\n"); - printf("|| \\ \\ __ __ __ __ __ ||\n"); - printf("|| \\ \\ || || ||=== || || ||\n"); - printf("|| \\ \\ || || || || || ||\n"); - printf("|| / / ||===|| ||=== || || ||\n"); - printf("|| ___/ / || || || || || ||\n"); - printf("|| |____/ || || ||=== ||=== ||=== ||\n"); - printf("|_____________________________________________|\n\n"); -} - t_memclass g_mc; +// Close the input and output fds of the command. static void close_fds(const t_command *command) { if (command->input_fd != 0) @@ -63,30 +25,46 @@ static void close_fds(const t_command *command) minishell_error("errno"); } +// Execute a command from a string. +static int do_command(char *const envp[], const char *str) +{ + const t_memclass mc = mem_subclass(fatal_error, g_mc); + t_command command; + int r; + + command = parse_command(mc, str); + if (command.error || command.empty) + return (command.error); + r = execute_command(mc, command, envp); + mem_freeall(mc); + close_fds(&command); + return (r); +} + +static void start(char *const envp[]) +{ + do_command(envp, "clear"); + do_command(envp, "cat ./header"); + do_command(envp, "echo"); +} + int main(const int argc, const char *argv[], char *const envp[]) { t_memclass mc; const char *command_str; - t_command command; int errorstatus; (void)argc; (void)argv; g_mc = NULL; g_mc = mem_newclass(fatal_error); - execclear(envp); - print_hi(); + start(envp); errorstatus = 0; while (true) { mc = mem_subclass(fatal_error, g_mc); command_str = ask_command(mc); - command = parse_command(mc, command_str); - if (command.error || command.empty) - continue ; - errorstatus = execute_command(mc, command, envp); - mem_freeall(mc); - close_fds(&command); + do_command(envp, command_str); } return (errorstatus); } From 74564daa521a329581d01fc5b0e93d80d395fe7e Mon Sep 17 00:00:00 2001 From: mcolonna Date: Wed, 1 May 2024 16:28:34 +0200 Subject: [PATCH 09/12] libtfise everything --- include/include.h | 4 ++-- src/exec_command.c | 47 ++++++++++++++++++---------------------------- src/path.c | 11 +++++------ 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/include/include.h b/include/include.h index 678e891..13f6b22 100644 --- a/include/include.h +++ b/include/include.h @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:15:12 by mcolonna #+# #+# */ -/* Updated: 2024/04/30 15:00:48 by mcolonna ### ########.fr */ +/* Updated: 2024/05/01 17:52:52 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -79,7 +79,7 @@ void fatal_error_msg(const char *msg); // Get the PATH values. // Return a list of strings ended by NULL. -char **get_path(char *const envp[]); +const char **get_path(const t_memclass mc, char *const envp[]); // Search the program in $PATH. // Returns the path of the program to use, or NULL if there is none. diff --git a/src/exec_command.c b/src/exec_command.c index 6ae9086..e9640da 100644 --- a/src/exec_command.c +++ b/src/exec_command.c @@ -6,54 +6,43 @@ /* By: jschaft +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:48:00 by jschaft #+# #+# */ -/* Updated: 2024/04/30 13:58:04 by mcolonna ### ########.fr */ +/* Updated: 2024/05/01 17:51:49 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "include.h" -// Free every element of tab, then tab itself. -static void free_tab(char **tab) -{ - int i; - - i = 0; - while (tab[i] != NULL) - { - free(tab[i]); - i++; - } - free(tab); -} - -static void fork_exec(const char *path, t_call call, const int inout[2], - char *const envp[]) -{ - dup2(inout[0], 0); - dup2(inout[1], 1); - execve(path, call.argv, envp); -} - +// Execute a program with specific stdin and stdout: +// - inout[0] is stdin +// - inout[0] is stdout +// If call.program doesn't start with "./" or "/", find the program in $PATH. +// (TODO) +// If the program wasn't to found in $PATH, or the fork didn't work, +// write the error (TODO) and return the error status. static int execute_call(t_memclass mc, t_call call, const int inout[2], char *const envp[]) { - char **const path = get_path(envp); - pid_t pid; - const char *program_path; + const char **path = get_path(mc, envp); + pid_t pid; + const char *program_path; - program_path = search_path(mc, (const char **)path, call.program); + program_path = search_path(mc, path, call.program); if (!program_path) return (127); pid = fork(); if (pid < 0) return (1); if (pid == 0) - fork_exec(program_path, call, inout, envp); - free_tab(path); + { + dup2(inout[0], 0); + dup2(inout[1], 1); + execve(program_path, call.argv, envp); + } return (0); } // TODO works with only one call (no pipe). +// Execute a command, return the error status. int execute_command(t_memclass mc, t_command command, char *const envp[]) { const int inout[] = {command.input_fd, command.output_fd}; diff --git a/src/path.c b/src/path.c index be44a0e..78f0660 100644 --- a/src/path.c +++ b/src/path.c @@ -6,24 +6,23 @@ /* By: jschaft +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/11/16 12:07:26 by jschaft #+# #+# */ -/* Updated: 2024/04/29 15:54:40 by mcolonna ### ########.fr */ +/* Updated: 2024/05/01 17:53:38 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "include.h" -char **get_path(char *const envp[]) +const char **get_path(const t_memclass mc, char *const envp[]) { int i; - char **re; + const char **re; char *path; i = 0; while (ft_strncmp(envp[i], "PATH=", 5) != 0) i++; - path = ft_substr(envp[i], 5, ft_strlen(envp[i]) - 5); - re = ft_split(path, ':'); - free(path); + path = envp[i] + 5; + re = (const char **)str_split(fatal_error, mc, path, ":"); return (re); } From c86126ec9dbd39102dcd257e9e782c8b38eb3f93 Mon Sep 17 00:00:00 2001 From: mcolonna Date: Thu, 2 May 2024 13:56:56 +0200 Subject: [PATCH 10/12] [ADD] redirection '>>' also fix close_fds() --- src/main.c | 6 +++--- src/parse_command.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main.c b/src/main.c index 0182151..9dcc9e0 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/23 14:33:45 by mcolonna #+# #+# */ -/* Updated: 2024/05/01 11:35:54 by mcolonna ### ########.fr */ +/* Updated: 2024/05/02 15:20:41 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,10 +18,10 @@ t_memclass g_mc; static void close_fds(const t_command *command) { if (command->input_fd != 0) - if (close(command->input_fd) != -1) + if (close(command->input_fd) == -1) minishell_error("errno"); if (command->output_fd != 1) - if (close(command->output_fd) != -1) + if (close(command->output_fd) == -1) minishell_error("errno"); } diff --git a/src/parse_command.c b/src/parse_command.c index 310cc71..271a47e 100644 --- a/src/parse_command.c +++ b/src/parse_command.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:47:40 by mcolonna #+# #+# */ -/* Updated: 2024/04/30 16:22:08 by mcolonna ### ########.fr */ +/* Updated: 2024/05/02 15:15:36 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -133,16 +133,24 @@ static int get_inputfile(t_parsing_args *args, const char *stop_charset) static int get_outputfile(t_parsing_args *args, const char *stop_charset) { const char *str; + int flag; if (args->r.output_fd != 1) return (parse_error("several output files")); if (!stream_read(&args->stream)) return (parse_error("EOF unexpected")); + flag = O_TRUNC; + if (stream_read(&args->stream) == '>') + { + stream_pop(&args->stream); + flag = O_APPEND; + } + skip_blank(&args->stream); str = get_string(args, stop_charset); if (!str) return (parse_error("EOF unexpected")); args->r.output_fd = open( - str, O_WRONLY | O_CREAT | O_TRUNC, 0666); + str, O_WRONLY | O_CREAT | flag, 0666); if (args->r.output_fd == -1) return (perror(str), errno); return (0); From 0fac25fd8154ae5eb20780449ae48019be262994 Mon Sep 17 00:00:00 2001 From: mcolonna Date: Tue, 7 May 2024 14:00:26 +0200 Subject: [PATCH 11/12] [ADD] redirection '<<' --- src/parse_command.c | 54 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/src/parse_command.c b/src/parse_command.c index 271a47e..2d6dd3b 100644 --- a/src/parse_command.c +++ b/src/parse_command.c @@ -6,12 +6,44 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:47:40 by mcolonna #+# #+# */ -/* Updated: 2024/05/02 15:15:36 by mcolonna ### ########.fr */ +/* Updated: 2024/05/07 13:59:30 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "include.h" +// Ask the user for data and set readfd to the fd which will receive this +// data. +// Returns 'errno' on error. +static int heredoc(t_memclass mc, int *readfd, const char *eof) +{ + const t_memclass mc_in = mem_subclass(fatal_error, mc); + int outpipe[2]; + t_const_string line; + const t_const_string eof_line = str_join(fatal_error, mc_in, eof, "\n"); + + if (pipe(outpipe) == -1) + minishell_error("errno"); + *readfd = outpipe[0]; + while (true) + { + print_str(fatal_error, 1, "\e[38;5;33m( 'o')> \e[0m"); + line = NULL; + while (!line) + line = read_line(fatal_error, mc_in, 0); + if (str_eq(line, eof) || str_eq(line, eof_line)) + break ; + print_str(err_remember, outpipe[1], line); + mem_free((void *)line); + if (err_get()) + return (minishell_error("errno"), errno); + } + mem_freeall(mc_in); + if (close(outpipe[1]) == -1) + return (minishell_error("errno"), errno); + return (0); +} + // To call when a parse error occurs. // Always returns 1 (parse error's status). static int parse_error(const char *msg) @@ -31,6 +63,7 @@ typedef struct s_parsing_args t_stream stream; t_list calls; bool got_first_call; // got at least the first program call? + const char *heredoc; } t_parsing_args; // Skip blank characters @@ -116,17 +149,27 @@ static int get_call(t_parsing_args *args, const char *stop_charset) static int get_inputfile(t_parsing_args *args, const char *stop_charset) { const char *str; + bool heredoc; if (args->r.input_fd != 0) return (parse_error("several input files")); if (!stream_read(&args->stream)) return (parse_error("EOF unexpected")); + heredoc = stream_read(&args->stream) == '<'; + if (heredoc) + stream_pop(&args->stream); + skip_blank(&args->stream); str = get_string(args, stop_charset); if (!str) return (parse_error("EOF unexpected")); - args->r.input_fd = open(str, O_RDONLY); - if (args->r.input_fd == -1) - return (perror(str), errno); + if (heredoc) + args->heredoc = str; + else + { + args->r.input_fd = open(str, O_RDONLY); + if (args->r.input_fd == -1) + return (perror(str), errno); + } return (0); } @@ -208,6 +251,7 @@ t_parsing_args init_parsing_args(const t_memclass mc) }, .calls = list_createempty(mc), .got_first_call = false, + .heredoc = NULL, }; return (r); @@ -237,5 +281,7 @@ t_command parse_command(const t_memclass mc, const char *command) fatal_error, args.mc, &args.calls, sizeof(t_call)); if (error) args.r.error = error; + if (args.heredoc) + heredoc(mc, &args.r.input_fd, args.heredoc); return (args.r); } From bfee212ed629ecef34b966d9a0048c20e5eff95f Mon Sep 17 00:00:00 2001 From: mcolonna Date: Tue, 7 May 2024 14:13:02 +0200 Subject: [PATCH 12/12] add dev/TODO --- dev/TODO | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 dev/TODO diff --git a/dev/TODO b/dev/TODO new file mode 100644 index 0000000..26b8dd7 --- /dev/null +++ b/dev/TODO @@ -0,0 +1,21 @@ +- working history (rl_* functions?) + - '<<' with history? +- finding commands + - built-in commands + - relative/absolute paths +- signals + - ^C, ^D, ^\ +- variables + - normal variables + - environment variables + - $? +- pipes + - no calls (like `$ < input_file > output_file`) +- builtins: + - echo (with option -n) + - cd [path] + - pwd (with no options) + - export (with no options) + - unset (with no options) + - env (with no options or arguments) + - exit (with no options)