From: Lukas Jiriste Date: Sat, 31 Aug 2024 16:38:12 +0000 (+0200) Subject: Make most functions in execution.c Normal X-Git-Url: https://git.ljiriste.work/?a=commitdiff_plain;h=6e19df7b026f68a79c5c1d6551d80034232df553;p=42%2Fminishell.git 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. --- 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);