Browse Source

fix fix

master
Michael Ea 3 years ago
parent
commit
b3dc5f9eb7
  1. 18
      README.md
  2. 55
      built-in.c
  3. 83
      caller.c
  4. 121
      env.c
  5. 207
      lexer.c
  6. 165
      minishell.c
  7. 48
      minishell.h
  8. 90
      parser.c
  9. 47
      utils.c
  10. 121
      utils_2.c

18
README.md

@ -2,17 +2,15 @@
--- ---
## TODO : ## TODO :
- free stack, - Protect mallocs,
- protect mallocs, - verify exits codes
- Norminette
- Finish check_builtin();
- export : edit datas->env
- unset : idem,
- exit: handle arguments
- setup correct ext_codes
https://wiki.bash-hackers.org/scripting/basics?s[]=variables#exit_codes https://wiki.bash-hackers.org/scripting/basics?s[]=variables#exit_codes
- do the `(...)` -> `./minishell ...` conversion
- finish && and ||
## Issues : ## 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/03 18:18:23 by narnaud ### ########.fr */ /* Updated: 2022/05/07 23:17:15 by narnaud@stude ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -15,33 +15,44 @@
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;
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; no_nl = 1;
while (*(cmd->argv)) while (cmd->argv[i])
{ {
ft_putstr_fd(*(cmd->argv), 1); ft_putstr_fd(cmd->argv[i], fd_out);
if (*(++cmd->argv)) if (cmd->argv[++i])
ft_putstr_fd(" ", 1); ft_putstr_fd(" ", fd_out);
} }
} }
if (!no_nl) if (!no_nl)
ft_putstr_fd("\n", 1); ft_putstr_fd("\n", fd_out);
return (0); return (0);
} }
int ft_pwd(t_command *cmd) int ft_pwd(t_command *cmd)
{ {
char *dir; 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)); dir = ft_calloc(PATHS_MAX_SIZE, sizeof(char));
getcwd(dir, PATHS_MAX_SIZE); getcwd(dir, PATHS_MAX_SIZE);
ft_putstr_fd(dir, 1); ft_putstr_fd(dir, fd_out);
ft_putstr_fd("\n", 1); ft_putstr_fd("\n", fd_out);
free(dir); free(dir);
return (0); return (0);
} }
@ -51,26 +62,24 @@ 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], \
printf("Minishell: %s: %s: Permission denied\n", cmd->argv[0], cmd->argv[1]); "Permission denied\n"));
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], \
printf("Minishell: %s: %s: Not a directory\n", cmd->argv[0], cmd->argv[1]); "Not a directory\n"));
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 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 :+: :+: :+: */ /* caller.c :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */ /* By: mea <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/03 11:48:16 by narnaud #+# #+# */ /* 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" #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) if (ft_strncmp(cmd->argv[0], "echo", 5) == 0)
return (ft_echo(cmd)); 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) 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)); return (ft_env(datas, cmd));
else if (ft_strncmp(cmd->argv[0], "exit", 5) == 0) else if (ft_strncmp(cmd->argv[0], "exit", 5) == 0)
return (close_minishell(0)); return (ft_exit(datas, cmd));
else else
return (-1); 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_dirs;
char *path; 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_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, cmd->argv[0], ft_strlen(cmd->argv[0])); ft_memcpy(path + ft_strlen(*path_dirs) + 1, \
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,79 +6,138 @@
/* 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/05 09:30:51 by narnaud ### ########.fr */ /* Updated: 2022/05/07 23:38:40 by narnaud@stude ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
int is_valid_identifier(char *ident) static void clean_env(t_datas *datas, int i);
{
if (ft_isalpha(ident[0]) || ident[0] == '_')
{
while (*ident)
{
if (!ft_isalpha(*ident) && !ft_isdigit(*ident) && *ident != '_')
return (0);
ident++;
}
return (1);
}
return (0);
}
int ft_unset(t_datas *datas, t_command *cmd) int ft_unset(t_datas *datas, t_command *cmd)
{ {
(void)datas; char **env;
if (!cmd->argv[1]) int i;
{ int j;
//read(input_fd, PIPE_MAX_SIZE); int name_len;
if (cmd->argc < 2)
return (1); 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); 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; i = 0;
while (datas->envp[i]) 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++; 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], ft_strlen(new[0]) + 1)) if (!ft_strncmp(new[0], env[0], name_len + 1))
{ datas->envp[i] = (free(datas->envp[i]), NULL);
datas->envp[i] = cmd->argv[1]; else
return (1);
}
i++; i++;
ft_free_split(env);
} }
datas->envp[i] = cmd->argv[1]; ft_free_split(new);
datas->envp[i + 1] = NULL; datas->envp[i] = ft_strdup(cmd->argv[1]);
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);
}

207
lexer.c

@ -6,15 +6,78 @@
/* 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/05 15:41:06 by mea ### ########.fr */ /* Updated: 2022/05/10 10:12:58 by mea ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #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 *tok;
t_token *tmp;
t_type type; t_type type;
type = lex->type; type = lex->type;
@ -23,132 +86,68 @@ int create_token(t_lexer *lex, char str[])
else else
lex->type = WORD; lex->type = WORD;
lex->next_type = WORD; lex->next_type = WORD;
if (!str[0]) if (!str[0] && !lex->empty)
return (0); return (0);
tok = lex->tokens; tok = ft_calloc(1, sizeof(*tok));
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 = strdup(str); tok->value = ft_strdup(str);
if (DEBUG) tmp = lex->tokens;
printf("token value : %s - token type : %d\n", tok->value, type); while (tmp && tmp->next)
if (!lex->tokens) tmp = tmp->next;
if (!tmp)
lex->tokens = tok; lex->tokens = tok;
else
tmp->next = tok;
lex->empty = 0;
return (1); 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 (!ft_strncmp(*line, "&&", 2))
if (lex->state != ROOT_ST)
return (0);
spaces = 0;
if (ft_isspace(**line))
{
while (ft_isspace(**line))
(*line)++;
spaces = 1;
}
if (**line == '>' && (*line)++)
{ {
if (**line == '>' && (*line)++) (*line) += 2;
lex->next_type = ADD; lex->next_type = AND;
else create_token(lex, tmp);
lex->next_type = OUT; return (create_token(lex, "&&"));
return (create_token(lex, tmp));
} }
else if (**line == '<' && (*line)++) if (!ft_strncmp(*line, "||", 2))
{ {
if (**line == '<' && (*line)++) (*line) += 2;
lex->next_type = HD; lex->next_type = OR;
else create_token(lex, tmp);
lex->next_type = IN; return (create_token(lex, "||"));
return (create_token(lex, tmp));
} }
else if (**line == '|') 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));
} }
int replace_var(t_datas *datas, char **line, char *tmp, int tmp_i) static int check_register(t_lexer *lex, char **line, char *tmp)
{ {
int name_len; int spaces;
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);
}
int check_state(t_lexer *lex, char **line)
{
t_state new;
new = OLD_ST; if (lex->state != ROOT_ST || lex->deep > 0)
if (**line == '"') return (0);
{ spaces = 0;
if (lex->state == D_QUOTE_ST) if (!*tmp && (*(*line - 1) == '"' || *(*line - 1) == '\''))
new = ROOT_ST; lex->empty = 1;
else if (lex->state == ROOT_ST) if (ft_isspace(**line))
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)
{ {
while (ft_isspace(**line))
(*line)++; (*line)++;
lex->state = new; spaces = 1;
return (1);
} }
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); return (0);
} }

165
minishell.c

@ -6,150 +6,85 @@
/* 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/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;
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) tty = ttyslot();
tcgetattr(tty, &termios_p);
if (ctl)
{ {
pipe(pip); termios_p.c_lflag |= ECHOCTL;
cmd->fd[1] = pip[1]; signal(SIGINT, nothing);
cmd->next->fd[0] = pip[0]; signal(SIGQUIT, nothing);
} }
else
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]) termios_p.c_lflag &= ~(ECHOCTL);
dup2(cmd->fd[0], STDIN_FILENO); signal(SIGINT, sigs_handler);
if (cmd->fd[1]) signal(SIGQUIT, sigs_handler);
dup2(cmd->fd[1], STDOUT_FILENO);
if (command_call(datas, cmd) == -1)
exe(datas, cmd);
exit(EXIT_SUCCESS);
} }
if (cmd->fd[1]) termios_p.c_cc[VQUIT] = ctl * 28;
close(cmd->fd[1]); tcsetattr(tty, TCSANOW, &termios_p);
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);
} }
t_command *parser(t_datas *datas, t_token *tok, t_command *prev) void free_cmd(t_command *cmd)
{ {
int i; int i;
t_command *cmd;
if (!tok) if (!cmd)
return (NULL); return ;
cmd = ft_calloc(1, sizeof(t_command));
if (prev)
cmd->prev = prev;
i = 0; i = 0;
cmd->argv = ft_calloc(count_arguments(tok) + 1, sizeof(char *)); while (cmd->argv[i])
while(tok && tok->type != PIPE)
{ {
if (tok->type) free(cmd->argv[i]);
update_redir(datas, cmd, tok); i++;
else
cmd->argv[i++] = tok->value;
tok = tok->next;
} }
if (DEBUG) free(cmd->argv);
printf("######\n->cmd : %s, in_fd : %d, out_fd : %d\n", \ free_cmd(cmd->next);
cmd->argv[0], cmd->fd[0], cmd->fd[1]); free(cmd);
cmd->argv[i] = NULL;
if (tok && tok->type == PIPE)
cmd->next = parser(datas, tok->next, cmd);
return(cmd);
} }
t_token *lexer(t_datas *datas, char *line) void prompt(t_datas *datas)
{ {
t_lexer *lex; char *line;
char *tmp; t_command *cmd;
int tmp_i;
lex = ft_calloc(1, sizeof *lex); termios(0);
lex->state = ROOT_ST; line = readline("$ ");
tmp = ft_calloc(1024, sizeof *tmp); termios(1);
tmp_i = 0; if (line == NULL)
while (*line) halt(datas, EXIT_SUCCESS);
{ if (is_empty(line))
if (check_state(lex, &line)) return ;
continue; cmd = parser(datas, lexer(datas, line), NULL);
if (lex->state != S_QUOTE_ST && *line == '$') if (!cmd->prev && !cmd->next && is_builtin(cmd->argv[0]))
tmp_i = replace_var(datas, &line, tmp, tmp_i); builtin_call(datas, cmd);
if (check_register(lex, &line, tmp)) else
{ piper(datas, cmd);
tmp_i = 0; free_cmd(cmd);
ft_bzero(tmp, 1024); add_history(line);
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)
{ {
t_datas datas; static t_datas datas;
char *line; static int i = 0;
char **env_copy;
int i;
env_copy = ft_calloc(1024, sizeof(char *)); datas.envp = ft_calloc(ENVP_MAX_SIZE, sizeof(char *));
i = 0; while (*envp)
while (envp[i]) datas.envp[i++] = ft_strdup(*(envp++));
{
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);
termios(0); halt(&datas, EXIT_SUCCESS);
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);
} }

48
minishell.h

@ -6,16 +6,15 @@
/* 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/05 14:18:56 by mea ### ########.fr */ /* Updated: 2022/05/10 10:20:04 by mea ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef MINISHELL_H #ifndef MINISHELL_H
# define 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 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>
@ -34,8 +33,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;
@ -48,36 +47,45 @@ typedef struct s_datas
// ----------------------------------Utils.c // ----------------------------------Utils.c
int is_empty(char *line); int is_empty(char *line);
void halt(int ret_code); void handle_status(t_datas *datas, int status);
void termios(int ctl); void nothing(int sig_num);
void sigs_handler(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 // ----------------------------------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); int ft_env(t_datas *datas, t_command *cmd);
int ft_export(t_datas *datas, t_command *cmd); int ft_export(t_datas *datas, t_command *cmd);
// ----------------------------------Caller.c // ----------------------------------Caller.c
void exe(t_datas *datas, t_command *cmd); int is_builtin(char *cmd);
int command_call(t_datas *datas, t_command *cmd); int builtin_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
@ -87,11 +95,9 @@ typedef struct s_token
struct s_token *next; struct s_token *next;
} t_token; } t_token;
size_t count_arguments(t_token *tok); t_command *parser(t_datas *datas, t_token *tok, t_command *prev);
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,
@ -106,13 +112,11 @@ 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;
int empty;
} t_lexer; } t_lexer;
int create_token(t_lexer *lex, char str[]); t_token *lexer(t_datas *datas, char *line);
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,43 +6,79 @@
/* 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/05 14:30:11 by mea ### ########.fr */ /* Updated: 2022/05/09 09:56:29 by narnaud ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #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; t_command *cmd;
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);
}
tmp = ft_calloc(1024, sizeof *tmp); static size_t count_arguments(t_token *tok)
if (!tmp) {
free(tmp); size_t ret;
tmp_i = 0;
while (*line) ret = 0;
while (tok && tok->type != PIPE)
{ {
if (*line == '$') if (tok->type == WORD)
tmp_i = replace_var(datas, &line, tmp, tmp_i); ret++;
tmp[tmp_i] = *line; tok = tok->next;
line++;
tmp_i++;
} }
return (tmp); return (ret);
} }
int push_heredoc(t_datas *datas, char *str) 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);
}
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);
} }
@ -50,21 +86,7 @@ int push_heredoc(t_datas *datas, char *str)
return (pip[0]); 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 == 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)
{ {
@ -91,5 +113,3 @@ 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/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); return (1);
} }
void nothing(int sig_num) void handle_status(t_datas *datas, int status)
{
(void)sig_num;
}
void termios(int ctl)
{ {
struct termios termios_p; if (WIFSIGNALED(status))
int tty;
tty = ttyslot();
if (tcgetattr(tty, &termios_p) < 0)
exit ((perror("stdin"), EXIT_FAILURE));
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);
termios_p.c_lflag &= ~(ECHOCTL); }
signal(SIGINT, sigs_handler);
signal(SIGQUIT, sigs_handler); void nothing(int sig_num)
} {
termios_p.c_cc[VQUIT] = ctl * 28; (void)sig_num;
tcsetattr(tty, TCSANOW, &termios_p);
} }
void sigs_handler(int sig_num) void sigs_handler(int sig_num)
@ -61,8 +50,18 @@ void sigs_handler(int sig_num)
return ; 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"); printf("exit\n");
exit(ret_code); 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