Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | ** EPITECH PROJECT, 2024 | ||
3 | ** 42sh | ||
4 | ** File description: | ||
5 | ** The file containing the foreach builtin | ||
6 | */ | ||
7 | /** | ||
8 | * @file foreach.c | ||
9 | * @brief The file containing the foreach builtin | ||
10 | */ | ||
11 | |||
12 | #include "../../include/myshell.h" | ||
13 | |||
14 | /** | ||
15 | * @brief Get the content of the variable | ||
16 | * @param mysh The shell structure | ||
17 | * @return <b>char **</b> The content of the variable | ||
18 | */ | ||
19 | ✗ | char **get_variable_content(mysh_t *mysh) | |
20 | { | ||
21 | ✗ | char *variables = NULL; | |
22 | ✗ | char **variable_content = NULL; | |
23 | ✗ | int size = 0; | |
24 | |||
25 | ✗ | for (int index = 2; mysh->args[index] != NULL; index++) | |
26 | ✗ | size += my_strlen(mysh->args[index]); | |
27 | ✗ | variables = calloc(size, sizeof(char)); | |
28 | ✗ | my_strcpy(variables, mysh->args[2] + 1); | |
29 | ✗ | for (int index = 3; mysh->args[index] != NULL; index++) { | |
30 | ✗ | my_strcat(variables, mysh->args[index]); | |
31 | ✗ | if (mysh->args[index + 1] != NULL) | |
32 | ✗ | my_strcat(variables, " "); | |
33 | } | ||
34 | ✗ | variables[my_strlen(variables) - 1] = '\0'; | |
35 | ✗ | variable_content = STR2ARRAY_SEP(variables, " \t\n"); | |
36 | ✗ | free(variables); | |
37 | ✗ | return variable_content; | |
38 | } | ||
39 | |||
40 | /** | ||
41 | * @brief Check if the foreach command is valid | ||
42 | * @param mysh The shell structure | ||
43 | * @return <b>int</b> <u>0</u> if the variable is valid, <u>1</u> otherwise | ||
44 | */ | ||
45 | 3 | static int error_handling(mysh_t *mysh) | |
46 | { | ||
47 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | if (mysh->args[1] == NULL || mysh->args[2] == NULL) { |
48 | 3 | my_putstr_error("foreach: Too few arguments.\n"); | |
49 | 3 | return 1; | |
50 | } | ||
51 | ✗ | if (is_valid_variable(mysh->args[1], "foreach") == 0) | |
52 | ✗ | return 1; | |
53 | ✗ | for (int index = 2; mysh->args[index] != NULL; index++) { | |
54 | ✗ | if (my_str_contains(mysh->args[index], "(") == 0 | |
55 | ✗ | || my_str_contains(mysh->args[index], ")") == 0) { | |
56 | ✗ | my_putstr_error("foreach: Words not parenthesized.\n"); | |
57 | ✗ | return 1; | |
58 | } | ||
59 | } | ||
60 | ✗ | return 0; | |
61 | } | ||
62 | |||
63 | /** | ||
64 | * @brief Read the content of the foreach | ||
65 | * @param mysh The shell structure | ||
66 | * @param command_list The list of commands | ||
67 | * @return <b>int</b> <u>0</u> if the command succeed, <u>1</u> otherwise | ||
68 | */ | ||
69 | ✗ | static int read_input(mysh_t *mysh, node_t **command_list) | |
70 | { | ||
71 | ✗ | int size = 0; | |
72 | ✗ | char *line = NULL; | |
73 | ✗ | char **content = NULL; | |
74 | |||
75 | ✗ | while (size != EOF && (content == NULL || my_strcmp(content[0], "end"))) { | |
76 | ✗ | IS_ATTY_PRINT("foreach? "); | |
77 | ✗ | free_str_and_tab(line, NULL); | |
78 | ✗ | size = my_getline(&line, stdin); | |
79 | ✗ | set_command_in_history(mysh, line); | |
80 | ✗ | free_str_and_tab(NULL, content); | |
81 | ✗ | content = str_to_array_inhibitors(line); | |
82 | ✗ | if (line != NULL) | |
83 | ✗ | my_push_back(command_list, my_strdup(line), STRING); | |
84 | } | ||
85 | ✗ | if (size == EOF || (content != NULL && my_strcmp(content[0], "end"))) { | |
86 | ✗ | free_str_and_tab(line, content); | |
87 | ✗ | return 1; | |
88 | } | ||
89 | ✗ | free_str_and_tab(line, content); | |
90 | ✗ | return 0; | |
91 | } | ||
92 | |||
93 | /** | ||
94 | * @brief Execute the command | ||
95 | * @param mysh The shell structure | ||
96 | * @param command The command to execute | ||
97 | * @return <b>void</b> | ||
98 | */ | ||
99 | ✗ | void execute_command(mysh_t *mysh, char *command) | |
100 | { | ||
101 | ✗ | pid_t pid = fork(); | |
102 | |||
103 | ✗ | if (pid == 0) { | |
104 | ✗ | analyse_backticks(mysh, command); | |
105 | ✗ | my_exit(mysh, mysh->exit_status, NULL); | |
106 | } else | ||
107 | ✗ | waitpid(pid, &mysh->exit_status, 0); | |
108 | ✗ | } | |
109 | |||
110 | /** | ||
111 | * @brief The foreach builtin | ||
112 | * @param mysh The shell structure | ||
113 | * @return <b>int</b> <u>0</u> if the command succeed, <u>1</u> otherwise | ||
114 | */ | ||
115 | 3 | int exec_foreach(mysh_t *mysh) | |
116 | { | ||
117 | 3 | char **variable_content = NULL; | |
118 | 3 | node_t *command_list = NULL; | |
119 | |||
120 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (error_handling(mysh)) |
121 | 3 | return 1; | |
122 | ✗ | variable_content = get_variable_content(mysh); | |
123 | ✗ | if (read_input(mysh, &command_list)) { | |
124 | ✗ | my_putstr_error("foreach: end not found.\n"); | |
125 | ✗ | FREE_WORD_ARRAY(variable_content); | |
126 | ✗ | my_delete_list(&command_list); | |
127 | ✗ | return 1; | |
128 | } | ||
129 | ✗ | for (int index = 0; variable_content[index] != NULL; index++) { | |
130 | ✗ | add_variable(mysh, mysh->args[1], variable_content[index]); | |
131 | ✗ | for (node_t *tmp = command_list; tmp && tmp->next; tmp = tmp->next) | |
132 | ✗ | execute_command(mysh, (char *)tmp->data); | |
133 | } | ||
134 | ✗ | FREE_WORD_ARRAY(variable_content); | |
135 | ✗ | my_delete_list(&command_list); | |
136 | ✗ | return 0; | |
137 | } | ||
138 |