~emersion/mrsh-dev

Add hash builtin. v1 PROPOSED

dragnel: 1
 Add hash builtin.

 9 files changed, 70 insertions(+), 0 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/4095/mbox | git am -3
Learn more about email & git

[PATCH] Add hash builtin. Export this patch

---
 builtin/builtin.c    |  1 +
 builtin/command.c    |  1 +
 builtin/hash.c       | 47 ++++++++++++++++++++++++++++++++++++++++++++
 include/builtin.h    |  1 +
 include/mrsh/shell.h |  1 +
 meson.build          |  1 +
 shell/path.c         |  7 +++++++
 test/hash.sh         | 10 ++++++++++
 test/meson.build     |  1 +
 9 files changed, 70 insertions(+)
 create mode 100644 builtin/hash.c
 create mode 100644 test/hash.sh

diff --git a/builtin/builtin.c b/builtin/builtin.c
index aaeac2b..8cea1a0 100644
--- a/builtin/builtin.c
@@ -26,6 +26,7 @@ static const struct builtin builtins[] = {
	{ "false", builtin_false, false },
	{ "fg", builtin_fg, false },
	{ "getopts", builtin_getopts, false },
	{ "hash", builtin_hash, false },
	{ "pwd", builtin_pwd, false },
	{ "read", builtin_read, false },
	{ "readonly", builtin_export, true },
diff --git a/builtin/command.c b/builtin/command.c
index 2a09af4..4a9c819 100644
--- a/builtin/command.c
@@ -7,6 +7,7 @@
#include <sys/stat.h>
#include "shell/path.h"
#include "mrsh/builtin.h"
#include "builtin.h"

static const char command_usage[] = "usage: command [-v|-V|-p] "
	"command_name [argument...]\n";
diff --git a/builtin/hash.c b/builtin/hash.c
new file mode 100644
index 0000000..43182b2
--- /dev/null
@@ -0,0 +1,47 @@
#define _POSIX_C_SOURCE 200809L
#include "parser.h"
#include "mrsh/getopt.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "shell/path.h"
#include "mrsh/builtin.h"
#include "builtin.h"

static const char hash_usage[] = "usage: hash [-r]";

static void state_string_finish_iterator(const char *key, void *value,
		void *user_data) {
	struct mrsh_hashtable *table = user_data;
	mrsh_hashtable_del(table, key);
}

static void print_hash_iterator(const char *key, void *_value,
		void *user_data) {
	print_escaped((char *)_value);
	printf("\n");
}

int builtin_hash(struct mrsh_state *state, int argc, char *argv[]) {
	mrsh_optind = 0;
	int opt;
	while ((opt = mrsh_getopt(argc, argv, ":r")) != -1) {
		if (opt == 'r') {
			mrsh_hashtable_for_each(&state->hash,
				state_string_finish_iterator, &state->hash);
			mrsh_hashtable_finish(&state->hash);
			return 0;
		} else {
			fprintf(stderr, "%s", hash_usage);
			return 1;
		}
	}
	
	if (mrsh_optind == argc) {
		mrsh_hashtable_for_each(&state->hash, print_hash_iterator, NULL);
		return 0;
	}
	return 0;
}

diff --git a/include/builtin.h b/include/builtin.h
index fb1933a..9a01988 100644
--- a/include/builtin.h
+++ b/include/builtin.h
@@ -19,6 +19,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_false(struct mrsh_state *state, int argc, char *argv[]);
int builtin_fg(struct mrsh_state *state, int argc, char *argv[]);
int builtin_hash(struct mrsh_state *state, int argc, char *argv[]);
int builtin_getopts(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[]);
diff --git a/include/mrsh/shell.h b/include/mrsh/shell.h
index d6ef789..101ded8 100644
--- a/include/mrsh/shell.h
+++ b/include/mrsh/shell.h
@@ -92,6 +92,7 @@ struct mrsh_state {
	struct mrsh_hashtable variables; // struct mrsh_variable *
	struct mrsh_hashtable aliases; // char *
	struct mrsh_hashtable functions; // struct mrsh_function *
	struct mrsh_hashtable hash; // char *
	struct mrsh_array processes;
	int last_status;

diff --git a/meson.build b/meson.build
index e9b43e8..8430d2d 100644
--- a/meson.build
+++ b/meson.build
@@ -85,6 +85,7 @@ lib_mrsh = library(
		'builtin/false.c',
		'builtin/fg.c',
		'builtin/getopts.c',
		'builtin/hash.c',
		'builtin/pwd.c',
		'builtin/read.c',
		'builtin/set.c',
diff --git a/shell/path.c b/shell/path.c
index 67a29b9..035559e 100644
--- a/shell/path.c
+++ b/shell/path.c
@@ -21,6 +21,12 @@ const char *expand_path(struct mrsh_state *state, const char *file, bool exec) {
	if (!pathe) {
		return NULL;
	}

	const char *look_hash = mrsh_hashtable_get(&state->hash, file);
	if(look_hash != NULL) {
		return look_hash;
	}

	char *basedir = strtok(pathe, ":");
	while (basedir) {
		int blen = strlen(basedir);
@@ -34,6 +40,7 @@ const char *expand_path(struct mrsh_state *state, const char *file, bool exec) {
			goto next;
		}
		if (access(path, exec ? X_OK : R_OK) != -1) {
			mrsh_hashtable_set(&state->hash, file, strdup(path));
			free(pathe);
			return path;
		}
diff --git a/test/hash.sh b/test/hash.sh
new file mode 100644
index 0000000..582ecf5
--- /dev/null
+++ b/test/hash.sh
@@ -0,0 +1,10 @@
#!/bin/sh -e

ls
touch foobar
rm foobar
hash
hash -r
ls
hash

diff --git a/test/meson.build b/test/meson.build
index 513b3f3..cb58c9d 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -7,6 +7,7 @@ test_files = [
	'case.sh',
	'for.sh',
	'function.sh',
	'hash.sh',
	'loop.sh',
	'subshell.sh',
	'ulimit.sh',
-- 
2.17.1
View this thread in the archives