Add heredoc

This commit is contained in:
savalet
2025-03-26 19:59:37 +01:00
parent 29208143ae
commit 9b5c06e927
8 changed files with 122 additions and 48 deletions

View File

@@ -20,7 +20,8 @@ ast_t *parse_arg(ast_ctx_t *ctx, ast_t *node)
ctx->act_tok = get_next_token(ctx);
if (ctx->act_tok.type == T_SEMICOLON)
return node;
if (ctx->act_tok.type & (T_ARG | T_REDIRECT | T_APPEND | T_IN_REDIRECT)) {
if (ctx->act_tok.type & (T_ARG | T_REDIRECT | T_APPEND |
T_IN_REDIRECT | T_HEREDOC)) {
if (!ensure_node_cap(node))
return NULL;
node->vector.tokens[node->vector.sz] = ctx->act_tok;

View File

@@ -29,11 +29,12 @@ typedef enum {
T_PREV_CMD = 1 << 9, // !!
T_VAR = 1 << 10, // $
T_REDIRECT = 1 << 11, // >
T_IN_REDIRECT = 1 << 12, // <
T_APPEND = 1 << 13, // >>
T_EOF = 1 << 14, // \0
T_ARG = 1 << 15,
T_INVALID = 1 << 16
T_APPEND = 1 << 12, // >>
T_HEREDOC = 1 << 13, // <
T_IN_REDIRECT = 1 << 14, // <
T_EOF = 1 << 15, // \0
T_ARG = 1 << 16,
T_INVALID = 1 << 17
} token_type_t;
typedef enum {

88
src/redirects.c Normal file
View File

@@ -0,0 +1,88 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "exec.h"
#include "u_str.h"
bool handle_out_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz)
{
if (!(node->vector.tokens[i].type & (T_REDIRECT | T_APPEND)))
return true;
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
return (WRITE_CONST(STDERR_FILENO,
"Missing name for redirect.\n"), false);
ef->skip_i = ef->skip_i ?: i;
ef->skip_sz += 2;
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
ef->rout_fd = open(node->vector.tokens[i + 1].str, O_CREAT | O_WRONLY |
(node->vector.tokens[i].type == T_APPEND ? O_APPEND : O_TRUNC), 0644);
if (ef->rout_fd < 0)
return (puterror(node->vector.tokens[i + 1].str), false);
ef->out_fd = ef->rout_fd;
return true;
}
bool handle_in_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz)
{
if (node->vector.tokens[i].type != T_IN_REDIRECT)
return true;
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
return (WRITE_CONST(STDERR_FILENO,
"Missing name for redirect.\n"), false);
ef->skip_i = ef->skip_i ?: i;
ef->skip_sz += 2;
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
ef->rin_fd = open(node->vector.tokens[i + 1].str, O_RDONLY);
if (ef->rin_fd < 0)
return (puterror(node->vector.tokens[i + 1].str), false);
ef->in_fd = ef->rin_fd;
return true;
}
int handle_heredoc_loop(ast_t *node, size_t i)
{
int fds[2];
buff_t buffer = { .str = NULL };
if (pipe(fds) < 0)
return (puterror("pipe"), -1);
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
WRITE_CONST(STDOUT_FILENO, "? ");
while (getline(&buffer.str, &buffer.sz, stdin) != -1) {
buffer.str[u_strlen(buffer.str) - 1] = '\0';
if (u_strcmp(buffer.str, node->vector.tokens[i + 1].str) == 0)
break;
write(fds[1], buffer.str, u_strlen(buffer.str));
write(fds[1], "\n", 1);
WRITE_CONST(STDOUT_FILENO, "? ");
}
free(buffer.str);
close(fds[1]);
return fds[0];
}
bool handle_heredoc(ef_t *ef, ast_t *node, size_t i, size_t sz)
{
if (node->vector.tokens[i].type != T_HEREDOC)
return true;
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
return (WRITE_CONST(STDERR_FILENO,
"Missing name for redirect.\n"), false);
ef->skip_i = ef->skip_i ?: i;
ef->skip_sz += 2;
ef->in_fd = handle_heredoc_loop(node, i);
if (ef->in_fd == -1)
return false;
return true;
}

18
src/redirects.h Normal file
View File

@@ -0,0 +1,18 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#ifndef REDIRECTS_H
#define REDIRECTS_H
#include <stdbool.h>
#include "exec.h"
bool handle_out_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz);
bool handle_in_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz);
int handle_heredoc_loop(ast_t *node, size_t i);
bool handle_heredoc(ef_t *ef, ast_t *node, size_t i, size_t sz);
#endif /* REDIRECTS_H */

