From 00d4cf45acf360cb1898028349dd95868199fa21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Cadoul?= Date: Tue, 22 May 2018 16:36:27 +0200 Subject: [PATCH 1/7] ADD [scripting] : check script file --- Makefile | 5 ++ include/script.h | 21 +++++++ include/shell.h | 2 +- src/check_args.c | 7 ++- src/main.c | 6 +- src/scripting/check_script.c | 82 +++++++++++++++++++++++++++ src/scripting/open_script.c | 25 ++++++++ tests/scripting/script_access_test.c | 39 +++++++++++++ tests/scripting/script_exec.sh | 3 + tests/scripting/script_name_test.c | 19 +++++++ tests/scripting/script_shebang.sh | 3 + tests/scripting/script_shebang_test.c | 22 +++++++ tests/scripting/script_test.sh | 3 + tests/shell/check_args_test.c | 8 +-- 14 files changed, 238 insertions(+), 7 deletions(-) create mode 100644 include/script.h create mode 100644 src/scripting/check_script.c create mode 100644 src/scripting/open_script.c create mode 100644 tests/scripting/script_access_test.c create mode 100644 tests/scripting/script_exec.sh create mode 100644 tests/scripting/script_name_test.c create mode 100755 tests/scripting/script_shebang.sh create mode 100644 tests/scripting/script_shebang_test.c create mode 100755 tests/scripting/script_test.sh diff --git a/Makefile b/Makefile index 1ef1155..c66e0a3 100644 --- a/Makefile +++ b/Makefile @@ -92,6 +92,8 @@ SRCS = $(PATH_SRC)/check_args.c \ $(PATH_SRC)/shell_loop/execution/display_error_instruction.c \ $(PATH_SRC)/shell_loop/execution/redirect_stdin_double.c \ $(PATH_SRC)/shell_loop/execution/condition_instruction.c \ + $(PATH_SRC)/scripting/check_script.c \ + $(PATH_SRC)/scripting/open_script.c \ SRC_MAIN = $(PATH_SRC)/main.c @@ -135,6 +137,9 @@ SRCS_TEST = $(PATH_TEST)/shell/check_args_test.c \ $(PATH_TEST)/execution/env_built_test.c \ $(PATH_TEST)/execution/roll_back_path_test.c \ $(PATH_TEST)/execution/alias_built_test.c \ + $(PATH_TEST)/scripting/script_name_test.c \ + $(PATH_TEST)/scripting/script_access_test.c \ + $(PATH_TEST)/scripting/script_shebang_test.c \ ## ---- FLAGS ---- ## diff --git a/include/script.h b/include/script.h new file mode 100644 index 0000000..b01945c --- /dev/null +++ b/include/script.h @@ -0,0 +1,21 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Include file of the scripting functions +*/ + +#ifndef SCRIPTING_H +#define SCRIPTING_H + +#include +#include + +#define SH_CHAR(c) (c == '.' || c == 's' || c == 'h') + +bool check_script(char *); +bool check_script_access(char *); +bool check_script_name(char *); +bool check_script_shebang(char *); + +#endif /* !CRIPTING_H */ diff --git a/include/shell.h b/include/shell.h index 1882d6a..d914bc0 100644 --- a/include/shell.h +++ b/include/shell.h @@ -44,7 +44,7 @@ typedef struct shell_s { char **paths; } shell_t; -int check_args(int); +int check_args(int, char **); char **copy_environement(char **); shell_t *initialisation_shell(int, char **, char **); char **copy_environement(char **); diff --git a/src/check_args.c b/src/check_args.c index 44f3531..3a27e58 100644 --- a/src/check_args.c +++ b/src/check_args.c @@ -7,12 +7,17 @@ #include "shell.h" #include "mylib.h" +#include "script.h" -int check_args(int argc) +int check_args(int argc, char **argv) { if (argc != 1 && argc != 2) { my_putstr("You must give 0 arguments to the program.\n"); return (FAILURE); } + if (argc == 2 && argv[1] && !check_script(argv[1])) { + my_putstr("The given argument must a valid script\n"); + return (FAILURE); + } return (SUCCESS); } diff --git a/src/main.c b/src/main.c index e0cacaf..0d2d577 100644 --- a/src/main.c +++ b/src/main.c @@ -12,7 +12,7 @@ int main(int argc, char **argv, char **env) { shell_t *shell = NULL; - if (check_args(argc) == FAILURE) + if (check_args(argc, argv) == FAILURE) return (FAILURE); shell = initialisation_shell(argc, argv, env); if (shell == NULL) @@ -21,3 +21,7 @@ int main(int argc, char **argv, char **env) return (FAILURE); return (destroy_shell(shell)); } +// int main(int argc, char **argv, char **env) +// { +// check_args(argc, argv); +// } diff --git a/src/scripting/check_script.c b/src/scripting/check_script.c new file mode 100644 index 0000000..30dd130 --- /dev/null +++ b/src/scripting/check_script.c @@ -0,0 +1,82 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Check script file +*/ + +#include "script.h" +#include +#include +#include + +bool check_script_shebang(char *path) +{ + FILE *fd = fopen(path, "r"); + size_t n = 0; + char *buf = NULL; + + if (!fd) + return (false); + if (getline(&buf, &n, fd) == -1) { + fclose(fd); + return (false); + } + if (buf && !strncmp(buf, "#!", 2)) { + free(buf); + fclose(fd); + return (true); + } + if (buf) + free(buf); + fclose(fd); + return (false); +} + +bool check_script_name(char *path) +{ + char *tmp = malloc(sizeof(*tmp) * (strlen(path) + 1)); + int j = 0; + + if (!tmp) + return (false); + for (int i = strlen(path) - 1; SH_CHAR(path[i]); i -= 1) { + tmp[j] = path[i]; + j += 1; + } + tmp[j] = '\0'; + if (!strcmp(tmp, "hs.")) { + free(tmp); + return (true); + } + free(tmp); + return (false); +} + +bool check_script_access(char *path) +{ + if (access(path, R_OK) == -1) { + write(1, path, strlen(path)); + write(1, ": Command not found.\n", 21); + return (false); + } + else if (access(path, X_OK) == -1) { + write(1, path, strlen(path)); + write(1, ": Permission denied.\n", 21); + return (false); + } + return (true); +} + +bool check_script(char *path) +{ + if (!path) + return (false); + if (!check_script_name(path)) + return (false); + if (!check_script_access(path)) + return (false); + if (!check_script_shebang(path)) + return (false); + return (true); +} diff --git a/src/scripting/open_script.c b/src/scripting/open_script.c new file mode 100644 index 0000000..9ea202d --- /dev/null +++ b/src/scripting/open_script.c @@ -0,0 +1,25 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Open script file +*/ + +#include "script.h" +#include "shell.h" +#include + +bool run_script(char *path) +{ + FILE *fd = fopen(path, "r"); + + if (!fd) + return (false); + fclose(fd); + return (true); +} + +void redirect_script(shell_t *shell, FILE *fd) +{ + +} diff --git a/tests/scripting/script_access_test.c b/tests/scripting/script_access_test.c new file mode 100644 index 0000000..1685314 --- /dev/null +++ b/tests/scripting/script_access_test.c @@ -0,0 +1,39 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Unit tests on script file +*/ + +#include +#include +#include "script.h" + +static void redirect_all_std(void) +{ + cr_redirect_stdout(); + cr_redirect_stderr(); +} + +Test(script_access, access_ok) +{ + bool status = check_script_access("./tests/scripting/script_test.sh"); + cr_assert_eq(status, true); +} + +Test(script_access, access_exist_ko, .init = redirect_all_std) +{ + bool status = check_script_access("./script.sh"); + + cr_assert_eq(status, false); + cr_assert_stdout_eq_str("./script.sh: Command not found.\n"); +} + +Test(script_access, access_exec_ko, .init = redirect_all_std) +{ + bool status = check_script_access("./tests/scripting/script_exec.sh"); + + cr_assert_eq(status, false); + cr_assert_stdout_eq_str("./tests/scripting/script_exec.sh:\ + Permission denied.\n"); +} diff --git a/tests/scripting/script_exec.sh b/tests/scripting/script_exec.sh new file mode 100644 index 0000000..54eee0e --- /dev/null +++ b/tests/scripting/script_exec.sh @@ -0,0 +1,3 @@ +#!./42sh + +ls diff --git a/tests/scripting/script_name_test.c b/tests/scripting/script_name_test.c new file mode 100644 index 0000000..8641670 --- /dev/null +++ b/tests/scripting/script_name_test.c @@ -0,0 +1,19 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Unit tests on script file +*/ + +#include +#include "script.h" + +Test(script_name, name_ok) +{ + cr_assert_eq(check_script_name("./script_test.sh"), true); +} + +Test(script_name, name_ko) +{ + cr_assert_eq(check_script_name("toto"), false); +} diff --git a/tests/scripting/script_shebang.sh b/tests/scripting/script_shebang.sh new file mode 100755 index 0000000..6fd961c --- /dev/null +++ b/tests/scripting/script_shebang.sh @@ -0,0 +1,3 @@ +!#./42sh + +echo toto diff --git a/tests/scripting/script_shebang_test.c b/tests/scripting/script_shebang_test.c new file mode 100644 index 0000000..d8c8b99 --- /dev/null +++ b/tests/scripting/script_shebang_test.c @@ -0,0 +1,22 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Unit tests on script shebang +*/ + +#include +#include "script.h" + +Test(script_shebang, shebang_ok) +{ + bool status = check_script_shebang("./tests/scripting/script_test.sh"); + cr_assert_eq(status, true); +} + +Test(script_shebang, shebang_ko) +{ + bool status = check_script_shebang("./tests/scripting/\ +script_shebang.sh"); + cr_assert_eq(status, false); +} diff --git a/tests/scripting/script_test.sh b/tests/scripting/script_test.sh new file mode 100755 index 0000000..ff52846 --- /dev/null +++ b/tests/scripting/script_test.sh @@ -0,0 +1,3 @@ +#!./42sh + +echo toto diff --git a/tests/shell/check_args_test.c b/tests/shell/check_args_test.c index a9c6f3c..cfb15d0 100644 --- a/tests/shell/check_args_test.c +++ b/tests/shell/check_args_test.c @@ -11,24 +11,24 @@ Test(check_args_1, valid_args) { - cr_assert_eq(check_args(1), SUCCESS); + cr_assert_eq(check_args(1, NULL), SUCCESS); } Test(check_args_2, not_valid_args) { cr_redirect_stdout(); - cr_assert_eq(check_args(8), FAILURE); + cr_assert_eq(check_args(8, NULL), FAILURE); cr_assert_stdout_eq_str("You must give 0 arguments to the program.\n"); } Test(check_args_3, negative_number_args) { cr_redirect_stdout(); - cr_assert_eq(check_args(0), FAILURE); + cr_assert_eq(check_args(0, NULL), FAILURE); cr_assert_stdout_eq_str("You must give 0 arguments to the program.\n"); } Test(check_args_4, valid_args) { - cr_assert_eq(check_args(2), SUCCESS); + cr_assert_eq(check_args(2, NULL), SUCCESS); } From 1c7c1c03e051e556319416786014fc70c57caefb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Cadoul?= Date: Tue, 22 May 2018 17:46:34 +0200 Subject: [PATCH 2/7] ADD [scripting] : run_script function in shell_loop --- Makefile | 1 + include/script.h | 4 ++++ include/shell.h | 3 ++- src/check_args.c | 2 +- src/main.c | 5 ++++- src/scripting/check_script.c | 1 - src/scripting/open_script.c | 20 +++++++------------- src/scripting/run_script.c | 21 +++++++++++++++++++++ src/shell_loop/shell_loop.c | 18 ++++++++++++++++-- tests/shell/check_args_test.c | 2 +- 10 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 src/scripting/run_script.c diff --git a/Makefile b/Makefile index c66e0a3..e83a739 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,7 @@ SRCS = $(PATH_SRC)/check_args.c \ $(PATH_SRC)/shell_loop/execution/condition_instruction.c \ $(PATH_SRC)/scripting/check_script.c \ $(PATH_SRC)/scripting/open_script.c \ + $(PATH_SRC)/scripting/run_script.c \ SRC_MAIN = $(PATH_SRC)/main.c diff --git a/include/script.h b/include/script.h index b01945c..43a35dd 100644 --- a/include/script.h +++ b/include/script.h @@ -10,6 +10,8 @@ #include #include +#include +#include "shell.h" #define SH_CHAR(c) (c == '.' || c == 's' || c == 'h') @@ -17,5 +19,7 @@ bool check_script(char *); bool check_script_access(char *); bool check_script_name(char *); bool check_script_shebang(char *); +char *run_script(shell_t *, FILE *); +FILE *open_script(char *); #endif /* !CRIPTING_H */ diff --git a/include/shell.h b/include/shell.h index d914bc0..c124e90 100644 --- a/include/shell.h +++ b/include/shell.h @@ -42,6 +42,7 @@ typedef struct shell_s { int code; bool bonus; char **paths; + bool script; } shell_t; int check_args(int, char **); @@ -49,7 +50,7 @@ char **copy_environement(char **); shell_t *initialisation_shell(int, char **, char **); char **copy_environement(char **); backup_t *initialisation_backup(char **); -unsigned int shell_loop(shell_t *); +unsigned int shell_loop(shell_t *, FILE *); unsigned int redirect_loop(shell_t *, char *); int display_prompt(shell_t *shell); void free_array_string(char **); diff --git a/src/check_args.c b/src/check_args.c index 3a27e58..1abb2b1 100644 --- a/src/check_args.c +++ b/src/check_args.c @@ -16,7 +16,7 @@ int check_args(int argc, char **argv) return (FAILURE); } if (argc == 2 && argv[1] && !check_script(argv[1])) { - my_putstr("The given argument must a valid script\n"); + my_putstr("The given argument must be a valid script\n"); return (FAILURE); } return (SUCCESS); diff --git a/src/main.c b/src/main.c index 0d2d577..97283c6 100644 --- a/src/main.c +++ b/src/main.c @@ -7,17 +7,20 @@ #include #include "shell.h" +#include "script.h" int main(int argc, char **argv, char **env) { shell_t *shell = NULL; + FILE *fd = NULL; if (check_args(argc, argv) == FAILURE) return (FAILURE); + fd = open_script(argv[1]); shell = initialisation_shell(argc, argv, env); if (shell == NULL) return (FAILURE); - if (shell_loop(shell) == FAILURE) + if (shell_loop(shell, fd) == FAILURE) return (FAILURE); return (destroy_shell(shell)); } diff --git a/src/scripting/check_script.c b/src/scripting/check_script.c index 30dd130..46b2d88 100644 --- a/src/scripting/check_script.c +++ b/src/scripting/check_script.c @@ -8,7 +8,6 @@ #include "script.h" #include #include -#include bool check_script_shebang(char *path) { diff --git a/src/scripting/open_script.c b/src/scripting/open_script.c index 9ea202d..8ec52d8 100644 --- a/src/scripting/open_script.c +++ b/src/scripting/open_script.c @@ -6,20 +6,14 @@ */ #include "script.h" -#include "shell.h" -#include -bool run_script(char *path) -{ - FILE *fd = fopen(path, "r"); - - if (!fd) - return (false); - fclose(fd); - return (true); -} - -void redirect_script(shell_t *shell, FILE *fd) +FILE *open_script(char *path) { + FILE *fd = NULL; + if (!path) + return (NULL); + if (!(fd = fopen(path, "r"))) + return (NULL); + return (fd); } diff --git a/src/scripting/run_script.c b/src/scripting/run_script.c new file mode 100644 index 0000000..1a41dfd --- /dev/null +++ b/src/scripting/run_script.c @@ -0,0 +1,21 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Run script +*/ + +#include "script.h" + +char *run_script(shell_t *shell, FILE *fd) +{ + char *line = NULL; + size_t n = 0; + + if (getline(&line, &n, fd) == -1) { + shell->script = false; + fclose(fd); + return (NULL); + } + return (line); +} diff --git a/src/shell_loop/shell_loop.c b/src/shell_loop/shell_loop.c index 57118f4..3c7b8bd 100644 --- a/src/shell_loop/shell_loop.c +++ b/src/shell_loop/shell_loop.c @@ -8,6 +8,7 @@ #include #include "shell.h" #include "mylib.h" +#include "script.h" #include "execution.h" bool is_empty_input(char *user_input) @@ -37,12 +38,25 @@ unsigned int redirect_loop(shell_t *shell, char *user_input) return (SUCCESS); } -unsigned int shell_loop(shell_t *shell) +char *redirect_script(shell_t *shell, FILE *fd) +{ + char *line = NULL; + size_t n = 0; + + if (!fd) + return (line); + if (shell->script) + if ((line = run_script(shell, fd))) + return (line); + return (line = get_next_line(0)); +} + +unsigned int shell_loop(shell_t *shell, FILE *fd) { char *user_input = NULL; while (shell->state == OK && display_prompt(shell) && - (user_input = get_next_line(0)) != NULL) { + (user_input = redirect_script(shell, fd)) != NULL) { if (redirect_loop(shell, user_input) == FAILURE) return (FAILURE); } diff --git a/tests/shell/check_args_test.c b/tests/shell/check_args_test.c index cfb15d0..4d398cf 100644 --- a/tests/shell/check_args_test.c +++ b/tests/shell/check_args_test.c @@ -30,5 +30,5 @@ Test(check_args_3, negative_number_args) Test(check_args_4, valid_args) { - cr_assert_eq(check_args(2, NULL), SUCCESS); + cr_assert_eq(check_args(2, NULL), FAILURE); } From e534fb22c25914a89614716646ba586da138268a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Cadoul?= Date: Wed, 23 May 2018 14:28:52 +0200 Subject: [PATCH 3/7] ADD [scripting] : condition structure filling and unit test --- Makefile | 7 ++ include/script.h | 33 ++++++- include/shell.h | 2 +- script.sh | 6 ++ src/check_args.c | 2 +- .../initialisation_shell.c | 1 + src/main.c | 2 +- src/scripting/fill_condition_script.c | 96 +++++++++++++++++++ src/scripting/init_condition_script.c | 32 +++++++ src/scripting/keywords_script.c | 52 ++++++++++ src/scripting/open_script.c | 3 +- src/scripting/run_script.c | 12 +++ src/shell_loop/free_array_string.c | 2 + tests/scripting/script_access_test.c | 4 +- tests/scripting/script_fill_cond_test.c | 54 +++++++++++ tests/scripting/script_if_keyword_test.c | 74 ++++++++++++++ tests/scripting/script_no_keyword_test.c | 22 +++++ tests/scripting/script_other_keyword_test.c | 74 ++++++++++++++ tests/shell/check_args_test.c | 5 - 19 files changed, 471 insertions(+), 12 deletions(-) create mode 100755 script.sh create mode 100644 src/scripting/fill_condition_script.c create mode 100644 src/scripting/init_condition_script.c create mode 100644 src/scripting/keywords_script.c create mode 100644 tests/scripting/script_fill_cond_test.c create mode 100644 tests/scripting/script_if_keyword_test.c create mode 100644 tests/scripting/script_no_keyword_test.c create mode 100644 tests/scripting/script_other_keyword_test.c diff --git a/Makefile b/Makefile index e83a739..a87791c 100644 --- a/Makefile +++ b/Makefile @@ -93,6 +93,9 @@ SRCS = $(PATH_SRC)/check_args.c \ $(PATH_SRC)/shell_loop/execution/redirect_stdin_double.c \ $(PATH_SRC)/shell_loop/execution/condition_instruction.c \ $(PATH_SRC)/scripting/check_script.c \ + $(PATH_SRC)/scripting/fill_condition_script.c \ + $(PATH_SRC)/scripting/init_condition_script.c \ + $(PATH_SRC)/scripting/keywords_script.c \ $(PATH_SRC)/scripting/open_script.c \ $(PATH_SRC)/scripting/run_script.c \ @@ -141,6 +144,10 @@ SRCS_TEST = $(PATH_TEST)/shell/check_args_test.c \ $(PATH_TEST)/scripting/script_name_test.c \ $(PATH_TEST)/scripting/script_access_test.c \ $(PATH_TEST)/scripting/script_shebang_test.c \ + $(PATH_TEST)/scripting/script_fill_cond_test.c \ + $(PATH_TEST)/scripting/script_if_keyword_test.c \ + $(PATH_TEST)/scripting/script_no_keyword_test.c \ + $(PATH_TEST)/scripting/script_other_keyword_test.c \ ## ---- FLAGS ---- ## diff --git a/include/script.h b/include/script.h index 43a35dd..34fdc81 100644 --- a/include/script.h +++ b/include/script.h @@ -14,12 +14,43 @@ #include "shell.h" #define SH_CHAR(c) (c == '.' || c == 's' || c == 'h') +#define NB_COND (6) +/* -- Structures definition --- */ +typedef enum keyword_e { + EMPTY, + IF, + ELSE, + ELSIF, + WHILE, + FOREACH, + WHICH, + WHERE +} keyword_t; + +typedef struct cond_script_s { + keyword_t key; + char *condition; + char *command; + bool end; +} cond_t; + +/* --- Check script file --- */ bool check_script(char *); bool check_script_access(char *); bool check_script_name(char *); bool check_script_shebang(char *); + +/* --- Script running --- */ char *run_script(shell_t *, FILE *); -FILE *open_script(char *); +FILE *open_script(char *, shell_t *); +bool fill_cond(cond_t *, char *, char **); +int search_keyword(cond_t *, char *); + +/* --- Initialization --- */ +cond_t *init_conditional_line(void); + +/* -- Resources destruction --- */ +void free_cond_line(cond_t *); #endif /* !CRIPTING_H */ diff --git a/include/shell.h b/include/shell.h index c124e90..38d49a9 100644 --- a/include/shell.h +++ b/include/shell.h @@ -41,8 +41,8 @@ typedef struct shell_s { state_t state; int code; bool bonus; - char **paths; bool script; + char **paths; } shell_t; int check_args(int, char **); diff --git a/script.sh b/script.sh new file mode 100755 index 0000000..9da9c14 --- /dev/null +++ b/script.sh @@ -0,0 +1,6 @@ +#!/bin/tcsh + +set toto = 2 + +while ($toto < 10) echo toto +@ toto = $toto + 1 diff --git a/src/check_args.c b/src/check_args.c index 1abb2b1..7827915 100644 --- a/src/check_args.c +++ b/src/check_args.c @@ -15,7 +15,7 @@ int check_args(int argc, char **argv) my_putstr("You must give 0 arguments to the program.\n"); return (FAILURE); } - if (argc == 2 && argv[1] && !check_script(argv[1])) { + if (argc == 2 && !check_script(argv[1])) { my_putstr("The given argument must be a valid script\n"); return (FAILURE); } diff --git a/src/initialisation_shell/initialisation_shell.c b/src/initialisation_shell/initialisation_shell.c index 9d24e3a..051d5d3 100644 --- a/src/initialisation_shell/initialisation_shell.c +++ b/src/initialisation_shell/initialisation_shell.c @@ -24,6 +24,7 @@ shell_t *initialisation_shell(int argc, char **argv, char **env) return (NULL); shell->bonus = true; shell->backup = initialisation_backup(shell->env); + shell->script = false; shell->command_line = NULL; shell->code = 0; shell->state = OK; diff --git a/src/main.c b/src/main.c index 97283c6..21c049f 100644 --- a/src/main.c +++ b/src/main.c @@ -16,10 +16,10 @@ int main(int argc, char **argv, char **env) if (check_args(argc, argv) == FAILURE) return (FAILURE); - fd = open_script(argv[1]); shell = initialisation_shell(argc, argv, env); if (shell == NULL) return (FAILURE); + fd = open_script(argv[1], shell); if (shell_loop(shell, fd) == FAILURE) return (FAILURE); return (destroy_shell(shell)); diff --git a/src/scripting/fill_condition_script.c b/src/scripting/fill_condition_script.c new file mode 100644 index 0000000..c7eca56 --- /dev/null +++ b/src/scripting/fill_condition_script.c @@ -0,0 +1,96 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Conditional structure initialization +*/ + +#include "script.h" + +static bool copy_command(cond_t *cond, char *line) +{ + int start = 0; + + for (int i = 0; line[i] != '\0'; i += 1) + if (line[i] == ')') + start = i; + if (line[start + 1] == '\0') { + if (cond->key == IF || cond->key == ELSIF) { + puts("if: Empty if."); + return (false); + } + else if (cond->key == ELSE) + return (true); + } + cond->command = malloc(sizeof(char) * (strlen(line) - start)); + if (!cond->command) + return (false); + for (int i = start + 1, j = 0; line[i] != '\0'; i += 1, j += 1) + cond->command[j] = line[i]; + cond->command[strlen(line) - start - 1] = '\0'; + return (true); +} + +static bool search_then(cond_t *cond, char *line, char **words_array) +{ + bool then_exist = false; + + for (int i = 0; words_array[i]; i += 1) + if (!strcmp(words_array[i], "then")) + then_exist = true; + if (!then_exist && cond->key != ELSE) + cond->end = true; + if (!then_exist || cond->key == ELSE) + if (copy_command(cond, line) != true) + return (false); + return (true); +} + +static bool copy_condition(cond_t *cond, char *line, int start, int end) +{ + char **words_array = cut_line(line); + + cond->condition = malloc(sizeof(char) * (end - start)); + if (!cond->condition || !words_array) + return (false); + for (int i = start + 1, j = 0;i < end; i += 1, j += 1) + cond->condition[j] = line[i]; + cond->condition[end - start - 1] = '\0'; + if (cond->key != IF && cond->key != ELSIF && cond->key != ELSE) + if (line[end + 1] != '\0') { + my_putstr(words_array[0]); + puts(": Expression Syntax."); + free_array_string(words_array); + return (false); + } + free_array_string(words_array); + return (true); +} + +static bool check_condition(cond_t *cond, char *line) +{ + int open_bracket = 0; + int close_bracket = 0; + + for (int i = 0; line[i] != '\0'; i += 1) { + if (line[i] == '(') + open_bracket = i; + else if (line[i] == ')') + close_bracket = i; + } + if (!open_bracket || !close_bracket) + return (false); + if (copy_condition(cond, line, open_bracket, close_bracket) != true) + return (false); + return (true); +} + +bool fill_cond(cond_t *cond, char *line, char **words_array) +{ + if (check_condition(cond, line) != true) + return (false); + if (cond->key == IF || cond->key == ELSIF || cond->key == ELSE) + if (search_then(cond, line, words_array) != true) + return (false); + return (true); +} diff --git a/src/scripting/init_condition_script.c b/src/scripting/init_condition_script.c new file mode 100644 index 0000000..1b9f8e2 --- /dev/null +++ b/src/scripting/init_condition_script.c @@ -0,0 +1,32 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Conditional structure initialization +*/ + +#include "script.h" + +cond_t *init_conditional_line(void) +{ + cond_t *line = malloc(sizeof(*line)); + + if (!line) + return (NULL); + line->key = EMPTY; + line->condition = NULL; + line->command = NULL; + line->end = false; + return (line); +} + +void free_cond_line(cond_t *line) +{ + if (!line) + return; + if (line->condition) + free(line->condition); + if (line->command) + free(line->command); + free(line); +} diff --git a/src/scripting/keywords_script.c b/src/scripting/keywords_script.c new file mode 100644 index 0000000..a10bcd8 --- /dev/null +++ b/src/scripting/keywords_script.c @@ -0,0 +1,52 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Search key words in script file +*/ + +#include "script.h" +#include + +static void search_elsif(cond_t *cond, char **words_array) +{ + if (!words_array[0] || !words_array[1]) + return; + if (!strcmp(words_array[0], "else") && !strcmp(words_array[1], "if")) + cond->key = ELSIF; +} + +static bool keyword_exist(cond_t *cond, char **words_array) +{ + cond_t cond_array[NB_COND] = {{IF, "if", NULL, false}, + {ELSE, "else", NULL, false}, {WHILE, "while", NULL, false}, + {FOREACH, "foreach", NULL, false}, + {WHICH, "which", NULL, false}, {WHERE, "where", NULL, false}}; + + for (int i = 0; i < NB_COND; i += 1) + if (!strcmp(cond_array[i].condition, words_array[0])) + cond->key = cond_array[i].key; + if (cond->key == ELSE) + search_elsif(cond, words_array); + if (cond->key == EMPTY) + return (false); + return (true); +} + +int search_keyword(cond_t *cond_line, char *line) +{ + char **words_array = cut_line(line); + + if (!words_array) + return (FAILURE); + if (keyword_exist(cond_line, words_array) == false) { + free_array_string(words_array); + return (SKIP); + } + if (fill_cond(cond_line, line, words_array) != true) { + free_array_string(words_array); + return (FAILURE); + } + free_array_string(words_array); + return (SUCCESS); +} diff --git a/src/scripting/open_script.c b/src/scripting/open_script.c index 8ec52d8..32e4a05 100644 --- a/src/scripting/open_script.c +++ b/src/scripting/open_script.c @@ -7,7 +7,7 @@ #include "script.h" -FILE *open_script(char *path) +FILE *open_script(char *path, shell_t *shell) { FILE *fd = NULL; @@ -15,5 +15,6 @@ FILE *open_script(char *path) return (NULL); if (!(fd = fopen(path, "r"))) return (NULL); + shell->script = true; return (fd); } diff --git a/src/scripting/run_script.c b/src/scripting/run_script.c index 1a41dfd..1ac1d7b 100644 --- a/src/scripting/run_script.c +++ b/src/scripting/run_script.c @@ -11,11 +11,23 @@ char *run_script(shell_t *shell, FILE *fd) { char *line = NULL; size_t n = 0; + int status = 0; + static cond_t *cond_line = NULL; + if (!cond_line) + if (!(cond_line = init_conditional_line())) + return (NULL); if (getline(&line, &n, fd) == -1) { shell->script = false; fclose(fd); return (NULL); } + if ((status = search_keyword(cond_line, line)) == FAILURE) { + free_cond_line(cond_line); + return (NULL); + } + if (status == SKIP) + return (line); + // contidion mangement return (line); } diff --git a/src/shell_loop/free_array_string.c b/src/shell_loop/free_array_string.c index c047839..03ccf1d 100644 --- a/src/shell_loop/free_array_string.c +++ b/src/shell_loop/free_array_string.c @@ -9,6 +9,8 @@ void free_array_string(char **array) { + if (!array) + return; for (int i = 0; array[i]; i++) { free(array[i]); } diff --git a/tests/scripting/script_access_test.c b/tests/scripting/script_access_test.c index 1685314..a6784ab 100644 --- a/tests/scripting/script_access_test.c +++ b/tests/scripting/script_access_test.c @@ -23,10 +23,10 @@ Test(script_access, access_ok) Test(script_access, access_exist_ko, .init = redirect_all_std) { - bool status = check_script_access("./script.sh"); + bool status = check_script_access("./scripting.sh"); cr_assert_eq(status, false); - cr_assert_stdout_eq_str("./script.sh: Command not found.\n"); + cr_assert_stdout_eq_str("./scripting.sh: Command not found.\n"); } Test(script_access, access_exec_ko, .init = redirect_all_std) diff --git a/tests/scripting/script_fill_cond_test.c b/tests/scripting/script_fill_cond_test.c new file mode 100644 index 0000000..4ff4c2c --- /dev/null +++ b/tests/scripting/script_fill_cond_test.c @@ -0,0 +1,54 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Unit tests on condition structure filling +*/ + +#include +#include "script.h" + +Test(script_fill_cond, ok) +{ + cond_t *cond = init_conditional_line(); + char **words_array = cut_line("if ($1 == $2) then"); + bool status = false; + + cond->key = IF; + status = fill_cond(cond, "if ($1 == $2) then", words_array); + cr_assert_eq(status, true); + cr_assert_str_eq(cond->condition, "$1 == $2"); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, false); + free_cond_line(cond); + free_array_string(words_array); +} + +Test(script_fill_cond, ko_brackets) +{ + cond_t *cond = init_conditional_line(); + char **words_array = cut_line("if $1 == $2 echo toto"); + bool status = false; + + cond->key = IF; + status = fill_cond(cond, "if $1 == $2 echo toto", words_array); + cr_assert_eq(status, false); + free_cond_line(cond); + free_array_string(words_array); +} + +Test(script_fill_cond, ok_simple_if) +{ + cond_t *cond = init_conditional_line(); + char **words_array = cut_line("if ($1 == $2) echo toto"); + bool status = false; + + cond->key = IF; + status = fill_cond(cond, "if ($1 == $2) echo toto", words_array); + cr_assert_eq(status, true); + cr_assert_str_eq(cond->condition, "$1 == $2"); + cr_assert_str_eq(cond->command, " echo toto"); + cr_assert_eq(cond->end, true); + free_cond_line(cond); + free_array_string(words_array); +} diff --git a/tests/scripting/script_if_keyword_test.c b/tests/scripting/script_if_keyword_test.c new file mode 100644 index 0000000..806df5a --- /dev/null +++ b/tests/scripting/script_if_keyword_test.c @@ -0,0 +1,74 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Unit tests on keyword identification +*/ + +#include +#include "script.h" + +Test(script_keyword, if_then_ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "if ($1 == $2) then"); + + cr_assert_eq(status, SUCCESS); + cr_assert_eq(cond->key, IF); + cr_assert_str_eq(cond->condition, "$1 == $2"); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, false); + free_cond_line(cond); +} + +Test(script_keyword, if_ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "if ($1 == $2) echo toto"); + + cr_assert_eq(status, SUCCESS); + cr_assert_eq(cond->key, IF); + cr_assert_str_eq(cond->condition, "$1 == $2"); + cr_assert_str_eq(cond->command, " echo toto"); + cr_assert_eq(cond->end, true); + free_cond_line(cond); +} + +Test(script_keyword, elseif_ko) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "else if ($1 == $2)"); + + cr_assert_eq(status, FAILURE); + cr_assert_eq(cond->key, ELSIF); + cr_assert_str_eq(cond->condition, "$1 == $2"); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, true); + free_cond_line(cond); +} + +Test(script_keyword, elseif_ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "else if ($1 == $2) set a = 2"); + + cr_assert_eq(status, SUCCESS); + cr_assert_eq(cond->key, ELSIF); + cr_assert_str_eq(cond->condition, "$1 == $2"); + cr_assert_str_eq(cond->command, " set a = 2"); + cr_assert_eq(cond->end, true); + free_cond_line(cond); +} + +Test(script_keyword, else_ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "else ($1 == $2) set a = 3"); + + cr_assert_eq(status, SUCCESS); + cr_assert_eq(cond->key, ELSE); + cr_assert_str_eq(cond->condition, "$1 == $2"); + cr_assert_str_eq(cond->command, " set a = 3"); + cr_assert_eq(cond->end, false); + free_cond_line(cond); +} diff --git a/tests/scripting/script_no_keyword_test.c b/tests/scripting/script_no_keyword_test.c new file mode 100644 index 0000000..70850a6 --- /dev/null +++ b/tests/scripting/script_no_keyword_test.c @@ -0,0 +1,22 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Unit tests on keyword identification +*/ + +#include +#include "script.h" + +Test(script_no_keyword, ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "echo toto"); + + cr_assert_eq(status, SKIP); + cr_assert_eq(cond->key, EMPTY); + cr_assert_eq(cond->condition, NULL); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, false); + free_cond_line(cond); +} diff --git a/tests/scripting/script_other_keyword_test.c b/tests/scripting/script_other_keyword_test.c new file mode 100644 index 0000000..03d95ea --- /dev/null +++ b/tests/scripting/script_other_keyword_test.c @@ -0,0 +1,74 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Unit tests on keyword identification +*/ + +#include +#include "script.h" + +Test(script_other_keyword, while_ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "while (&toto < 10)"); + + cr_assert_eq(status, SUCCESS); + cr_assert_eq(cond->key, WHILE); + cr_assert_str_eq(cond->condition, "&toto < 10"); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, false); + free_cond_line(cond); +} + +Test(script_other_keyword, while_ko) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "while (&toto < 10) echo toto"); + + cr_assert_eq(status, FAILURE); + cr_assert_eq(cond->key, WHILE); + cr_assert_str_eq(cond->condition, "&toto < 10"); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, false); + free_cond_line(cond); +} + +Test(script_other_keyword, foreach_ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "foreach (&toto < 10)"); + + cr_assert_eq(status, SUCCESS); + cr_assert_eq(cond->key, FOREACH); + cr_assert_str_eq(cond->condition, "&toto < 10"); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, false); + free_cond_line(cond); +} + +Test(script_other_keyword, where_ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "where (&toto < 10)"); + + cr_assert_eq(status, SUCCESS); + cr_assert_eq(cond->key, WHERE); + cr_assert_str_eq(cond->condition, "&toto < 10"); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, false); + free_cond_line(cond); +} + +Test(script_other_keyword, which_ok) +{ + cond_t *cond = init_conditional_line(); + int status = search_keyword(cond, "which (&toto < 10)"); + + cr_assert_eq(status, SUCCESS); + cr_assert_eq(cond->key, WHICH); + cr_assert_str_eq(cond->condition, "&toto < 10"); + cr_assert_eq(cond->command, NULL); + cr_assert_eq(cond->end, false); + free_cond_line(cond); +} diff --git a/tests/shell/check_args_test.c b/tests/shell/check_args_test.c index 4d398cf..5c18a67 100644 --- a/tests/shell/check_args_test.c +++ b/tests/shell/check_args_test.c @@ -27,8 +27,3 @@ Test(check_args_3, negative_number_args) cr_assert_eq(check_args(0, NULL), FAILURE); cr_assert_stdout_eq_str("You must give 0 arguments to the program.\n"); } - -Test(check_args_4, valid_args) -{ - cr_assert_eq(check_args(2, NULL), FAILURE); -} From 1c572341930a7318ac2a4e973400f0648ddda139 Mon Sep 17 00:00:00 2001 From: Florent Poinsard Date: Thu, 24 May 2018 11:49:58 +0200 Subject: [PATCH 4/7] PATCH [line edition] : fixed bug in the line edition. --- Makefile | 1 + include/shell.h | 4 ++-- src/shell_loop/input/history_binding.c | 4 ++-- src/shell_loop/shell_loop.c | 19 +++++++++--------- src/shell_loop/write_command_history.c | 11 ++++++++--- tests/execution/history_builtin_test.c | 27 +++++++++----------------- tests/execution/setenv_crash_test.c | 4 ++-- tests/shell/write_history_test.c | 14 ++++++------- 8 files changed, 41 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index 87627f6..9fbea4c 100644 --- a/Makefile +++ b/Makefile @@ -122,6 +122,7 @@ SRCS_TEST = $(PATH_TEST)/shell/check_args_test.c \ $(PATH_TEST)/shell/get_input_test.c \ $(PATH_TEST)/shell/modify_input_auto_test.c \ $(PATH_TEST)/shell/get_alias_test.c \ + $(PATH_TEST)/shell/write_history_test.c \ $(PATH_TEST)/parsing/analyse_redirect_test.c \ $(PATH_TEST)/parsing/analyse_redirect_2_test.c \ $(PATH_TEST)/parsing/check_env_variable_test.c \ diff --git a/include/shell.h b/include/shell.h index 95ca7ee..383285b 100644 --- a/include/shell.h +++ b/include/shell.h @@ -80,7 +80,7 @@ int destroy_shell(shell_t *); int find_option_env(char **, char *); int find_separator_env(char *); unsigned int shell_loop(shell_t *); -unsigned int redirect_loop(shell_t *, char *); +unsigned int redirect_loop(shell_t *, char *, char *); char **init_local(void); /* --- basic init functions --- */ @@ -89,7 +89,7 @@ backup_t *initialisation_backup(char **); char **init_paths(char **); /* --- history function --- */ -void write_command_history(command_line_t *, char **); +void write_command_history(char *, char **); /* --- binding functions / redirection struct / macros --- */ binding_t *init_bindings(shell_t *shell); diff --git a/src/shell_loop/input/history_binding.c b/src/shell_loop/input/history_binding.c index 1189dcc..314b0e4 100644 --- a/src/shell_loop/input/history_binding.c +++ b/src/shell_loop/input/history_binding.c @@ -39,7 +39,7 @@ static char *up_history(shell_t *shell, char *input, int *i, int *hist_i) new = get_line_history(shell, *hist_i); if (new == NULL) return (input); - for (int i = 0; i < (int)strlen(input); i++) + for (int a = 0; a < *i; a++) my_putstr("\033[1D"); my_putstr(CLEAR_END_LINE); write(0, new, strlen(new)); @@ -56,7 +56,7 @@ static char *down_history(shell_t *shell, char *input, int *i, int *hist_i) new = get_line_history(shell, (*hist_i) - 1); if (new == NULL) return (input); - for (int i = 0; i < (int)strlen(input); i++) + for (int a = 0; a < *i; a++) my_putstr("\033[1D"); my_putstr(CLEAR_END_LINE); write(1, new, strlen(new)); diff --git a/src/shell_loop/shell_loop.c b/src/shell_loop/shell_loop.c index afe0611..90483c3 100644 --- a/src/shell_loop/shell_loop.c +++ b/src/shell_loop/shell_loop.c @@ -20,31 +20,32 @@ bool is_empty_input(char *user_input) return (false); } -unsigned int redirect_loop(shell_t *shell, char *user_input) +unsigned int redirect_loop(shell_t *shell, char *input, char *copy_input) { - if (is_empty_input(user_input) == true) { - user_input = apply_transformation(shell->bonus, user_input, + if (is_empty_input(input) == true && copy_input != NULL) { + input = apply_transformation(shell->bonus, input, shell->paths); shell->command_line = get_command_line(shell->bonus, - user_input, shell->env, shell->local); + input, shell->env, shell->local); if (shell->command_line == NULL) return (FAILURE); shell->code = execute_command(shell, shell->command_line); - write_command_history(shell->command_line, shell->paths); + write_command_history(copy_input, shell->paths); free_command(shell->command_line); update_backup(shell); - free(user_input); + free(input); + free(copy_input); } return (SUCCESS); } unsigned int shell_loop(shell_t *shell) { - char *user_input = NULL; + char *input = NULL; while (shell->state == OK && display_prompt(shell) && - (user_input = get_input(shell, 1, 0)) != NULL) { - if (redirect_loop(shell, user_input) == FAILURE) + (input = get_input(shell, 1, 0)) != NULL) { + if (redirect_loop(shell, input, strdup(input)) == FAILURE) return (FAILURE); } return (SUCCESS); diff --git a/src/shell_loop/write_command_history.c b/src/shell_loop/write_command_history.c index 4a431e6..8f01012 100644 --- a/src/shell_loop/write_command_history.c +++ b/src/shell_loop/write_command_history.c @@ -14,14 +14,19 @@ #include "shell.h" #include "instruction.h" -void write_command_history(command_line_t *cmd, char **paths) +void write_command_history(char *cmd, char **paths) { int fd = 0; + char *path = NULL; - fd = open(paths[1], O_WRONLY | O_CREAT | O_APPEND, + if (paths == NULL) + path = ".history42"; + else + path = paths[1]; + fd = open(path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (fd != -1) { - write(fd, cmd->full_command, strlen(cmd->full_command)); + write(fd, cmd, strlen(cmd)); write(fd, "\n", 1); close(fd); } diff --git a/tests/execution/history_builtin_test.c b/tests/execution/history_builtin_test.c index ca632f9..527abe8 100644 --- a/tests/execution/history_builtin_test.c +++ b/tests/execution/history_builtin_test.c @@ -40,8 +40,7 @@ Test(history_built, display_full_history) FILE *fp = NULL; close(open(shell->paths[1], O_RDONLY | O_TRUNC)); - write_command_history(get_command_line(true, "echo a > z", - shell->env, NULL), shell->paths); + write_command_history("echo a > z", shell->paths); shell->command_line = get_command_line(true, "history > buf", shell->env, NULL); execute_command(shell, shell->command_line); @@ -55,10 +54,8 @@ Test(history_built, display_full_history_2) FILE *fp = NULL; close(open(shell->paths[1], O_RDONLY | O_TRUNC)); - write_command_history(get_command_line(true, "echo a > z", - shell->env, NULL), shell->paths); - write_command_history(get_command_line(true, "vald", - shell->env, NULL), shell->paths); + write_command_history("echo a > z", shell->paths); + write_command_history("vald", shell->paths); shell->command_line = get_command_line(true, "history > buf2", shell->env, NULL); execute_command(shell, shell->command_line); @@ -72,12 +69,9 @@ Test(history_built, display_2) FILE *fp = NULL; close(open(shell->paths[1], O_RDONLY | O_TRUNC)); - write_command_history(get_command_line(true, "echo a > z", - shell->env, NULL), shell->paths); - write_command_history(get_command_line(true, "vald", - shell->env, NULL), shell->paths); - write_command_history(get_command_line(true, "valdgrind ; toto", - shell->env, NULL), shell->paths); + write_command_history("echo a > z", shell->paths); + write_command_history("vald", shell->paths); + write_command_history("valdgrind ; toto", shell->paths); shell->command_line = get_command_line(true, "history 2 > buf2", shell->env, NULL); execute_command(shell, shell->command_line); @@ -91,12 +85,9 @@ Test(history_built, display_too_big) FILE *fp = NULL; close(open(shell->paths[1], O_RDONLY | O_TRUNC)); - write_command_history(get_command_line(true, "echo a > z", - shell->env, NULL), shell->paths); - write_command_history(get_command_line(true, "vald", - shell->env, NULL), shell->paths); - write_command_history(get_command_line(true, "valdgrind ; toto", - shell->env, NULL), shell->paths); + write_command_history("echo a > z", shell->paths); + write_command_history("vald", shell->paths); + write_command_history("valdgrind ; toto", shell->paths); shell->command_line = get_command_line(true, "history 24 > buf2", shell->env, NULL); execute_command(shell, shell->command_line); diff --git a/tests/execution/setenv_crash_test.c b/tests/execution/setenv_crash_test.c index 64f9ba7..10f7ce0 100644 --- a/tests/execution/setenv_crash_test.c +++ b/tests/execution/setenv_crash_test.c @@ -31,7 +31,7 @@ Test(setenv_builtin, crash_test_1) env[1] = NULL; shell = initialisation_shell(1, NULL, env); for (int i = 0; i < 11; i++) - redirect_loop(shell, cmd[i]); + redirect_loop(shell, cmd[i], strdup(cmd[i])); } Test(setenv_builtin, crash_test_2) @@ -54,5 +54,5 @@ Test(setenv_builtin, crash_test_2) env[1] = NULL; shell = initialisation_shell(1, NULL, env); for (int i = 0; i < 14; i++) - redirect_loop(shell, cmd[i]); + redirect_loop(shell, cmd[i], strdup(cmd[i])); } diff --git a/tests/shell/write_history_test.c b/tests/shell/write_history_test.c index 3bcdfe7..f2c68d5 100644 --- a/tests/shell/write_history_test.c +++ b/tests/shell/write_history_test.c @@ -23,15 +23,15 @@ Test(write_command_history, simple_command_1) "PWD=/home/marvin"}; FILE *fp; - close(open(".history", O_RDWR | O_TRUNC)); + close(open(".history42", O_RDWR | O_TRUNC)); for (int i = 0; i < 4; i++) { env[i] = malloc(sizeof(char) * my_strlen(str[i])); env[i] = my_strcpy(env[i], str[i]); } env[4] = NULL; cmd = get_command_line(true, "ls -l", env, NULL); - write_command_history(true, cmd); - fp = fopen (".history","r"); + write_command_history(cmd->full_command, NULL); + fp = fopen (".history42","r"); cr_assert_file_contents_eq_str(fp, "ls -l\n"); } @@ -43,16 +43,16 @@ Test(write_command_history, simple_command_2) "PWD=/home/marvin"}; FILE *fp; - close(open(".history", O_RDWR | O_TRUNC)); + close(open(".history42", O_RDWR | O_TRUNC)); for (int i = 0; i < 4; i++) { env[i] = malloc(sizeof(char) * my_strlen(str[i])); env[i] = my_strcpy(env[i], str[i]); } env[4] = NULL; cmd = get_command_line(true, "ls -l", env, NULL); - write_command_history(true, cmd); + write_command_history(cmd->full_command, NULL); cmd = get_command_line(true, "env", env, NULL); - write_command_history(true, cmd); - fp = fopen (".history","r"); + write_command_history(cmd->full_command, NULL); + fp = fopen (".history42","r"); cr_assert_file_contents_eq_str(fp, "ls -l\nenv\n"); } From fe62c982f68296446083481c9f1deba943df55ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Cadoul?= Date: Fri, 25 May 2018 12:56:05 +0200 Subject: [PATCH 5/7] ADD [scripting] : scripting management in shell_loop --- Makefile | 1 + include/script.h | 1 + script.sh | 6 ----- src/main.c | 4 --- src/scripting/check_script.c | 16 +++++------ src/scripting/get_valid_line_script.c | 38 +++++++++++++++++++++++++++ src/scripting/run_script.c | 32 ++++++++++++++-------- src/shell_loop/shell_loop.c | 14 ++++++---- tests/scripting/script_test.sh | 2 +- 9 files changed, 77 insertions(+), 37 deletions(-) delete mode 100755 script.sh create mode 100644 src/scripting/get_valid_line_script.c diff --git a/Makefile b/Makefile index a87791c..5ebf021 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,7 @@ SRCS = $(PATH_SRC)/check_args.c \ $(PATH_SRC)/shell_loop/execution/condition_instruction.c \ $(PATH_SRC)/scripting/check_script.c \ $(PATH_SRC)/scripting/fill_condition_script.c \ + $(PATH_SRC)/scripting/get_valid_line_script.c \ $(PATH_SRC)/scripting/init_condition_script.c \ $(PATH_SRC)/scripting/keywords_script.c \ $(PATH_SRC)/scripting/open_script.c \ diff --git a/include/script.h b/include/script.h index 34fdc81..eed6298 100644 --- a/include/script.h +++ b/include/script.h @@ -42,6 +42,7 @@ bool check_script_name(char *); bool check_script_shebang(char *); /* --- Script running --- */ +char *get_valid_line(FILE *, shell_t *); char *run_script(shell_t *, FILE *); FILE *open_script(char *, shell_t *); bool fill_cond(cond_t *, char *, char **); diff --git a/script.sh b/script.sh deleted file mode 100755 index 9da9c14..0000000 --- a/script.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/tcsh - -set toto = 2 - -while ($toto < 10) echo toto -@ toto = $toto + 1 diff --git a/src/main.c b/src/main.c index 21c049f..0e298a9 100644 --- a/src/main.c +++ b/src/main.c @@ -24,7 +24,3 @@ int main(int argc, char **argv, char **env) return (FAILURE); return (destroy_shell(shell)); } -// int main(int argc, char **argv, char **env) -// { -// check_args(argc, argv); -// } diff --git a/src/scripting/check_script.c b/src/scripting/check_script.c index 46b2d88..88fc76a 100644 --- a/src/scripting/check_script.c +++ b/src/scripting/check_script.c @@ -14,22 +14,18 @@ bool check_script_shebang(char *path) FILE *fd = fopen(path, "r"); size_t n = 0; char *buf = NULL; + bool status = false; if (!fd) return (false); - if (getline(&buf, &n, fd) == -1) { - fclose(fd); - return (false); - } - if (buf && !strncmp(buf, "#!", 2)) { - free(buf); - fclose(fd); - return (true); - } + if (getline(&buf, &n, fd) == -1) + status = false; + else if (buf && !strncmp(buf, "#!", 2)) + status = true; if (buf) free(buf); fclose(fd); - return (false); + return (status); } bool check_script_name(char *path) diff --git a/src/scripting/get_valid_line_script.c b/src/scripting/get_valid_line_script.c new file mode 100644 index 0000000..919a101 --- /dev/null +++ b/src/scripting/get_valid_line_script.c @@ -0,0 +1,38 @@ +/* +** EPITECH PROJECT, 2018 +** PSU_42sh_2017 +** File description: +** Get valid line in the script +*/ + +#include "script.h" + +static char *check_and_rect_line(char *line) +{ + if (!line) + return (NULL); + for (int i = 0; line[i] != '\0'; i += 1) { + if (line[i] == '#' || line[i] == '\n') + line[i] = '\0'; + } + if (!strncmp(line, "#!", 2) || !strcmp(line, "\n") || + !strcmp(line, "")) { + free(line); + line = NULL; + } + return (line); +} + +char *get_valid_line(FILE *fd, shell_t *shell) +{ + char *line = NULL; + size_t n = 0; + + while (!(line = check_and_rect_line(line))) + if (getline(&line, &n, fd) == -1) { + shell->script = false; + fclose(fd); + return (NULL); + } + return (line); +} diff --git a/src/scripting/run_script.c b/src/scripting/run_script.c index 1ac1d7b..9e822f1 100644 --- a/src/scripting/run_script.c +++ b/src/scripting/run_script.c @@ -7,6 +7,25 @@ #include "script.h" +char *is_conditional_line(shell_t *sell, cond_t *cond_line, char *line, +FILE *fd) +{ + int status = 0; + + if (cond_line->end == true) { + free_cond_line(cond_line); + cond_line = init_conditional_line(); + } + if (cond_line->key == EMPTY) { + if ((status = search_keyword(cond_line, line)) == FAILURE) { + free_cond_line(cond_line); + return (NULL); + } + if (status == SKIP) + return (line); + } +} + char *run_script(shell_t *shell, FILE *fd) { char *line = NULL; @@ -17,17 +36,8 @@ char *run_script(shell_t *shell, FILE *fd) if (!cond_line) if (!(cond_line = init_conditional_line())) return (NULL); - if (getline(&line, &n, fd) == -1) { - shell->script = false; - fclose(fd); - return (NULL); - } - if ((status = search_keyword(cond_line, line)) == FAILURE) { - free_cond_line(cond_line); + if (!(line = get_valid_line(fd, shell))) return (NULL); - } - if (status == SKIP) - return (line); - // contidion mangement + line = is_conditional_line(shell, cond_line, line, fd); return (line); } diff --git a/src/shell_loop/shell_loop.c b/src/shell_loop/shell_loop.c index 3c7b8bd..409aad0 100644 --- a/src/shell_loop/shell_loop.c +++ b/src/shell_loop/shell_loop.c @@ -43,19 +43,23 @@ char *redirect_script(shell_t *shell, FILE *fd) char *line = NULL; size_t n = 0; - if (!fd) - return (line); - if (shell->script) + if (shell->script) { if ((line = run_script(shell, fd))) return (line); - return (line = get_next_line(0)); + shell->script = false; + return (NULL); + } + if(!display_prompt(shell)) + return (NULL); + line = get_next_line(0); + return (line); } unsigned int shell_loop(shell_t *shell, FILE *fd) { char *user_input = NULL; - while (shell->state == OK && display_prompt(shell) && + while (shell->state == OK && (user_input = redirect_script(shell, fd)) != NULL) { if (redirect_loop(shell, user_input) == FAILURE) return (FAILURE); diff --git a/tests/scripting/script_test.sh b/tests/scripting/script_test.sh index ff52846..4ca45db 100755 --- a/tests/scripting/script_test.sh +++ b/tests/scripting/script_test.sh @@ -1,3 +1,3 @@ -#!./42sh +#!42sh echo toto From 872b52d0feb9c3a4236482feac0469d512fd11ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Cadoul?= Date: Fri, 25 May 2018 14:58:56 +0200 Subject: [PATCH 6/7] MOD [scripting] : check script name condition --- src/scripting/check_script.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/check_script.c b/src/scripting/check_script.c index 88fc76a..0b1c1d5 100644 --- a/src/scripting/check_script.c +++ b/src/scripting/check_script.c @@ -35,7 +35,7 @@ bool check_script_name(char *path) if (!tmp) return (false); - for (int i = strlen(path) - 1; SH_CHAR(path[i]); i -= 1) { + for (int i = strlen(path) - 1; SH_CHAR(path[i]) && j < 3; i -= 1) { tmp[j] = path[i]; j += 1; } From 2fd24f8058f01ed8ab7ffae0cdae5e9daf2da4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Cadoul?= Date: Fri, 25 May 2018 15:27:39 +0200 Subject: [PATCH 7/7] MERGE: version 0.8 Scripting added --- include/shell.h | 8 ++------ src/shell_loop/shell_loop.c | 6 +++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/include/shell.h b/include/shell.h index 28c7bd9..5e7fefa 100644 --- a/include/shell.h +++ b/include/shell.h @@ -69,25 +69,21 @@ typedef struct shell_s { bool script; } shell_t; -int check_args(int, char **); char **copy_environement(char **); shell_t *initialisation_shell(int, char **, char **); char **copy_environement(char **); backup_t *initialisation_backup(char **); -unsigned int shell_loop(shell_t *); -unsigned int redirect_loop(shell_t *, char *); -int display_prompt(shell_t *shell); void free_array_string(char **); void display_bonus_prompt(int, char *, char *, char *); void update_backup(shell_t *); bool init_terminal(shell_t *); bool is_bonus(int, char **); int display_prompt(shell_t *); -int check_args(int); +int check_args(int, char **); int destroy_shell(shell_t *); int find_option_env(char **, char *); int find_separator_env(char *); -unsigned int shell_loop(shell_t *); +unsigned int shell_loop(shell_t *, FILE *); unsigned int redirect_loop(shell_t *, char *, char *); char **init_local(void); diff --git a/src/shell_loop/shell_loop.c b/src/shell_loop/shell_loop.c index 976d7b3..9424db7 100644 --- a/src/shell_loop/shell_loop.c +++ b/src/shell_loop/shell_loop.c @@ -53,16 +53,16 @@ char *redirect_script(shell_t *shell, FILE *fd) } if(!display_prompt(shell)) return (NULL); - line = get_next_line(0); + line = get_input(shell, 1, 0); return (line); } unsigned int shell_loop(shell_t *shell, FILE *fd) { - char *user_input = NULL; + char *input = NULL; while (shell->state == OK && - (user_input = redirect_script(shell, fd)) != NULL) { + (input = redirect_script(shell, fd)) != NULL) { if (redirect_loop(shell, input, strdup(input)) == FAILURE) return (FAILURE); }