From 90843713f4762dd706e5f6de08631cd5eb16392e Mon Sep 17 00:00:00 2001 From: Marko Semet Date: Tue, 16 Feb 2021 23:53:52 +0100 Subject: [PATCH] Add system util echo --- README.md | 7 ++ sysutils/echo.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++ sysutils/utils.h | 64 ++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 sysutils/echo.c create mode 100644 sysutils/utils.h diff --git a/README.md b/README.md index 9c3f536..31ae95d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # c-bootbox +Standalone libraries and tools to bootstrap a system when you have a running c compiler + +## System utils + +Basic commands for a system can be found at `/sysutils`. + +Current supported: `echo` \ No newline at end of file diff --git a/sysutils/echo.c b/sysutils/echo.c new file mode 100644 index 0000000..c2b6998 --- /dev/null +++ b/sysutils/echo.c @@ -0,0 +1,172 @@ +#include +#include + +#include "utils.h" + +int echo_main(int argc, char **argv) +{ + // Init + int add_newline; + int escape; + int backup_add_newline; + int backup_escape; + const char *escape_from; + const char *escape_to; + int argv_pos; + int i; + int j; + int len; + int len2; + int break_outer; + int first; + unsigned char tmp_char; + + add_newline = 1; + escape = 0; + escape_from = "\\abnrtvf"; + escape_to = "\\\a\\\n\r\t\v\f"; + len2 = strlen(escape_from); + argv_pos = 1; + + // Check for options + break_outer = 0; + while((argv_pos < argc) && (break_outer == 0)) { + backup_add_newline = add_newline; + backup_escape = escape; + if(argv[argv_pos][0] != '-') { + break; + } + i = 1; + len = strlen(argv[argv_pos]); + while(i < len) { + if(argv[argv_pos][i] == 'e') { + escape = 1; + } + else if(argv[argv_pos][i] == 'E') { + escape = 0; + } + else if(argv[argv_pos][i] == 'n') { + add_newline = 0; + } + else { + escape = backup_escape; + add_newline = backup_add_newline; + break_outer = 1; + break; + } + i++; + } + argv_pos++; + } + + // Output strings + first = 1; + while(argv_pos < argc) { + // Add spaces betwean arguments + if(first != 0) { + first = 0; + } + else { + if(fwrite(" ", 1, 1, stdout) != 1) { + return 1; + } + } + + if(escape != 0) { + // Escaped output + i = 0; + len = strlen(argv[argv_pos]); + while(i < len) { + if(argv[argv_pos][i] == '\\') { + i++; + if(argv[argv_pos][i] == 'c') { + return 0; + } + else if(argv[argv_pos][i] == '0') { + tmp_char = 0; + i++; + if(is_octal_dig(argv[argv_pos][i]) != 0) { + tmp_char = (tmp_char << 3) | ((unsigned char)parse_octal_dig(argv[argv_pos][i])); + i++; + if(is_octal_dig(argv[argv_pos][i]) != 0) { + tmp_char = (tmp_char << 3) | ((unsigned char)parse_octal_dig(argv[argv_pos][i])); + i++; + if(is_octal_dig(argv[argv_pos][i]) != 0) { + tmp_char = (tmp_char << 3) | ((unsigned char)parse_octal_dig(argv[argv_pos][i])); + i++; + } + } + } + i--; + if(fwrite(&tmp_char, 1, 1, stdout) != 1) { + return 1; + } + } + else if(argv[argv_pos][i] == 'x') { + i++; + tmp_char = 0; + if(is_hex_dig(argv[argv_pos][i]) != 0) { + tmp_char = (tmp_char << 4) | ((unsigned char)parse_octal_dig(argv[argv_pos][i])); + i++; + if(is_hex_dig(argv[argv_pos][i]) != 0) { + tmp_char = (tmp_char << 4) | ((unsigned char)parse_octal_dig(argv[argv_pos][i])); + i++; + } + } + i--; + if(fwrite(&tmp_char, 1, 1, stdout) != 1) { + return 1; + } + } + else { + j = 0; + while(j < len2) { + if(escape_from[j] == argv[argv_pos][i]) { + if(fwrite(escape_to + j, 1, 1, stdout) != 1) { + return 1; + } + break; + } + j++; + } + if(j >= len2) { + if(fwrite(argv[argv_pos] + i - 1, 2, 1, stdout) != 1) { + return 1; + } + } + } + } + else { + if(fwrite(argv[argv_pos] + i, 1, 1, stdout) != 1) { + return 1; + } + } + i++; + } + } + else { + // Unescaped output + if(fwrite(argv[argv_pos], strlen(argv[argv_pos]), 1, stdout) != 1) { + return 1; + } + } + argv_pos++; + } + + // Write final newline when required + if(add_newline != 0) { + if(fwrite("\n", 1, 1, stdout) != 1) { + return 1; + } + } + + // Done + return 0; +} + +#ifndef CBOOTBOX_INCLUDED_CALL +int main(int argc, char **argv) +{ + return echo_main(argc, argv); +} +#endif \ No newline at end of file diff --git a/sysutils/utils.h b/sysutils/utils.h new file mode 100644 index 0000000..059ce00 --- /dev/null +++ b/sysutils/utils.h @@ -0,0 +1,64 @@ +#ifndef _SYSUTILS_UTILS_H + +// Number parsing +static inline int parse_num_dig(char dig) +{ + if((dig >= '0') && (dig <= '9')) { + return dig - '0'; + } + else if((dig >= 'a') && (dig <= 'z')) { + return dig - 'a'; + } + else if((dig >= 'A') && (dig <= 'Z')) { + return dig - 'A'; + } + else { + return -1; + } +} +static inline int is_octal_dig(char dig) +{ + int tmp; + tmp = parse_num_dig(dig); + if((tmp >= 0) && (tmp <= 7)) { + return 1; + } + else { + return 0; + } +} +static inline int is_hex_dig(char dig) +{ + int tmp; + tmp = parse_num_dig(dig); + if((tmp >= 0) && (tmp <= 15)) { + return 1; + } + else { + return 0; + } +} +static inline int parse_octal_dig(char dig) +{ + int tmp; + tmp = parse_num_dig(dig); + if((tmp >= 0) && (tmp <= 7)) { + return tmp; + } + else { + return -1; + } +} +static inline int parse_hex_dig(char dig) +{ + int tmp; + tmp = parse_num_dig(dig); + if((tmp >= 0) && (tmp <= 15)) { + return tmp; + } + else { + return -1; + } +} + +#endif \ No newline at end of file