From 6beb7818efb57851a042953937af72163f1bde6c Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Wed, 9 Apr 2014 00:11:10 -0400 Subject: spawn a shell process and run it on a pty not at all convinced that this is correct, but it at least does things --- Makefile | 2 +- events.c | 2 +- pty-unix.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pty-unix.h | 23 ++++++++++++++++ runes.h | 3 +++ term.c | 5 ++++ term.h | 1 + 7 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 pty-unix.c create mode 100644 pty-unix.h 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 +#include +#include +#include + +#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; -- cgit v1.2.3-54-g00ecf