From 967be9e750221ab2ab783f95df79bb26d290a45e Mon Sep 17 00:00:00 2001 From: Martial Simon Date: Mon, 15 Sep 2025 01:07:58 +0200 Subject: add: added projects --- 42sh/src/exec/ast_exec_redirs.c | 149 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 42sh/src/exec/ast_exec_redirs.c (limited to '42sh/src/exec/ast_exec_redirs.c') diff --git a/42sh/src/exec/ast_exec_redirs.c b/42sh/src/exec/ast_exec_redirs.c new file mode 100644 index 0000000..5cd013c --- /dev/null +++ b/42sh/src/exec/ast_exec_redirs.c @@ -0,0 +1,149 @@ +#define _POSIX_C_SOURCE 200809L + +#include "exec/ast_exec_redirs.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ast/ast.h" +#include "ast/ast_accessors.h" +#include "ast/ast_redirect.h" +#include "utils/env.h" +#include "utils/libstring.h" + +inline static long _get_open_max(void) +{ + return sysconf(_SC_OPEN_MAX); +} + +static bool _file_exists(char *filename) +{ + struct stat s; + return stat(filename, &s) == 0; +} + +inline static bool _is_a_digit(char c) +{ + return c >= '0' && c <= '9'; +} + +static bool _is_a_number(struct string *s) +{ + size_t i = 0; + while (i < s->length && _is_a_digit(s->data[i])) + { + i++; + } + return i == s->length; +} + +/** + * @brief Assigns the fd described by s to out_fd if s + * describes an integer which is less than _SC_OPEN_MAX. + */ +static void _assign_if_valid_int_fd(struct string *s, int *out_fd) +{ + if (_is_a_number(s)) + { + int fd = atoi(s->data); + if (fd < _get_open_max()) + { + *out_fd = fd; + return; + } + } + *out_fd = BAD_FD; +} + +/** + * @brief Assigns the fd described by s to out_fd if s + * describes an integer which is less than _SC_OPEN_MAX. + * s can also be exactly '-', in which case out_fd contains + * the value CLOSE_FD. + */ +static void _assign_if_valid_fd_and(struct string *s, int *out_fd) +{ + if (_is_a_number(s)) + { + int fd = atoi(s->data); + int cpy_fd = dup(fd); + *out_fd = cpy_fd; + return; + } + if (s->length == 1 && s->data[0] == '-') + { + *out_fd = CLOSE_FD; + return; + } + *out_fd = BAD_FD; +} + +void find_fds(struct redirect r, int *left_fd, int *right_fd) +{ + char *rd = r.redir->data; + static const int filemode = 0644; + + // Default value is no valid left fd is passed in `r`. + *left_fd = BAD_FD; + *right_fd = BAD_FD; + + if (STRINGS_ARE_EQUAL(rd, ">")) + { + // Sec. 2.7.2: noclobber must avoid overwritting on an existing file + if (env_get("noclobber") != NULL && _file_exists(r.file->data)) + { + fprintf(stderr, "redirection: Unable to overwrite on %s.\n", + r.file->data); + return; + } + *right_fd = open(r.file->data, O_WRONLY | O_CREAT | O_TRUNC, filemode); + _assign_if_valid_int_fd(r.fd, left_fd); + } + if (STRINGS_ARE_EQUAL(rd, ">>")) + { + *right_fd = open(r.file->data, O_WRONLY | O_CREAT | O_APPEND, filemode); + _assign_if_valid_int_fd(r.fd, left_fd); + } + if (STRINGS_ARE_EQUAL(rd, ">|")) + { + // Sec. 2.7.2: this redir bypasses noclobber + *right_fd = open(r.file->data, O_WRONLY | O_CREAT | O_TRUNC, filemode); + _assign_if_valid_int_fd(r.fd, left_fd); + } + if (STRINGS_ARE_EQUAL(rd, ">&")) + { + _assign_if_valid_int_fd(r.fd, left_fd); + _assign_if_valid_fd_and(r.file, right_fd); + if (*right_fd == BAD_FD) + { + // Sure why not after all, + // Because when it is about bash posix + // 'undefined' in the SCL means: + // OH <&{filename} is AMBIGUOUS + // BUT >&{filename} is PERFECTLY FINE + *right_fd = + open(r.file->data, O_WRONLY | O_CREAT | O_TRUNC, filemode); + } + } + if (STRINGS_ARE_EQUAL(rd, "<")) + { + *right_fd = open(r.file->data, O_RDONLY); + _assign_if_valid_int_fd(r.fd, left_fd); + } + if (STRINGS_ARE_EQUAL(rd, "<&")) + { + _assign_if_valid_int_fd(r.fd, left_fd); + _assign_if_valid_fd_and(r.file, right_fd); + } + if (STRINGS_ARE_EQUAL(rd, "<>")) + { + *right_fd = open(r.file->data, O_RDWR | O_CREAT, filemode); + _assign_if_valid_int_fd(r.fd, left_fd); + } +} -- cgit v1.2.3