mirror of
https://github.com/Savapitech/42sh.git
synced 2026-03-18 21:50:35 +01:00
Add bonus
This commit is contained in:
126
bonus/Makefile
Normal file
126
bonus/Makefile
Normal file
@@ -0,0 +1,126 @@
|
||||
##
|
||||
## EPITECH PROJECT, 2024
|
||||
## __
|
||||
## File description:
|
||||
## ./Makefile
|
||||
##
|
||||
|
||||
MAKEFLAGS += -j
|
||||
|
||||
BIN_NAME := mysh
|
||||
|
||||
LIB_NAME := libu.a
|
||||
|
||||
SRC := $(wildcard src/*.c)
|
||||
|
||||
LIB_SRC := $(wildcard ulib/*.c)
|
||||
LIB_SRC += $(wildcard ulib/write/printf/*.c)
|
||||
LIB_SRC += $(wildcard ulib/math/*.c)
|
||||
LIB_SRC += $(wildcard ulib/mem/*.c)
|
||||
LIB_SRC += $(wildcard ulib/str/*.c)
|
||||
LIB_SRC += $(wildcard ulib/write/*.c)
|
||||
|
||||
BUILD_DIR := .build
|
||||
|
||||
CC := gcc
|
||||
|
||||
CFLAGS += -Wall -Wextra -Werror=write-strings -iquote ulib
|
||||
CFLAGS += -Wno-unused-parameter -Wunused-result -fanalyzer
|
||||
CFLAGS += -Wp,-U_FORTIFY_SOURCE -Wcast-qual -Wduplicated-branches
|
||||
CFLAGS += -Wduplicated-cond -Wformat=2 -Wshadow -fno-builtin
|
||||
CFLAGS += -Wstrict-aliasing=0 -Wstrict-prototypes -Wunreachable-code
|
||||
CFLAGS += -Wwrite-strings -Werror=declaration-after-statement
|
||||
CFLAGS += -Werror=format-nonliteral -Werror=int-conversion -Werror=return-type
|
||||
CFLAGS += -Werror=vla-larger-than=0 -Wno-discarded-qualifiers
|
||||
|
||||
LDFLAGS += -L .
|
||||
LDLIBS := -lu
|
||||
|
||||
include utils.mk
|
||||
|
||||
.PHONY: _start all
|
||||
_start: all
|
||||
|
||||
# call mk-profile release, SRC, additional CFLAGS
|
||||
define mk-profile
|
||||
|
||||
NAME_$(strip $1) := $4
|
||||
OBJ_$(strip $1) := $$($(strip $2):%.c=$$(BUILD_DIR)/$(strip $1)/%.o)
|
||||
|
||||
LIB_NAME_$(strip $1) := $(BUILD_DIR)/$(strip $1)/$(LIB_NAME)
|
||||
LIB_OBJ_$(strip $1) := $$(LIB_SRC:%.c=$$(BUILD_DIR)/$(strip $1)/%.o)
|
||||
|
||||
$$(BUILD_DIR)/$(strip $1)/%.o: %.c
|
||||
@ mkdir -p $$(dir $$@)
|
||||
@ $$(CC) $$(CFLAGS) -o $$@ -c $$<
|
||||
@ $$(LOG_TIME) "$$(C_GREEN) CC $$(C_PURPLE) $$(notdir $$@) $$(C_RESET)"
|
||||
|
||||
$$(LIB_NAME_$(strip $1)): $$(LIB_OBJ_$(strip $1))
|
||||
@ ar rc $$@ $$(LIB_OBJ_$(strip $1))
|
||||
@ $$(LOG_TIME) "$$(C_CYAN) AR $$(C_PURPLE) $$(notdir $$@) $$(C_RESET)"
|
||||
|
||||
$$(NAME_$(strip $1)): CFLAGS += -L $$(BUILD_DIR)/$(strip $1) $3
|
||||
$$(NAME_$(strip $1)): $$(LIB_NAME_$(strip $1)) $$(OBJ_$(strip $1))
|
||||
@ $$(CC) $$(CFLAGS) $$(OBJ_$(strip $1)) $$(LDFLAGS) $$(LDLIBS) -o $$@
|
||||
@ $$(LOG_TIME) "$$(C_GREEN) CC $$(C_PURPLE) $$(notdir $$@) $$(C_RESET)"
|
||||
@ $$(LOG_TIME) "$$(C_GREEN) OK Compilation finished $$(C_RESET)"
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call mk-profile, release, SRC, , $(BIN_NAME)))
|
||||
$(eval $(call mk-profile, debug, SRC, -D U_DEBUG_MODE -g3, debug))
|
||||
$(eval $(call mk-profile, test, SRC, --coverage, test))
|
||||
$(eval $(call mk-profile, afl, SRC, -D AFL_MODE, afl_runner))
|
||||
|
||||
all: $(NAME_release)
|
||||
|
||||
.PHONY: tests_run
|
||||
tests_run: $(NAME_test)
|
||||
- find fixtures -name "*.sh" | xargs -i \
|
||||
sh -c 'cat {} | env -i PATH="$(dir $(shell which ls))" ./$^'
|
||||
|
||||
.PHONY: cov
|
||||
cov: tests_run
|
||||
gcovr . \
|
||||
--gcov-ignore-errors=no_working_dir_found \
|
||||
--exclude-unreachable-branches \
|
||||
--exclude tests
|
||||
|
||||
.PHONY: afl
|
||||
afl: CC := AFL_USE_ASAN=1 afl-gcc-fast
|
||||
afl: $(NAME_afl)
|
||||
|
||||
define newline
|
||||
|
||||
|
||||
endef
|
||||
|
||||
AFL_FLAGS := -i afl/inputs
|
||||
AFL_FLAGS += -x afl/tokens
|
||||
AFL_FLAGS += -o afl/generated
|
||||
|
||||
PROCS ?= $(shell nproc)
|
||||
|
||||
.PHONY: afl_run
|
||||
afl_run: afl
|
||||
@ mkdir -p afl/generated
|
||||
screen -dmS main_instance \
|
||||
afl-fuzz $(AFL_FLAGS) -M fuzzer_1 -- ./afl_runner
|
||||
$(foreach instance, $(shell seq 1 $(PROCS)),\
|
||||
screen -dmS afl_$(instance) \
|
||||
afl-fuzz $(AFL_FLAGS) -S fuzzer_$(instance) -- ./afl_runner$(newline))
|
||||
watch -n 0.25 -- afl-whatsup -s afl/generated
|
||||
|
||||
clean:
|
||||
@ $(RM) $(OBJ)
|
||||
@ $(LOG_TIME) "$(C_YELLOW) RM $(C_PURPLE) $(OBJ) $(C_RESET)"
|
||||
|
||||
fclean:
|
||||
@ $(RM) -r $(NAME_release) $(NAME_debug) $(BUILD_DIR)
|
||||
@ $(LOG_TIME) "$(C_YELLOW) RM $(C_PURPLE) $(NAME_release) $(NAME_debug) \
|
||||
$(C_RESET)"
|
||||
|
||||
.NOTPARALLEL: re
|
||||
re: fclean all
|
||||
|
||||
.PHONY: all clean fclean re
|
||||
36
bonus/afunc.txt
Normal file
36
bonus/afunc.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
malloc
|
||||
free
|
||||
exit
|
||||
opendir
|
||||
readdir
|
||||
closedir
|
||||
getcwd
|
||||
chdir
|
||||
fork
|
||||
stat
|
||||
lstat
|
||||
fstat
|
||||
open
|
||||
close
|
||||
getline
|
||||
strtok
|
||||
strtok_r
|
||||
read
|
||||
write
|
||||
execve
|
||||
access
|
||||
isatty
|
||||
wait
|
||||
wait-pid
|
||||
wait3
|
||||
wait4
|
||||
signal
|
||||
kill
|
||||
getpid
|
||||
strerror
|
||||
perror
|
||||
strsignal
|
||||
pipe
|
||||
dup
|
||||
dup2
|
||||
stdin
|
||||
150
bonus/src/builtins.c
Normal file
150
bonus/src/builtins.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "env.h"
|
||||
#include "shell.h"
|
||||
#include "u_mem.h"
|
||||
#include "u_str.h"
|
||||
|
||||
int builtins_exit(env_t *env, char **args __attribute__((unused)), char *buff,
|
||||
history_t *history)
|
||||
{
|
||||
free_env(env);
|
||||
free((void *)args);
|
||||
free(buff);
|
||||
exit(history->last_exit_code);
|
||||
}
|
||||
|
||||
int builtins_env(env_t *env, char **args __attribute__((unused)),
|
||||
char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)))
|
||||
{
|
||||
for (size_t i = 0; i < env->sz; i++) {
|
||||
if (env->env[i] == NULL)
|
||||
continue;
|
||||
write(STDOUT_FILENO, env->env[i], u_strlen(env->env[i]));
|
||||
WRITE_CONST(STDOUT_FILENO, "\n");
|
||||
}
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
int builtins_setenv(env_t *env, char **args,
|
||||
char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)))
|
||||
{
|
||||
if (args[1] == NULL)
|
||||
return builtins_env(env, args, buff, history);
|
||||
if (args[2] != NULL && args[3] != NULL) {
|
||||
WRITE_CONST(STDERR_FILENO, "setenv: Too many arguments.\n");
|
||||
return RETURN_FAILURE;
|
||||
}
|
||||
if (!isalpha(args[1][0]))
|
||||
return (WRITE_CONST(STDERR_FILENO, "setenv: Variable name must begin"
|
||||
" with a letter.\n"), RETURN_FAILURE);
|
||||
if (!u_str_is_only_alnum(args[1]))
|
||||
return (WRITE_CONST(STDERR_FILENO, "setenv: Variable name must contain"
|
||||
" alphanumeric characters.\n"), RETURN_FAILURE);
|
||||
if (!set_env(env, args[1], args[2]))
|
||||
return RETURN_FAILURE;
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
int builtins_unsetenv(env_t *env, char **args,
|
||||
__attribute__((unused)) char *buff,
|
||||
history_t *history __attribute__((unused)))
|
||||
{
|
||||
if (args[1] == NULL)
|
||||
return (WRITE_CONST(STDERR_FILENO, "unsetenv: Too few arguments.\n"),
|
||||
RETURN_FAILURE);
|
||||
if (!unset_env(env, args[1]))
|
||||
return RETURN_FAILURE;
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
void cd_print_error(void)
|
||||
{
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
WRITE_CONST(STDERR_FILENO, ": Permission denied.\n");
|
||||
break;
|
||||
case ENOENT:
|
||||
WRITE_CONST(STDERR_FILENO, ": No such file or directory.\n");
|
||||
break;
|
||||
case ENOTDIR:
|
||||
WRITE_CONST(STDERR_FILENO, ": Not a directory.\n");
|
||||
break;
|
||||
default:
|
||||
WRITE_CONST(STDERR_FILENO, ": Unknown error.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
char *get_current_dir(void)
|
||||
{
|
||||
size_t size = 64;
|
||||
char *buffer = malloc(size);
|
||||
char *new_buffer;
|
||||
size_t max_it = 100;
|
||||
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
while (getcwd(buffer, size) == NULL && max_it > 0) {
|
||||
if (errno != ERANGE)
|
||||
return (free(buffer), NULL);
|
||||
size <<= 1;
|
||||
new_buffer = u_realloc(buffer, u_strlen(buffer) + 1, size);
|
||||
if (!new_buffer)
|
||||
return (free(buffer), NULL);
|
||||
buffer = new_buffer;
|
||||
max_it--;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static
|
||||
int builtins_cd_chdir(char *path, history_t *history, char **args, env_t *env)
|
||||
{
|
||||
char *act_pwd;
|
||||
|
||||
if (history->last_chdir != NULL && args[1] != NULL
|
||||
&& u_strcmp(args[1], "-") == 0)
|
||||
path = history->last_chdir;
|
||||
act_pwd = get_current_dir();
|
||||
U_DEBUG("last chdir %s\n", history->last_chdir);
|
||||
if (chdir(path) < 0) {
|
||||
write(STDERR_FILENO, path, u_strlen(path));
|
||||
cd_print_error();
|
||||
return RETURN_FAILURE;
|
||||
}
|
||||
free(history->last_chdir);
|
||||
history->last_chdir = act_pwd;
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
int builtins_cd(env_t *env, char **args, char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)))
|
||||
{
|
||||
char *path = args[1];
|
||||
|
||||
if (path == NULL || u_strcmp(args[1], "~") == 0)
|
||||
path = get_env_value(env, "HOME");
|
||||
if (path == NULL)
|
||||
return RETURN_FAILURE;
|
||||
if (args[1] != NULL && args[2] != NULL) {
|
||||
WRITE_CONST(STDERR_FILENO, "cd: Too many arguments.\n");
|
||||
return RETURN_FAILURE;
|
||||
}
|
||||
return builtins_cd_chdir(path, history, args, env);
|
||||
}
|
||||
48
bonus/src/builtins.h
Normal file
48
bonus/src/builtins.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BUILTINS_H
|
||||
#define BUILTINS_H
|
||||
#include "env.h"
|
||||
#include "shell.h"
|
||||
|
||||
typedef struct {
|
||||
char const *name;
|
||||
int (*ptr)(env_t *env, char **args, char *buff, history_t *history);
|
||||
} builtins_t;
|
||||
|
||||
extern const builtins_t BUILTINS[];
|
||||
extern const size_t BUILTINS_SZ;
|
||||
|
||||
int builtins_exit(env_t *env, char **args __attribute__((unused)),
|
||||
char *buff, history_t *history);
|
||||
|
||||
int builtins_env(env_t *env, char **args __attribute__((unused)),
|
||||
char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)));
|
||||
|
||||
int builtins_setenv(env_t *env, char **args,
|
||||
char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)));
|
||||
|
||||
int builtins_unsetenv(env_t *env, char **args,
|
||||
char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)));
|
||||
|
||||
int builtins_cd(env_t *env, char **args,
|
||||
char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)));
|
||||
|
||||
int builtins_builtins(env_t *env __attribute__((unused)),
|
||||
char **args __attribute__((unused)), char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)));
|
||||
|
||||
int builtins_funny_double_dot(env_t *env __attribute__((unused)),
|
||||
char **args __attribute__((unused)), char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)));
|
||||
#endif /* BUILTIND_H */
|
||||
30
bonus/src/builtins2.c
Normal file
30
bonus/src/builtins2.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "common.h"
|
||||
#include "env.h"
|
||||
#include "shell.h"
|
||||
#include "u_str.h"
|
||||
|
||||
int builtins_builtins(env_t *env __attribute__((unused)),
|
||||
char **args __attribute__((unused)), char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)))
|
||||
{
|
||||
for (size_t i = 0; i < BUILTINS_SZ; i++)
|
||||
write(STDOUT_FILENO, BUILTINS[i].name, u_strlen(BUILTINS[i].name));
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
int builtins_funny_double_dot(env_t *env __attribute__((unused)),
|
||||
char **args __attribute__((unused)), char *buff __attribute__((unused)),
|
||||
history_t *history __attribute__((unused)))
|
||||
{
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
14
bonus/src/common.h
Normal file
14
bonus/src/common.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
enum {
|
||||
RETURN_SUCCESS = 0,
|
||||
RETURN_FAILURE = 1
|
||||
};
|
||||
#endif /* COMMON_H */
|
||||
36
bonus/src/debug.h
Normal file
36
bonus/src/debug.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
#include "vt100_esc_codes.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define OMIT
|
||||
|
||||
#ifdef U_DEBUG_MODE
|
||||
#define HEAD __FILE_NAME__, __LINE__
|
||||
|
||||
#define HEAD_FMT_FILE BOLD BLUE "%s" RESET
|
||||
#define HEAD_FMT_LINE ":" BOLD PURPLE "%d" RESET
|
||||
|
||||
#define HEAD_FMT HEAD_FMT_FILE HEAD_FMT_LINE " "
|
||||
|
||||
#define ERR(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
|
||||
#define DEBUG_INTERNAL(fmt, ...) ERR(HEAD_FMT fmt, HEAD, __VA_ARGS__)
|
||||
|
||||
#define U_DEBUG(fmt, ...) DEBUG_INTERNAL(fmt, __VA_ARGS__)
|
||||
#define U_DEBUG_MSG(msg) DEBUG_INTERNAL("%s\n", msg)
|
||||
|
||||
#define U_DEBUG_CALL(func, ...) func(__VA_ARGS__)
|
||||
#else
|
||||
#define U_DEBUG_CALL(func, ...) OMIT
|
||||
#define U_DEBUG_MSG(msg) OMIT
|
||||
#define U_DEBUG(fmt, ...) OMIT
|
||||
#endif
|
||||
|
||||
#endif /* DEBUG_H */
|
||||
136
bonus/src/env.c
Normal file
136
bonus/src/env.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "u_mem.h"
|
||||
#include "u_str.h"
|
||||
|
||||
char *get_env_value(env_t *env, char const *key)
|
||||
{
|
||||
int key_len = u_strlen(key);
|
||||
|
||||
for (size_t i = 0; i < env->sz; i++) {
|
||||
if (env->env[i] == NULL)
|
||||
continue;
|
||||
if (u_strcspn(env->env[i], '=') != key_len)
|
||||
continue;
|
||||
if (u_strcmp(env->env[i], key) == 0)
|
||||
return env->env[i] + key_len + 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void unset_env_move(env_t *env, size_t i)
|
||||
{
|
||||
while (env->env[i]) {
|
||||
env->env[i] = env->env[i + 1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
bool unset_env(env_t *env, char *key)
|
||||
{
|
||||
int key_len = u_strlen(key);
|
||||
|
||||
for (size_t i = 0; i < env->sz; i++) {
|
||||
if (env->env[i] == NULL)
|
||||
continue;
|
||||
if (u_strcspn(env->env[i], '=') != key_len)
|
||||
continue;
|
||||
if (u_strcmp(env->env[i], key) == 0) {
|
||||
unset_env_move(env, i);
|
||||
env->sz--;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void free_env(env_t *env)
|
||||
{
|
||||
for (size_t i = 0; i < env->sz; i++) {
|
||||
if (env->env[i] == NULL)
|
||||
continue;
|
||||
free(env->env[i]);
|
||||
}
|
||||
free((void *)env->env);
|
||||
}
|
||||
|
||||
static __attribute__((nonnull))
|
||||
bool ensure_env_capacity(env_t *env)
|
||||
{
|
||||
char **new_ptr;
|
||||
|
||||
if (env->sz < env->cap)
|
||||
return true;
|
||||
new_ptr = (char **)u_realloc((void *)env->env, sizeof *env->env * env->sz,
|
||||
sizeof *env->env * env->cap << 1);
|
||||
if (!new_ptr)
|
||||
return false;
|
||||
env->cap <<= 1;
|
||||
env->env = new_ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
void env_bzero(char **env, size_t sz)
|
||||
{
|
||||
for (size_t i = 0; i < sz; i++)
|
||||
env[i] = NULL;
|
||||
}
|
||||
|
||||
bool set_env(env_t *env, char *key, char *value)
|
||||
{
|
||||
char *new_env = NULL;
|
||||
size_t key_len = u_strlen(key);
|
||||
size_t value_len = u_strlen(value);
|
||||
|
||||
if (get_env_value(env, key) != NULL)
|
||||
unset_env(env, key);
|
||||
env->sz++;
|
||||
if (!ensure_env_capacity(env))
|
||||
return false;
|
||||
new_env = malloc(sizeof(char) * (key_len + value_len + 2));
|
||||
if (new_env == NULL)
|
||||
return false;
|
||||
u_bzero(new_env, key_len + value_len + 2);
|
||||
u_strcpy(new_env, key);
|
||||
new_env[key_len] = '=';
|
||||
if (value_len > 0)
|
||||
u_strcpy(new_env + key_len + 1, value);
|
||||
env->env[env->sz - 1] = new_env;
|
||||
return true;
|
||||
}
|
||||
|
||||
env_t parse_env(char **env)
|
||||
{
|
||||
env_t new_env = { 0, .cap = BASE_ENV_CAP };
|
||||
|
||||
new_env.env = (char **)malloc(sizeof(char *) * new_env.cap);
|
||||
if (!new_env.env)
|
||||
return (env_t){ 0, .env = NULL };
|
||||
env_bzero(new_env.env, new_env.sz);
|
||||
for (; *env != NULL; env++) {
|
||||
if (!ensure_env_capacity(&new_env))
|
||||
return (free((void *)new_env.env), (env_t){ 0 });
|
||||
new_env.env[new_env.sz] = u_strdup(*env);
|
||||
if (new_env.env[new_env.sz] == NULL)
|
||||
return (free((void *)new_env.env), (env_t){ 0 });
|
||||
new_env.sz++;
|
||||
}
|
||||
if (!ensure_env_capacity(&new_env))
|
||||
return (free((void *)new_env.env), (env_t){ 0 });
|
||||
new_env.env[new_env.sz] = NULL;
|
||||
return new_env;
|
||||
}
|
||||
30
bonus/src/env.h
Normal file
30
bonus/src/env.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef ENV_H
|
||||
#define ENV_H
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#define BASE_ENV_CAP 128
|
||||
|
||||
typedef struct {
|
||||
size_t sz;
|
||||
size_t cap;
|
||||
char **env;
|
||||
} env_t;
|
||||
|
||||
__attribute__((unused))
|
||||
void free_env(env_t *env);
|
||||
__attribute__((unused))
|
||||
env_t parse_env(char **env);
|
||||
__attribute__((unused))
|
||||
char *get_env_value(env_t *env, char const *key);
|
||||
__attribute__((unused))
|
||||
bool unset_env(env_t *env, char *key);
|
||||
__attribute__((nonnull(1, 2)))
|
||||
bool set_env(env_t *env, char *key, char *value);
|
||||
#endif
|
||||
242
bonus/src/exec.c
Normal file
242
bonus/src/exec.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "env.h"
|
||||
#include "exec.h"
|
||||
#include "u_mem.h"
|
||||
#include "u_str.h"
|
||||
|
||||
const builtins_t BUILTINS[] = {
|
||||
{ "builtins", &builtins_builtins },
|
||||
{ "cd", &builtins_cd },
|
||||
{ "chdir", &builtins_cd },
|
||||
{ "env", &builtins_env },
|
||||
{ "printenv", &builtins_env },
|
||||
{ "setenv", &builtins_setenv },
|
||||
{ "unsetenv", &builtins_unsetenv },
|
||||
{ ":", &builtins_funny_double_dot },
|
||||
{ "exit", &builtins_exit }
|
||||
};
|
||||
|
||||
const size_t BUILTINS_SZ = sizeof BUILTINS / sizeof *BUILTINS;
|
||||
|
||||
static
|
||||
char *build_full_path(const char *token, const char *binary)
|
||||
{
|
||||
size_t len_token = u_strlen(token);
|
||||
size_t len_bin = u_strlen(binary);
|
||||
char *full_path = malloc(len_token + len_bin + 2);
|
||||
|
||||
if (!full_path)
|
||||
return NULL;
|
||||
u_strcpy(full_path, token);
|
||||
full_path[len_token] = '/';
|
||||
u_strcpy(full_path + len_token + 1, binary);
|
||||
full_path[len_token + len_bin + 1] = '\0';
|
||||
return full_path;
|
||||
}
|
||||
|
||||
static
|
||||
char *find_binary(const char *path_env, const char *binary)
|
||||
{
|
||||
static char *saveptr = NULL;
|
||||
static char *path = NULL;
|
||||
char *token;
|
||||
char *full_path;
|
||||
|
||||
if (path_env) {
|
||||
path = u_strdup(path_env);
|
||||
if (!path)
|
||||
return NULL;
|
||||
token = strtok_r(path, ":", &saveptr);
|
||||
} else
|
||||
token = strtok_r(NULL, ":", &saveptr);
|
||||
if (!token)
|
||||
return free(path), u_strdup(binary);
|
||||
full_path = build_full_path(token, binary);
|
||||
if (!full_path)
|
||||
return NULL;
|
||||
return access(full_path, X_OK) == 0 ? full_path : (free(full_path),
|
||||
find_binary(NULL, binary));
|
||||
}
|
||||
|
||||
static __attribute__((nonnull))
|
||||
bool ensure_args_capacity(char ***args, size_t const sz, size_t *cap)
|
||||
{
|
||||
char **new_ptr;
|
||||
|
||||
if (sz < *cap)
|
||||
return true;
|
||||
new_ptr = (char **)u_realloc((void *)*args, sizeof *args * sz,
|
||||
sizeof *args * *cap << 1);
|
||||
if (!new_ptr)
|
||||
return false;
|
||||
*cap <<= 1;
|
||||
*args = new_ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
char **parse_args(char *buffer)
|
||||
{
|
||||
size_t sz = 0;
|
||||
size_t cap = DEFAULT_ARGS_CAP;
|
||||
char **args = (char **)malloc(sizeof *args * cap);
|
||||
char *token;
|
||||
|
||||
if (!args)
|
||||
return NULL;
|
||||
token = strtok(buffer, " \t\v");
|
||||
while (token != NULL) {
|
||||
ensure_args_capacity(&args, sz, &cap);
|
||||
args[sz] = token;
|
||||
U_DEBUG("Args [%lu] [%s]\n", sz, args[sz]);
|
||||
sz++;
|
||||
token = strtok(NULL, " \t\v");
|
||||
}
|
||||
ensure_args_capacity(&args, sz, &cap);
|
||||
args[sz] = NULL;
|
||||
return args;
|
||||
}
|
||||
|
||||
static
|
||||
int command_error(char *cmd, char **args, int error)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (access(cmd, F_OK) == -1) {
|
||||
write(STDERR_FILENO, args[0], u_strlen(args[0]));
|
||||
WRITE_CONST(STDERR_FILENO, ": Command not found.\n");
|
||||
return 84;
|
||||
}
|
||||
stat(cmd, &st);
|
||||
if (S_ISDIR(st.st_mode) || access(cmd, X_OK)) {
|
||||
write(STDERR_FILENO, args[0], u_strlen(args[0]));
|
||||
WRITE_CONST(STDERR_FILENO, ": Permission denied.\n");
|
||||
return 84;
|
||||
}
|
||||
if (error == ENOEXEC) {
|
||||
write(STDERR_FILENO, args[0], u_strlen(args[0]));
|
||||
WRITE_CONST(STDERR_FILENO, ": Exec format error."
|
||||
" Binary file not executable.\n");
|
||||
return 0;
|
||||
}
|
||||
return 84;
|
||||
}
|
||||
|
||||
static
|
||||
int launch_bin(char *full_bin_path, char **args, env_t *env, char *buff)
|
||||
{
|
||||
int status;
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
#if defined(AFL_MODE)
|
||||
exit(0);
|
||||
#else
|
||||
if (execve(full_bin_path, args, env->env) < 0) {
|
||||
status = command_error(full_bin_path, args, errno);
|
||||
free_env(env);
|
||||
free((void *)args);
|
||||
free(buff);
|
||||
exit(status);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
waitpid(pid, &status, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
void status_handler(int status, history_t *history)
|
||||
{
|
||||
char *strsig;
|
||||
|
||||
if (WIFEXITED(status))
|
||||
history->last_exit_code = WEXITSTATUS(status);
|
||||
if (!WIFEXITED(status) && WIFSIGNALED(status)) {
|
||||
if (WTERMSIG(status) != SIGFPE && WTERMSIG(status) != SIGINT &&
|
||||
WTERMSIG(status) != SIGTRAP) {
|
||||
strsig = strsignal(WTERMSIG(status));
|
||||
write(STDERR_FILENO, strsig, u_strlen(strsig));
|
||||
}
|
||||
if (WTERMSIG(status) == SIGTRAP)
|
||||
WRITE_CONST(STDERR_FILENO, "Trace/BPT trap");
|
||||
if (WTERMSIG(status) == SIGFPE)
|
||||
WRITE_CONST(STDERR_FILENO, "Floating exception");
|
||||
if (WCOREDUMP(status))
|
||||
WRITE_CONST(STDERR_FILENO, " (core dumped)");
|
||||
WRITE_CONST(STDERR_FILENO, "\n");
|
||||
}
|
||||
U_DEBUG("Exit code [%d]\n", history->last_exit_code);
|
||||
}
|
||||
|
||||
static
|
||||
bool builtins_launcher(char *buffer, env_t *env, history_t *history,
|
||||
char **args)
|
||||
{
|
||||
int buffer_l = u_strlen(buffer);
|
||||
|
||||
for (size_t i = 0; i < BUILTINS_SZ; i++) {
|
||||
if (u_strlen(BUILTINS[i].name) != buffer_l)
|
||||
continue;
|
||||
if (u_strcmp(BUILTINS[i].name, buffer) == 0) {
|
||||
history->last_exit_code =
|
||||
BUILTINS[i].ptr(env, args, buffer, history);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
char *parse_full_bin_path(env_t *env, char *bin_name)
|
||||
{
|
||||
char const *path = get_env_value(env, "PATH");
|
||||
char *full_bin_path;
|
||||
|
||||
if (path == NULL)
|
||||
path = DEFAULT_PATH;
|
||||
U_DEBUG("Used path [%s]\n", path);
|
||||
full_bin_path = find_binary(path, bin_name);
|
||||
U_DEBUG("Exec bin [%s]\n", full_bin_path);
|
||||
if (full_bin_path == NULL)
|
||||
return NULL;
|
||||
return full_bin_path;
|
||||
}
|
||||
|
||||
int execute(char *buffer, env_t *env, history_t *history)
|
||||
{
|
||||
char *full_bin_path;
|
||||
char **args = parse_args(buffer);
|
||||
int status;
|
||||
|
||||
if (!args)
|
||||
return RETURN_FAILURE;
|
||||
if (builtins_launcher(buffer, env, history, args))
|
||||
return RETURN_SUCCESS;
|
||||
full_bin_path = parse_full_bin_path(env, args[0]);
|
||||
if (full_bin_path == NULL)
|
||||
return (free((void *)args), RETURN_FAILURE);
|
||||
U_DEBUG("Found bin [%s]\n", full_bin_path);
|
||||
status = launch_bin(full_bin_path, args, env, buffer);
|
||||
status_handler(status, history);
|
||||
free(full_bin_path);
|
||||
free((void *)args);
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
23
bonus/src/exec.h
Normal file
23
bonus/src/exec.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef EXEC_H
|
||||
#define EXEC_H
|
||||
#include "env.h"
|
||||
#include "shell.h"
|
||||
#define DEFAULT_ARGS_CAP 1
|
||||
#define DEFAULT_PATH "/usr/bin:."
|
||||
|
||||
typedef struct {
|
||||
char **args;
|
||||
size_t count;
|
||||
size_t cap;
|
||||
} args_t;
|
||||
|
||||
__attribute__((nonnull))
|
||||
int execute(char *buffer, env_t *env, history_t *history);
|
||||
#endif /* EXEC_H */
|
||||
16
bonus/src/main.c
Normal file
16
bonus/src/main.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "shell.h"
|
||||
|
||||
int main(int ac __attribute__((unused)), char **av __attribute__((unused)),
|
||||
char **env)
|
||||
{
|
||||
U_DEBUG_MSG("Debug mode activated.");
|
||||
return shell(env);
|
||||
}
|
||||
68
bonus/src/shell.c
Normal file
68
bonus/src/shell.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "env.h"
|
||||
#include "exec.h"
|
||||
#include "shell.h"
|
||||
#include "u_str.h"
|
||||
|
||||
__attribute__((unused))
|
||||
static
|
||||
void debug_env_entries(env_t *env)
|
||||
{
|
||||
for (size_t i = 0; i < env->sz; i++) {
|
||||
if (env->env[i] == NULL)
|
||||
continue;
|
||||
U_DEBUG("Env entry [%lu] [%s]\n", i, env->env[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int shell_loop(env_t *env, int is_a_tty, history_t *history)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
size_t buffer_sz;
|
||||
size_t buffer_len;
|
||||
|
||||
while (true) {
|
||||
if (is_a_tty)
|
||||
WRITE_CONST(STDOUT_FILENO, SHELL_PROMPT);
|
||||
if (getline(&buffer, &buffer_sz, stdin) == -1)
|
||||
break;
|
||||
buffer_len = u_strlen(buffer);
|
||||
if (buffer_len < 2 || !u_str_is_alnum(buffer))
|
||||
continue;
|
||||
if (buffer[buffer_len - 1] == '\n')
|
||||
buffer[buffer_len - 1] = '\0';
|
||||
U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, buffer);
|
||||
execute(buffer, env, history);
|
||||
}
|
||||
if (is_a_tty)
|
||||
WRITE_CONST(STDOUT_FILENO, "exit\n");
|
||||
return (free(buffer), history->last_exit_code);
|
||||
}
|
||||
|
||||
int shell(char **env_ptr)
|
||||
{
|
||||
env_t env = parse_env(env_ptr);
|
||||
history_t history = { .cmd_history = NULL, 0, .last_chdir = NULL };
|
||||
int shell_result;
|
||||
|
||||
if (!env.env)
|
||||
return RETURN_FAILURE;
|
||||
U_DEBUG_CALL(debug_env_entries, &env);
|
||||
shell_result = shell_loop(&env, isatty(STDIN_FILENO), &history);
|
||||
free_env(&env);
|
||||
return shell_result;
|
||||
}
|
||||
19
bonus/src/shell.h
Normal file
19
bonus/src/shell.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef SHELL_H
|
||||
#define SHELL_H
|
||||
#include "vt100_esc_codes.h"
|
||||
#define SHELL_PROMPT RED "|> " RESET
|
||||
|
||||
typedef struct {
|
||||
char **cmd_history;
|
||||
int last_exit_code;
|
||||
char *last_chdir;
|
||||
} history_t;
|
||||
int shell(char **env);
|
||||
#endif /* SHELL_H */
|
||||
27
bonus/src/vt100_esc_codes.h
Normal file
27
bonus/src/vt100_esc_codes.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef CR_VT100_ESC_CODES_H
|
||||
#define CR_VT100_ESC_CODES_H
|
||||
|
||||
#define ESC "\033"
|
||||
#define CFMT(n) ESC "[" #n "m"
|
||||
|
||||
// move
|
||||
#define MOVE_RIGHT(n) ESC "[" #n "C"
|
||||
|
||||
// colors
|
||||
#define RESET CFMT(0)
|
||||
#define BOLD CFMT(1)
|
||||
|
||||
#define RED CFMT(31)
|
||||
#define GREEN CFMT(32)
|
||||
#define YELLOW CFMT(33)
|
||||
#define BLUE CFMT(34)
|
||||
#define PURPLE CFMT(35)
|
||||
#define CYAN CFMT(36)
|
||||
#endif
|
||||
1
bonus/ulib/lib.h
Symbolic link
1
bonus/ulib/lib.h
Symbolic link
@@ -0,0 +1 @@
|
||||
../../include/lib.h
|
||||
18
bonus/ulib/mem/bzero.c
Normal file
18
bonus/ulib/mem/bzero.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
__attribute__((nonnull(1)))
|
||||
bool u_bzero(char *restrict str, size_t sz)
|
||||
{
|
||||
if (sz > 0)
|
||||
for (size_t i = 0; i < sz; i++)
|
||||
str[i] = 0;
|
||||
return true;
|
||||
}
|
||||
15
bonus/ulib/mem/memcpy.c
Normal file
15
bonus/ulib/mem/memcpy.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2024
|
||||
** CPoolDay08
|
||||
** File description:
|
||||
** ./u_realloc.c
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *u_memcpy(char *dst, char const *src, size_t sz)
|
||||
{
|
||||
for (size_t i = 0; i < sz; i++)
|
||||
dst[i] = src[i];
|
||||
return dst;
|
||||
}
|
||||
28
bonus/ulib/mem/realloc.c
Normal file
28
bonus/ulib/mem/realloc.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2024
|
||||
** CPoolDay08
|
||||
** File description:
|
||||
** ./u_realloc.c
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "u_mem.h"
|
||||
|
||||
void *u_realloc(void *ptr, size_t actual_size, size_t new_size)
|
||||
{
|
||||
void *new;
|
||||
|
||||
if (ptr == NULL)
|
||||
return ptr;
|
||||
if (!actual_size && !new_size)
|
||||
return NULL;
|
||||
new = malloc(new_size);
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
if (actual_size > 0 && new_size > 0)
|
||||
u_memcpy(new, ptr, actual_size);
|
||||
free(ptr);
|
||||
return new;
|
||||
}
|
||||
25
bonus/ulib/str/str_isalnum.c
Normal file
25
bonus/ulib/str/str_isalnum.c
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool u_str_is_alnum(char *str)
|
||||
{
|
||||
for (; *str != '\0'; str++)
|
||||
if (isalnum(*str))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool u_str_is_only_alnum(char *str)
|
||||
{
|
||||
for (; *str != '\0'; str++)
|
||||
if (!isalnum(*str))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
16
bonus/ulib/str/strcmp.c
Normal file
16
bonus/ulib/str/strcmp.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2024
|
||||
** B-CPE-100-REN-1-1-cpoolday06-savinien.petitjean
|
||||
** File description:
|
||||
** Task 1
|
||||
*/
|
||||
|
||||
int u_strcmp(char const *s1, char const *s2)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (; s1[i] == s2[i] && s1[i] != '\0'; i++);
|
||||
if (i > 0 && (s1[i] == '\0' || s2[i] == '\0'))
|
||||
return s1[i - 1] - s2[i - 1];
|
||||
return s1[i] - s2[i];
|
||||
}
|
||||
16
bonus/ulib/str/strcpy.c
Normal file
16
bonus/ulib/str/strcpy.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2024
|
||||
** B-CPE-100-REN-1-1-cpoolday06-savinien.petitjean
|
||||
** File description:
|
||||
** Task 1
|
||||
*/
|
||||
|
||||
__attribute__((nonnull(1, 2)))
|
||||
char *u_strcpy(char *dest, char const *src)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (; src[i] != '\0'; i++)
|
||||
dest[i] = src[i];
|
||||
return (dest);
|
||||
}
|
||||
16
bonus/ulib/str/strcspn.c
Normal file
16
bonus/ulib/str/strcspn.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
int u_strcspn(char *str, char c)
|
||||
{
|
||||
char *old_str = str;
|
||||
|
||||
for (; *str != '\0'; str++)
|
||||
if (*str == c)
|
||||
return str - old_str;
|
||||
return 0;
|
||||
}
|
||||
23
bonus/ulib/str/strdup.c
Normal file
23
bonus/ulib/str/strdup.c
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2024
|
||||
** CPoolDay08
|
||||
** File description:
|
||||
** ./u_strdup.c
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "u_mem.h"
|
||||
#include "u_str.h"
|
||||
|
||||
char *u_strdup(char const *src)
|
||||
{
|
||||
char *dest;
|
||||
int len = u_strlen(src);
|
||||
|
||||
dest = malloc(sizeof(char) * (len + 1));
|
||||
if (dest == NULL)
|
||||
return NULL;
|
||||
u_bzero(dest, len + 1);
|
||||
return u_strcpy(dest, src);
|
||||
}
|
||||
19
bonus/ulib/str/strlen.c
Normal file
19
bonus/ulib/str/strlen.c
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2024
|
||||
** B-CPE-100-REN-1-1-cpoolday06-savinien.petitjean
|
||||
** File description:
|
||||
** Task 3
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int u_strlen(char const *str)
|
||||
{
|
||||
char const *p = str;
|
||||
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
for (; *p != '\0'; p++);
|
||||
return (p - str);
|
||||
}
|
||||
20
bonus/ulib/u_mem.h
Normal file
20
bonus/ulib/u_mem.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef MEM_H
|
||||
#define MEM_H
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#define IDX_OF(array, i, mem_s) (array + ((i) * (mem_s)))
|
||||
|
||||
void *u_memcpy(char *dst, char const *src, size_t sz);
|
||||
void *u_realloc(void *ptr, size_t actual_size, size_t new_size);
|
||||
void u_swap(int *, int *);
|
||||
bool u_bzero(char *restrict str, size_t sz);
|
||||
int swap_uint32(int src);
|
||||
|
||||
#endif /* MEM_H */
|
||||
37
bonus/ulib/u_str.h
Normal file
37
bonus/ulib/u_str.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2025
|
||||
** __
|
||||
** File description:
|
||||
** _
|
||||
*/
|
||||
|
||||
#ifndef STRING_H
|
||||
#define STRING_H
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#define WRITE_CONST(fd, str) write(fd, str, sizeof str - 1)
|
||||
|
||||
typedef struct {
|
||||
char *str;
|
||||
size_t sz;
|
||||
size_t cap;
|
||||
} buff_t;
|
||||
|
||||
int u_getnbr(char const *);
|
||||
char *u_strcat(char *, char const *);
|
||||
char *u_strncat(char *, char const *, int);
|
||||
char *u_strdup(char const *);
|
||||
int u_strlen(char const *);
|
||||
char *u_strcpy(char *, char const *);
|
||||
char *u_strncpy(char *, char const *, int);
|
||||
char *u_revstr(char *);
|
||||
char *u_strstr(char *, char const *);
|
||||
int u_strcmp(char const *, char const *);
|
||||
int u_strncmp(char const *, char const *, int);
|
||||
char *u_numstr(char *, int);
|
||||
int u_spacelen(char const *str);
|
||||
int u_strcspn(char *str, char c);
|
||||
bool u_str_is_alnum(char *str);
|
||||
bool u_str_is_only_alnum(char *str);
|
||||
|
||||
#endif /* STRING_H */
|
||||
36
bonus/utils.mk
Normal file
36
bonus/utils.mk
Normal file
@@ -0,0 +1,36 @@
|
||||
##
|
||||
## EPITECH PROJECT, 2024
|
||||
## template
|
||||
## File description:
|
||||
## utils.mk
|
||||
##
|
||||
|
||||
ifneq ($(shell command -v tput),)
|
||||
ifneq ($(shell tput colors),0)
|
||||
|
||||
C_RESET := \033[00m
|
||||
C_BOLD := \e[1m
|
||||
C_RED := \e[31m
|
||||
C_GREEN := \e[32m
|
||||
C_YELLOW := \e[33m
|
||||
C_BLUE := \e[34m
|
||||
C_PURPLE := \e[35m
|
||||
C_CYAN := \e[36m
|
||||
|
||||
C_BEGIN := \033[A
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
NOW = $(shell date +%s%3N)
|
||||
STIME := $(call NOW)
|
||||
TIME_NS = $(shell expr $(call NOW) - $(STIME))
|
||||
TIME_MS = $(shell expr $(call TIME_NS))
|
||||
|
||||
BOXIFY = "[$(C_BLUE)$(1)$(C_RESET)] $(2)"
|
||||
|
||||
ifneq ($(shell command -v printf),)
|
||||
LOG_TIME = printf $(call BOXIFY, %6s , %b\n) "$(call TIME_MS)"
|
||||
else
|
||||
LOG_TIME = echo -e $(call BOXIFY, $(call TIME_MS) ,)
|
||||
endif
|
||||
Reference in New Issue
Block a user