Started from buttom go to the sky
This commit is contained in:
parent
96215449bd
commit
f811e55dea
4781 changed files with 10121 additions and 1743 deletions
|
|
@ -1 +0,0 @@
|
|||
# shcat
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
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/"
|
||||
|
||||
3
other/pipex/.gitmodules
vendored
3
other/pipex/.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "mecstd"]
|
||||
path = mecstd
|
||||
url = git@github.com:Maix0/mecstd.git
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* main.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/01/06 18:51:07 by maiboyer #+# #+# */
|
||||
/* Updated: 2024/03/28 12:37:04 by rparodi ### ########.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 */
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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 */
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
[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"
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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);
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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));
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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);
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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));
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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);
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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);
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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 ('\\');
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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);
|
||||
}
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
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 project’s
|
||||
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
|
||||
won’t have to be submitted and won’t 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
|
||||
Deepthought’s 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 mustn’t 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. Don’t hesitate to double check the
|
||||
names of your files to ensure they are correct.
|
||||
|
||||
|
||||
|
||||
|
||||
file.bfe:VACsSfsWN1cy33ROeASsmsgnY0o0sDMJev7zFHhw
|
||||
QS8mvM8V5xQQpLc6cDCFXDWTiFzZ2H9skYkiJ/DpQtnM/uZ0
|
||||
|
||||
|
||||
|
||||
|
||||
8
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue