From 893a7c74e9e5d56b2804c524b356e3b2a47b5507 Mon Sep 17 00:00:00 2001 From: tekClovis Date: Tue, 22 Apr 2025 02:57:26 +0200 Subject: [PATCH 1/5] [ADD] local utils and foreach (that don't work) as built-ins --- Makefile | 1 + src/ast.h | 15 ++-- src/ast/ast.c | 4 +- src/ast/loop.c | 4 +- src/builtins.h | 1 + src/builtins/foreach.c | 166 ++++++++++++++++++++++++++++++++++++ src/builtins_handler.h | 2 + src/exec.c | 3 +- src/local.h | 24 ++++++ src/local/change_local.c | 57 +++++++++++++ src/local/check_local_var.c | 28 ++++++ src/local/create_local.c | 28 ++++++ src/local/set_local.c | 52 +++++++++++ src/local/unset_local.c | 30 +++++++ src/loop.h | 18 ++++ src/shell.c | 5 +- 16 files changed, 423 insertions(+), 15 deletions(-) create mode 100644 src/builtins/foreach.c create mode 100644 src/local.h create mode 100644 src/local/change_local.c create mode 100644 src/local/check_local_var.c create mode 100644 src/local/create_local.c create mode 100644 src/local/set_local.c create mode 100644 src/local/unset_local.c create mode 100644 src/loop.h diff --git a/Makefile b/Makefile index 580fa5f..1e495ce 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ SRC := $(wildcard src/*.c) SRC += $(wildcard src/builtins/*.c) SRC += $(wildcard src/ast/*.c) SRC += $(wildcard src/utils/*.c) +SRC += $(wildcard src/local/*.c) LIB_SRC := $(wildcard ulib/*.c) LIB_SRC += $(wildcard ulib/write/printf/*.c) diff --git a/src/ast.h b/src/ast.h index 767ced1..af622b2 100644 --- a/src/ast.h +++ b/src/ast.h @@ -36,14 +36,13 @@ typedef enum { T_IN_REDIRECT = 1 << 14, // < T_AT = 1 << 15, // < T_WHILE = 1 << 16, // while - T_FOREACH = 1 << 17, // foreach - T_IF = 1 << 18, // if - T_THEN = 1 << 19, // then - T_ELSE = 1 << 20, // else - T_ENDIF = 1 << 21, // endif - T_EOF = 1 << 22, // \0 - T_ARG = 1 << 23, - T_INVALID = 1 << 24 + T_IF = 1 << 17, // if + T_THEN = 1 << 18, // then + T_ELSE = 1 << 19, // else + T_ENDIF = 1 << 20, // endif + T_EOF = 1 << 21, // \0 + T_ARG = 1 << 22, + T_INVALID = 1 << 23 } token_type_t; typedef enum { diff --git a/src/ast/ast.c b/src/ast/ast.c index 2ee8754..0f40952 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -59,7 +59,7 @@ ast_t *fill_cmd_node(ast_ctx_t *ctx) ast_t *parse_cmd(ast_ctx_t *ctx) { if (ctx->act_tok.type != T_ARG) { - if (ctx->act_tok.type & (T_WHILE | T_FOREACH)) + if (ctx->act_tok.type & (T_WHILE)) return NULL; if (!parser_eat(ctx, T_ARG)) return NULL; @@ -107,7 +107,7 @@ ast_t *parse_condition(ast_ctx_t *ctx) if (l_node == NULL) return NULL; - if (ctx->act_tok.type & (T_WHILE | T_FOREACH)) + if (ctx->act_tok.type & (T_WHILE)) ctx->ast = parse_loop(ctx); else { switch (ctx->act_tok.type) { diff --git a/src/ast/loop.c b/src/ast/loop.c index f53e0e4..b2a5b58 100644 --- a/src/ast/loop.c +++ b/src/ast/loop.c @@ -80,12 +80,10 @@ ast_t *increase_buffers(ast_t *node, size_t *buffer_len) static ast_t *get_usr_loop_cmd(ast_t *node) { - char prompt[] = "foreach? "; + char prompt[] = "while? "; size_t buffer_len; node->loop.buffers = malloc(sizeof(char *) * node->loop.cap); - if (node->tok.type == T_WHILE) - strcpy(prompt, "while? "); node = get_first_cmd(node, prompt, &buffer_len); while (strcmp("end", node->loop.buffers[node->loop.sz - 1])){ printf("%s", prompt); diff --git a/src/builtins.h b/src/builtins.h index dc42fb0..5b22df5 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -30,4 +30,5 @@ int builtins_alias(ef_t *ef, char **args); int builtins_display_alias(alias_t *alias); int builtins_repeat(ef_t *ef, char **args); int builtins_yes(ef_t *ef, char **args); +int builtins_foreach(ef_t *ef, char **args); #endif /* BUILTIND_H */ diff --git a/src/builtins/foreach.c b/src/builtins/foreach.c new file mode 100644 index 0000000..990e5af --- /dev/null +++ b/src/builtins/foreach.c @@ -0,0 +1,166 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** foreach +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ast.h" +#include "builtins.h" +#include "common.h" +#include "exec.h" +#include "redirects.h" +#include "u_str.h" +#include "u_mem.h" +#include "loop.h" +#include "local.h" + +static +bool checking_error(ef_t *ef, char **args) +{ + if (my_array_len(args) < 3) + return (WRITE_CONST(STDERR_FILENO, "foreach: Too few arguments.\n"), + true); + if (!check_local_var(args[1], args[0])) + return true; + return false; +} + +static +usr_cmd_t *buffers_realloc(usr_cmd_t *usr) +{ + char **new_buffers = u_realloc(usr->local_var, sizeof + *usr->local_var * usr->sz, sizeof + *usr->local_var * (usr->cap << 1)); + + if (new_buffers == NULL) + return NULL; + usr->local_var = new_buffers; + usr->cap <<= 1; + return usr; +} + +static +usr_cmd_t *get_first_cmd(usr_cmd_t *usr, char prompt[], size_t *bf_len) +{ + printf("%s", prompt); + usr->local_var[usr->sz] = NULL; + getline(&(usr->local_var[usr->sz]), bf_len, stdin); + *bf_len = u_strlen(usr->local_var[usr->sz]); + usr->local_var[usr->sz][*bf_len - 1] = '\0'; + usr->sz += 1; + return usr; +} + +static +usr_cmd_t *increase_buffers(usr_cmd_t *usr, size_t *buffer_len) +{ + usr->local_var[usr->sz] = NULL; + getline(&(usr->local_var[usr->sz]), buffer_len, stdin); + *buffer_len = u_strlen(usr->local_var[usr->sz]); + usr->local_var[usr->sz][*buffer_len - 1] = '\0'; + usr->sz++; + return usr; +} + +static +usr_cmd_t *get_usr_loop_cmd(usr_cmd_t *usr_cmd) +{ + char prompt[] = "foreach? "; + size_t buffer_len; + + usr_cmd->local_var = malloc(sizeof(char *) * usr_cmd->cap); + if (usr_cmd->local_var == NULL) + return NULL; + usr_cmd = get_first_cmd(usr_cmd, prompt, &buffer_len); + while (strcmp("end", usr_cmd->local_var[usr_cmd->sz - 1])){ + printf("foreach? "); + if (usr_cmd->sz >= usr_cmd->cap) + usr_cmd = buffers_realloc(usr_cmd); + if (usr_cmd == NULL) + return NULL; + increase_buffers(usr_cmd, &buffer_len); + } + free(usr_cmd->local_var[usr_cmd->sz]); + usr_cmd->sz--; + usr_cmd->local_var[usr_cmd->sz] = NULL; + return usr_cmd; +} + +static +int do_a_lap(ef_t *ef, char **args, char **save_cmds) +{ + int status = 0; + + for (int i = 0; args[i]; i++) + status = visitor(args[i], ef->exec_ctx); + return status; +} + +static +int foreach_loop(ef_t *ef, char **args, usr_cmd_t *usr_cmds) +{ + int status = 0; + char **save_cmds = arraydup(usr_cmds->local_var); + + if (save_cmds == NULL) + exit(84); + for (int i = 2; args[i]; i++){ + if (!change_local(ef->exec_ctx->local, args[1], args[i])) + exit(84); + status = do_a_lap(ef, usr_cmds->local_var, save_cmds); + free_array(args); + args = arraydup(save_cmds); + } + free_array(usr_cmds->local_var); + return status; +} + +static +void launch_loop(ef_t *ef, char **args) +{ + int status = RETURN_FAILURE; + usr_cmd_t *usr_cmds = malloc(sizeof(usr_cmd_t)); + + if (usr_cmds == NULL) + exit(84); + usr_cmds->cap = 2; + usr_cmds->sz = 0; + signal(SIGINT, exit_child); + signal(EOF, exit_child); + usr_cmds = get_usr_loop_cmd(usr_cmds); + if (usr_cmds == NULL) + exit(84); + status = foreach_loop(ef, args, usr_cmds); + free_array(usr_cmds->local_var); + exit(status); +} + +int builtins_foreach(ef_t *ef, char **args) +{ + int status = 0; + pid_t pid; + + if (checking_error(ef, args)) + return RETURN_FAILURE; + printf("caok\n"); + pid = fork(); + if (pid == 0) + launch_loop(ef, args); + else + wait(&status); + if (WIFEXITED(status)) + ef->history->last_exit_code = + ef->history->last_exit_code ?: WEXITSTATUS(status); + return status; +} diff --git a/src/builtins_handler.h b/src/builtins_handler.h index 02c4a2a..b0793c3 100644 --- a/src/builtins_handler.h +++ b/src/builtins_handler.h @@ -12,12 +12,14 @@ #include "history.h" #include "shell.h" #include "alias.h" + #include "local.h" typedef struct { env_t *env; history_t *history; his_command_t *history_command; alias_t *alias; + local_t *local; } exec_ctx_t; size_t update_command(char **buffer, diff --git a/src/exec.c b/src/exec.c index ac49af6..9aec020 100644 --- a/src/exec.c +++ b/src/exec.c @@ -37,7 +37,8 @@ const builtins_funcs_t BUILTINS[] = { { "exit", &builtins_exit }, { "history", &builtins_history}, { "alias", &builtins_alias}, - { "yes", &builtins_yes } + { "yes", &builtins_yes }, + { "foreach", &builtins_foreach } }; const size_t BUILTINS_SZ = sizeof BUILTINS / sizeof *BUILTINS; diff --git a/src/local.h b/src/local.h new file mode 100644 index 0000000..32630f3 --- /dev/null +++ b/src/local.h @@ -0,0 +1,24 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + +#ifndef LOCAL_H + #define LOCAL_H + #include + #include + +typedef struct { + size_t sz; + size_t cap; + char **local_var; +} local_t; + +bool set_local(local_t *local, char *var, char *value); +bool change_local(local_t *local, char *var, char *value); +bool check_var(char *local, char *var); +bool check_local_var(char *var, char *func_name); +local_t create_local(void); +#endif /* LOCAL_H */ diff --git a/src/local/change_local.c b/src/local/change_local.c new file mode 100644 index 0000000..8e24b61 --- /dev/null +++ b/src/local/change_local.c @@ -0,0 +1,57 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** change_local +*/ + +#include +#include +#include +#include +#include + +#include "env.h" +#include "u_mem.h" +#include "u_str.h" +#include "local.h" + +bool check_var(char *local, char *var) +{ + if (!strncmp(local, var, strlen(var))) + return true; + return false; +} + +char *reset_value(char *value, char *var) +{ + char *new_local = malloc(sizeof(char) * (u_strlen(value) + u_strlen(var) + + 2)); + + if (new_local == NULL) + return NULL; + strcpy(new_local, var); + strcat(new_local, "\t"); + if (value != NULL) + strcat(new_local, value); + return new_local; +} + +bool change_local(local_t *local, char *var, char *value) +{ + bool find_a_var = false; + + for (int i = 0; local->local_var[i]; i++){ + if (!check_var(local->local_var[i], var)) + continue; + free(local->local_var[i]); + local->local_var[i] = reset_value(value, var); + if (local->local_var[i] == NULL) + return false; + find_a_var = true; + break; + } + if (!find_a_var && !set_local(local, var, value)) + return false; + return true; +} diff --git a/src/local/check_local_var.c b/src/local/check_local_var.c new file mode 100644 index 0000000..fadf098 --- /dev/null +++ b/src/local/check_local_var.c @@ -0,0 +1,28 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** check_local_var +*/ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "env.h" +#include "exec.h" +#include "u_str.h" + +bool check_local_var(char *var, char *func_name) +{ + if (!isalpha(var[0])) + return (fprintf(stdout, "%s: Variable name must begin" + " with a letter.\n", func_name), RETURN_FAILURE); + if (!u_str_is_only_alnum(var)) + return (fprintf(stdout, "%s: Variable name must contain" + " alphanumeric characters.\n", func_name), RETURN_FAILURE); + return RETURN_SUCCESS; +} diff --git a/src/local/create_local.c b/src/local/create_local.c new file mode 100644 index 0000000..0a1e011 --- /dev/null +++ b/src/local/create_local.c @@ -0,0 +1,28 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** create_local +*/ +#include +#include +#include +#include +#include + +#include "env.h" +#include "u_mem.h" +#include "u_str.h" +#include "local.h" + +local_t create_local(void) +{ + local_t local = {.sz = 0, .cap = 2}; + + local.local_var = (char **)malloc(sizeof(char *) * local.cap); + if (local.local_var == NULL) + return (local_t){.sz = 0, .cap = 2, .local_var = NULL}; + local.local_var[local.sz] = NULL; + local.sz++; + return local; +} diff --git a/src/local/set_local.c b/src/local/set_local.c new file mode 100644 index 0000000..a77686f --- /dev/null +++ b/src/local/set_local.c @@ -0,0 +1,52 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** set_local +*/ + +#include +#include +#include +#include +#include + +#include "env.h" +#include "u_mem.h" +#include "u_str.h" +#include "local.h" + +static +bool ensure_local_capacity(local_t *local) +{ + char **new_ptr = NULL; + + if (local->sz < local->cap) + return true; + new_ptr = (char **)u_realloc((void *)local->local_var, + sizeof *local->local_var * local->sz, + sizeof *local->local_var * local->cap << 1); + if (!new_ptr) + return false; + local->cap <<= 1; + local->local_var = new_ptr; + return true; +} + +bool set_local(local_t *local, char *var, char *value) +{ + char *new_var = NULL; + + local->sz++; + if (!ensure_local_capacity(local)) + return false; + new_var = malloc(sizeof(char) * (u_strlen(var) + u_strlen(value) + 2)); + if (new_var == NULL) + return false; + strcpy(new_var, var); + strcat(new_var, "\t"); + if (value != NULL) + strcat(new_var, value); + local->local_var[local->sz - 1] = new_var; + return true; +} diff --git a/src/local/unset_local.c b/src/local/unset_local.c new file mode 100644 index 0000000..146a3c1 --- /dev/null +++ b/src/local/unset_local.c @@ -0,0 +1,30 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** unset_local +*/ + +#include +#include +#include +#include +#include + +#include "env.h" +#include "u_mem.h" +#include "u_str.h" +#include "local.h" + +local_t *unset_local(local_t *local, char *var, char *value) +{ + for (int i = 0; local->local_var[i]; i++){ + if (!check_var(local->local_var[i], var)) + continue; + free(local->local_var[i]); + for (int j = i + 1; local->local_var[j]; j++) + local->local_var[j - 1] = local->local_var[j]; + break; + } + return local; +} diff --git a/src/loop.h b/src/loop.h new file mode 100644 index 0000000..997b3da --- /dev/null +++ b/src/loop.h @@ -0,0 +1,18 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + +#ifndef LOOP_H + #define LOOP_H + #include + #include + +typedef struct { + size_t sz; + size_t cap; + char **local_var; +} usr_cmd_t; +#endif /* LOOP_H */ diff --git a/src/shell.c b/src/shell.c index 7cf3754..8dfdcdd 100644 --- a/src/shell.c +++ b/src/shell.c @@ -18,6 +18,8 @@ #include "history.h" #include "shell.h" #include "u_str.h" +#include "local.h" +#include "loop.h" __attribute__((unused)) static @@ -145,7 +147,8 @@ int shell(char **env_ptr) env_t env = parse_env(env_ptr); 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, + local_t local = create_local(); + exec_ctx_t exec_ctx = {.env = &env, .local = &local, .history = &history, .history_command = cmd_history, .alias = &alias}; int shell_result; From 4a7566cc347e6ae32e270ed1ee20251198357285 Mon Sep 17 00:00:00 2001 From: tekClovis Date: Tue, 22 Apr 2025 04:31:48 +0200 Subject: [PATCH 2/5] [FIX] foreach that work with the local env --- src/builtins/foreach.c | 37 ++++++++++++++++++-------- src/exec.c | 2 +- src/exec.h | 2 +- src/handle_vars.c | 7 +++-- src/local.h | 2 ++ src/local/change_local.c | 57 ---------------------------------------- src/local/get_local.c | 32 ++++++++++++++++++++++ src/local/set_local.c | 21 +++++++++------ src/local/unset_local.c | 33 ++++++++++++++++------- 9 files changed, 104 insertions(+), 89 deletions(-) delete mode 100644 src/local/change_local.c create mode 100644 src/local/get_local.c diff --git a/src/builtins/foreach.c b/src/builtins/foreach.c index 990e5af..f24dff3 100644 --- a/src/builtins/foreach.c +++ b/src/builtins/foreach.c @@ -31,7 +31,7 @@ bool checking_error(ef_t *ef, char **args) if (my_array_len(args) < 3) return (WRITE_CONST(STDERR_FILENO, "foreach: Too few arguments.\n"), true); - if (!check_local_var(args[1], args[0])) + if (check_local_var(args[1], args[0])) return true; return false; } @@ -73,6 +73,23 @@ usr_cmd_t *increase_buffers(usr_cmd_t *usr, size_t *buffer_len) return usr; } +static +usr_cmd_t *handle_end(usr_cmd_t *us, char prompt[]) +{ + us->sz--; + if (!us->local_var[us->sz] || + strcmp("end", us->local_var[us->sz])){ + printf("%s: end not found.\n", prompt); + free_array(us->local_var); + us->local_var = NULL; + exit(RETURN_FAILURE); + return NULL; + } + free(us->local_var[us->sz]); + us->local_var[us->sz] = NULL; + return us; +} + static usr_cmd_t *get_usr_loop_cmd(usr_cmd_t *usr_cmd) { @@ -91,14 +108,12 @@ usr_cmd_t *get_usr_loop_cmd(usr_cmd_t *usr_cmd) return NULL; increase_buffers(usr_cmd, &buffer_len); } - free(usr_cmd->local_var[usr_cmd->sz]); - usr_cmd->sz--; - usr_cmd->local_var[usr_cmd->sz] = NULL; + usr_cmd = handle_end(usr_cmd, prompt); return usr_cmd; } static -int do_a_lap(ef_t *ef, char **args, char **save_cmds) +int do_a_lap(ef_t *ef, char **args) { int status = 0; @@ -116,13 +131,13 @@ int foreach_loop(ef_t *ef, char **args, usr_cmd_t *usr_cmds) if (save_cmds == NULL) exit(84); for (int i = 2; args[i]; i++){ - if (!change_local(ef->exec_ctx->local, args[1], args[i])) + if (!set_local(ef->exec_ctx->local, args[1], args[i])) exit(84); - status = do_a_lap(ef, usr_cmds->local_var, save_cmds); - free_array(args); - args = arraydup(save_cmds); + status = do_a_lap(ef, usr_cmds->local_var); + free_array(usr_cmds->local_var); + usr_cmds->local_var = arraydup(save_cmds); } - free_array(usr_cmds->local_var); + free_array(save_cmds); return status; } @@ -143,6 +158,7 @@ void launch_loop(ef_t *ef, char **args) exit(84); status = foreach_loop(ef, args, usr_cmds); free_array(usr_cmds->local_var); + free(usr_cmds); exit(status); } @@ -153,7 +169,6 @@ int builtins_foreach(ef_t *ef, char **args) if (checking_error(ef, args)) return RETURN_FAILURE; - printf("caok\n"); pid = fork(); if (pid == 0) launch_loop(ef, args); diff --git a/src/exec.c b/src/exec.c index 9aec020..f3a7ee0 100644 --- a/src/exec.c +++ b/src/exec.c @@ -74,7 +74,7 @@ char **parse_args(ef_t *ef, ast_t *node, env_t *env) if (ef->skip_sz > 0 && i >= ef->skip_i && i < ef->skip_i + ef->skip_sz) continue; ensure_args_capacity(&args, sz, &cap); - args[sz] = handle_var_case(node, env, &i); + args[sz] = handle_var_case(node, ef->exec_ctx, &i); if (args[sz] == NULL) return free(args), NULL; sz++; diff --git a/src/exec.h b/src/exec.h index 88b75a5..5b56ace 100644 --- a/src/exec.h +++ b/src/exec.h @@ -51,5 +51,5 @@ int execute(ef_t *ef); int exec_the_args(ef_t *ef, char **args); void exit_child(int sig __attribute__((unused))); int visit_loop(ef_t *ef, ast_t *node); -char *handle_var_case(ast_t *node, env_t *env, size_t *i); +char *handle_var_case(ast_t *node, exec_ctx_t *ctx, size_t *i); #endif /* EXEC_H */ diff --git a/src/handle_vars.c b/src/handle_vars.c index f271292..38ff33d 100644 --- a/src/handle_vars.c +++ b/src/handle_vars.c @@ -8,15 +8,18 @@ #include "ast.h" #include "env.h" #include "stdio.h" +#include "local.h" -char *handle_var_case(ast_t *node, env_t *env, size_t *i) +char *handle_var_case(ast_t *node, exec_ctx_t *ctx, size_t *i) { char *r_char; if (node->vector.tokens[*i].type == T_VAR && *i + 1 < node->vector.sz) { *i += 1; node->vector.tokens[*i].str[node->vector.tokens[*i].sz] = '\0'; - r_char = get_env_value(env, node->vector.tokens[*i].str); + r_char = get_env_value(ctx->env, node->vector.tokens[*i].str); + if (r_char == NULL) + r_char = get_local_value(ctx->local, node->vector.tokens[*i].str); if (r_char == NULL) { printf("%s: Undefined variable.\n", node->vector.tokens[*i].str); return NULL; diff --git a/src/local.h b/src/local.h index 32630f3..ef8f6b2 100644 --- a/src/local.h +++ b/src/local.h @@ -20,5 +20,7 @@ bool set_local(local_t *local, char *var, char *value); bool change_local(local_t *local, char *var, char *value); bool check_var(char *local, char *var); bool check_local_var(char *var, char *func_name); +bool unset_local(local_t *local, char *var); +char *get_local_value(local_t *local, char const *key); local_t create_local(void); #endif /* LOCAL_H */ diff --git a/src/local/change_local.c b/src/local/change_local.c deleted file mode 100644 index 8e24b61..0000000 --- a/src/local/change_local.c +++ /dev/null @@ -1,57 +0,0 @@ -/* -** EPITECH PROJECT, 2025 -** 42sh -** File description: -** change_local -*/ - -#include -#include -#include -#include -#include - -#include "env.h" -#include "u_mem.h" -#include "u_str.h" -#include "local.h" - -bool check_var(char *local, char *var) -{ - if (!strncmp(local, var, strlen(var))) - return true; - return false; -} - -char *reset_value(char *value, char *var) -{ - char *new_local = malloc(sizeof(char) * (u_strlen(value) + u_strlen(var) + - 2)); - - if (new_local == NULL) - return NULL; - strcpy(new_local, var); - strcat(new_local, "\t"); - if (value != NULL) - strcat(new_local, value); - return new_local; -} - -bool change_local(local_t *local, char *var, char *value) -{ - bool find_a_var = false; - - for (int i = 0; local->local_var[i]; i++){ - if (!check_var(local->local_var[i], var)) - continue; - free(local->local_var[i]); - local->local_var[i] = reset_value(value, var); - if (local->local_var[i] == NULL) - return false; - find_a_var = true; - break; - } - if (!find_a_var && !set_local(local, var, value)) - return false; - return true; -} diff --git a/src/local/get_local.c b/src/local/get_local.c new file mode 100644 index 0000000..7f07ee4 --- /dev/null +++ b/src/local/get_local.c @@ -0,0 +1,32 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** get_local +*/ + +#include +#include +#include +#include +#include + +#include "env.h" +#include "u_mem.h" +#include "u_str.h" +#include "local.h" + +char *get_local_value(local_t *local, char const *key) +{ + int key_len = u_strlen(key); + + for (size_t i = 0; i < local->sz; i++) { + if (local->local_var[i] == NULL) + continue; + if (u_strcspn(local->local_var[i], '\t') != key_len) + continue; + if (u_strcmp(local->local_var[i], key) == 0) + return local->local_var[i] + key_len + 1; + } + return NULL; +} diff --git a/src/local/set_local.c b/src/local/set_local.c index a77686f..a90161b 100644 --- a/src/local/set_local.c +++ b/src/local/set_local.c @@ -35,18 +35,23 @@ bool ensure_local_capacity(local_t *local) bool set_local(local_t *local, char *var, char *value) { - char *new_var = NULL; + char *new_loc = NULL; + size_t key_len = u_strlen(var); + size_t value_len = u_strlen(value); + if (get_local_value(local, var) != NULL) + unset_local(local, var); local->sz++; if (!ensure_local_capacity(local)) return false; - new_var = malloc(sizeof(char) * (u_strlen(var) + u_strlen(value) + 2)); - if (new_var == NULL) + new_loc = malloc(sizeof(char) * (key_len + value_len + 2)); + if (new_loc == NULL) return false; - strcpy(new_var, var); - strcat(new_var, "\t"); - if (value != NULL) - strcat(new_var, value); - local->local_var[local->sz - 1] = new_var; + u_bzero(new_loc, key_len + value_len + 2); + u_strcpy(new_loc, var); + new_loc[key_len] = '\t'; + if (value_len > 0) + u_strcpy(new_loc + key_len + 1, value); + local->local_var[local->sz - 1] = new_loc; return true; } diff --git a/src/local/unset_local.c b/src/local/unset_local.c index 146a3c1..8ff115f 100644 --- a/src/local/unset_local.c +++ b/src/local/unset_local.c @@ -16,15 +16,30 @@ #include "u_str.h" #include "local.h" -local_t *unset_local(local_t *local, char *var, char *value) + +static +void unset_local_move(local_t *local, size_t i) { - for (int i = 0; local->local_var[i]; i++){ - if (!check_var(local->local_var[i], var)) - continue; - free(local->local_var[i]); - for (int j = i + 1; local->local_var[j]; j++) - local->local_var[j - 1] = local->local_var[j]; - break; + while (local->local_var[i]) { + local->local_var[i] = local->local_var[i + 1]; + i++; } - return local; +} + +bool unset_local(local_t *local, char *var) +{ + int key_len = u_strlen(var); + + for (size_t i = 0; i < local->sz; i++) { + if (local->local_var[i] == NULL) + continue; + if (u_strcspn(local->local_var[i], '\t') != key_len) + continue; + if (u_strcmp(local->local_var[i], var) == 0) { + unset_local_move(local, i); + local->sz--; + return true; + } + } + return false; } From c3f5d822e4f58b336f759de8eb7c905e082f01f3 Mon Sep 17 00:00:00 2001 From: tekClovis Date: Tue, 22 Apr 2025 05:02:41 +0200 Subject: [PATCH 3/5] [ADD] set and unset built-ins --- src/builtins.h | 2 + src/builtins/env.c | 4 +- src/builtins/local.c | 123 ++++++++++++++++++++++++++++++++++++ src/builtins/set.c | 51 +++++++++++++++ src/builtins/unset.c | 28 ++++++++ src/exec.c | 4 +- src/local/check_local_var.c | 28 -------- src/local/create_local.c | 28 -------- src/local/get_local.c | 32 ---------- src/local/set_local.c | 57 ----------------- src/local/unset_local.c | 45 ------------- 11 files changed, 209 insertions(+), 193 deletions(-) create mode 100644 src/builtins/local.c create mode 100644 src/builtins/set.c create mode 100644 src/builtins/unset.c delete mode 100644 src/local/check_local_var.c delete mode 100644 src/local/create_local.c delete mode 100644 src/local/get_local.c delete mode 100644 src/local/set_local.c delete mode 100644 src/local/unset_local.c diff --git a/src/builtins.h b/src/builtins.h index 5b22df5..8fa0707 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -31,4 +31,6 @@ int builtins_display_alias(alias_t *alias); int builtins_repeat(ef_t *ef, char **args); int builtins_yes(ef_t *ef, char **args); int builtins_foreach(ef_t *ef, char **args); +int builtins_set(ef_t *ef, char **args); +int builtins_unset(ef_t *ef, char **args); #endif /* BUILTIND_H */ diff --git a/src/builtins/env.c b/src/builtins/env.c index 8f2f252..3665aab 100644 --- a/src/builtins/env.c +++ b/src/builtins/env.c @@ -49,7 +49,7 @@ int builtins_unsetenv(ef_t *ef, char **args) if (args[1] == NULL) return (WRITE_CONST(STDERR_FILENO, "unsetenv: Too few arguments.\n"), RETURN_FAILURE); - if (!unset_env(ef->env, args[1])) - return RETURN_FAILURE; + for (int i = 0; args[i]; i++) + unset_env(ef->env, args[1]); return RETURN_SUCCESS; } diff --git a/src/builtins/local.c b/src/builtins/local.c new file mode 100644 index 0000000..ea74e1b --- /dev/null +++ b/src/builtins/local.c @@ -0,0 +1,123 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** local +*/ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "env.h" +#include "exec.h" +#include "u_str.h" +#include "u_mem.h" + +bool check_local_var(char *var, char *func_name) +{ + if (!isalpha(var[0])) + return (fprintf(stdout, "%s: Variable name must begin" + " with a letter.\n", func_name), RETURN_FAILURE); + if (!u_str_is_only_alnum(var)) + return (fprintf(stdout, "%s: Variable name must contain" + " alphanumeric characters.\n", func_name), RETURN_FAILURE); + return RETURN_SUCCESS; +} + +char *get_local_value(local_t *local, char const *key) +{ + int key_len = u_strlen(key); + + for (size_t i = 0; i < local->sz; i++) { + if (local->local_var[i] == NULL) + continue; + if (u_strcspn(local->local_var[i], '\t') != key_len) + continue; + if (u_strcmp(local->local_var[i], key) == 0) + return local->local_var[i] + key_len + 1; + } + return NULL; +} + +local_t create_local(void) +{ + local_t local = {.sz = 0, .cap = 2}; + + local.local_var = (char **)malloc(sizeof(char *) * local.cap); + if (local.local_var == NULL) + return (local_t){.sz = 0, .cap = 2, .local_var = NULL}; + local.local_var[local.sz] = NULL; + local.sz++; + return local; +} + +static +bool ensure_local_capacity(local_t *local) +{ + char **new_ptr = NULL; + + if (local->sz < local->cap) + return true; + new_ptr = (char **)u_realloc((void *)local->local_var, + sizeof *local->local_var * local->sz, + sizeof *local->local_var * local->cap << 1); + if (!new_ptr) + return false; + local->cap <<= 1; + local->local_var = new_ptr; + return true; +} + +bool set_local(local_t *local, char *var, char *value) +{ + char *new_loc = NULL; + size_t key_len = u_strlen(var); + size_t value_len = u_strlen(value); + + if (get_local_value(local, var) != NULL) + unset_local(local, var); + local->sz++; + if (!ensure_local_capacity(local)) + return false; + new_loc = malloc(sizeof(char) * (key_len + value_len + 2)); + if (new_loc == NULL) + return false; + u_bzero(new_loc, key_len + value_len + 2); + u_strcpy(new_loc, var); + new_loc[key_len] = '\t'; + if (value_len > 0) + u_strcpy(new_loc + key_len + 1, value); + local->local_var[local->sz - 1] = new_loc; + return true; +} + +static +void unset_local_move(local_t *local, size_t i) +{ + while (local->local_var[i]) { + local->local_var[i] = local->local_var[i + 1]; + i++; + } +} + +bool unset_local(local_t *local, char *var) +{ + int key_len = u_strlen(var); + + for (size_t i = 0; i < local->sz; i++) { + if (local->local_var[i] == NULL) + continue; + if (u_strcspn(local->local_var[i], '\t') != key_len) + continue; + if (u_strcmp(local->local_var[i], var) == 0) { + unset_local_move(local, i); + local->sz--; + return true; + } + } + return false; +} diff --git a/src/builtins/set.c b/src/builtins/set.c new file mode 100644 index 0000000..d766704 --- /dev/null +++ b/src/builtins/set.c @@ -0,0 +1,51 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** set +*/ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "env.h" +#include "exec.h" +#include "u_str.h" + +void print_local(ef_t *ef) +{ + for (size_t i = 0; i < ef->exec_ctx->local->sz; i++) { + if (ef->exec_ctx->local->local_var[i] == NULL) + continue; + write(ef->out_fd, ef->exec_ctx->local->local_var[i], + u_strlen(ef->exec_ctx->local->local_var[i])); + WRITE_CONST(ef->out_fd, "\n"); + } +} + +int builtins_set(ef_t *ef, char **args) +{ + char *var = NULL; + + if (args[1] == NULL) + return (print_local(ef), RETURN_SUCCESS); + for (int i = 1; args[i]; i++){ + if (check_local_var(args[i], args[0])) + return RETURN_FAILURE; + var = args[i]; + i++; + if (!args[i]) + return (set_local(ef->exec_ctx->local, var, NULL) + , RETURN_SUCCESS); + if (strcmp(args[i], "=")) + return RETURN_FAILURE; + i++; + if (!set_local(ef->exec_ctx->local, var, args[i])) + return RETURN_FAILURE; + } + return RETURN_SUCCESS; +} diff --git a/src/builtins/unset.c b/src/builtins/unset.c new file mode 100644 index 0000000..ced6864 --- /dev/null +++ b/src/builtins/unset.c @@ -0,0 +1,28 @@ +/* +** EPITECH PROJECT, 2025 +** 42sh +** File description: +** unset +*/ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "env.h" +#include "exec.h" +#include "u_str.h" + + +int builtins_unset(ef_t *ef, char **args) +{ + if (args[1] == NULL) + return (WRITE_CONST(STDERR_FILENO, "unset: Too few arguments.\n"), + RETURN_FAILURE); + for (int i = 1; args[i]; i++) + unset_local(ef->exec_ctx->local, args[i]); + return RETURN_SUCCESS; +} diff --git a/src/exec.c b/src/exec.c index f3a7ee0..d940ea2 100644 --- a/src/exec.c +++ b/src/exec.c @@ -38,7 +38,9 @@ const builtins_funcs_t BUILTINS[] = { { "history", &builtins_history}, { "alias", &builtins_alias}, { "yes", &builtins_yes }, - { "foreach", &builtins_foreach } + { "foreach", &builtins_foreach }, + { "set", &builtins_set }, + { "unset", &builtins_unset } }; const size_t BUILTINS_SZ = sizeof BUILTINS / sizeof *BUILTINS; diff --git a/src/local/check_local_var.c b/src/local/check_local_var.c deleted file mode 100644 index fadf098..0000000 --- a/src/local/check_local_var.c +++ /dev/null @@ -1,28 +0,0 @@ -/* -** EPITECH PROJECT, 2025 -** 42sh -** File description: -** check_local_var -*/ - -#include -#include -#include -#include -#include - -#include "common.h" -#include "env.h" -#include "exec.h" -#include "u_str.h" - -bool check_local_var(char *var, char *func_name) -{ - if (!isalpha(var[0])) - return (fprintf(stdout, "%s: Variable name must begin" - " with a letter.\n", func_name), RETURN_FAILURE); - if (!u_str_is_only_alnum(var)) - return (fprintf(stdout, "%s: Variable name must contain" - " alphanumeric characters.\n", func_name), RETURN_FAILURE); - return RETURN_SUCCESS; -} diff --git a/src/local/create_local.c b/src/local/create_local.c deleted file mode 100644 index 0a1e011..0000000 --- a/src/local/create_local.c +++ /dev/null @@ -1,28 +0,0 @@ -/* -** EPITECH PROJECT, 2025 -** 42sh -** File description: -** create_local -*/ -#include -#include -#include -#include -#include - -#include "env.h" -#include "u_mem.h" -#include "u_str.h" -#include "local.h" - -local_t create_local(void) -{ - local_t local = {.sz = 0, .cap = 2}; - - local.local_var = (char **)malloc(sizeof(char *) * local.cap); - if (local.local_var == NULL) - return (local_t){.sz = 0, .cap = 2, .local_var = NULL}; - local.local_var[local.sz] = NULL; - local.sz++; - return local; -} diff --git a/src/local/get_local.c b/src/local/get_local.c deleted file mode 100644 index 7f07ee4..0000000 --- a/src/local/get_local.c +++ /dev/null @@ -1,32 +0,0 @@ -/* -** EPITECH PROJECT, 2025 -** 42sh -** File description: -** get_local -*/ - -#include -#include -#include -#include -#include - -#include "env.h" -#include "u_mem.h" -#include "u_str.h" -#include "local.h" - -char *get_local_value(local_t *local, char const *key) -{ - int key_len = u_strlen(key); - - for (size_t i = 0; i < local->sz; i++) { - if (local->local_var[i] == NULL) - continue; - if (u_strcspn(local->local_var[i], '\t') != key_len) - continue; - if (u_strcmp(local->local_var[i], key) == 0) - return local->local_var[i] + key_len + 1; - } - return NULL; -} diff --git a/src/local/set_local.c b/src/local/set_local.c deleted file mode 100644 index a90161b..0000000 --- a/src/local/set_local.c +++ /dev/null @@ -1,57 +0,0 @@ -/* -** EPITECH PROJECT, 2025 -** 42sh -** File description: -** set_local -*/ - -#include -#include -#include -#include -#include - -#include "env.h" -#include "u_mem.h" -#include "u_str.h" -#include "local.h" - -static -bool ensure_local_capacity(local_t *local) -{ - char **new_ptr = NULL; - - if (local->sz < local->cap) - return true; - new_ptr = (char **)u_realloc((void *)local->local_var, - sizeof *local->local_var * local->sz, - sizeof *local->local_var * local->cap << 1); - if (!new_ptr) - return false; - local->cap <<= 1; - local->local_var = new_ptr; - return true; -} - -bool set_local(local_t *local, char *var, char *value) -{ - char *new_loc = NULL; - size_t key_len = u_strlen(var); - size_t value_len = u_strlen(value); - - if (get_local_value(local, var) != NULL) - unset_local(local, var); - local->sz++; - if (!ensure_local_capacity(local)) - return false; - new_loc = malloc(sizeof(char) * (key_len + value_len + 2)); - if (new_loc == NULL) - return false; - u_bzero(new_loc, key_len + value_len + 2); - u_strcpy(new_loc, var); - new_loc[key_len] = '\t'; - if (value_len > 0) - u_strcpy(new_loc + key_len + 1, value); - local->local_var[local->sz - 1] = new_loc; - return true; -} diff --git a/src/local/unset_local.c b/src/local/unset_local.c deleted file mode 100644 index 8ff115f..0000000 --- a/src/local/unset_local.c +++ /dev/null @@ -1,45 +0,0 @@ -/* -** EPITECH PROJECT, 2025 -** 42sh -** File description: -** unset_local -*/ - -#include -#include -#include -#include -#include - -#include "env.h" -#include "u_mem.h" -#include "u_str.h" -#include "local.h" - - -static -void unset_local_move(local_t *local, size_t i) -{ - while (local->local_var[i]) { - local->local_var[i] = local->local_var[i + 1]; - i++; - } -} - -bool unset_local(local_t *local, char *var) -{ - int key_len = u_strlen(var); - - for (size_t i = 0; i < local->sz; i++) { - if (local->local_var[i] == NULL) - continue; - if (u_strcspn(local->local_var[i], '\t') != key_len) - continue; - if (u_strcmp(local->local_var[i], var) == 0) { - unset_local_move(local, i); - local->sz--; - return true; - } - } - return false; -} From f7faa4745beac471992009e820b4ee2617b3192f Mon Sep 17 00:00:00 2001 From: tekClovis Date: Tue, 22 Apr 2025 14:01:46 +0200 Subject: [PATCH 4/5] [FIX] set the last local varr to NULL in set --- src/builtins/local.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/builtins/local.c b/src/builtins/local.c index ea74e1b..18be358 100644 --- a/src/builtins/local.c +++ b/src/builtins/local.c @@ -92,6 +92,7 @@ bool set_local(local_t *local, char *var, char *value) if (value_len > 0) u_strcpy(new_loc + key_len + 1, value); local->local_var[local->sz - 1] = new_loc; + local->local_var[local->sz] = NULL; return true; } From 78833c087b61f438d6e42c86a406ef9fbdc9cd5b Mon Sep 17 00:00:00 2001 From: tekClovis Date: Tue, 22 Apr 2025 14:14:27 +0200 Subject: [PATCH 5/5] [FIX] in yes was not allocated correctly --- src/builtins/yes.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/builtins/yes.c b/src/builtins/yes.c index 5678eab..2790f4e 100644 --- a/src/builtins/yes.c +++ b/src/builtins/yes.c @@ -16,6 +16,7 @@ #include "common.h" #include "exec.h" #include "u_str.h" +#include "u_mem.h" static int len_buffer(char **args) @@ -37,13 +38,15 @@ char *define_prompt(char **args) buffer = malloc(sizeof(char) * (len_buffer(args) + 1)); if (buffer == NULL) return NULL; + u_bzero(buffer, len_buffer(args) + 1); strcpy(buffer, args[1]); + buffer[strlen(buffer)] = ' '; for (int i = 2; args[i]; i++){ strcat(buffer, args[i]); if (args[i + 1] != NULL) - buffer[strlen(buffer) - 1] = ' '; + buffer[strlen(buffer)] = ' '; } - buffer[strlen(buffer) - 1] = '\n'; + buffer[strlen(buffer)] = '\n'; return buffer; }