#include #include #include #include "interp.h" #include "macros.h" #define LINEBUF_MAX 1024 uint64_t PID; struct { char *modestr; enum { MODE_INTERACTIVE = 1, MODE_RUNFILE = 2 } mode; char *filepath; bool logcmds; char *preloadpath; } CONFIG; static Arg ARGS[] = { ARG("-m", ARG_STRING, &CONFIG.modestr), ARG("-f", ARG_STRING, &CONFIG.filepath), ARG("-logcmds", ARG_BOOL, &CONFIG.logcmds), ARG("-preload", ARG_STRING, &CONFIG.preloadpath), ARG_END(), }; void do_file(char *filepath); void set_config(void) { int32_t ret; if ((ret = parse_args(args(), argslen(), ARGS)) < 0) { uprintf("Could not parse args: %d\n", ret); } if (CONFIG.modestr != NULL) { if (string_strcmp(CONFIG.modestr, "interactive") == 0) { CONFIG.mode = MODE_INTERACTIVE; } else if (string_strcmp(CONFIG.modestr, "runfile") == 0) { CONFIG.mode = MODE_RUNFILE; } else { LOG(LOG_ERR, "Unknown mode %s\n", CONFIG.modestr); } } else { CONFIG.mode = MODE_RUNFILE; } } void do_file(char *filepath) { int32_t ret; int32_t ioh = ioctl(IOCTL_NOHANDLE, IOCTL_OPENF, (uint64_t)filepath, IOCTL_F_READ, 0); if (ioh < 0) { LOG(LOG_ERR, "Could not open %s: %s\n", filepath, ERRSTRING(ioh)); return; } IoctlStat statbuf = {0}; ioctl(ioh, IOCTL_STAT, (uint64_t)&statbuf, 0, 0); if (statbuf.type != IOCTLSTAT_FILE) { LOG(LOG_ERR, "%s is not a file (%d)\n", filepath, statbuf.type); return; } uint8_t *buf = dlmalloc(statbuf.size+1); string_memset(buf, 0, statbuf.size+1); if ((ret = ioctl(ioh, IOCTL_READ, (uint64_t)buf, statbuf.size, 0)) < 0) { LOG(LOG_ERR, "Could not read %s (%d): %s\n", filepath, ioh, ERRSTRING(ioh)); goto done; } InterpResult *res; bool ok = interp_runstring((const char *)buf, &res, CONFIG.logcmds, CONFIG.mode == MODE_INTERACTIVE); if (!ok) { uprintf("Interpreter error:\n"); uprintf("%s\n", res->errmsg); goto done; } done: dlfree(buf); ioctl(ioh, IOCTL_CLOSEF, 0, 0, 0); } void do_mode_interactive(void) { char linebuf[LINEBUF_MAX]; size_t cursor; for(;;) { begin: uprintf("tb# "); cursor = 0; string_memset(linebuf, 0, LINEBUF_MAX); uint8_t b = 0; for (;;) { int32_t nrd = ipcpipe(PID, IPCPIPE_IN, IPCPIPE_READ, &b, 1); if (nrd > 0) { switch (b) { case C('C'): case 0xE9: uprintf("\n"); goto begin; break; case C('L'): uprintf(ANSIQ_CUR_SET(0, 0)); uprintf(ANSIQ_SCR_CLR_ALL); goto begin; break; } if (b == '\n') { break; } if (string_chr_isascii(b) && b != 0 && cursor < LINEBUF_MAX) { linebuf[cursor++] = b; uprintf("%c", b); } } } if (cursor < LINEBUF_MAX) { linebuf[cursor] = '\0'; } uprintf("\n"); InterpResult *res; if (!interp_runstring(linebuf, &res, CONFIG.logcmds, CONFIG.mode == MODE_INTERACTIVE)) { LOG(LOG_ERR, "%s\n", res->errmsg); } } } void main(void) { PID = processctl(-1, PCTL_GETPID, 0, 0, 0); set_config(); if (CONFIG.preloadpath != NULL) { LOG(LOG_INF, "Preloading script: %s\n", CONFIG.preloadpath); do_file(CONFIG.preloadpath); } if (CONFIG.mode == MODE_INTERACTIVE) { do_mode_interactive(); } else if (CONFIG.mode == MODE_RUNFILE) { if (CONFIG.filepath == NULL) { uprintf("No file provided\n"); return; } do_file(CONFIG.filepath); } }