Run command in a pty and feed output to wayland terminal.
diff --git a/terminal.c b/terminal.c
index 0ecb304..acd4f2b 100644
--- a/terminal.c
+++ b/terminal.c
@@ -28,6 +28,7 @@
 #include <unistd.h>
 #include <math.h>
 #include <time.h>
+#include <pty.h>
 #include <cairo.h>
 #include <glib.h>
 
@@ -48,9 +49,10 @@
 	struct wl_display *display;
 	int resize_scheduled;
 	char *data;
-	int width, height;
+	int width, height, tail, row, column;
 	int fd;
 	struct buffer *buffer;
+	GIOChannel *channel;
 };
 
 static void
@@ -60,7 +62,7 @@
 	cairo_surface_t *surface;
 	cairo_t *cr;
 	cairo_font_extents_t extents;
-	int i;
+	int i, line;
 
 	window_get_child_rectangle(terminal->window, &rectangle);
 
@@ -76,11 +78,13 @@
 	cairo_select_font_face (cr, "mono",
 				CAIRO_FONT_SLANT_NORMAL,
 				CAIRO_FONT_WEIGHT_NORMAL);
+	cairo_set_font_size(cr, 14);
 
 	cairo_font_extents(cr, &extents);
 	for (i = 0; i < terminal->height; i++) {
+		line = (terminal->tail + i) % terminal->height;
 		cairo_move_to(cr, 0, extents.ascent + extents.height * i);
-		cairo_show_text(cr, &terminal->data[i * (terminal->width + 1)]);
+		cairo_show_text(cr, &terminal->data[line * (terminal->width + 1)]);
 	}
 	cairo_destroy(cr);
 
@@ -132,16 +136,47 @@
 	terminal->resize_scheduled = 0;
 }
 
+static void
+terminal_data(struct terminal *terminal, const char *data, size_t length)
+{
+	int i;
+	char *row;
+
+	for (i = 0; i < length; i++) {
+		row = &terminal->data[terminal->row * (terminal->width + 1)];
+		switch (data[i]) {
+		case '\r':
+			terminal->column = 0;
+			break;
+		case '\n':
+			terminal->row++;
+			terminal->column = 0;
+			if (terminal->row == terminal->height)
+				terminal->row = 0;
+			break;
+		case '\t':
+			memset(&row[terminal->column], ' ', -terminal->column & 7);
+			terminal->column = (terminal->column + 7) & ~7;
+			break;
+		default:
+			if (terminal->column < terminal->width)
+				row[terminal->column++] = data[i];
+			break;
+		}
+	}
+}
+
 static struct terminal *
 terminal_create(struct wl_display *display, int fd)
 {
 	struct terminal *terminal;
-	int size, i;
+	int size;
 
 	terminal = malloc(sizeof *terminal);
 	if (terminal == NULL)
 		return terminal;
 
+	memset(terminal, 0, sizeof *terminal);
 	terminal->fd = fd;
 	terminal->window = window_create(display, fd, "Wayland Terminal",
 					 500, 100, 500, 400);
@@ -153,17 +188,60 @@
 	terminal->data = malloc(size);
 	memset(terminal->data, 0, size);
 
-	for (i = 0; i < terminal->height; i++) {
-		snprintf(&terminal->data[i * (terminal->width + 1)], terminal->width,
-			 "hello world, line %d", i);
-	}
-
 	window_set_resize_handler(terminal->window, resize_handler, terminal);
 	window_set_acknowledge_handler(terminal->window, acknowledge_handler, terminal);
 
 	return terminal;
 }
 
+static gboolean
+io_handler(GIOChannel   *source,
+	   GIOCondition  condition,
+	   gpointer      data)
+{
+	struct terminal *terminal = data;
+	gchar buffer[256];
+	gsize bytes_read;
+	GError *error = NULL;
+
+	g_io_channel_read_chars(source, buffer, sizeof buffer,
+				&bytes_read, &error);
+	printf("got data: %.*s\n", bytes_read, buffer);
+
+	terminal_data(terminal, buffer, bytes_read);
+
+	if (!terminal->resize_scheduled) {
+		g_idle_add(idle_redraw, terminal);
+		terminal->resize_scheduled = 1;
+	}
+
+	return TRUE;
+}
+
+static int
+terminal_run(struct terminal *terminal, const char *path)
+{
+	int master, slave;
+	pid_t pid;
+
+	pid = forkpty(&master, NULL, NULL, NULL);
+	if (pid == 0) {
+		close(master);
+		if (execl(path, path, NULL)) {
+			printf("exec failed: %m\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	close(slave);
+	terminal->channel = g_io_channel_unix_new(master);
+	fcntl(master, F_SETFL, O_NONBLOCK);
+	g_io_add_watch(terminal->channel, G_IO_IN,
+		       io_handler, terminal);
+
+	return 0;
+}
+
 int main(int argc, char *argv[])
 {
 	struct wl_display *display;
@@ -189,6 +267,7 @@
 	g_source_attach(source, NULL);
 
 	terminal = terminal_create(display, fd);
+	terminal_run(terminal, "/bin/bash");
 	terminal_draw(terminal);
 
 	g_main_loop_run(loop);