diff --git a/README.md b/README.md index 62423c1..6274ed0 100755 --- a/README.md +++ b/README.md @@ -2,17 +2,15 @@ --- ## TODO : -- free stack, -- protect mallocs, -- Norminette -- Finish check_builtin(); +- Protect mallocs, +- verify exits codes + https://wiki.bash-hackers.org/scripting/basics?s[]=variables#exit_codes +- do the `(...)` -> `./minishell ...` conversion +- finish && and || -- export : edit datas->env -- unset : idem, -- exit: handle arguments - -- setup correct ext_codes - https://wiki.bash-hackers.org/scripting/basics?s[]=variables#exit_codes ## Issues : +- + +## Notes : diff --git a/built-in.c b/built-in.c index 683aa63..e8d82c8 100755 --- a/built-in.c +++ b/built-in.c @@ -6,7 +6,7 @@ /* By: narnaud +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/01/06 09:02:57 by narnaud #+# #+# */ -/* Updated: 2022/05/03 18:18:23 by narnaud ### ########.fr */ +/* Updated: 2022/05/07 23:17:15 by narnaud@stude ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,34 +14,45 @@ int ft_echo(t_command *cmd) { - int no_nl; + int no_nl; + int fd_out; + int i; + if (cmd->fd[1]) + fd_out = cmd->fd[1]; + else + fd_out = 1; no_nl = 0; - if (*(++cmd->argv)) + i = 1; + if (cmd->argv[1]) { - if (ft_strncmp(*(cmd->argv), "-n", 3) == 0 && cmd->argv++) + if (ft_strncmp(cmd->argv[1], "-n", 3) == 0 && i++) no_nl = 1; - while (*(cmd->argv)) + while (cmd->argv[i]) { - ft_putstr_fd(*(cmd->argv), 1); - if (*(++cmd->argv)) - ft_putstr_fd(" ", 1); + ft_putstr_fd(cmd->argv[i], fd_out); + if (cmd->argv[++i]) + ft_putstr_fd(" ", fd_out); } } if (!no_nl) - ft_putstr_fd("\n", 1); + ft_putstr_fd("\n", fd_out); return (0); } int ft_pwd(t_command *cmd) { char *dir; + int fd_out; - (void)cmd; + if (cmd->fd[1]) + fd_out = cmd->fd[1]; + else + fd_out = 1; dir = ft_calloc(PATHS_MAX_SIZE, sizeof(char)); getcwd(dir, PATHS_MAX_SIZE); - ft_putstr_fd(dir, 1); - ft_putstr_fd("\n", 1); + ft_putstr_fd(dir, fd_out); + ft_putstr_fd("\n", fd_out); free(dir); return (0); } @@ -51,26 +62,24 @@ int ft_cd(t_command *cmd) if (cmd->argv[1]) { if (access(cmd->argv[1], X_OK)) - { - printf("Minishell: %s: %s: Permission denied\n", cmd->argv[0], cmd->argv[1]); - return (0); - } + return (file_error(cmd->argv[0], cmd->argv[1], \ + "Permission denied\n")); else if (access(cmd->argv[1], F_OK)) - { - printf("Minishell: %s: %s: Not a directory\n", cmd->argv[0], cmd->argv[1]); - return (0); - } + return (file_error(cmd->argv[0], cmd->argv[1], \ + "Not a directory\n")); chdir(cmd->argv[1]); return (1); } else - { chdir(getenv("HOME")); - } return (0); } -int close_minishell(int exit_code) +int ft_exit(t_datas *datas, t_command *cmd) { - exit(exit_code); + if (cmd->argc > 1) + halt(datas, EXIT_SUCCESS); + else + halt(datas, ft_atoi(cmd->argv[1])); + return (1); } diff --git a/caller.c b/caller.c index a548b8a..9a50b26 100755 --- a/caller.c +++ b/caller.c @@ -3,16 +3,36 @@ /* ::: :::::::: */ /* caller.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: narnaud +#+ +:+ +#+ */ +/* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/03 11:48:16 by narnaud #+# #+# */ -/* Updated: 2022/05/05 09:40:42 by narnaud ### ########.fr */ +/* Updated: 2022/05/10 09:56:53 by mea ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -int command_call(t_datas *datas, t_command *cmd) +static void exe(t_datas *datas, t_command *cmd); +static pid_t caller(t_datas *datas, t_command *cmd); + +int is_builtin(char *cmd) +{ + int cmd_len; + + cmd_len = ft_strlen(cmd) + 1; + if (!ft_strncmp(cmd, "echo", ft_min(cmd_len, 5)) \ + || !ft_strncmp(cmd, "pwd", ft_min(cmd_len, 4)) \ + || !ft_strncmp(cmd, "cd", ft_min(cmd_len, 3)) \ + || !ft_strncmp(cmd, "export", ft_min(cmd_len, 7)) \ + || !ft_strncmp(cmd, "unset", ft_min(cmd_len, 6)) \ + || !ft_strncmp(cmd, "env", ft_min(cmd_len, 4)) \ + || !ft_strncmp(cmd, "exit", ft_min(cmd_len, 5))) + return (1); + else + return (0); +} + +int builtin_call(t_datas *datas, t_command *cmd) { if (ft_strncmp(cmd->argv[0], "echo", 5) == 0) return (ft_echo(cmd)); @@ -25,14 +45,39 @@ int command_call(t_datas *datas, t_command *cmd) else if (ft_strncmp(cmd->argv[0], "unset", 6) == 0) return (ft_unset(datas, cmd)); else if (ft_strncmp(cmd->argv[0], "env", 4) == 0) - return (ft_env(datas)); + return (ft_env(datas, cmd)); else if (ft_strncmp(cmd->argv[0], "exit", 5) == 0) - return (close_minishell(0)); + return (ft_exit(datas, cmd)); else return (-1); } -void exe(t_datas *datas, t_command *cmd) +int piper(t_datas *datas, t_command *cmd) +{ + int pip[2]; + int status; + pid_t pid; + + if (cmd->fd[1] == 0 && cmd->next && cmd->next->fd[0] == 0) + { + pipe(pip); + cmd->fd[1] = pip[1]; + cmd->next->fd[0] = pip[0]; + } + pid = caller(datas, cmd); + if (cmd->fd[1]) + close(cmd->fd[1]); + if (cmd->next) + piper(datas, cmd->next); + waitpid(pid, &status, 0); + if (!cmd->next) + handle_status(datas, status); + if (cmd->fd[0]) + close(cmd->fd[0]); + return (1); +} + +static void exe(t_datas *datas, t_command *cmd) { char **path_dirs; char *path; @@ -48,10 +93,32 @@ void exe(t_datas *datas, t_command *cmd) path_length = ft_strlen(*path_dirs) + ft_strlen(cmd->argv[0]) + 2; path = ft_calloc(path_length, sizeof(char)); ft_memcpy(path, *path_dirs, ft_strlen(*path_dirs)); - ft_memcpy(path + ft_strlen(*path_dirs),"/", 1); - ft_memcpy(path + ft_strlen(*path_dirs) + 1, cmd->argv[0], ft_strlen(cmd->argv[0])); + ft_memcpy(path + ft_strlen(*path_dirs), "/", 1); + ft_memcpy(path + ft_strlen(*path_dirs) + 1, \ + cmd->argv[0], ft_strlen(cmd->argv[0])); execve(path, cmd->argv, datas->envp); + free(path); path_dirs++; } } } + +static pid_t caller(t_datas *datas, t_command *cmd) +{ + pid_t pid; + + pid = fork(); + if (!pid) + { + if (builtin_call(datas, cmd) == -1) + { + if (cmd->fd[0]) + dup2(cmd->fd[0], STDIN_FILENO); + if (cmd->fd[1]) + dup2(cmd->fd[1], STDOUT_FILENO); + exe(datas, cmd); + } + exit(EXIT_SUCCESS); + } + return (pid); +} diff --git a/env.c b/env.c index 39eb825..65e6249 100755 --- a/env.c +++ b/env.c @@ -6,79 +6,138 @@ /* By: narnaud +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/02/16 09:41:29 by narnaud #+# #+# */ -/* Updated: 2022/05/05 09:30:51 by narnaud ### ########.fr */ +/* Updated: 2022/05/07 23:38:40 by narnaud@stude ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -int is_valid_identifier(char *ident) -{ - if (ft_isalpha(ident[0]) || ident[0] == '_') - { - while (*ident) - { - if (!ft_isalpha(*ident) && !ft_isdigit(*ident) && *ident != '_') - return (0); - ident++; - } - return (1); - } - return (0); -} +static void clean_env(t_datas *datas, int i); int ft_unset(t_datas *datas, t_command *cmd) { - (void)datas; - if (!cmd->argv[1]) - { - //read(input_fd, PIPE_MAX_SIZE); + char **env; + int i; + int j; + int name_len; + + if (cmd->argc < 2) return (1); + env = datas->envp; + i = 1; + while (i < cmd->argc && datas->envp[i - 1]) + { + name_len = ft_strlen(cmd->argv[i]); + j = 0; + while (datas->envp[j]) + { + env = ft_split(datas->envp[j], '='); + if (!ft_strncmp(cmd->argv[i], env[0], name_len + 1)) + clean_env(datas, j); + else if (++j) + ft_free_split(env); + } + i++; } return (0); } -int ft_env(t_datas *datas) +int ft_env(t_datas *datas, t_command *cmd) { - int i; + int i; + int fd_out; + if (cmd->fd[1]) + fd_out = cmd->fd[1]; + else + fd_out = 1; i = 0; while (datas->envp[i]) { - printf("%s\n", datas->envp[i]); + ft_putstr_fd(datas->envp[i], fd_out); + ft_putchar_fd('\n', fd_out); i++; } return (0); } +static int is_valid_identifier(char *ident); + int ft_export(t_datas *datas, t_command *cmd) { char **new; + int name_len; char **env; int i; i = 0; + if (cmd->argc < 2) + return (0); new = ft_split(cmd->argv[1], '='); + name_len = ft_strlen(new[0]); if (!is_valid_identifier(new[0])) - { - printf ("export: not an identifier: %s\n", new[0]); return (0); - } while (datas->envp[i]) { env = ft_split(datas->envp[i], '='); - if (!ft_strncmp(new[0], env[0], ft_strlen(new[0]) + 1)) - { - datas->envp[i] = cmd->argv[1]; - return (1); - } - i++; + if (!ft_strncmp(new[0], env[0], name_len + 1)) + datas->envp[i] = (free(datas->envp[i]), NULL); + else + i++; + ft_free_split(env); } - datas->envp[i] = cmd->argv[1]; - datas->envp[i + 1] = NULL; + ft_free_split(new); + datas->envp[i] = ft_strdup(cmd->argv[1]); return (1); } +static void clean_env(t_datas *datas, int i) +{ + int j; + free(datas->envp[i]); + datas->envp[i] = NULL; + i = 0; + j = 0; + while (i < ENVP_MAX_SIZE) + { + if (!datas->envp[i]) + { + j = 1; + while (!datas->envp[i + j] && (i + j) < ENVP_MAX_SIZE) + j++; + if (i + j == ENVP_MAX_SIZE) + return ; + datas->envp[i] = datas->envp[i + j]; + datas->envp[i + j] = NULL; + } + i++; + } +} +static int is_valid_identifier(char *ident) +{ + int i; + i = 0; + if (ft_isalpha(ident[0]) || ident[0] == '_') + { + while (ident[i]) + { + if (!ft_isalpha(ident[i]) && !ft_isdigit(ident[i]) \ + && ident[i] != '_') + { + ft_putstr_fd("export: not an identifier: ", 2); + ft_putstr_fd(ident, 2); + ft_putchar_fd('\n', 2); + return (0); + } + i++; + } + return (1); + } + ft_putstr_fd("export: not an identifier: ", 2); + ft_putstr_fd(ident, 2); + ft_putchar_fd('\n', 2); + return (0); +} diff --git a/lexer.c b/lexer.c index 5985ccc..896aa5b 100755 --- a/lexer.c +++ b/lexer.c @@ -6,15 +6,78 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/02 13:44:57 by narnaud #+# #+# */ -/* Updated: 2022/05/05 15:41:06 by mea ### ########.fr */ +/* Updated: 2022/05/10 10:12:58 by mea ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -int create_token(t_lexer *lex, char str[]) +static int check_state(t_lexer *lex, char **line); +static int create_token(t_lexer *lex, char str[]); +static int check_register(t_lexer *lex, char **line, char *tmp); + +t_token *lexer(t_datas *datas, char *line) +{ + t_lexer *lex; + t_token *ret; + char *tmp; + int tmp_i; + + lex = ft_calloc(1, sizeof(*lex)); + lex->state = ROOT_ST; + tmp = ft_calloc(STR_MAX_SIZE, sizeof(*tmp)); + tmp_i = 0; + while (*line) + { + if (check_state(lex, &line)) + continue ; + if (lex->state != S_QUOTE_ST && lex->deep == 0 && *line == '$') + tmp_i = replace_var(datas, &line, tmp, tmp_i); + else if (check_register(lex, &line, tmp)) + tmp_i = (ft_bzero(tmp, STR_MAX_SIZE), 0); + else + tmp[tmp_i++] = *(line++); + } + create_token(lex, tmp); + free(tmp); + ret = lex->tokens; + free(lex); + return (ret); +} + +static int check_state(t_lexer *lex, char **line) +{ + t_state new; + + new = OLD_ST; + if (**line == '"' && lex->state == D_QUOTE_ST) + new = ROOT_ST; + else if (**line == '"' && lex->state == ROOT_ST) + new = D_QUOTE_ST; + else if (**line == '\'' && lex->state == S_QUOTE_ST) + new = ROOT_ST; + else if (**line == '\'' && lex->state == ROOT_ST) + new = S_QUOTE_ST; + else if (**line == '(' && lex->state == ROOT_ST) + lex->deep++; + else if (**line == ')' && lex->state == ROOT_ST) + lex->deep--; + if (new) + { + lex->state = new; + if (lex->deep == 0) + { + (*line)++; + return (1); + } + } + return (0); +} + +static int create_token(t_lexer *lex, char str[]) { t_token *tok; + t_token *tmp; t_type type; type = lex->type; @@ -23,132 +86,68 @@ int create_token(t_lexer *lex, char str[]) else lex->type = WORD; lex->next_type = WORD; - if (!str[0]) + if (!str[0] && !lex->empty) return (0); - tok = lex->tokens; - if (!lex->tokens) - tok = ft_calloc(1, sizeof *tok); - else - { - while (tok->next) - tok = tok->next; - tok->next = ft_calloc(1, sizeof *tok); - tok = tok->next; - } + tok = ft_calloc(1, sizeof(*tok)); tok->type = type; - tok->value = strdup(str); - if (DEBUG) - printf("token value : %s - token type : %d\n", tok->value, type); - if (!lex->tokens) + tok->value = ft_strdup(str); + tmp = lex->tokens; + while (tmp && tmp->next) + tmp = tmp->next; + if (!tmp) lex->tokens = tok; + else + tmp->next = tok; + lex->empty = 0; return (1); } -int check_register(t_lexer *lex, char **line, char *tmp) +static int check_ope(t_lexer *lex, char **line, char *tmp) { - int spaces; - - if (lex->state != ROOT_ST) - return (0); - spaces = 0; - if (ft_isspace(**line)) - { - while (ft_isspace(**line)) - (*line)++; - spaces = 1; - } - if (**line == '>' && (*line)++) + if (!ft_strncmp(*line, "&&", 2)) { - if (**line == '>' && (*line)++) - lex->next_type = ADD; - else - lex->next_type = OUT; - return (create_token(lex, tmp)); + (*line) += 2; + lex->next_type = AND; + create_token(lex, tmp); + return (create_token(lex, "&&")); } - else if (**line == '<' && (*line)++) + if (!ft_strncmp(*line, "||", 2)) { - if (**line == '<' && (*line)++) - lex->next_type = HD; - else - lex->next_type = IN; - return (create_token(lex, tmp)); + (*line) += 2; + lex->next_type = OR; + create_token(lex, tmp); + return (create_token(lex, "||")); } - else if (**line == '|') + if (**line == '|') { (*line)++; lex->next_type = PIPE; create_token(lex, tmp); return (create_token(lex, "|")); } - if (!spaces || !*tmp) - return (0); - return (create_token(lex, tmp)); -} - -int replace_var(t_datas *datas, char **line, char *tmp, int tmp_i) -{ - int name_len; - int i; - char *var_name; - char *value; - char **env; - i = 1; - if ((*line)[1] == '?') - { - value = ft_itoa(datas->exit_code); - name_len = 2; - } - else - { - while (ft_isalpha((*line)[i]) || ft_isdigit((*line)[i]) || (*line)[i] == '_') - i++; - var_name = ft_substr(*line, 1, i - 1); - i = 0; - while (datas->envp[i]) - { - env = ft_split(datas->envp[i], '='); - if (!ft_strncmp(var_name, env[0], ft_strlen(var_name) + 1)) - break ; - i++; - } - if (!datas->envp[i]) - value = strdup(""); - else - value = env[1]; - name_len = ft_strlen(var_name); - } - i = 0; - while (value[i]) - tmp[tmp_i++] = value[i++]; - tmp[tmp_i] = 0; - *line += name_len + 1; - return (tmp_i); + return (0); } -int check_state(t_lexer *lex, char **line) +static int check_register(t_lexer *lex, char **line, char *tmp) { - t_state new; + int spaces; - new = OLD_ST; - if (**line == '"') + if (lex->state != ROOT_ST || lex->deep > 0) + return (0); + spaces = 0; + if (!*tmp && (*(*line - 1) == '"' || *(*line - 1) == '\'')) + lex->empty = 1; + if (ft_isspace(**line)) { - if (lex->state == D_QUOTE_ST) - new = ROOT_ST; - else if (lex->state == ROOT_ST) - new = D_QUOTE_ST; - } - else if (**line == '\'') - { - if (lex->state == S_QUOTE_ST) - new = ROOT_ST; - else if (lex->state == ROOT_ST) - new = S_QUOTE_ST; + while (ft_isspace(**line)) + (*line)++; + spaces = 1; } - if (new) - { - (*line)++; - lex->state = new; + if (set_redir(lex, line, '>') || set_redir(lex, line, '<')) + return (create_token(lex, tmp)); + if (check_ope(lex, line, tmp)) return (1); - } + if ((**line == '(' || spaces) && (*tmp || lex->empty)) + return (create_token(lex, tmp)); return (0); } diff --git a/minishell.c b/minishell.c index 067bfb3..c20df95 100755 --- a/minishell.c +++ b/minishell.c @@ -6,150 +6,85 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/02 12:14:09 by narnaud #+# #+# */ -/* Updated: 2022/05/05 16:28:15 by mea ### ########.fr */ +/* Updated: 2022/05/07 23:08:05 by narnaud@stude ### ########.fr */ /* */ /* ************************************************************************** */ -# include "minishell.h" +#include "minishell.h" -void handle_status(t_datas *datas, int status) +void termios(int ctl) { - if (WIFSIGNALED(status)) + struct termios termios_p; + int tty; + + tty = ttyslot(); + tcgetattr(tty, &termios_p); + if (ctl) { - datas->exit_code = 128 + WTERMSIG(status); - if (datas->exit_code == 131) - printf("Quit: 3\n"); + termios_p.c_lflag |= ECHOCTL; + signal(SIGINT, nothing); + signal(SIGQUIT, nothing); } else - datas->exit_code = WEXITSTATUS(status); -} - -int caller(t_datas *datas, t_command *cmd) -{ - pid_t pid; - int pip[2]; - int status; - - if (cmd->fd[1] == 0 && cmd->next && cmd->next->fd[0] == 0) { - pipe(pip); - cmd->fd[1] = pip[1]; - cmd->next->fd[0] = pip[0]; + termios_p.c_lflag &= ~(ECHOCTL); + signal(SIGINT, sigs_handler); + signal(SIGQUIT, sigs_handler); } - - if (!cmd->prev && !cmd->next && command_call(datas, cmd) != -1)//check_builtin(cmd->argv[0])) - return (1); - pid = fork(); - if (!pid) - { - if (cmd->fd[0]) - dup2(cmd->fd[0], STDIN_FILENO); - if (cmd->fd[1]) - dup2(cmd->fd[1], STDOUT_FILENO); - if (command_call(datas, cmd) == -1) - exe(datas, cmd); - exit(EXIT_SUCCESS); - } - if (cmd->fd[1]) - close(cmd->fd[1]); - if (cmd->next) - caller(datas, cmd->next); - waitpid(pid, &status, 0); - handle_status(datas, status); - if (cmd->fd[0]) - close(cmd->fd[0]); - return (1); + termios_p.c_cc[VQUIT] = ctl * 28; + tcsetattr(tty, TCSANOW, &termios_p); } -t_command *parser(t_datas *datas, t_token *tok, t_command *prev) +void free_cmd(t_command *cmd) { - int i; - t_command *cmd; + int i; - if (!tok) - return (NULL); - cmd = ft_calloc(1, sizeof(t_command)); - if (prev) - cmd->prev = prev; + if (!cmd) + return ; i = 0; - cmd->argv = ft_calloc(count_arguments(tok) + 1, sizeof(char *)); - while(tok && tok->type != PIPE) + while (cmd->argv[i]) { - if (tok->type) - update_redir(datas, cmd, tok); - else - cmd->argv[i++] = tok->value; - tok = tok->next; + free(cmd->argv[i]); + i++; } - if (DEBUG) - printf("######\n->cmd : %s, in_fd : %d, out_fd : %d\n", \ - cmd->argv[0], cmd->fd[0], cmd->fd[1]); - cmd->argv[i] = NULL; - if (tok && tok->type == PIPE) - cmd->next = parser(datas, tok->next, cmd); - return(cmd); + free(cmd->argv); + free_cmd(cmd->next); + free(cmd); } -t_token *lexer(t_datas *datas, char *line) +void prompt(t_datas *datas) { - t_lexer *lex; - char *tmp; - int tmp_i; + char *line; + t_command *cmd; - lex = ft_calloc(1, sizeof *lex); - lex->state = ROOT_ST; - tmp = ft_calloc(1024, sizeof *tmp); - tmp_i = 0; - while (*line) - { - if (check_state(lex, &line)) - continue; - if (lex->state != S_QUOTE_ST && *line == '$') - tmp_i = replace_var(datas, &line, tmp, tmp_i); - if (check_register(lex, &line, tmp)) - { - tmp_i = 0; - ft_bzero(tmp, 1024); - continue ; - } - tmp[tmp_i] = *line; - line++; - tmp_i++; - } - create_token(lex, tmp); - return (lex->tokens); + termios(0); + line = readline("$ "); + termios(1); + if (line == NULL) + halt(datas, EXIT_SUCCESS); + if (is_empty(line)) + return ; + cmd = parser(datas, lexer(datas, line), NULL); + if (!cmd->prev && !cmd->next && is_builtin(cmd->argv[0])) + builtin_call(datas, cmd); + else + piper(datas, cmd); + free_cmd(cmd); + add_history(line); } int main(int argc, char **argv, char **envp) { - t_datas datas; - char *line; - char **env_copy; - int i; + static t_datas datas; + static int i = 0; - env_copy = ft_calloc(1024, sizeof(char *)); - i = 0; - while (envp[i]) - { - env_copy[i] = ft_strdup(envp[i]); - i++; - } - datas.envp = env_copy; + datas.envp = ft_calloc(ENVP_MAX_SIZE, sizeof(char *)); + while (*envp) + datas.envp[i++] = ft_strdup(*(envp++)); datas.exit_code = 0; if (argc < 2) (void)argv; while (1) - { - termios(0); - line = readline("$ "); - termios(1); - if (line == NULL) - halt(EXIT_FAILURE); - if (is_empty(line)) - continue ; - caller(&datas, parser(&datas, lexer(&datas, line), NULL)); - add_history(line); - } - clear_history(); - return (EXIT_SUCCESS); + prompt(&datas); + halt(&datas, EXIT_SUCCESS); } diff --git a/minishell.h b/minishell.h index 45f03f3..079659d 100755 --- a/minishell.h +++ b/minishell.h @@ -6,16 +6,15 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/02 13:50:44 by narnaud #+# #+# */ -/* Updated: 2022/05/05 14:18:56 by mea ### ########.fr */ +/* Updated: 2022/05/10 10:20:04 by mea ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef MINISHELL_H # define MINISHELL_H -# define PIPE_MAX_SIZE 8192 +# define ENVP_MAX_SIZE 1024 +# define STR_MAX_SIZE 1024 # define PATHS_MAX_SIZE 126 -# define PROMPT_PREFIX 0 -# define DEBUG 0 # include "libft/libft.h" # include @@ -31,11 +30,11 @@ # include # include -typedef struct s_command +typedef struct s_command { char **argv; + int argc; int fd[2]; - char *heredoc; struct s_command *next; struct s_command *prev; } t_command; @@ -47,38 +46,47 @@ typedef struct s_datas } t_datas; // ----------------------------------Utils.c -int is_empty(char *line); -void halt(int ret_code); -void termios(int ctl); -void sigs_handler(int sig_num); +int is_empty(char *line); +void handle_status(t_datas *datas, int status); +void nothing(int sig_num); +void sigs_handler(int sig_num); +void halt(t_datas *datas, int ret_code); + +typedef struct s_lex t_lexer; +// ----------------------------------Utils_2.c +int file_error(char *cmd, char *file, char *msg); +int replace_var(t_datas *datas, char **line, char *tmp, int tmp_i); +char *expend_str(t_datas *datas, char *line); +int set_redir(t_lexer *lex, char **line, char ch); // ----------------------------------Builtins.c -int close_minishell(int exit_code); -int ft_echo(t_command *cmd); -int ft_pwd(t_command *cmd); -int ft_cd(t_command *cmd); +int ft_echo(t_command *cmd); +int ft_pwd(t_command *cmd); +int ft_cd(t_command *cmd); +int ft_exit(t_datas *datas, t_command *cmd); // ----------------------------------Env.c -int is_valid_identifier(char *ident); -int ft_unset(t_datas *datas, t_command *cmd); -int ft_env(t_datas *datas); -int ft_export(t_datas *datas, t_command *cmd); +int ft_unset(t_datas *datas, t_command *cmd); +int ft_env(t_datas *datas, t_command *cmd); +int ft_export(t_datas *datas, t_command *cmd); // ----------------------------------Caller.c -void exe(t_datas *datas, t_command *cmd); -int command_call(t_datas *datas, t_command *cmd); +int is_builtin(char *cmd); +int builtin_call(t_datas *datas, t_command *cmd); +int piper(t_datas *datas, t_command *cmd); // ----------------------------------Parser.c - typedef enum e_type { WORD, - PIPE, OUT, ADD, IN, HD, -} t_type; + PIPE, + AND, + OR, +} t_type; typedef struct s_token { @@ -87,18 +95,16 @@ typedef struct s_token struct s_token *next; } t_token; -size_t count_arguments(t_token *tok); -void update_redir(t_datas *datas, t_command *cmd, t_token *tok); +t_command *parser(t_datas *datas, t_token *tok, t_command *prev); // ----------------------------------Lexer.c - typedef enum e_state { OLD_ST, ROOT_ST, S_QUOTE_ST, D_QUOTE_ST, -} t_state; +} t_state; typedef struct s_lex { @@ -106,13 +112,11 @@ typedef struct s_lex t_type type; t_type next_type; t_token *tokens; + int deep; int n_elem; -} t_lexer; + int empty; +} t_lexer; -int create_token(t_lexer *lex, char str[]); -int check_register(t_lexer *lex, char **line, char *tmp); -int replace_var(t_datas *datas, char **line, char *tmp, int tmp_i); -int check_state(t_lexer *lex, char **line); -char *expend_str(t_datas *datas, char *line); +t_token *lexer(t_datas *datas, char *line); #endif diff --git a/parser.c b/parser.c index 134d113..05f7583 100755 --- a/parser.c +++ b/parser.c @@ -6,43 +6,79 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/02 16:09:25 by narnaud #+# #+# */ -/* Updated: 2022/05/05 14:30:11 by mea ### ########.fr */ +/* Updated: 2022/05/09 09:56:29 by narnaud ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -char *expend_str(t_datas *datas, char *line) +static size_t count_arguments(t_token *tok); +static t_token *parse_cmd(t_datas *datas, t_token *tok, t_command *cmd); + +t_command *parser(t_datas *datas, t_token *tok, t_command *prev) { - char *tmp; - int tmp_i; + t_command *cmd; + + if (!tok) + return (NULL); + cmd = ft_calloc(1, sizeof(*cmd)); + if (prev) + cmd->prev = prev; + cmd->argv = ft_calloc(count_arguments(tok) + 1, sizeof(char *)); + cmd->argc = 0; + while (tok && tok->type < PIPE) + tok = parse_cmd(datas, tok, cmd); + if (tok) + { + cmd->next = parser(datas, tok->next, cmd); + free(tok->value); + free(tok); + } + return (cmd); +} - tmp = ft_calloc(1024, sizeof *tmp); - if (!tmp) - free(tmp); - tmp_i = 0; - while (*line) +static size_t count_arguments(t_token *tok) +{ + size_t ret; + + ret = 0; + while (tok && tok->type != PIPE) { - if (*line == '$') - tmp_i = replace_var(datas, &line, tmp, tmp_i); - tmp[tmp_i] = *line; - line++; - tmp_i++; + if (tok->type == WORD) + ret++; + tok = tok->next; } - return (tmp); + return (ret); +} + +static void update_redir(t_datas *datas, t_command *cmd, t_token *tok); + +static t_token *parse_cmd(t_datas *datas, t_token *tok, t_command *cmd) +{ + t_token *prev_tok; + + if (tok->type) + update_redir(datas, cmd, tok); + else + cmd->argv[cmd->argc++] = ft_strdup(tok->value); + prev_tok = tok; + tok = tok->next; + free(prev_tok->value); + free(prev_tok); + return (tok); } -int push_heredoc(t_datas *datas, char *str) +static int push_heredoc(t_datas *datas, char *str) { char *line; int pip[2]; pipe(pip); - while(1) + while (1) { line = readline(">"); if (!ft_strncmp(line, str, ft_strlen(str) + 1)) - break; + break ; ft_putstr_fd(expend_str(datas, line), pip[1]); write(pip[1], "\n", 1); } @@ -50,46 +86,30 @@ int push_heredoc(t_datas *datas, char *str) return (pip[0]); } -size_t count_arguments(t_token *tok) +static void update_redir(t_datas *datas, t_command *cmd, t_token *tok) { - size_t ret; - - ret = 0; - while (tok && tok->type != PIPE) + if (tok->type == OUT) { - if (tok->type == WORD) - ret++; - tok = tok->next; + if (cmd->fd[1]) + close(cmd->fd[1]); + cmd->fd[1] = open(tok->value, O_CREAT | O_TRUNC | O_WRONLY, 0644); + } + else if (tok->type == ADD) + { + if (cmd->fd[1]) + close(cmd->fd[1]); + cmd->fd[1] = open(tok->value, O_CREAT | O_APPEND | O_WRONLY, 0644); + } + else if (tok->type == IN) + { + if (cmd->fd[0]) + close(cmd->fd[0]); + cmd->fd[0] = open(tok->value, O_RDONLY); + } + else if (tok->type == HD) + { + if (cmd->fd[0]) + close(cmd->fd[0]); + cmd->fd[0] = push_heredoc(datas, tok->value); } - return (ret); -} - -void update_redir(t_datas *datas, t_command *cmd, t_token *tok) -{ - if (tok->type == OUT) - { - if (cmd->fd[1]) - close(cmd->fd[1]); - cmd->fd[1] = open(tok->value, O_CREAT | O_TRUNC | O_WRONLY, 0644); - } - else if (tok->type == ADD) - { - if (cmd->fd[1]) - close(cmd->fd[1]); - cmd->fd[1] = open(tok->value, O_CREAT | O_APPEND | O_WRONLY, 0644); - } - else if (tok->type == IN) - { - if (cmd->fd[0]) - close(cmd->fd[0]); - cmd->fd[0] = open(tok->value, O_RDONLY); - } - else if (tok->type == HD) - { - if (cmd->fd[0]) - close(cmd->fd[0]); - cmd->fd[0] = push_heredoc(datas, tok->value); - } } - - diff --git a/utils.c b/utils.c index 2d4da7e..a8eb2ea 100755 --- a/utils.c +++ b/utils.c @@ -6,7 +6,7 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/03 08:57:53 by narnaud #+# #+# */ -/* Updated: 2022/05/05 16:33:21 by mea ### ########.fr */ +/* Updated: 2022/05/06 13:15:33 by narnaud ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,32 +23,21 @@ int is_empty(char *line) return (1); } -void nothing(int sig_num) -{ - (void)sig_num; -} -void termios(int ctl) +void handle_status(t_datas *datas, int status) { - struct termios termios_p; - int tty; - - tty = ttyslot(); - if (tcgetattr(tty, &termios_p) < 0) - exit ((perror("stdin"), EXIT_FAILURE)); - if (ctl) + if (WIFSIGNALED(status)) { - termios_p.c_lflag |= ECHOCTL; - signal(SIGINT, nothing); - signal(SIGQUIT, nothing); + datas->exit_code = 128 + WTERMSIG(status); + if (datas->exit_code == 131) + printf("Quit: 3\n"); } else - { - termios_p.c_lflag &= ~(ECHOCTL); - signal(SIGINT, sigs_handler); - signal(SIGQUIT, sigs_handler); - } - termios_p.c_cc[VQUIT] = ctl * 28; - tcsetattr(tty, TCSANOW, &termios_p); + datas->exit_code = WEXITSTATUS(status); +} + +void nothing(int sig_num) +{ + (void)sig_num; } void sigs_handler(int sig_num) @@ -61,8 +50,18 @@ void sigs_handler(int sig_num) return ; } -void halt(int ret_code) +void halt(t_datas *datas, int ret_code) { + int i; + + i = 0; + while (datas->envp[i]) + { + free(datas->envp[i]); + i++; + } + free(datas->envp); + clear_history(); printf("exit\n"); exit(ret_code); } diff --git a/utils_2.c b/utils_2.c new file mode 100755 index 0000000..65f566d --- /dev/null +++ b/utils_2.c @@ -0,0 +1,121 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils_2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mea +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2022/05/06 13:15:59 by narnaud #+# #+# */ +/* Updated: 2022/05/10 10:16:58 by mea ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int file_error(char *cmd, char *file, char *msg) +{ + ft_putstr_fd("Minishell: ", 2); + ft_putstr_fd(cmd, 2); + ft_putstr_fd(": ", 2); + ft_putstr_fd(file, 2); + ft_putstr_fd(": ", 2); + ft_putstr_fd(msg, 2); + ft_putchar_fd('\n', 2); + return (0); +} + +static char *get_var_value(t_datas *datas, char **line, int name_len); + +int replace_var(t_datas *datas, char **line, char *tmp, int tmp_i) +{ + int name_len; + int i; + char *value; + + if ((*line)[1] == '?') + { + value = ft_itoa(datas->exit_code); + name_len = 2; + } + else + { + name_len = 1; + while (ft_isalpha((*line)[name_len]) \ + || ft_isdigit((*line)[name_len]) || (*line)[name_len] == '_') + name_len++; + value = get_var_value(datas, line, name_len); + } + i = 0; + while (value[i]) + tmp[tmp_i++] = value[i++]; + tmp[tmp_i] = 0; + *line += name_len; + free(value); + return (tmp_i); +} + +char *expend_str(t_datas *datas, char *line) +{ + char *tmp; + int tmp_i; + + tmp = ft_calloc(STR_MAX_SIZE, sizeof(*tmp)); + if (!tmp) + free(tmp); + tmp_i = 0; + while (*line) + { + if (*line == '$') + tmp_i = replace_var(datas, &line, tmp, tmp_i); + else + tmp[tmp_i++] = *(line++); + } + return (tmp); +} + +static char *get_var_value(t_datas *datas, char **line, int name_len) +{ + int i; + char **env; + char *name; + char *value; + + name = ft_substr(*line, 1, name_len - 1); + i = 0; + value = NULL; + while (datas->envp[i] && !value) + { + env = ft_split(datas->envp[i], '='); + if (!ft_strncmp(name, env[0], name_len + 1)) + value = (free(env[0]), env[1]); + else if (++i) + ft_free_split(env); + } + free(name); + if (value) + free(env); + else + value = strdup(""); + return (value); +} + +int set_redir(t_lexer *lex, char **line, char ch) +{ + static t_type type_out[2] = {OUT, ADD}; + static t_type type_in[2] = {IN, HD}; + t_type *type; + + if (ch == '>') + type = type_out; + else + type = type_in; + if (**line == ch && (*line)++) + { + if (**line == ch && (*line)++) + lex->next_type = type[1]; + else + lex->next_type = type[0]; + return (1); + } + return (0); +}