Skip to content

Commit

Permalink
Merge pull request #99 from LeaYeh/feat-builtin-exit
Browse files Browse the repository at this point in the history
[FEAT] Implement builtin of exit
  • Loading branch information
LeaYeh authored Jan 21, 2024
2 parents ff352d6 + c23534d commit 9596430
Show file tree
Hide file tree
Showing 17 changed files with 200 additions and 67 deletions.
17 changes: 14 additions & 3 deletions include/builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,19 @@

# include "defines.h"

int ft_exec_env(t_shell *shell);
int ft_exec_echo(char **args);
int ft_exec_pwd(void);
typedef enum e_exit_args_error
{
NO_ARGS = -1,
NORM_ARGS = 0,
TOO_MANY_ARGS,
NOT_NUMERIC,
} t_exit_args_error;

int ft_exec_env(t_shell *shell);
int ft_exec_echo(char **args);
int ft_exec_pwd(void);
void exec_exit(t_shell *shell, t_final_cmd_table *final_cmd_table);

int get_args_error(char **args);

#endif
74 changes: 40 additions & 34 deletions include/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

# include <fcntl.h>
# include <linux/limits.h>
# include <limits.h>
# include <sysexits.h>
# include <sys/stat.h>
# include <sys/wait.h>
# include <unistd.h>
Expand All @@ -32,60 +34,60 @@
/* Error codes */
# define SUCCESS 0
# define EXIT_SUCCESS 0
# define GENERAL_ERROR 1

# define BAD_SUBSTITUTION 2
// # define EXPAND_ERROR 2
# define MISUSE_BUILTIN 2
# define CMD_EXEC_FAILED 126
# define CMD_NOT_FOUND 127
# define TERM_BY_SIGNAL 128
# define UNEXPECT_EXIT 128
# define TERM_BY_SIGNAL 128
# define EXIT_SIGTERM 130
# define PREPROCESS_ERROR 195
# define SUBSHELL_ERROR 196

/* Parsing Table */
# define PT_COL_SIZE 5
# define PT_ROW_SIZE 191
# define UNDEFINED_TYPE -99
# define UNDEFINED_STATE -1

# define STY_BLD "\e[1m"
# define STY_UND "\e[4m"
# define STY_RED "\e[31m"
# define STY_GRN "\e[32m"
# define STY_YEL "\e[33m"
# define STY_BLU "\e[34m"
# define STY_MAG "\e[35m"
# define STY_CYN "\e[36m"
# define STY_WHT "\e[37m"
# define STY_GRY "\e[90m"
# define STY_HWHT "\e[97m"
# define STY_BLKB "\e[41m"
# define STY_REDB "\e[41m"
# define STY_GRNB "\e[42m"
# define STY_YELB "\e[43m"
# define STY_BLUB "\e[44m"
# define STY_MAGB "\e[45m"
# define STY_CYNB "\e[46m"
# define STY_WHTB "\e[47m"
# define STY_GRYB "\e[100m"
# define STY_HWHTB "\e[107m"
# define STY_RES "\e[0m"

# define STY_BLD "\e[1m"
# define STY_UND "\e[4m"
# define STY_RED "\e[31m"
# define STY_GRN "\e[32m"
# define STY_YEL "\e[33m"
# define STY_BLU "\e[34m"
# define STY_MAG "\e[35m"
# define STY_CYN "\e[36m"
# define STY_WHT "\e[37m"
# define STY_GRY "\e[90m"
# define STY_HWHT "\e[97m"
# define STY_BLKB "\e[41m"
# define STY_REDB "\e[41m"
# define STY_GRNB "\e[42m"
# define STY_YELB "\e[43m"
# define STY_BLUB "\e[44m"
# define STY_MAGB "\e[45m"
# define STY_CYNB "\e[46m"
# define STY_WHTB "\e[47m"
# define STY_GRYB "\e[100m"
# define STY_HWHTB "\e[107m"
# define STY_RES "\e[0m"
// TODO: Remove the color codes from the prompt before the evaluations
# define PROMPT "\e[1;34m🌊rash$ \e[0m"
// # define PROMPT "\e[1;32mminishell$ \e[0m"
# define PROMPT "\e[1;34m🌊rash$ \e[0m"
// # define PROMPT "\e[1;32mminishell$ \e[0m"
# define HEREDOC_PROMPT "\e[1;37m> \e[0m"
// # define PROMPT "\001\033[1;32m\002minishell$ \001\033[0m\002"
// # define PROMPT "minishell$ "
// # define PROMPT "\001\033[1;32m\002minishell$ \001\033[0m\002"
// # define PROMPT "minishell$ "

