Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | ** EPITECH PROJECT, 2024 | ||
3 | ** 42sh | ||
4 | ** File description: | ||
5 | ** The file containing the input_command functions | ||
6 | */ | ||
7 | /** | ||
8 | * @file input_command.c | ||
9 | * @brief The file containing the input_command functions | ||
10 | */ | ||
11 | |||
12 | #include "../../include/myshell.h" | ||
13 | |||
14 | /** | ||
15 | * @brief Initialize the input command | ||
16 | * @param command The command | ||
17 | * @return <b>input_command_t *</b> The input command | ||
18 | */ | ||
19 | 1153 | input_command_t *init_input_command(char *command) | |
20 | { | ||
21 | 1153 | input_command_t *input_command = malloc(sizeof(input_command_t)); | |
22 | |||
23 | 1153 | input_command->command = CALLOC(my_strlen(command) + 1, sizeof(char)); | |
24 | 1153 | input_command->args = NULL; | |
25 | 1153 | input_command->left = NULL; | |
26 | 1153 | input_command->right = NULL; | |
27 | 1153 | input_command->left_type = 0; | |
28 | 1153 | input_command->right_type = 0; | |
29 | 1153 | input_command->current = input_command->command; | |
30 | 1153 | return input_command; | |
31 | } | ||
32 | |||
33 | /** | ||
34 | * @brief Check if there is an error in the input command | ||
35 | * @param input_command The input command | ||
36 | * @param command The command | ||
37 | * @param index The index | ||
38 | * @param inhibitors The inhibitors | ||
39 | * @return <b>int</b> <u>1</u> if there is an error, <u>0</u> otherwise | ||
40 | */ | ||
41 | 178451 | static int check_error(input_command_t *input_command, | |
42 | const char *command, int index, int inhibitors) | ||
43 | { | ||
44 |
4/4✓ Branch 0 taken 972 times.
✓ Branch 1 taken 177479 times.
✓ Branch 2 taken 720 times.
✓ Branch 3 taken 252 times.
|
178451 | if (input_command->right_type != 0 && |
45 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 707 times.
|
720 | inhibitors == 0 && command[index] == '>') { |
46 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
|
13 | if (input_command->right[0] == '\0') |
47 | 7 | my_putstr_error("Missing name for redirect.\n"); | |
48 | else | ||
49 | 6 | my_putstr_error("Ambiguous output redirect.\n"); | |
50 | 13 | return 1; | |
51 | } | ||
52 |
3/4✓ Branch 0 taken 769 times.
✓ Branch 1 taken 177669 times.
✓ Branch 2 taken 769 times.
✗ Branch 3 not taken.
|
178438 | if (input_command->left_type != 0 && |
53 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 769 times.
|
769 | inhibitors == 0 && command[index] == '<') { |
54 | ✗ | if (input_command->left[0] == '\0') | |
55 | ✗ | my_putstr_error("Missing name for redirect.\n"); | |
56 | else | ||
57 | ✗ | my_putstr_error("Ambiguous input redirect.\n"); | |
58 | ✗ | return 1; | |
59 | } | ||
60 | 178438 | return 0; | |
61 | } | ||
62 | |||
63 | /** | ||
64 | * @brief Check if the character is a right redirection and | ||
65 | * change the input structure | ||
66 | * @param input_command The input command | ||
67 | * @param command The command | ||
68 | * @param index The index | ||
69 | * @return <b>int</b> <u>1</u> if the character is a right redirection, | ||
70 | * <u>0</u> otherwise | ||
71 | */ | ||
72 | 177773 | static int right_redirection(input_command_t *input_command, | |
73 | char *command, int *index) | ||
74 | { | ||
75 |
4/4✓ Branch 0 taken 100 times.
✓ Branch 1 taken 177673 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 63 times.
|
177773 | if (command[*index] == '>' && command[*index + 1] == '>') { |
76 | 37 | input_command->right_type = 2; | |
77 | 37 | input_command->right = CALLOC(my_strlen(command), sizeof(char)); | |
78 | 37 | input_command->current = input_command->right; | |
79 | 37 | (*index)++; | |
80 | 37 | return 1; | |
81 | } | ||
82 |
2/2✓ Branch 0 taken 63 times.
✓ Branch 1 taken 177673 times.
|
177736 | if (command[*index] == '>') { |
83 | 63 | input_command->right_type = 1; | |
84 | 63 | input_command->right = CALLOC(my_strlen(command), sizeof(char)); | |
85 | 63 | input_command->current = input_command->right; | |
86 | 63 | return 1; | |
87 | } | ||
88 | 177673 | return 0; | |
89 | } | ||
90 | |||
91 | /** | ||
92 | * @brief Check if the character is a left redirection and | ||
93 | * change the input structure | ||
94 | * @param input_command The input command | ||
95 | * @param command The command | ||
96 | * @param index The index | ||
97 | * @return <b>int</b> <u>1</u> if the character is a left redirection, | ||
98 | * <u>0</u> otherwise | ||
99 | */ | ||
100 | 177673 | static int left_redirection(input_command_t *input_command, | |
101 | char *command, int *index) | ||
102 | { | ||
103 |
4/4✓ Branch 0 taken 45 times.
✓ Branch 1 taken 177628 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 38 times.
|
177673 | if (command[*index] == '<' && command[*index + 1] == '<') { |
104 | 7 | input_command->left_type = 2; | |
105 | 7 | input_command->left = CALLOC(my_strlen(command), sizeof(char)); | |
106 | 7 | input_command->current = input_command->left; | |
107 | 7 | (*index)++; | |
108 | 7 | return 1; | |
109 | } | ||
110 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 177628 times.
|
177666 | if (command[*index] == '<') { |
111 | 38 | input_command->left_type = 1; | |
112 | 38 | input_command->left = CALLOC(my_strlen(command), sizeof(char)); | |
113 | 38 | input_command->current = input_command->left; | |
114 | 38 | return 1; | |
115 | } | ||
116 | 177628 | return 0; | |
117 | } | ||
118 | |||
119 | /** | ||
120 | * @brief Add a character to the input command | ||
121 | * @param input_command The input command | ||
122 | * @param command The command | ||
123 | * @param index The index | ||
124 | * @param inhibitors The inhibitors | ||
125 | * @return <b>int</b> The start value | ||
126 | */ | ||
127 | 178438 | static int add_char_to_input(input_command_t *input_command, | |
128 | char *command, int *index, char *inhibitors) | ||
129 | { | ||
130 | static int start = 1; | ||
131 | |||
132 |
4/4✓ Branch 0 taken 177773 times.
✓ Branch 1 taken 665 times.
✓ Branch 2 taken 177673 times.
✓ Branch 3 taken 100 times.
|
356211 | if (*inhibitors == 0 && |
133 |
2/2✓ Branch 1 taken 45 times.
✓ Branch 2 taken 177628 times.
|
355446 | (right_redirection(input_command, command, index) || |
134 | 177673 | left_redirection(input_command, command, index))) { | |
135 | 145 | start = 1; | |
136 | 145 | return -1; | |
137 | } | ||
138 |
2/2✓ Branch 0 taken 1291 times.
✓ Branch 1 taken 177002 times.
|
178293 | if (input_command->current == input_command->command || |
139 |
5/6✓ Branch 0 taken 252 times.
✓ Branch 1 taken 1039 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 252 times.
✓ Branch 4 taken 270 times.
✓ Branch 5 taken 769 times.
|
2330 | (*inhibitors != 0 && *inhibitors != command[*index]) || |
140 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 270 times.
|
1309 | my_char_is(command[*index], " \t\n\"\'\\()") == 0 || *inhibitors == 1) { |
141 | 178023 | my_add_chr(input_command->current, command[*index]); | |
142 | 178023 | start = 0; | |
143 | 178023 | return -1; | |
144 | } | ||
145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
|
270 | if (*inhibitors != 0) |
146 | ✗ | return -1; | |
147 | 270 | return start; | |
148 | } | ||
149 | |||
150 | /** | ||
151 | * @brief Update the inhibitors | ||
152 | * @param command The command | ||
153 | * @param index The index | ||
154 | * @param inhibitors The inhibitors | ||
155 | * @param end_inhibitors The end inhibitors | ||
156 | * @return <b>void</b> | ||
157 | */ | ||
158 | 178515 | static int update_inhibitors(char *command, int index, | |
159 | char *inhibitors) | ||
160 | { | ||
161 |
4/4✓ Branch 0 taken 678 times.
✓ Branch 1 taken 177837 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 616 times.
|
178515 | if ((*inhibitors != 0 && *inhibitors == command[index] |
162 |
5/6✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 106 times.
✓ Branch 3 taken 178347 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 95 times.
|
178515 | && *inhibitors != '\\') || (*inhibitors == '(' && command[index] == ')')) { |
163 | 73 | *inhibitors = 0; | |
164 | 73 | return 1; | |
165 | } | ||
166 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 178419 times.
|
178442 | if (*inhibitors == '\\') { |
167 | 23 | *inhibitors = 1; | |
168 | 23 | return 0; | |
169 | } | ||
170 |
4/4✓ Branch 0 taken 177837 times.
✓ Branch 1 taken 582 times.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 177739 times.
|
178419 | if (*inhibitors == 0 && my_char_is(command[index], "\'\"\\(")) { |
171 | 98 | *inhibitors = command[index]; | |
172 | 98 | return 1; | |
173 | } | ||
174 | 178321 | return 0; | |
175 | } | ||
176 | |||
177 | /** | ||
178 | * @brief Validate the input command | ||
179 | * @param input_command The input command | ||
180 | * @param inhibitors The inhibitors | ||
181 | * @return <b>input_command_t *</b> The input command if it is valid, | ||
182 | * <u>NULL</u> otherwise | ||
183 | */ | ||
184 | 1140 | input_command_t *validate_input_command(input_command_t *input_command, | |
185 | char inhibitors) | ||
186 | { | ||
187 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1138 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
1140 | if (inhibitors != 0 && inhibitors != 1) { |
188 | 2 | my_fprintf(2, "Unmatched '%c'.\n", inhibitors); | |
189 | 2 | return NULL; | |
190 | } | ||
191 | 1138 | return input_command; | |
192 | } | ||
193 | |||
194 | /** | ||
195 | * @brief Get the input command | ||
196 | * @param command The command | ||
197 | * @return <b>input_command_t *</b> The input command | ||
198 | */ | ||
199 | 1153 | input_command_t *get_input_command(char *command) | |
200 | { | ||
201 | 1153 | input_command_t *input_command = init_input_command(command); | |
202 | 1153 | char inhibitors = 0; | |
203 | |||
204 |
6/6✓ Branch 0 taken 193 times.
✓ Branch 1 taken 1178 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1166 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 1153 times.
|
1371 | while (command[0] == ' ' || command[0] == '\t' || command[0] == '\n') |
205 | 218 | command++; | |
206 |
2/2✓ Branch 0 taken 178515 times.
✓ Branch 1 taken 1140 times.
|
179655 | for (int index = 0; command[index] != '\0'; index++) { |
207 |
2/2✓ Branch 1 taken 171 times.
✓ Branch 2 taken 178344 times.
|
178515 | if (update_inhibitors(command, index, &inhibitors) |
208 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 107 times.
|
171 | && input_command->current != input_command->command) |
209 | 64 | continue; | |
210 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 178438 times.
|
178451 | if (check_error(input_command, command, index, inhibitors) == 1) |
211 | 13 | return NULL; | |
212 |
2/2✓ Branch 1 taken 132 times.
✓ Branch 2 taken 178306 times.
|
178438 | if (!add_char_to_input(input_command, command, &index, &inhibitors)) |
213 | 132 | input_command->current = input_command->command; | |
214 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 178415 times.
|
178438 | if (inhibitors == 1) |
215 | 23 | inhibitors = 0; | |
216 | } | ||
217 | 1140 | return validate_input_command(input_command, inhibitors); | |
218 | } | ||
219 | |||
220 | /** | ||
221 | * @brief Display the input command | ||
222 | * @note The function is used for debugging | ||
223 | * @param input_command The input command | ||
224 | * @return <b>void</b> | ||
225 | */ | ||
226 | ✗ | void display_input_command(input_command_t *input_command) | |
227 | { | ||
228 | ✗ | if (input_command == NULL) | |
229 | ✗ | return; | |
230 | ✗ | my_printf("Command: %s\n", input_command->command); | |
231 | ✗ | my_printf("Left: %s\n", input_command->left); | |
232 | ✗ | my_printf("Right: %s\n", input_command->right); | |
233 | ✗ | my_printf("Left type: %d\n", input_command->left_type); | |
234 | ✗ | my_printf("Right type: %d\n", input_command->right_type); | |
235 | ✗ | my_printf("Args: %S", input_command->args); | |
236 | } | ||
237 |