#include #include #include #include #include #include #include #include #include #include #include #include #include "interp.h" #include "runtime.h" extern uint64_t PID; static InterpResult RES; void tz_init(Tokenizer *tz, const char *str, size_t len) { tz->str = str; tz->len = len; tz->pos = 0; } void tz_free(Tokenizer *tz) { Token *tk = tz->tokens; while (tk) { Token *tmp = tk; tk = tk->next; dlfree(tmp); } } int tz_next(Tokenizer *tz, Token *out) { while (tz->pos < tz->len && string_chr_isspace(tz->str[tz->pos])) { tz->pos++; } if (tz->pos >= tz->len) { return 0; } size_t start = tz->pos; if (tz->str[start] == '"') { start++; tz->pos++; while (tz->pos < tz->len && tz->str[tz->pos] != '"') { tz->pos++; } if (tz->pos >= tz->len) { out->ptr = tz->str + start; out->len = tz->len - start; tz->pos = tz->len; } else { out->ptr = tz->str + start; out->len = tz->pos - start; tz->pos++; } } else { while (tz->pos < tz->len && !string_chr_isspace(tz->str[tz->pos])) { tz->pos++; } out->ptr = tz->str + start; out->len = tz->pos - start; } return 1; } void tz_classify(Tokenizer *tz) { const int tmpbufsz = 256; char *tmpbuf = dlmalloc(tmpbufsz); Token *tk = tz->tokens; while (tk) { if (tk->ptr[0] == '"' && tk->ptr[tk->len - 1] == '"') { tk->type = TOK_STRING; } else if (tk->ptr[0] == '@') { RtCmd *cmd = RTCMDS; while (cmd) { string_memset(tmpbuf, 0, tmpbufsz); usnprintf(tmpbuf, tmpbufsz, "%.*s", (int)tk->len, tk->ptr); if (string_strcmp(tmpbuf, cmd->cmdname) == 0) { tk->type = TOK_CMD; tk->cmd = cmd; break; } cmd = cmd->next; } } else { tk->type = TOK_MISC; } tk = tk->next; } dlfree(tmpbuf); } void tz_expandspecial(Tokenizer *tz) { Token *tk = tz->tokens; while (tk) { if (tk->ptr[0] == '$' && tk->len > 1) { char *aliasbuf = dlmalloc(RTALIAS_NAMEBUF_MAX); usnprintf(aliasbuf, RTALIAS_NAMEBUF_MAX, "%.*s", (int)tk->len-1, &tk->ptr[1]); RtAlias *alias = RTALIASES; while (alias) { if (string_strcmp(alias->namebuf, aliasbuf) == 0) { tk->ptr = alias->valbuf; tk->len = string_len(alias->valbuf); break; } alias = alias->next; } dlfree(aliasbuf); } tk = tk->next; } } bool interp_readline(char *data, const char **bgptr, const char **endptr) { static char *nextstart; if (data) { nextstart = data; return true; } if (*nextstart == '\0') { return false; } *bgptr = nextstart; const char *scn = nextstart; for (;;) { while (*scn != '\0' && *scn != '\n') { scn++; } if (*scn == '\n') { if (scn > *bgptr && *(scn - 1) == '\\') { scn--; nextstart = scn; *nextstart = ' '; scn++; if (*scn == '\n') { scn++; } nextstart = scn; continue; } } break; } *endptr = scn - 1; while (string_chr_isspace(**bgptr) && *bgptr < *endptr) { (*bgptr)++; } while (string_chr_isspace(**endptr) && *endptr >= *bgptr) { (*endptr)--; } (*endptr)++; if (*scn == '\n') { scn++; } nextstart = scn; return true; } bool interp_runstring(const char *string, InterpResult **res, bool logcmds) { *res = &RES; string_memset(RES.errmsg, 0, sizeof(RES.errmsg)); rt_init(); bool ok = true; const char *bg, *end; interp_readline((char *)string, NULL, NULL); while (interp_readline(NULL, &bg, &end)) { size_t linelen = end - bg; if (logcmds) { uprintf("+ %.*s\n", (int)linelen, bg); } Tokenizer tz = {0}; tz_init(&tz, bg, linelen); Token toktmp = {0}; while (tz_next(&tz, &toktmp)) { Token *tok = dlmalloc(sizeof(*tok)); tok->ptr = toktmp.ptr; tok->len = toktmp.len; LL_APPEND(tz.tokens, tok); } tz_classify(&tz); tz_expandspecial(&tz); Token *cmdtk = tz.tokens; if (cmdtk->type == TOK_CMD) { ok = cmdtk->cmd->fn(cmdtk->next); if (!ok) { ok = false; usprintf(RES.errmsg, "cmd %.*s failed", (int)cmdtk->len, cmdtk->ptr); tz_free(&tz); goto done; } } else if (cmdtk->type == TOK_MISC) { char *appname = dlmalloc(1024); usprintf(appname, "%.*s", (int)cmdtk->len, cmdtk->ptr); size_t argslen1 = 0; Token *argtk = cmdtk->next; while (argtk) { argslen1++; argtk = argtk->next; } char **args1 = (char **)dlmalloc(sizeof(char *) * argslen1); argtk = cmdtk->next; size_t i = 0; while (argtk) { args1[i] = (char *)dlmalloc(PROC_ARG_MAX); string_memset(args1[i], 0, PROC_ARG_MAX); string_memcpy(args1[i], argtk->ptr, argtk->len); i++; argtk = argtk->next; } int32_t app = processctl(-1, PCTL_SPAWN, (uint64_t)appname, (uint64_t)args1, argslen1); if (app < 0) { usprintf(RES.errmsg, "Could not run %s: %s\n", appname, ERRSTRING(app)); ok = false; goto cleanup; } processctl(app, PCTL_RUN, 0, 0, 0); while(processctl(app, PCTL_POLLSTATE, 0, 0, 0) != 4); cleanup: for (size_t j = 0; j < argslen1; j++) { dlfree(args1[j]); } dlfree(args1); dlfree(appname); } tz_free(&tz); } done: return ok; }