None: Add hash builtin. v1 PROPOSED

dragnel: 1
 Add hash builtin.

 9 files changed, 70 insertions(+), 0 deletions(-)
View this thread in the archives
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/%3CQApj-cWDqHPJK-eYD88z-4WkPuDx72S_X6VGgEHFYpltpKF7xlcm6I_gQuskSSTf--YAECR7UFNBh-tVitdge1t7A9N3XovLlmVHNPTQ4Mo%3D%40protonmail.com%3E/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