aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--include/builtin.h20
-rw-r--r--src/builtin.c75
-rw-r--r--src/hush.c18
-rw-r--r--src/variables.c7
5 files changed, 108 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index fbe4e9d..c860407 100644
--- a/Makefile
+++ b/Makefile
@@ -5,8 +5,8 @@ LIBMAP_LIB := $(LIBMAP_DIR)/lib/libmap.a
$(LIBMAP_LIB): $(LIBMAP_DIR)/Makefile
make -C $(LIBMAP_DIR) lib/libmap.a
-bin/hush: build/lexer.o build/command.o src/hush.c build build/variables.o $(LIBMAP_LIB)
- gcc -Iinclude -I$(LIBMAP_DIR)/include build/lexer.o build/command.o build/variables.o src/hush.c $(LIBMAP_LIB) -ggdb -o bin/hush
+bin/hush: build/lexer.o build/command.o src/hush.c build build/variables.o build/builtin.o $(LIBMAP_LIB)
+ gcc -Iinclude -I$(LIBMAP_DIR)/include build/lexer.o build/command.o build/variables.o build/builtin.o src/hush.c $(LIBMAP_LIB) -ggdb -o bin/hush
build/lexer.o: include/lexer.h src/lexer.c build
gcc -Iinclude -c src/lexer.c -ggdb -o build/lexer.o
@@ -17,6 +17,10 @@ build/command.o: include/lexer.h include/command.h src/command.c
build/variables.o: include/variables.h
gcc -Iinclude -I$(LIBMAP_DIR)/include -c src/variables.c -ggdb -o build/variables.o
+build/builtin.o: include/builtin.h include/variables.h
+ gcc -Iinclude -I$(LIBMAP_DIR)/include -c src/builtin.c -ggdb -o build/builtin.o
+
+
.PHONY: build clean
build:
-mkdir build
diff --git a/include/builtin.h b/include/builtin.h
new file mode 100644
index 0000000..1c99ef5
--- /dev/null
+++ b/include/builtin.h
@@ -0,0 +1,20 @@
+/*
+ *
+ */
+#ifndef H_HUSH_BUILTIN
+#define H_HUSH_BUILTIN
+
+#include <limits.h>
+#include <unistd.h>
+
+#include "command.h"
+#include "variables.h"
+
+/*
+ * Check if the provided command corresponds with a known built-in
+ * function. If so, run the builtin and return true. If not, return
+ * false.
+ */
+bool run_builtin(command *cmd);
+
+#endif
diff --git a/src/builtin.c b/src/builtin.c
new file mode 100644
index 0000000..f22ce33
--- /dev/null
+++ b/src/builtin.c
@@ -0,0 +1,75 @@
+/*
+ *
+ */
+#include "builtin.h"
+#include "variables.h"
+#include <unistd.h>
+
+struct builtin {
+ char *name;
+ int (*builtin_func)(const char **);
+};
+
+static int builtin_cd(const char *args[]) {
+ const char *dir = (args[1]) ? args[1] : get_variable("$HOME");
+ int res = chdir(dir);
+
+ if (res != 0) {
+ perror("cd:");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int builtin_export(const char *args[]) {
+ const char *key = args[1];
+
+ if (!key) {
+ fprintf(stderr, "export: no variable name specified\n");
+ return 0;
+ }
+
+ if (!promote_variable_to_env(key)) {
+ perror("export:");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int builtin_pwd(const char *args[]) {
+ char buffer[PATH_MAX];
+ char *path = getcwd(buffer, PATH_MAX);
+ if (path) {
+ fprintf(stdout, "%s\n", path);
+ return 1;
+ }
+
+ perror("pwd:");
+ return 0;
+}
+
+static int builtin_exit(const char *args[]) { exit(EXIT_SUCCESS); }
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
+static struct builtin builtin_lookup[] = {
+ {.name = "cd", .builtin_func = builtin_cd},
+ {.name = "export", .builtin_func = builtin_export},
+ {.name = "pwd", .builtin_func = builtin_pwd},
+ {.name = "exit", .builtin_func = builtin_exit}};
+
+static const size_t BUILTIN_CNT = ARRAY_SIZE(builtin_lookup);
+
+bool run_builtin(command *cmd) {
+
+ for (size_t i = 0; i < BUILTIN_CNT; i++) {
+ if (!strcmp(cmd->command, builtin_lookup[i].name)) {
+ builtin_lookup[i].builtin_func(cmd->args);
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/src/hush.c b/src/hush.c
index 0d25244..2d40aa7 100644
--- a/src/hush.c
+++ b/src/hush.c
@@ -15,6 +15,7 @@
#include "lexer.h"
#include "command.h"
#include "variables.h"
+#include "builtin.h"
FILE *open_input(int argc, char **argv) {
FILE *input_file = (argc > 1) ? fopen(argv[1], "r") : stdin;
@@ -37,8 +38,6 @@ static size_t get_command_len(char *cmdstr) {
void variable_substitution(command *cmds) {
for (command *cmd = cmds; cmd; cmd = cmd->next) {
- fprintf(stderr, "Before substitution\n");
- print_commands(stderr, cmd);
for (size_t i=0; i < MAX_ARGUMENT_CNT + 1; i++) {
if (is_variable(cmd->args[i])) {
cmd->args[i] = get_variable(cmd->args[i]);
@@ -52,9 +51,6 @@ void variable_substitution(command *cmds) {
if (is_variable(cmd->infile)) {
cmd->infile = get_variable(cmd->infile);
}
-
- fprintf(stderr, "After substitution\n");
- print_commands(stderr, cmd);
}
}
@@ -94,8 +90,6 @@ int main(int argc, char **argv) {
}
}
- // print_parsed_command(stdout, parsed_cmd);
-
if (parsed_cmd->type == TKN_VARKEY) {
if (!add_variable(parsed_cmd->text, parsed_cmd->next->text)) {
fprintf(stderr, "ERROR: Failed to create variable\n");
@@ -113,14 +107,14 @@ int main(int argc, char **argv) {
variable_substitution(cmds);
for (command *cmd = cmds; cmd; cmd = cmd->next) {
- pid_t result = execute_command(cmd);
- if (result < 0) {
- break;
+ if (!run_builtin(cmd)) {
+ pid_t result = execute_command(cmd);
+ if (result < 0) {
+ break;
+ }
}
}
- // print_commands(stdout, cmds);
-
for (command *cmd = cmds; cmd; cmd = cmd->next) {
if (cmd->pid > 0) {
waitpid(cmd->pid, NULL, 0);
diff --git a/src/variables.c b/src/variables.c
index c7cc4da..c478d9d 100644
--- a/src/variables.c
+++ b/src/variables.c
@@ -21,8 +21,6 @@ bool add_variable(const char *key, const char *val) {
}
const char *get_variable(const char *key) {
- fprintf(stderr, "Key is: %s\n", key);
-
key += (key[0] == '$');
const char *val;
strmap_status stat = strmap_get(map, key, &val);
@@ -37,10 +35,7 @@ const char *get_variable(const char *key) {
break;
}
- val = (val) ? val : "";
- fprintf(stderr, "Value is: %s\n", val);
-
- return val;
+ return (val) ? val : "";
}
bool promote_variable_to_env(const char *key) {