~emersion/mrsh-dev

Add -i option v1 PROPOSED

Victor Westerhuis: 1
 Add -i option

 1 files changed, 83 insertions(+), 56 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~emersion/mrsh-dev/patches/28917/mbox | git am -3
Learn more about email & git

[PATCH] Add -i option Export this patch

This is specified by POSIX and easily implemented.
---
 builtin/set.c | 139 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 83 insertions(+), 56 deletions(-)

diff --git a/builtin/set.c b/builtin/set.c
index c3ad0e6..fc65eaa 100644
--- a/builtin/set.c
@@ -1,51 +1,55 @@
#define _POSIX_C_SOURCE 200809L
#include "builtin.h"
#include "shell/shell.h"

#include <errno.h>
#include <mrsh/builtin.h>
#include <mrsh/shell.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include "builtin.h"
#include "shell/shell.h"

#include <mrsh/builtin.h>
#include <mrsh/shell.h>

static const char set_usage[] =
	"usage: set [(-|+)abCefhmnuvx] [-o option] [args...]\n"
	"       set [(-|+)abCefhmnuvx] [+o option] [args...]\n"
	"       set -- [args...]\n"
	"       set -o\n"
	"       set +o\n";
        "usage: set [(-|+)abCefhmnuvx] [-o option] [args...]\n"
        "       set [(-|+)abCefhmnuvx] [+o option] [args...]\n"
        "       set -- [args...]\n"
        "       set -o\n"
        "       set +o\n";

struct option_map {
	const char *name;
	const char* name;
	char short_name;
	enum mrsh_option value;
};

static const struct option_map options[] = {
	{ "allexport", 'a', MRSH_OPT_ALLEXPORT },
	{ "notify", 'b', MRSH_OPT_NOTIFY },
	{ "noclobber", 'C', MRSH_OPT_NOCLOBBER },
	{ "errexit", 'e', MRSH_OPT_ERREXIT },
	{ "noglob", 'f', MRSH_OPT_NOGLOB },
	{ NULL, 'h', MRSH_OPT_PRELOOKUP },
	{ "monitor", 'm', MRSH_OPT_MONITOR },
	{ "noexec", 'n', MRSH_OPT_NOEXEC },
	{ "ignoreeof", 0, MRSH_OPT_IGNOREEOF },
	{ "nolog", 0, MRSH_OPT_NOLOG },
	{ "vi", 0, MRSH_OPT_VI },
	{ "nounset", 'u', MRSH_OPT_NOUNSET },
	{ "verbose", 'v', MRSH_OPT_VERBOSE },
	{ "xtrace", 'x', MRSH_OPT_XTRACE },
        {"allexport", 'a', MRSH_OPT_ALLEXPORT},
        {"notify", 'b', MRSH_OPT_NOTIFY},
        {"noclobber", 'C', MRSH_OPT_NOCLOBBER},
        {"errexit", 'e', MRSH_OPT_ERREXIT},
        {"noglob", 'f', MRSH_OPT_NOGLOB},
        {NULL, 'h', MRSH_OPT_PRELOOKUP},
        {"monitor", 'm', MRSH_OPT_MONITOR},
        {"noexec", 'n', MRSH_OPT_NOEXEC},
        {"ignoreeof", 0, MRSH_OPT_IGNOREEOF},
        {"nolog", 0, MRSH_OPT_NOLOG},
        {"vi", 0, MRSH_OPT_VI},
        {"nounset", 'u', MRSH_OPT_NOUNSET},
        {"verbose", 'v', MRSH_OPT_VERBOSE},
        {"xtrace", 'x', MRSH_OPT_XTRACE},
};

