Something went wrong. Try again.
MIRROR: javascript for ๐'s, a tiny runtime with big ambitions ant.themackabu.dev
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205#include <compat.h> // IWYU pragma: keep
#include <stdio.h>#include <stdlib.h>#include <string.h>
#ifdef _WIN32#define popen _popen#define pclose _pclose#else#include <sys/wait.h>#endif
#include "ant.h"#include "errors.h"#include "internal.h"#include "modules/symbol.h"
static ant_value_t builtin_shell_text(ant_t *js, ant_value_t *args, int nargs);static ant_value_t builtin_shell_lines(ant_t *js, ant_value_t *args, int nargs);
static ant_value_t shell_exec(ant_t *js, const char *cmd, size_t cmd_len) { ant_value_t result = js_mkobj(js); FILE *fp = popen(cmd, "r"); if (!fp) { js_set(js, result, "stdout", js_mkstr(js, "", 0)); js_set(js, result, "stderr", js_mkstr(js, "Failed to execute command", 25)); js_set(js, result, "exitCode", js_mknum(1)); return result; } char *output = NULL; size_t output_size = 0; size_t output_capacity = 4096; output = malloc(output_capacity); if (!output) { pclose(fp); return js_mkerr(js, "Out of memory"); } char buffer[4096]; while (fgets(buffer, sizeof(buffer), fp) != NULL) { size_t len = strlen(buffer); if (output_size + len >= output_capacity) { output_capacity *= 2; char *new_output = realloc(output, output_capacity); if (!new_output) { free(output); pclose(fp); return js_mkerr(js, "Out of memory"); } output = new_output; } memcpy(output + output_size, buffer, len); output_size += len; } int status = pclose(fp);#ifdef _WIN32 int exit_code = status;#else int exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1;#endif if (output_size > 0 && output[output_size - 1] == '\n') output_size--; ant_value_t stdout_val = js_mkstr(js, output, output_size); free(output); js_set(js, result, "exitCode", js_mknum(exit_code)); js_set(js, result, "text", js_heavy_mkfun(js, builtin_shell_text, stdout_val)); js_set(js, result, "lines", js_heavy_mkfun(js, builtin_shell_lines, stdout_val)); return result;}
static ant_value_t builtin_shell_text(ant_t *js, ant_value_t *args, int nargs) { (void)args; (void)nargs; ant_value_t fn = js_getcurrentfunc(js); return js_get_slot(fn, SLOT_DATA);}
static ant_value_t builtin_shell_lines(ant_t *js, ant_value_t *args, int nargs) { (void)args; (void)nargs; ant_value_t fn = js_getcurrentfunc(js); ant_value_t stdout_val = js_get_slot(fn, SLOT_DATA); size_t text_len; char *text = js_getstr(js, stdout_val, &text_len); if (!text) return js_mkarr(js); ant_value_t lines_array = js_mkarr(js); size_t line_start = 0; for (size_t i = 0; i <= text_len; i++) { if (i == text_len || text[i] == '\n') { size_t line_len = i - line_start; ant_value_t line_val = js_mkstr(js, text + line_start, line_len); js_arr_push(js, lines_array, line_val); line_start = i + 1; } } return lines_array;}
static ant_value_t builtin_shell_dollar(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "$() requires at least one argument"); if (!is_special_object(args[0])) { if (vtype(args[0]) == T_STR) { size_t cmd_len; char *cmd = js_getstr(js, args[0], &cmd_len); if (!cmd) return js_mkerr(js, "Failed to get command string"); return shell_exec(js, cmd, cmd_len); } return js_mkerr(js, "$() requires a template string"); } ant_value_t strings_array = args[0]; char *command = malloc(4096); if (!command) return js_mkerr(js, "Out of memory"); size_t cmd_pos = 0; size_t cmd_capacity = 4096; ant_value_t length_val = js_get(js, strings_array, "length"); int length = (int)js_getnum(length_val); for (int i = 0; i < length; i++) { char idx_str[32]; snprintf(idx_str, sizeof(idx_str), "%d", i); ant_value_t str_val = js_get(js, strings_array, idx_str); if (vtype(str_val) == T_STR) { size_t str_len; char *str = js_getstr(js, str_val, &str_len); if (cmd_pos + str_len >= cmd_capacity) { cmd_capacity *= 2; char *new_cmd = realloc(command, cmd_capacity); if (!new_cmd) { free(command); return js_mkerr(js, "Out of memory"); } command = new_cmd; } memcpy(command + cmd_pos, str, str_len); cmd_pos += str_len; } if (i + 1 < nargs) { ant_value_t val = args[i + 1]; char val_str[256]; size_t val_len = 0; if (vtype(val) == T_STR) { size_t len; char *s = js_getstr(js, val, &len); val_len = len < sizeof(val_str) - 1 ? len : sizeof(val_str) - 1; memcpy(val_str, s, val_len); } else if (vtype(val) == T_NUM) { val_len = snprintf(val_str, sizeof(val_str), "%g", js_getnum(val)); } if (cmd_pos + val_len >= cmd_capacity) { cmd_capacity *= 2; char *new_cmd = realloc(command, cmd_capacity); if (!new_cmd) { free(command); return js_mkerr(js, "Out of memory"); } command = new_cmd; } memcpy(command + cmd_pos, val_str, val_len); cmd_pos += val_len; } } command[cmd_pos] = '\0'; ant_value_t result = shell_exec(js, command, cmd_pos); free(command); return result;}
ant_value_t shell_library(ant_t *js) { ant_value_t lib = js_mkobj(js); js_set(js, lib, "$", js_mkfun(builtin_shell_dollar)); js_set_sym(js, lib, get_toStringTag_sym(), js_mkstr(js, "shell", 5)); return lib;}