diff --git a/ulib/_premain.c b/ulib/_premain.c index 5a0845f..6dfc53d 100644 --- a/ulib/_premain.c +++ b/ulib/_premain.c @@ -21,7 +21,7 @@ void clearbss(void) { } } -#define MAX_ARGS 15 +#define MAX_ARGS 25 static char *_args[MAX_ARGS]; size_t _argslen; @@ -34,14 +34,10 @@ size_t argslen(void) { return _argslen; } -Dev_t termdev; - // ulib initialization goes here void _premain(void) { clearbss(); - devctl(&termdev, DEVCTL_GET_HANDLE, (uint8_t *)DEV_TERMDEV, 0, 0); - for (size_t i = 0; i < ARRLEN(_args); i++) { _args[i] = umalloc(PROC_ARG_MAX); } diff --git a/ulib/linearlist.h b/ulib/linearlist.h new file mode 100644 index 0000000..15be0e3 --- /dev/null +++ b/ulib/linearlist.h @@ -0,0 +1,30 @@ +#ifndef ULIB_LINEARLIST_H_ +#define ULIB_LINEARLIST_H_ + +#include +#include + +#define LINLIST_APPEND(lst, d) \ + do { \ + if ((lst)->data == NULL) { \ + (lst)->capacity = 1; \ + (lst)->data = umalloc(sizeof(*(lst)->data) * (lst)->capacity); \ + } else { \ + if ((lst)->count == (lst)->capacity) { \ + (lst)->capacity *= 2; \ + (lst)->data = urealloc((lst)->data, sizeof(*(lst)->data) * (lst)->capacity); \ + } \ + } \ + (lst)->data[(lst)->count++] = (d); \ + } while(0) + +#define LINLIST_FREE(lst) \ + do { \ + if ((lst)->data != NULL) { \ + ufree((lst)->data); \ + (lst)->data = NULL; \ + } \ + (lst)->count = 0; \ + } while(0) + +#endif // ULIB_LINEARLIST_H_ diff --git a/ulib/putchar.c b/ulib/putchar.c index 61994da..415407d 100644 --- a/ulib/putchar.c +++ b/ulib/putchar.c @@ -1,11 +1,8 @@ #include #include #include -#include #include -extern Dev_t termdev; - void putchar_(char c) { - devctl(&termdev, 0x00, (uint8_t *)&c, 1, 0); + ipcpipe(-1, IPCPIPE_OUT, IPCPIPE_WRITE, (uint8_t *)&c, 1); } diff --git a/ulib/string/stringbuffer.c b/ulib/string/stringbuffer.c new file mode 100644 index 0000000..996d636 --- /dev/null +++ b/ulib/string/stringbuffer.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include + +void stringbuffer_init(StringBuffer *sb) { + string_memset(sb, 0, sizeof(*sb)); +} + +void stringbuffer_free(StringBuffer *sb) { + LINLIST_FREE(sb); +} + +void stringbuffer_appendchar(StringBuffer *sb, char c) { + LINLIST_APPEND(sb, c); +} + +void stringbuffer_appendcstr(StringBuffer *sb, char *cstr) { + char *s = cstr; + while (*s) { + stringbuffer_appendchar(sb, *s); + s++; + } +} diff --git a/ulib/string/stringbuffer.h b/ulib/string/stringbuffer.h new file mode 100644 index 0000000..3fd0114 --- /dev/null +++ b/ulib/string/stringbuffer.h @@ -0,0 +1,15 @@ +#ifndef ULIB_STRING_STRINGBUFFER_H_ +#define ULIB_STRING_STRINGBUFFER_H_ + +typedef struct { + size_t count; + size_t capacity; + char *data; +} StringBuffer; + +void stringbuffer_init(StringBuffer *sb); +void stringbuffer_free(StringBuffer *sb); +void stringbuffer_appendchar(StringBuffer *sb, char c); +void stringbuffer_appendcstr(StringBuffer *sb, char *cstr); + +#endif // ULIB_STRING_STRINGBUFFER_H_ diff --git a/ulib/ulib.h b/ulib/ulib.h index 414ea09..a9ee4d0 100644 --- a/ulib/ulib.h +++ b/ulib/ulib.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/ulib/umalloc/umalloc.c b/ulib/umalloc/umalloc.c index d05d49b..ade581c 100644 --- a/ulib/umalloc/umalloc.c +++ b/ulib/umalloc/umalloc.c @@ -118,3 +118,33 @@ void ufree(void *ptr_) { } } +void *urealloc(void *ptr, size_t newsize) { + void *new; + + UmBlock *block = (UmBlock *)(ptr - sizeof(UmBlock)); + if (block->magic != BLOCK_MAGIC || block->data != ptr) { + goto err; + } + + if (!ptr) { + new = umalloc(newsize); + if (!new) { + goto err; + } + } else { + if (block->size < newsize) { + new = umalloc(newsize); + if (!new) { + goto err; + } + string_memcpy(new, ptr, block->size); + ufree(ptr); + } else { + new = ptr; + } + } + return new; + +err: + return NULL; +} diff --git a/ulib/umalloc/umalloc.h b/ulib/umalloc/umalloc.h index b287d84..96fd7f8 100644 --- a/ulib/umalloc/umalloc.h +++ b/ulib/umalloc/umalloc.h @@ -6,5 +6,6 @@ void *umalloc(size_t size); void ufree(void *ptr_); +void *urealloc(void *ptr, size_t newsize); #endif // ULIB_UMALLOC_UMALLOC_H_ diff --git a/user/init/main.c b/user/init/main.c index 619dbbb..7857b3b 100644 --- a/user/init/main.c +++ b/user/init/main.c @@ -3,15 +3,27 @@ uint64_t PID; Dev_t ps2kbdev; +Dev_t termdev; void tb_runinitscript(void) { + devctl(&termdev, DEVCTL_GET_HANDLE, (uint8_t *)DEV_TERMDEV, 0, 0); + char *tbargs[] = { "-m", "runfile", "-f", "base:/scripts/init.tb", "-logcmds", "yes" }; - int32_t tb = processctl(-1, PCTL_SPAWN, (uint64_t)"base:/bin/tb", (uint64_t)&tbargs, ARRLEN(tbargs)); + int32_t tb = processctl(-1, PCTL_SPAWN, (uint64_t)"base:/bin/tb", (uint64_t)(char **)tbargs, ARRLEN(tbargs)); processctl(tb, PCTL_RUN, 0, 0, 0); while(processctl(tb, PCTL_POLLSTATE, 0, 0, 0) != 4) { - int32_t r = devctl(&ps2kbdev, 0x00, NULL, 0, 0); + int32_t r; + + char buf[100]; + string_memset(buf, 0, sizeof(buf)); + r = ipcpipe(tb, IPCPIPE_OUT, IPCPIPE_READ, (uint8_t *)buf, sizeof(buf)-1); + if (r > 0) { + devctl(&termdev, 0x00, (uint8_t *)buf, string_len(buf), 0); + } + + r = devctl(&ps2kbdev, 0x00, NULL, 0, 0); if (r != E_NOTYET) { uint8_t b = r; ipcpipe(tb, IPCPIPE_IN, IPCPIPE_WRITE, &b, 1); diff --git a/user/tb/main.c b/user/tb/main.c index ae4d032..3fdee2e 100644 --- a/user/tb/main.c +++ b/user/tb/main.c @@ -10,13 +10,19 @@ PID_t PID; struct { char *modestr; - enum { MODE_INTERACTIVE = 1, MODE_RUNFILE = 2 } mode; + enum { + MODE_INTERACTIVE = 1, + MODE_RUNFILE = 2, + MODE_RUNSTRING = 3, + } mode; char *filepath; bool logcmds; char *preloadpath; + + char *runstring; } CONFIG; static Arg ARGS[] = { @@ -24,6 +30,7 @@ static Arg ARGS[] = { ARG("-f", ARG_STRING, &CONFIG.filepath), ARG("-logcmds", ARG_BOOL, &CONFIG.logcmds), ARG("-preload", ARG_STRING, &CONFIG.preloadpath), + ARG("-rs", ARG_STRING, &CONFIG.runstring), ARG_END(), }; @@ -40,6 +47,8 @@ void set_config(void) { CONFIG.mode = MODE_INTERACTIVE; } else if (string_strcmp(CONFIG.modestr, "runfile") == 0) { CONFIG.mode = MODE_RUNFILE; + } else if (string_strcmp(CONFIG.modestr, "runstring") == 0) { + CONFIG.mode = MODE_RUNSTRING; } else { LOG(LOG_ERR, "Unknown mode %s\n", CONFIG.modestr); } @@ -142,7 +151,6 @@ void main(void) { set_config(); if (CONFIG.preloadpath != NULL) { - LOG(LOG_INF, "Preloading script: %s\n", CONFIG.preloadpath); do_file(CONFIG.preloadpath); } @@ -154,5 +162,21 @@ void main(void) { return; } do_file(CONFIG.filepath); + } else if (CONFIG.mode == MODE_RUNSTRING) { + if (CONFIG.runstring == NULL) { + uprintf("Run string is empty\n"); + return; + } + InterpResult *res; + if (CONFIG.runstring[0] == '\'') { + CONFIG.runstring[0] = ' '; + } + size_t len = string_len(CONFIG.runstring); + if (CONFIG.runstring[len] == '\'') { + CONFIG.runstring[len] = ' '; + } + if (!interp_runstring(CONFIG.runstring, &res, CONFIG.logcmds, false)) { + LOG(LOG_ERR, "%s\n", res->errmsg); + } } } diff --git a/user/tb/runtime.c b/user/tb/runtime.c index 2a017f1..71dcf3a 100644 --- a/user/tb/runtime.c +++ b/user/tb/runtime.c @@ -52,8 +52,73 @@ bool rt_PID(Token *tks) { return true; } +bool rt_subsh(Token *tks) { + bool ok = true; + + char *prepended_args[] = { "-m", "runstring", "-preload", "base:/scripts/rc.tb", "-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 = processctl(-1, PCTL_SPAWN, (uint64_t)"base:/bin/tb", (uint64_t)args1, ARRLEN(prepended_args)+1); + if (app < 0) { + ok = false; + goto done; + } + + StringBuffer outbuf; + stringbuffer_init(&outbuf); + + ipcpipe(PID, 10, IPCPIPE_MAKE, NULL, 0); + ipcpipe(app, IPCPIPE_OUT, IPCPIPE_REPLACE, (uint8_t *)PID, 10); + + processctl(app, PCTL_RUN, 0, 0, 0); + + while (processctl(app, PCTL_POLLSTATE, 0, 0, 0) != 4) { + int32_t r; + char buf[100]; + string_memset(buf, 0, sizeof(buf)); + + r = ipcpipe(app, IPCPIPE_OUT, IPCPIPE_READ, (uint8_t *)buf, sizeof(buf)-1); + stringbuffer_appendcstr(&outbuf, buf); + } + + ipcpipe(PID, 10, IPCPIPE_DELETE, NULL, 0); + + stringbuffer_free(&outbuf); + +done: + for (size_t i = 0; i < ARRLEN(prepended_args)+1; i++) { + ufree(args1[i]); + } + ufree(s); + + return ok; +} + void rt_init(void) { RTCMD("%print", &rt_print); RTCMD("%mkalias", &rt_mkalias); RTCMD("%PID", &rt_PID); + RTCMD("%subsh", &rt_subsh); }