~emersion/mrsh

8312ce143903f0befff5d0d595bf94d7836236ec — Simon Ser 5 months ago 9f43095
Make mrsh_getopt private
M builtin/alias.c => builtin/alias.c +6 -6
@@ 1,10 1,10 @@
#define _POSIX_C_SOURCE 200809L
#include <mrsh/getopt.h>
#include <mrsh/builtin.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/shell.h"

static const char alias_usage[] = "usage: alias [alias-name[=string]...]\n";


@@ 20,19 20,19 @@ static void print_alias_iterator(const char *key, void *_value,
int builtin_alias(struct mrsh_state *state, int argc, char *argv[]) {
	struct mrsh_state_priv *priv = state_get_priv(state);

	mrsh_optind = 0;
	if (mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "alias: unknown option -- %c\n", mrsh_optopt);
	_mrsh_optind = 0;
	if (_mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "alias: unknown option -- %c\n", _mrsh_optopt);
		fprintf(stderr, "%s", alias_usage);
		return 1;
	}

	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		mrsh_hashtable_for_each(&priv->aliases, print_alias_iterator, NULL);
		return 0;
	}

	for (int i = mrsh_optind; i < argc; ++i) {
	for (int i = _mrsh_optind; i < argc; ++i) {
		char *alias = argv[i];
		char *equal = strchr(alias, '=');
		if (equal != NULL) {

M builtin/bg.c => builtin/bg.c +6 -6
@@ 1,7 1,7 @@
#include <mrsh/getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/job.h"
#include "shell/shell.h"
#include "shell/task.h"


@@ 9,17 9,17 @@
static const char bg_usage[] = "usage: bg [job_id...]\n";

int builtin_bg(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":")) != -1) {
		switch (opt) {
		default:
			fprintf(stderr, "bg: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "bg: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, bg_usage);
			return EXIT_FAILURE;
		}
	}
	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		struct mrsh_job *job = job_by_id(state, "%%", true);
		if (!job) {
			return EXIT_FAILURE;


@@ 30,7 30,7 @@ int builtin_bg(struct mrsh_state *state, int argc, char *argv[]) {
		return EXIT_SUCCESS;
	}

	for (int i = mrsh_optind; i < argc; ++i) {
	for (int i = _mrsh_optind; i < argc; ++i) {
		struct mrsh_job *job = job_by_id(state, argv[i], true);
		if (!job) {
			return EXIT_FAILURE;

M builtin/cd.c => builtin/cd.c +6 -6
@@ 1,7 1,6 @@
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <limits.h>
#include <mrsh/getopt.h>
#include <mrsh/shell.h>
#include <stdio.h>
#include <stdlib.h>


@@ 9,6 8,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include "builtin.h"
#include "mrsh_getopt.h"

static const char cd_usage[] = "usage: cd [-L|-P] [-|directory]\n";



@@ 37,9 37,9 @@ static int isdir(char *path) {
}

int builtin_cd(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":LP")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":LP")) != -1) {
		switch (opt) {
		case 'L':
		case 'P':


@@ 47,13 47,13 @@ int builtin_cd(struct mrsh_state *state, int argc, char *argv[]) {
			fprintf(stderr, "cd: `-L` and `-P` not yet implemented\n");
			return 1;
		default:
			fprintf(stderr, "cd: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "cd: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, cd_usage);
			return 1;
		}
	}

	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		const char *home = mrsh_env_get(state, "HOME", NULL);
		if (home && home[0] != '\0') {
			return cd(state, home);


@@ 63,7 63,7 @@ int builtin_cd(struct mrsh_state *state, int argc, char *argv[]) {
		return 1;
	}

	char *curpath = argv[mrsh_optind];
	char *curpath = argv[_mrsh_optind];
	// `cd -`
	if (strcmp(curpath, "-") == 0) {
		// This case is special as we print `pwd` at the end

M builtin/command.c => builtin/command.c +9 -9
@@ 1,10 1,10 @@
#define _POSIX_C_SOURCE 200809L
#include <mrsh/getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "parser.h"
#include "shell/job.h"
#include "shell/path.h"


@@ 59,7 59,7 @@ static int verify_command(struct mrsh_state *state, const char *command_name,
static int run_command(struct mrsh_state *state, int argc, char *argv[],
		bool default_path) {
	if (mrsh_has_builtin(argv[0])) {
		return mrsh_run_builtin(state, argc - mrsh_optind, &argv[mrsh_optind]);
		return mrsh_run_builtin(state, argc - _mrsh_optind, &argv[_mrsh_optind]);
	}

	const char *path = expand_path(state, argv[0], true, default_path);


@@ 86,11 86,11 @@ static int run_command(struct mrsh_state *state, int argc, char *argv[],
}

int builtin_command(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;

	bool verify = false, default_path = false;
	while ((opt = mrsh_getopt(argc, argv, ":vVp")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":vVp")) != -1) {
		switch (opt) {
		case 'v':
			verify = true;


@@ 103,25 103,25 @@ int builtin_command(struct mrsh_state *state, int argc, char *argv[]) {
			default_path = true;
			break;
		default:
			fprintf(stderr, "command: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "command: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, command_usage);
			return 1;
		}
	}

	if (mrsh_optind >= argc) {
	if (_mrsh_optind >= argc) {
		fprintf(stderr, command_usage);
		return 1;
	}

	if (verify) {
		if (mrsh_optind != argc - 1) {
		if (_mrsh_optind != argc - 1) {
			fprintf(stderr, command_usage);
			return 1;
		}
		return verify_command(state, argv[mrsh_optind], default_path);
		return verify_command(state, argv[_mrsh_optind], default_path);
	}

	return run_command(state, argc - mrsh_optind, &argv[mrsh_optind],
	return run_command(state, argc - _mrsh_optind, &argv[_mrsh_optind],
		default_path);
}

M builtin/exec.c => builtin/exec.c +8 -8
@@ 1,25 1,25 @@
#include <mrsh/getopt.h>
#include <stdio.h>
#include <unistd.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/path.h"

static const char exec_usage[] = "usage: exec [command [argument...]]\n";

int builtin_exec(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	if (mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "exec: unknown option -- %c\n", mrsh_optopt);
	_mrsh_optind = 0;
	if (_mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "exec: unknown option -- %c\n", _mrsh_optopt);
		fprintf(stderr, exec_usage);
		return 1;
	}
	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		return 0;
	}

	const char *path = expand_path(state, argv[mrsh_optind], false, false);
	const char *path = expand_path(state, argv[_mrsh_optind], false, false);
	if (path == NULL) {
		fprintf(stderr, "exec: %s: command not found\n", argv[mrsh_optind]);
		fprintf(stderr, "exec: %s: command not found\n", argv[_mrsh_optind]);
		return 127;
	}
	if (access(path, X_OK) != 0) {


@@ 27,7 27,7 @@ int builtin_exec(struct mrsh_state *state, int argc, char *argv[]) {
		return 126;
	}

	execv(path, &argv[mrsh_optind]);
	execv(path, &argv[_mrsh_optind]);
	perror("exec");
	return 1;
}

M builtin/fg.c => builtin/fg.c +7 -7
@@ 1,29 1,29 @@
#include <mrsh/getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/job.h"
#include "shell/shell.h"

static const char fg_usage[] = "usage: fg [job_id]\n";

int builtin_fg(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":")) != -1) {
		switch (opt) {
		default:
			fprintf(stderr, "fg: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "fg: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, fg_usage);
			return EXIT_FAILURE;
		}
	}

	struct mrsh_job *job;
	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		job = job_by_id(state, "%%", true);
	} else if (mrsh_optind == argc - 1) {
		job = job_by_id(state, argv[mrsh_optind], true);
	} else if (_mrsh_optind == argc - 1) {
		job = job_by_id(state, argv[_mrsh_optind], true);
	} else {
		fprintf(stderr, fg_usage);
		return EXIT_FAILURE;

M builtin/getopts.c => builtin/getopts.c +21 -21
@@ 2,38 2,38 @@
#include <errno.h>
#include <limits.h>
#include <mrsh/buffer.h>
#include <mrsh/getopt.h>
#include <mrsh/shell.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "builtin.h"
#include "mrsh_getopt.h"

static const char getopts_usage[] = "usage: getopts optstring name [arg...]\n";

int builtin_getopts(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	if (mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "getopts: unknown option -- %c\n", mrsh_optopt);
	_mrsh_optind = 0;
	if (_mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "getopts: unknown option -- %c\n", _mrsh_optopt);
		fprintf(stderr, getopts_usage);
		return 1;
	}
	if (mrsh_optind + 2 < argc) {
	if (_mrsh_optind + 2 < argc) {
		fprintf(stderr, getopts_usage);
		return 1;
	}

	int optc;
	char **optv;
	if (mrsh_optind + 2 > argc) {
		optc = argc - mrsh_optind - 2;
		optv = &argv[mrsh_optind + 2];
	if (_mrsh_optind + 2 > argc) {
		optc = argc - _mrsh_optind - 2;
		optv = &argv[_mrsh_optind + 2];
	} else {
		optc = state->frame->argc;
		optv = state->frame->argv;
	}
	char *optstring = argv[mrsh_optind];
	char *name = argv[mrsh_optind + 1];
	char *optstring = argv[_mrsh_optind];
	char *name = argv[_mrsh_optind + 1];

	const char *optind_str = mrsh_env_get(state, "OPTIND", NULL);
	if (optind_str == NULL) {


@@ 46,29 46,29 @@ int builtin_getopts(struct mrsh_state *state, int argc, char *argv[]) {
		fprintf(stderr, "getopts: OPTIND is not a positive integer\n");
		return 1;
	}
	mrsh_optind = (int)optind_long;
	_mrsh_optind = (int)optind_long;

	mrsh_optopt = 0;
	int opt = mrsh_getopt(optc, optv, optstring);
	_mrsh_optopt = 0;
	int opt = _mrsh_getopt(optc, optv, optstring);

	char optind_fmt[16];
	snprintf(optind_fmt, sizeof(optind_fmt), "%d", mrsh_optind);
	snprintf(optind_fmt, sizeof(optind_fmt), "%d", _mrsh_optind);
	mrsh_env_set(state, "OPTIND", optind_fmt, MRSH_VAR_ATTRIB_NONE);

	if (mrsh_optopt != 0) {
	if (_mrsh_optopt != 0) {
		if (opt == ':') {
			char value[] = {(char)mrsh_optopt, '\0'};
			char value[] = {(char)_mrsh_optopt, '\0'};
			mrsh_env_set(state, "OPTARG", value, MRSH_VAR_ATTRIB_NONE);
		} else if (optstring[0] != ':') {
			mrsh_env_unset(state, "OPTARG");
		} else {
			// either missing option-argument or unknown option character
			// in the former case, unset OPTARG
			// in the latter case, set OPTARG to mrsh_optopt
			// in the latter case, set OPTARG to _mrsh_optopt
			bool opt_exists = false;
			size_t len = strlen(optstring);
			for (size_t i = 0; i < len; ++i) {
				if (optstring[i] == mrsh_optopt) {
				if (optstring[i] == _mrsh_optopt) {
					opt_exists = true;
					break;
				}


@@ 76,12 76,12 @@ int builtin_getopts(struct mrsh_state *state, int argc, char *argv[]) {
			if (opt_exists) {
				mrsh_env_unset(state, "OPTARG");
			} else {
				char value[] = {(char)mrsh_optopt, '\0'};
				char value[] = {(char)_mrsh_optopt, '\0'};
				mrsh_env_set(state, "OPTARG", value, MRSH_VAR_ATTRIB_NONE);
			}
		}
	} else if (mrsh_optarg != NULL) {
		mrsh_env_set(state, "OPTARG", mrsh_optarg, MRSH_VAR_ATTRIB_NONE);
	} else if (_mrsh_optarg != NULL) {
		mrsh_env_set(state, "OPTARG", _mrsh_optarg, MRSH_VAR_ATTRIB_NONE);
	} else {
		mrsh_env_unset(state, "OPTARG");
	}

M builtin/hash.c => builtin/hash.c +4 -4
@@ 1,24 1,24 @@
#include <mrsh/getopt.h>
#include <mrsh/builtin.h>
#include <shell/path.h>
#include <stdio.h>
#include <string.h>
#include "builtin.h"
#include "mrsh_getopt.h"

static const char hash_usage[] = "usage: hash -r|utility...\n";

int builtin_hash(struct mrsh_state *state, int argc, char *argv[]) {
	/* Hashing and remembering executable location isn't implemented. Thus most
	 * of this builtin just does nothing. */
	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":r")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":r")) != -1) {
		switch (opt) {
		case 'r':
			/* no-op: reset list of cached utilities */
			return 0;
		default:
			fprintf(stderr, "hash: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "hash: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, hash_usage);
			return 1;
		}

M builtin/jobs.c => builtin/jobs.c +6 -6
@@ 1,10 1,10 @@
#include <assert.h>
#include <limits.h>
#include <mrsh/getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/job.h"
#include "shell/process.h"
#include "shell/shell.h"


@@ 61,9 61,9 @@ int builtin_jobs(struct mrsh_state *state, int argc, char *argv[]) {
		.r = rand() % 2 == 0,
	};

	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":lp")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":lp")) != -1) {
		switch (opt) {
		case 'l':
			if (ctx.pids) {


@@ 82,19 82,19 @@ int builtin_jobs(struct mrsh_state *state, int argc, char *argv[]) {
			ctx.pids = true;
			break;
		default:
			fprintf(stderr, "jobs: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "jobs: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, jobs_usage);
			return EXIT_FAILURE;
		}
	}

	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		for (size_t i = 0; i < priv->jobs.len; i++) {
			struct mrsh_job *job = priv->jobs.data[i];
			show_job(job, &ctx);
		}
	} else {
		for (int i = mrsh_optind; i < argc; i++) {
		for (int i = _mrsh_optind; i < argc; i++) {
			struct mrsh_job *job = job_by_id(state, argv[i], true);
			if (!job) {
				return 1;

M builtin/pwd.c => builtin/pwd.c +5 -5
@@ 1,30 1,30 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <mrsh/getopt.h>
#include <mrsh/shell.h>
#include <stdio.h>
#include <stdlib.h>
#include "builtin.h"
#include "mrsh_getopt.h"

static const char pwd_usage[] = "usage: pwd [-L|-P]\n";

int builtin_pwd(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":LP")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":LP")) != -1) {
		switch (opt) {
		case 'L':
		case 'P':
			/* This space deliberately left blank */
			break;
		default:
			fprintf(stderr, "pwd: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "pwd: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, pwd_usage);
			return 1;
		}
	}

	if (mrsh_optind < argc) {
	if (_mrsh_optind < argc) {
		fprintf(stderr, pwd_usage);
		return 1;
	}

M builtin/read.c => builtin/read.c +12 -12
@@ 1,33 1,33 @@
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <mrsh/buffer.h>
#include <mrsh/getopt.h>
#include <mrsh/shell.h>
#include <shell/word.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "builtin.h"
#include "mrsh_getopt.h"

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

int builtin_read(struct mrsh_state *state, int argc, char *argv[]) {
	bool raw = false;

	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":r")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":r")) != -1) {
		switch (opt) {
		case 'r':
			raw = true;
			break;
		default:
			fprintf(stderr, "read: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "read: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, read_usage);
			return 1;
		}
	}
	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		fprintf(stderr, read_usage);
		return 1;
	}


@@ 68,19 68,19 @@ int builtin_read(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_array_finish(&fields);
	fields = strs;

	if (fields.len <= (size_t)(argc - mrsh_optind)) {
	if (fields.len <= (size_t)(argc - _mrsh_optind)) {
		for (size_t i = 0; i < fields.len; ++i) {
			mrsh_env_set(state, argv[mrsh_optind + i], (char *)fields.data[i], MRSH_VAR_ATTRIB_NONE);
			mrsh_env_set(state, argv[_mrsh_optind + i], (char *)fields.data[i], MRSH_VAR_ATTRIB_NONE);
		}
		for (size_t i = fields.len; i < (size_t)(argc - mrsh_optind); ++i) {
			mrsh_env_set(state, argv[mrsh_optind + i], "", MRSH_VAR_ATTRIB_NONE);
		for (size_t i = fields.len; i < (size_t)(argc - _mrsh_optind); ++i) {
			mrsh_env_set(state, argv[_mrsh_optind + i], "", MRSH_VAR_ATTRIB_NONE);
		}
	} else {
		for (int i = 0; i < argc - mrsh_optind - 1; ++i) {
			mrsh_env_set(state, argv[mrsh_optind + i], (char *)fields.data[i], MRSH_VAR_ATTRIB_NONE);
		for (int i = 0; i < argc - _mrsh_optind - 1; ++i) {
			mrsh_env_set(state, argv[_mrsh_optind + i], (char *)fields.data[i], MRSH_VAR_ATTRIB_NONE);
		}
		struct mrsh_buffer buf_last = {0};
		for (size_t i = (size_t)(argc - mrsh_optind - 1); i < fields.len; ++i) {
		for (size_t i = (size_t)(argc - _mrsh_optind - 1); i < fields.len; ++i) {
			char *field = (char *)fields.data[i];
			mrsh_buffer_append(&buf_last, field, strlen(field));
			if (i != fields.len - 1) {

M builtin/trap.c => builtin/trap.c +9 -9
@@ 1,6 1,5 @@
#define _XOPEN_SOURCE 1 // for SIGPOLL and SIGVTALRM
#include <assert.h>
#include <mrsh/getopt.h>
#include <mrsh/parser.h>
#include <mrsh/shell.h>
#include <signal.h>


@@ 8,6 7,7 @@
#include <stdlib.h>
#include <string.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/shell.h"
#include "shell/trap.h"



@@ 132,23 132,23 @@ static void print_traps(struct mrsh_state *state) {
}

int builtin_trap(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	if (mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "trap: unknown option -- %c\n", mrsh_optopt);
	_mrsh_optind = 0;
	if (_mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "trap: unknown option -- %c\n", _mrsh_optopt);
		fprintf(stderr, trap_usage);
		return 1;
	}
	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		print_traps(state);
		return 0;
	}

	const char *action_str;
	if (is_decimal_str(argv[mrsh_optind])) {
	if (is_decimal_str(argv[_mrsh_optind])) {
		action_str = "-";
	} else {
		action_str = argv[mrsh_optind];
		mrsh_optind++;
		action_str = argv[_mrsh_optind];
		_mrsh_optind++;
	}

	enum mrsh_trap_action action;


@@ 176,7 176,7 @@ int builtin_trap(struct mrsh_state *state, int argc, char *argv[]) {
		mrsh_parser_destroy(parser);
	}

	for (int i = mrsh_optind; i < argc; i++) {
	for (int i = _mrsh_optind; i < argc; i++) {
		int sig = parse_sig(argv[i]);
		if (sig < 0) {
			return 1;

M builtin/type.c => builtin/type.c +6 -6
@@ 1,9 1,9 @@
#define _POSIX_C_SOURCE 200809L
#include <mrsh/builtin.h>
#include <mrsh/getopt.h>
#include <shell/path.h>
#include <stdlib.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/shell.h"

static const char type_usage[] = "usage: type name...\n";


@@ 11,19 11,19 @@ static const char type_usage[] = "usage: type name...\n";
int builtin_type(struct mrsh_state *state, int argc, char *argv[]) {
	struct mrsh_state_priv *priv = state_get_priv(state);

	mrsh_optind = 0;
	if (mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "type: unknown option -- %c\n", mrsh_optopt);
	_mrsh_optind = 0;
	if (_mrsh_getopt(argc, argv, ":") != -1) {
		fprintf(stderr, "type: unknown option -- %c\n", _mrsh_optopt);
		fprintf(stderr, type_usage);
		return 1;
	}
	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		fprintf(stderr, type_usage);
		return 1;
	}

	bool error = false;
	for (int i = mrsh_optind; i < argc; ++i) {
	for (int i = _mrsh_optind; i < argc; ++i) {
		char *name = argv[i];

		char *alias = mrsh_hashtable_get(&priv->aliases, name);

M builtin/ulimit.c => builtin/ulimit.c +6 -6
@@ 2,7 2,6 @@
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <mrsh/getopt.h>
#include <mrsh/shell.h>
#include <stdio.h>
#include <stdlib.h>


@@ 10,13 9,14 @@
#include <sys/resource.h>
#include <sys/time.h>
#include "builtin.h"
#include "mrsh_getopt.h"

static const char ulimit_usage[] = "usage: ulimit [-f] [blocks]\n";

int builtin_ulimit(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":f")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":f")) != -1) {
		if (opt == 'f') {
			// Nothing here
		} else {


@@ 25,8 25,8 @@ int builtin_ulimit(struct mrsh_state *state, int argc, char *argv[]) {
		}
	}

	if (mrsh_optind == argc - 1) {
		char *arg = argv[mrsh_optind];
	if (_mrsh_optind == argc - 1) {
		char *arg = argv[_mrsh_optind];
		char *end;
		long int new_limit = strtol(arg, &end, 10);
		if (end == arg || end[0] != '\0') {


@@ 41,7 41,7 @@ int builtin_ulimit(struct mrsh_state *state, int argc, char *argv[]) {
			perror("setrlimit");
			return 1;
		}
	} else if (mrsh_optind == argc) {
	} else if (_mrsh_optind == argc) {
		struct rlimit old = { 0 };
		if (getrlimit(RLIMIT_FSIZE, &old) != 0) {
			perror("getrlimit");

M builtin/umask.c => builtin/umask.c +7 -7
@@ 1,11 1,11 @@
#define _POSIX_C_SOURCE 200809L
#include <mrsh/builtin.h>
#include <mrsh/getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "builtin.h"
#include "mrsh_getopt.h"

static const char umask_usage[] = "usage: umask [-S] [mode]\n";



@@ 162,23 162,23 @@ int builtin_umask(struct mrsh_state *state, int argc, char *argv[]) {
	mode_t mode;
	bool umask_symbolic = false;

	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;

	while ((opt = mrsh_getopt(argc, argv, ":S")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":S")) != -1) {
		switch (opt) {
		case 'S':
			umask_symbolic = true;
			break;

		default:
			fprintf(stderr, "Unknown option -- '%c'\n", mrsh_optopt);
			fprintf(stderr, "Unknown option -- '%c'\n", _mrsh_optopt);
			fprintf(stderr, umask_usage);
			return 1;
		}
	}

	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		mode = umask_current_mask();

		if (umask_symbolic) {


@@ 191,10 191,10 @@ int builtin_umask(struct mrsh_state *state, int argc, char *argv[]) {
	}

	char *endptr;
	mode = strtol(argv[mrsh_optind], &endptr, 8);
	mode = strtol(argv[_mrsh_optind], &endptr, 8);

	if (*endptr != '\0') {
		if (!umask_mode(&mode, argv[mrsh_optind])) {
		if (!umask_mode(&mode, argv[_mrsh_optind])) {
			fprintf(stderr, umask_usage);
			return 1;
		}

M builtin/unalias.c => builtin/unalias.c +7 -7
@@ 1,10 1,10 @@
#define _POSIX_C_SOURCE 200809L
#include <mrsh/builtin.h>
#include <mrsh/getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/shell.h"

static const char unalias_usage[] = "usage: unalias -a|alias-name...\n";


@@ 19,22 19,22 @@ int builtin_unalias(struct mrsh_state *state, int argc, char *argv[]) {

	bool all = false;

	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":a")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":a")) != -1) {
		switch (opt) {
		case 'a':
			all = true;
			break;
		default:
			fprintf(stderr, "unalias: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "unalias: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, unalias_usage);
			return 1;
		}
	}

	if (all) {
		if (mrsh_optind < argc) {
		if (_mrsh_optind < argc) {
			fprintf(stderr, unalias_usage);
			return 1;
		}


@@ 43,12 43,12 @@ int builtin_unalias(struct mrsh_state *state, int argc, char *argv[]) {
		return 0;
	}

	if (mrsh_optind == argc) {
	if (_mrsh_optind == argc) {
		fprintf(stderr, unalias_usage);
		return 1;
	}

	for (int i = mrsh_optind; i < argc; ++i) {
	for (int i = _mrsh_optind; i < argc; ++i) {
		free(mrsh_hashtable_del(&priv->aliases, argv[i]));
	}
	return 0;

M builtin/unset.c => builtin/unset.c +6 -6
@@ 1,10 1,10 @@
#define _POSIX_C_SOURCE 200809L
#include <mrsh/builtin.h>
#include <mrsh/getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/shell.h"

static const char unset_usage[] = "usage: unset [-fv] name...\n";


@@ 14,9 14,9 @@ int builtin_unset(struct mrsh_state *state, int argc, char *argv[]) {

	bool funcs = false;

	mrsh_optind = 0;
	_mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":fv")) != -1) {
	while ((opt = _mrsh_getopt(argc, argv, ":fv")) != -1) {
		switch (opt) {
		case 'f':
			funcs = true;


@@ 25,16 25,16 @@ int builtin_unset(struct mrsh_state *state, int argc, char *argv[]) {
			funcs = false;
			break;
		default:
			fprintf(stderr, "unset: unknown option -- %c\n", mrsh_optopt);
			fprintf(stderr, "unset: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, unset_usage);
			return 1;
		}
	}
	if (mrsh_optind >= argc) {
	if (_mrsh_optind >= argc) {
		fprintf(stderr, unset_usage);
		return 1;
	}
	for (int i = mrsh_optind; i < argc; ++i) {
	for (int i = _mrsh_optind; i < argc; ++i) {
		if (!funcs) {
			uint32_t prev_attribs = 0;
			if (mrsh_env_get(state, argv[i], &prev_attribs)) {

M getopt.c => getopt.c +31 -31
@@ 1,37 1,37 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <mrsh/getopt.h>
#include <stdio.h>
#include "mrsh_getopt.h"

char *mrsh_optarg = NULL;
int mrsh_optind = 1;
int mrsh_opterr = 1;
int mrsh_optopt = 0;
int mrsh_optpos = 1;
char *_mrsh_optarg = NULL;
int _mrsh_optind = 1;
int _mrsh_opterr = 1;
int _mrsh_optopt = 0;
int _mrsh_optpos = 1;

int mrsh_getopt(int argc, char *const argv[], const char *optstring) {
int _mrsh_getopt(int argc, char *const argv[], const char *optstring) {
	assert(argv[argc] == NULL);
	mrsh_optarg = NULL;
	_mrsh_optarg = NULL;

	if (mrsh_optind == 0) {
		mrsh_optind = 1;
		mrsh_optpos = 1;
	if (_mrsh_optind == 0) {
		_mrsh_optind = 1;
		_mrsh_optpos = 1;
	}

	if (mrsh_optind >= argc) {
	if (_mrsh_optind >= argc) {
		return -1;
	}

	if (argv[mrsh_optind][0] != '-') {
	if (argv[_mrsh_optind][0] != '-') {
		return -1;
	}

	if (argv[mrsh_optind][1] == '\0') {
	if (argv[_mrsh_optind][1] == '\0') {
		return -1;
	}

	if (argv[mrsh_optind][1] == '-') {
		mrsh_optind++;
	if (argv[_mrsh_optind][1] == '-') {
		_mrsh_optind++;
		return -1;
	}



@@ 40,44 40,44 @@ int mrsh_getopt(int argc, char *const argv[], const char *optstring) {
		c++;
	}

	mrsh_optopt = 0;
	int opt = argv[mrsh_optind][mrsh_optpos];
	_mrsh_optopt = 0;
	int opt = argv[_mrsh_optind][_mrsh_optpos];
	for (; *c != '\0'; c++) {
		if (*c != opt) {
			continue;
		}

		if (c[1] != ':') {
			if (argv[mrsh_optind][mrsh_optpos + 1] == '\0') {
				mrsh_optind++;
				mrsh_optpos = 1;
			if (argv[_mrsh_optind][_mrsh_optpos + 1] == '\0') {
				_mrsh_optind++;
				_mrsh_optpos = 1;
			} else {
				mrsh_optpos++;
				_mrsh_optpos++;
			}
			return opt;
		}

		if (argv[mrsh_optind][mrsh_optpos + 1] != '\0') {
			mrsh_optarg = &argv[mrsh_optind][mrsh_optpos + 1];
		if (argv[_mrsh_optind][_mrsh_optpos + 1] != '\0') {
			_mrsh_optarg = &argv[_mrsh_optind][_mrsh_optpos + 1];
		} else {
			if (mrsh_optind + 2 > argc) {
				mrsh_optopt = opt;
				if (mrsh_opterr != 0 && optstring[0] != ':') {
			if (_mrsh_optind + 2 > argc) {
				_mrsh_optopt = opt;
				if (_mrsh_opterr != 0 && optstring[0] != ':') {
					fprintf(stderr, "%s: Option '%c' requires an argument.\n",
						argv[0], mrsh_optopt);
						argv[0], _mrsh_optopt);
				}

				return optstring[0] == ':' ? ':' : '?';
			}

			mrsh_optarg = argv[++mrsh_optind];
			_mrsh_optarg = argv[++_mrsh_optind];
		}

		mrsh_optind++;
		_mrsh_optind++;
		return opt;
	}

	if (mrsh_opterr != 0 && optstring[0] != ':') {
	if (_mrsh_opterr != 0 && optstring[0] != ':') {
		fprintf(stderr, "%s: Option '%c' not found.\n", argv[0], opt);
	}


R include/mrsh/getopt.h => include/mrsh_getopt.h +3 -3
@@ 1,9 1,9 @@
#ifndef MRSH_GETOPT_H
#define MRSH_GETOPT_H

extern char *mrsh_optarg;
extern int mrsh_opterr, mrsh_optind, mrsh_optopt;
extern char *_mrsh_optarg;
extern int _mrsh_opterr, _mrsh_optind, _mrsh_optopt;

int mrsh_getopt(int argc, char * const argv[], const char *optstring);
int _mrsh_getopt(int argc, char * const argv[], const char *optstring);

#endif