From 6e19df7b026f68a79c5c1d6551d80034232df553 Mon Sep 17 00:00:00 2001 From: Lukas Jiriste Date: Sat, 31 Aug 2024 18:38:12 +0200 Subject: [PATCH] Make most functions in execution.c Normal All but one function were rewritten to comply with the 42 Norm. Some small obvious bugs were also fixed as to not be forgotten. --- inc/minishell.h | 4 +- inc/minishell_structs.h | 4 +- src/execution.c | 446 +++++++++++++++++++++++----------------- 3 files changed, 256 insertions(+), 198 deletions(-) diff --git a/inc/minishell.h b/inc/minishell.h index 7a3369c..f612698 100644 --- a/inc/minishell.h +++ b/inc/minishell.h @@ -6,7 +6,7 @@ /* By: lnikolov 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; @@ -208,7 +207,8 @@ int write_line_to_pipe(int pipe_fd, const char *line, return (0); } -char *unquote_delimiter(const char *str) +/* +static char *unquote_delimiter(const char *str) { size_t i; char *res; @@ -240,41 +240,41 @@ char *unquote_delimiter(const char *str) } 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, @@ -369,59 +369,90 @@ int save_redirections(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) @@ -466,44 +497,38 @@ size_t get_next_word_size(const char *str) { 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) @@ -519,40 +544,46 @@ 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); @@ -560,32 +591,36 @@ char **quoted_split(const char *str) 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); @@ -625,6 +660,8 @@ void free_split(char **fields) { size_t i; + if (!fields) + return ; i = 0; while (fields[i]) { @@ -745,8 +782,7 @@ void close_redirections(const t_vec *redirections) 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; @@ -838,23 +874,21 @@ int ex_builtin(char **fields, __attribute__((unused)) 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); @@ -876,44 +910,59 @@ void close_fds(t_vec *fds_to_close) 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); } @@ -939,23 +988,14 @@ int ex_simple_command(t_parse_tree_node *simple_command, t_execution_env *env) 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); } @@ -1070,7 +1110,7 @@ void wait_for_return(t_execution_env *env) 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) @@ -1088,10 +1128,37 @@ void wait_for_return(t_execution_env *env) 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) @@ -1101,20 +1168,11 @@ int ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth) } 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); -- 2.30.2