diff options
author | Alex Auvolat <alex@adnab.me> | 2015-03-13 15:37:30 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2015-03-13 15:37:30 +0100 |
commit | 41a4f5309ef298da764bf1dca1254e734a4417f0 (patch) | |
tree | 43e2e820f39c09db36d3a12e3fb2495cb38adca7 | |
parent | d0dc9f38184956af49379d7e2585756523cfa4c1 (diff) | |
download | kogata-41a4f5309ef298da764bf1dca1254e734a4417f0.tar.gz kogata-41a4f5309ef298da764bf1dca1254e734a4417f0.zip |
Basis for a shell.
-rw-r--r-- | Makefile | 2 | ||||
-rwxr-xr-x | make_cdrom.sh | 1 | ||||
-rw-r--r-- | src/lib/include/stdio.h | 14 | ||||
-rw-r--r-- | src/lib/libkogata/Makefile | 3 | ||||
-rw-r--r-- | src/lib/libkogata/stdio.c | 66 | ||||
-rw-r--r-- | src/sysbin/login/main.c | 26 | ||||
-rw-r--r-- | src/sysbin/shell/Makefile | 12 | ||||
-rw-r--r-- | src/sysbin/shell/main.c | 27 | ||||
-rw-r--r-- | src/sysbin/terminal/main.c | 67 |
9 files changed, 191 insertions, 27 deletions
@@ -1,6 +1,6 @@ DIRS = src/common/libkogata src/common/libc src/common/libalgo \ src/kernel src/lib/libkogata \ - src/sysbin/init src/sysbin/giosrv src/sysbin/login src/sysbin/terminal \ + src/sysbin/init src/sysbin/giosrv src/sysbin/login src/sysbin/terminal src/sysbin/shell \ res/fonts res/keymaps all: diff --git a/make_cdrom.sh b/make_cdrom.sh index d42a33c..fc51638 100755 --- a/make_cdrom.sh +++ b/make_cdrom.sh @@ -16,6 +16,7 @@ mkdir -p cdrom/sys/bin cp src/sysbin/giosrv/giosrv.bin cdrom/sys/bin cp src/sysbin/login/login.bin cdrom/sys/bin cp src/sysbin/terminal/terminal.bin cdrom/sys/bin +cp src/sysbin/shell/shell.bin cdrom/sys/bin for BIN in cdrom/sys/bin/*.bin; do strip $BIN; done mkdir -p cdrom/sys/fonts diff --git a/src/lib/include/stdio.h b/src/lib/include/stdio.h new file mode 100644 index 0000000..4b300da --- /dev/null +++ b/src/lib/include/stdio.h @@ -0,0 +1,14 @@ +#pragma once + +#include <stddef.h> +#include <stdarg.h> +#include <stdint.h> + +void putchar(int c); +void puts(char* s); +void printf(char* arg, ...); + +int getchar(); +void getline(char* buf, size_t l); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/lib/libkogata/Makefile b/src/lib/libkogata/Makefile index a02a862..20c6dee 100644 --- a/src/lib/libkogata/Makefile +++ b/src/lib/libkogata/Makefile @@ -1,5 +1,6 @@ OBJ = start.o malloc.o debug.o syscall.o user_region.o \ - mainloop.o gip.o draw.o keyboard.o + mainloop.o gip.o draw.o keyboard.o \ + stdio.o LIB = ../../common/libkogata/libkogata.lib ../../common/libalgo/libalgo.lib ../../common/libc/libc.lib diff --git a/src/lib/libkogata/stdio.c b/src/lib/libkogata/stdio.c new file mode 100644 index 0000000..1c298ad --- /dev/null +++ b/src/lib/libkogata/stdio.c @@ -0,0 +1,66 @@ +#include <syscall.h> + +#include <printf.h> +#include <stdio.h> + + +fd_t stdio = 1; + +int getc() { + sel_fd_t fd; + fd.fd = stdio; + fd.req_flags = SEL_READ; + ASSERT(select(&fd, 1, -1)); + ASSERT(fd.got_flags & SEL_READ); + + char chr; + size_t sz = read(stdio, 0, 1, &chr); + ASSERT(sz == 1); + return chr; +} + + +void putc(int c) { + char chr = c; + write(stdio, 0, 1, &chr); +} + +void puts(char* s) { + while (*s) putc(*(s++)); +} + +void getline(char* buf, size_t l) { + size_t i = 0; + while (true) { + int c = getc(); + if (c == '\n') { + putc('\n'); + buf[i] = 0; + break; + } else if (c == '\b') { + if (i > 0) { + i--; + putc('\b'); + } + } else if (c >= ' ') { + buf[i] = c; + if (i < l-1) { + i++; + putc(c); + } + } + } +} + +void printf(char* fmt, ...) { + va_list ap; + char buffer[256]; + + va_start(ap, fmt); + vsnprintf(buffer, 256, fmt, ap); + va_end(ap); + + puts(buffer); +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/sysbin/login/main.c b/src/sysbin/login/main.c index 5d8840b..359d677 100644 --- a/src/sysbin/login/main.c +++ b/src/sysbin/login/main.c @@ -8,6 +8,9 @@ int main(int argc, char **argv) { dbg_print("[login] Starting up.\n"); + // communication channel between terminal && shell + fd_pair_t tc = make_channel(false); + // just launch a terminal pid_t term_pid = new_proc(); if (term_pid == 0) { @@ -16,17 +19,32 @@ int main(int argc, char **argv) { bool ok; - ok = bind_fs(term_pid, "root", "root") - && bind_fs(term_pid, "sys", "sys") + ok = bind_fs(term_pid, "sys", "sys") && bind_fs(term_pid, "config", "config") - && bind_fd(term_pid, 1, 1); + && bind_fd(term_pid, 1, 1) + && bind_fd(term_pid, 2, tc.a); if (!ok) PANIC("[login] Could not bind to terminal process."); ok = proc_exec(term_pid, "sys:/bin/terminal.bin"); if (!ok) PANIC("[login] Could not run terminal.bin"); + // and launch the shell + pid_t shell_pid = new_proc(); + if (shell_pid == 0) { + PANIC("[login] Could not launch shell"); + } + + ok = bind_fs(shell_pid, "root", "root") + && bind_fs(shell_pid, "sys", "sys") + && bind_fs(shell_pid, "config", "config") + && bind_fd(shell_pid, 1, tc.b); + if (!ok) PANIC("[login] Could not bind to shell process."); + + ok = proc_exec(shell_pid, "sys:/bin/shell.bin"); + if (!ok) PANIC("[login] Could not run shell.bin"); + proc_status_t s; - proc_wait(term_pid, true, &s); + proc_wait(0, true, &s); return 0; } diff --git a/src/sysbin/shell/Makefile b/src/sysbin/shell/Makefile new file mode 100644 index 0000000..80d1009 --- /dev/null +++ b/src/sysbin/shell/Makefile @@ -0,0 +1,12 @@ + +OBJ = main.o + +LIB = ../../lib/libkogata/libkogata.lib + +CFLAGS = -I ./include -I ../../common/include -I ../../lib/include + +LDFLAGS = -T ../linker.ld -Xlinker -Map=shell.map + +OUT = shell.bin + +include ../../rules.make diff --git a/src/sysbin/shell/main.c b/src/sysbin/shell/main.c new file mode 100644 index 0000000..54cec06 --- /dev/null +++ b/src/sysbin/shell/main.c @@ -0,0 +1,27 @@ +#include <string.h> +#include <malloc.h> +#include <user_region.h> +#include <debug.h> + +#include <stdio.h> + +#include <syscall.h> + +int main(int argc, char **argv) { + dbg_printf("[shell] Starting\n"); + + /*fctl(stdio, FC_SET_BLOCKING, 0);*/ + + puts("Hello, world!\n"); + + while(true) { + puts("> "); + char buf[256]; + getline(buf, 256); + printf("You said: '%s'. I don't understand a word of that.\n\n", buf); + } + + return 0; +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/sysbin/terminal/main.c b/src/sysbin/terminal/main.c index 9ba7afe..133736b 100644 --- a/src/sysbin/terminal/main.c +++ b/src/sysbin/terminal/main.c @@ -27,6 +27,9 @@ typedef struct { int csrl, csrc; bool csr_visible; + mainloop_fd_t app; + char rd_c_buf; + char wr_c_buf; } term_t; void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m); @@ -35,6 +38,9 @@ void c_key_up(gip_handler_t *s, gip_msg_header *p); void c_unknown_msg(gip_handler_t *s, gip_msg_header *p); void c_fd_error(gip_handler_t *s); +void term_on_rd_c(mainloop_fd_t *fd); +void term_app_on_error(mainloop_fd_t *fd); + void c_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata); gip_handler_callbacks_t term_gip_cb = { @@ -76,6 +82,12 @@ int main(int argc, char **argv) { h->mainloop_item.fd = 1; mainloop_add_fd(&h->mainloop_item); + // setup communication with app + term.app.fd = 2; + term.app.on_error = term_app_on_error; + term.app.data = &term; + mainloop_expect(&term.app, &term.rd_c_buf, 1, term_on_rd_c); + gip_msg_header reset_msg = { .code = GIPC_RESET, .arg = 0 }; gip_cmd(h, &reset_msg, 0, c_async_initiate, 0); @@ -94,8 +106,10 @@ void term_draw_c(term_t *t, int l, int c) { ss[0] = t->scr_chars[l * t->w + c]; ss[1] = 0; - g_fillrect(t->fb, c * t->cw, l * t->ch, t->cw, t->ch, bg); - g_write(t->fb, c * t->cw, l * t->ch, ss, t->font, t->fg); + if (t->fb) { + g_fillrect(t->fb, c * t->cw, l * t->ch, t->cw, t->ch, bg); + g_write(t->fb, c * t->cw, l * t->ch, ss, t->font, t->fg); + } } void term_move_cursor(term_t *t, int l, int c) { @@ -111,7 +125,8 @@ void term_clear_screen(term_t *t) { for (int i = 0; i < t->w * t->h; i++) t->scr_chars[i] = ' '; - g_fillrect(t->fb, 0, 0, t->mode.width, t->mode.height, t->bg); + if (t->fb) + g_fillrect(t->fb, 0, 0, t->mode.width, t->mode.height, t->bg); term_move_cursor(t, 0, 0); } @@ -124,8 +139,10 @@ void term_scroll1(term_t *t) { } t->csrl--; - g_scroll_up(t->fb, t->ch); - g_fillrect(t->fb, 0, t->ch * (t->h - 1), t->cw * t->w, t->ch, t->bg); + if (t->fb) { + g_scroll_up(t->fb, t->ch); + g_fillrect(t->fb, 0, t->ch * (t->h - 1), t->cw * t->w, t->ch, t->bg); + } } void term_putc(term_t *t, int c) { @@ -135,8 +152,11 @@ void term_putc(term_t *t, int c) { } else if (c == '\b') { if (nc > 0) { nc--; - t->scr_chars[nl * t->w + nc] = ' '; + } else { + nl--; + nc = t->w - 1; } + t->scr_chars[nl * t->w + nc] = ' '; } else if (c == '\t') { while (nc % 4 != 0) nc++; } else if (c >= ' ' && c < 128) { @@ -198,6 +218,9 @@ void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) c->bg = g_color_rgb(c->fb, 0, 0, 0); c->fg = g_color_rgb(c->fb, 200, 200, 200); term_clear_screen(c); + + mainloop_rm_fd(&c->app); + mainloop_add_fd(&c->app); } else { dbg_printf("[terminal] Could not open framebuffer file %d\n", c->fd); } @@ -208,12 +231,7 @@ void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) void c_key_down(gip_handler_t *s, gip_msg_header *p) { term_t *c = (term_t*)s->data; - key_t k = keyboard_press(c->kb, p->arg); - - if (k.flags & KBD_CHAR) - dbg_printf("D %x %c\n", k.flags, k.key); - else - dbg_printf("D %x %d\n", k.flags, k.key); + keyboard_press(c->kb, p->arg); } void c_key_up(gip_handler_t *s, gip_msg_header *p) { @@ -221,18 +239,15 @@ void c_key_up(gip_handler_t *s, gip_msg_header *p) { key_t k = keyboard_release(c->kb, p->arg); - if (k.flags & KBD_CHAR) - dbg_printf("U %x %c\n", k.flags, k.key); - else - dbg_printf("U %x %d\n", k.flags, k.key); - + c->wr_c_buf = 0; if (k.flags & KBD_CHAR) { - term_putc(c, k.chr); + c->wr_c_buf = k.chr; } else { - if (k.key == KBD_CODE_RETURN) term_putc(c, '\n'); - if (k.key == KBD_CODE_TAB) term_putc(c, '\t'); - if (k.key == KBD_CODE_BKSP) term_putc(c, '\b'); + if (k.key == KBD_CODE_RETURN) c->wr_c_buf = '\n'; + if (k.key == KBD_CODE_TAB) c->wr_c_buf = '\t'; + if (k.key == KBD_CODE_BKSP) c->wr_c_buf = '\b'; } + mainloop_nonblocking_write(&c->app, &c->wr_c_buf, 1, false); } void c_unknown_msg(gip_handler_t *s, gip_msg_header *p) { @@ -243,6 +258,16 @@ void c_fd_error(gip_handler_t *s) { // TODO } +void term_on_rd_c(mainloop_fd_t *fd) { + term_t *t = (term_t*)fd->data; + + term_putc(t, t->rd_c_buf); +} + +void term_app_on_error(mainloop_fd_t *fd) { + // TODO +} + void c_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void* hdata) { term_t *c = (term_t*)s->data; c->sv_features = p->arg; |