summaryrefslogtreecommitdiff
path: root/userland/terminal
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-22 19:50:38 +0200
committerAnton Kling <anton@kling.gg>2023-10-22 19:50:38 +0200
commit4e09bca9e34c226b6d7e34b4fa11248405fd988e (patch)
tree80f156b7940d9d19971395f335530170c69516c7 /userland/terminal
Move everything into a new repo.
Diffstat (limited to 'userland/terminal')
-rw-r--r--userland/terminal/Makefile15
-rw-r--r--userland/terminal/term.c166
2 files changed, 181 insertions, 0 deletions
diff --git a/userland/terminal/Makefile b/userland/terminal/Makefile
new file mode 100644
index 0000000..330f6e0
--- /dev/null
+++ b/userland/terminal/Makefile
@@ -0,0 +1,15 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -static -fsanitize=shift,signed-integer-overflow,bounds
+LIB=-L../libgui -lgui -L../json -ljson -L../libc -lc -lgcc
+INC=-I../libc/ -I../json/ -I../libgui/
+BINS=term
+all: $(BINS)
+
+term.o: term.c
+ $(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $<
+
+term: term.o
+ $(CC) -nostdlib $(CFLAGS) -o $@ $^ $(LIB)
+
+clean:
+ rm $(BINS) *.o
diff --git a/userland/terminal/term.c b/userland/terminal/term.c
new file mode 100644
index 0000000..8a2ae83
--- /dev/null
+++ b/userland/terminal/term.c
@@ -0,0 +1,166 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <json.h>
+#include <libgui.h>
+#include <poll.h>
+#include <pty.h>
+#include <socket.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define TERM_BACKGROUND 0x000000
+
+int cmdfd;
+GUI_Window *global_w;
+uint32_t screen_pos_x = 0;
+uint32_t screen_pos_y = 0;
+int serial_fd;
+
+void execsh(void) {
+ char *argv[] = {NULL};
+ execv("/sh", argv);
+}
+
+uint32_t cursor_pos_x = 0;
+uint32_t cursor_pos_y = 0;
+
+void screen_remove_old_cursor() {
+ GUI_OverwriteFont(global_w, cursor_pos_x, cursor_pos_y, TERM_BACKGROUND);
+}
+
+void screen_update_cursor() {
+ GUI_OverwriteFont(global_w, screen_pos_x, screen_pos_y, 0xFFFFFF);
+ cursor_pos_x = screen_pos_x;
+ cursor_pos_y = screen_pos_y;
+}
+
+void screen_putchar(uint32_t c) {
+ if (c == '\n') {
+ screen_pos_x = 0;
+ screen_pos_y += 8;
+ screen_remove_old_cursor();
+ screen_update_cursor();
+ return;
+ }
+ if (screen_pos_y > global_w->sy - 8) {
+ uint8_t line[global_w->sx * sizeof(uint32_t)];
+ for (int i = 0; i < global_w->sy - 8; i++) {
+ memcpy(line, global_w->bitmap_ptr + ((i + 8) * global_w->sx),
+ global_w->sx * sizeof(uint32_t));
+ memcpy(global_w->bitmap_ptr + (i * global_w->sx), line,
+ global_w->sx * sizeof(uint32_t));
+ }
+ for (int i = 0; i < global_w->sx; i += 8) {
+ GUI_OverwriteFont(global_w, i, screen_pos_y - 8, TERM_BACKGROUND);
+ }
+ screen_pos_x = 0;
+ screen_pos_y -= 8;
+ }
+ GUI_DrawFont(global_w, screen_pos_x, screen_pos_y, c);
+ screen_pos_x += 8;
+ if (screen_pos_x >= global_w->sx - 8) {
+ screen_pos_x = 0;
+ screen_pos_y += 8;
+ }
+ screen_update_cursor();
+}
+
+void screen_delete_char(void) {
+ GUI_OverwriteFont(global_w, screen_pos_x, screen_pos_y, TERM_BACKGROUND);
+ screen_pos_x -= 8;
+ GUI_OverwriteFont(global_w, screen_pos_x, screen_pos_y, TERM_BACKGROUND);
+ screen_update_cursor();
+}
+
+void screen_print(const unsigned char *s, int l) {
+ for (; l; l--, s++) {
+ if ('\b' == *s) {
+ screen_delete_char();
+ continue;
+ }
+ screen_putchar((uint32_t)*s);
+ }
+}
+
+void newtty(void) {
+ int m;
+ int s;
+ openpty(&m, &s, NULL, NULL, NULL);
+ int pid = fork();
+ if (0 == pid) {
+ dup2(s, 0);
+ dup2(s, 1);
+ dup2(s, 2);
+ execsh();
+ return;
+ }
+ close(s);
+ cmdfd = m;
+}
+
+void writetty(const char *b, size_t len) {
+ write(serial_fd, b, len);
+ for (int rc; len; len -= rc) {
+ rc = write(cmdfd, b, len);
+ if (-1 == rc) {
+ perror("write");
+ assert(0);
+ }
+ }
+}
+
+void run() {
+ char buffer[4096];
+ struct pollfd fds[2];
+ fds[0].fd = cmdfd;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ fds[1].fd = global_w->ws_socket;
+ fds[1].events = POLLIN;
+ fds[1].revents = 0;
+ for (;; fds[0].revents = fds[1].revents = 0) {
+ poll(fds, 2, 0);
+ if (fds[0].revents & POLLIN) {
+ int rc;
+ if ((rc = read(cmdfd, buffer, 4096))) {
+ screen_print(buffer, rc);
+ GUI_UpdateWindow(global_w);
+ }
+ }
+ if (fds[1].revents & POLLIN) {
+ WS_EVENT e;
+ int rc;
+ if (0 >= (rc = read(global_w->ws_socket, &e, sizeof(e))))
+ continue;
+ if (1 == e.ev.release)
+ continue;
+ if (0 == e.ev.c)
+ continue;
+ write(cmdfd, &e.ev.c, 1);
+ }
+ }
+}
+
+int main(void) {
+ open("/dev/serial", O_RDWR, 0);
+ open("/dev/serial", O_RDWR, 0);
+ printf("running the terminal\n");
+ int pid = fork();
+ if (0 == pid) {
+ char *argv[] = {NULL};
+ execv("/ws", argv);
+ }
+
+ global_w = GUI_CreateWindow(20, 20, 250 * 4, 150 * 4);
+ assert(global_w);
+ for (int i = 0; i < 250 * 150 * 4 * 4; i++)
+ global_w->bitmap_ptr[i] = TERM_BACKGROUND;
+ // memset(global_w->bitmap_ptr, 0x0, 50 * 50);
+ GUI_UpdateWindow(global_w);
+ newtty();
+ run();
+ return 0;
+}