aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2015-03-13 15:37:30 +0100
committerAlex Auvolat <alex@adnab.me>2015-03-13 15:37:30 +0100
commit41a4f5309ef298da764bf1dca1254e734a4417f0 (patch)
tree43e2e820f39c09db36d3a12e3fb2495cb38adca7
parentd0dc9f38184956af49379d7e2585756523cfa4c1 (diff)
downloadkogata-41a4f5309ef298da764bf1dca1254e734a4417f0.tar.gz
kogata-41a4f5309ef298da764bf1dca1254e734a4417f0.zip
Basis for a shell.
-rw-r--r--Makefile2
-rwxr-xr-xmake_cdrom.sh1
-rw-r--r--src/lib/include/stdio.h14
-rw-r--r--src/lib/libkogata/Makefile3
-rw-r--r--src/lib/libkogata/stdio.c66
-rw-r--r--src/sysbin/login/main.c26
-rw-r--r--src/sysbin/shell/Makefile12
-rw-r--r--src/sysbin/shell/main.c27
-rw-r--r--src/sysbin/terminal/main.c67
9 files changed, 191 insertions, 27 deletions
diff --git a/Makefile b/Makefile
index 7e026bb..e29c08b 100644
--- a/Makefile
+++ b/Makefile
@@ -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;