aboutsummaryrefslogtreecommitdiffstats
path: root/pty-unix.c
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2014-04-09 00:11:10 -0400
committerJesse Luehrs <doy@tozt.net>2014-04-09 00:11:10 -0400
commit6beb7818efb57851a042953937af72163f1bde6c (patch)
tree6abc8763d6182f4c3de6da8567d05f995fd53db0 /pty-unix.c
parentef5cd6e10e93ef973536d2df2ad57ac42a2118ea (diff)
downloadrunes-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.c91
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);
+}