315 lines
6.8 KiB
C
315 lines
6.8 KiB
C
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <ulib.h>
|
|
#include "runtime.h"
|
|
#include "interp.h"
|
|
#include "config.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);
|
|
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;
|
|
}
|
|
|
|
bool rt_setlogcmds(Token *tks) {
|
|
Token *tk = tks;
|
|
|
|
if (tk == NULL) {
|
|
return false;
|
|
}
|
|
|
|
bool set;
|
|
|
|
if (string_strcmp(tk->str, "yes") == 0) {
|
|
set = true;
|
|
} else if (string_strcmp(tk->str, "no") == 0) {
|
|
set = false;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
CONFIG.logcmds = set;
|
|
|
|
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);
|
|
RTCMD("setlogcmds", &rt_setlogcmds);
|
|
}
|