diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 173d502..62423c1 100755 --- a/README.md +++ b/README.md @@ -2,15 +2,17 @@ --- ## TODO : -- Protect mallocs, -- verify exits codes - https://wiki.bash-hackers.org/scripting/basics?s[]=variables#exit_codes -- do the `(...)` -> `./minishell ...` conversion -- finish && and || +- free stack, +- protect mallocs, +- Norminette +- Finish check_builtin(); +- export : edit datas->env +- unset : idem, +- exit: handle arguments -## Issues : -- only "" line segfault (no token created) +- 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 e8d82c8..683aa63 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/07 23:17:15 by narnaud@stude ### ########.fr */ +/* Updated: 2022/05/03 18:18:23 by narnaud ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,45 +14,34 @@ int ft_echo(t_command *cmd) { - int no_nl; - int fd_out; - int i; + int no_nl; - if (cmd->fd[1]) - fd_out = cmd->fd[1]; - else - fd_out = 1; no_nl = 0; - i = 1; - if (cmd->argv[1]) + if (*(++cmd->argv)) { - if (ft_strncmp(cmd->argv[1], "-n", 3) == 0 && i++) + if (ft_strncmp(*(cmd->argv), "-n", 3) == 0 && cmd->argv++) no_nl = 1; - while (cmd->argv[i]) + while (*(cmd->argv)) { - ft_putstr_fd(cmd->argv[i], fd_out); - if (cmd->argv[++i]) - ft_putstr_fd(" ", fd_out); + ft_putstr_fd(*(cmd->argv), 1); + if (*(++cmd->argv)) + ft_putstr_fd(" ", 1); } } if (!no_nl) - ft_putstr_fd("\n", fd_out); + ft_putstr_fd("\n", 1); return (0); } int ft_pwd(t_command *cmd) { char *dir; - int fd_out; - if (cmd->fd[1]) - fd_out = cmd->fd[1]; - else - fd_out = 1; + (void)cmd; dir = ft_calloc(PATHS_MAX_SIZE, sizeof(char)); getcwd(dir, PATHS_MAX_SIZE); - ft_putstr_fd(dir, fd_out); - ft_putstr_fd("\n", fd_out); + ft_putstr_fd(dir, 1); + ft_putstr_fd("\n", 1); free(dir); return (0); } @@ -62,24 +51,26 @@ int ft_cd(t_command *cmd) if (cmd->argv[1]) { if (access(cmd->argv[1], X_OK)) - return (file_error(cmd->argv[0], cmd->argv[1], \ - "Permission denied\n")); + { + printf("Minishell: %s: %s: Permission denied\n", cmd->argv[0], cmd->argv[1]); + return (0); + } else if (access(cmd->argv[1], F_OK)) - return (file_error(cmd->argv[0], cmd->argv[1], \ - "Not a directory\n")); + { + printf("Minishell: %s: %s: Not a directory\n", cmd->argv[0], cmd->argv[1]); + return (0); + } chdir(cmd->argv[1]); return (1); } else + { chdir(getenv("HOME")); + } return (0); } -int ft_exit(t_datas *datas, t_command *cmd) +int close_minishell(int exit_code) { - if (cmd->argc > 1) - halt(datas, EXIT_SUCCESS); - else - halt(datas, ft_atoi(cmd->argv[1])); - return (1); + exit(exit_code); } diff --git a/caller.c b/caller.c index 5bf475d..a548b8a 100755 --- a/caller.c +++ b/caller.c @@ -6,33 +6,13 @@ /* By: narnaud +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/03 11:48:16 by narnaud #+# #+# */ -/* Updated: 2022/05/09 09:43:21 by narnaud ### ########.fr */ +/* Updated: 2022/05/05 09:40:42 by narnaud ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -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) +int command_call(t_datas *datas, t_command *cmd) { if (ft_strncmp(cmd->argv[0], "echo", 5) == 0) return (ft_echo(cmd)); @@ -45,39 +25,14 @@ int builtin_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, cmd)); + return (ft_env(datas)); else if (ft_strncmp(cmd->argv[0], "exit", 5) == 0) - return (ft_exit(datas, cmd)); + return (close_minishell(0)); else return (-1); } -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) +void exe(t_datas *datas, t_command *cmd) { char **path_dirs; char *path; @@ -93,32 +48,10 @@ static 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 65e6249..39eb825 100755 --- a/env.c +++ b/env.c @@ -6,138 +6,79 @@ /* By: narnaud +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/02/16 09:41:29 by narnaud #+# #+# */ -/* Updated: 2022/05/07 23:38:40 by narnaud@stude ### ########.fr */ +/* Updated: 2022/05/05 09:30:51 by narnaud ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static void clean_env(t_datas *datas, int i); - -int ft_unset(t_datas *datas, t_command *cmd) +int is_valid_identifier(char *ident) { - 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]) + if (ft_isalpha(ident[0]) || ident[0] == '_') { - name_len = ft_strlen(cmd->argv[i]); - j = 0; - while (datas->envp[j]) + while (*ident) { - 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); + if (!ft_isalpha(*ident) && !ft_isdigit(*ident) && *ident != '_') + return (0); + ident++; } - i++; + return (1); + } + return (0); +} + +int ft_unset(t_datas *datas, t_command *cmd) +{ + (void)datas; + if (!cmd->argv[1]) + { + //read(input_fd, PIPE_MAX_SIZE); + return (1); } return (0); } -int ft_env(t_datas *datas, t_command *cmd) +int ft_env(t_datas *datas) { - int i; - int fd_out; + int i; - if (cmd->fd[1]) - fd_out = cmd->fd[1]; - else - fd_out = 1; i = 0; while (datas->envp[i]) { - ft_putstr_fd(datas->envp[i], fd_out); - ft_putchar_fd('\n', fd_out); + printf("%s\n", datas->envp[i]); 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], name_len + 1)) - datas->envp[i] = (free(datas->envp[i]), NULL); - else - i++; - ft_free_split(env); - } - 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]) + if (!ft_strncmp(new[0], env[0], ft_strlen(new[0]) + 1)) { - 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; + datas->envp[i] = cmd->argv[1]; + return (1); } i++; } + datas->envp[i] = cmd->argv[1]; + datas->envp[i + 1] = NULL; + return (1); } -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 444ec89..5985ccc 100755 --- a/lexer.c +++ b/lexer.c @@ -6,78 +6,15 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/02 13:44:57 by narnaud #+# #+# */ -/* Updated: 2022/05/09 09:59:11 by narnaud ### ########.fr */ +/* Updated: 2022/05/05 15:41:06 by mea ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -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[]) +int create_token(t_lexer *lex, char str[]) { t_token *tok; - t_token *tmp; t_type type; type = lex->type; @@ -88,85 +25,129 @@ static int create_token(t_lexer *lex, char str[]) lex->next_type = WORD; if (!str[0]) return (0); - tok = ft_calloc(1, sizeof(*tok)); + 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->type = type; - tok->value = ft_strdup(str); - tmp = lex->tokens; - while (tmp && tmp->next) - tmp = tmp->next; - if (!tmp) + tok->value = strdup(str); + if (DEBUG) + printf("token value : %s - token type : %d\n", tok->value, type); + if (!lex->tokens) lex->tokens = tok; - else - tmp->next = tok; return (1); } -static int check_ope(t_lexer *lex, char **line, char *tmp) +int check_register(t_lexer *lex, char **line, char *tmp) { - if (!ft_strncmp(*line, "&&", 2)) + int spaces; + + if (lex->state != ROOT_ST) + return (0); + spaces = 0; + if (ft_isspace(**line)) { - (*line) += 2; - lex->next_type = AND; - create_token(lex, tmp); - return (create_token(lex, "&&")); + while (ft_isspace(**line)) + (*line)++; + spaces = 1; } - if (!ft_strncmp(*line, "||", 2)) + if (**line == '>' && (*line)++) { - (*line) += 2; - lex->next_type = OR; - create_token(lex, tmp); - return (create_token(lex, "||")); + if (**line == '>' && (*line)++) + lex->next_type = ADD; + else + lex->next_type = OUT; + return (create_token(lex, tmp)); + } + else if (**line == '<' && (*line)++) + { + if (**line == '<' && (*line)++) + lex->next_type = HD; + else + lex->next_type = IN; + return (create_token(lex, tmp)); } - if (**line == '|') + else if (**line == '|') { (*line)++; lex->next_type = PIPE; create_token(lex, tmp); return (create_token(lex, "|")); } - return (0); - + if (!spaces || !*tmp) + return (0); + return (create_token(lex, tmp)); } -static int set_redir(t_lexer *lex, char **line, char ch); -static int check_register(t_lexer *lex, char **line, char *tmp) +int replace_var(t_datas *datas, char **line, char *tmp, int tmp_i) { - int spaces; - - if (lex->state != ROOT_ST || lex->deep > 0) - return (0); - spaces = 0; - if (ft_isspace(**line)) + int name_len; + int i; + char *var_name; + char *value; + char **env; + i = 1; + if ((*line)[1] == '?') { - while (ft_isspace(**line)) - (*line)++; - spaces = 1; + value = ft_itoa(datas->exit_code); + name_len = 2; } - 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) - return (create_token(lex, tmp)); - return (0); + 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); } -static int set_redir(t_lexer *lex, char **line, char ch) +int check_state(t_lexer *lex, char **line) { - static t_type type_out[2] = {OUT, ADD}; - static t_type type_in[2] = {IN, HD}; - t_type *type; + t_state new; - if (ch == '>') - type = type_out; - else - type = type_in; - if (**line == ch && (*line)++) + new = OLD_ST; + if (**line == '"') { - if (**line == ch && (*line)++) - lex->next_type = type[1]; - else - lex->next_type = type[0]; + 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; + } + if (new) + { + (*line)++; + lex->state = new; return (1); } return (0); diff --git a/minishell.c b/minishell.c index c20df95..067bfb3 100755 --- a/minishell.c +++ b/minishell.c @@ -6,85 +6,150 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/02 12:14:09 by narnaud #+# #+# */ -/* Updated: 2022/05/07 23:08:05 by narnaud@stude ### ########.fr */ +/* Updated: 2022/05/05 16:28:15 by mea ### ########.fr */ /* */ /* ************************************************************************** */ -#include "minishell.h" +# include "minishell.h" -void termios(int ctl) +void handle_status(t_datas *datas, int status) { - struct termios termios_p; - int tty; - - tty = ttyslot(); - tcgetattr(tty, &termios_p); - 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 + 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) { - termios_p.c_lflag &= ~(ECHOCTL); - signal(SIGINT, sigs_handler); - signal(SIGQUIT, sigs_handler); + pipe(pip); + cmd->fd[1] = pip[1]; + cmd->next->fd[0] = pip[0]; } - termios_p.c_cc[VQUIT] = ctl * 28; - tcsetattr(tty, TCSANOW, &termios_p); + + 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); } -void free_cmd(t_command *cmd) +t_command *parser(t_datas *datas, t_token *tok, t_command *prev) { - int i; + int i; + t_command *cmd; - if (!cmd) - return ; + if (!tok) + return (NULL); + cmd = ft_calloc(1, sizeof(t_command)); + if (prev) + cmd->prev = prev; i = 0; - while (cmd->argv[i]) + cmd->argv = ft_calloc(count_arguments(tok) + 1, sizeof(char *)); + while(tok && tok->type != PIPE) { - free(cmd->argv[i]); - i++; + if (tok->type) + update_redir(datas, cmd, tok); + else + cmd->argv[i++] = tok->value; + tok = tok->next; } - free(cmd->argv); - free_cmd(cmd->next); - free(cmd); + 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); } -void prompt(t_datas *datas) +t_token *lexer(t_datas *datas, char *line) { - char *line; - t_command *cmd; + t_lexer *lex; + char *tmp; + int tmp_i; - 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); + 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); } int main(int argc, char **argv, char **envp) { - static t_datas datas; - static int i = 0; + t_datas datas; + char *line; + char **env_copy; + int i; - datas.envp = ft_calloc(ENVP_MAX_SIZE, sizeof(char *)); - while (*envp) - datas.envp[i++] = ft_strdup(*(envp++)); + 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.exit_code = 0; if (argc < 2) (void)argv; while (1) - prompt(&datas); - halt(&datas, EXIT_SUCCESS); + { + 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); } diff --git a/minishell.h b/minishell.h index 6068ec0..45f03f3 100755 --- a/minishell.h +++ b/minishell.h @@ -6,15 +6,16 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/02 13:50:44 by narnaud #+# #+# */ -/* Updated: 2022/05/09 09:02:20 by narnaud ### ########.fr */ +/* Updated: 2022/05/05 14:18:56 by mea ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef MINISHELL_H # define MINISHELL_H -# define ENVP_MAX_SIZE 1024 -# define STR_MAX_SIZE 1024 +# define PIPE_MAX_SIZE 8192 # define PATHS_MAX_SIZE 126 +# define PROMPT_PREFIX 0 +# define DEBUG 0 # include "libft/libft.h" # include @@ -33,8 +34,8 @@ typedef struct s_command { char **argv; - int argc; int fd[2]; + char *heredoc; struct s_command *next; struct s_command *prev; } t_command; @@ -47,62 +48,57 @@ typedef struct s_datas // ----------------------------------Utils.c int is_empty(char *line); -void handle_status(t_datas *datas, int status); -void nothing(int sig_num); +void halt(int ret_code); +void termios(int ctl); void sigs_handler(int sig_num); -void halt(t_datas *datas, int ret_code); - -// ----------------------------------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); // ----------------------------------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_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, t_command *cmd); +int ft_env(t_datas *datas); int ft_export(t_datas *datas, t_command *cmd); // ----------------------------------Caller.c -int is_builtin(char *cmd); -int builtin_call(t_datas *datas, t_command *cmd); -int piper(t_datas *datas, t_command *cmd); +void exe(t_datas *datas, t_command *cmd); +int command_call(t_datas *datas, t_command *cmd); // ----------------------------------Parser.c + typedef enum e_type { WORD, + PIPE, OUT, ADD, IN, HD, - PIPE, - AND, - OR, -} t_type; +} t_type; typedef struct s_token { char *value; t_type type; struct s_token *next; -} t_token; +} t_token; -t_command *parser(t_datas *datas, t_token *tok,t_command *prev); +size_t count_arguments(t_token *tok); +void update_redir(t_datas *datas, t_command *cmd, t_token *tok); // ----------------------------------Lexer.c + typedef enum e_state { OLD_ST, ROOT_ST, S_QUOTE_ST, D_QUOTE_ST, -} t_state; +} t_state; typedef struct s_lex { @@ -110,10 +106,13 @@ typedef struct s_lex t_type type; t_type next_type; t_token *tokens; - int deep; int n_elem; -} t_lexer; +} t_lexer; -t_token *lexer(t_datas *datas, char *line); +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); #endif diff --git a/parser.c b/parser.c index 05f7583..134d113 100755 --- a/parser.c +++ b/parser.c @@ -6,79 +6,43 @@ /* By: mea +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/05/02 16:09:25 by narnaud #+# #+# */ -/* Updated: 2022/05/09 09:56:29 by narnaud ### ########.fr */ +/* Updated: 2022/05/05 14:30:11 by mea ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -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 *expend_str(t_datas *datas, char *line) { - 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); -} + char *tmp; + int tmp_i; -static size_t count_arguments(t_token *tok) -{ - size_t ret; - - ret = 0; - while (tok && tok->type != PIPE) + tmp = ft_calloc(1024, sizeof *tmp); + if (!tmp) + free(tmp); + tmp_i = 0; + while (*line) { - if (tok->type == WORD) - ret++; - tok = tok->next; + if (*line == '$') + tmp_i = replace_var(datas, &line, tmp, tmp_i); + tmp[tmp_i] = *line; + line++; + tmp_i++; } - 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); + return (tmp); } -static int push_heredoc(t_datas *datas, char *str) +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); } @@ -86,30 +50,46 @@ static int push_heredoc(t_datas *datas, char *str) return (pip[0]); } -static void update_redir(t_datas *datas, t_command *cmd, t_token *tok) +size_t count_arguments(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) + size_t ret; + + ret = 0; + while (tok && tok->type != PIPE) { - if (cmd->fd[0]) - close(cmd->fd[0]); - cmd->fd[0] = push_heredoc(datas, tok->value); + if (tok->type == WORD) + ret++; + tok = tok->next; } + 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 a8eb2ea..2d4da7e 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/06 13:15:33 by narnaud ### ########.fr */ +/* Updated: 2022/05/05 16:33:21 by mea ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,21 +23,32 @@ int is_empty(char *line) return (1); } -void handle_status(t_datas *datas, int status) +void nothing(int sig_num) +{ + (void)sig_num; +} +void termios(int ctl) { - if (WIFSIGNALED(status)) + struct termios termios_p; + int tty; + + tty = ttyslot(); + if (tcgetattr(tty, &termios_p) < 0) + exit ((perror("stdin"), EXIT_FAILURE)); + 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); -} - -void nothing(int sig_num) -{ - (void)sig_num; + { + 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); } void sigs_handler(int sig_num) @@ -50,18 +61,8 @@ void sigs_handler(int sig_num) return ; } -void halt(t_datas *datas, int ret_code) +void halt(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 deleted file mode 100644 index 13f7442..0000000 --- a/utils_2.c +++ /dev/null @@ -1,100 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* utils_2.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: narnaud +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2022/05/06 13:15:59 by narnaud #+# #+# */ -/* Updated: 2022/05/07 23:04:44 by narnaud@stude ### ########.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); -}