From 02b2f871f67d203ed64bfd1f2cf38120769f0151 Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Sun, 5 Sep 2021 20:50:09 +0300 Subject: [PATCH 01/10] Fix CMake warning --- CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aeba5d2..9a11c46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,6 @@ -# set the project name -project(fdbox) - -# add the executable cmake_minimum_required(VERSION 3.10) +# set the project name project(fdbox VERSION 0.1) include(cmake/CPM.cmake) From 302f160f29fae758d00d155e1700b2eac76358b4 Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Wed, 11 Aug 2021 19:36:25 +0300 Subject: [PATCH 02/10] Lets start working on batch file support 1. move `file_exists` to a global scope, instead of `if` 1. prompt is printed only on interactive shells. 1. We can start a new batch file (no `call` support yet). We can even nest batches one inside another. 1. Exiting from a batch file is iffie. I need to re-think how this works. --- dos/command.c | 87 ++++++++++++++++++++++++++++++++++++++++---------- dos/if.c | 10 +----- lib/strextra.c | 17 ++++++++++ lib/strextra.h | 3 ++ 4 files changed, 92 insertions(+), 25 deletions(-) diff --git a/dos/command.c b/dos/command.c index 166fe53..97fc4ca 100644 --- a/dos/command.c +++ b/dos/command.c @@ -17,13 +17,15 @@ For license - read license.txt #include "dos/prompt.h" #include "fdbox.h" -#ifdef __MSDOS__ +#if defined(__TURBOC__) +#include #include "lib/tc202/stdbool.h" #include "lib/tc202/stdextra.h" #endif #ifdef _POSIX_C_SOURCE #include +#include #endif #ifdef __WIN32__ @@ -43,6 +45,7 @@ static void command_shell_config_init(struct command_shell_config *config); static bool command_shell_config_parse(int argc, char *argv[], struct command_shell_config *config); static void command_shell_config_print(const struct command_shell_config *config); static void command_shell_print_extended_help(); +static char* find_batch_in_path(const char* batch_file_name); /* TODO - I am unsure if this is the best way to tell the main loop * we should exit. For now it works @@ -93,10 +96,13 @@ int command_execute_line_new(const char *line) { int command_execute_line_old(char *line) { size_t c_argc; char *c_argv[256]; + const char* command_name; bool parsed_ok; + bool is_silent = false; /* TODO use global state from echo! */ struct applet *cmd; int code; extern struct applet commands[]; + bool is_interactive = isatty(fileno(stdin)); /* this function will not modify the args, so its marked `const * but some commands (date/time) will modify the args instead of making copies @@ -111,21 +117,57 @@ int command_execute_line_old(char *line) { return EXIT_SUCCESS; } + command_name = c_argv[0]; + if (*command_name == '@') { + is_silent = !is_silent; + command_name = command_name+1; + } + /* Special handling for exit, as it should break the main loop */ - if (strcasecmp(c_argv[0], "exit") == 0) { - return EXIT_FAILURE; + + if (strcasecmp(command_name, "exit") == 0) { + if (is_interactive) { + printf("interactive shell, not exit, just redirecting stdin back\n"); + if ((freopen("", "r", stdin) == NULL)) { + fprintf(stderr, "Error reopening stdin\n"); + abort(); + } + } + else { + printf("exit shell!\n"); + return EXIT_SUCCESS; + } } cmd = find_applet(CASE_INSENSITVE, c_argv[0], commands); - if (cmd != NULL) { + /* ok, this fails, since we modify the original line, this will get fixed soon */ + if (!is_silent && !is_interactive) { + puts(line); + } + if (cmd != NULL) { code = cmd->handler(c_argc, c_argv); errno = code; if (code != EXIT_SUCCESS) { fprintf(stderr, "Command failed (%d)\n", code); } } else { - fprintf(stderr, "Command not found\n"); - errno = ENOENT; + /* is it a batch file ? */ + char* batch_file_path = find_batch_in_path(command_name); + bool ok = false; + + if (batch_file_path != NULL) { + if (freopen(batch_file_path, "r", stdin)) { + ok = true; + } + } else { + /* execvp */ + } + + if (!ok) { + fprintf(stderr, "Command not found\n"); + errno = ENOENT; + } + free(batch_file_path); } return EXIT_SUCCESS; @@ -146,20 +188,25 @@ int command_command(int argc, char *argv[]) { command_shell_print_extended_help(); return EXIT_SUCCESS; } - do { - char prompt[256]; - const char *t; - - t = getenv("PROMPT"); - if (t == NULL) { - command_prompt(1, NULL); + bool is_interactive = isatty(fileno(stdin)); + if (is_interactive) { + char prompt[256]; + const char *t; t = getenv("PROMPT"); + if (t == NULL) { + command_prompt(1, NULL); + t = getenv("PROMPT"); + } + get_prompt(t, prompt, 256); + printf("%s", prompt); } - get_prompt(t, prompt, 256); - printf("%s", prompt); - fgets(line, 1024, stdin); + if (feof(stdin)) { + printf("EOF, exit!"); + break; + } + fgets(line, 1024, stdin); if ((pos = strchr(line, '\n')) != NULL) { *pos = '\0'; } @@ -207,3 +254,11 @@ static void command_shell_print_extended_help() { printf(" Runs an interactive shell \n"); printf(" TODO: properly implement the command.com swithces \n"); } + +static char* find_batch_in_path(const char* batch_file_name) +{ + if (file_exists(batch_file_name)) { + return strdup(batch_file_name); + } + return NULL; +} diff --git a/dos/if.c b/dos/if.c index a5ee0a5..ad1a2df 100644 --- a/dos/if.c +++ b/dos/if.c @@ -32,7 +32,6 @@ For license - read license.txt #include #endif -static bool if_file_exists(const char *path); static char *find_if_command(int argc, char *argv[]); static char *find_else_command(int argc, char *argv[]); @@ -51,7 +50,7 @@ int command_if(int argc, char *argv[]) { if (strcasecmp(argv[arg_index], "exist") == 0) { arg_index++; - evaluated_value = if_file_exists(argv[arg_index]); + evaluated_value = file_exists(argv[arg_index]); } else if (strcasecmp(argv[arg_index], "ERRORLEVEL") == 0) { arg_index++; if (argv[arg_index] != NULL && arg_index < argc) { @@ -112,13 +111,6 @@ int command_if(int argc, char *argv[]) { const char *help_if() { return "Conditionally execute a command"; } -/* this implementation also returns true for directories, is this OK? */ -static bool if_file_exists(const char *path) { - struct stat path_stat; - int rc = stat(path, &path_stat); - return rc == 0; -} - /* This function concatinates all arguments for the * positive resolution of "if". * The input is the first token to be added diff --git a/lib/strextra.c b/lib/strextra.c index b56727c..201f082 100644 --- a/lib/strextra.c +++ b/lib/strextra.c @@ -2,6 +2,17 @@ #include #include +#ifdef _POSIX_C_SOURCE +#include +#endif + +#if defined(__TURBOC__) +#include "lib/tc202/dos-glob.h" +#include "lib/tc202/stdbool.h" +#include "lib/tc202/stdextra.h" +#include +#endif + const char *str_bool(bool b) { return b ? "true" : "false"; } char *str_to_lower(char *s) { @@ -54,6 +65,12 @@ const char *file_get_extesnsion(const char *fname) { return p; } +bool file_exists(const char *path) { + struct stat path_stat; + int rc = stat(path, &path_stat); + return rc == 0; +} + #if defined(__WIN32__) /* happily borrowed from https://stackoverflow.com/a/8514474 */ char *strsep(char **stringp, const char *delim) { diff --git a/lib/strextra.h b/lib/strextra.h index 0eff18f..d2f2700 100644 --- a/lib/strextra.h +++ b/lib/strextra.h @@ -37,6 +37,9 @@ const char *file_base_name(const char *file_name); /* returns the last tip of the file name */ const char *file_get_extesnsion(const char *fname); +/* this implementation also returns true for directories, is this OK? */ +bool file_exists(const char *path); + #if defined(__WIN32__) /* This function is available on Linux, but now on Windows */ char *strsep(char **stringp, const char *delim); From 1b8e013541dce4896f1ea63dc0d8d0e7edc6831d Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Mon, 6 Sep 2021 00:38:56 +0300 Subject: [PATCH 03/10] Cleanups after merge as a bonus - also support for running batch files without extensions. --- dos/command.c | 107 +++++++++++++++----------------------------------- 1 file changed, 32 insertions(+), 75 deletions(-) diff --git a/dos/command.c b/dos/command.c index 97fc4ca..12bc80e 100644 --- a/dos/command.c +++ b/dos/command.c @@ -18,9 +18,9 @@ For license - read license.txt #include "fdbox.h" #if defined(__TURBOC__) -#include #include "lib/tc202/stdbool.h" #include "lib/tc202/stdextra.h" +#include #endif #ifdef _POSIX_C_SOURCE @@ -45,17 +45,20 @@ static void command_shell_config_init(struct command_shell_config *config); static bool command_shell_config_parse(int argc, char *argv[], struct command_shell_config *config); static void command_shell_config_print(const struct command_shell_config *config); static void command_shell_print_extended_help(); -static char* find_batch_in_path(const char* batch_file_name); +static char *find_batch_in_path(const char *batch_file_name); /* TODO - I am unsure if this is the best way to tell the main loop * we should exit. For now it works */ -int command_execute_line_new(const char *line) { +int command_execute_line(const char *line) { struct command_args args; struct applet *cmd; + const char *command_name; int code; + bool is_silent = false; /* TODO use global state from echo! */ extern struct applet commands[]; + bool is_interactive = isatty(fileno(stdin)); /* this function will not modify the args, so its marked `const * but some commands (date/time) will modify the args instead of making copies @@ -71,88 +74,32 @@ int command_execute_line_new(const char *line) { return EXIT_SUCCESS; } - /* Special handling for exit, as it should break the main loop */ - if (strcasecmp(args.argv[0], "exit") == 0) { - command_args_free(&args); - return EXIT_FAILURE; - } - - cmd = find_applet(CASE_INSENSITVE, args.argv[0], commands); - if (cmd != NULL) { - code = cmd->handler(args.argc, args.argv); - errno = code; - if (code != EXIT_SUCCESS) { - fprintf(stderr, "Command failed (%d)\n", code); - } - } else { - fprintf(stderr, "Command not found\n"); - errno = ENOENT; - } - - command_args_free(&args); - return EXIT_SUCCESS; -} - -int command_execute_line_old(char *line) { - size_t c_argc; - char *c_argv[256]; - const char* command_name; - bool parsed_ok; - bool is_silent = false; /* TODO use global state from echo! */ - struct applet *cmd; - int code; - extern struct applet commands[]; - bool is_interactive = isatty(fileno(stdin)); - - /* this function will not modify the args, so its marked `const - * but some commands (date/time) will modify the args instead of making copies - * this is OK for now */ - parsed_ok = command_split_args(line, &c_argc, (const char **)c_argv, 256); - if (!parsed_ok) { - fprintf(stderr, "Command line parsing failed\n"); - return EXIT_SUCCESS; - } - - if (c_argc == 0) { - return EXIT_SUCCESS; - } - - command_name = c_argv[0]; + command_name = args.argv[0]; if (*command_name == '@') { is_silent = !is_silent; - command_name = command_name+1; + command_name = command_name + 1; + } + /* ok, this fails, since we modify the original line, this will get fixed soon */ + if (!is_silent && !is_interactive) { + puts(line); } /* Special handling for exit, as it should break the main loop */ - if (strcasecmp(command_name, "exit") == 0) { - if (is_interactive) { - printf("interactive shell, not exit, just redirecting stdin back\n"); - if ((freopen("", "r", stdin) == NULL)) { - fprintf(stderr, "Error reopening stdin\n"); - abort(); - } - } - else { - printf("exit shell!\n"); - return EXIT_SUCCESS; - } + command_args_free(&args); + return EXIT_FAILURE; } - cmd = find_applet(CASE_INSENSITVE, c_argv[0], commands); - /* ok, this fails, since we modify the original line, this will get fixed soon */ - if (!is_silent && !is_interactive) { - puts(line); - } - if (cmd != NULL) { - code = cmd->handler(c_argc, c_argv); + cmd = find_applet(CASE_INSENSITVE, command_name, commands); + if (cmd != NULL) { + code = cmd->handler(args.argc, args.argv); errno = code; if (code != EXIT_SUCCESS) { fprintf(stderr, "Command failed (%d)\n", code); } } else { /* is it a batch file ? */ - char* batch_file_path = find_batch_in_path(command_name); + char *batch_file_path = find_batch_in_path(command_name); bool ok = false; if (batch_file_path != NULL) { @@ -168,13 +115,13 @@ int command_execute_line_old(char *line) { errno = ENOENT; } free(batch_file_path); + errno = ENOENT; } + command_args_free(&args); return EXIT_SUCCESS; } -int command_execute_line(char *line) { return command_execute_line_new(line); } - int command_command(int argc, char *argv[]) { char line[1024], *pos; int code; @@ -207,6 +154,9 @@ int command_command(int argc, char *argv[]) { break; } fgets(line, 1024, stdin); + if ((pos = strchr(line, '\r')) != NULL) { + *pos = '\0'; + } if ((pos = strchr(line, '\n')) != NULL) { *pos = '\0'; } @@ -255,10 +205,17 @@ static void command_shell_print_extended_help() { printf(" TODO: properly implement the command.com swithces \n"); } -static char* find_batch_in_path(const char* batch_file_name) -{ +static char *find_batch_in_path(const char *batch_file_name) { + char *f; if (file_exists(batch_file_name)) { return strdup(batch_file_name); } + f = malloc(strlen(batch_file_name) + 4); + strcpy(f, batch_file_name); + strcat(f, ".bat"); + if (file_exists(f)) { + return f; + } + free(f); return NULL; } From 81b72df1fc86a6de1604d31a0e65cdede4b5068c Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Sun, 5 Sep 2021 20:50:09 +0300 Subject: [PATCH 04/10] Fix CMake warning --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 63e5a8f..d2e40ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) -# add the executable +# set the project name project(fdbox VERSION 0.1) include(cmake/CPM.cmake) From 8f0a438bf25c363de2754b9800e2b7ae41af00d3 Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Wed, 11 Aug 2021 19:36:25 +0300 Subject: [PATCH 05/10] Lets start working on batch file support 1. move `file_exists` to a global scope, instead of `if` 1. prompt is printed only on interactive shells. 1. We can start a new batch file (no `call` support yet). We can even nest batches one inside another. 1. Exiting from a batch file is iffie. I need to re-think how this works. --- .vscode/settings.json | 3 +- src/dos/command.c | 125 ++++++++++++++++++++++++++++++++++++------ src/dos/if.c | 10 +--- src/lib/strextra.c | 14 +++++ src/lib/strextra.h | 3 + 5 files changed, 129 insertions(+), 26 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 443eac7..0416376 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "dos-glob.h": "c", "stdextra.h": "c", "DOS-GLOB.H": "cpp", - "stat.h": "c" + "stat.h": "c", + "strextra.h": "c" } } \ No newline at end of file diff --git a/src/dos/command.c b/src/dos/command.c index f3ac183..9c0d58e 100644 --- a/src/dos/command.c +++ b/src/dos/command.c @@ -19,7 +19,8 @@ For license - read license.txt #include "dos/prompt.h" -#ifdef __MSDOS__ +#if defined(__TURBOC__) +#include #include "lib/tc202/stdbool.h" #include "lib/tc202/stdextra.h" #include @@ -36,6 +37,8 @@ For license - read license.txt #include #include #include +======= +>>>>>>> 302f160 (Lets start working on batch file support):dos/command.c #endif #ifdef __WIN32__ @@ -76,6 +79,7 @@ static void command_shell_config_init(struct command_shell_config *config); static bool command_shell_config_parse(int argc, char *argv[], struct command_shell_config *config); static void command_shell_config_print(const struct command_shell_config *config); static void command_shell_print_extended_help(); +static char* find_batch_in_path(const char* batch_file_name); int read_line(char line[], int max_size); @@ -83,7 +87,7 @@ int read_line(char line[], int max_size); * we should exit. For now it works */ -int command_execute_line(const char *line) { +int command_execute_line_new(const char *line) { struct command_args args; struct applet *cmd; int code; @@ -130,6 +134,88 @@ int command_execute_line(const char *line) { return EXIT_SUCCESS; } +int command_execute_line_old(char *line) { + size_t c_argc; + char *c_argv[256]; + const char* command_name; + bool parsed_ok; + bool is_silent = false; /* TODO use global state from echo! */ + struct applet *cmd; + int code; + extern struct applet commands[]; + bool is_interactive = isatty(fileno(stdin)); + + /* this function will not modify the args, so its marked `const + * but some commands (date/time) will modify the args instead of making copies + * this is OK for now */ + parsed_ok = command_split_args(line, &c_argc, (const char **)c_argv, 256); + if (!parsed_ok) { + fprintf(stderr, "Command line parsing failed\n"); + return EXIT_SUCCESS; + } + + if (c_argc == 0) { + return EXIT_SUCCESS; + } + + command_name = c_argv[0]; + if (*command_name == '@') { + is_silent = !is_silent; + command_name = command_name+1; + } + + /* Special handling for exit, as it should break the main loop */ + + if (strcasecmp(command_name, "exit") == 0) { + if (is_interactive) { + printf("interactive shell, not exit, just redirecting stdin back\n"); + if ((freopen("", "r", stdin) == NULL)) { + fprintf(stderr, "Error reopening stdin\n"); + abort(); + } + } + else { + printf("exit shell!\n"); + return EXIT_SUCCESS; + } + } + + cmd = find_applet(CASE_INSENSITVE, c_argv[0], commands); + /* ok, this fails, since we modify the original line, this will get fixed soon */ + if (!is_silent && !is_interactive) { + puts(line); + } + if (cmd != NULL) { + code = cmd->handler(c_argc, c_argv); + errno = code; + if (code != EXIT_SUCCESS) { + fprintf(stderr, "Command failed (%d)\n", code); + } + } else { + /* is it a batch file ? */ + char* batch_file_path = find_batch_in_path(command_name); + bool ok = false; + + if (batch_file_path != NULL) { + if (freopen(batch_file_path, "r", stdin)) { + ok = true; + } + } else { + /* execvp */ + } + + if (!ok) { + fprintf(stderr, "Command not found\n"); + errno = ENOENT; + } + free(batch_file_path); + } + + return EXIT_SUCCESS; +} + +int command_execute_line(char *line) { return command_execute_line_new(line); } + int command_command(int argc, char *argv[]) { char line[1024], *pos; int code; @@ -143,24 +229,23 @@ int command_command(int argc, char *argv[]) { command_shell_print_extended_help(); return EXIT_SUCCESS; } - do { - char prompt[256]; - const char *t; - int l; - - t = getenv("PROMPT"); - if (t == NULL) { - command_prompt(1, NULL); + bool is_interactive = isatty(fileno(stdin)); + if (is_interactive) { + char prompt[256]; + const char *t; t = getenv("PROMPT"); - } - get_prompt(t, prompt, 256); - printf("%s", prompt); - l = read_line(line, 1024); - if (l < 0) { - return EXIT_FAILURE; + if (t == NULL) { + command_prompt(1, NULL); + t = getenv("PROMPT"); + } } + if (feof(stdin)) { + printf("EOF, exit!"); + break; + } + fgets(line, 1024, stdin); if ((pos = strchr(line, '\n')) != NULL) { *pos = '\0'; } @@ -225,3 +310,11 @@ int read_line(char line[], int max_size) { l = read_string(line, max_size); return l; } + +static char* find_batch_in_path(const char* batch_file_name) +{ + if (file_exists(batch_file_name)) { + return strdup(batch_file_name); + } + return NULL; +} \ No newline at end of file diff --git a/src/dos/if.c b/src/dos/if.c index b4b47d1..e1b1c5d 100644 --- a/src/dos/if.c +++ b/src/dos/if.c @@ -38,7 +38,6 @@ For license - read license.txt #include #endif -static bool if_file_exists(const char *path); static char *find_if_command(int argc, char *argv[]); static char *find_else_command(int argc, char *argv[]); @@ -57,7 +56,7 @@ int command_if(int argc, char *argv[]) { if (strcasecmp(argv[arg_index], "exist") == 0) { arg_index++; - evaluated_value = if_file_exists(argv[arg_index]); + evaluated_value = file_exists(argv[arg_index]); } else if (strcasecmp(argv[arg_index], "ERRORLEVEL") == 0) { arg_index++; if (argv[arg_index] != NULL && arg_index < argc) { @@ -118,13 +117,6 @@ int command_if(int argc, char *argv[]) { const char *help_if() { return "Conditionally execute a command"; } -/* this implementation also returns true for directories, is this OK? */ -static bool if_file_exists(const char *path) { - struct stat path_stat; - int rc = stat(path, &path_stat); - return rc == 0; -} - /* This function concatinates all arguments for the * positive resolution of "if". * The input is the first token to be added diff --git a/src/lib/strextra.c b/src/lib/strextra.c index 34bf807..a39e3e6 100644 --- a/src/lib/strextra.c +++ b/src/lib/strextra.c @@ -2,6 +2,14 @@ #include #include +#include + +#if defined(__TURBOC__) +#include "lib/tc202/dos-glob.h" +#include "lib/tc202/stdbool.h" +#include "lib/tc202/stdextra.h" +#endif + const char *str_bool(bool b) { return b ? "true" : "false"; } char *str_to_lower(char *s) { @@ -95,6 +103,12 @@ const char *file_get_extension(const char *fname) { return p; } +bool file_exists(const char *path) { + struct stat path_stat; + int rc = stat(path, &path_stat); + return rc == 0; +} + #if defined(__WIN32__) /* happily borrowed from https://stackoverflow.com/a/8514474 */ char *strsep(char **stringp, const char *delim) { diff --git a/src/lib/strextra.h b/src/lib/strextra.h index ed569be..5040ea8 100644 --- a/src/lib/strextra.h +++ b/src/lib/strextra.h @@ -53,6 +53,9 @@ char *file_get_dir(const char *file_name); char *strsep(char **stringp, const char *delim); #endif +/* this implementation also returns true for directories, is this OK? */ +bool file_exists(const char *path); + struct str_list { size_t length; size_t next; From e10bca7beaafa6f6c0d831f8f3792829fee583c8 Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Mon, 6 Sep 2021 00:38:56 +0300 Subject: [PATCH 06/10] Cleanups after merge as a bonus - also support for running batch files without extensions. --- src/dos/command.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/dos/command.c b/src/dos/command.c index 9c0d58e..551cdd8 100644 --- a/src/dos/command.c +++ b/src/dos/command.c @@ -20,10 +20,10 @@ For license - read license.txt #include "dos/prompt.h" #if defined(__TURBOC__) -#include #include "lib/tc202/stdbool.h" #include "lib/tc202/stdextra.h" #include +#include #endif #if defined(__WATCOMC__) @@ -37,8 +37,6 @@ For license - read license.txt #include #include #include -======= ->>>>>>> 302f160 (Lets start working on batch file support):dos/command.c #endif #ifdef __WIN32__ @@ -79,7 +77,7 @@ static void command_shell_config_init(struct command_shell_config *config); static bool command_shell_config_parse(int argc, char *argv[], struct command_shell_config *config); static void command_shell_config_print(const struct command_shell_config *config); static void command_shell_print_extended_help(); -static char* find_batch_in_path(const char* batch_file_name); +static char *find_batch_in_path(const char *batch_file_name); int read_line(char line[], int max_size); @@ -87,11 +85,14 @@ int read_line(char line[], int max_size); * we should exit. For now it works */ -int command_execute_line_new(const char *line) { +int command_execute_line(const char *line) { struct command_args args; struct applet *cmd; + const char *command_name; int code; + bool is_silent = false; /* TODO use global state from echo! */ extern struct applet commands[]; + bool is_interactive = isatty(fileno(stdin)); /* this function will not modify the args, so its marked `const * but some commands (date/time) will modify the args instead of making copies @@ -107,13 +108,23 @@ int command_execute_line_new(const char *line) { return EXIT_SUCCESS; } + command_name = args.argv[0]; + if (*command_name == '@') { + is_silent = !is_silent; + command_name = command_name + 1; + } + /* ok, this fails, since we modify the original line, this will get fixed soon */ + if (!is_silent && !is_interactive) { + puts(line); + } + /* Special handling for exit, as it should break the main loop */ - if (strcasecmp(args.argv[0], "exit") == 0) { + if (strcasecmp(command_name, "exit") == 0) { command_args_free(&args); return EXIT_FAILURE; } - cmd = find_applet(CASE_INSENSITVE, args.argv[0], commands); + cmd = find_applet(CASE_INSENSITVE, command_name, commands); if (cmd != NULL) { code = cmd->handler(args.argc, args.argv); errno = code; @@ -193,7 +204,7 @@ int command_execute_line_old(char *line) { } } else { /* is it a batch file ? */ - char* batch_file_path = find_batch_in_path(command_name); + char *batch_file_path = find_batch_in_path(command_name); bool ok = false; if (batch_file_path != NULL) { @@ -209,13 +220,11 @@ int command_execute_line_old(char *line) { errno = ENOENT; } free(batch_file_path); + errno = ENOENT; } - return EXIT_SUCCESS; } -int command_execute_line(char *line) { return command_execute_line_new(line); } - int command_command(int argc, char *argv[]) { char line[1024], *pos; int code; @@ -239,6 +248,8 @@ int command_command(int argc, char *argv[]) { command_prompt(1, NULL); t = getenv("PROMPT"); } + get_prompt(t, prompt, 256); + printf("%s", prompt); } if (feof(stdin)) { @@ -246,6 +257,9 @@ int command_command(int argc, char *argv[]) { break; } fgets(line, 1024, stdin); + if ((pos = strchr(line, '\r')) != NULL) { + *pos = '\0'; + } if ((pos = strchr(line, '\n')) != NULL) { *pos = '\0'; } @@ -311,10 +325,17 @@ int read_line(char line[], int max_size) { return l; } -static char* find_batch_in_path(const char* batch_file_name) -{ +static char *find_batch_in_path(const char *batch_file_name) { + char *f; if (file_exists(batch_file_name)) { return strdup(batch_file_name); } + f = malloc(strlen(batch_file_name) + 4); + strcpy(f, batch_file_name); + strcat(f, ".bat"); + if (file_exists(f)) { + return f; + } + free(f); return NULL; } \ No newline at end of file From 934b95fbdfd440e7b7d5f6b6a750cb8c8db0d53a Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Thu, 16 Jun 2022 21:25:43 +0300 Subject: [PATCH 07/10] Fix compilation of test on Windows I have no idea how this worked before. Don't care - now it does work :) --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2e40ae..ac4d34c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,8 @@ cpmaddpackage( # path to exclude (optional, supports regular expressions) "CMAKE_FORMAT_EXCLUDE cmake/CPM.cmake") -add_executable( + + add_executable( tests src/tests.c src/lib/applet.c @@ -26,6 +27,13 @@ add_executable( src/lib/readline.c src/lib/strextra.c ) +if(WIN32) + target_sources(tests PRIVATE + src/lib/win32/win32-glob.h + src/lib/tc202/stdextra.c + ) +endif() + target_include_directories(tests PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/src/") From 698d4b416750af9b250b4cc13ebfd0662fa434c8 Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Fri, 23 Dec 2022 18:31:58 +0200 Subject: [PATCH 08/10] Remove extra definition of file_exists() --- src/lib/strextra.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lib/strextra.h b/src/lib/strextra.h index 5040ea8..ed569be 100644 --- a/src/lib/strextra.h +++ b/src/lib/strextra.h @@ -53,9 +53,6 @@ char *file_get_dir(const char *file_name); char *strsep(char **stringp, const char *delim); #endif -/* this implementation also returns true for directories, is this OK? */ -bool file_exists(const char *path); - struct str_list { size_t length; size_t next; From 6ce307cd6297a950ff8e8975101a04e24123eb2d Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Fri, 23 Dec 2022 18:32:31 +0200 Subject: [PATCH 09/10] Remove extra definition of file_exists() / take2 --- src/lib/strextra.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/lib/strextra.c b/src/lib/strextra.c index a39e3e6..ad5f604 100644 --- a/src/lib/strextra.c +++ b/src/lib/strextra.c @@ -103,12 +103,6 @@ const char *file_get_extension(const char *fname) { return p; } -bool file_exists(const char *path) { - struct stat path_stat; - int rc = stat(path, &path_stat); - return rc == 0; -} - #if defined(__WIN32__) /* happily borrowed from https://stackoverflow.com/a/8514474 */ char *strsep(char **stringp, const char *delim) { From 4725406ab614287ce62dbba52caa17a4b47a7af0 Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Fri, 23 Dec 2022 18:38:55 +0200 Subject: [PATCH 10/10] Fix compilatio under OSX, found a real issue --- src/dos/if.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dos/if.c b/src/dos/if.c index 11394f1..3a0a7fe 100644 --- a/src/dos/if.c +++ b/src/dos/if.c @@ -14,6 +14,7 @@ For license - read license.txt #include "fdbox.h" #include "lib/environ.h" #include "lib/strextra.h" +#include "lib/args.h" #if defined(_POSIX_C_SOURCE) || defined(__APPLE__) #include