GCC Code Coverage Report


Directory: ./
File: src/separators/backticks.c
Date: 2024-05-07 14:54:03
Exec Total Coverage
Lines: 68 70 97.1%
Functions: 6 6 100.0%
Branches: 23 30 76.7%

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 4784 int check_unmatched(mysh_t *mysh, char *line)
22 {
23 4784 int count = 0;
24
25
2/2
✓ Branch 0 taken 12668 times.
✓ Branch 1 taken 4784 times.
17452 for (int i = 0; line[i] != '\0'; i++) {
26
4/6
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 12657 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
12668 if (line[i] == '`' && (i == 0 || line[i - 1] != '\\' ||
27 (line[i - 1] == '\\' && char_is_inhibited(line, i - 1) == 0)))
28 11 count++;
29 }
30
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4783 times.
4784 if (count % 2 != 0) {
31 1 my_putstr_error("Unmatched '`'.\n");
32 1 mysh->exit_status = 1;
33 1 return -1;
34 }
35 4783 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 5 static void child_process(mysh_t *mysh, char *line, int fd[2])
46 {
47 5 dup2(fd[1], 1);
48 5 close(fd[0]);
49 5 close(fd[1]);
50 5 analyse_multi_commands(mysh, line);
51 5 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 5 static void parent_process(mysh_t *mysh, char **command, int fd[2], pid_t pid)
63 {
64 5 int nb_bytes = 0;
65
66 5 close(fd[1]);
67 5 waitpid(pid, &mysh->exit_status, 0);
68 5 nb_bytes = read(fd[0], *command, 1024);
69
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 5 times.
34 while (nb_bytes == 1024) {
70 29 *command = realloc(*command,
71 29 sizeof(char) * (1024 + my_strlen(*command)));
72 29 nb_bytes = read(fd[0], *command + my_strlen(*command), 1024);
73 }
74 5 close(fd[0]);
75 5 }
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 5 char *exec_command_in_backticks(mysh_t *mysh, char *line)
84 {
85 int fd[2];
86 pid_t pid;
87 5 char *command = calloc(1024, sizeof(char));
88
89 5 line[my_get_char_index(line, '`', 1)] = '\0';
90 5 mysh->saved_stdout = dup(1);
91 5 pipe(fd);
92 5 pid = fork();
93
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (pid == 0)
94 5 child_process(mysh, line, fd);
95 else
96 5 parent_process(mysh, &command, fd, pid);
97 5 FREE(line);
98 5 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 5 static void set_new_command_line(mysh_t *mysh, char *line, char **new_line)
109 {
110 5 char *command = exec_command_in_backticks(mysh,
111 5 my_strdup(line + my_get_char_index(line, '`', 1) + 1));
112
113 5 my_replace_char(command, '\n', ' ');
114
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 for (int index = my_strlen(command) - 1; index >= 0; index--) {
115
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (my_char_is(command[index], " \t\n"))
116 1 command[index] = '\0';
117 else
118 1 break;
119 }
120 5 *new_line = calloc(my_get_char_index(line, '`', 1) + strlen(command) +
121 5 my_strlen(line + my_get_char_index(line, '`', 2)) + 2, sizeof(char));
122 5 my_strncpy(*new_line, line, my_get_char_index(line, '`', 1));
123 5 my_strcat(*new_line, command);
124 5 my_strcat(*new_line, line + my_get_char_index(line, '`', 2) + 1);
125 5 FREE(command);
126 5 }
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 4784 void analyse_backticks(mysh_t *mysh, char *line)
135 {
136 4784 char *new_line = NULL;
137 4784 int nb_cmds = check_unmatched(mysh, line);
138 4784 char *backup = my_strdup(line);
139
140
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4783 times.
4784 if (nb_cmds == -1)
141 10 return;
142 4783 FREE(mysh->line);
143 4783 mysh->line = backup;
144
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4783 times.
4788 for (int i = 0; i < nb_cmds; i++) {
145 5 set_new_command_line(mysh, mysh->line, &new_line);
146 5 FREE(mysh->line);
147 5 mysh->line = new_line;
148 }
149
3/4
✓ Branch 1 taken 4774 times.
✓ Branch 2 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4774 times.
4783 if (replace_variables(mysh) || check_tilde(mysh))
150 9 return;
151 4774 analyse_multi_commands(mysh, mysh->line);
152 }
153