mirror of
https://github.com/Savapitech/42sh.git
synced 2026-03-18 21:50:35 +01:00
Add heredoc
This commit is contained in:
@@ -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;
|
||||
|
||||
11
src/ast.h
11
src/ast.h
@@ -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
88
src/redirects.c
Normal 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
18
src/redirects.h
Normal 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 */
|
||||
@@ -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" }
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user