/* Lexer */
# define QUOTES "'\""
# define TOK_SYMBOLS "<>|&()"
# define T_UNINITIALIZED -1 //TODO Replace with Lea's UNDEFINED_TYPE -99

/* Expander */
# define OPENING_BRACE '{'
# define CLOSING_BRACE '}'
# define OPENING_BRACE '{'
# define CLOSING_BRACE '}'

/* Error Messages */
// TODO Add minishell name in the front of messages
Expand All @@ -95,10 +97,14 @@
"%s: warning: here-document delimited by end-of-file (wanted `%s')\n"
# define ERROR_EXPANDER_BAD_SUBSTITUTION \
"%s: %s: bad substitution\n"
# define ERROR_EXIT_TOO_MANY_ARGS \
"%s: %s: too many arguments\n"
# define ERROR_EXIT_NUMERIC_ARG \
"%s: %s: %s: numeric argument required\n"

// TODO: Replace with OS error message
# define ERROR_REMOVE_FILE "%s: \
warning: failed to remove file `%s'\n"
# define ERROR_REMOVE_FILE \
"%s: warning: failed to remove file `%s'\n"

extern const int g_parsing_table[][PT_COL_SIZE];

Expand Down
9 changes: 5 additions & 4 deletions source/backend/executor/executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void handle_cmd_execution(t_shell *shell, t_list_d **cmd_table_node)
final_cmd_table = get_final_cmd_table(shell, (*cmd_table_node)->content);
if (!final_cmd_table)
ft_clean_and_exit_shell(
shell, GENERAL_ERROR, "final cmd table malloc failed");
shell, PREPROCESS_ERROR, "final cmd table malloc failed");
if (is_builtin(final_cmd_table->simple_cmd[0]) && \
!is_scmd_in_pipeline(*cmd_table_node))
{
Expand Down Expand Up @@ -54,15 +54,16 @@ void handle_process(t_shell *shell, t_list_d *cmd_table_node)
else if (cmd_table->type == C_SUBSHELL_START)
handle_pipeline(shell, &cmd_table_node);
else
ft_clean_and_exit_shell(
shell, GENERAL_ERROR, "handle process, unknown command type");
ft_clean_and_exit_shell(shell,
PREPROCESS_ERROR, "handle process, unknown command type");
}
}

// TODO: activate signal listener in the child process
void ft_executor(t_shell *shell)
{
if (!ft_heredoc(shell->cmd_table_list))
ft_clean_and_exit_shell(shell, GENERAL_ERROR, "heredoc malloc failed");
ft_clean_and_exit_shell(
shell, PREPROCESS_ERROR, "heredoc malloc failed");
handle_process(shell, shell->cmd_table_list);
}
2 changes: 1 addition & 1 deletion source/backend/executor/handle_builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void exec_builtin_cmd(t_shell *shell, t_final_cmd_table *final_cmd_table)
else if (ft_strcmp(final_cmd_table->simple_cmd[0], "export") == 0)
shell->exit_code = 123;
else if (ft_strcmp(final_cmd_table->simple_cmd[0], "exit") == 0)
shell->exit_code = 123;
exec_exit(shell, final_cmd_table);
}

