Added: Pipex as ressources, not most readable code tho...

This commit is contained in:
Maieul BOYER 2024-03-27 13:42:54 +01:00
parent 9482844642
commit 5d425048f2
No known key found for this signature in database
38 changed files with 2975 additions and 0 deletions

View file

@ -0,0 +1,9 @@
BasedOnStyle: Microsoft
IndentWidth: 4
ColumnLimit: 80
UseTab: Always
SortIncludes: CaseInsensitive
IndentPPDirectives: AfterHash
PPIndentWidth: 1
AllowShortIfStatementsOnASingleLine: false
AlignConsecutiveDeclarations: true

20
other/pipex/.clangd Normal file
View file

@ -0,0 +1,20 @@
CompileFlags: # Tweak the parse settings
Add:
- "-I/usr/include/"
- "-I/home/maix/school/pipex/mlx/"
- "-I/home/maix/school/pipex/mecstd/include/"
- "-I/home/maix/school/pipex/mecstd/vendor/"
- "-I/home/maix/school/pipex/mecstd/output/include/"
- "-I/home/maix/school/pipex/mecstd/generic_sources/header/"
- "-I/home/maix/school/pipex/include/"
- "-I/home/maix/school/pipex/output/include/"
- "-I/home/maix/school/pipex/generic_sources/header/"
- "-I/home/maiboyer/Documents/ring-1/pipex/vendor/"
- "-I/home/maiboyer/Documents/ring-1/pipex/mecstd/include/"
- "-I/home/maiboyer/Documents/ring-1/pipex/mecstd/vendor/"
- "-I/home/maiboyer/Documents/ring-1/pipex/mecstd/output/include/"
- "-I/home/maiboyer/Documents/ring-1/pipex/mecstd/generic_sources/header/"
- "-I/home/maiboyer/Documents/ring-1/pipex/include/"
- "-I/home/maiboyer/Documents/ring-1/pipex/output/include/"
- "-I/home/maiboyer/Documents/ring-1/pipex/generic_sources/header/"

1
other/pipex/.envrc Normal file
View file

@ -0,0 +1 @@
use flake

60
other/pipex/.gitignore vendored Normal file
View file

@ -0,0 +1,60 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
./generic
.direnv
test
so_long
vgcore.*
a.out
pipex

3
other/pipex/.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "mecstd"]
path = mecstd
url = git@github.com:Maix0/mecstd.git

139
other/pipex/Makefile Normal file
View file

