176 lines
4.2 KiB
C
176 lines
4.2 KiB
C
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <ulib.h>
|
|
#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;
|
|
}
|