aboutsummaryrefslogtreecommitdiffstats
path: root/src/hush.c
diff options
context:
space:
mode:
authorDouglas B. Rumbaugh <doug@douglasrumbaugh.com>2025-10-31 23:41:32 -0400
committerDouglas B. Rumbaugh <doug@douglasrumbaugh.com>2025-10-31 23:41:32 -0400
commit06a02a3a50baf261a0f1c998bfd02269c3ed45de (patch)
tree00aa66e09a31b2563221c385e5ac129a57082729 /src/hush.c
downloadhush-06a02a3a50baf261a0f1c998bfd02269c3ed45de.tar.gz
Initial commit
Diffstat (limited to 'src/hush.c')
-rw-r--r--src/hush.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/hush.c b/src/hush.c
new file mode 100644
index 0000000..478103f
--- /dev/null
+++ b/src/hush.c
@@ -0,0 +1,106 @@
+/*
+ * hush -- the HU Shell
+ *
+ * A minimal shell for CISC 301, Operating Systems
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include "config.h"
+#include "lexer.h"
+#include "command.h"
+
+FILE *open_input(int argc, char **argv) {
+ FILE *input_file = (argc > 1) ? fopen(argv[1], "r") : stdin;
+ if (!input_file) {
+ fprintf(stderr, "ERROR: Failed to open input file %s\n", argv[1]);
+ exit(EXIT_FAILURE);
+ }
+
+ return input_file;
+}
+
+static size_t get_command_len(char *cmdstr) {
+ size_t len = strlen(cmdstr);
+ if (cmdstr[len - 1] != '\n') {
+ len = 0;
+ }
+
+ return len;
+}
+
+int main(int argc, char **argv) {
+ FILE *input_file = open_input(argc, argv);
+ char buffer[MAX_LINE_LEN];
+
+ fprintf(stdout, "$ ");
+ while (fgets(buffer, MAX_LINE_LEN, input_file)) {
+ char *cmdstr = trim(buffer);
+ if (!cmdstr) {
+ fprintf(stderr, "ERROR: Specified command is too long\n");
+ goto draw_prompt;
+ }
+
+ if (strlen(cmdstr) == 0) {
+ goto draw_prompt;
+ }
+
+ token *parsed_cmd;
+ if (!(parsed_cmd = parse_command(cmdstr))) {
+ fprintf(stderr, "ERROR: Failed to parse command\n");
+ goto draw_prompt;
+ }
+
+ {
+ token *error;
+ if ((error = validate_command(parsed_cmd))) {
+ fprintf(stderr, "ERROR: Invalid syntax near %s\n", error->text);
+ print_parsed_command(stdout, parsed_cmd);
+ goto free_tokens;
+ }
+ }
+
+ // print_parsed_command(stdout, parsed_cmd);
+
+ if (parsed_cmd->type == TKN_VARKEY) {
+ /* handle variable creation */
+ goto free_tokens;
+ }
+
+ size_t commands;
+ command *cmds;
+ if (!(cmds = commands_from_tokens(parsed_cmd, &commands ))) {
+ fprintf(stderr, "ERROR: Unable to create commands from tokens");
+ goto free_tokens;
+ }
+
+ // print_commands(stdout, cmds);
+
+ for (command *cmd = cmds; cmd; cmd = cmd->next) {
+ pid_t result = execute_command(cmd);
+ if (result < 0) {
+ break;
+ }
+ }
+
+ for (command *cmd = cmds; cmd; cmd = cmd->next) {
+ if (cmd->pid > 0) {
+ waitpid(cmd->pid, NULL, 0);
+ }
+ }
+
+ free_tokens:
+ destroy_tokens(parsed_cmd);
+
+ free_commands:
+ destroy_commands(cmds);
+
+ draw_prompt:
+ fprintf(stdout, "$ ");
+ }
+}