Browse Source

fix fix

master
Michael Ea 3 years ago
parent
commit
b3dc5f9eb7
  1. 18
      README.md
  2. 57
      built-in.c
  3. 83
      caller.c
  4. 125
      env.c
  5. 209
      lexer.c
  6. 167
      minishell.c
  7. 70
      minishell.h
  8. 134
      parser.c
  9. 47
      utils.c
  10. 121
      utils_2.c

18
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 :

57
built-in.c

@ -6,7 +6,7 @@
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

83
caller.c

@ -3,16 +3,36 @@
/* ::: :::::::: */
/* caller.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

125
env.c

@ -6,79 +6,138 @@
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

209
lexer.c

@ -6,15 +6,78 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

167
minishell.c

@ -6,150 +6,85 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

70
minishell.h

@ -6,16 +6,15 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <fcntl.h>
@ -31,11 +30,11 @@
# include <errno.h>
# include <termios.h>
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

134
parser.c

@ -6,43 +6,79 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}
}

47
utils.c

@ -6,7 +6,7 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

121
utils_2.c

@ -0,0 +1,121 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utils_2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}
Loading…
Cancel
Save