GCC Code Coverage Report


Directory: ./
File: src/separators/backticks.c
Date: 2024-06-05 00:36:48
Exec Total Coverage
Lines: 68 70 97.1%
Functions: 6 6 100.0%
Branches: 24 30 80.0%

Line Branch Exec Source
1 /*
2 ** EPITECH PROJECT, 2024
3 ** 42sh
4 ** File description:
5 ** The file containing the backticks functions
6 */
7 /**
8 * @file backticks.c
9 * @brief The file containing the backticks functions
10 */
11
12 #include "../../include/myshell.h"
13
14 /**
15 * @brief Check if the backticks are matched
16 * @param mysh The shell structure
17 * @param line The command line
18 * @return <b>int</b> <u>-1</u> if the backticks are not matched,
19 * the number of commands in backticks otherwise
20 */
21 4713 int check_unmatched(mysh_t *mysh, char *line)
22 {
23 4713 int count = 0;
24
25
2/2
✓ Branch 0 taken 10599 times.
✓ Branch 1 taken 4713 times.
15312 for (int i = 0; line[i] != '\0'; i++) {
26
4/6
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 10568 times.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 31 times.
10599 if (line[i] == '`' && (i == 0 || line[i - 1] != '\\' ||
27 (line[i - 1] == '\\' && char_is_inhibited(line, i - 1) == 0)))
28 31 count++;
29 }
30
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4712 times.
4713 if (count % 2 != 0) {
31 1 my_putstr_error("Unmatched '`'.\n");
32 1 mysh->exit_status = 1;
33 1 return -1;
34 }
35 4712 return count / 2;
36 }
37
38 /**
39 * @brief Execute the child process for backticks
40 * @param mysh The shell structure
41 * @param line The command line to execute
42 * @param fd The file descriptor for the pipe
43 * @return <b>void</b>
44 */
45 15 static void child_process(mysh_t *mysh, char *line, int fd[2])
46 {
47 15 dup2(fd[1], 1);
48 15 close(fd[0]);
49 15 close(fd[1]);
50 15 analyse_multi_commands(mysh, line);
51 15 my_exit(mysh, mysh->exit_status, NULL);
52 }
53
54 /**
55 * @brief Execute the parent process for backticks
56 * @param mysh The shell structure
57 * @param command The result of the command
58 * @param fd The file descriptor for the pipe
59 * @param pid The process id
60 * @return <b>void</b>
61 */
62 15 static void parent_process(mysh_t *mysh, char **command, int fd[2], pid_t pid)
63 {
64 15 int nb_bytes = 0;
65
66 15 close(fd[1]);
67 15 waitpid(pid, &mysh->exit_status, 0);
68 15 nb_bytes = read(fd[0], *command, 1024);
69
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 15 times.
169 while (nb_bytes == 1024) {
70 154 *command = realloc(*command,
71 154 sizeof(char) * (1024 + my_strlen(*command)));
72 154 nb_bytes = read(fd[0], *command + my_strlen(*command), 1024);
73 }
74 15 close(fd[0]);
75 15 }
76
77 /**
78 * @brief Execute the command in backticks
79 * @param mysh The shell structure
80 * @param line The command line to execute
81 * @return <b>char *</b> The result of the command
82 */
83 15 char *exec_command_in_backticks(mysh_t *mysh, char *line)
84 {
85 int fd[2];
86 pid_t pid;
87 15 char *command = calloc(1024, sizeof(char));
88
89 15 line[my_get_char_index(line, '`', 1)] = '\0';
90 15 mysh->saved_stdout = dup(1);
91 15 pipe(fd);
92 15 pid = fork();
93
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 if (pid == 0)
94 15 child_process(mysh, line, fd);
95 else
96 15 parent_process(mysh, &command, fd, pid);
97 15 FREE(line);
98 15 return command;
99 }
100
101 /**
102 * @brief Set the new command line without backticks
103 * @param mysh The shell structure
104 * @param line The command line
105 * @param new_line The new command line
106 * @return <b>void</b>
107 */
108 15 static void set_new_command_line(mysh_t *mysh, char *line, char **new_line)
109 {
110 15 char *command = exec_command_in_backticks(mysh,
111 15 my_strdup(line + my_get_char_index(line, '`', 1) + 1));
112
113 15 my_replace_char(command, '\n', ' ');
114
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 4 times.
26 for (int index = my_strlen(command) - 1; index >= 0; index--) {
115
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 11 times.
22 if (my_char_is(command[index], " \t\n"))
116 11 command[index] = '\0';
117 else
118 11 break;
119 }
120 15 *new_line = calloc(my_get_char_index(line, '`', 1) + strlen(command) +
121 15 my_strlen(line + my_get_char_index(line, '`', 2)) + 2, sizeof(char));
122 15 my_strncpy(*new_line, line, my_get_char_index(line, '`', 1));
123 15 my_strcat(*new_line, command);
124 15 my_strcat(*new_line, line + my_get_char_index(line, '`', 2) + 1);
125 15 FREE(command);
126 15 }
127
128 /**
129 * @brief Analyse and execute backticks commands
130 * @param mysh The shell structure
131 * @param line The command line
132 * @return <b>void</b>
133 */
134 4713 void analyse_backticks(mysh_t *mysh, char *line)
135 {
136 4713 char *new_line = NULL;
137 4713 int nb_cmds = check_unmatched(mysh, line);
138 4713 char *backup = my_strdup(line);
139
140
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4712 times.
4713 if (nb_cmds == -1)
141 15 return;
142 4712 FREE(mysh->line);
143 4712 mysh->line = backup;
144
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4712 times.
4727 for (int i = 0; i < nb_cmds; i++) {
145 15 set_new_command_line(mysh, mysh->line, &new_line);
146 15 FREE(mysh->line);
147 15 mysh->line = new_line;
148 }
149
4/4
✓ Branch 1 taken 4699 times.
✓ Branch 2 taken 13 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4698 times.
4712 if (replace_variables(mysh) || check_tilde(mysh))
150 14 return;
151 4698 analyse_multi_commands(mysh, mysh->line);
152 }
153