#include #include #include #include "runtime.h" #include "interp.h" RtStringV *RTSTRINGV_STACK = NULL; void rtstringv_stackpushcopy(char *s, size_t len) { char *c = umalloc(len+1); string_memcpy(c, s, len); c[len] = '\0'; RtStringV *v = umalloc(sizeof(*v)); v->data = c; LL_APPEND(RTSTRINGV_STACK, v); } char *rtstringv_stackpop(void) { RtStringV *v; LL_BACK(RTSTRINGV_STACK, v); if (v == NULL) { return NULL; } LL_REMOVE(RTSTRINGV_STACK, v); char *d = v->data; ufree(v); return d; } char *rtstringv_stackpeek(void) { RtStringV *v; LL_BACK(RTSTRINGV_STACK, v); if (v == NULL) { return NULL; } return v->data; } extern PID_t PID; RtCmd *RTCMDS = NULL; RtAlias *RTALIASES = NULL; #define RTCMD(name, _fn) \ do { \ RtCmd *_cmd = umalloc(sizeof(*_cmd)); \ _cmd->cmdname = (name); \ _cmd->fn = (_fn); \ LL_APPEND(RTCMDS, _cmd); \ } while(0) bool rt_print(Token *tks) { Token *tk, *tktmp; LL_FOREACH_SAFE(tks, tk, tktmp) { uprintf("%s", tk->str); if (tk->next != NULL) { uprintf(" "); } } return true; } bool rt_mkalias(Token *tks) { RtAlias *alias = umalloc(sizeof(*alias)); string_memset(alias, 0, sizeof(*alias)); size_t i; Token *tk, *tktmp; LL_FOREACH_SAFE_IDX(tks, tk, tktmp, i) { if (i == 0) { string_memcpy(alias->namebuf, tk->str, MIN(string_len(tk->str), RTALIAS_NAMEBUF_MAX)); } else if (i == 1) { string_memcpy(alias->valbuf, tk->str, MIN(string_len(tk->str), RTALIAS_VALBUF_MAX)); } } LL_APPEND(RTALIASES, alias); return true; } bool rt_PID(Token *tks) { (void)tks; uprintf("%lu\n", PID); return true; } bool rt_do(Token *tks) { bool ok = true; char *prepended_args[] = { "-m", "runstring", "-rs" }; #define SUBSH_MAX_STRING PROC_ARG_MAX char *s = umalloc(SUBSH_MAX_STRING); string_memset(s, 0, SUBSH_MAX_STRING); size_t cursor = 0; Token *argtk, *argtktmp; LL_FOREACH_SAFE(tks, argtk, argtktmp) { size_t len = string_len(argtk->str); string_memcpy(&s[cursor], argtk->str, len); cursor += len; s[cursor] = ' '; cursor++; } char **args1 = umalloc(sizeof(char *) * (ARRLEN(prepended_args) + 1)); for (size_t i = 0; i < ARRLEN(prepended_args); i++) { args1[i] = umalloc(PROC_ARG_MAX); string_memset(args1[i], 0, PROC_ARG_MAX); string_strcpy(args1[i], prepended_args[i]); } args1[ARRLEN(prepended_args)] = umalloc(PROC_ARG_MAX); string_strcpy(args1[ARRLEN(prepended_args)], s); int32_t app = proc_spawn("base:/bin/tb", args1, ARRLEN(prepended_args)+1); if (app < 0) { ok = false; goto done; } StringBuffer outbuf; stringbuffer_init(&outbuf); ipc_pipemake(10); ipc_pipeconnect(app, 0, PID, 10); proc_run(app); while (proc_pollstate(app) != 4) { int32_t r; char buf[100]; string_memset(buf, 0, sizeof(buf)); r = ipc_piperead(app, 0, (uint8_t *const)buf, sizeof(buf)-1); if (r > 0) { stringbuffer_appendcstr(&outbuf, buf); } } ipc_pipedelete(10); rtstringv_stackpushcopy(outbuf.data, outbuf.count); stringbuffer_free(&outbuf); done: for (size_t i = 0; i < ARRLEN(prepended_args)+1; i++) { ufree(args1[i]); } ufree(s); return ok; } bool rt_stackpush(Token *tks) { Token *tk, *tktmp; LL_FOREACH_SAFE(tks, tk, tktmp) { rtstringv_stackpushcopy(tk->str, string_len(tk->str)); } return true; } bool rt_stackpop(Token *tks) { (void)tks; char *s = rtstringv_stackpop(); if (s) ufree(s); return true; } void rt_init(void) { RTCMD("%print", &rt_print); RTCMD("%mkalias", &rt_mkalias); RTCMD("%PID", &rt_PID); RTCMD("%do", &rt_do); RTCMD("%stackpush", &rt_stackpush); RTCMD("%stackpop", &rt_stackpop); }