aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--events.c2
-rw-r--r--pty-unix.c91
-rw-r--r--pty-unix.h23
-rw-r--r--runes.h3
-rw-r--r--term.c5
-rw-r--r--term.h1
7 files changed, 125 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index edbc068..397dd7f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
OUT = runes
-OBJ = runes.o display.o term.o events.o window-xlib.o
+OBJ = runes.o display.o term.o events.o window-xlib.o pty-unix.o
LIBS = cairo cairo-xlib libuv
CFLAGS ?= -g -Wall -Wextra -Werror
LDFLAGS ?= -g -Wall -Wextra -Werror
diff --git a/events.c b/events.c
index 7112b17..e721518 100644
--- a/events.c
+++ b/events.c
@@ -2,7 +2,7 @@
void runes_handle_keyboard_event(RunesTerm *t, char *buf, size_t len)
{
- runes_display_glyph(t, buf, len);
+ runes_pty_backend_write(t, buf, len);
}
void runes_handle_close_window(RunesTerm *t)
diff --git a/pty-unix.c b/pty-unix.c
new file mode 100644
index 0000000..71fde3a
--- /dev/null
+++ b/pty-unix.c
@@ -0,0 +1,91 @@
+#define _XOPEN_SOURCE 600
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "runes.h"
+
+void runes_pty_backend_init(RunesTerm *t)
+{
+ RunesPtyBackend *pty;
+
+ pty = &t->pty;
+ pty->master = posix_openpt(O_RDWR);
+ grantpt(pty->master);
+ unlockpt(pty->master);
+ pty->slave = open(ptsname(pty->master), O_RDWR);
+
+ pty->child_pid = fork();
+ if (pty->child_pid) {
+ close(pty->slave);
+ pty->slave = -1;
+ }
+ else {
+ char *shell;
+
+ setsid();
+ ioctl(pty->slave, TIOCSCTTY, NULL);
+
+ close(pty->master);
+
+ dup2(pty->slave, 0);
+ dup2(pty->slave, 1);
+ dup2(pty->slave, 2);
+
+ close(pty->slave);
+
+ shell = getenv("SHELL");
+ if (!shell) {
+ shell = "/bin/sh";
+ }
+
+ execl(shell, shell, (char *)NULL);
+ }
+}
+
+static void runes_read_pty(uv_work_t *req)
+{
+ RunesPtyLoopData *data;
+
+ data = (RunesPtyLoopData *)req->data;
+ data->len = read(data->data.t->pty.master, data->buf, RUNES_PTY_BUFFER_LENGTH);
+}
+
+static void runes_got_pty_data(uv_work_t *req, int status)
+{
+ RunesTerm *t;
+ RunesPtyLoopData *data;
+
+ UNUSED(status);
+ data = (RunesPtyLoopData *)req->data;
+ t = data->data.t;
+
+ runes_display_glyph(data->data.t, data->buf, data->len);
+
+ uv_queue_work(t->loop, req, runes_read_pty, runes_got_pty_data);
+}
+
+void runes_pty_backend_loop_init(RunesTerm *t)
+{
+ void *data;
+
+ data = malloc(sizeof(RunesPtyLoopData));
+ ((RunesLoopData *)data)->req.data = data;
+ ((RunesLoopData *)data)->t = t;
+
+ uv_queue_work(t->loop, data, runes_read_pty, runes_got_pty_data);
+}
+
+void runes_pty_backend_write(RunesTerm *t, char *buf, size_t len)
+{
+ write(t->pty.master, buf, len);
+}
+
+void runes_pty_backend_cleanup(RunesTerm *t)
+{
+ RunesPtyBackend *pty;
+
+ pty = &t->pty;
+ close(pty->master);
+}
diff --git a/pty-unix.h b/pty-unix.h
new file mode 100644
index 0000000..ab5acc2
--- /dev/null
+++ b/pty-unix.h
@@ -0,0 +1,23 @@
+#ifndef _RUNES_PTY_H
+#define _RUNES_PTY_H
+
+#define RUNES_PTY_BUFFER_LENGTH 4096
+
+struct runes_pty {
+ int master;
+ int slave;
+ pid_t child_pid;
+};
+
+typedef struct {
+ RunesLoopData data;
+ size_t len;
+ char buf[RUNES_PTY_BUFFER_LENGTH];
+} RunesPtyLoopData;
+
+void runes_pty_backend_init(RunesTerm *t);
+void runes_pty_backend_loop_init(RunesTerm *t);
+void runes_pty_backend_write(RunesTerm *t, char *buf, size_t len);
+void runes_pty_backend_cleanup(RunesTerm *t);
+
+#endif
diff --git a/runes.h b/runes.h
index bf51186..9b90b84 100644
--- a/runes.h
+++ b/runes.h
@@ -6,15 +6,18 @@
struct runes_term;
struct runes_window;
+struct runes_pty;
struct runes_loop_data;
typedef struct runes_term RunesTerm;
typedef struct runes_window RunesWindowBackend;
+typedef struct runes_pty RunesPtyBackend;
typedef struct runes_loop_data RunesLoopData;
#include "events.h"
#include "window-xlib.h"
+#include "pty-unix.h"
#include "term.h"
#include "display.h"
diff --git a/term.c b/term.c
index 1335678..bf1f078 100644
--- a/term.c
+++ b/term.c
@@ -4,8 +4,12 @@
void runes_term_init(RunesTerm *t, int argc, char *argv[])
{
+ runes_pty_backend_init(t);
+
t->loop = uv_default_loop();
+ runes_pty_backend_loop_init(t);
+
runes_window_backend_init(t, argc, argv);
t->cr = cairo_create(runes_window_backend_surface_create(t));
}
@@ -14,4 +18,5 @@ void runes_term_cleanup(RunesTerm *t)
{
cairo_destroy(t->cr);
runes_window_backend_cleanup(t);
+ runes_pty_backend_cleanup(t);
}
diff --git a/term.h b/term.h
index dc00387..3993edf 100644
--- a/term.h
+++ b/term.h
@@ -3,6 +3,7 @@
struct runes_term {
RunesWindowBackend w;
+ RunesPtyBackend pty;
cairo_t *cr;
uv_loop_t *loop;