/* By: lnikolov <lnikolov@student.42prague.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/07/21 08:57:54 by ljiriste #+# #+# */
-/* Updated: 2024/08/31 12:43:50 by lnikolov ### ########.fr */
+/* Updated: 2024/08/31 18:35:42 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
return (0);
}
+static void handle_fds(int *fd, int *sec_fd, const char *filename,
+ const t_parse_tree_node *operator)
+{
+ if (*fd < 0)
+ {
+ if (is_token_type(operator, "LESS"))
+ *fd = STDIN_FILENO;
+ else
+ *fd = STDOUT_FILENO;
+ }
+ if (is_token_type(operator, "LESS"))
+ *sec_fd = open(filename, O_RDONLY);
+ else if (is_token_type(operator, "GREAT"))
+ *sec_fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC,
+ S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+ else
+ *sec_fd = open(filename, O_CREAT | O_WRONLY | O_APPEND,
+ S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+ return ;
+}
+
int add_redirection_file(t_vec *redirections,
t_parse_tree_node *io_file, int fd, t_execution_env *env)
{
return (1);
expand_filename(&filename, env);
operator = ft_vec_caccess(&io_file->children, 0);
- if (is_token_type(operator, "LESS"))
+ handle_fds(&fd, &sec_fd, filename, operator);
+ if (sec_fd < 0)
{
- if (fd == -1)
- fd = STDIN_FILENO;
- sec_fd = open(filename, O_RDONLY);
- if (sec_fd < 0)
- {
- free(filename);
- env->ret_val = 1;
- return (1);
- }
- redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = sec_fd};
- }
- else
- {
- if (fd < 0)
- fd = STDOUT_FILENO;
- if (is_token_type(operator, "GREAT"))
- sec_fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC,
- S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
- else
- sec_fd = open(filename, O_CREAT | O_WRONLY | O_APPEND,
- S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
- if (sec_fd == -1)
- {
- free(filename);
- return (1);
- }
- redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = sec_fd};
+ free(filename);
+ env->ret_val = 1;
+ return (1);
}
+ redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = sec_fd};
free(filename);
return (ft_vec_append(redirections, &redir) != success);
}
-int write_line_to_pipe(int pipe_fd, const char *line,
+static int write_line_to_pipe(int pipe_fd, const char *line,
const t_execution_env *env, int expand)
{
size_t i;
return (0);
}
-char *unquote_delimiter(const char *str)
+/*
+static char *unquote_delimiter(const char *str)
{
size_t i;
char *res;
}
return (res);
}
+*/
+
+static char *here_file_getline(void)
+{
+ ft_printf("> ");
+ return (get_next_line(STDIN_FILENO));
+}
-int here_file_to_pipe(int pipe_fd, const char *delimiter,
+// In case of an error the pipe_fd is repurposed to indicate the error.
+// This is done to save a few lines
+int here_file_to_pipe(int pipe_fd, char *delimiter,
const t_execution_env *env)
{
int expand;
char *line;
- char *unquoted_delimiter;
- unquoted_delimiter = unquote_delimiter(delimiter);
- if (!unquoted_delimiter)
- return (1);
- expand = !ft_strcmp(unquoted_delimiter, delimiter);
- ft_printf("> ");
- line = get_next_line(STDIN_FILENO);
- while (line && ft_strncmp(line, unquoted_delimiter, ft_strlen(line) - 1))
+ expand = !unquote_field(delimiter);
+ line = here_file_getline();
+ while (line && ft_strncmp(line, delimiter, ft_strlen(line) - 1))
{
if (write_line_to_pipe(pipe_fd, line, env, expand))
{
- get_next_line(-1);
- free(line);
- free(unquoted_delimiter);
- return (1);
+ pipe_fd = -1;
+ break ;
}
free(line);
- ft_printf("> ");
- line = get_next_line(STDIN_FILENO);
+ line = here_file_getline();
}
if (!line)
ft_printf
- ("minishell: warning: here-document delimited by EOF instead of %s!\n",
- unquoted_delimiter);
+ ("minishell: warning: here-document delimited by EOF instead of %s\n",
+ delimiter);
get_next_line(-1);
free(line);
- free(unquoted_delimiter);
- return (0);
+ return (pipe_fd == -1);
}
int add_redirection_here(t_vec *redirections,
return (0);
}
-static const char space = ' ';
+static char *get_value(const char *word, size_t *i, const t_execution_env *env)
+{
+ char *var;
+ char *value;
+ const char *const_val;
+
+ if (word[*i] == '?')
+ {
+ ++*i;
+ value = ft_itoa(env->ret_val);
+ }
+ else
+ {
+ var = get_var_name(word + *i);
+ if (!var)
+ return (NULL);
+ *i += ft_strlen(var);
+ const_val = get_env_var_value(env, var);
+ free(var);
+ if (!const_val)
+ return (ft_strdup(""));
+ value = ft_strdup(const_val);
+ }
+ return (value);
+}
+
+static int append_value(t_vec *exp_str, const char *value, int enquote_result)
+{
+ int error;
+
+ if (enquote_result)
+ {
+ error = ft_vec_append(exp_str, "'") != success;
+ error = error
+ || ft_vec_append_range(exp_str, value, ft_strlen(value)) != success;
+ error = error || ft_vec_append(exp_str, "'") != success;
+ return (error);
+ }
+ return (ft_vec_append_range(exp_str, value, ft_strlen(value)) != success);
+}
+
+// Returns 1 when quote is set (or unset)
+// and 0 when quote is left in current state
+int set_quote(char *quote, char c)
+{
+ if (c == '"' || c == '\'')
+ {
+ if (*quote == '\0')
+ *quote = c;
+ else if (*quote == c)
+ *quote = '\0';
+ else
+ return (0);
+ return (1);
+ }
+ return (0);
+}
int add_word(t_vec *exp_str, const char *word,
const t_execution_env *env, int enquote_result)
{
size_t i;
- char *var;
- char *value;
- const char *const_val;
char quote;
- int error;
+ const char space = ' ';
+ char *value;
- error = 0;
quote = '\0';
i = 0;
while (word[i])
{
- if (word[i] == '\'' && quote != '"')
- quote = '\'' * !quote;
- else if (word[i] == '"' && quote != '\'')
- quote = '"' * !quote;
+ set_quote("e, word[i]);
if (word[i] == '$' && quote != '\'' && (ft_isalnum(word[i + 1])
|| word[i + 1] == '_' || word[i + 1] == '?'))
{
++i;
- if (word[i] == '?')
- {
- ++i;
- value = ft_itoa(env->ret_val);
- }
- else
- {
- var = get_var_name(word + i);
- if (!var)
- return (1);
- i += ft_strlen(var);
- const_val = get_env_var_value(env, var);
- free(var);
- if (!const_val)
- continue ;
- value = ft_strdup(const_val);
- }
+ value = get_value(word, &i, env);
if (!value)
return (1);
- if (enquote_result)
- error = error || ft_vec_append(exp_str, "'") != success;
- error = error || ft_vec_append_range(exp_str,
- value, ft_strlen(value)) != success;
- if (enquote_result)
- error = error || ft_vec_append(exp_str, "'") != success;
- free(value);
- if (error)
+ if (append_value(exp_str, value, enquote_result))
+ {
+ free(value);
return (1);
+ }
+ free(value);
}
else
if (ft_vec_append(exp_str, word + (i++)) != success)
{
if (str[n] == ' ' && !quote)
break ;
- if ((str[n] == '"' || str[n] == '\''))
- {
- if (!quote)
- quote = str[n];
- else if (quote == str[n])
- quote = 0;
- }
+ set_quote("e, str[n]);
++n;
}
return (n);
}
-void unquote_field(char *field)
+// Returns 1 if any unquoting happened else returns 0
+int unquote_field(char *field)
{
+ int res;
size_t i;
char quote;
+ res = 0;
quote = 0;
i = 0;
while (field && field[i])
{
if (field[i] == '"' || field[i] == '\'')
{
- if (!quote)
- quote = field[i];
- else if (quote == field[i])
- quote = 0;
- else
+ if (!set_quote("e, field[i]))
{
++i;
continue ;
}
+ res = 1;
ft_memmove(field + i, field + i + 1, ft_strlen(field + i + 1) + 1);
}
else
++i;
}
- return ;
+ return (res);
}
void unquote(char **fields)
return ;
}
-static const void *nullptr = NULL;
-
-char **quoted_split(const char *str)
+int process_word(const char *str, t_vec *fields, size_t *i)
{
- size_t i;
size_t n;
- t_vec fields;
char *new_str;
+ while (str[*i] == ' ')
+ ++*i;
+ n = get_next_word_size(str + *i);
+ if (n == 0)
+ return (0);
+ new_str = ft_strndup(str + *i, n);
+ if (!new_str)
+ return (1);
+ if (ft_vec_append(fields, &new_str) != success)
+ {
+ free(new_str);
+ return (1);
+ }
+ *i += n;
+ return (0);
+}
+
+char **quoted_split(const char *str)
+{
+ size_t i;
+ t_vec fields;
+ const void *g_nullptr = NULL;
+
if (ft_vec_init(&fields, sizeof(char *)) != success)
return (NULL);
i = 0;
while (str[i])
{
- while (str[i] == ' ')
- ++i;
- n = get_next_word_size(str + i);
- if (n == 0)
- break ;
- new_str = ft_strndup(str + i, n);
- if (!new_str)
+ if (process_word(str, &fields, &i))
{
ft_vec_free(&fields, free);
return (NULL);
}
- if (ft_vec_append(&fields, &new_str) != success)
- {
- ft_vec_free(&fields, free);
- free(new_str);
- return (NULL);
- }
- i += n;
}
- if (ft_vec_append(&fields, &nullptr) != success)
+ if (ft_vec_append(&fields, &g_nullptr) != success)
{
ft_vec_free(&fields, free);
return (NULL);
return (fields.vec);
}
-static const char null_char = '\0';
+int expand_child(t_parse_tree_node *subnode,
+ t_vec *expanded_str, const t_execution_env *env)
+{
+ if ((is_token_type(subnode, "cmd_name")
+ || is_token_type(subnode, "cmd_word")
+ || is_token_type(subnode, "cmd_suffix"))
+ && expand_cmd(expanded_str, subnode, env))
+ return (1);
+ return (0);
+}
char **expand(t_parse_tree_node *simple_command, const t_execution_env *env)
{
- size_t i;
- char **fields;
- t_vec expanded_str;
- t_parse_tree_node *subnode;
+ const char g_null_char = '\0';
+ size_t i;
+ char **fields;
+ t_vec expanded_str;
ft_vec_init(&expanded_str, sizeof(char));
- ft_vec_reserve(&expanded_str, 64);
i = 0;
while (i < simple_command->children.size)
{
- subnode = ft_vec_access(&simple_command->children, i);
- if ((is_token_type(subnode, "cmd_name")
- || is_token_type(subnode, "cmd_word")
- || is_token_type(subnode, "cmd_suffix"))
- && expand_cmd(&expanded_str, subnode, env))
+ if (expand_child(ft_vec_access(&simple_command->children, i++),
+ &expanded_str, env))
{
ft_vec_free(&expanded_str, NULL);
return (NULL);
}
- ++i;
}
- if (ft_vec_append(&expanded_str, &null_char) != success)
+ if (ft_vec_append(&expanded_str, &g_null_char) != success)
{
ft_vec_free(&expanded_str, NULL);
return (NULL);
{
size_t i;
+ if (!fields)
+ return ;
i = 0;
while (fields[i])
{
return ;
}
-int add_exported(__attribute__((unused))
- t_vec *assignments, __attribute__((unused)) const t_execution_env *env)
+int add_exported(t_vec *assignments, const t_execution_env *env)
{
size_t i;
char *var;
dup_pipes(env);
dup_redirections(redirections);
if (!ft_strcmp(fields[0], "cd"))
- env->last_builtin_ret_val = cd(count_fields(fields), fields, env);
+ env->builtin_ret_val = cd(count_fields(fields), fields, env);
else if (!ft_strcmp(fields[0], "echo"))
- env->last_builtin_ret_val = echo(count_fields(fields), fields);
+ env->builtin_ret_val = echo(count_fields(fields), fields);
else if (!ft_strcmp(fields[0], "pwd"))
- env->last_builtin_ret_val = pwd();
+ env->builtin_ret_val = pwd();
else if (!ft_strcmp(fields[0], "env"))
- env->last_builtin_ret_val = ft_env(count_fields(fields), env);
+ env->builtin_ret_val = ft_env(count_fields(fields), env);
else if (!ft_strcmp(fields[0], "export"))
- env->last_builtin_ret_val = export(count_fields(fields), fields, env);
+ env->builtin_ret_val = export(count_fields(fields), fields, env);
else if (!ft_strcmp(fields[0], "unset"))
- env->last_builtin_ret_val = unset(count_fields(fields), fields, env);
+ env->builtin_ret_val = unset(count_fields(fields), fields, env);
else if (!ft_strcmp(fields[0], "exit"))
- env->last_builtin_ret_val = execute_exit(count_fields(fields),
- fields, env);
+ env->builtin_ret_val = execute_exit(count_fields(fields), fields, env);
else
return (1);
- env->last_was_builtin = 1;
close_redirections(redirections);
close_pipes(env);
restore_std_filenos(fds);
return ;
}
+char *get_path(const char *cmd, t_execution_env *env)
+{
+ char *path;
+
+ path = NULL;
+ if (contains_path(cmd) && file_exists(cmd))
+ path = ft_strdup(cmd);
+ else if (!contains_path(cmd))
+ path = find_exe(cmd, env);
+ if (!path)
+ env->ret_val = 127;
+ return (path);
+}
+
+int prepare_env(t_execution_env *env,
+ const t_vec *redirections, t_vec *assignments)
+{
+ int res;
+
+ close_fds(&env->fds_to_close);
+ res = dup_pipes(env);
+ res = dup_redirections(redirections) || res;
+ res = add_exported(assignments, env) || res;
+ return (res);
+}
+
int ex_fields(char **fields, t_vec *assignments,
const t_vec *redirections, t_execution_env *env)
{
pid_t pid;
char *path;
- if (is_builtin(fields[0]))
+ env->last_was_builtin = is_builtin(fields[0]);
+ if (env->last_was_builtin)
return (ex_builtin(fields, assignments, redirections, env));
- env->last_was_builtin = 0;
- path = NULL;
- if (contains_path(fields[0]) && file_exists(fields[0]))
- path = ft_strdup(fields[0]);
- else if (!contains_path(fields[0]))
- path = find_exe(fields[0], env);
+ path = get_path(fields[0], env);
if (!path)
- {
- env->ret_val = 127;
return (1);
- }
pid = fork();
if (pid == 0)
{
- close_fds(&env->fds_to_close);
- dup_pipes(env);
- dup_redirections(redirections);
- add_exported(assignments, env);
- ft_vec_append(assignments, nullptr);
- execve(path, fields, assignments->vec);
+ if (prepare_env(env, redirections, assignments) == 0)
+ execve(path, fields, assignments->vec);
exit(-1);
}
free(path);
- if (pid > 0)
+ if (pid < 0)
+ return (1);
+ if (ft_vec_append(&env->child_pids, &pid) != success)
{
- if (ft_vec_append(&env->child_pids, &pid) != success)
- return (1);
- }
- else
+ kill(pid, SIGTERM);
return (1);
+ }
return (0);
}
if (!res)
fields = expand(simple_command, env);
if (!fields || res)
- {
- ft_vec_free(&redirections, close_redirection);
- ft_vec_free(&assignments, free);
- return (1);
- }
- if (!*fields)
- {
- assignments_to_env(&assignments, env);
- ft_vec_free(&redirections, close_redirection);
- ft_vec_free(&assignments, free_str);
- free_split(fields);
- return (0);
- }
- res = ex_fields(fields, &assignments, &redirections, env);
+ res = 1;
+ else if (!*fields)
+ res = assignments_to_env(&assignments, env);
+ else
+ res = ex_fields(fields, &assignments, &redirections, env);
+ free_split(fields);
ft_vec_free(&redirections, close_redirection);
ft_vec_free(&assignments, free_str);
- free_split(fields);
return (res);
}
int status;
if (env->last_was_builtin)
- env->ret_val = env->last_builtin_ret_val;
+ env->ret_val = env->builtin_ret_val;
else
{
if (env->child_pids.size == 0)
return ;
}
-int ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth)
+int ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth);
+
+int advance_pipeline(t_parse_tree_node *pipeline,
+ t_execution_env *env, int depth)
{
int pipe_fds[2];
+ int res;
+ if (pipe(pipe_fds))
+ return (1);
+ res = ft_vec_append(&env->fds_to_close, &pipe_fds[0]);
+ res = res || ft_vec_append(&env->fds_to_close, &env->stdout_fd);
+ ft_swap_int(&pipe_fds[1], &env->stdout_fd);
+ res = res
+ || ex_pipeline(ft_vec_access(&pipeline->children, 0), env, depth + 1);
+ ft_swap_int(&pipe_fds[1], &env->stdout_fd);
+ close(pipe_fds[1]);
+ if (res == 0)
+ {
+ ft_vec_forget(&env->fds_to_close, env->fds_to_close.size - 1);
+ ft_vec_forget(&env->fds_to_close, env->fds_to_close.size - 1);
+ }
+ ft_swap_int(&pipe_fds[0], &env->stdin_fd);
+ res = res || ex_command(ft_vec_access(&pipeline->children, 2), env);
+ ft_swap_int(&pipe_fds[0], &env->stdin_fd);
+ close(pipe_fds[0]);
+ return (res);
+}
+
+int ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth)
+{
if (g_last_signal != 0)
return (0);
if (pipeline->children.size == 1)
}
else
{
- if (pipe(pipe_fds))
+ if (advance_pipeline(pipeline, env, depth))
+ {
+ killall(&env->child_pids, SIGTERM);
return (1);
- ft_vec_append(&env->fds_to_close, &pipe_fds[0]);
- ft_vec_append(&env->fds_to_close, &env->stdout_fd);
- ft_swap_int(&pipe_fds[1], &env->stdout_fd);
- ex_pipeline(ft_vec_access(&pipeline->children, 0), env, depth + 1);
- ft_swap_int(&pipe_fds[1], &env->stdout_fd);
- close(pipe_fds[1]);
- ft_vec_forget(&env->fds_to_close, env->fds_to_close.size - 1);
- ft_vec_forget(&env->fds_to_close, env->fds_to_close.size - 1);
- ft_swap_int(&pipe_fds[0], &env->stdin_fd);
- ex_command(ft_vec_access(&pipeline->children, 2), env);
- ft_swap_int(&pipe_fds[0], &env->stdin_fd);
- close(pipe_fds[0]);
+ }
}
if (depth == 0)
wait_for_return(env);