void handle_builtin(t_shell *shell,
Expand Down
2 changes: 1 addition & 1 deletion source/backend/executor/handle_pipeline.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void handle_pipeline(t_shell *shell, t_list_d **cmd_table_node)
shell->subshell_pid = fork();
if (shell->subshell_pid == -1)
ft_clean_and_exit_shell(
shell, GENERAL_ERROR, "handle_pipeline, fork failed");
shell, SUBSHELL_ERROR, "handle_pipeline, fork failed");
else if (shell->subshell_pid == 0)
{
shell->subshell_level += 1;
Expand Down
4 changes: 2 additions & 2 deletions source/backend/executor/handle_simple_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void exec_simple_cmd(t_shell *shell, t_list_d **cmd_table_node)
final_cmd_table = get_final_cmd_table(shell, cmd_table);
if (!final_cmd_table)
ft_clean_and_exit_shell(
shell, GENERAL_ERROR, "get_final_cmd_table failed");
shell, SUBSHELL_ERROR, "get_final_cmd_table failed");
print_final_cmd_table(final_cmd_table);
if (final_cmd_table->simple_cmd[0] == NULL)
printf("\n");
Expand All @@ -59,7 +59,7 @@ void handle_simple_cmd(t_shell *shell, t_list_d **cmd_table_node)
shell->subshell_pid = fork();
if (shell->subshell_pid == -1)
ft_clean_and_exit_shell(
shell, GENERAL_ERROR, "handle_simple_cmd, fork failed");
shell, SUBSHELL_ERROR, "handle_simple_cmd, fork failed");
else if (shell->subshell_pid == 0)
{
shell->subshell_level += 1;
Expand Down
2 changes: 1 addition & 1 deletion source/backend/executor/handle_subshell.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void handle_subshell(t_shell *shell, t_list_d **cmd_table_node)
{
shell->subshell_pid = fork();
if (shell->subshell_pid == -1)
ft_clean_and_exit_shell(shell, GENERAL_ERROR, "subshell fork failed");
ft_clean_and_exit_shell(shell, SUBSHELL_ERROR, "subshell fork failed");
else if (shell->subshell_pid == 0)
{
shell->subshell_level += 1;
Expand Down
37 changes: 37 additions & 0 deletions source/builtins/exit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "builtins.h"
#include "utils.h"
#include "clean.h"

void handle_exit(
t_shell *shell, t_final_cmd_table *final_cmd_table, int args_error)
{
if (shell->subshell_level == 0)
printf("exit\n");
if (args_error == TOO_MANY_ARGS)
{
ft_dprintf(2, ERROR_EXIT_TOO_MANY_ARGS, PROGRAM_NAME, "exit");
if (shell->subshell_level == 0)
return ;
}
else if (args_error == NOT_NUMERIC)
ft_dprintf(2, ERROR_EXIT_NUMERIC_ARG,
PROGRAM_NAME, "exit", final_cmd_table->simple_cmd[1]);
free_final_cmd_table(&final_cmd_table);
ft_clean_and_exit_shell(shell, shell->exit_code, NULL);
}

void exec_exit(t_shell *shell, t_final_cmd_table *final_cmd_table)
{
int args_error;
char **args;

args = &final_cmd_table->simple_cmd[1];
args_error = get_args_error(args);
if (args_error == NO_ARGS)
shell->exit_code = SUCCESS;
else if (args_error == NORM_ARGS)
shell->exit_code = (ft_atol(args[0])) % 256;
else
shell->exit_code = args_error;
handle_exit(shell, final_cmd_table, args_error);
}
76 changes: 76 additions & 0 deletions source/builtins/exit_utils.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "defines.h"
#include "utils.h"
#include "builtins.h"

bool is_sign(char c)
{
if (c == '+' || c == '-')
return (true);
return (false);
}

bool valid_number(char *str)
{
int i;

if (!str)
return (false);
i = 0;
if (ft_strlen(str) > 1 && is_sign(str[i]))
i++;
while (str[i])
{
if (ft_isdigit(str[i]))
i++;
else
return (false);
}
return (true);
}

bool is_atol_overflow(char *str)
{
int i;
char *long_max;

i = 0;
if (str[i] == '-')
long_max = "9223372036854775808";
else
long_max = "9223372036854775807";
if (is_sign(str[i]))
i++;
while (str[i] == '0')
i++;
if (ft_strlen(&str[i]) < ft_strlen(long_max) || \
ft_strcmp(&str[i], long_max) <= 0)
return (false);
return (true);
}

int get_args_error(char **args)
{
int type;
// int i;

if (!*args)
return (NO_ARGS);
type = NORM_ARGS;
if (!valid_number(args[0]) || is_atol_overflow(args[0]))
type = NOT_NUMERIC;
else if (get_array_len(args) > 1)
{
type = TOO_MANY_ARGS;
// i = 1;
// while (args[i])
// {
// if (!valid_number(args[i]) || is_overflow(args[i]))
// {
// type = NOT_NUMERIC;
// break ;
// }
// i++;
// }
}
return (type);
}
2 changes: 1 addition & 1 deletion source/debug/print_expanded_cmd_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ bool expand_and_print(char *str, t_shell *shell)

expanded_list = NULL;
ret = ft_expander(str, &expanded_list, shell);
if (ret == GENERAL_ERROR)
if (ret == SUBSHELL_ERROR)
return (printf("malloc failed in expander"), false);
if (ret == BAD_SUBSTITUTION)
printf(STY_RED "Bad substitution." STY_RES);
Expand Down
8 changes: 4 additions & 4 deletions source/frontend/expander/expander.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,16 @@ int ft_expander(char *str, t_list **lst, t_shell *shell)
return (BAD_SUBSTITUTION);
dup = ft_strdup(str);
if (!dup)
return (GENERAL_ERROR);
return (SUBSHELL_ERROR);
if (!parameter_expansion(&dup, shell))
return (free(dup), GENERAL_ERROR);
return (free(dup), SUBSHELL_ERROR);
if (!*dup)
return (free(dup), SUCCESS);
if (!quote_removal(&dup))
return (free(dup), GENERAL_ERROR);
return (free(dup), SUBSHELL_ERROR);
// TODO: Potentially split into multiple nodes by whitespace here.
// The keyword in the bash manual is "Word Splitting".
if (!ft_lstnew_back(lst, dup))
return (free(dup), GENERAL_ERROR);
return (free(dup), SUBSHELL_ERROR);
return (SUCCESS);
}
6 changes: 3 additions & 3 deletions source/frontend/lexer/lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ bool ft_lexer(t_shell *shell)
if (!create_token_data_list(&token_data_list, shell->input_line))
{
ft_lstclear(&token_data_list, free);
ft_clean_and_exit_shell(shell, GENERAL_ERROR, "lexer malloc failed");
ft_clean_and_exit_shell(shell, PREPROCESS_ERROR, "lexer malloc failed");
}
if (!token_data_list)
return (false);
if (!create_token_list(&shell->token_list, &token_data_list))
{
ft_lstclear(&token_data_list, free);
ft_clean_and_exit_shell(shell, GENERAL_ERROR, "lexer malloc failed");
ft_clean_and_exit_shell(shell, PREPROCESS_ERROR, "lexer malloc failed");
}
set_token_type(shell->token_list);
finetune_token_list(shell->token_list);
if (!add_end_node(&shell->token_list))
ft_clean_and_exit_shell(shell, GENERAL_ERROR, "lexer malloc failed");
ft_clean_and_exit_shell(shell, PREPROCESS_ERROR, "lexer malloc failed");
return (true);
}
Loading

0 comments on commit 9596430

Please sign in to comment.