Started from buttom go to the sky

This commit is contained in:
Raphaël 2024-04-28 19:59:01 +02:00
parent 96215449bd
commit f811e55dea
4781 changed files with 10121 additions and 1743 deletions

View file

@ -1 +0,0 @@
# shcat

View file

@ -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/"

View file

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

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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++;
}
}

View file

@ -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

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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 ('\\');
}

View file

@ -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);
}

View file

@ -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 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

Some files were not shown because too many files have changed in this diff Show more