mirror of
https://github.com/Savapitech/42sh.git
synced 2026-03-18 21:50:35 +01:00
1
Makefile
1
Makefile
@@ -13,6 +13,7 @@ LIB_NAME := libu.a
|
||||
|
||||
SRC := $(wildcard src/*.c)
|
||||
SRC += $(wildcard src/builtins/*.c)
|
||||
SRC += $(wildcard src/utils/*.c)
|
||||
|
||||
LIB_SRC := $(wildcard ulib/*.c)
|
||||
LIB_SRC += $(wildcard ulib/write/printf/*.c)
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
#define AST_H
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "env.h"
|
||||
#include "builtins_handler.h"
|
||||
|
||||
#define DEFAULT_AST_CAP 128
|
||||
#define T_ALL 0xff
|
||||
@@ -96,7 +95,7 @@ extern const tokens_list_t TOKENS_LIST[];
|
||||
ast_t *parse_expression(ast_ctx_t *ctx);
|
||||
void print_ast(ast_ctx_t *ctx, ast_t *ast, size_t depth);
|
||||
token_t get_next_token(ast_ctx_t *ctx);
|
||||
int visitor(char *buffer, env_t *env, history_t *history);
|
||||
int visitor(char *buffer, exec_ctx_t *exec_ctx);
|
||||
ast_t *create_node(ast_ctx_t *ctx);
|
||||
bool ensure_node_cap(ast_t *node);
|
||||
bool ensure_list_cap(ast_t *node);
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
typedef struct {
|
||||
char const *name;
|
||||
int (*ptr)(ef_t *ef, char **args);
|
||||
} builtins_t;
|
||||
} builtins_funcs_t;
|
||||
|
||||
extern const builtins_t BUILTINS[];
|
||||
extern const builtins_funcs_t BUILTINS[];
|
||||
extern const size_t BUILTINS_SZ;
|
||||
|
||||
int builtins_exit(ef_t *ef, char **args);
|
||||
@@ -25,4 +25,5 @@ int builtins_unsetenv(ef_t *ef, char **args);
|
||||
int builtins_cd(ef_t *ef, char **args);
|
||||
int builtins_builtins(ef_t *ef, char **args);
|
||||
int builtins_funny_double_dot(ef_t *ef, char **args);
|
||||
int builtins_history(ef_t *ef, char **args);
|
||||
#endif /* BUILTIND_H */
|
||||
|
||||
176
src/builtins/builtin_history.c
Normal file
176
src/builtins/builtin_history.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** history_42sh
|
||||
** File description:
|
||||
** builtin_history
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "history.h"
|
||||
|
||||
/*
|
||||
**Il faut deux \0 parce que dans le gettokeniser
|
||||
** y un truc qui regarde
|
||||
**après le premier \0
|
||||
*/
|
||||
|
||||
/*
|
||||
**cat in str prend un
|
||||
** his_variable_t en
|
||||
** parametre pour
|
||||
** connaitre la coord
|
||||
** d' ou commencer a concaténer
|
||||
** mais aussi le nombre de charactère a retiré
|
||||
** il vas free le buffer
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *concat_cmd_arg(char *dest, char *src)
|
||||
{
|
||||
int l;
|
||||
int i;
|
||||
char *r_value = NULL;
|
||||
|
||||
if (!src) {
|
||||
r_value = u_strdup(dest);
|
||||
return r_value;
|
||||
} else {
|
||||
l = strlen(dest);
|
||||
i = strlen(src);
|
||||
r_value = malloc(sizeof(char)* (i + l + 2));
|
||||
if (r_value != NULL) {
|
||||
strcpy(r_value, dest);
|
||||
r_value[l] = ' ';
|
||||
r_value[l +1] = '\0';
|
||||
strcat(r_value, src);
|
||||
}
|
||||
}
|
||||
return r_value;
|
||||
}
|
||||
|
||||
char *his_last_command(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command)
|
||||
{
|
||||
char *new_line = NULL;
|
||||
char *new_str = NULL;
|
||||
|
||||
if (his_command->sz == 0){
|
||||
printf("%d: Event not found\n", his_command->sz);
|
||||
return NULL;
|
||||
}
|
||||
new_line = concat_cmd_arg(his_command[his_command->sz - 1].command,
|
||||
his_command[his_command->sz - 1].arg);
|
||||
new_str = cat_in_str(his_variable, line, new_line);
|
||||
printf("%s\n", new_line);
|
||||
free(new_line);
|
||||
free(line);
|
||||
return new_str;
|
||||
}
|
||||
|
||||
char *his_last_same_command(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command)
|
||||
{
|
||||
char *new_line = &line[his_variable->coord_variable + 1];
|
||||
char *new_str = NULL;
|
||||
|
||||
for (int i = his_command->sz - 1; i > 0; i--) {
|
||||
if (his_command[i].command == NULL) {
|
||||
printf("%s: Event not found\n", new_line);
|
||||
return new_str;
|
||||
}
|
||||
if (strncmp(his_command[i].command, new_line, strlen(new_line)) == 0) {
|
||||
new_line = concat_cmd_arg(his_command[i].command,
|
||||
his_command[i].arg);
|
||||
new_str = cat_in_str(his_variable, line, new_line);
|
||||
free(line);
|
||||
return new_str;
|
||||
}
|
||||
}
|
||||
printf("%s: Event not found\n", new_line);
|
||||
return new_str;
|
||||
}
|
||||
|
||||
char *his_id_command(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command)
|
||||
{
|
||||
int id = -1 + atoi(&line[his_variable->coord_variable + 1]);
|
||||
char *new_line;
|
||||
char *new_str = NULL;
|
||||
|
||||
if (id < 0 || id > 100 || his_command[id].command == NULL){
|
||||
printf("%d: Event not found\n", id + 1);
|
||||
return new_str;
|
||||
}
|
||||
new_line = concat_cmd_arg(his_command[id].command, his_command[id].arg);
|
||||
new_str = cat_in_str(his_variable, line, new_line);
|
||||
printf("%s\n", new_str);
|
||||
free(new_line);
|
||||
free(line);
|
||||
return new_str;
|
||||
}
|
||||
|
||||
static char *get_last_word(char *str)
|
||||
{
|
||||
char *last_word = NULL;
|
||||
int last_space = 0;
|
||||
int x = 0;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
while (str[x] != '\0') {
|
||||
if (isblank(str[x]))
|
||||
last_space = x + 1;
|
||||
x++;
|
||||
}
|
||||
last_word = malloc(sizeof(char) * (x - last_space) + 1);
|
||||
if (last_word != NULL) {
|
||||
last_word = strncpy(last_word, &str[last_space], x - last_space);
|
||||
last_word[x - last_space] = '\0';
|
||||
}
|
||||
return last_word;
|
||||
}
|
||||
|
||||
char *his_last_word(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command)
|
||||
{
|
||||
char *new_line = NULL;
|
||||
char *new_str = NULL;
|
||||
|
||||
if (his_command[his_command->sz - 1].arg == NULL){
|
||||
new_line = get_last_word(his_command[his_command->sz - 1].command);
|
||||
} else
|
||||
new_line = get_last_word(his_command[his_command->sz - 1].arg);
|
||||
if (!new_line)
|
||||
return NULL;
|
||||
new_str = cat_in_str(his_variable, line, new_line);
|
||||
printf("%s\n", new_str);
|
||||
free(new_line);
|
||||
free(line);
|
||||
return new_str;
|
||||
}
|
||||
|
||||
char *his_last_arg(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command)
|
||||
{
|
||||
int id = his_command->sz - 1;
|
||||
char *new_line = NULL;
|
||||
char *new_str = NULL;
|
||||
|
||||
if (!his_command[id].arg)
|
||||
new_line = " ";
|
||||
else
|
||||
new_line = u_strdup(his_command[id].arg);
|
||||
new_str = cat_in_str(his_variable, line, new_line);
|
||||
printf("%s\n", new_line);
|
||||
if (his_command[id].arg)
|
||||
free(new_line);
|
||||
free(line);
|
||||
return new_str;
|
||||
}
|
||||
@@ -62,17 +62,17 @@ int builtins_cd_chdir(ef_t *ef, char **args, char *path)
|
||||
{
|
||||
char *act_pwd;
|
||||
|
||||
if (ef->history->last_chdir != NULL && args[1] != NULL
|
||||
if (ef->exec_ctx->history->last_chdir != NULL && args[1] != NULL
|
||||
&& u_strcmp(args[1], "-") == 0)
|
||||
path = ef->history->last_chdir;
|
||||
path = ef->exec_ctx->history->last_chdir;
|
||||
act_pwd = get_current_dir();
|
||||
if (chdir(path) < 0) {
|
||||
write(STDERR_FILENO, path, u_strlen(path));
|
||||
cd_print_error();
|
||||
return RETURN_FAILURE;
|
||||
}
|
||||
free(ef->history->last_chdir);
|
||||
ef->history->last_chdir = act_pwd;
|
||||
free(ef->exec_ctx->history->last_chdir);
|
||||
ef->exec_ctx->history->last_chdir = act_pwd;
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,5 +23,5 @@ int builtins_exit(ef_t *ef, char **args __attribute__((unused)))
|
||||
}
|
||||
free_env(ef->env);
|
||||
free(ef->buffer);
|
||||
exit(ef->history->last_exit_code);
|
||||
exit(ef->exec_ctx->history->last_exit_code);
|
||||
}
|
||||
|
||||
25
src/builtins/history.c
Normal file
25
src/builtins/history.c
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** 42sh
|
||||
** File description:
|
||||
** history
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
#include "env.h"
|
||||
#include "exec.h"
|
||||
|
||||
int builtins_history(ef_t *ef, char **args __attribute__((unused)))
|
||||
{
|
||||
his_command_t *cmd_history = ef->exec_ctx->history_command;
|
||||
|
||||
for (int i = 0; i < cmd_history->sz; i++){
|
||||
if (cmd_history[i].arg) {
|
||||
printf("%d %s %s\n", i + 1, cmd_history[i].command,
|
||||
cmd_history[i].arg);
|
||||
} else
|
||||
printf("%d %s\n", i + 1, cmd_history[i].command);
|
||||
}
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
23
src/builtins_handler.h
Normal file
23
src/builtins_handler.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BUILTINS_HANDLER_H
|
||||
#define BUILTINS_HANDLER_H
|
||||
#include "env.h"
|
||||
#include "history.h"
|
||||
#include "shell.h"
|
||||
|
||||
typedef struct {
|
||||
env_t *env;
|
||||
history_t *history;
|
||||
his_command_t *history_command;
|
||||
} exec_ctx_t;
|
||||
|
||||
size_t update_command(char **buffer,
|
||||
size_t *buffer_sz, exec_ctx_t *exec_ctx);
|
||||
#endif /* BUILTINS_HANDLER_H */
|
||||
14
src/exec.c
14
src/exec.c
@@ -23,7 +23,7 @@
|
||||
#include "u_mem.h"
|
||||
#include "u_str.h"
|
||||
|
||||
const builtins_t BUILTINS[] = {
|
||||
const builtins_funcs_t BUILTINS[] = {
|
||||
{ "builtins", &builtins_builtins },
|
||||
{ "cd", &builtins_cd },
|
||||
{ "chdir", &builtins_cd },
|
||||
@@ -32,7 +32,8 @@ const builtins_t BUILTINS[] = {
|
||||
{ "setenv", &builtins_setenv },
|
||||
{ "unsetenv", &builtins_unsetenv },
|
||||
{ ":", &builtins_funny_double_dot },
|
||||
{ "exit", &builtins_exit }
|
||||
{ "exit", &builtins_exit },
|
||||
{ "history", &builtins_history}
|
||||
};
|
||||
|
||||
const size_t BUILTINS_SZ = sizeof BUILTINS / sizeof *BUILTINS;
|
||||
@@ -137,8 +138,8 @@ int launch_bin(char *full_bin_path, char **args, ef_t *ef)
|
||||
else
|
||||
waitpid(pid, &status, WNOHANG);
|
||||
if (WIFEXITED(status))
|
||||
ef->history->last_exit_code =
|
||||
ef->history->last_exit_code ?: WEXITSTATUS(status);
|
||||
ef->exec_ctx->history->last_exit_code =
|
||||
ef->exec_ctx->history->last_exit_code ?: WEXITSTATUS(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -171,7 +172,7 @@ bool builtins_launcher(ef_t *ef, char **args)
|
||||
if (u_strlen(BUILTINS[i].name) != bin_l)
|
||||
continue;
|
||||
if (u_strcmp(BUILTINS[i].name, args[0]) == 0) {
|
||||
ef->history->last_exit_code =
|
||||
ef->exec_ctx->history->last_exit_code =
|
||||
BUILTINS[i].ptr(ef, args);
|
||||
return true;
|
||||
}
|
||||
@@ -199,5 +200,6 @@ int execute(ef_t *ef)
|
||||
U_DEBUG("Exit code [%d]\n", ef->history->last_exit_code);
|
||||
free(full_bin_path);
|
||||
free((void *)args);
|
||||
return ef->history->last_exit_code != 0 ? RETURN_FAILURE : RETURN_SUCCESS;
|
||||
return ef->exec_ctx->history->last_exit_code
|
||||
!= 0 ? RETURN_FAILURE : RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ typedef struct {
|
||||
int pout_fd;
|
||||
int in_fd;
|
||||
int out_fd;
|
||||
exec_ctx_t *exec_ctx;
|
||||
} ef_t;
|
||||
|
||||
__attribute__((nonnull))
|
||||
|
||||
54
src/history.h
Normal file
54
src/history.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef HISTORY_H
|
||||
#define HISTORY_H
|
||||
#define CHAR_HIST '!'
|
||||
#define TWO_CHAR_CMD 3
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
|
||||
typedef struct history_variable_s {
|
||||
int coord_variable;
|
||||
int size_variable;
|
||||
int type;
|
||||
char *str;
|
||||
int id;
|
||||
} his_variable_t;
|
||||
|
||||
typedef struct history_command_s {
|
||||
int id;
|
||||
char *command;
|
||||
char *arg;
|
||||
int sz;
|
||||
} his_command_t;
|
||||
|
||||
typedef struct parsing_history_s {
|
||||
char *name;
|
||||
char *(*funct)(char *, his_variable_t *, his_command_t *);
|
||||
} parsing_history_t;
|
||||
|
||||
extern const parsing_history_t tab_fnct[];
|
||||
|
||||
int parse_history(char **pointer_line,
|
||||
size_t *buffer_len, size_t *buffer_sz, his_command_t **cmd_history);
|
||||
char *his_last_command(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command);
|
||||
char *his_last_same_command(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command);
|
||||
char *his_id_command(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command);
|
||||
char *his_last_word(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command);
|
||||
char *his_last_arg(char *line,
|
||||
his_variable_t *his_variable, his_command_t *his_command);
|
||||
his_command_t *fill_cmd_history(his_command_t *cmd_history);
|
||||
int save_cmd_history(his_command_t *cmd_history);
|
||||
his_command_t set_cmd(char *line, his_command_t cmd_struct);
|
||||
#endif /* HISTORY_H */
|
||||
46
src/init_history.c
Normal file
46
src/init_history.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** 42sh
|
||||
** File description:
|
||||
** init_history
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "history.h"
|
||||
#include "ctype.h"
|
||||
|
||||
static char *get_arg(char *line, int x, int end_cmd)
|
||||
{
|
||||
char *tmp = malloc(sizeof(char) * (x - end_cmd) + 1);
|
||||
|
||||
if (tmp != NULL) {
|
||||
tmp = strncpy(tmp, &line[end_cmd], x - end_cmd);
|
||||
tmp[x - end_cmd] = '\0';
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
his_command_t set_cmd(char *line, his_command_t cmd_struct)
|
||||
{
|
||||
int x = 0;
|
||||
int end_cmd;
|
||||
|
||||
while (line[x] != '\0' && !isblank(line[x]))
|
||||
x++;
|
||||
cmd_struct.command = malloc(sizeof(char) * x + 1);
|
||||
if (cmd_struct.command != NULL) {
|
||||
cmd_struct.command = strncpy(cmd_struct.command, line, x);
|
||||
cmd_struct.command[x] = '\0';
|
||||
}
|
||||
end_cmd = x + 1;
|
||||
while (line[x] != '\0')
|
||||
x++;
|
||||
if (x <= end_cmd)
|
||||
return cmd_struct;
|
||||
cmd_struct.arg = get_arg(line, x, end_cmd);
|
||||
return cmd_struct;
|
||||
}
|
||||
131
src/parse_history.c
Normal file
131
src/parse_history.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** history_42sh
|
||||
** File description:
|
||||
** his for history
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "common.h"
|
||||
#include "env.h"
|
||||
#include "exec.h"
|
||||
#include "u_mem.h"
|
||||
#include "u_str.h"
|
||||
#include "history.h"
|
||||
|
||||
const parsing_history_t tab_fnct[] = {
|
||||
{"!!", &his_last_command},
|
||||
{"!$", &his_last_word},
|
||||
{"!*", &his_last_arg},
|
||||
{"![command]", &his_last_same_command},
|
||||
{"![number]", &his_id_command},
|
||||
};
|
||||
|
||||
static
|
||||
int cmd_history_is_in(char *line)
|
||||
{
|
||||
for (int i = 0; line[i] != 0; i++)
|
||||
if (line[i] == CHAR_HIST &&
|
||||
(line[i + 1] != ' ' && line[i + 1] != '\t'
|
||||
&& line[i + 1] != '\0'))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int is_two_char_cmd(char *line, int coord_x)
|
||||
{
|
||||
if (line[coord_x] != CHAR_HIST)
|
||||
return -1;
|
||||
coord_x++;
|
||||
switch (line[coord_x]){
|
||||
case '!':
|
||||
return 0;
|
||||
case '$':
|
||||
return 1;
|
||||
case '*':
|
||||
return 2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static
|
||||
int choose_id_or_last(his_variable_t *his_variable, int index_str, char *str)
|
||||
{
|
||||
int mode = 0;
|
||||
const int cpy_index = index_str;
|
||||
|
||||
if (str[index_str] != CHAR_HIST && is_a_token(str, index_str + 1) == false)
|
||||
return -1;
|
||||
index_str++;
|
||||
for (; str[index_str] != 0; index_str++){
|
||||
if (is_a_token(str, index_str) == true || isblank(str[index_str]))
|
||||
break;
|
||||
if (!isdigit(str[index_str]))
|
||||
mode = 1;
|
||||
}
|
||||
his_variable->coord_variable = cpy_index;
|
||||
his_variable->size_variable = index_str - cpy_index;
|
||||
his_variable->str = strn_to_ndup(cpy_index, (index_str - cpy_index), str);
|
||||
if (his_variable->str == NULL)
|
||||
return 3;
|
||||
his_variable->id = atoi(his_variable->str + 1);
|
||||
return (mode == 1) ? 3 : 4;
|
||||
}
|
||||
|
||||
static
|
||||
int which_his_cmd(his_variable_t *his_variable, char const *line)
|
||||
{
|
||||
for (int i = 0; line[i] != '\0'; i++){
|
||||
his_variable->type = is_two_char_cmd(line, i);
|
||||
if (his_variable->type != -1){
|
||||
his_variable->coord_variable = i;
|
||||
his_variable->size_variable = 2;
|
||||
return 0;
|
||||
}
|
||||
his_variable->type = choose_id_or_last(his_variable, i, line);
|
||||
if (his_variable->type != -1)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
char *replace_history(char *line, his_command_t *cmd_history)
|
||||
{
|
||||
his_variable_t his_variable = {.coord_variable = 0,
|
||||
.id = 0, .size_variable = 0, .str = NULL, .type = -1};
|
||||
|
||||
which_his_cmd(&his_variable, line);
|
||||
while (his_variable.type != -1){
|
||||
line = tab_fnct[his_variable.type].funct(line, &his_variable,
|
||||
cmd_history);
|
||||
if (line == NULL)
|
||||
return NULL;
|
||||
which_his_cmd(&his_variable, line);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
int parse_history(char **pointer_line,
|
||||
size_t *buffer_len, size_t *buffer_sz, his_command_t **cmd_history)
|
||||
{
|
||||
char *line = *pointer_line;
|
||||
|
||||
*buffer_sz = 0;
|
||||
if (cmd_history_is_in(line) == 0){
|
||||
line = replace_history(line, *cmd_history);
|
||||
if (line == NULL)
|
||||
return 84;
|
||||
*buffer_len = u_strlen(line) + 1;
|
||||
*pointer_line = line;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
74
src/shell.c
74
src/shell.c
@@ -15,6 +15,7 @@
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "env.h"
|
||||
#include "history.h"
|
||||
#include "shell.h"
|
||||
#include "u_str.h"
|
||||
|
||||
@@ -32,6 +33,8 @@ void debug_env_entries(env_t *env)
|
||||
static
|
||||
void check_basic_error(char const *buffer)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
if (*buffer == '|')
|
||||
WRITE_CONST(STDERR_FILENO, "Invalid null command.\n");
|
||||
if (*buffer == '>' || *buffer == '<')
|
||||
@@ -46,40 +49,83 @@ void ignore_sigint(int sig __attribute__((unused)))
|
||||
}
|
||||
|
||||
static
|
||||
int shell_loop(env_t *env, int is_a_tty, history_t *history)
|
||||
void write_prompt(int is_a_tty)
|
||||
{
|
||||
if (is_a_tty)
|
||||
WRITE_CONST(STDOUT_FILENO, SHELL_PROMPT);
|
||||
}
|
||||
|
||||
/*
|
||||
** Noeud de fonction
|
||||
** Pour changer la commande
|
||||
** passer en parametre
|
||||
** si besoin
|
||||
*/
|
||||
static
|
||||
int shell_loop(int is_a_tty, exec_ctx_t *exec_ctx)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
size_t buffer_sz;
|
||||
size_t buffer_len;
|
||||
size_t buffer_sz = 0;
|
||||
size_t buffer_len = 0;
|
||||
|
||||
while (true) {
|
||||
if (is_a_tty)
|
||||
WRITE_CONST(STDOUT_FILENO, SHELL_PROMPT);
|
||||
write_prompt(is_a_tty);
|
||||
if (getline(&buffer, &buffer_sz, stdin) == -1)
|
||||
break;
|
||||
buffer_len = u_strlen(buffer);
|
||||
if (buffer_len < 2 || !u_str_is_alnum(buffer)) {
|
||||
buffer_len = update_command(&buffer, &buffer_sz, exec_ctx);
|
||||
if (buffer_len < 1 || !u_str_is_alnum(buffer)) {
|
||||
check_basic_error(buffer);
|
||||
continue;
|
||||
}
|
||||
buffer[buffer_len - 1] = '\0';
|
||||
U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, buffer);
|
||||
visitor(buffer, env, history);
|
||||
visitor(buffer, exec_ctx);
|
||||
free(buffer);
|
||||
}
|
||||
return (free(buffer), history->last_exit_code);
|
||||
free(exec_ctx->history_command);
|
||||
return (free(buffer), exec_ctx->history->last_exit_code);
|
||||
}
|
||||
|
||||
his_command_t *init_cmd_history(void)
|
||||
{
|
||||
his_command_t *cmd_history = malloc(sizeof(his_command_t) * 100);
|
||||
|
||||
if (cmd_history == NULL)
|
||||
return NULL;
|
||||
for (int i = 0; i != 100; i++){
|
||||
cmd_history[i].arg = NULL;
|
||||
cmd_history[i].command = NULL;
|
||||
cmd_history[i].id = i;
|
||||
}
|
||||
cmd_history->sz = 0;
|
||||
return cmd_history;
|
||||
}
|
||||
|
||||
static
|
||||
bool error_in_init(exec_ctx_t *exec_ctx)
|
||||
{
|
||||
if (!exec_ctx->history_command || !exec_ctx->env->env) {
|
||||
free(exec_ctx->history_command);
|
||||
free(exec_ctx->env->env);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int shell(char **env_ptr)
|
||||
{
|
||||
env_t env = parse_env(env_ptr);
|
||||
history_t history = { .cmd_history = NULL, 0, .last_chdir = NULL };
|
||||
history_t history = { .cmd_history = NULL, 0, .last_chdir = NULL};
|
||||
his_command_t *cmd_history = init_cmd_history();
|
||||
exec_ctx_t exec_ctx = {.env = &env,
|
||||
.history = &history, .history_command = cmd_history };
|
||||
int shell_result;
|
||||
|
||||
if (!env.env)
|
||||
if (error_in_init(&exec_ctx) == true){
|
||||
return RETURN_FAILURE;
|
||||
}
|
||||
U_DEBUG_CALL(debug_env_entries, &env);
|
||||
signal(SIGINT, ignore_sigint);
|
||||
shell_result = shell_loop(&env, isatty(STDIN_FILENO), &history);
|
||||
free_env(&env);
|
||||
shell_result = shell_loop(isatty(STDIN_FILENO), &exec_ctx);
|
||||
free_env(exec_ctx.env);
|
||||
return shell_result;
|
||||
}
|
||||
|
||||
48
src/update_command.c
Normal file
48
src/update_command.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** 42sh
|
||||
** File description:
|
||||
** update_command
|
||||
*/
|
||||
#include "history.h"
|
||||
#include "builtins_handler.h"
|
||||
#include "u_str.h"
|
||||
|
||||
static int check_cmd(char *cmd)
|
||||
{
|
||||
if (!cmd)
|
||||
return 84;
|
||||
for (int i = 0; cmd[i] != 0; i++)
|
||||
if (cmd[i] == CHAR_HIST &&
|
||||
(cmd[i + 1] != ' ' && cmd[i + 1] != '\t'
|
||||
&& cmd[i + 1] != '\0'))
|
||||
return 84;
|
||||
return 0;
|
||||
}
|
||||
|
||||
his_command_t *save_command(char *cmd, his_command_t *cmd_history)
|
||||
{
|
||||
if (check_cmd(cmd) == 84)
|
||||
return cmd_history;
|
||||
if (cmd_history->sz < 100) {
|
||||
cmd_history[cmd_history->sz] = set_cmd(cmd,
|
||||
cmd_history[cmd_history->sz]);
|
||||
}
|
||||
cmd_history->sz++;
|
||||
return cmd_history;
|
||||
}
|
||||
|
||||
size_t update_command(char **buffer,
|
||||
size_t *buffer_sz, exec_ctx_t *exec_ctx)
|
||||
{
|
||||
size_t buffer_len = 0;
|
||||
|
||||
buffer_len = u_strlen(*buffer);
|
||||
(*buffer)[buffer_len - 1] = '\0';
|
||||
if (parse_history(buffer, &buffer_len,
|
||||
buffer_sz, &exec_ctx->history_command) == 84)
|
||||
return -1;
|
||||
exec_ctx->history_command = save_command(*buffer,
|
||||
exec_ctx->history_command);
|
||||
return buffer_len;
|
||||
}
|
||||
18
src/utils.h
Normal file
18
src/utils.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
#include "history.h"
|
||||
#include "u_str.h"
|
||||
|
||||
char *strn_to_ndup(int start, int size, char *str);
|
||||
bool is_a_token(char *str, int index_str);
|
||||
char *cat_in_str(his_variable_t *his_variable, char *str, char *cpy);
|
||||
int len_array(char **array);
|
||||
#endif /* UTILS_H */
|
||||
43
src/utils/cat_in_str.c
Normal file
43
src/utils/cat_in_str.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** 42sh
|
||||
** File description:
|
||||
** cat_in_str
|
||||
*/
|
||||
#include "history.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static
|
||||
int insert_in_str(char *dest, char *cpy, int start)
|
||||
{
|
||||
for (int j = 0; cpy[j] != 0; j++){
|
||||
dest[start] = cpy[j];
|
||||
start++;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
char *cat_in_str(his_variable_t *his_variable, char *str, char *cpy)
|
||||
{
|
||||
int i = 0;
|
||||
int len_str = strlen(str);
|
||||
int size_right = len_str -
|
||||
his_variable->coord_variable - his_variable->size_variable;
|
||||
int size_left = (len_str - size_right) - his_variable->size_variable;
|
||||
char *new_str = malloc(sizeof(char) *
|
||||
(size_right + size_left + strlen(cpy) + 2));
|
||||
|
||||
if (new_str == NULL)
|
||||
return NULL;
|
||||
for (; i < size_left; i++)
|
||||
new_str[i] = str[i];
|
||||
i += insert_in_str(new_str, cpy, i);
|
||||
for (int k = 0; k < size_right; k++){
|
||||
new_str[i] = str[k + size_left + his_variable->size_variable];
|
||||
i++;
|
||||
}
|
||||
new_str[i] = '\0';
|
||||
new_str[i + 1] = '\0';
|
||||
return new_str;
|
||||
}
|
||||
20
src/utils/is_a_token.c
Normal file
20
src/utils/is_a_token.c
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** 42sh
|
||||
** File description:
|
||||
** is_a_token
|
||||
*/
|
||||
#include "string.h"
|
||||
#include "u_str.h"
|
||||
#include "ast.h"
|
||||
|
||||
bool is_a_token(char *str, int index_str)
|
||||
{
|
||||
str += index_str;
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
if (strncmp(str, TOKENS_LIST[i].str, 2) == 0){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
17
src/utils/len_array.c
Normal file
17
src/utils/len_array.c
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** 42sh
|
||||
** File description:
|
||||
** len_array
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int len_array(char **array)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (array[i] != NULL)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
22
src/utils/strn_to_ndup.c
Normal file
22
src/utils/strn_to_ndup.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** 42sh
|
||||
** File description:
|
||||
** strn_to_ndup
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
char *strn_to_ndup(int start, int size, char *str)
|
||||
{
|
||||
char *new_str = malloc(sizeof(char) * (size + 1));
|
||||
int count = 0;
|
||||
|
||||
if (new_str == NULL)
|
||||
return NULL;
|
||||
new_str[size] = '\0';
|
||||
for (int i = start; i != start + size; i++){
|
||||
new_str[count] = str[i];
|
||||
count++;
|
||||
}
|
||||
return new_str;
|
||||
}
|
||||
@@ -146,18 +146,19 @@ void remove_trailing_semi(char *str)
|
||||
}
|
||||
}
|
||||
|
||||
int visitor(char *buffer, env_t *env, history_t *history)
|
||||
int visitor(char *buffer, exec_ctx_t *exec_ctx)
|
||||
{
|
||||
ast_ctx_t ctx = { 0, .str = buffer, .cap = u_strlen(buffer) + 10,
|
||||
.ast = malloc(sizeof *ctx.ast * (u_strlen(buffer) + 10)) };
|
||||
ef_t ef = { .buffer = buffer, .env = env,
|
||||
.history = history, .ctx = &ctx, .pout_fd = STDOUT_FILENO,
|
||||
.flags = 0, 0 };
|
||||
ef_t ef = { .buffer = buffer, .env = exec_ctx->env,
|
||||
.history = exec_ctx->history, .ctx
|
||||
= &ctx, .pout_fd = STDOUT_FILENO, .flags = 0,
|
||||
.exec_ctx = exec_ctx};
|
||||
int result = RETURN_FAILURE;
|
||||
|
||||
ctx.first_node = ctx.ast;
|
||||
remove_trailing_semi(ctx.str);
|
||||
history->last_exit_code = 0;
|
||||
exec_ctx->history->last_exit_code = 0;
|
||||
if (ctx.ast == NULL)
|
||||
return RETURN_FAILURE;
|
||||
result = visitor_launcher(&ef);
|
||||
|
||||
Reference in New Issue
Block a user