diff --git a/.gitignore b/.gitignore index f3b5883..3f7e8c4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ 42sh **/*.gcda **/*.gcno -unit_tests \ No newline at end of file +unit_tests +.vscode \ No newline at end of file diff --git a/Makefile b/Makefile index 21a70a2..8a5d4a3 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ SRC = src/shell.c \ src/builtin/builtin_manager.c \ src/builtin/builtin_env.c \ src/builtin/builtin_source.c \ + src/builtin/builtin_source_two.c \ src/builtin/builtin_which.c \ src/builtin/builtin_where.c \ src/signal.c \ @@ -32,6 +33,7 @@ SRC = src/shell.c \ src/utility/envpath.c \ src/utility/fusion.c \ src/utility/split_commands.c \ + src/utility/get_return.c \ OBJ = $(SRC:%.c=%.o) OBJ += src/main.o @@ -39,7 +41,8 @@ OBJ += src/main.o TESTS = tests/tenv.c \ tests/targc.c \ tests/texecute.c \ - tests/tcd.c + tests/tcd.c \ + tests/tsource.c \ COVERAGE = -lcriterion --coverage diff --git a/include/builtin.h b/include/builtin.h index de1254b..e8368ce 100644 --- a/include/builtin.h +++ b/include/builtin.h @@ -39,4 +39,6 @@ int clear_history(env_t *env); int execute_from_history(char **args, env_t *env); void remove_duplicate_history(env_t *env); int execute_command_history(history_t *old, history_t *new, -char **args, env_t *env); \ No newline at end of file +char **args, env_t *env); +//source +char *parse_source_cmd(char *cmd, char **argv, int len_argv); \ No newline at end of file diff --git a/src/builtin/builtin_source.c b/src/builtin/builtin_source.c index c495045..6ea5ebc 100644 --- a/src/builtin/builtin_source.c +++ b/src/builtin/builtin_source.c @@ -16,27 +16,27 @@ #include "utility.h" #include "shell.h" -static void start_script(char *path, env_t *env) +static void start_script(char **argv, env_t *env, int len_argv) { char *str = NULL; char **arr = NULL; - int fd = open(path, O_RDONLY); + int fd = open(argv[1], O_RDONLY); bool should_close = false; struct stat st_buff; if (fd == -1) return; - stat(path, &st_buff); - str = malloc(st_buff.st_size); - if (!str) { - close(fd); - return; + stat(argv[1], &st_buff); + str = malloc(st_buff.st_size + 1); + if (str) { + read(fd, str, st_buff.st_size); + arr = split_str(str, '\n'); + if (arr) + for (int i = 0; arr[i] && !should_close; i++) + should_close = (eval_raw_cmd(parse_source_cmd(arr[i], + argv, len_argv), env) < 0); + free(str); } - read(fd, str, st_buff.st_size); - arr = split_str(str, '\n'); - if (arr) - for (int i = 0; arr[i] && !should_close; i++) - should_close = (eval_raw_cmd(strdup(arr[i]), env) < 0); close(fd); } @@ -72,6 +72,6 @@ int builtin_source(char **argv, env_t *env) return (0); } if (file_is_accessible(argv[1])) - start_script(argv[1], env); + start_script(argv, env, len); return (0); } \ No newline at end of file diff --git a/src/builtin/builtin_source_two.c b/src/builtin/builtin_source_two.c new file mode 100644 index 0000000..025e608 --- /dev/null +++ b/src/builtin/builtin_source_two.c @@ -0,0 +1,80 @@ +/* +** EPITECH PROJECT, 2020 +** ash +** File description: +** second part of the source function +*/ + +#include +#include +#include +#include +#include + +int count_char_in_str(char *str, char c) +{ + int res = 0; + + for(int i = 0; str[i]; i++) + if (str[i] == c) + res++; + return (res); +} + +static char *get_str_arg(int arg_index, char **argv) +{ + if (arg_index == 0) + return ("42sh"); + return (argv[arg_index + 1]); +} + +static int get_max_args_len(char **argv) +{ + int max_len = 4; + int len = 0; + + for (int i = 2; argv[i]; i++) { + len = strlen(argv[i]); + if (len > max_len) + max_len = len; + } + return (max_len); +} + +void fill_parsed_str(char *result, char *cmd, char **argv, int len_argv) +{ + int counter = 0; + int argv_index = 0; + char *str_arg = NULL; + + for (int i = 0; cmd[i]; i++) { + if (cmd[i] == '$') { + if (!cmd[i + 1]) + break; + argv_index = atoi(&cmd[i + 1]); + if (argv_index <= len_argv - 2 && isdigit(cmd[i + 1])) { + str_arg = get_str_arg(argv_index, argv); + for (int j = 0; str_arg[j]; j++) + result[counter++] = str_arg[j]; + } + i++; + } + else + result[counter++] = cmd[i]; + } + result[counter] = '\0'; +} + +char *parse_source_cmd(char *cmd, char **argv, int len_argv) +{ + char *result = NULL; + int max_arg_len = get_max_args_len(argv); + int max_parsed_str_len = strlen(cmd) + + (max_arg_len * count_char_in_str(cmd, '$')); + + result = malloc(sizeof(char) * (max_parsed_str_len + 1)); + if (!result) + return (NULL); + fill_parsed_str(result, cmd, argv, len_argv); + return (result); +} \ No newline at end of file diff --git a/src/main.c b/src/main.c index 3f7131e..6e98fc0 100644 --- a/src/main.c +++ b/src/main.c @@ -11,13 +11,6 @@ #include #include -int get_return(char *ret) -{ - if (!ret) - return (0); - return (atoi(ret)); -} - int main(int argc, char **argv, char **env) { env_t *envt = malloc(sizeof(*envt)); diff --git a/src/prompt.c b/src/prompt.c index a414b44..2127e4b 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -20,10 +20,10 @@ const builtin builtins[] = { {"unsetenv", &builtin_unsetenv}, {"exit", &builtin_exit}, {"cd", &builtin_cd}, + {"history", &builtin_history}, {"which", &builtin_which}, {"where", &builtin_where}, {"source", &builtin_source}, - {"history", &builtin_history}, {NULL, NULL} }; diff --git a/src/utility/get_return.c b/src/utility/get_return.c new file mode 100644 index 0000000..fc913fa --- /dev/null +++ b/src/utility/get_return.c @@ -0,0 +1,15 @@ +/* +** EPITECH PROJECT, 2020 +** ash +** File description: +** get return +*/ + +#include + +int get_return(char *ret) +{ + if (!ret) + return (0); + return (atoi(ret)); +} \ No newline at end of file diff --git a/tests/texecute.c b/tests/texecute.c index 032450b..537aae1 100644 --- a/tests/texecute.c +++ b/tests/texecute.c @@ -9,7 +9,7 @@ #include #include "shell.h" -void eval(char *cmd, char **argv, env_t* env); +char *eval(char *cmd, char **argv, env_t* env); extern char **environ; diff --git a/tests/tsource.c b/tests/tsource.c new file mode 100644 index 0000000..4a5ba17 --- /dev/null +++ b/tests/tsource.c @@ -0,0 +1,109 @@ +/* +** EPITECH PROJECT, 2020 +** ash +** File description: +** test source function +*/ + +#include +#include +#include +#include +#include "shell.h" +#include "builtin.h" + +Test(parse_source_cmd, no_args) +{ + char *cmd = strdup("echo wow"); + char **argv = get_argv(strdup("source source_file")); + int argv_len = 0; + char *res = NULL; + + for (; argv[argv_len]; argv_len++); + res = parse_source_cmd(cmd, argv, argv_len); + cr_assert_str_eq(res, "echo wow"); +} + +Test(parse_source_cmd, one_arg) +{ + char *cmd = strdup("echo $1"); + char **argv = get_argv(strdup("source source_file wow")); + int argv_len = 0; + char *res = NULL; + + for (; argv[argv_len]; argv_len++); + res = parse_source_cmd(cmd, argv, argv_len); + cr_assert_str_eq(res, "echo wow"); +} + +Test(parse_source_cmd, two_args) +{ + char *cmd = strdup("$2 $1"); + char **argv = get_argv(strdup("source source_file wow echo")); + int argv_len = 0; + char *res = NULL; + + for (; argv[argv_len]; argv_len++); + res = parse_source_cmd(cmd, argv, argv_len); + cr_assert_str_eq(res, "echo wow"); +} + +Test(parse_source_cmd, args_out_of_range) +{ + char *cmd = strdup("echo wow$1"); + char **argv = get_argv(strdup("source source_file")); + int argv_len = 0; + char *res = NULL; + + for (; argv[argv_len]; argv_len++); + res = parse_source_cmd(cmd, argv, argv_len); + cr_assert_str_eq(res, "echo wow"); +} + +Test(parse_source_cmd, args_index_0) +{ + char *cmd = strdup("echo shell is: $0"); + char **argv = get_argv(strdup("source source_file")); + int argv_len = 0; + char *res = NULL; + + for (; argv[argv_len]; argv_len++); + res = parse_source_cmd(cmd, argv, argv_len); + cr_assert_str_eq(res, "echo shell is: 42sh"); +} + +Test(parse_source_cmd, args_inside_cmd) +{ + char *cmd = strdup("e$1o wow"); + char **argv = get_argv(strdup("source source_file ch")); + int argv_len = 0; + char *res = NULL; + + for (; argv[argv_len]; argv_len++); + res = parse_source_cmd(cmd, argv, argv_len); + cr_assert_str_eq(res, "echo wow"); +} + +Test(parse_source_cmd, invalid_arg) +{ + char *cmd = strdup("e$o wow"); + char **argv = get_argv(strdup("source source_file ch")); + int argv_len = 0; + char *res = NULL; + + for (; argv[argv_len]; argv_len++); + res = parse_source_cmd(cmd, argv, argv_len); + cr_assert_str_eq(res, "e wow"); +} + +Test(parse_source_cmd, empty_str) +{ + char *cmd = strdup(""); + char **argv = get_argv(strdup("source source_file ch")); + int argv_len = 0; + char *res = NULL; + + for (; argv[argv_len]; argv_len++); + res = parse_source_cmd(cmd, argv, argv_len); + cr_assert_str_eq(res, ""); +} \ No newline at end of file