diff options
author | Jesse Luehrs <doy@tozt.net> | 2014-04-09 00:11:10 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2014-04-09 00:11:10 -0400 |
commit | 6beb7818efb57851a042953937af72163f1bde6c (patch) | |
tree | 6abc8763d6182f4c3de6da8567d05f995fd53db0 /pty-unix.c | |
parent | ef5cd6e10e93ef973536d2df2ad57ac42a2118ea (diff) | |
download | runes-6beb7818efb57851a042953937af72163f1bde6c.tar.gz runes-6beb7818efb57851a042953937af72163f1bde6c.zip |
spawn a shell process and run it on a pty
not at all convinced that this is correct, but it at least does things
Diffstat (limited to 'pty-unix.c')
-rw-r--r-- | pty-unix.c | 91 |
1 files changed, 91 insertions, 0 deletions
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); +} |