Browse Source

fix empty token

master
Michael Ea 3 years ago
parent
commit
43a2d9b357
  1. BIN
      .DS_Store
  2. 18
      README.md
  3. 55
      built-in.c
  4. 81
      caller.c
  5. 121
      env.c
  6. 215
      lexer.c
  7. 165
      minishell.c
  8. 45
      minishell.h
  9. 90
      parser.c
  10. 47
      utils.c
  11. 100
      utils_2.c

BIN
.DS_Store

Binary file not shown.

18
README.md

@ -2,15 +2,17 @@
--- ---
## TODO : ## TODO :
- Protect mallocs, - free stack,
- verify exits codes - protect mallocs,
https://wiki.bash-hackers.org/scripting/basics?s[]=variables#exit_codes - Norminette
- do the `(...)` -> `./minishell ...` conversion - Finish check_builtin();
- finish && and ||
- export : edit datas->env
- unset : idem,
- exit: handle arguments
## Issues : - setup correct ext_codes
- only "" line segfault (no token created) https://wiki.bash-hackers.org/scripting/basics?s[]=variables#exit_codes
## Issues :
## Notes :

55
built-in.c

@ -6,7 +6,7 @@
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */ /* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/01/06 09:02:57 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 */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -15,44 +15,33 @@
int ft_echo(t_command *cmd) 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; no_nl = 0;
i = 1; if (*(++cmd->argv))
if (cmd->argv[1])
{ {
if (ft_strncmp(cmd->argv[1], "-n", 3) == 0 && i++) if (ft_strncmp(*(cmd->argv), "-n", 3) == 0 && cmd->argv++)
no_nl = 1; no_nl = 1;
while (cmd->argv[i]) while (*(cmd->argv))
{ {
ft_putstr_fd(cmd->argv[i], fd_out); ft_putstr_fd(*(cmd->argv), 1);
if (cmd->argv[++i]) if (*(++cmd->argv))
ft_putstr_fd(" ", fd_out); ft_putstr_fd(" ", 1);
} }
} }
if (!no_nl) if (!no_nl)
ft_putstr_fd("\n", fd_out); ft_putstr_fd("\n", 1);
return (0); return (0);
} }
int ft_pwd(t_command *cmd) int ft_pwd(t_command *cmd)
{ {
char *dir; char *dir;
int fd_out;
if (cmd->fd[1]) (void)cmd;
fd_out = cmd->fd[1];
else
fd_out = 1;
dir = ft_calloc(PATHS_MAX_SIZE, sizeof(char)); dir = ft_calloc(PATHS_MAX_SIZE, sizeof(char));
getcwd(dir, PATHS_MAX_SIZE); getcwd(dir, PATHS_MAX_SIZE);
ft_putstr_fd(dir, fd_out); ft_putstr_fd(dir, 1);
ft_putstr_fd("\n", fd_out); ft_putstr_fd("\n", 1);
free(dir); free(dir);
return (0); return (0);
} }
@ -62,24 +51,26 @@ int ft_cd(t_command *cmd)
if (cmd->argv[1]) if (cmd->argv[1])
{ {
if (access(cmd->argv[1], X_OK)) 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)) 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]); chdir(cmd->argv[1]);
return (1); return (1);
} }
else else
{
chdir(getenv("HOME")); chdir(getenv("HOME"));
}
return (0); return (0);
} }
int ft_exit(t_datas *datas, t_command *cmd) int close_minishell(int exit_code)
{ {
if (cmd->argc > 1) exit(exit_code);
halt(datas, EXIT_SUCCESS);
else
halt(datas, ft_atoi(cmd->argv[1]));
return (1);
} }

81
caller.c

