42sh/src/io_backend/io_backend.c
2026-01-22 14:05:49 +01:00

138 lines
3 KiB
C

#define _POSIX_C_SOURCE 200809L
#include "io_backend.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// === Static variables
#include "../utils/args/args.h"
static struct iob_context context;
static FILE *input = NULL;
static char *stream_buf = NULL;
static size_t stream_buf_size = 0;
static enum iob_state state = IOB_STATE_NOT_INITIALIZED;
// === Functions
int iob_init(struct iob_context *ctx)
{
if (state != IOB_STATE_NOT_INITIALIZED)
return IOB_ERROR_MODULE_ALREADY_INITIALIZED;
context = *ctx;
switch (context.mode)
{
case IOB_MODE_STDIN:
input = stdin;
state = IOB_STATE_READY;
return 0;
case IOB_MODE_SCRIPT:
if (context.args == NULL)
return IOB_ERROR_BAD_ARG;
input = fopen(context.args, "r");
if (input == NULL)
return IOB_ERROR_CANNOT_OPEN_FILE;
state = IOB_STATE_READY;
return 0;
case IOB_MODE_CMD:
if (context.args == NULL)
return IOB_ERROR_BAD_ARG;
state = IOB_STATE_READY;
return 0;
default:
return IOB_ERROR_BAD_ARG;
}
}
void iob_close(void)
{
fclose(input);
if ((context.mode == IOB_MODE_STDIN || context.mode == IOB_MODE_SCRIPT)
&& stream_buf != NULL)
{
free(stream_buf);
stream_buf_size = 0;
}
state = IOB_STATE_NOT_INITIALIZED;
}
ssize_t stream_read(char **stream)
{
// Check args
if (stream == NULL)
return IOB_ERROR_BAD_ARG;
// Check env
if (state == IOB_STATE_NOT_INITIALIZED)
return IOB_ERROR_MODULE_NOT_INITIALIZED;
if (state == IOB_STATE_FINISHED)
return 0;
if (state == IOB_STATE_ERROR)
return IOB_ERROR_GENERIC;
// Use input
if (context.mode == IOB_MODE_STDIN || context.mode == IOB_MODE_SCRIPT)
{
ssize_t nread = getline(&stream_buf, &stream_buf_size, input);
if (nread == -1)
{
state = IOB_STATE_FINISHED;
// MAGNIFICO
// malloc(1);
*stream_buf = EOF;
*stream = stream_buf;
return 1;
}
else if (nread < 0)
state = IOB_STATE_ERROR;
*stream = stream_buf;
return nread;
}
// Use args
else if (context.mode == IOB_MODE_CMD)
{
*stream = context.args;
size_t len = strlen(context.args);
context.args[len] = EOF;
return len + 1;
}
else
{
*stream = NULL;
return IOB_ERROR_GENERIC;
}
}
int iob_config_from_args(struct args_options *args, struct iob_context *ctx)
{
switch (args->type)
{
case INPUT_STDIN:
ctx->mode = IOB_MODE_STDIN;
ctx->args = NULL;
break;
case INPUT_FILE:
ctx->mode = IOB_MODE_SCRIPT;
ctx->args = (char *)args->input_source;
break;
case INPUT_CMD:
ctx->mode = IOB_MODE_CMD;
ctx->args = (char *)args->input_source;
break;
default:
return IOB_ERROR_GENERIC;
}
return 0;
}