#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; } typedef struct EachFileSkip { struct EachFileSkip *next; char *filename; } EachFileSkip; bool rt_eachfile(Token *tks) { EachFileSkip *skips = NULL; Token *tk = tks; char *dirpath; while (tk && tk->str[0] == '!') { EachFileSkip *skip = (EachFileSkip *)umalloc(sizeof(*skip)); skip->filename = tk->str + 1; LL_APPEND(skips, skip); tk = tk->next; } if (tk != NULL) { dirpath = tk->str; tk = tk->next; } FsStat statbuf; ZERO(&statbuf); if (fs_stat(dirpath, &statbuf) != E_OK || statbuf.type != FSSTAT_DIR) { return false; } FsDirent *dirents = (FsDirent *)umalloc(statbuf.size * sizeof(*dirents)); for (size_t i = 0; i < statbuf.size; i++) { fs_fetchdirent(dirpath, &dirents[i], i); FsDirent *dirent = &dirents[i]; if (string_strcmp(dirent->name, ".") == 0 || string_strcmp(dirent->name, "..") == 0) { continue; } EachFileSkip *skip1, *skip1tmp; LL_FOREACH_SAFE(skips, skip1, skip1tmp) { if (string_strcmp(skip1->filename, dirent->name) == 0) { goto nextiter; } } char tmpbuf[1024]; ZERO(tmpbuf); string_strcpy(tmpbuf, dirpath); if (dirpath[string_len(dirpath) - 1] != '/') { string_combine(tmpbuf, "/"); } string_combine(tmpbuf, dirent->name); #define EACHFILE_MAX_STRING 1024 char *s = umalloc(EACHFILE_MAX_STRING); string_memset(s, 0, EACHFILE_MAX_STRING); size_t cursor = 0; Token *argtk, *argtktmp; LL_FOREACH_SAFE(tk, argtk, argtktmp) { if (string_strcmp(argtk->str, "&EF-ELEM") == 0) { size_t len = string_len(tmpbuf); string_memcpy(&s[cursor], tmpbuf, len); cursor += len; s[cursor] = ' '; cursor++; } else { size_t len = string_len(argtk->str); string_memcpy(&s[cursor], argtk->str, len); cursor += len; s[cursor] = ' '; cursor++; } } InterpResult save; string_memcpy(&save, &RES, sizeof(save)); InterpResult *res; interp_runstring(s, &res, false, false); string_memcpy(&RES, &save, sizeof(save)); /* ufree(s); */ nextiter: } ufree(dirents); EachFileSkip *skip1, *skip1tmp; LL_FOREACH_SAFE(skips, skip1, skip1tmp) { ufree(skip1); } return true; } bool rt_mkaliasbn(Token *tks) { Token *tk = tks; if (tk == NULL) { return false; } RtAlias *alias = umalloc(sizeof(*alias)); string_memset(alias, 0, sizeof(*alias)); char *basename = (char *)path_basename(tk->str); string_memcpy(alias->namebuf, basename, MIN(string_len(basename), RTALIAS_NAMEBUF_MAX)); string_memcpy(alias->valbuf, tk->str, MIN(string_len(tk->str), RTALIAS_VALBUF_MAX)); LL_APPEND(RTALIASES, alias); 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); RTCMD("eachfile", &rt_eachfile); RTCMD("mkaliasbn", &rt_mkaliasbn); }