From ddcf611815c145b1fadca042e65648a7a81cc497 Mon Sep 17 00:00:00 2001 From: "Douglas B. Rumbaugh" Date: Sat, 1 Nov 2025 14:53:14 -0400 Subject: Added variable support --- src/command.c | 10 +++++++++- src/hush.c | 38 +++++++++++++++++++++++++++++++++++--- src/variables.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 src/variables.c (limited to 'src') diff --git a/src/command.c b/src/command.c index 20b00b1..3d63121 100644 --- a/src/command.c +++ b/src/command.c @@ -119,7 +119,15 @@ pid_t execute_command(command *cmd) { close(cmd->pipe[1]); } - execvp(cmd->command, cmd->args); + /* + * NOTE: discarding the const qualifier here is okay because either + * 1) exec fails, in which case the process is aborted immediately + * 2) exec succeeds, in which case the memory is released immediately + * + * In either case, the args won't be accessed again. + */ + execvp(cmd->command, (char**)cmd->args); + perror("Could not run command"); exit(EXIT_FAILURE); } else if (res < 0) { diff --git a/src/hush.c b/src/hush.c index 557ae1e..0d25244 100644 --- a/src/hush.c +++ b/src/hush.c @@ -14,6 +14,7 @@ #include "config.h" #include "lexer.h" #include "command.h" +#include "variables.h" FILE *open_input(int argc, char **argv) { FILE *input_file = (argc > 1) ? fopen(argv[1], "r") : stdin; @@ -34,10 +35,38 @@ static size_t get_command_len(char *cmdstr) { return len; } +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]); + } + } + + if (is_variable(cmd->outfile)) { + cmd->outfile = get_variable(cmd->outfile); + } + + if (is_variable(cmd->infile)) { + cmd->infile = get_variable(cmd->infile); + } + + fprintf(stderr, "After substitution\n"); + print_commands(stderr, cmd); + } +} + int main(int argc, char **argv) { FILE *input_file = open_input(argc, argv); char buffer[MAX_LINE_LEN]; + if (!init_variable_store()) { + fprintf(stderr, "ERROR: Failed to initialize variable store\n"); + exit(EXIT_FAILURE); + } + fprintf(stdout, "$ "); while (fgets(buffer, MAX_LINE_LEN, input_file)) { char *cmdstr = trim(buffer); @@ -68,7 +97,9 @@ int main(int argc, char **argv) { // print_parsed_command(stdout, parsed_cmd); if (parsed_cmd->type == TKN_VARKEY) { - /* handle variable creation */ + if (!add_variable(parsed_cmd->text, parsed_cmd->next->text)) { + fprintf(stderr, "ERROR: Failed to create variable\n"); + } goto free_tokens; } @@ -79,6 +110,7 @@ int main(int argc, char **argv) { goto free_tokens; } + variable_substitution(cmds); for (command *cmd = cmds; cmd; cmd = cmd->next) { pid_t result = execute_command(cmd); @@ -91,9 +123,7 @@ int main(int argc, char **argv) { for (command *cmd = cmds; cmd; cmd = cmd->next) { if (cmd->pid > 0) { - fprintf(stderr, "Waiting for %d\n", cmd->pid); waitpid(cmd->pid, NULL, 0); - fprintf(stderr, "%d completed\n", cmd->pid); } } @@ -107,4 +137,6 @@ int main(int argc, char **argv) { draw_prompt: fprintf(stdout, "$ "); } + + destroy_variable_store(); } diff --git a/src/variables.c b/src/variables.c new file mode 100644 index 0000000..c7cc4da --- /dev/null +++ b/src/variables.c @@ -0,0 +1,57 @@ +/* + * + */ + +#include "variables.h" +#include "strmap.h" + +static strmap *map; + +bool init_variable_store(void) { + map = strmap_create(hash_key); + return map; +} + +bool add_variable(const char *key, const char *val) { + if (strmap_put(map, key, val) != STRMAP_OK) { + return false; + } + + return true; +} + +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); + switch (stat) { + case STRMAP_OK: + break; + case STRMAP_NOTFOUND: + val = getenv(key); + break; + default: + val = NULL; + break; + } + + val = (val) ? val : ""; + fprintf(stderr, "Value is: %s\n", val); + + return val; +} + +bool promote_variable_to_env(const char *key) { + const char *val = get_variable(key); + if (!val) { + val = ""; + } + + return !setenv(key, val, 1); +} + +void destroy_variable_store() { + strmap_destroy(map); +} -- cgit v1.2.3