diff options
| author | Douglas B. Rumbaugh <doug@douglasrumbaugh.com> | 2025-10-31 23:41:32 -0400 |
|---|---|---|
| committer | Douglas B. Rumbaugh <doug@douglasrumbaugh.com> | 2025-10-31 23:41:32 -0400 |
| commit | 06a02a3a50baf261a0f1c998bfd02269c3ed45de (patch) | |
| tree | 00aa66e09a31b2563221c385e5ac129a57082729 /src/hush.c | |
| download | hush-06a02a3a50baf261a0f1c998bfd02269c3ed45de.tar.gz | |
Initial commit
Diffstat (limited to 'src/hush.c')
| -rw-r--r-- | src/hush.c | 106 |
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, "$ "); + } +} |