Line data Source code
1 : #include "utils.h"
2 :
3 1064 : void free_if_needed(void *to_free)
4 : {
5 1064 : if (to_free != NULL)
6 1019 : free(to_free);
7 1064 : }
8 :
9 246 : void free_command_node(command_node_t *node)
10 : {
11 246 : if (node == NULL)
12 142 : return;
13 :
14 104 : if (node->args != NULL)
15 : {
16 212 : for (int i = 0; i < MAX_ARGS && node->args[i] != NULL; i++)
17 : {
18 108 : free_if_needed(node->args[i]);
19 108 : node->args[i] = NULL;
20 : }
21 104 : free_if_needed(node->args);
22 104 : node->args = NULL;
23 : }
24 104 : free_command_node(node->left);
25 104 : free_command_node(node->right);
26 104 : free_if_needed(node);
27 : }
28 :
29 13 : int safe_open(const char *path, int flags, mode_t mode)
30 : {
31 13 : int fd = open(path, flags, mode);
32 13 : if (fd < 0)
33 : {
34 2 : print_error("[ERROR] open() failed");
35 2 : exit(EXIT_FAILURE);
36 : }
37 11 : return fd;
38 : }
39 :
40 61 : void safe_close(int fd)
41 : {
42 61 : int ret = close(fd);
43 61 : if (ret < 0)
44 : {
45 1 : print_error("[ERROR] close() failed");
46 1 : exit(EXIT_FAILURE);
47 : }
48 60 : }
49 :
50 10 : int is_all_space(const char *str)
51 : {
52 20 : while (*str)
53 : {
54 17 : if (!isspace(*str))
55 7 : return 0;
56 10 : str++;
57 : }
58 3 : return 1;
59 : }
60 :
61 8 : void add_history_entry(const char *entry)
62 : {
63 8 : if (entry == NULL || is_all_space(entry))
64 3 : return;
65 :
66 5 : char *home = getenv(HOME_ENV_VAR);
67 5 : if (home == NULL)
68 : {
69 1 : print_error("[ERROR] HOME environment variable not set");
70 1 : return;
71 : }
72 :
73 4 : char *history_file = malloc(strlen(home) + strlen(HISTORY_FILE) + 2);
74 4 : if (history_file == NULL)
75 : {
76 0 : errno = ENOMEM;
77 0 : print_error("[ERROR] Failed to allocate memory for history file path");
78 0 : return;
79 : }
80 :
81 4 : sprintf(history_file, "%s/%s", home, HISTORY_FILE);
82 4 : int history_fd = safe_open(history_file, O_WRONLY | O_CREAT | O_APPEND, 0644);
83 :
84 4 : print_generic(history_fd, "%s\n", entry);
85 4 : safe_close(history_fd);
86 4 : free_if_needed(history_file);
87 : }
88 :
89 34 : char *get_env_var(const char *token)
90 : {
91 34 : if (token[0] == DOLLAR_SIGN)
92 : {
93 33 : const char *env_name = token + 1;
94 33 : const char *env_value = getenv(env_name);
95 33 : if (env_value != NULL)
96 : {
97 27 : return strdup(env_value);
98 : }
99 :
100 6 : return strdup("");
101 : }
102 :
103 1 : return NULL;
104 : }
105 :
106 30 : int get_var_values(const char *token, char *name, char *value)
107 : {
108 30 : char *equal_sign = strchr(token, EQUAL_SIGN);
109 30 : if (!equal_sign)
110 1 : return -1;
111 :
112 29 : size_t name_len = equal_sign - token;
113 29 : char *processed_name = strndup(token, name_len);
114 :
115 29 : if (!processed_name)
116 0 : return -1;
117 :
118 29 : const char *current_value = equal_sign + 1;
119 29 : char *processed_value = NULL;
120 : size_t value_len;
121 :
122 30 : while (isspace(*current_value))
123 1 : current_value++;
124 :
125 29 : if (*current_value == DOUBLE_QUOTES || *current_value == SINGLE_QUOTE)
126 22 : {
127 22 : char quote_char = *current_value;
128 22 : current_value++;
129 22 : const char *end_quote = strchr(current_value, quote_char);
130 :
131 22 : if (end_quote)
132 : {
133 1 : value_len = end_quote - current_value;
134 1 : processed_value = strndup(current_value, value_len);
135 : }
136 : else
137 : {
138 21 : processed_value = strdup(current_value);
139 : }
140 : }
141 : else
142 : {
143 7 : processed_value = strdup(current_value);
144 : }
145 :
146 29 : if (!processed_value)
147 : {
148 0 : free_if_needed(processed_name);
149 0 : return -1;
150 : }
151 :
152 29 : strcpy(name, processed_name);
153 29 : strcpy(value, processed_value);
154 :
155 29 : free_if_needed(processed_name);
156 29 : free_if_needed(processed_value);
157 :
158 29 : return 0;
159 : }
160 :
161 18 : int set_env_var(const char *token)
162 : {
163 : // Get values from get_var_values
164 : char name[MAX_INPUT_LENGTH];
165 : char value[MAX_INPUT_LENGTH];
166 18 : int ret = get_var_values(token, name, value);
167 18 : if (ret < 0)
168 1 : return ret;
169 :
170 17 : ret = setenv(name, value, 1);
171 :
172 17 : return ret;
173 : }
174 :
175 19 : const char *get_operator_str(operator_t op_type)
176 : {
177 19 : switch (op_type)
178 : {
179 6 : case OP_NONE:
180 6 : return "NONE";
181 3 : case OP_PIPE:
182 3 : return "PIPE";
183 1 : case OP_SEQ:
184 1 : return "SEQ";
185 2 : case OP_AND:
186 2 : return "AND";
187 1 : case OP_OR:
188 1 : return "OR";
189 1 : case OP_BG:
190 1 : return "BG";
191 1 : case OP_REDIR_OUT:
192 1 : return "REDIR_OUT";
193 1 : case OP_REDIR_IN:
194 1 : return "REDIR_IN";
195 1 : case OP_APPEND:
196 1 : return "APPEND";
197 1 : case OP_HEREDOC:
198 1 : return "HEREDOC";
199 1 : default:
200 1 : return "UNKNOWN";
201 : }
202 : }
203 :
204 9 : void print_command_tree(command_node_t *node, int depth)
205 : {
206 9 : if (!node)
207 1 : return;
208 :
209 8 : print("%s", CYAN_COLOR);
210 :
211 8 : if(depth == 0)
212 4 : print("Root: ");
213 :
214 8 : print("OP=%s%s%s, args=[%s", YELLOW_COLOR, get_operator_str(node->op_type), CYAN_COLOR, YELLOW_COLOR);
215 :
216 8 : if (node->args)
217 : {
218 18 : for (int i = 0; node->args[i] != NULL; i++)
219 10 : print("%s%s", i > 0 ? CYAN_COLOR "," YELLOW_COLOR " " : "", node->args[i] ? node->args[i] : "NULL");
220 : }
221 8 : print("%s]%s\n", CYAN_COLOR, RESET_COLOR);
222 :
223 8 : if (node->left)
224 : {
225 2 : print("%s", CYAN_COLOR);
226 5 : for (int i = 0; i <= depth; i++)
227 : {
228 3 : if(i == depth)
229 2 : print("|-- ");
230 : else
231 1 : print("| ");
232 : }
233 :
234 2 : print("Left: ");
235 2 : print_command_tree(node->left, depth + 1);
236 : }
237 :
238 8 : if (node->right)
239 : {
240 2 : print("%s", CYAN_COLOR);
241 5 : for (int i = 0; i <= depth; i++)
242 : {
243 3 : if(i == depth)
244 2 : print("|-- ");
245 : else
246 1 : print("| ");
247 : }
248 :
249 2 : print("Right: ");
250 2 : print_command_tree(node->right, depth + 1);
251 : }
252 : }
|