~emersion/mrsh

a27dfd54eb0d6e25793936caf2b2fef7639e97e3 — delthas 3 years ago 2f7a930
builtin/read: implement basic read builtin
4 files changed, 65 insertions(+), 0 deletions(-)

M builtin/builtin.c
A builtin/read.c
M include/builtin.h
M meson.build
M builtin/builtin.c => builtin/builtin.c +1 -0
@@ 23,6 23,7 @@ static const struct builtin builtins[] = {
	{ "export", builtin_export, true },
	{ "false", builtin_false, false },
	{ "pwd", builtin_pwd, false },
	{ "read", builtin_read, false },
	{ "readonly", builtin_export, true },
	{ "set", builtin_set, true },
	{ "shift", builtin_shift, true },

A builtin/read.c => builtin/read.c +62 -0
@@ 0,0 1,62 @@
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <mrsh/buffer.h>
#include <mrsh/shell.h>
#include "builtin.h"

// usage: read [-r] var...
static const char read_usage[] = "usage: read [-r] var...\n";

int builtin_read(struct mrsh_state *state, int argc, char *argv[]) {
	bool raw = false;
	
	int opt;
	while ((opt = getopt(argc, argv, "r")) != -1) {
		switch (opt) {
		case 'r':
			raw = true;
			break;
		default:
			fprintf(stderr, read_usage);
			return EXIT_FAILURE;
		}
	}
	if (optind >= argc) {
		fprintf(stderr, read_usage);
		return EXIT_FAILURE;
	}

	// TODO handle multiple variables and split
	if (argc > optind + 1) {
		fprintf(stderr, "read: multiple variables not yet implemented\n");
		return EXIT_FAILURE;
	}
	
	struct mrsh_buffer buf = {0};
	bool escaped = false;
	int c;
	while ((c = fgetc(stdin)) != EOF) {
		if (!raw && !escaped && c == '\\') {
			escaped = true;
			continue;
		}
		if (c == '\n') {
			if (escaped) {
				escaped = false;
				continue;
			}
			break;
		}
		escaped = false;
		mrsh_buffer_append_char(&buf, (char)c);
	}
	mrsh_buffer_append_char(&buf, '\0');

	mrsh_env_set(state, argv[optind], buf.data, MRSH_VAR_ATTRIB_NONE);
	mrsh_buffer_finish(&buf);
	return EXIT_SUCCESS;
}

M include/builtin.h => include/builtin.h +1 -0
@@ 15,6 15,7 @@ int builtin_exit(struct mrsh_state *state, int argc, char *argv[]);
int builtin_export(struct mrsh_state *state, int argc, char *argv[]);
int builtin_eval(struct mrsh_state *state, int argc, char *argv[]);
int builtin_pwd(struct mrsh_state *state, int argc, char *argv[]);
int builtin_read(struct mrsh_state *state, int argc, char *argv[]);
int builtin_shift(struct mrsh_state *state, int argc, char *argv[]);
int builtin_source(struct mrsh_state *state, int argc, char *argv[]);
int builtin_times(struct mrsh_state *state, int argc, char *argv[]);

M meson.build => meson.build +1 -0
@@ 40,6 40,7 @@ lib_mrsh = library(
		'builtin/exit.c',
		'builtin/export.c',
		'builtin/pwd.c',
		'builtin/read.c',
		'builtin/set.c',
		'builtin/shift.c',
		'builtin/source.c',