View File

@@ -25,6 +25,7 @@ const tokens_list_t TOKENS_LIST[] = {
{ T_VAR, "$", 1, "T_VAR" },
{ T_APPEND, ">>", 2, "T_APPEND" },
{ T_REDIRECT, ">", 1, "T_REDIRECT" },
{ T_HEREDOC, "<<", 2, "T_HEREDOC" },
{ T_IN_REDIRECT, "<", 1, "T_IN_REDIRECT" },
{ T_EOF, "\0", 1, "T_EOF" }
};

View File

@@ -6,6 +6,7 @@
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -13,45 +14,9 @@
#include "builtins.h"
#include "common.h"
#include "exec.h"
#include "redirects.h"
#include "u_str.h"
static
bool handle_out_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz)
{
if (!(node->vector.tokens[i].type & (T_REDIRECT | T_APPEND)))
return true;
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
return (WRITE_CONST(STDERR_FILENO,
"Missing name for redirect.\n"), false);
ef->skip_i = ef->skip_i ?: i;
ef->skip_sz += 2;
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
ef->rout_fd = open(node->vector.tokens[i + 1].str, O_CREAT | O_WRONLY |
(node->vector.tokens[i].type == T_APPEND ? O_APPEND : O_TRUNC), 0644);
if (ef->rout_fd < 0)
return (puterror(node->vector.tokens[i + 1].str), false);
ef->out_fd = ef->rout_fd;
return true;
}
static
bool handle_in_redirect(ef_t *ef, ast_t *node, size_t i, size_t sz)
{
if (node->vector.tokens[i].type != T_IN_REDIRECT)
return true;
if (i >= sz || node->vector.tokens[i + 1].type != T_ARG)
return (WRITE_CONST(STDERR_FILENO,
"Missing name for redirect.\n"), false);
ef->skip_i = ef->skip_i ?: i;
ef->skip_sz += 2;
node->vector.tokens[i + 1].str[node->vector.tokens[i + 1].sz] = '\0';
ef->rin_fd = open(node->vector.tokens[i + 1].str, O_RDONLY);
if (ef->rin_fd < 0)
return (puterror(node->vector.tokens[i + 1].str), false);
ef->in_fd = ef->rin_fd;
return true;
}
/*
* ef->in_fd = ef->pin_fd;
* ef->out_fd = ef->out_fd;
@@ -69,9 +34,9 @@ int visit_cmd(ef_t *ef)
ef->rout_fd = 0;
ef->rin_fd = 0;
for (size_t i = 0; i < ef->act_node->vector.sz; i++) {
if (!handle_in_redirect(ef, ef->act_node, i, ef->act_node->vector.sz))
return -1;
if (!handle_out_redirect(ef, ef->act_node, i, ef->act_node->vector.sz))
if (!handle_in_redirect(ef, ef->act_node, i, ef->act_node->vector.sz)
|| !handle_out_redirect(ef, ef->act_node, i, ef->act_node->vector.sz)
|| !handle_heredoc(ef, ef->act_node, i, ef->act_node->vector.sz))
return -1;
}
result = execute(ef);

View File

@@ -11,7 +11,7 @@
#include "u_str.h"
void puterror(char *prefix)
void puterror(char const *prefix)
{
char const *error_msg = strerror(errno);
size_t len;

View File

@@ -33,6 +33,6 @@ int u_spacelen(char const *str);
int u_strcspn(char *str, char c);
bool u_str_is_alnum(char *str);
bool u_str_is_only_alnum(char *str);
void puterror(char *prefix);
void puterror(char const *prefix);
#endif /* STRING_H */