diff options
Diffstat (limited to 'stdlib/shell.c')
| -rw-r--r-- | stdlib/shell.c | 157 |
1 files changed, 0 insertions, 157 deletions
diff --git a/stdlib/shell.c b/stdlib/shell.c deleted file mode 100644 index 30dc7c6f..00000000 --- a/stdlib/shell.c +++ /dev/null @@ -1,157 +0,0 @@ -// A lang for Shell Command Language -#include <errno.h> -#include <stdbool.h> -#include <stdint.h> -#include <unistr.h> - -#include "arrays.h" -#include "integers.h" -#include "paths.h" -#include "patterns.h" -#include "shell.h" -#include "text.h" -#include "types.h" -#include "util.h" - -public Shell_t Shell$escape_text(Text_t text) -{ - return Texts(Text("'"), Text$replace(text, Text("'"), Text("'\"'\"'"), Text(""), false), Text("'")); -} - -public Shell_t Shell$escape_path(Path_t path) -{ - return Shell$escape_text(Path$as_text(&path, false, &Path$info)); -} - -public Shell_t Shell$escape_text_array(Array_t texts) -{ - Array_t all_escaped = {}; - for (int64_t i = 0; i < texts.length; i++) { - Text_t raw = *(Text_t*)(texts.data + i*texts.stride); - Text_t escaped = Shell$escape_text(raw); - Array$insert(&all_escaped, &escaped, I(0), sizeof(Text_t)); - } - return Text$join(Text(" "), all_escaped); -} - -public Shell_t Shell$escape_path_array(Array_t paths) -{ - Array_t all_escaped = {}; - for (int64_t i = 0; i < paths.length; i++) { - Path_t path = *(Path_t*)(paths.data + i*paths.stride); - Text_t escaped = Shell$escape_path(path); - Array$insert(&all_escaped, &escaped, I(0), sizeof(Text_t)); - } - return Text$join(Text(" "), all_escaped); -} - -public OptionalArray_t Shell$run_bytes(Shell_t command) -{ - const char *cmd_str = Text$as_c_string(command); - FILE *prog = popen(cmd_str, "r"); - if (!prog) - return NONE_ARRAY; - - size_t capacity = 256, len = 0; - char *content = GC_MALLOC_ATOMIC(capacity); - char chunk[256]; - size_t just_read; - do { - just_read = fread(chunk, 1, sizeof(chunk), prog); - if (just_read == 0) { - if (errno == EAGAIN || errno == EINTR) - continue; - break; - } - - if (len + (size_t)just_read >= capacity) - content = GC_REALLOC(content, (capacity *= 2)); - - memcpy(content + len, chunk, (size_t)just_read); - len += (size_t)just_read; - } while (just_read == sizeof(chunk)); - - int status = pclose(prog); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - return NONE_ARRAY; - - return (Array_t){.data=content, .atomic=1, .stride=1, .length=len}; -} - -public OptionalText_t Shell$run(Shell_t command) -{ - Array_t bytes = Shell$run_bytes(command); - if (bytes.length < 0) - return NONE_TEXT; - - if (bytes.length > 0 && *(char*)(bytes.data + (bytes.length-1)*bytes.stride) == '\n') { - --bytes.length; - if (bytes.length > 0 && *(char*)(bytes.data + (bytes.length-1)*bytes.stride) == '\r') - --bytes.length; - } - return Text$from_bytes(bytes); -} - -public OptionalInt32_t Shell$execute(Shell_t command) -{ - const char *cmd_str = Text$as_c_string(command); - int status = system(cmd_str); - if (WIFEXITED(status)) - return (OptionalInt32_t){.i=WEXITSTATUS(status)}; - else - return (OptionalInt32_t){.is_none=true}; -} - -static void _line_reader_cleanup(FILE **f) -{ - if (f && *f) { - pclose(*f); - *f = NULL; - } -} - -static Text_t _next_line(FILE **f) -{ - if (!f || !*f) return NONE_TEXT; - - char *line = NULL; - size_t size = 0; - ssize_t len = getline(&line, &size, *f); - if (len <= 0) { - _line_reader_cleanup(f); - return NONE_TEXT; - } - - while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n')) - --len; - - if (u8_check((uint8_t*)line, (size_t)len) != NULL) - fail("Invalid UTF8!"); - - Text_t line_text = Text$format("%.*s", len, line); - free(line); - return line_text; -} - -public OptionalClosure_t Shell$by_line(Shell_t command) -{ - const char *cmd_str = Text$as_c_string(command); - FILE *prog = popen(cmd_str, "r"); - if (!prog) - return NONE_CLOSURE; - - FILE **wrapper = GC_MALLOC(sizeof(FILE*)); - *wrapper = prog; - GC_register_finalizer(wrapper, (void*)_line_reader_cleanup, NULL, NULL, NULL); - return (Closure_t){.fn=(void*)_next_line, .userdata=wrapper}; -} - -public const TypeInfo_t Shell$info = { - .size=sizeof(Shell_t), - .align=__alignof__(Shell_t), - .tag=TextInfo, - .TextInfo={.lang="Shell"}, - .metamethods=Text$metamethods, -}; - -// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 |
