#include #include #include #include "interp.h" #include "runtime.h" #include "macros.h" extern PID_t PID; static InterpResult RES; void tz_init(Tokenizer *tz, char *str) { tz->str = str; tz->tokens = NULL; } void tz_free(Tokenizer *tz) { Token *tk, *tktmp; LL_FOREACH_SAFE(tz->tokens, tk, tktmp) { ufree(tk->str); ufree(tk); } tz->tokens = NULL; } #define TZ_MAX_TK 1024 void tz_tokenize(Tokenizer *tz) { size_t len = string_len(tz->str); for (size_t i = 0; i < len; i++) { if (tz->str[i] == '\'') { char *str = umalloc(TZ_MAX_TK); string_memset(str, 0, TZ_MAX_TK); i++; size_t j = 0; while (i < len && tz->str[i] != '\'') { str[j++] = tz->str[i++]; } Token *tk = umalloc(sizeof(*tk)); tk->str = str; tk->next = NULL; LL_APPEND(tz->tokens, tk); } else { char *tkstr = umalloc(TZ_MAX_TK); string_memset(tkstr, 0, TZ_MAX_TK); size_t j = 0; while (i < len && !string_chr_isspace(tz->str[i])) { tkstr[j++] = tz->str[i++]; } Token *tk = umalloc(sizeof(*tk)); tk->str = tkstr; tk->next = NULL; LL_APPEND(tz->tokens, tk); } } } void tz_classify(Tokenizer *tz) { Token *tk, *tktmp; LL_FOREACH_SAFE(tz->tokens, tk, tktmp) { if (tk->str[0] == '"') { tk->type = TOK_STRING; } else if (tk->str[0] == '%') { RtCmd *cmd, *cmdtmp; LL_FOREACH_SAFE(RTCMDS, cmd, cmdtmp) { if (string_strcmp(tk->str, cmd->cmdname) == 0) { tk->type = TOK_CMD; tk->cmd = cmd; break; } } } else { tk->type = TOK_MISC; } } } void tz_expandspecial(Tokenizer *tz) { Token *tk, *tktmp; LL_FOREACH_SAFE(tz->tokens, tk, tktmp) { if (tk->str[0] == '$' && string_len(tk->str) > 1) { RtAlias *alias, *aliastmp; LL_FOREACH_SAFE(RTALIASES, alias, aliastmp) { if (string_strcmp(alias->namebuf, tk->str+1) == 0) { ufree(tk->str); size_t len = string_len(alias->valbuf)+1; tk->str = umalloc(len); string_memset(tk->str, 0, len); string_memcpy(tk->str, alias->valbuf, string_len(alias->valbuf)); break; } } } } } #define LINE_MAX 1024 bool interp_runstring(char *string, InterpResult **res, bool logcmds, bool interactive) { *res = &RES; string_memset(RES.errmsg, 0, sizeof(RES.errmsg)); rt_init(); bool ok = true; char *line = string_tokenizealloc(string, "\n"); while (line != NULL) { if (logcmds) { uprintf("+%s\n", line); } Tokenizer tz; ZERO(&tz); tz_init(&tz, line); tz_tokenize(&tz); tz_classify(&tz); tz_expandspecial(&tz); Token *cmdtk = tz.tokens; if (cmdtk->type == TOK_CMD) { ok = cmdtk->cmd->fn(cmdtk->next); if (!ok) { usprintf(RES.errmsg, "cmd %s failed", cmdtk->str); goto next; } } else if (cmdtk->type == TOK_MISC) { size_t argslen1; Token *argtk, *argtktmp; LL_FOREACH_SAFE_IDX(cmdtk->next, argtk, argtktmp, argslen1); size_t i; char **args1 = (char **)umalloc(sizeof(char *) * argslen1); LL_FOREACH_SAFE_IDX(cmdtk->next, argtk, argtktmp, i) { args1[i] = (char *)umalloc(PROC_ARG_MAX); string_memset(args1[i], 0, PROC_ARG_MAX); string_memcpy(args1[i], argtk->str, MIN(string_len(argtk->str), PROC_ARG_MAX)); } int32_t app = processctl(-1, PCTL_SPAWN, (uint64_t)cmdtk->str, (uint64_t)args1, argslen1); if (app < 0) { usprintf(RES.errmsg, "Could not run %s: %s\n", cmdtk->str, ERRSTRING(app)); ok = false; goto cleanup; } processctl(app, PCTL_RUN, 0, 0, 0); uint8_t b; while(processctl(app, PCTL_POLLSTATE, 0, 0, 0) != 4) { if (interactive) { int32_t nrd = ipcpipe(PID, IPCPIPE_IN, IPCPIPE_READ, &b, 1); if (nrd > 0 && b == C('S')) { processctl(app, PCTL_KILL, 0, 0, 0); goto cleanup; } } schedrelease(); } cleanup: { for (size_t j = 0; j < argslen1; j++) ufree(args1[j]); ufree(args1); } } next: tz_free(&tz); ufree(line); line = string_tokenizealloc(NULL, "\n"); } done: return ok; }