-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path5_execute_ast.c
More file actions
146 lines (138 loc) · 4.34 KB
/
5_execute_ast.c
File metadata and controls
146 lines (138 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 5_execute_ast.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: astein <astein@student.42lisboa.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/06 18:19:44 by astein #+# #+# */
/* Updated: 2024/01/07 22:02:57 by astein ### ########.fr */
/* */
/* ************************************************************************** */
/**
* @brief This file is the starting point of the execution. It calls all the
* functions needed to setup redirections, pipes and the execution of
* the commands.
*
* DOCUMENATION:
* https://github.com/ahokcool/frankenshell/docs/documentation.md#executing
*/
#include "frankenshell.h"
/**
* @brief Before we start to execute we need to allocate the pid array so we
* can store the pids of all the child processes. The array is used in
* 'wait_for_execution' to wait for all the child processes to be
* finished
*
* @param mbox
* @return t_bool
*/
static t_bool allocate_pid_array(t_mbox *mbox)
{
mbox->exec.pid = ft_calloc(cmd_counter(mbox->ast), sizeof(int));
if (!mbox->exec.pid)
return (ft_false);
return (ft_true);
}
/**
* @brief called by 'execute_ast' after all the child processes have been
* forked. This function uses the pid array in which all the child
* processes pids are stored. It uses the pid array to wait for all
* the child processes to be finished. It also updates the exit status.
*
* @param mbox
*/
static void wait_for_execution(t_mbox *mbox)
{
int i;
int exit_status;
i = -1;
exit_status = 0;
if (mbox->exec.pid_index != 0)
{
while (++i < cmd_counter(mbox->ast))
waitpid(mbox->exec.pid[i], &exit_status, 0);
if (g_signal_status == 0)
{
if (WIFEXITED(exit_status))
set_var_value_int(mbox, "?", WEXITSTATUS(exit_status));
else if (WIFSIGNALED(exit_status))
set_var_value_int(mbox, "?", exit_status + 128);
}
}
}
/**
* @brief traverses trough the AST.
*
* (SINGLE_CMD)
* If the root is an cmd, no pipe is needed and the function call
* 'setup_cmd' with the corresponding flag will process the cmd.
*
* If the root is a pipe node the function will:
* - (FIRST_CMD) once:
* - call the function 'setup_cmd' with the corresponding flag for
* the first cmd in the expression.
* - (MIDDLE_CMD) until the second last cmd is reached:
* - call the function 'setup_cmd' with the corresponding flag for
* the middle cmd in the expression.
* - (LAST_CMD) once:
* - call the function 'setup_cmd' with the corresponding flag for
* the last cmd in the expression.
*
* In any case the function 'wait_for_execution' will be called to wait
* for all the child processes to be finished.
*
* EXAMPLES:
*
* FLAG: SINGLE_CMD FIRST_CMD MIDDLE_CMD LAST_CMD
* INPUT: ls -l
* INPUT: echo HI
* INPUT: ls -l | grep "Makefile" | wc -l
*
* DOCUMENATION:
* https://github.com/ahokcool/frankenshell/docs/documentation.md#executing
*
* @param mbox
*/
void execute_ast(t_mbox *mbox)
{
t_ast *cur;
info_print_executor_banner(mbox, ft_true, GREEN);
if (!allocate_pid_array(mbox))
return ;
cur = mbox->ast;
if (cur->type == CMD_NODE)
{
if (!setup_cmd(mbox, cur, SINGLE_CMD))
return ;
}
else
{
if (!setup_cmd(mbox, cur->left, FIRST_CMD))
return ;
while (cur->right->type == PIPE_NODE)
{
cur = cur->right;
if (!setup_cmd(mbox, cur->left, MIDDLE_CMD))
return ;
}
if (!setup_cmd(mbox, cur->right, LAST_CMD))
return ;
}
wait_for_execution(mbox);
info_print_executor_banner(mbox, ft_false, GREEN);
}
/**
* @brief called by 'reset_cycle' to free pid array which was allocated
* via 'allocate_pid_array'
*
* @param mbox
*/
void free_process(t_mbox *mbox)
{
if (mbox->exec.pid)
{
free (mbox->exec.pid);
mbox->exec.pid = NULL;
}
}