@ -0,0 +1,139 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# Makefile :+: :+: :+: #
# +:+ +:+ +:+ #
# By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2023/11/03 13:20:01 by maiboyer #+# #+# #
# Updated: 2024/01/06 18:59:45 by maiboyer ### ########.fr #
# #
# **************************************************************************** #
define_module = $(addprefix $(1)/, $(2))
BUILD_DIR = build
SRC_DIR = src
INCLUDE_DIR = include output/include
LIBS_DIR = .
GENERIC_DIR = output/src
GENERIC_INCLUDE = output/include
BONUS_FLAGS =
NAME = pipex
LIB_NAME ?=
TARGET = $(NAME)
CC = clang
CFLAGS = -Wall -Wextra -Werror -g2 -lme -L$(BUILD_DIR) -Wno-unused-command-line-argument -MMD -Wno-unused-parameter -Wno-unused-variable
BONUS_FILES =
LIBS_NAME = mecstd
SUBJECT_URL = 'https://cdn.intra.42.fr/pdf/pdf/105445/en.subject.pdf'
GENERIC_FILES = $(shell cat generic_files.list)
SRC_FILES = $(shell cat source_files.list)
BONUS = $(addsuffix .c,$(addprefix $(SRC_DIR)/,$(BONUS_FILES)))
SRC = $(addsuffix .c,$(addprefix $(SRC_DIR)/,$(SRC_FILES))) \
$(addsuffix .c,$(addprefix $(GENERIC_DIR)/,$(GENERIC_FILES)))
BONUS_OBJ = $(addsuffix .o,$(addprefix $(BUILD_DIR)/,$(BONUS_FILES)))
OBJ = $(addsuffix .o,$(addprefix $(BUILD_DIR)/,$(SRC_FILES))) \
$(addsuffix .o,$(addprefix $(BUILD_DIR)/,$(GENERIC_FILES)))
DEPS = $(addsuffix .d,$(addprefix $(BUILD_DIR)/,$(SRC_FILES))) \
$(addsuffix .d,$(addprefix $(BUILD_DIR)/,$(GENERIC_FILES)))
LIBS = $(addprefix $(LIBS_DIR)/,$(LIBS_NAME))
INCLUDES = $(addprefix -I,$(foreach P,$(INCLUDE_DIR) $(GENERIC_INCLUDE) $(LIBS) $(addsuffix /include,$(LIBS)) vendor $(addsuffix /vendor,$(LIBS)),$(realpath $(P))))
COL_GRAY = \\e[90m
COL_WHITE = \\e[37m
COL_GREEN = \\e[32m
COL_BOLD = \\e[1m
COL_RESET = \\e[0m
.PHONY: all
.PHONY: libs_build
.PHONY: bonus
.PHONY: clean
.PHONY: fclean
.PHONY: re
.PHONY: format
.PHONY: subject
.PHONY: submit
.PHONY: so
all: $(NAME)
bonus: fclean
bonus: BONUS_FLAGS = -DBONUS=1
bonus: all
get_lib:
@printf $(LIB_NAME)/$(NAME)
$(NAME): $(OBJ) libs_build
@printf \\n$(COL_GRAY)Building\ Output\ $(COL_WHITE)$(COL_BOLD)%-28s$(COL_RESET)\ \
$(NAME)
@$(CC) $(INCLUDES) $(OBJ) $(CFLAGS) $(BONUS_FLAGS) -o $(NAME)
@#ar rcs $(BUILD_DIR)/$(NAME) $(OBJ)
@printf $(COL_GREEN)done$(COL_RESET)\\n
libs_build:
@- $(foreach LIB,$(LIBS),\
mkdir -p $(BUILD_DIR); \
printf \\n; \
printf $(COL_GRAY)Building\ library\ $(COL_RESET); \
printf $(COL_WHITE)$(COL_BOLD)%-25s$(COL_RESET)\\n $(LIB); \
make LIB_NAME=$(LIB)/ BUILD_DIR=$(realpath $(BUILD_DIR)) -C $(LIB) --no-print-directory all; \
printf \\n; \
)
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(dir $@)
@printf $(COL_GRAY)Building\ $(COL_BOLD)$(COL_WHITE)%-50s\ $(LIB_NAME)$<
@$(CC) $(CFLAGS) $(WERROR) $(BONUS_FLAGS) $(INCLUDES) -c $< -o $@
@printf $(COL_RESET)$(COL_GREEN)done$(COL_RESET)\\n
$(BUILD_DIR)/%.o: $(GENERIC_DIR)/%.c
@mkdir -p $(dir $@)
@printf $(COL_GRAY)Building\ $(COL_BOLD)$(COL_WHITE)%-50s\ $(LIB_NAME)$<
@$(CC) $(CFLAGS) $(WERROR) $(BONUS_FLAGS) $(INCLUDES) -c $< -o $@
@printf $(COL_RESET)$(COL_GREEN)done$(COL_RESET)\\n
clean:
@- $(foreach LIB,$(LIBS), \
make clean LIB_NAME=$(LIB)/ BUILD_DIR=$(realpath $(BUILD_DIR)) -C $(LIB) --no-print-directory || true;\
)
@- $(if $(LIB_NAME),,\
printf $(COL_WHITE)Clearing\ Artefacts\ ; \
printf $(COL_GRAY)\%-25s$(COL_RESET)\ \($(BUILD_DIR)\); \
rm -rf $(BUILD_DIR); \
printf $(COL_GREEN)done$(COL_RESET)\\n; \
)
@echo >/dev/null
fclean: clean
@- $(foreach LIB,$(LIBS), \
make fclean LIB_NAME=$(LIB)/ BUILD_DIR=$(realpath $(BUILD_DIR)) -C $(LIB) --no-print-directory || true;\
)
@printf $(COL_WHITE)Clearing\ Output\ $(COL_GRAY)%-28s$(COL_RESET)\ \
\($(LIB_NAME)$(NAME)\)
@rm -f $(BUILD_DIR)$(NAME)
@printf $(COL_GREEN)done$(COL_RESET)\\n
re: fclean all
format:
@zsh -c "c_formatter_42 **/*.c **/*.h"
subject: subject.txt
@bat --plain subject.txt
subject.txt:
@curl $(SUBJECT_URL) | pdftotext -layout -nopgbrk - subject.txt
fuck_raphael:
@echo "Oh que oui~~~\net jte nioc"
generate_filelist:
@/usr/bin/env zsh -c "tree -iFf --noreport output | rg '^output/src/(.*)\.c\$$' --replace '\$$1' | sort -u" > ./generic_files.list
@/usr/bin/env zsh -c "tree -iFf --noreport src | rg '^src/(.*)\.c\$$' --replace '\$$1' | sort -u" > ./source_files.list
-include $(DEPS)

314
other/pipex/flake.lock generated Normal file
View file

@ -0,0 +1,314 @@
{
"nodes": {
"c_formatter_42": {
"inputs": {
"c_formatter_42_src": "c_formatter_42_src",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1700259489,
"narHash": "sha256-Ye2zwphDUY/eDjyFCPFt0r9RyqMr4ZQprCE4bydNdpw=",
"owner": "maix0",
"repo": "c_formatter_42-flake",
"rev": "3d4f6a40bd1edf9fdb4959051edc172473d9544d",
"type": "github"
},
"original": {
"owner": "maix0",
"repo": "c_formatter_42-flake",
"type": "github"
}
},
"c_formatter_42_src": {
"flake": false,
"locked": {
"lastModified": 1696506114,
"narHash": "sha256-jUScF2lAHhjTWOWZsIAocE6FN8+HG+kLdpbYsEA1SZs=",
"owner": "dawnbeen",
"repo": "c_formatter_42",
"rev": "ef91ff383966885374695c327fa6015f9cfbc364",
"type": "github"
},
"original": {
"owner": "dawnbeen",
"repo": "c_formatter_42",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"inputs": {
"systems": "systems_3"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"inputs": {
"systems": "systems_4"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"generic_c": {
"inputs": {
"flake-utils": "flake-utils_3",
"naersk": "naersk",
"nixpkgs": "nixpkgs_3",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1702388541,
"narHash": "sha256-ExzIrROCDRXVnvbOs81aL9DKHm1OxlzVXQPpUTrB75c=",
"owner": "maix0",
"repo": "generic_c",
"rev": "52b5de885c015d3b84ca26c02c3684ca0e9b426d",
"type": "github"
},
"original": {
"owner": "maix0",
"repo": "generic_c",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1698420672,
"narHash": "sha256-/TdeHMPRjjdJub7p7+w55vyABrsJlt5QkznPYy55vKA=",
"owner": "nix-community",
"repo": "naersk",
"rev": "aeb58d5e8faead8980a807c840232697982d47b9",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1700108881,
"narHash": "sha256-+Lqybl8kj0+nD/IlAWPPG/RDTa47gff9nbei0u7BntE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7414e9ee0b3e9903c24d3379f577a417f0aae5f1",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1704008649,
"narHash": "sha256-rGPSWjXTXTurQN9beuHdyJhB8O761w1Zc5BqSSmHvoM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d44d59d2b5bd694cd9d996fd8c51d03e3e9ba7f7",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1702272962,
"narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e97b3e4186bcadf0ef1b6be22b8558eab1cdeb5d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1681358109,
"narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1704008649,
"narHash": "sha256-rGPSWjXTXTurQN9beuHdyJhB8O761w1Zc5BqSSmHvoM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d44d59d2b5bd694cd9d996fd8c51d03e3e9ba7f7",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"c_formatter_42": "c_formatter_42",
"flake-utils": "flake-utils_2",
"generic_c": "generic_c",
"nixpkgs": "nixpkgs_5"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": "flake-utils_4",
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1702347444,
"narHash": "sha256-ueDw7aQf4Xyk69XnDD0YNWDlFdlOgJGPeWFa7uu/cfw=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "bc13176f27cf3be724d18924b4f6aa47686ca2e3",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

39
other/pipex/flake.nix Normal file
View file

@ -0,0 +1,39 @@
{
description = "Flake utils demo";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
generic_c.url = "github:maix0/generic_c";
c_formatter_42.url = "github:maix0/c_formatter_42-flake";
};
outputs = {
self,
nixpkgs,
flake-utils,
generic_c,
c_formatter_42,
}:
flake-utils.lib.eachDefaultSystem (
system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShell = pkgs.mkShell {
packages = [
pkgs.xorg.libXext
pkgs.xorg.libX11
pkgs.clang
pkgs.clang-tools
pkgs.norminette
generic_c.packages.${system}.default
c_formatter_42.packages.${system}.default
pkgs.poppler_utils
pkgs.minilibx
pkgs.valgrind
pkgs.libbsd
pkgs.tree
pkgs.fastmod
];
};
}
);
}

View file

@ -0,0 +1,8 @@
vec/vec_buf_str
vec/vec_buf_str_functions2
vec/vec_process
vec/vec_process_functions2
vec/vec_str
vec/vec_str_functions2
vec/vec_u8
vec/vec_u8_functions2

View file

@ -0,0 +1,67 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/06 18:51:07 by maiboyer #+# #+# */
/* Updated: 2024/01/06 18:52:58 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MAIN_H
# define MAIN_H
# include "me/fs/open.h"
# include "me/fs/read.h"
# include "me/fs/write.h"
# include "me/gnl/gnl.h"
# include "me/mem/mem_find_bytes.h"
# include "me/mem/mem_move.h"
# include "me/os/pipe.h"
# include "me/os/process.h"
# include "me/printf/printf.h"
# include "me/string/split_literals.h"
# include "me/string/str_clone.h"
# include "me/string/str_len.h"
# include "me/string/str_n_compare.h"
# include "me/string/str_n_find_str.h"
# include "me/vec/vec_process.h"
# include "me/vec/vec_str.h"
# include <stdlib.h>
# include <sys/wait.h>
# include <unistd.h>
# ifndef BONUS
# define BONUS 0
# endif
typedef struct s_pipex_args
{
t_usize argc;
t_str *argv;
bool here_doc;
t_str here_doc_limiter;
t_file here_doc_fd;
t_vec_str env;
t_file in;
t_file out;
t_vec_process processes;
t_usize min;
t_usize max;
} t_pipex_args;
void set_here_doc(t_pipex_args *s);
void open_read_file(t_pipex_args *s);
void clone_vec_str_iter_fn(t_usize idx, t_str *s, void *out);
t_vec_str clone_vec_str(t_vec_str *v);
void vec_process_free_ptr(void *s);
t_error spawn_helper(t_pipex_args *s, t_usize idx, t_redirection in,
t_redirection out);
void cleanup(t_pipex_args *s, bool error);
void process_cleanup(t_process elem);
void do_here_doc_thing(t_pipex_args *s);
int main2(t_pipex_args *s);
#endif /* MAIN_H */

View file

@ -0,0 +1,26 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pipe.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 17:57:29 by maiboyer #+# #+# */
/* Updated: 2024/01/04 17:59:30 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PIPE_H
# define PIPE_H
# include "me/types.h"
typedef struct s_pipe
{
t_file read;
t_file write;
} t_pipe;
t_error create_pipe(t_pipe *out);
#endif /* PIPE_H */

View file

@ -0,0 +1,145 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* process.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/03 15:43:08 by maiboyer #+# #+# */
/* Updated: 2024/01/06 18:39:58 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PROCESS_H
# define PROCESS_H
# include "me/types.h"
# include "me/vec/vec_str.h"
# include "me/vec/vec_u8.h"
typedef t_i32 t_pid;
typedef t_i32 t_exit_code;
enum e_redirection
{
R_INHERITED = 0,
R_PIPED = 1,
R_FD = 2,
};
union u_redirection
{
struct s_fd
{
t_file value;
} fd;
struct s_piped
{
} piped;
struct s_inherited
{
} inherited;
};
typedef struct s_redirection
{
enum e_redirection tag;
union u_redirection vals;
} t_redirection;
static inline t_redirection piped(void)
{
return ((t_redirection){
.tag = R_PIPED,
});
}
static inline t_redirection inherited(void)
{
return ((t_redirection){
.tag = R_INHERITED,
});
}
static inline t_redirection fd(t_file fd)
{
return ((t_redirection){.tag = R_FD, \
.vals = (union u_redirection){.fd = {.value = fd},}});
}
enum e_wrapped_fd_tag
{
READ_ONLY,
WRITE_ONLY,
READ_WRITE,
INVALID,
};
union u_wrapped_fd
{
struct s_read_only
{
t_file fd;
} ro;
struct s_write_only
{
t_file fd;
} wo;
struct s_read_write
{
t_file fd;
} rw;
};
typedef struct s_wrapped_fd
{
enum e_wrapped_fd_tag tag;
union u_wrapped_fd vals;
} t_wrapped_fd;
static inline t_wrapped_fd ro(t_file fd)
{
return ((t_wrapped_fd){.tag = READ_ONLY,
.vals = (union u_wrapped_fd){
.ro = {.fd = fd},
}});
}
static inline t_wrapped_fd wo(t_file fd)
{
return ((t_wrapped_fd){.tag = WRITE_ONLY,
.vals = (union u_wrapped_fd){.wo = {.fd = fd}}});
}
typedef struct s_spawn_info
{
t_redirection stdin;
t_redirection stdout;
t_redirection stderr;
t_vec_str arguments;
t_vec_str environement;
t_str binary_path;
void (*forked_free)(void *);
void *forked_free_args;
} t_spawn_info;
typedef struct s_process
{
t_wrapped_fd stdin;
t_wrapped_fd stdout;
t_wrapped_fd stderr;
t_pid pid;
} t_process;
typedef struct s_process_output
{
t_pid pid;
t_vec_u8 stdout;
t_vec_u8 stderr;
t_exit_code exit_code;
} t_process_output;
t_error spawn_process(t_spawn_info info,
t_process *process);
#endif /* PROCESS_H */

View file

@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* inner_split_literals.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 14:33:41 by maiboyer #+# #+# */
/* Updated: 2024/01/06 18:42:41 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef INNER_SPLIT_LITERALS_H
# define INNER_SPLIT_LITERALS_H
# include "me/string/split_literals.h"
# include "me/types.h"
typedef struct s_booleans
{
bool error;
bool lit_sq;
bool lit_dq;
bool esc;
bool append;
} t_booleans;
char unescape(t_const_str s, t_usize *current_index, bool *did_escape,
t_error *error);
#endif /* INNER_SPLIT_LITERALS_H */

View file

@ -0,0 +1,21 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* split_literals.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 14:31:04 by maiboyer #+# #+# */
/* Updated: 2024/01/04 14:32:40 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef SPLIT_LITERALS_H
# define SPLIT_LITERALS_H
# include "me/types.h"
# include "me/vec/vec_str.h"
t_error split_literals(t_const_str s, t_vec_str *out);
#endif /* SPLIT_LITERALS_H */

56
other/pipex/input.toml Normal file
View file

@ -0,0 +1,56 @@
[definition.vec]
headers = ["mecstd/generic_sources/header/vec_C__PREFIX__.h__TEMPLATE__"]
sources = [
"mecstd/generic_sources/src/vec_C__PREFIX__.c__TEMPLATE__",
"mecstd/generic_sources/src/vec_C__PREFIX___functions2.c__TEMPLATE__",
]
replace.C__TYPENAME__ = "type"
replace.C__TYPEHEADER__ = "header_include"
replace.C__PREFIX__ = "prefix"
replace.C__PREFIXUP__ = "prefix"
[definition.hashmap]
headers = ["mecstd/generic_sources/header/hashmap_C__PREFIX__.h__TEMPLATE__"]
sources = [
"mecstd/generic_sources/src/hashmap_C__PREFIX__.c__TEMPLATE__",
"mecstd/generic_sources/src/hashmap_C__PREFIX___utils.c__TEMPLATE__",
]
replace.C__VALTYPE__ = "type"
replace.C__KEYTYPE__ = "type"
replace.C__TYPEHEADER__ = "header_include"
replace.C__PREFIX__ = "prefix"
replace.C__PREFIXUP__ = "prefix"
[[create.vec]]
sources_output = "src/vec/"
headers_output = "include/me/vec/"
replace.C__TYPENAME__ = "t_u8"
replace.C__TYPEHEADER__ = ''
replace.C__PREFIX__ = "u8"
replace.C__PREFIXUP__ = "U8"
[[create.vec]]
sources_output = "src/vec/"
headers_output = "include/me/vec/"
replace.C__TYPENAME__ = "t_buffer_str"
replace.C__TYPEHEADER__ = '#include "me/buffered_str/buf_str.h"'
replace.C__PREFIX__ = "buf_str"
replace.C__PREFIXUP__ = "BUF_STR"
[[create.vec]]
sources_output = "src/vec/"
headers_output = "include/me/vec/"
replace.C__TYPENAME__ = "t_str"
replace.C__TYPEHEADER__ = ''
replace.C__PREFIX__ = "str"
replace.C__PREFIXUP__ = "STR"
[[create.vec]]
sources_output = "src/vec/"
headers_output = "include/me/vec/"
replace.C__TYPENAME__ = "t_process"
replace.C__TYPEHEADER__ = '#include "me/os/process.h"'
replace.C__PREFIX__ = "process"
replace.C__PREFIXUP__ = "PROCESS"

View file

@ -0,0 +1,51 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_buf_str.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/04 18:46:53 by maiboyer #+# #+# */
/* Updated: 2023/12/09 17:53:00 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef VEC_BUF_STR_H
# define VEC_BUF_STR_H
# include "me/buffered_str/buf_str.h"
# include "me/types.h"
typedef void (*t_free_buf_str_item)(t_buffer_str);
typedef struct s_vec_buf_str
{
t_free_buf_str_item free_func;
t_usize len;
t_usize capacity;
t_buffer_str *buffer;
} t_vec_buf_str;
t_vec_buf_str vec_buf_str_new(t_usize capacity,
t_free_buf_str_item free_function);
t_error vec_buf_str_push(t_vec_buf_str *vec,
t_buffer_str element);
t_error vec_buf_str_pop(t_vec_buf_str *vec,
t_buffer_str *value);
void vec_buf_str_free(t_vec_buf_str vec);
t_error vec_buf_str_reserve(t_vec_buf_str *vec,
t_usize wanted_capacity);
t_error vec_buf_str_find(t_vec_buf_str *vec,
bool (*fn)(const t_buffer_str *), t_usize *index);
t_error vec_buf_str_find_starting(t_vec_buf_str *vec,
bool (*fn)(const t_buffer_str *),
t_usize starting_index, t_usize *index);
t_error vec_buf_str_all(t_vec_buf_str *vec,
bool (*fn)(const t_buffer_str *), bool *result);
t_error vec_buf_str_any(t_vec_buf_str *vec,
bool (*fn)(const t_buffer_str *), bool *result);
void vec_buf_str_iter(t_vec_buf_str *vec,
void (*fn)(t_usize index, t_buffer_str *value,
void *state), void *state);
#endif

View file

@ -0,0 +1,49 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_process.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/04 18:46:53 by maiboyer #+# #+# */
/* Updated: 2023/12/09 17:53:00 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef VEC_PROCESS_H
# define VEC_PROCESS_H
# include "me/os/process.h"
# include "me/types.h"
typedef void (*t_free_process_item)(t_process);
typedef struct s_vec_process
{
t_free_process_item free_func;
t_usize len;
t_usize capacity;
t_process *buffer;
} t_vec_process;
t_vec_process vec_process_new(t_usize capacity,
t_free_process_item free_function);
t_error vec_process_push(t_vec_process *vec, t_process element);
t_error vec_process_pop(t_vec_process *vec, t_process *value);
void vec_process_free(t_vec_process vec);
t_error vec_process_reserve(t_vec_process *vec,
t_usize wanted_capacity);
t_error vec_process_find(t_vec_process *vec,
bool (*fn)(const t_process *), t_usize *index);
t_error vec_process_find_starting(t_vec_process *vec,
bool (*fn)(const t_process *),
t_usize starting_index, t_usize *index);
t_error vec_process_all(t_vec_process *vec,
bool (*fn)(const t_process *), bool *result);
t_error vec_process_any(t_vec_process *vec,
bool (*fn)(const t_process *), bool *result);
void vec_process_iter(t_vec_process *vec,
void (*fn)(t_usize index, t_process *value,
void *state), void *state);
#endif

View file

@ -0,0 +1,46 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_str.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/04 18:46:53 by maiboyer #+# #+# */
/* Updated: 2023/12/09 17:53:00 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef VEC_STR_H
# define VEC_STR_H
# include "me/types.h"
typedef void (*t_free_str_item)(t_str);
typedef struct s_vec_str
{
t_free_str_item free_func;
t_usize len;
t_usize capacity;
t_str *buffer;
} t_vec_str;
t_vec_str vec_str_new(t_usize capacity,
t_free_str_item free_function);
t_error vec_str_push(t_vec_str *vec, t_str element);
t_error vec_str_pop(t_vec_str *vec, t_str *value);
void vec_str_free(t_vec_str vec);
t_error vec_str_reserve(t_vec_str *vec, t_usize wanted_capacity);
t_error vec_str_find(t_vec_str *vec, bool (*fn)(const t_str *),
t_usize *index);
t_error vec_str_find_starting(t_vec_str *vec,
bool (*fn)(const t_str *), t_usize starting_index,
t_usize *index);
t_error vec_str_all(t_vec_str *vec, bool (*fn)(const t_str *),
bool *result);
t_error vec_str_any(t_vec_str *vec, bool (*fn)(const t_str *),
bool *result);
void vec_str_iter(t_vec_str *vec, void (*fn)(t_usize index,
t_str *value, void *state), void *state);
#endif

View file

@ -0,0 +1,45 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_u8.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/04 18:46:53 by maiboyer #+# #+# */
/* Updated: 2023/12/09 17:53:00 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef VEC_U8_H
# define VEC_U8_H
# include "me/types.h"
typedef void (*t_free_u8_item)(t_u8);
typedef struct s_vec_u8
{
t_free_u8_item free_func;
t_usize len;
t_usize capacity;
t_u8 *buffer;
} t_vec_u8;
t_vec_u8 vec_u8_new(t_usize capacity, t_free_u8_item free_function);
t_error vec_u8_push(t_vec_u8 *vec, t_u8 element);
t_error vec_u8_pop(t_vec_u8 *vec, t_u8 *value);
void vec_u8_free(t_vec_u8 vec);
t_error vec_u8_reserve(t_vec_u8 *vec, t_usize wanted_capacity);
t_error vec_u8_find(t_vec_u8 *vec, bool (*fn)(const t_u8 *),
t_usize *index);
t_error vec_u8_find_starting(t_vec_u8 *vec,
bool (*fn)(const t_u8 *), t_usize starting_index,
t_usize *index);
t_error vec_u8_all(t_vec_u8 *vec, bool (*fn)(const t_u8 *),
bool *result);
t_error vec_u8_any(t_vec_u8 *vec, bool (*fn)(const t_u8 *),
bool *result);
void vec_u8_iter(t_vec_u8 *vec, void (*fn)(t_usize index,
t_u8 *value, void *state), void *state);
#endif

View file

@ -0,0 +1,115 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_buf_str.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/05 18:46:28 by maiboyer #+# #+# */
/* Updated: 2023/12/09 17:54:11 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/mem/mem_alloc_array.h"
#include "me/mem/mem_copy.h"
#include "me/mem/mem_set_zero.h"
#include "me/types.h"
#include "me/vec/vec_buf_str.h"
#include <stdlib.h>
t_vec_buf_str vec_buf_str_new(t_usize capacity,
t_free_buf_str_item free_function)
{
t_vec_buf_str out;
out = (t_vec_buf_str){0};
out.free_func = free_function;
out.buffer = mem_alloc_array(capacity, sizeof(t_buffer_str));
if (out.buffer)
out.capacity = capacity;
return (out);
}
/// Return true in case of an error
t_error vec_buf_str_push(t_vec_buf_str *vec, t_buffer_str element)
{
t_buffer_str *temp_buffer;
size_t new_capacity;
if (vec == NULL)
return (ERROR);
if (vec->len + 1 > vec->capacity)
{
new_capacity = (vec->capacity * 3) / 2 + 1;
while (vec->len + 1 > new_capacity)
new_capacity = (new_capacity * 3) / 2 + 1;
temp_buffer = mem_alloc_array(new_capacity, sizeof(t_buffer_str));
if (temp_buffer == NULL)
return (ERROR);
mem_copy(temp_buffer, vec->buffer, vec->len * sizeof(t_buffer_str));
free(vec->buffer);
vec->buffer = temp_buffer;
vec->capacity = new_capacity;
}
vec->buffer[vec->len] = element;
vec->len += 1;
return (NO_ERROR);
}
/// Return true in case of an error
t_error vec_buf_str_reserve(t_vec_buf_str *vec, t_usize wanted_capacity)
{
t_buffer_str *temp_buffer;
size_t new_capacity;
if (vec == NULL)
return (ERROR);
if (wanted_capacity > vec->capacity)
{
new_capacity = (vec->capacity * 3) / 2 + 1;
while (wanted_capacity > new_capacity)
new_capacity = (new_capacity * 3) / 2 + 1;
temp_buffer = mem_alloc_array(new_capacity, sizeof(t_buffer_str));
if (temp_buffer == NULL)
return (ERROR);
mem_copy(temp_buffer, vec->buffer, vec->len * sizeof(t_buffer_str));
free(vec->buffer);
vec->buffer = temp_buffer;
vec->capacity = new_capacity;
}
return (NO_ERROR);
}
/// Return true if the vector is empty
/// This function is safe to call with value being NULL
t_error vec_buf_str_pop(t_vec_buf_str *vec, t_buffer_str *value)
{
t_buffer_str temp_value;
t_buffer_str *ptr;
if (vec == NULL)
return (ERROR);
ptr = value;
if (vec->len == 0)
return (ERROR);
if (value == NULL)
ptr = &temp_value;
vec->len--;
*ptr = vec->buffer[vec->len];
mem_set_zero(&vec->buffer[vec->len], sizeof(t_buffer_str));
return (NO_ERROR);
}
/// This function is safe to call with `free_elem` being NULL
void vec_buf_str_free(t_vec_buf_str vec)
{
if (vec.free_func)
{
while (vec.len)
{
vec.free_func(vec.buffer[vec.len - 1]);
vec.len--;
}
}
free(vec.buffer);
}

View file

@ -0,0 +1,110 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_buf_str.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/30 17:59:28 by maiboyer #+# #+# */
/* Updated: 2023/12/30 17:59:28 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/mem/mem_alloc_array.h"
#include "me/mem/mem_copy.h"
#include "me/mem/mem_set_zero.h"
#include "me/types.h"
#include "me/vec/vec_buf_str.h"
#include <stdlib.h>
t_error vec_buf_str_find(t_vec_buf_str *vec, bool (*fn)(const t_buffer_str *),
t_usize *index)
{
t_usize idx;
if (vec == NULL || fn == NULL || index == NULL)
return (ERROR);
idx = 0;
while (idx < vec->len)
{
if (fn(&vec->buffer[idx]))
{
*index = idx;
return (NO_ERROR);
}
idx++;
}
return (ERROR);
}
t_error vec_buf_str_find_starting(t_vec_buf_str *vec,
bool (*fn)(const t_buffer_str *), t_usize starting_index,
t_usize *index)
{
t_usize idx;
if (vec == NULL || fn == NULL || index == NULL)
return (ERROR);
idx = starting_index;
while (idx < vec->len)
{
if (fn(&vec->buffer[idx]))
{
*index = idx;
return (NO_ERROR);
}
idx++;
}
return (ERROR);
}
t_error vec_buf_str_all(t_vec_buf_str *vec, bool (*fn)(const t_buffer_str *),
bool *result)
{
t_usize idx;
if (vec == NULL || fn == NULL || result == NULL)
return (ERROR);
idx = 0;
*result = true;
while (*result && idx < vec->len)
{
if (!fn(&vec->buffer[idx]))
*result = false;
idx++;
}
return (ERROR);
}
t_error vec_buf_str_any(t_vec_buf_str *vec, bool (*fn)(const t_buffer_str *),
bool *result)
{
t_usize idx;
if (vec == NULL || fn == NULL || result == NULL)
return (ERROR);
idx = 0;
*result = false;
while (*result && idx < vec->len)
{
if (fn(&vec->buffer[idx]))
*result = true;
idx++;
}
return (ERROR);
}
void vec_buf_str_iter(t_vec_buf_str *vec, void (*fn)(t_usize index,
t_buffer_str *value, void *state), void *state)
{
t_usize idx;
if (vec == NULL || fn == NULL)
return ;
idx = 0;
while (idx < vec->len)
{
fn(idx, &vec->buffer[idx], state);
idx++;
}
}

View file

@ -0,0 +1,115 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_process.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/05 18:46:28 by maiboyer #+# #+# */
/* Updated: 2023/12/09 17:54:11 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/mem/mem_alloc_array.h"
#include "me/mem/mem_copy.h"
#include "me/mem/mem_set_zero.h"
#include "me/types.h"
#include "me/vec/vec_process.h"
#include <stdlib.h>
t_vec_process vec_process_new(t_usize capacity,
t_free_process_item free_function)
{
t_vec_process out;
out = (t_vec_process){0};
out.free_func = free_function;
out.buffer = mem_alloc_array(capacity, sizeof(t_process));
if (out.buffer)
out.capacity = capacity;
return (out);
}
/// Return true in case of an error
t_error vec_process_push(t_vec_process *vec, t_process element)
{
t_process *temp_buffer;
size_t new_capacity;
if (vec == NULL)
return (ERROR);
if (vec->len + 1 > vec->capacity)
{
new_capacity = (vec->capacity * 3) / 2 + 1;
while (vec->len + 1 > new_capacity)
new_capacity = (new_capacity * 3) / 2 + 1;
temp_buffer = mem_alloc_array(new_capacity, sizeof(t_process));
if (temp_buffer == NULL)
return (ERROR);
mem_copy(temp_buffer, vec->buffer, vec->len * sizeof(t_process));
free(vec->buffer);
vec->buffer = temp_buffer;
vec->capacity = new_capacity;
}
vec->buffer[vec->len] = element;
vec->len += 1;
return (NO_ERROR);
}
/// Return true in case of an error
t_error vec_process_reserve(t_vec_process *vec, t_usize wanted_capacity)
{
t_process *temp_buffer;
size_t new_capacity;
if (vec == NULL)
return (ERROR);
if (wanted_capacity > vec->capacity)
{
new_capacity = (vec->capacity * 3) / 2 + 1;
while (wanted_capacity > new_capacity)
new_capacity = (new_capacity * 3) / 2 + 1;
temp_buffer = mem_alloc_array(new_capacity, sizeof(t_process));
if (temp_buffer == NULL)
return (ERROR);
mem_copy(temp_buffer, vec->buffer, vec->len * sizeof(t_process));
free(vec->buffer);
vec->buffer = temp_buffer;
vec->capacity = new_capacity;
}
return (NO_ERROR);
}
/// Return true if the vector is empty
/// This function is safe to call with value being NULL
t_error vec_process_pop(t_vec_process *vec, t_process *value)
{
t_process temp_value;
t_process *ptr;
if (vec == NULL)
return (ERROR);
ptr = value;
if (vec->len == 0)
return (ERROR);
if (value == NULL)
ptr = &temp_value;
vec->len--;
*ptr = vec->buffer[vec->len];
mem_set_zero(&vec->buffer[vec->len], sizeof(t_process));
return (NO_ERROR);
}
/// This function is safe to call with `free_elem` being NULL
void vec_process_free(t_vec_process vec)
{
if (vec.free_func)
{
while (vec.len)
{
vec.free_func(vec.buffer[vec.len - 1]);
vec.len--;
}
}
free(vec.buffer);
}

View file

@ -0,0 +1,109 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_process.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/30 17:59:28 by maiboyer #+# #+# */
/* Updated: 2023/12/30 17:59:28 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/mem/mem_alloc_array.h"
#include "me/mem/mem_copy.h"
#include "me/mem/mem_set_zero.h"
#include "me/types.h"
#include "me/vec/vec_process.h"
#include <stdlib.h>
t_error vec_process_find(t_vec_process *vec, bool (*fn)(const t_process *),
t_usize *index)
{
t_usize idx;
if (vec == NULL || fn == NULL || index == NULL)
return (ERROR);
idx = 0;
while (idx < vec->len)
{
if (fn(&vec->buffer[idx]))
{
*index = idx;
return (NO_ERROR);
}
idx++;
}
return (ERROR);
}
t_error vec_process_find_starting(t_vec_process *vec,
bool (*fn)(const t_process *), t_usize starting_index, t_usize *index)
{
t_usize idx;
if (vec == NULL || fn == NULL || index == NULL)
return (ERROR);
idx = starting_index;
while (idx < vec->len)
{
if (fn(&vec->buffer[idx]))
{
*index = idx;
return (NO_ERROR);
}
idx++;
}
return (ERROR);
}
t_error vec_process_all(t_vec_process *vec, bool (*fn)(const t_process *),
bool *result)
{
t_usize idx;
if (vec == NULL || fn == NULL || result == NULL)
return (ERROR);
idx = 0;
*result = true;
while (*result && idx < vec->len)
{
if (!fn(&vec->buffer[idx]))
*result = false;
idx++;
}
return (ERROR);
}
t_error vec_process_any(t_vec_process *vec, bool (*fn)(const t_process *),
bool *result)
{
t_usize idx;
if (vec == NULL || fn == NULL || result == NULL)
return (ERROR);
idx = 0;
*result = false;
while (*result && idx < vec->len)
{
if (fn(&vec->buffer[idx]))
*result = true;
idx++;
}
return (ERROR);
}
void vec_process_iter(t_vec_process *vec, void (*fn)(t_usize index,
t_process *value, void *state), void *state)
{
t_usize idx;
if (vec == NULL || fn == NULL)
return ;
idx = 0;
while (idx < vec->len)
{
fn(idx, &vec->buffer[idx], state);
idx++;
}
}

View file

@ -0,0 +1,114 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_str.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/05 18:46:28 by maiboyer #+# #+# */
/* Updated: 2023/12/09 17:54:11 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/mem/mem_alloc_array.h"
#include "me/mem/mem_copy.h"
#include "me/mem/mem_set_zero.h"
#include "me/types.h"
#include "me/vec/vec_str.h"
#include <stdlib.h>
t_vec_str vec_str_new(t_usize capacity, t_free_str_item free_function)
{
t_vec_str out;
out = (t_vec_str){0};
out.free_func = free_function;
out.buffer = mem_alloc_array(capacity, sizeof(t_str));
if (out.buffer)
out.capacity = capacity;
return (out);
}
/// Return true in case of an error
t_error vec_str_push(t_vec_str *vec, t_str element)
{
t_str *temp_buffer;
size_t new_capacity;
if (vec == NULL)
return (ERROR);
if (vec->len + 1 > vec->capacity)
{
new_capacity = (vec->capacity * 3) / 2 + 1;
while (vec->len + 1 > new_capacity)
new_capacity = (new_capacity * 3) / 2 + 1;
temp_buffer = mem_alloc_array(new_capacity, sizeof(t_str));
if (temp_buffer == NULL)
return (ERROR);
mem_copy(temp_buffer, vec->buffer, vec->len * sizeof(t_str));
free(vec->buffer);
vec->buffer = temp_buffer;
vec->capacity = new_capacity;
}
vec->buffer[vec->len] = element;
vec->len += 1;
return (NO_ERROR);
}
/// Return true in case of an error
t_error vec_str_reserve(t_vec_str *vec, t_usize wanted_capacity)
{
t_str *temp_buffer;
size_t new_capacity;
if (vec == NULL)
return (ERROR);
if (wanted_capacity > vec->capacity)
{
new_capacity = (vec->capacity * 3) / 2 + 1;
while (wanted_capacity > new_capacity)
new_capacity = (new_capacity * 3) / 2 + 1;
temp_buffer = mem_alloc_array(new_capacity, sizeof(t_str));
if (temp_buffer == NULL)
return (ERROR);
mem_copy(temp_buffer, vec->buffer, vec->len * sizeof(t_str));
free(vec->buffer);
vec->buffer = temp_buffer;
vec->capacity = new_capacity;
}
return (NO_ERROR);
}
/// Return true if the vector is empty
/// This function is safe to call with value being NULL
t_error vec_str_pop(t_vec_str *vec, t_str *value)
{
t_str temp_value;
t_str *ptr;
if (vec == NULL)
return (ERROR);
ptr = value;
if (vec->len == 0)
return (ERROR);
if (value == NULL)
ptr = &temp_value;
vec->len--;
*ptr = vec->buffer[vec->len];
mem_set_zero(&vec->buffer[vec->len], sizeof(t_str));
return (NO_ERROR);
}
/// This function is safe to call with `free_elem` being NULL
void vec_str_free(t_vec_str vec)
{
if (vec.free_func)
{
while (vec.len)
{
vec.free_func(vec.buffer[vec.len - 1]);
vec.len--;
}
}
free(vec.buffer);
}

View file

@ -0,0 +1,106 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_str.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/30 17:59:28 by maiboyer #+# #+# */
/* Updated: 2023/12/30 17:59:28 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/mem/mem_alloc_array.h"
#include "me/mem/mem_copy.h"
#include "me/mem/mem_set_zero.h"
#include "me/types.h"
#include "me/vec/vec_str.h"
#include <stdlib.h>
t_error vec_str_find(t_vec_str *vec, bool (*fn)(const t_str *), t_usize *index)
{
t_usize idx;
if (vec == NULL || fn == NULL || index == NULL)
return (ERROR);
idx = 0;
while (idx < vec->len)
{
if (fn(&vec->buffer[idx]))
{
*index = idx;
return (NO_ERROR);
}
idx++;
}
return (ERROR);
}
t_error vec_str_find_starting(t_vec_str *vec, bool (*fn)(const t_str *),
t_usize starting_index, t_usize *index)
{
t_usize idx;
if (vec == NULL || fn == NULL || index == NULL)
return (ERROR);
idx = starting_index;
while (idx < vec->len)
{
if (fn(&vec->buffer[idx]))
{
*index = idx;
return (NO_ERROR);
}
idx++;
}
return (ERROR);
}
t_error vec_str_all(t_vec_str *vec, bool (*fn)(const t_str *), bool *result)
{
t_usize idx;
if (vec == NULL || fn == NULL || result == NULL)
return (ERROR);
idx = 0;
*result = true;
while (*result && idx < vec->len)
{
if (!fn(&vec->buffer[idx]))
*result = false;
idx++;
}
return (ERROR);
}
t_error vec_str_any(t_vec_str *vec, bool (*fn)(const t_str *), bool *result)
{
t_usize idx;
if (vec == NULL || fn == NULL || result == NULL)
return (ERROR);
idx = 0;
*result = false;
while (*result && idx < vec->len)
{
if (fn(&vec->buffer[idx]))
*result = true;
idx++;
}
return (ERROR);
}
void vec_str_iter(t_vec_str *vec, void (*fn)(t_usize index, t_str *value,
void *state), void *state)
{
t_usize idx;
if (vec == NULL || fn == NULL)
return ;
idx = 0;
while (idx < vec->len)
{
fn(idx, &vec->buffer[idx], state);
idx++;
}
}

View file

@ -0,0 +1,114 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_u8.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/05 18:46:28 by maiboyer #+# #+# */
/* Updated: 2023/12/09 17:54:11 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/mem/mem_alloc_array.h"
#include "me/mem/mem_copy.h"
#include "me/mem/mem_set_zero.h"
#include "me/types.h"
#include "me/vec/vec_u8.h"
#include <stdlib.h>
t_vec_u8 vec_u8_new(t_usize capacity, t_free_u8_item free_function)
{
t_vec_u8 out;
out = (t_vec_u8){0};
out.free_func = free_function;
out.buffer = mem_alloc_array(capacity, sizeof(t_u8));
if (out.buffer)
out.capacity = capacity;
return (out);
}
/// Return true in case of an error
t_error vec_u8_push(t_vec_u8 *vec, t_u8 element)
{
t_u8 *temp_buffer;
size_t new_capacity;
if (vec == NULL)
return (ERROR);
if (vec->len + 1 > vec->capacity)
{
new_capacity = (vec->capacity * 3) / 2 + 1;
while (vec->len + 1 > new_capacity)
new_capacity = (new_capacity * 3) / 2 + 1;
temp_buffer = mem_alloc_array(new_capacity, sizeof(t_u8));
if (temp_buffer == NULL)
return (ERROR);
mem_copy(temp_buffer, vec->buffer, vec->len * sizeof(t_u8));
free(vec->buffer);
vec->buffer = temp_buffer;
vec->capacity = new_capacity;
}
vec->buffer[vec->len] = element;
vec->len += 1;
return (NO_ERROR);
}
/// Return true in case of an error
t_error vec_u8_reserve(t_vec_u8 *vec, t_usize wanted_capacity)
{
t_u8 *temp_buffer;
size_t new_capacity;
if (vec == NULL)
return (ERROR);
if (wanted_capacity > vec->capacity)
{
new_capacity = (vec->capacity * 3) / 2 + 1;
while (wanted_capacity > new_capacity)
new_capacity = (new_capacity * 3) / 2 + 1;
temp_buffer = mem_alloc_array(new_capacity, sizeof(t_u8));
if (temp_buffer == NULL)
return (ERROR);
mem_copy(temp_buffer, vec->buffer, vec->len * sizeof(t_u8));
free(vec->buffer);
vec->buffer = temp_buffer;
vec->capacity = new_capacity;
}
return (NO_ERROR);
}
/// Return true if the vector is empty
/// This function is safe to call with value being NULL
t_error vec_u8_pop(t_vec_u8 *vec, t_u8 *value)
{
t_u8 temp_value;
t_u8 *ptr;
if (vec == NULL)
return (ERROR);
ptr = value;
if (vec->len == 0)
return (ERROR);
if (value == NULL)
ptr = &temp_value;
vec->len--;
*ptr = vec->buffer[vec->len];
mem_set_zero(&vec->buffer[vec->len], sizeof(t_u8));
return (NO_ERROR);
}
/// This function is safe to call with `free_elem` being NULL
void vec_u8_free(t_vec_u8 vec)
{
if (vec.free_func)
{
while (vec.len)
{
vec.free_func(vec.buffer[vec.len - 1]);
vec.len--;
}
}
free(vec.buffer);
}

View file

@ -0,0 +1,106 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vec_u8.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/30 17:59:28 by maiboyer #+# #+# */
/* Updated: 2023/12/30 17:59:28 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/mem/mem_alloc_array.h"
#include "me/mem/mem_copy.h"
#include "me/mem/mem_set_zero.h"
#include "me/types.h"
#include "me/vec/vec_u8.h"
#include <stdlib.h>
t_error vec_u8_find(t_vec_u8 *vec, bool (*fn)(const t_u8 *), t_usize *index)
{
t_usize idx;
if (vec == NULL || fn == NULL || index == NULL)
return (ERROR);
idx = 0;
while (idx < vec->len)
{
if (fn(&vec->buffer[idx]))
{
*index = idx;
return (NO_ERROR);
}
idx++;
}
return (ERROR);
}
t_error vec_u8_find_starting(t_vec_u8 *vec, bool (*fn)(const t_u8 *),
t_usize starting_index, t_usize *index)
{
t_usize idx;
if (vec == NULL || fn == NULL || index == NULL)
return (ERROR);
idx = starting_index;
while (idx < vec->len)
{
if (fn(&vec->buffer[idx]))
{
*index = idx;
return (NO_ERROR);
}
idx++;
}
return (ERROR);
}
t_error vec_u8_all(t_vec_u8 *vec, bool (*fn)(const t_u8 *), bool *result)
{
t_usize idx;
if (vec == NULL || fn == NULL || result == NULL)
return (ERROR);
idx = 0;
*result = true;
while (*result && idx < vec->len)
{
if (!fn(&vec->buffer[idx]))
*result = false;
idx++;
}
return (ERROR);
}
t_error vec_u8_any(t_vec_u8 *vec, bool (*fn)(const t_u8 *), bool *result)
{
t_usize idx;
if (vec == NULL || fn == NULL || result == NULL)
return (ERROR);
idx = 0;
*result = false;
while (*result && idx < vec->len)
{
if (fn(&vec->buffer[idx]))
*result = true;
idx++;
}
return (ERROR);
}
void vec_u8_iter(t_vec_u8 *vec, void (*fn)(t_usize index, t_u8 *value,
void *state), void *state)
{
t_usize idx;
if (vec == NULL || fn == NULL)
return ;
idx = 0;
while (idx < vec->len)
{
fn(idx, &vec->buffer[idx], state);
idx++;
}
}

View file

@ -0,0 +1,9 @@
app/main
app/main2
app/main3
lib/os/pipe
lib/os/process
lib/os/process_inner
lib/os/process_inner2
lib/string/inner/split_literals_escaped
lib/string/split_literals

119
other/pipex/src/app/main.c Normal file
View file

@ -0,0 +1,119 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/03 15:35:44 by maiboyer #+# #+# */
/* Updated: 2024/01/06 18:52:49 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/main.h"
void cleanup(t_pipex_args *s, bool error)
{
if (s->here_doc)
close(s->here_doc_fd);
close(s->in);
close(s->out);
vec_str_free(s->env);
vec_process_free(s->processes);
if (error)
exit(1);
wait(NULL);
exit(0);
}
void process_cleanup(t_process elem)
{
close(elem.stdin.vals.wo.fd);
close(elem.stdout.vals.ro.fd);
close(elem.stderr.vals.ro.fd);
}
void do_here_doc_thing(t_pipex_args *s)
{
t_buffer_str line;
t_isize f;
t_usize len;
bool error;
len = str_len(s->here_doc_limiter);
error = false;
while (!error)
{
line = get_next_line(0, &error);
if (error)
(me_eprintf("Error:\nError when reading stdin!\n"), cleanup(s,
true));
f = str_n_compare(line.buf, s->here_doc_limiter, len);
if (f == 0 && line.len >= len + 1 && (line.buf[len] == '\0'
|| line.buf[len] == '\n'))
{
str_free(line);
break ;
}
write(s->here_doc_fd, line.buf, line.len);
str_free(line);
}
cleanup(s, false);
}
int main2(t_pipex_args *s)
{
t_usize p_idx;
if (s->argc < 2 || s->argc < s->min || s->argc > s->max)
(me_eprintf("Error:\nWrong number of arguments!\n"), s->here_doc
&& close(s->here_doc_fd), close(s->in), vec_str_free(s->env),
exit(1));
s->processes = vec_process_new(s->argc, process_cleanup);
p_idx = s->argc - 2 - (t_usize)(s->here_doc);
if (spawn_helper(s, p_idx--, piped(), fd(s->out)))
(me_eprintf("Error:\nFailed to spawn process!\n"), cleanup(s, true));
while (p_idx > 1 + (t_usize)s->here_doc)
{
if (spawn_helper(s, p_idx--, piped(),
fd(s->processes.buffer[s->processes.len - 1].stdin.vals.wo.fd)))
(me_eprintf("Error:\nFailed to spawn process!\n"), cleanup(s,
true));
}
if (spawn_helper(s, p_idx, fd(s->in),
fd(s->processes.buffer[s->processes.len - 1].stdin.vals.wo.fd)))
(me_eprintf("Error:\nFailed to spawn process!\n"), cleanup(s, true));
if (s->here_doc)
do_here_doc_thing(s);
cleanup(s, false);
return (0);
}
int main(int argc, t_str argv[], t_str env[])
{
t_usize env_idx;
t_pipex_args s;
s.min = 4;
s.max = 4;
s.argv = argv + 1;
s.argc = argc - 1;
s.here_doc = false;
if (s.argc < 3)
(me_eprintf("Error:\nNot enough arguments!"), exit(1));
s.env = vec_str_new(128, (t_free_str_item)free);
env_idx = 0;
while (env[env_idx])
vec_str_push(&s.env, str_clone(env[env_idx++]));
if (BONUS)
s.max = ~0;
if (BONUS && str_n_compare(s.argv[0], "here_doc", 9) == 0)
set_here_doc(&s);
else
open_read_file(&s);
if ((s.here_doc && me_open_create(s.argv[s.argc - 1], &s.out))
|| (!s.here_doc && me_open_truncate(s.argv[s.argc - 1], &s.out)))
(me_eprintf("Error:\n Failed to open output file!\n"), s.here_doc
&& close(s.here_doc_fd), close(s.in), vec_str_free(s.env), exit(1));
return (s.here_doc && s.argv++, main2(&s));
}

View file

@ -0,0 +1,47 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/06 18:46:52 by maiboyer #+# #+# */
/* Updated: 2024/01/06 18:55:12 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/main.h"
void set_here_doc(t_pipex_args *s)
{
t_pipe pipe;
if (create_pipe(&pipe))
(vec_str_free(s->env), exit(1));
s->min = 5;
s->here_doc = true;
s->here_doc_limiter = s->argv[1];
s->here_doc_fd = pipe.write;
s->in = pipe.read;
}
void open_read_file(t_pipex_args *s)
{
if (me_open(s->argv[0], true, false, &s->in))
(me_eprintf("Error:\nInput file not found!\n"), vec_str_free(s->env),
exit(1));
}
void clone_vec_str_iter_fn(t_usize idx, t_str *s, void *out)
{
vec_str_push(out, str_clone(*s));
}
t_vec_str clone_vec_str(t_vec_str *v)
{
t_vec_str val;
val = vec_str_new(v->len + 2, (t_free_str_item)free);
vec_str_iter(v, &clone_vec_str_iter_fn, &val);
return (val);
}

View file

@ -0,0 +1,48 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main3.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/06 18:48:21 by maiboyer #+# #+# */
/* Updated: 2024/01/06 18:55:33 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/main.h"
void vec_process_free_ptr(void *s)
{
close(((t_pipex_args *)s)->in);
close(((t_pipex_args *)s)->out);
if (((t_pipex_args *)s)->here_doc)
close(((t_pipex_args *)s)->here_doc_fd);
vec_process_free(((t_pipex_args *)s)->processes);
}
t_error spawn_helper(t_pipex_args *s, t_usize idx, t_redirection in,
t_redirection out)
{
t_process o;
t_vec_str args;
t_spawn_info info;
if (split_literals(s->argv[idx], &args))
return (ERROR);
info = (t_spawn_info){
.stdin = in,
.stdout = out,
.stderr = inherited(),
.binary_path = str_clone(args.buffer[0]),
.arguments = args,
.environement = clone_vec_str(&s->env),
.forked_free = vec_process_free_ptr,
.forked_free_args = s,
};
if (spawn_process(
info,
&o))
return (ERROR);
return (vec_process_push(&s->processes, o));
}

View file

@ -0,0 +1,24 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pipe.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 17:59:48 by maiboyer #+# #+# */
/* Updated: 2024/01/04 18:01:42 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/os/pipe.h"
t_error create_pipe(t_pipe *out)
{
t_file fds[2];
if (pipe(fds))
return (ERROR);
out->read = fds[0];
out->write = fds[1];
return (NO_ERROR);
}

View file

@ -0,0 +1,141 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* process.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/03 16:22:41 by maiboyer #+# #+# */
/* Updated: 2024/01/06 17:50:47 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/buffered_str/buf_str.h"
#include "me/os/pipe.h"
#include "me/os/process.h"
#include "me/string/str_find_chr.h"
#include "me/string/str_n_compare.h"
#include "me/string/str_split.h"
#include "me/types.h"
#include "me/vec/vec_str.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
bool find_path(const t_str *s);
bool find_null(const t_str *s);
bool str_start_with(t_const_str s, t_const_str prefix);
t_error handle_redirections(t_spawn_info *info, t_process *process);
t_error spawn_process_exec(t_spawn_info info, t_process *process)
{
bool res;
if (info.forked_free)
info.forked_free(info.forked_free_args);
dup2(info.stdin.vals.fd.value, 0);
dup2(info.stdout.vals.fd.value, 1);
dup2(info.stderr.vals.fd.value, 2);
close(process->stdin.vals.ro.fd);
close(process->stdout.vals.ro.fd);
close(process->stderr.vals.ro.fd);
close(info.stdin.vals.fd.value);
close(info.stdout.vals.fd.value);
close(info.stderr.vals.fd.value);
if (!vec_str_any(&info.arguments, find_null, &res) && res)
vec_str_push(&info.arguments, NULL);
res = false;
if (!vec_str_any(&info.environement, find_null, &res) && res)
vec_str_push(&info.environement, NULL);
execve(info.binary_path, info.arguments.buffer, info.environement.buffer);
return (NO_ERROR);
}
t_error in_path(t_spawn_info *info, t_process *process, t_const_str path,
t_buffer_str *s)
{
t_str *splitted_path;
t_usize sp_index;
splitted_path = str_split(path + 5, ':');
if (splitted_path == NULL)
return (str_free(*s), ERROR);
sp_index = 0;
while (splitted_path[sp_index])
{
((void)(process), str_clear(s));
push_str_buffer(s, splitted_path[sp_index]);
push_str_buffer(s, "/");
push_str_buffer(s, info->binary_path);
sp_index++;
if (access(s->buf, X_OK | R_OK) == 0)
break ;
}
sp_index = 0;
while (splitted_path[sp_index])
free(splitted_path[sp_index++]);
free(splitted_path);
return (NO_ERROR);
}
t_error find_binary(t_spawn_info *info, t_process *process)
{
t_usize p_idx;
t_str *splitted_path;
t_buffer_str s;
(void)(process);
splitted_path = NULL;
s = alloc_new_buffer(256);
if (str_start_with(info->binary_path, "/")
|| str_find_chr(info->binary_path, '/') != NULL)
push_str_buffer(&s, info->binary_path);
else
{
if (vec_str_find(&info->environement, find_path, &p_idx))
return (str_free(s), ERROR);
if (in_path(info, process, info->environement.buffer[p_idx], &s))
return (ERROR);
}
if (access(s.buf, X_OK | R_OK) == 0)
{
free(info->binary_path);
info->binary_path = s.buf;
return (NO_ERROR);
}
return (str_free(s), ERROR);
}
static void cleanup(t_spawn_info info, t_process *process, bool cleanup_process)
{
if (cleanup_process && process->stdin.tag != INVALID)
close(process->stdin.vals.ro.fd);
if (cleanup_process && process->stdout.tag != INVALID)
close(process->stdout.vals.ro.fd);
if (cleanup_process && process->stderr.tag != INVALID)
close(process->stderr.vals.ro.fd);
close(info.stdin.vals.fd.value);
close(info.stdout.vals.fd.value);
close(info.stderr.vals.fd.value);
vec_str_free(info.arguments);
vec_str_free(info.environement);
free(info.binary_path);
}
t_error spawn_process(t_spawn_info info, t_process *process)
{
if (handle_redirections(&info, process))
return (cleanup(info, process, true), ERROR);
if (find_binary(&info, process))
return (cleanup(info, process, true), ERROR);
process->pid = fork();
if (process->pid == 0)
(spawn_process_exec(info, process), exit(1));
else
{
cleanup(info, process, false);
if (process->pid == -1)
return (printf("pid\n"), ERROR);
}
return (NO_ERROR);
}

View file

@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* process_inner.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 22:25:44 by maiboyer #+# #+# */
/* Updated: 2024/01/04 22:26:10 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/types.h"
bool find_null(const t_str *s)
{
return (s == NULL);
}
bool str_start_with(t_const_str s, t_const_str prefix)
{
while (*prefix && *s)
{
if (*prefix++ != *s++)
return (false);
}
return (*prefix == '\0');
}
bool find_path(const t_str *s)
{
return (str_start_with(*s, "PATH="));
}

View file

@ -0,0 +1,92 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* process_inner2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 22:27:00 by maiboyer #+# #+# */
/* Updated: 2024/01/04 23:01:03 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/types.h"
#include "me/os/process.h"
#include "me/os/pipe.h"
void handle_redirections_second(t_spawn_info *info, t_process *process)
{
(void)(process);
if (info->stdin.tag == R_INHERITED)
{
info->stdin = fd(dup(0));
process->stdin = ro(dup(0));
}
if (info->stdout.tag == R_INHERITED)
{
info->stdout = fd(dup(1));
process->stdout = wo(dup(1));
}
if (info->stderr.tag == R_INHERITED)
{
info->stderr = fd(dup(2));
process->stderr = wo(dup(2));
}
}
void handle_redirections_fds(t_spawn_info *info, t_process *process)
{
if (info->stdin.tag == R_FD)
{
info->stdin = fd(dup(info->stdin.vals.fd.value));
process->stdin = wo(dup(info->stdin.vals.fd.value));
}
if (info->stdout.tag == R_FD)
{
info->stdout = fd(dup(info->stdout.vals.fd.value));
process->stdout = ro(dup(info->stdout.vals.fd.value));
}
if (info->stderr.tag == R_FD)
{
info->stderr = fd(dup(info->stderr.vals.fd.value));
process->stderr = ro(dup(info->stderr.vals.fd.value));
}
}
static inline void redirection_inner(t_spawn_info *info, t_process *process)
{
process->stderr.tag = INVALID;
process->stdout.tag = INVALID;
process->stdin.tag = INVALID;
handle_redirections_fds(info, process);
handle_redirections_second(info, process);
}
t_error handle_redirections(t_spawn_info *info, t_process *process)
{
t_pipe pipe_fd;
redirection_inner(info, process);
if (info->stdin.tag == R_PIPED)
{
if (create_pipe(&pipe_fd))
return (ERROR);
process->stdin = wo(pipe_fd.write);
info->stdin = fd(pipe_fd.read);
}
if (info->stdout.tag == R_PIPED)
{
if (create_pipe(&pipe_fd))
return (ERROR);
process->stdout = ro(pipe_fd.read);
info->stdout = fd(pipe_fd.write);
}
if (info->stderr.tag == R_PIPED)
{
if (create_pipe(&pipe_fd))
return (ERROR);
process->stderr = ro(pipe_fd.read);
info->stderr = fd(pipe_fd.write);
}
return (NO_ERROR);
}

View file

@ -0,0 +1,118 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* split_literals_escaped.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 14:44:48 by maiboyer #+# #+# */
/* Updated: 2024/01/05 00:06:48 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/buffered_str/buf_str.h"
#include "me/char/isspace.h"
#include "me/char/tolower.h"
#include "me/string/inner/inner_split_literals.h"
#include "me/string/split_literals.h"
#include "me/vec/vec_str.h"
#include <stdio.h>
#include <stdlib.h>
static inline char escape_oct(t_const_str s, t_usize *current_index,
bool *did_escape, t_error *error)
{
char out;
char first;
first = s[*current_index];
out = first - '0';
(*current_index)++;
first = s[(*current_index)];
if (first >= '0' && first <= '7')
{
out = out * 8 + (first - '0');
(*current_index)++;
first = s[(*current_index)];
if (first >= '0' && first <= '7')
{
out = out * 8 + (first - '0');
(*current_index)++;
first = s[(*current_index)];
}
}
return (out);
}
static inline char escape_hex(t_const_str s, t_usize *current_index,
bool *did_escape, t_error *error)
{
char out;
char first;
out = 0;
first = me_tolower(s[++(*current_index)]);
if (first >= '0' && first <= '9')
out = first - '0';
else if (first >= 'a' && first <= 'f')
out = 10 + first - 'a';
else
{
(*current_index)--;
return ('\0');
}
first = me_tolower(s[++(*current_index)]);
if (first >= '0' && first <= '9')
out = out * 16 + first - '0';
else if (first >= 'a' && first <= 'f')
out = out * 16 + 10 + first - 'a';
return (out);
}
char unescape_single(char first)
{
if (first == '\\')
return ('\\');
if (first == 'a')
return ('\a');
if (first == 'b')
return ('\b');
if (first == 't')
return ('\t');
if (first == 'n')
return ('\n');
if (first == 'v')
return ('\v');
if (first == 'f')
return ('\f');
if (first == 'r')
return ('\r');
if (first == 'e')
return ('\e');
if (first == 'E')
return ('\e');
return ('\0');
}
char unescape(t_const_str s, t_usize *current_index, bool *did_escape,
t_error *error)
{
char first;
char out;
*did_escape = false;
if (s[(*current_index)] != '\\')
return (s[(*current_index)]);
(*current_index)++;
first = s[(*current_index)];
*did_escape = true;
if (unescape_single(first))
return (unescape_single(first));
if (first >= '0' && first <= '7')
return (escape_oct(s, current_index, did_escape, error));
if (first == 'x')
return (escape_hex(s, current_index, did_escape, error));
*did_escape = false;
(*current_index)--;
return ('\\');
}

View file

@ -0,0 +1,100 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* split_literals.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 14:28:23 by maiboyer #+# #+# */
/* Updated: 2024/01/06 18:43:33 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "me/buffered_str/buf_str.h"
#include "me/char/isspace.h"
#include "me/string/inner/inner_split_literals.h"
#include "me/string/split_literals.h"
#include "me/string/str_clone.h"
#include "me/vec/vec_str.h"
#include <stdio.h>
#include <stdlib.h>
static inline void flip_and_set_false(bool *flip, bool *false_)
{
*flip = !(*flip);
*false_ = false;
}
static inline bool is_word_splitter(char c, t_str prefix)
{
(void)(prefix);
return (c == ' ' || c == '\n' || c == '\t');
}
static inline char set_thingy(t_const_str s, t_usize *idx, bool *esc,
bool *lit_sq)
{
char c;
bool error;
if (!lit_sq)
{
(*idx)++;
c = unescape(s, idx, esc, &error);
}
else
{
(*idx)++;
c = s[*idx];
}
return (c);
}
static inline void yes(t_const_str s, t_usize *idx, t_buffer_str *temp,
t_usize *len)
{
t_booleans b;
char c;
b.lit_sq = false;
b.lit_dq = false;
c = unescape(s, idx, &b.esc, &b.error);
while (c != '\0' && !b.esc && is_word_splitter(c, "\t@"))
c = unescape(s, ((*idx)++, idx), &b.esc, &b.error);
while (c != '\0')
{
if (((!b.lit_sq && !b.lit_dq && !b.esc) && is_word_splitter(c, ".")))
break ;
b.append = true;
if (c == '\'' && !b.esc && !b.lit_dq)
(flip_and_set_false(&b.lit_sq, &b.append), (*len)++);
if (c == '"' && !b.esc && !b.lit_sq)
(flip_and_set_false(&b.lit_dq, &b.append), (*len)++);
if (b.append)
(push_str_char(temp, c), (*len)++);
c = set_thingy(s, idx, &b.esc, &b.lit_sq);
}
}
t_error split_literals(t_const_str s, t_vec_str *out)
{
t_usize idx;
t_usize len;
t_buffer_str temp;
*out = vec_str_new(16, (t_free_str_item)free);
temp = alloc_new_buffer(64);
idx = 0;
while (s[idx])
{
len = 0;
yes(s, &idx, &temp, &len);
if (len == 0)
continue ;
if (vec_str_push(out, temp.buf))
return (str_free(temp), vec_str_free(*out), ERROR);
temp = alloc_new_buffer(64);
}
str_free(temp);
return (NO_ERROR);
}

225
other/pipex/subject.txt Normal file
View file

@ -0,0 +1,225 @@
Pipex
Summary:
This project will let you discover in detail a UNIX mechanism that you already know
by using it in your program.
Version: 3
Contents
I Foreword 2
II Common Instructions 3
III Mandatory part 5
III.1 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
III.2 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
IV Bonus part 7
V Submission and peer-evaluation 8
1
Chapter I
Foreword
Cristina: "Go dance salsa somewhere :)"
2
Chapter II
Common Instructions
• Your project must be written in C.
• Your project must be written in accordance with the Norm. If you have bonus
files/functions, they are included in the norm check and you will receive a 0 if there
is a norm error inside.
• Your functions should not quit unexpectedly (segmentation fault, bus error, double
free, etc) apart from undefined behaviors. If this happens, your project will be
considered non functional and will receive a 0 during the evaluation.
• All heap allocated memory space must be properly freed when necessary. No leaks
will be tolerated.
• If the subject requires it, you must submit a Makefile which will compile your
source files to the required output with the flags -Wall, -Wextra and -Werror, use
cc, and your Makefile must not relink.
• Your Makefile must at least contain the rules $(NAME), all, clean, fclean and
re.
• To turn in bonuses to your project, you must include a rule bonus to your Makefile,
which will add all the various headers, librairies or functions that are forbidden on
the main part of the project. Bonuses must be in a different file _bonus.{c/h} if
the subject does not specify anything else. Mandatory and bonus part evaluation
is done separately.
• If your project allows you to use your libft, you must copy its sources and its
associated Makefile in a libft folder with its associated Makefile. Your projects
Makefile must compile the library by using its Makefile, then compile the project.
• We encourage you to create test programs for your project even though this work
wont have to be submitted and wont be graded. It will give you a chance
to easily test your work and your peers work. You will find those tests especially
useful during your defence. Indeed, during defence, you are free to use your tests
and/or the tests of the peer you are evaluating.
• Submit your work to your assigned git repository. Only the work in the git reposi-
tory will be graded. If Deepthought is assigned to grade your work, it will be done
3
Pipex
after your peer-evaluations. If an error happens in any section of your work during
Deepthoughts grading, the evaluation will stop.
4
Chapter III
Mandatory part
Program name pipex
Turn in files Makefile, *.h, *.c
Makefile NAME, all, clean, fclean, re
Arguments file1 cmd1 cmd2 file2
External functs.
• open, close, read, write,
malloc, free, perror,
strerror, access, dup, dup2,
execve, exit, fork, pipe,
unlink, wait, waitpid
• ft_printf and any equivalent
YOU coded
Libft authorized Yes
Description This project is about handling pipes.
Your program will be executed as follows:
./pipex file1 cmd1 cmd2 file2
It must take 4 arguments:
• file1 and file2 are file names.
• cmd1 and cmd2 are shell commands with their parameters.
It must behave exactly the same as the shell command below:
$> < file1 cmd1 | cmd2 > file2
5
Pipex
III.1 Examples
$> ./pipex infile "ls -l" "wc -l" outfile
Should behave like: < infile ls -l | wc -l > outfile
$> ./pipex infile "grep a1" "wc -w" outfile
Should behave like: < infile grep a1 | wc -w > outfile
III.2 Requirements
Your project must comply with the following rules:
• You have to turn in a Makefile which will compile your source files. It must not
relink.
• You have to handle errors thoroughly. In no way your program should quit unex-
pectedly (segmentation fault, bus error, double free, and so forth).
• Your program mustnt have memory leaks.
• If you have any doubt, handle the errors like the shell command:
< file1 cmd1 | cmd2 > file2
6
Chapter IV
Bonus part
You will get extra points if you:
• Handle multiple pipes.
This:
$> ./pipex file1 cmd1 cmd2 cmd3 ... cmdn file2
Should behave like:
< file1 cmd1 | cmd2 | cmd3 ... | cmdn > file2
• Support « and » when the first parameter is "here_doc".
This:
$> ./pipex here_doc LIMITER cmd cmd1 file
Should behave like:
cmd << LIMITER | cmd1 >> file
The bonus part will only be assessed if the mandatory part is
PERFECT. Perfect means the mandatory part has been integrally done
and works without malfunctioning. If you have not passed ALL the
mandatory requirements, your bonus part will not be evaluated at all.
7
Chapter V
Submission and peer-evaluation
Turn in your assignment in your Git repository as usual. Only the work inside your
repository will be evaluated during the defense. Dont hesitate to double check the
names of your files to ensure they are correct.
file.bfe:VACsSfsWN1cy33ROeASsmsgnY0o0sDMJev7zFHhw
QS8mvM8V5xQQpLc6cDCFXDWTiFzZ2H9skYkiJ/DpQtnM/uZ0
8