@ -6,33 +6,13 @@
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */ /* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/03 11:48:16 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" #include "minishell.h"
static void exe(t_datas *datas, t_command *cmd); int command_call(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) if (ft_strncmp(cmd->argv[0], "echo", 5) == 0)
return (ft_echo(cmd)); 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) else if (ft_strncmp(cmd->argv[0], "unset", 6) == 0)
return (ft_unset(datas, cmd)); return (ft_unset(datas, cmd));
else if (ft_strncmp(cmd->argv[0], "env", 4) == 0) 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) else if (ft_strncmp(cmd->argv[0], "exit", 5) == 0)
return (ft_exit(datas, cmd)); return (close_minishell(0));
else else
return (-1); return (-1);
} }
int piper(t_datas *datas, t_command *cmd) void exe(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_dirs;
char *path; 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_length = ft_strlen(*path_dirs) + ft_strlen(cmd->argv[0]) + 2;
path = ft_calloc(path_length, sizeof(char)); path = ft_calloc(path_length, sizeof(char));
ft_memcpy(path, *path_dirs, ft_strlen(*path_dirs)); 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);
ft_memcpy(path + ft_strlen(*path_dirs) + 1, \ ft_memcpy(path + ft_strlen(*path_dirs) + 1, cmd->argv[0], ft_strlen(cmd->argv[0]));
cmd->argv[0], ft_strlen(cmd->argv[0]));
execve(path, cmd->argv, datas->envp); execve(path, cmd->argv, datas->envp);
free(path);
path_dirs++; 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);
}

121
env.c

@ -6,138 +6,79 @@
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */ /* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/02/16 09:41:29 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" #include "minishell.h"
static void clean_env(t_datas *datas, int i); int is_valid_identifier(char *ident)
int ft_unset(t_datas *datas, t_command *cmd)
{ {
char **env; if (ft_isalpha(ident[0]) || ident[0] == '_')
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]); while (*ident)
j = 0;
while (datas->envp[j])
{ {
env = ft_split(datas->envp[j], '='); if (!ft_isalpha(*ident) && !ft_isdigit(*ident) && *ident != '_')
if (!ft_strncmp(cmd->argv[i], env[0], name_len + 1)) return (0);
clean_env(datas, j); ident++;
else if (++j)
ft_free_split(env);
} }
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); return (0);
} }
int ft_env(t_datas *datas, t_command *cmd) int ft_env(t_datas *datas)
{ {
int i; int i;
int fd_out;
if (cmd->fd[1])
fd_out = cmd->fd[1];
else
fd_out = 1;
i = 0; i = 0;
while (datas->envp[i]) while (datas->envp[i])
{ {
ft_putstr_fd(datas->envp[i], fd_out); printf("%s\n", datas->envp[i]);
ft_putchar_fd('\n', fd_out);
i++; i++;
} }
return (0); return (0);
} }
static int is_valid_identifier(char *ident);
int ft_export(t_datas *datas, t_command *cmd) int ft_export(t_datas *datas, t_command *cmd)
{ {
char **new; char **new;
int name_len;
char **env; char **env;
int i; int i;
i = 0; i = 0;
if (cmd->argc < 2)
return (0);
new = ft_split(cmd->argv[1], '='); new = ft_split(cmd->argv[1], '=');
name_len = ft_strlen(new[0]);
if (!is_valid_identifier(new[0])) if (!is_valid_identifier(new[0]))
{
printf ("export: not an identifier: %s\n", new[0]);
return (0); return (0);
}
while (datas->envp[i]) while (datas->envp[i])
{ {
env = ft_split(datas->envp[i], '='); env = ft_split(datas->envp[i], '=');
if (!ft_strncmp(new[0], env[0], name_len + 1)) if (!ft_strncmp(new[0], env[0], ft_strlen(new[0]) + 1))
datas->envp[i] = (free(datas->envp[i]), NULL); {
else datas->envp[i] = cmd->argv[1];
return (1);
}
i++; i++;
ft_free_split(env);
} }
ft_free_split(new); datas->envp[i] = cmd->argv[1];
datas->envp[i] = ft_strdup(cmd->argv[1]); datas->envp[i + 1] = NULL;
return (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);
}

215
lexer.c

@ -6,78 +6,15 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */ /* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/02 13:44:57 by narnaud #+# #+# */ /* 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" #include "minishell.h"
static int check_state(t_lexer *lex, char **line); int create_token(t_lexer *lex, char str[])
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 *tok;
t_token *tmp;
t_type type; t_type type;
type = lex->type; type = lex->type;
@ -88,85 +25,129 @@ static int create_token(t_lexer *lex, char str[])
lex->next_type = WORD; lex->next_type = WORD;
if (!str[0]) if (!str[0])
return (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->type = type;
tok->value = ft_strdup(str); tok->value = strdup(str);
tmp = lex->tokens; if (DEBUG)
while (tmp && tmp->next) printf("token value : %s - token type : %d\n", tok->value, type);
tmp = tmp->next; if (!lex->tokens)
if (!tmp)
lex->tokens = tok; lex->tokens = tok;
else
tmp->next = tok;
return (1); 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; while (ft_isspace(**line))
lex->next_type = AND; (*line)++;
create_token(lex, tmp); spaces = 1;
return (create_token(lex, "&&"));
} }
if (!ft_strncmp(*line, "||", 2)) if (**line == '>' && (*line)++)
{ {
(*line) += 2; if (**line == '>' && (*line)++)
lex->next_type = OR; lex->next_type = ADD;
create_token(lex, tmp); else
return (create_token(lex, "||")); 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)++; (*line)++;
lex->next_type = PIPE; lex->next_type = PIPE;
create_token(lex, tmp); create_token(lex, tmp);
return (create_token(lex, "|")); return (create_token(lex, "|"));
} }
if (!spaces || !*tmp)
return (0); 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; int name_len;
int i;
if (lex->state != ROOT_ST || lex->deep > 0) char *var_name;
return (0); char *value;
spaces = 0; char **env;
if (ft_isspace(**line)) i = 1;
if ((*line)[1] == '?')
{ {
while (ft_isspace(**line)) value = ft_itoa(datas->exit_code);
(*line)++; name_len = 2;
spaces = 1;
} }
if (set_redir(lex, line, '>') || set_redir(lex, line, '<')) else
return (create_token(lex, tmp)); {
if (check_ope(lex, line, tmp)) while (ft_isalpha((*line)[i]) || ft_isdigit((*line)[i]) || (*line)[i] == '_')
return (1); i++;
if ((**line == '(' || spaces) && *tmp) var_name = ft_substr(*line, 1, i - 1);
return (create_token(lex, tmp)); i = 0;
return (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}; t_state new;
static t_type type_in[2] = {IN, HD};
t_type *type;
if (ch == '>') new = OLD_ST;
type = type_out; if (**line == '"')
else
type = type_in;
if (**line == ch && (*line)++)
{ {
if (**line == ch && (*line)++) if (lex->state == D_QUOTE_ST)
lex->next_type = type[1]; new = ROOT_ST;
else else if (lex->state == ROOT_ST)
lex->next_type = type[0]; 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 (1);
} }
return (0); return (0);

165
minishell.c

@ -6,85 +6,150 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */ /* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/02 12:14:09 by narnaud #+# #+# */ /* 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; if (WIFSIGNALED(status))
int tty;
tty = ttyslot();
tcgetattr(tty, &termios_p);
if (ctl)
{ {
termios_p.c_lflag |= ECHOCTL; datas->exit_code = 128 + WTERMSIG(status);
signal(SIGINT, nothing); if (datas->exit_code == 131)
signal(SIGQUIT, nothing); printf("Quit: 3\n");
} }
else 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); pipe(pip);
signal(SIGINT, sigs_handler); cmd->fd[1] = pip[1];
signal(SIGQUIT, sigs_handler); 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) if (!tok)
return ; return (NULL);
cmd = ft_calloc(1, sizeof(t_command));
if (prev)
cmd->prev = prev;
i = 0; 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]); if (tok->type)
i++; update_redir(datas, cmd, tok);
else
cmd->argv[i++] = tok->value;
tok = tok->next;
} }
free(cmd->argv); if (DEBUG)
free_cmd(cmd->next); printf("######\n->cmd : %s, in_fd : %d, out_fd : %d\n", \
free(cmd); 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_lexer *lex;
t_command *cmd; char *tmp;
int tmp_i;
termios(0); lex = ft_calloc(1, sizeof *lex);
line = readline("$ "); lex->state = ROOT_ST;
termios(1); tmp = ft_calloc(1024, sizeof *tmp);
if (line == NULL) tmp_i = 0;
halt(datas, EXIT_SUCCESS); while (*line)
if (is_empty(line)) {
return ; if (check_state(lex, &line))
cmd = parser(datas, lexer(datas, line), NULL); continue;
if (!cmd->prev && !cmd->next && is_builtin(cmd->argv[0])) if (lex->state != S_QUOTE_ST && *line == '$')
builtin_call(datas, cmd); tmp_i = replace_var(datas, &line, tmp, tmp_i);
else if (check_register(lex, &line, tmp))
piper(datas, cmd); {
free_cmd(cmd); tmp_i = 0;
add_history(line); 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) int main(int argc, char **argv, char **envp)
{ {
static t_datas datas; t_datas datas;
static int i = 0; char *line;
char **env_copy;
int i;
datas.envp = ft_calloc(ENVP_MAX_SIZE, sizeof(char *)); env_copy = ft_calloc(1024, sizeof(char *));
while (*envp) i = 0;
datas.envp[i++] = ft_strdup(*(envp++)); while (envp[i])
{
env_copy[i] = ft_strdup(envp[i]);
i++;
}
datas.envp = env_copy;
datas.exit_code = 0; datas.exit_code = 0;
if (argc < 2) if (argc < 2)
(void)argv; (void)argv;
while (1) 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);
} }

45
minishell.h

@ -6,15 +6,16 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */ /* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/02 13:50:44 by narnaud #+# #+# */ /* 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 #ifndef MINISHELL_H
# define MINISHELL_H # define MINISHELL_H
# define ENVP_MAX_SIZE 1024 # define PIPE_MAX_SIZE 8192
# define STR_MAX_SIZE 1024
# define PATHS_MAX_SIZE 126 # define PATHS_MAX_SIZE 126
# define PROMPT_PREFIX 0
# define DEBUG 0
# include "libft/libft.h" # include "libft/libft.h"
# include <fcntl.h> # include <fcntl.h>
@ -33,8 +34,8 @@
typedef struct s_command typedef struct s_command
{ {
char **argv; char **argv;
int argc;
int fd[2]; int fd[2];
char *heredoc;
struct s_command *next; struct s_command *next;
struct s_command *prev; struct s_command *prev;
} t_command; } t_command;
@ -47,43 +48,36 @@ typedef struct s_datas
// ----------------------------------Utils.c // ----------------------------------Utils.c
int is_empty(char *line); int is_empty(char *line);
void handle_status(t_datas *datas, int status); void halt(int ret_code);
void nothing(int sig_num); void termios(int ctl);
void sigs_handler(int sig_num); 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 // ----------------------------------Builtins.c
int close_minishell(int exit_code);
int ft_echo(t_command *cmd); int ft_echo(t_command *cmd);
int ft_pwd(t_command *cmd); int ft_pwd(t_command *cmd);
int ft_cd(t_command *cmd); int ft_cd(t_command *cmd);
int ft_exit(t_datas *datas, t_command *cmd);
// ----------------------------------Env.c // ----------------------------------Env.c
int is_valid_identifier(char *ident);
int ft_unset(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_env(t_datas *datas);
int ft_export(t_datas *datas, t_command *cmd); int ft_export(t_datas *datas, t_command *cmd);
// ----------------------------------Caller.c // ----------------------------------Caller.c
int is_builtin(char *cmd); void exe(t_datas *datas, t_command *cmd);
int builtin_call(t_datas *datas, t_command *cmd); int command_call(t_datas *datas, t_command *cmd);
int piper(t_datas *datas, t_command *cmd);
// ----------------------------------Parser.c // ----------------------------------Parser.c
typedef enum e_type typedef enum e_type
{ {
WORD, WORD,
PIPE,
OUT, OUT,
ADD, ADD,
IN, IN,
HD, HD,
PIPE,
AND,
OR,
} t_type; } t_type;
typedef struct s_token typedef struct s_token
@ -93,9 +87,11 @@ typedef struct s_token
struct s_token *next; 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 // ----------------------------------Lexer.c
typedef enum e_state typedef enum e_state
{ {
OLD_ST, OLD_ST,
@ -110,10 +106,13 @@ typedef struct s_lex
t_type type; t_type type;
t_type next_type; t_type next_type;
t_token *tokens; t_token *tokens;
int deep;
int n_elem; 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 #endif

90
parser.c

@ -6,79 +6,43 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */ /* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/02 16:09:25 by narnaud #+# #+# */ /* 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" #include "minishell.h"
static size_t count_arguments(t_token *tok); char *expend_str(t_datas *datas, char *line)
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)
{ {
t_command *cmd; char *tmp;
int tmp_i;
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);
}
static size_t count_arguments(t_token *tok) tmp = ft_calloc(1024, sizeof *tmp);
{ if (!tmp)
size_t ret; free(tmp);
tmp_i = 0;
ret = 0; while (*line)
while (tok && tok->type != PIPE)
{ {
if (tok->type == WORD) if (*line == '$')
ret++; tmp_i = replace_var(datas, &line, tmp, tmp_i);
tok = tok->next; tmp[tmp_i] = *line;
line++;
tmp_i++;
} }
return (ret); return (tmp);
} }
static void update_redir(t_datas *datas, t_command *cmd, t_token *tok); int push_heredoc(t_datas *datas, char *str)
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);
}
static int push_heredoc(t_datas *datas, char *str)
{ {
char *line; char *line;
int pip[2]; int pip[2];
pipe(pip); pipe(pip);
while (1) while(1)
{ {
line = readline(">"); line = readline(">");
if (!ft_strncmp(line, str, ft_strlen(str) + 1)) if (!ft_strncmp(line, str, ft_strlen(str) + 1))
break ; break;
ft_putstr_fd(expend_str(datas, line), pip[1]); ft_putstr_fd(expend_str(datas, line), pip[1]);
write(pip[1], "\n", 1); write(pip[1], "\n", 1);
} }
@ -86,7 +50,21 @@ static int push_heredoc(t_datas *datas, char *str)
return (pip[0]); return (pip[0]);
} }
static void update_redir(t_datas *datas, t_command *cmd, t_token *tok) size_t count_arguments(t_token *tok)
{
size_t ret;
ret = 0;
while (tok && tok->type != PIPE)
{
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 (tok->type == OUT)
{ {
@ -113,3 +91,5 @@ static void update_redir(t_datas *datas, t_command *cmd, t_token *tok)
cmd->fd[0] = push_heredoc(datas, tok->value); cmd->fd[0] = push_heredoc(datas, tok->value);
} }
} }

47
utils.c

@ -6,7 +6,7 @@
/* By: mea <marvin@42.fr> +#+ +:+ +#+ */ /* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/03 08:57:53 by narnaud #+# #+# */ /* 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); 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); termios_p.c_lflag |= ECHOCTL;
if (datas->exit_code == 131) signal(SIGINT, nothing);
printf("Quit: 3\n"); signal(SIGQUIT, nothing);
} }
else else
datas->exit_code = WEXITSTATUS(status); {
} termios_p.c_lflag &= ~(ECHOCTL);
signal(SIGINT, sigs_handler);
void nothing(int sig_num) signal(SIGQUIT, sigs_handler);
{ }
(void)sig_num; termios_p.c_cc[VQUIT] = ctl * 28;
tcsetattr(tty, TCSANOW, &termios_p);
} }
void sigs_handler(int sig_num) void sigs_handler(int sig_num)
@ -50,18 +61,8 @@ void sigs_handler(int sig_num)
return ; 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"); printf("exit\n");
exit(ret_code); exit(ret_code);
} }

100
utils_2.c

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