const char *state_get_options(struct mrsh_state *state) {
const char* state_get_options(struct mrsh_state* state)
{
	static char opts[sizeof(options) / sizeof(options[0]) + 1];
	int i = 0;
	for (size_t j = 0; j < sizeof(options) / sizeof(options[0]); ++j) {
		if (options[j].short_name != '\0' &&
				(state->options & options[j].value)) {
		    (state->options & options[j].value)) {
			opts[i++] = options[j].short_name;
		}
	}
@@ -53,17 +57,19 @@ const char *state_get_options(struct mrsh_state *state) {
	return opts;
}

static void print_options(struct mrsh_state *state) {
static void print_options(struct mrsh_state* state)
{
	for (size_t j = 0; j < sizeof(options) / sizeof(options[0]); ++j) {
		if (options[j].name != NULL) {
			printf("set %co %s\n",
				(state->options & options[j].value) ? '-' : '+',
				options[j].name);
			       (state->options & options[j].value) ? '-' : '+',
			       options[j].name);
		}
	}
}

static const struct option_map *find_option(char opt) {
static const struct option_map* find_option(char opt)
{
	for (size_t i = 0; i < sizeof(options) / sizeof(options[0]); ++i) {
		if (options[i].short_name && options[i].short_name == opt) {
			return &options[i];
@@ -72,7 +78,8 @@ static const struct option_map *find_option(char opt) {
	return NULL;
}

static const struct option_map *find_long_option(const char *opt) {
static const struct option_map* find_long_option(const char* opt)
{
	for (size_t i = 0; i < sizeof(options) / sizeof(options[0]); ++i) {
		if (options[i].name && strcmp(options[i].name, opt) == 0) {
			return &options[i];
@@ -81,8 +88,9 @@ static const struct option_map *find_long_option(const char *opt) {
	return NULL;
}

static char **argv_dup(char *argv_0, int argc, char *argv[]) {
	char **_argv = calloc(argc + 1, sizeof(char *));
static char** argv_dup(char* argv_0, int argc, char* argv[])
{
	char** _argv = calloc(argc + 1, sizeof(char*));
	_argv[0] = argv_0;
	for (int i = 1; i < argc; ++i) {
		_argv[i] = strdup(argv[i - 1]);
@@ -90,7 +98,8 @@ static char **argv_dup(char *argv_0, int argc, char *argv[]) {
	return _argv;
}

static void argv_free(int argc, char **argv) {
static void argv_free(int argc, char** argv)
{
	if (!argv) {
		return;
	}
@@ -100,12 +109,13 @@ static void argv_free(int argc, char **argv) {
	free(argv);
}

static int set(struct mrsh_state *state, int argc, char *argv[],
		struct mrsh_init_args *init_args, uint32_t *populated_opts) {
static int set(struct mrsh_state* state, int argc, char* argv[],
               struct mrsh_init_args* init_args, uint32_t* populated_opts)
{
	if (argc == 1 && init_args == NULL) {
		size_t count;
		struct mrsh_collect_var *vars = collect_vars(
			state, MRSH_VAR_ATTRIB_NONE, &count);
		struct mrsh_collect_var* vars =
		        collect_vars(state, MRSH_VAR_ATTRIB_NONE, &count);
		for (size_t i = 0; i < count; ++i) {
			printf("%s=", vars[i].key);
			print_escaped(vars[i].value);
@@ -130,7 +140,7 @@ static int set(struct mrsh_state *state, int argc, char *argv[],
			fprintf(stderr, set_usage);
			return 1;
		}
		const struct option_map *option;
		const struct option_map* option;
		switch (argv[i][1]) {
		case 'o':
			if (i + 1 == argc) {
@@ -144,7 +154,8 @@ static int set(struct mrsh_state *state, int argc, char *argv[],
			}
			if (argv[i][0] == '-') {
				state->options |= option->value;
			} else {
			}
			else {
				state->options &= ~option->value;
			}
			if (populated_opts != NULL) {
@@ -160,6 +171,13 @@ static int set(struct mrsh_state *state, int argc, char *argv[],
			init_args->command_str = argv[i + 1];
			++i;
			break;
		case 'i':
			if (init_args == NULL) {
				fprintf(stderr, set_usage);
				return 1;
			}
			state->interactive = argv[i][0] == '-';
			break;
		case 's':
			if (init_args == NULL) {
				fprintf(stderr, set_usage);
@@ -177,7 +195,8 @@ static int set(struct mrsh_state *state, int argc, char *argv[],
				}
				if (argv[i][0] == '-') {
					state->options |= option->value;
				} else {
				}
				else {
					state->options &= ~option->value;
				}
				if (populated_opts != NULL) {
@@ -189,31 +208,35 @@ static int set(struct mrsh_state *state, int argc, char *argv[],
	}

	if (i != argc || force_positional) {
		char *argv_0;
		char* argv_0;
		if (init_args != NULL) {
			argv_0 = strdup(argv[i++]);
			init_args->command_file = argv_0;
		} else if (state->frame->argv) {
		}
		else if (state->frame->argv) {
			argv_0 = strdup(state->frame->argv[0]);
		} else {
		}
		else {
			fprintf(stderr, set_usage);
			return 1;
		}
		argv_free(state->frame->argc, state->frame->argv);
		state->frame->argc = argc - i + 1;
		state->frame->argv = argv_dup(argv_0, state->frame->argc, &argv[i]);
	} else
out:
	  if (init_args != NULL) {
		// No args given, but we need to initialize state->argv
		state->frame->argc = 1;
		state->frame->argv = argv_dup(strdup(argv[0]), 1, argv);
	}
	else
	out:
		if (init_args != NULL) {
			// No args given, but we need to initialize state->argv
			state->frame->argc = 1;
			state->frame->argv = argv_dup(strdup(argv[0]), 1, argv);
		}

	return 0;
}

int builtin_set(struct mrsh_state *state, int argc, char *argv[]) {
int builtin_set(struct mrsh_state* state, int argc, char* argv[])
{
	uint32_t populated_opts = 0;
	int ret = set(state, argc, argv, NULL, &populated_opts);
	if (ret != 0) {
@@ -229,9 +252,10 @@ int builtin_set(struct mrsh_state *state, int argc, char *argv[]) {
	return 0;
}

int mrsh_process_args(struct mrsh_state *state, struct mrsh_init_args *init_args,
		int argc, char *argv[]) {
	struct mrsh_state_priv *priv = state_get_priv(state);
int mrsh_process_args(struct mrsh_state* state,
                      struct mrsh_init_args* init_args, int argc, char* argv[])
{
	struct mrsh_state_priv* priv = state_get_priv(state);

	uint32_t populated_opts = 0;
	int ret = set(state, argc, argv, init_args, &populated_opts);
@@ -239,8 +263,11 @@ int mrsh_process_args(struct mrsh_state *state, struct mrsh_init_args *init_args
		return ret;
	}

	state->interactive = isatty(priv->term_fd) &&
		init_args->command_str == NULL && init_args->command_file == NULL;
	if (!state->interactive) {
		state->interactive = isatty(priv->term_fd) &&
		                     init_args->command_str == NULL &&
		                     init_args->command_file == NULL;
	}
	if (state->interactive && !(populated_opts & MRSH_OPT_MONITOR)) {
		state->options |= MRSH_OPT_MONITOR;
	}
-- 
2.34.1