diff --git a/README.md b/README.md index f9130ce..be08206 100644 --- a/README.md +++ b/README.md @@ -7,26 +7,22 @@ TODO ### Build -run theses commands: - `autoreconf --force --verbose --install && ./configure` +run this command: + `autoreconf --force --verbose --install` + +### Test +run this command: + `./configure CFLAGS='-std=c99 -Werror -Wall -Wextra -Wvla'` +then: `make` - `./src/42sh --help` - -### Testing +#### asan run this command: + `./configure CFLAGS='-std=c99 -Werror -Wall -Wextra -Wvla -g -fsanitize=address'` + +then: `make check` -#### debug (asan) - -run this command: - `./src/debug` - -#### testsuite - -run this command: - `./src/testsuite` - ## Authors - Matteo Flebus diff --git a/src/Makefile.am b/src/Makefile.am index c5c19e7..bd5d691 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,8 +28,8 @@ bin_PROGRAMS = 42sh check_PROGRAMS = testsuite -testsuite_CFLAGS = $(42sh_CFLAGS) -testsuite_CFLAGS += $(CRITERION_CFLAGS) +#testsuite_CFLAGS = $(42sh_CFLAGS) +#testsuite_CFLAGS += $(CRITERION_CFLAGS) testsuite_SOURCES = ../tests/unit/lexer/lexer_tests.c \ ../tests/unit/utils/utils_tests.c @@ -42,8 +42,8 @@ testsuite_LDADD = $(42sh_LDADD) $(CRITERION_LIBS) check_PROGRAMS += debug -debug_CFLAGS = $(42sh_CFLAGS) -debug_CFLAGS += -fsanitize=address -g +#debug_CFLAGS = $(42sh_CFLAGS) +#debug_CFLAGS += -fsanitize=address -g debug_SOURCES = $(42sh_SOURCES) diff --git a/src/execution/execution.c b/src/execution/execution.c index 33389cb..a882397 100644 --- a/src/execution/execution.c +++ b/src/execution/execution.c @@ -1,13 +1,13 @@ #include "execution.h" +#include +#include #include #include +#include #include #include #include -#include -#include -#include #include "../utils/ast/ast.h" @@ -70,7 +70,7 @@ static int builtin_echo(char **argv) } if (newline) printf("\n"); - + fflush(stdout); return 0; } @@ -120,7 +120,7 @@ static int try_builtin(char **argv) { if (!argv || !argv[0]) return 0; - + if (strcmp(argv[0], "echo") == 0) return builtin_echo(argv); if (strcmp(argv[0], "true") == 0) @@ -242,7 +242,7 @@ int execution(struct ast *ast) case AST_AND_OR: { struct ast_and_or *ao_node = ast_get_and_or(ast); int left_ret = execution(ao_node->left); - + if (ao_node->type == AST_AND_OR_TYPE_AND) { if (left_ret == 0) @@ -258,38 +258,42 @@ int execution(struct ast *ast) } case AST_REDIR: { struct ast_redir *redir = ast_get_redir(ast); - + int fd_target = redir->io_number; if (fd_target == -1) { - if (redir->type == AST_REDIR_TYPE_LESS || redir->type == AST_REDIR_TYPE_DLESS || redir->type == AST_REDIR_TYPE_LESSAND) + if (redir->type == AST_REDIR_TYPE_LESS + || redir->type == AST_REDIR_TYPE_DLESS + || redir->type == AST_REDIR_TYPE_LESSAND) fd_target = 0; else fd_target = 1; } - + int saved_fd = dup(fd_target); - + int new_fd = -1; int flags = 0; int mode = 0644; - - if (redir->type == AST_REDIR_TYPE_GREAT || redir->type == AST_REDIR_TYPE_CLOBBER) + + if (redir->type == AST_REDIR_TYPE_GREAT + || redir->type == AST_REDIR_TYPE_CLOBBER) { flags = O_WRONLY | O_CREAT | O_TRUNC; new_fd = open(redir->filename, flags, mode); } else if (redir->type == AST_REDIR_TYPE_DGREAT) { - flags = O_WRONLY | O_CREAT | O_APPEND; - new_fd = open(redir->filename, flags, mode); + flags = O_WRONLY | O_CREAT | O_APPEND; + new_fd = open(redir->filename, flags, mode); } else if (redir->type == AST_REDIR_TYPE_LESS) { - flags = O_RDONLY; - new_fd = open(redir->filename, flags); + flags = O_RDONLY; + new_fd = open(redir->filename, flags); } - else if (redir->type == AST_REDIR_TYPE_GREATAND || redir->type == AST_REDIR_TYPE_LESSAND) + else if (redir->type == AST_REDIR_TYPE_GREATAND + || redir->type == AST_REDIR_TYPE_LESSAND) { // Simple fd duplication new_fd = atoi(redir->filename); @@ -297,16 +301,18 @@ int execution(struct ast *ast) if (dup2(new_fd, fd_target) == -1) { perror("dup2"); - if (saved_fd != -1) close(saved_fd); + if (saved_fd != -1) + close(saved_fd); return 1; } new_fd = -2; // Mark as "already duped" } - + if (new_fd == -1) { perror("open"); - if (saved_fd != -1) close(saved_fd); + if (saved_fd != -1) + close(saved_fd); return 1; } @@ -316,7 +322,8 @@ int execution(struct ast *ast) { perror("dup2"); close(new_fd); - if (saved_fd != -1) close(saved_fd); + if (saved_fd != -1) + close(saved_fd); return 1; } close(new_fd); diff --git a/src/io_backend/io_backend.h b/src/io_backend/io_backend.h index 7b9e9b2..413dced 100644 --- a/src/io_backend/io_backend.h +++ b/src/io_backend/io_backend.h @@ -2,6 +2,7 @@ #define IO_BACKEND_H #include + #include "utils/args/args.h" // Error codes diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index ef5a478..47703f3 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -69,62 +69,62 @@ static void set_token_spechar(struct token *tok, char *begin, ssize_t size) return; switch (begin[0]) { - case EOF: - tok->type = TOKEN_EOF; - break; - case ';': - tok->type = TOKEN_SEMICOLON; - break; - case '\n': - tok->type = TOKEN_NEWLINE; - break; - case '\'': - tok->type = TOKEN_QUOTE; - break; - case '"': - tok->type = TOKEN_DOUBLE_QUOTE; - break; - case '`': - tok->type = TOKEN_GRAVE; - break; - case '#': - tok->type = TOKEN_COMMENT; - break; - case '|': - tok->type = TOKEN_PIPE; - break; - case '&': - tok->type = TOKEN_AMPERSAND; - break; - case '\\': - tok->type = TOKEN_BACKSLASH; - break; - case '$': - tok->type = TOKEN_DOLLAR; - break; - case '(': - tok->type = TOKEN_LEFT_PAREN; - break; - case ')': - tok->type = TOKEN_RIGHT_PAREN; - break; - case '{': - tok->type = TOKEN_LEFT_BRACKET; - break; - case '}': - tok->type = TOKEN_RIGHT_BRACKET; - break; - case '<': - tok->type = TOKEN_LESS; - break; - case '>': - tok->type = TOKEN_GREATER; - break; - case '*': - tok->type = TOKEN_STAR; - break; - default: - break; + case EOF: + tok->type = TOKEN_EOF; + break; + case ';': + tok->type = TOKEN_SEMICOLON; + break; + case '\n': + tok->type = TOKEN_NEWLINE; + break; + case '\'': + tok->type = TOKEN_QUOTE; + break; + case '"': + tok->type = TOKEN_DOUBLE_QUOTE; + break; + case '`': + tok->type = TOKEN_GRAVE; + break; + case '#': + tok->type = TOKEN_COMMENT; + break; + case '|': + tok->type = TOKEN_PIPE; + break; + case '&': + tok->type = TOKEN_AMPERSAND; + break; + case '\\': + tok->type = TOKEN_BACKSLASH; + break; + case '$': + tok->type = TOKEN_DOLLAR; + break; + case '(': + tok->type = TOKEN_LEFT_PAREN; + break; + case ')': + tok->type = TOKEN_RIGHT_PAREN; + break; + case '{': + tok->type = TOKEN_LEFT_BRACKET; + break; + case '}': + tok->type = TOKEN_RIGHT_BRACKET; + break; + case '<': + tok->type = TOKEN_LESS; + break; + case '>': + tok->type = TOKEN_GREATER; + break; + case '*': + tok->type = TOKEN_STAR; + break; + default: + break; } } diff --git a/src/main.c b/src/main.c index 8a81efb..a3e9527 100644 --- a/src/main.c +++ b/src/main.c @@ -69,9 +69,14 @@ int main(int argc, char **argv) // Execute AST return_code = execution(command_ast); + ast_free(&command_ast); + // Retrieve and build next AST command_ast = get_ast(); } + + ast_free(&command_ast); + if (command_ast == NULL) return ERR_INPUT_PROCESSING; diff --git a/src/parser/parser.c b/src/parser/parser.c index 0cce2fb..cf7b052 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -7,8 +7,8 @@ #include #include "lexer/lexer.h" -#include "utils/lists/lists.h" #include "parser/parsing_utils.h" +#include "utils/lists/lists.h" // === Static functions // ... diff --git a/src/parser/parsing_utils.c b/src/parser/parsing_utils.c index c07653e..9ac32d8 100644 --- a/src/parser/parsing_utils.c +++ b/src/parser/parsing_utils.c @@ -1,9 +1,11 @@ +#define _POSIX_C_SOURCE 200809L // === Includes #include "parsing_utils.h" #include #include #include +#include #include "lexer/lexer.h" #include "utils/ast/ast.h" @@ -58,7 +60,8 @@ struct ast *parse_simple_command(void) while (!isterminator(token)) { token = POP_TOKEN(); - command_elements = list_append(command_elements, token->data); + char *word = strdup(token->data); + command_elements = list_append(command_elements, word); token = PEEK_TOKEN(); } @@ -86,6 +89,7 @@ struct ast *parse_list(void) } token = PEEK_TOKEN(); } + result_list = list_append(result_list, current_node); return ast_create_list(result_list); } @@ -163,7 +167,9 @@ struct ast *parse_compound_list(void) return NULL; } - command_elements = list_append(command_elements, token->data); + char *word = strdup(token->data); + + command_elements = list_append(command_elements, word); token = POP_TOKEN(); } diff --git a/src/parser/parsing_utils.h b/src/parser/parsing_utils.h index a380a85..6fe6b89 100644 --- a/src/parser/parsing_utils.h +++ b/src/parser/parsing_utils.h @@ -28,7 +28,7 @@ struct ast *parse_list(void); */ struct ast *parse_simple_command(void); -/* +/* */ struct ast *parse_if_rule(void); @@ -39,14 +39,14 @@ struct ast *parse_shell_command(void); /* @brief parses commands inside if/else clauses and returns the corresponding * AST list */ -struct ast* parse_compound_list(void); +struct ast *parse_compound_list(void); /* */ -struct ast* parse_and_or(void); +struct ast *parse_and_or(void); /* */ -struct ast* parse_else_clause(void); +struct ast *parse_else_clause(void); #endif /* ! PARSING_UTILS_H */ diff --git a/src/utils/ast/ast.h b/src/utils/ast/ast.h index 1062782..5a06cf8 100644 --- a/src/utils/ast/ast.h +++ b/src/utils/ast/ast.h @@ -1,13 +1,13 @@ #ifndef AST_H #define AST_H +#include "utils/ast/ast_and_or.h" #include "utils/ast/ast_base.h" #include "utils/ast/ast_command.h" -#include "utils/ast/ast_if.h" -#include "utils/ast/ast_and_or.h" -#include "utils/ast/ast_redir.h" -#include "utils/ast/ast_list.h" #include "utils/ast/ast_end.h" +#include "utils/ast/ast_if.h" +#include "utils/ast/ast_list.h" +#include "utils/ast/ast_redir.h" #include "utils/ast/ast_void.h" #endif /* ! AST_H */ diff --git a/src/utils/ast/ast_and_or.c b/src/utils/ast/ast_and_or.c index d07eaf5..6b6038b 100644 --- a/src/utils/ast/ast_and_or.c +++ b/src/utils/ast/ast_and_or.c @@ -1,4 +1,5 @@ #include "utils/ast/ast_and_or.h" + #include bool ast_is_and_or(struct ast *node) @@ -13,7 +14,8 @@ struct ast_and_or *ast_get_and_or(struct ast *node) return NULL; } -struct ast *ast_create_and_or(struct ast *left, struct ast *right, enum ast_and_or_type type) +struct ast *ast_create_and_or(struct ast *left, struct ast *right, + enum ast_and_or_type type) { struct ast_and_or *and_or = malloc(sizeof(struct ast_and_or)); if (!and_or) diff --git a/src/utils/ast/ast_and_or.h b/src/utils/ast/ast_and_or.h index 57a9668..e370558 100644 --- a/src/utils/ast/ast_and_or.h +++ b/src/utils/ast/ast_and_or.h @@ -2,14 +2,17 @@ #define AST_AND_OR_H #include + #include "utils/ast/ast_base.h" -enum ast_and_or_type { +enum ast_and_or_type +{ AST_AND_OR_TYPE_AND, AST_AND_OR_TYPE_OR }; -struct ast_and_or { +struct ast_and_or +{ struct ast *left; struct ast *right; enum ast_and_or_type type; @@ -17,7 +20,8 @@ struct ast_and_or { bool ast_is_and_or(struct ast *node); struct ast_and_or *ast_get_and_or(struct ast *node); -struct ast *ast_create_and_or(struct ast *left, struct ast *right, enum ast_and_or_type type); +struct ast *ast_create_and_or(struct ast *left, struct ast *right, + enum ast_and_or_type type); void ast_free_and_or(struct ast_and_or *and_or); #endif /* ! AST_AND_OR_H */ diff --git a/src/utils/ast/ast_command.c b/src/utils/ast/ast_command.c index 920b1ff..89ed379 100644 --- a/src/utils/ast/ast_command.c +++ b/src/utils/ast/ast_command.c @@ -1,8 +1,8 @@ #include "utils/ast/ast_command.h" -#include #include #include +#include #include "utils/lists/lists.h" diff --git a/src/utils/ast/ast_command.h b/src/utils/ast/ast_command.h index 08c62ba..b83bade 100644 --- a/src/utils/ast/ast_command.h +++ b/src/utils/ast/ast_command.h @@ -3,8 +3,8 @@ #include -#include "utils/lists/lists.h" #include "utils/ast/ast_base.h" +#include "utils/lists/lists.h" struct ast_command { diff --git a/src/utils/ast/ast_end.c b/src/utils/ast/ast_end.c index 3be1eeb..a74fdb3 100644 --- a/src/utils/ast/ast_end.c +++ b/src/utils/ast/ast_end.c @@ -1,8 +1,8 @@ #include "utils/ast/ast_end.h" -#include #include #include +#include bool ast_is_end(struct ast *node) { diff --git a/src/utils/ast/ast_end.h b/src/utils/ast/ast_end.h index f86e477..df24d8b 100644 --- a/src/utils/ast/ast_end.h +++ b/src/utils/ast/ast_end.h @@ -3,8 +3,8 @@ #include -#include "utils/lists/lists.h" #include "utils/ast/ast_base.h" +#include "utils/lists/lists.h" /** * Checks if the given AST node is of type AST_END. diff --git a/src/utils/ast/ast_if.c b/src/utils/ast/ast_if.c index 6a25a9c..400a390 100644 --- a/src/utils/ast/ast_if.c +++ b/src/utils/ast/ast_if.c @@ -1,8 +1,8 @@ #include "utils/ast/ast_if.h" -#include #include #include +#include struct ast *ast_create_if(struct ast *condition, struct ast *then_clause, struct ast *else_clause) diff --git a/src/utils/ast/ast_list.c b/src/utils/ast/ast_list.c index 4fc87f5..0455698 100644 --- a/src/utils/ast/ast_list.c +++ b/src/utils/ast/ast_list.c @@ -1,7 +1,7 @@ -#include "utils/ast/ast.h" - #include +#include "utils/ast/ast.h" + struct ast *ast_create_list(struct list *list) { struct ast_list *ast_list = malloc(sizeof(struct ast_list)); @@ -16,7 +16,7 @@ struct ast *ast_create_list(struct list *list) struct ast_list *ast_get_list(struct ast *node) { assert(node != NULL); - return (struct ast_list*)node->data; + return (struct ast_list *)node->data; } bool ast_is_list(struct ast *node) diff --git a/src/utils/ast/ast_redir.c b/src/utils/ast/ast_redir.c index c5eec63..e4c92f3 100644 --- a/src/utils/ast/ast_redir.c +++ b/src/utils/ast/ast_redir.c @@ -1,4 +1,5 @@ #include "utils/ast/ast_redir.h" + #include bool ast_is_redir(struct ast *node) @@ -13,13 +14,16 @@ struct ast_redir *ast_get_redir(struct ast *node) return NULL; } -struct ast *ast_create_redir(struct ast *child, char *filename, int io_number, enum ast_redir_type type) +struct ast *ast_create_redir(struct ast *child, char *filename, int io_number, + enum ast_redir_type type) { struct ast_redir *redir = malloc(sizeof(struct ast_redir)); if (!redir) return NULL; redir->child = child; - redir->filename = filename; // Takes ownership? Usually yes in simple ASTs, or dup. Let's assume pointer copy for now, but user must manage memory. + redir->filename = + filename; // Takes ownership? Usually yes in simple ASTs, or dup. Let's + // assume pointer copy for now, but user must manage memory. redir->io_number = io_number; redir->type = type; diff --git a/src/utils/ast/ast_redir.h b/src/utils/ast/ast_redir.h index 5f5ffb5..65be4a2 100644 --- a/src/utils/ast/ast_redir.h +++ b/src/utils/ast/ast_redir.h @@ -2,28 +2,33 @@ #define AST_REDIR_H #include + #include "utils/ast/ast_base.h" -enum ast_redir_type { - AST_REDIR_TYPE_LESS, // < - AST_REDIR_TYPE_GREAT, // > - AST_REDIR_TYPE_DLESS, // << - AST_REDIR_TYPE_DGREAT, // >> - AST_REDIR_TYPE_LESSAND, // <& - AST_REDIR_TYPE_GREATAND, // >& - AST_REDIR_TYPE_CLOBBER // >| +enum ast_redir_type +{ + AST_REDIR_TYPE_LESS, // < + AST_REDIR_TYPE_GREAT, // > + AST_REDIR_TYPE_DLESS, // << + AST_REDIR_TYPE_DGREAT, // >> + AST_REDIR_TYPE_LESSAND, // <& + AST_REDIR_TYPE_GREATAND, // >& + AST_REDIR_TYPE_CLOBBER // >| }; -struct ast_redir { +struct ast_redir +{ struct ast *child; char *filename; - int io_number; // The FD being redirected (default -1 if not specified, implies 0 or 1 based on type) + int io_number; // The FD being redirected (default -1 if not specified, + // implies 0 or 1 based on type) enum ast_redir_type type; }; bool ast_is_redir(struct ast *node); struct ast_redir *ast_get_redir(struct ast *node); -struct ast *ast_create_redir(struct ast *child, char *filename, int io_number, enum ast_redir_type type); +struct ast *ast_create_redir(struct ast *child, char *filename, int io_number, + enum ast_redir_type type); void ast_free_redir(struct ast_redir *redir); #endif /* ! AST_REDIR_H */ diff --git a/src/utils/ast/ast_void.c b/src/utils/ast/ast_void.c index 1396121..3368c7d 100644 --- a/src/utils/ast/ast_void.c +++ b/src/utils/ast/ast_void.c @@ -1,8 +1,8 @@ #include "utils/ast/ast_void.h" -#include #include #include +#include bool ast_is_void(struct ast *node) { diff --git a/src/utils/ast/ast_void.h b/src/utils/ast/ast_void.h index 866a8d8..6abaef8 100644 --- a/src/utils/ast/ast_void.h +++ b/src/utils/ast/ast_void.h @@ -3,8 +3,8 @@ #include -#include "utils/lists/lists.h" #include "utils/ast/ast_base.h" +#include "utils/lists/lists.h" /** * Checks if the given AST node is of type AST_VOID. diff --git a/tests/unit/lexer/lexer_tests.c b/tests/unit/lexer/lexer_tests.c index 910a81a..7cb84a5 100644 --- a/tests/unit/lexer/lexer_tests.c +++ b/tests/unit/lexer/lexer_tests.c @@ -5,8 +5,8 @@ #include #include -#include "lexer/lexer.h" #include "io_backend/io_backend.h" +#include "lexer/lexer.h" TestSuite(peek_token); @@ -14,11 +14,7 @@ Test(peek_token, basic_empty) { // simulates input char command[] = ""; - struct iob_context context = - { - IOB_MODE_CMD, - command - }; + struct iob_context context = { IOB_MODE_CMD, command }; iob_init(&context); // test @@ -38,11 +34,7 @@ Test(peek_token, basic_word) { // simulates input char command[] = "hello"; - struct iob_context context = - { - IOB_MODE_CMD, - command - }; + struct iob_context context = { IOB_MODE_CMD, command }; iob_init(&context); // test @@ -60,11 +52,7 @@ Test(peek_token, basic_words) { // simulates input char command[] = "echo hello there"; - struct iob_context context = - { - IOB_MODE_CMD, - command - }; + struct iob_context context = { IOB_MODE_CMD, command }; iob_init(&context); // ======= echo