about summary refs log tree commit diff homepage
path: root/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'client.c')
-rw-r--r--client.c663
1 files changed, 331 insertions, 332 deletions
diff --git a/client.c b/client.c
index 48dc03b..ee120e5 100644
--- a/client.c
+++ b/client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, Curtis McEnroe <curtis@cmcenroe.me>
+/* Copyright (C) 2017  Curtis McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
@@ -30,398 +30,397 @@
 #include "torus.h"
 
 enum {
-    ESC = 0x1B,
-    DEL = 0x7F,
+	ESC = 0x1B,
+	DEL = 0x7F,
 };
 
 static int client;
 
 static void clientMessage(struct ClientMessage msg) {
-    ssize_t size = send(client, &msg, sizeof(msg), 0);
-    if (size < 0) err(EX_IOERR, "send");
+	ssize_t size = send(client, &msg, sizeof(msg), 0);
+	if (size < 0) err(EX_IOERR, "send");
 }
 
 static void clientMove(int8_t dx, int8_t dy) {
-    struct ClientMessage msg = {
-        .type = CLIENT_MOVE,
-        .move = { .dx = dx, .dy = dy },
-    };
-    clientMessage(msg);
+	struct ClientMessage msg = {
+		.type = CLIENT_MOVE,
+		.move = { .dx = dx, .dy = dy },
+	};
+	clientMessage(msg);
 }
 
 static void clientPut(uint8_t color, char cell) {
-    struct ClientMessage msg = {
-        .type = CLIENT_PUT,
-        .put = { .color = color, .cell = cell },
-    };
-    clientMessage(msg);
+	struct ClientMessage msg = {
+		.type = CLIENT_PUT,
+		.put = { .color = color, .cell = cell },
+	};
+	clientMessage(msg);
 }
 
 static void clientSpawn(uint8_t spawn) {
-    struct ClientMessage msg = {
-        .type = CLIENT_SPAWN,
-        .spawn = spawn,
-    };
-    clientMessage(msg);
+	struct ClientMessage msg = {
+		.type = CLIENT_SPAWN,
+		.spawn = spawn,
+	};
+	clientMessage(msg);
 }
 
 static chtype colorAttrs(uint8_t color) {
-    uint8_t bright = color & COLOR_BRIGHT;
-    uint8_t fg = color & 0x07;
-    uint8_t bg = color & 0x70;
-    return COLOR_PAIR(bg >> 1 | fg) | (bright ? A_BOLD : 0);
+	uint8_t bright = color & COLOR_BRIGHT;
+	uint8_t fg = color & 0x07;
+	uint8_t bg = color & 0x70;
+	return COLOR_PAIR(bg >> 1 | fg) | (bright ? A_BOLD : 0);
 }
 
 static uint8_t attrsColor(chtype attrs) {
-    chtype bright = attrs & A_BOLD;
-    short fg = PAIR_NUMBER(attrs) & 007;
-    short bg = PAIR_NUMBER(attrs) & 070;
-    return bg << 1 | fg | (bright ? COLOR_BRIGHT : 0);
+	chtype bright = attrs & A_BOLD;
+	short fg = PAIR_NUMBER(attrs) & 007;
+	short bg = PAIR_NUMBER(attrs) & 070;
+	return bg << 1 | fg | (bright ? COLOR_BRIGHT : 0);
 }
 
 static struct {
-    int8_t speed;
-    uint8_t color;
-    enum {
-        MODE_NORMAL,
-        MODE_INSERT,
-        MODE_REPLACE,
-        MODE_PUT,
-        MODE_DRAW,
-    } mode;
-    int8_t dx;
-    int8_t dy;
-    uint8_t len;
-    char draw;
+	int8_t speed;
+	uint8_t color;
+	enum {
+		MODE_NORMAL,
+		MODE_INSERT,
+		MODE_REPLACE,
+		MODE_PUT,
+		MODE_DRAW,
+	} mode;
+	int8_t dx;
+	int8_t dy;
+	uint8_t len;
+	char draw;
 } input = {
-    .speed = 1,
-    .color = COLOR_WHITE,
-    .dx = 1,
+	.speed = 1,
+	.color = COLOR_WHITE,
+	.dx = 1,
 };
 
 static void colorFg(uint8_t fg) {
-    input.color = (input.color & 0xF8) | fg;
+	input.color = (input.color & 0xF8) | fg;
 }
 
 static void colorBg(uint8_t bg) {
-    input.color = (input.color & 0x0F) | (bg << 4);
+	input.color = (input.color & 0x0F) | (bg << 4);
 }
 
 static void colorInvert(void) {
-    input.color =
-        (input.color & 0x08) |
-        ((input.color & 0x07) << 4) |
-        ((input.color & 0x70) >> 4);
+	input.color =
+		(input.color & 0x08) |
+		((input.color & 0x07) << 4) |
+		((input.color & 0x70) >> 4);
 }
 
 static void insertMode(int8_t dx, int8_t dy) {
-    input.mode = MODE_INSERT;
-    input.dx = dx;
-    input.dy = dy;
-    input.len = 0;
+	input.mode = MODE_INSERT;
+	input.dx = dx;
+	input.dy = dy;
+	input.len = 0;
 }
 
 static void swapCell(int8_t dx, int8_t dy) {
-    uint8_t aColor = attrsColor(inch());
-    char aCell = inch() & A_CHARTEXT;
-
-    int sy, sx;
-    getyx(stdscr, sy, sx);
-    move(sy + dy, sx + dx);
-    uint8_t bColor = attrsColor(inch());
-    char bCell = inch() & A_CHARTEXT;
-    move(sy, sx);
-
-    clientPut(bColor, bCell);
-    clientMove(dx, dy);
-    clientPut(aColor, aCell);
+	uint8_t aColor = attrsColor(inch());
+	char aCell = inch() & A_CHARTEXT;
+
+	int sy, sx;
+	getyx(stdscr, sy, sx);
+	move(sy + dy, sx + dx);
+	uint8_t bColor = attrsColor(inch());
+	char bCell = inch() & A_CHARTEXT;
+	move(sy, sx);
+
+	clientPut(bColor, bCell);
+	clientMove(dx, dy);
+	clientPut(aColor, aCell);
 }
 
 static void readInput(void) {
-    int c = getch();
-
-    if (input.mode == MODE_INSERT) {
-        if (c == ESC) {
-            input.mode = MODE_NORMAL;
-            clientMove(-input.dx, -input.dy);
-        } else if (!input.dx && !input.dy) {
-            switch (c) {
-                case 'h': insertMode(-1,  0); break;
-                case 'j': insertMode( 0,  1); break;
-                case 'k': insertMode( 0, -1); break;
-                case 'l': insertMode( 1,  0); break;
-                case 'y': insertMode(-1, -1); break;
-                case 'u': insertMode( 1, -1); break;
-                case 'b': insertMode(-1,  1); break;
-                case 'n': insertMode( 1,  1); break;
-            }
-        } else if (c == '\b' || c == DEL) {
-            clientMove(-input.dx, -input.dy);
-            clientPut(input.color, ' ');
-            input.len--;
-        } else if (c == '\n') {
-            clientMove(input.dy, input.dx);
-            clientMove(-input.dx * input.len, -input.dy * input.len);
-            input.len = 0;
-        } else if (isprint(c)) {
-            clientPut(input.color, c);
-            clientMove(input.dx, input.dy);
-            input.len++;
-        }
-        return;
-    }
-
-    if (input.mode == MODE_REPLACE) {
-        if (isprint(c)) clientPut(attrsColor(inch()), c);
-        input.mode = MODE_NORMAL;
-        return;
-    }
-
-    if (input.mode == MODE_PUT) {
-        if (isprint(c)) clientPut(input.color, c);
-        input.mode = MODE_NORMAL;
-        return;
-    }
-
-    if (input.mode == MODE_DRAW && !input.draw) {
-        if (c == ESC) input.mode = MODE_NORMAL;
-        if (isprint(c)) {
-            input.draw = c;
-            clientPut(input.color, c);
-        }
-        return;
-    }
-
-    switch (c) {
-        case ESC: input.mode = MODE_NORMAL; break;
-
-        case 'q': endwin(); exit(EX_OK);
-        case 'Q': {
-            if ((input.color & 0x07) < SPAWNS_LEN) {
-                clientSpawn(input.color & 0x07);
-            } else {
-                clientSpawn(0);
-            }
-        } break;
-
-        case 'a': clientMove(1, 0); // fallthrough
-        case 'i': insertMode(1, 0); break;
-        case 'I': insertMode(0, 0); break;
-        case 'r': input.mode = MODE_REPLACE; break;
-        case 'p': input.mode = MODE_PUT; break;
-        case 'R': input.mode = MODE_DRAW; input.draw = 0; break;
-        case 'x': clientPut(attrsColor(inch()), ' '); break;
-
-        case '~': {
-            clientPut(input.color, inch() & A_CHARTEXT);
-            clientMove(input.dx, input.dy);
-        } break;
-
-        case '[': if (input.speed > 1) input.speed--; break;
-        case ']': if (input.speed < 4) input.speed++; break;
-
-        case 'h': clientMove(-input.speed,            0); break;
-        case 'j': clientMove(           0,  input.speed); break;
-        case 'k': clientMove(           0, -input.speed); break;
-        case 'l': clientMove( input.speed,            0); break;
-        case 'y': clientMove(-input.speed, -input.speed); break;
-        case 'u': clientMove( input.speed, -input.speed); break;
-        case 'b': clientMove(-input.speed,  input.speed); break;
-        case 'n': clientMove( input.speed,  input.speed); break;
-
-        case 'H': swapCell(-1,  0); break;
-        case 'J': swapCell( 0,  1); break;
-        case 'K': swapCell( 0, -1); break;
-        case 'L': swapCell( 1,  0); break;
-        case 'Y': swapCell(-1, -1); break;
-        case 'U': swapCell( 1, -1); break;
-        case 'B': swapCell(-1,  1); break;
-        case 'N': swapCell( 1,  1); break;
-
-        case '`': input.color = attrsColor(inch()); break;
-
-        case '0': colorFg(COLOR_BLACK);   break;
-        case '1': colorFg(COLOR_RED);     break;
-        case '2': colorFg(COLOR_GREEN);   break;
-        case '3': colorFg(COLOR_YELLOW);  break;
-        case '4': colorFg(COLOR_BLUE);    break;
-        case '5': colorFg(COLOR_MAGENTA); break;
-        case '6': colorFg(COLOR_CYAN);    break;
-        case '7': colorFg(COLOR_WHITE);   break;
-
-        case ')': colorBg(COLOR_BLACK);   break;
-        case '!': colorBg(COLOR_RED);     break;
-        case '@': colorBg(COLOR_GREEN);   break;
-        case '#': colorBg(COLOR_YELLOW);  break;
-        case '$': colorBg(COLOR_BLUE);    break;
-        case '%': colorBg(COLOR_MAGENTA); break;
-        case '^': colorBg(COLOR_CYAN);    break;
-        case '&': colorBg(COLOR_WHITE);   break;
-
-        case '*':
-        case '8': input.color ^= COLOR_BRIGHT; break;
-
-        case '(':
-        case '9': colorInvert(); break;
-
-        case KEY_LEFT:  clientMove(-1,  0); break;
-        case KEY_DOWN:  clientMove( 0,  1); break;
-        case KEY_UP:    clientMove( 0, -1); break;
-        case KEY_RIGHT: clientMove( 1,  0); break;
-    }
-
-    if (input.mode == MODE_DRAW && input.draw) clientPut(input.color, input.draw);
+	int c = getch();
+
+	if (input.mode == MODE_INSERT) {
+		if (c == ESC) {
+			input.mode = MODE_NORMAL;
+			clientMove(-input.dx, -input.dy);
+		} else if (!input.dx && !input.dy) {
+			switch (c) {
+				break; case 'h': insertMode(-1,  0);
+				break; case 'j': insertMode( 0,  1);
+				break; case 'k': insertMode( 0, -1);
+				break; case 'l': insertMode( 1,  0);
+				break; case 'y': insertMode(-1, -1);
+				break; case 'u': insertMode( 1, -1);
+				break; case 'b': insertMode(-1,  1);
+				break; case 'n': insertMode( 1,  1);
+			}
+		} else if (c == '\b' || c == DEL) {
+			clientMove(-input.dx, -input.dy);
+			clientPut(input.color, ' ');
+			input.len--;
+		} else if (c == '\n') {
+			clientMove(input.dy, input.dx);
+			clientMove(-input.dx * input.len, -input.dy * input.len);
+			input.len = 0;
+		} else if (isprint(c)) {
+			clientPut(input.color, c);
+			clientMove(input.dx, input.dy);
+			input.len++;
+		}
+		return;
+	}
+
+	if (input.mode == MODE_REPLACE) {
+		if (isprint(c)) clientPut(attrsColor(inch()), c);
+		input.mode = MODE_NORMAL;
+		return;
+	}
+
+	if (input.mode == MODE_PUT) {
+		if (isprint(c)) clientPut(input.color, c);
+		input.mode = MODE_NORMAL;
+		return;
+	}
+
+	if (input.mode == MODE_DRAW && !input.draw) {
+		if (c == ESC) input.mode = MODE_NORMAL;
+		if (isprint(c)) {
+			input.draw = c;
+			clientPut(input.color, c);
+		}
+		return;
+	}
+
+	switch (c) {
+		break; case ESC: input.mode = MODE_NORMAL;
+
+		break; case 'q': endwin(); exit(EX_OK);
+		break; case 'Q': {
+			if ((input.color & 0x07) < SPAWNS_LEN) {
+				clientSpawn(input.color & 0x07);
+			} else {
+				clientSpawn(0);
+			}
+		}
+
+		break; case 'i': insertMode(1, 0);
+		break; case 'a': clientMove(1, 0); insertMode(1, 0);
+		break; case 'I': insertMode(0, 0);
+		break; case 'r': input.mode = MODE_REPLACE;
+		break; case 'p': input.mode = MODE_PUT;
+		break; case 'R': input.mode = MODE_DRAW; input.draw = 0;
+		break; case 'x': clientPut(attrsColor(inch()), ' ');
+
+		break; case '~': {
+			clientPut(input.color, inch() & A_CHARTEXT);
+			clientMove(input.dx, input.dy);
+		}
+
+		break; case '[': if (input.speed > 1) input.speed--;
+		break; case ']': if (input.speed < 4) input.speed++;
+
+		break; case 'h': clientMove(-input.speed,            0);
+		break; case 'j': clientMove(           0,  input.speed);
+		break; case 'k': clientMove(           0, -input.speed);
+		break; case 'l': clientMove( input.speed,            0);
+		break; case 'y': clientMove(-input.speed, -input.speed);
+		break; case 'u': clientMove( input.speed, -input.speed);
+		break; case 'b': clientMove(-input.speed,  input.speed);
+		break; case 'n': clientMove( input.speed,  input.speed);
+
+		break; case 'H': swapCell(-1,  0);
+		break; case 'J': swapCell( 0,  1);
+		break; case 'K': swapCell( 0, -1);
+		break; case 'L': swapCell( 1,  0);
+		break; case 'Y': swapCell(-1, -1);
+		break; case 'U': swapCell( 1, -1);
+		break; case 'B': swapCell(-1,  1);
+		break; case 'N': swapCell( 1,  1);
+
+		break; case '`': input.color = attrsColor(inch());
+
+		break; case '0': colorFg(COLOR_BLACK);
+		break; case '1': colorFg(COLOR_RED);
+		break; case '2': colorFg(COLOR_GREEN);
+		break; case '3': colorFg(COLOR_YELLOW);
+		break; case '4': colorFg(COLOR_BLUE);
+		break; case '5': colorFg(COLOR_MAGENTA);
+		break; case '6': colorFg(COLOR_CYAN);
+		break; case '7': colorFg(COLOR_WHITE);
+
+		break; case ')': colorBg(COLOR_BLACK);
+		break; case '!': colorBg(COLOR_RED);
+		break; case '@': colorBg(COLOR_GREEN);
+		break; case '#': colorBg(COLOR_YELLOW);
+		break; case '$': colorBg(COLOR_BLUE);
+		break; case '%': colorBg(COLOR_MAGENTA);
+		break; case '^': colorBg(COLOR_CYAN);
+		break; case '&': colorBg(COLOR_WHITE);
+
+		break; case '*': case '8': input.color ^= COLOR_BRIGHT;
+
+		break; case '(': case '9': colorInvert();
+
+		break; case KEY_LEFT:  clientMove(-1,  0);
+		break; case KEY_DOWN:  clientMove( 0,  1);
+		break; case KEY_UP:    clientMove( 0, -1);
+		break; case KEY_RIGHT: clientMove( 1,  0);
+	}
+
+	if (input.mode == MODE_DRAW && input.draw) clientPut(input.color, input.draw);
 }
 
 static void serverPut(uint8_t x, uint8_t y, uint8_t color, char cell) {
-    mvaddch(y, x, colorAttrs(color) | cell);
+	mvaddch(y, x, colorAttrs(color) | cell);
 }
 
 static void serverTile(void) {
-    struct Tile tile;
-    ssize_t size = recv(client, &tile, sizeof(tile), 0);
-    if (size < 0) err(EX_IOERR, "recv");
-    if ((size_t)size < sizeof(tile)) {
-        errx(EX_PROTOCOL, "This tile isn't big enough...");
-    }
-
-    for (int y = 0; y < CELL_ROWS; ++y) {
-        for (int x = 0; x < CELL_COLS; ++x) {
-            serverPut(x, y, tile.colors[y][x], tile.cells[y][x]);
-        }
-    }
+	struct Tile tile;
+	ssize_t size = recv(client, &tile, sizeof(tile), 0);
+	if (size < 0) err(EX_IOERR, "recv");
+	if ((size_t)size < sizeof(tile)) {
+		errx(EX_PROTOCOL, "This tile isn't big enough...");
+	}
+
+	for (int y = 0; y < CELL_ROWS; ++y) {
+		for (int x = 0; x < CELL_COLS; ++x) {
+			serverPut(x, y, tile.colors[y][x], tile.cells[y][x]);
+		}
+	}
 }
 
 static void serverCursor(uint8_t oldX, uint8_t oldY, uint8_t newX, uint8_t newY) {
-    if (oldX != CURSOR_NONE) {
-        move(oldY, oldX);
-        addch(inch() & ~A_REVERSE);
-    }
-    if (newX != CURSOR_NONE) {
-        move(newY, newX);
-        addch(inch() | A_REVERSE);
-    }
+	if (oldX != CURSOR_NONE) {
+		move(oldY, oldX);
+		addch(inch() & ~A_REVERSE);
+	}
+	if (newX != CURSOR_NONE) {
+		move(newY, newX);
+		addch(inch() | A_REVERSE);
+	}
 }
 
 static void readMessage(void) {
-    struct ServerMessage msg;
-    ssize_t size = recv(client, &msg, sizeof(msg), 0);
-    if (size < 0) err(EX_IOERR, "recv");
-    if ((size_t)size < sizeof(msg)) errx(EX_PROTOCOL, "A message was cut short.");
-
-    int sy, sx;
-    getyx(stdscr, sy, sx);
-
-    switch (msg.type) {
-        case SERVER_TILE: {
-            serverTile();
-        } break;
-
-        case SERVER_MOVE: {
-            move(msg.move.cellY, msg.move.cellX);
-            refresh();
-        } return;
-
-        case SERVER_PUT: {
-            serverPut(
-                msg.put.cellX,
-                msg.put.cellY,
-                msg.put.color,
-                msg.put.cell
-            );
-        } break;
-
-        case SERVER_CURSOR: {
-            serverCursor(
-                msg.cursor.oldCellX,
-                msg.cursor.oldCellY,
-                msg.cursor.newCellX,
-                msg.cursor.newCellY
-            );
-        } break;
-
-        default: errx(EX_PROTOCOL, "I don't know what %d means!", msg.type);
-    }
-
-    move(sy, sx);
-    refresh();
+	struct ServerMessage msg;
+	ssize_t size = recv(client, &msg, sizeof(msg), 0);
+	if (size < 0) err(EX_IOERR, "recv");
+	if ((size_t)size < sizeof(msg)) errx(EX_PROTOCOL, "A message was cut short.");
+
+	int sy, sx;
+	getyx(stdscr, sy, sx);
+
+	switch (msg.type) {
+		break; case SERVER_TILE: {
+			serverTile();
+		}
+
+		break; case SERVER_MOVE: {
+			move(msg.move.cellY, msg.move.cellX);
+			refresh();
+			return;
+		}
+
+		break; case SERVER_PUT: {
+			serverPut(
+				msg.put.cellX,
+				msg.put.cellY,
+				msg.put.color,
+				msg.put.cell
+			);
+		}
+
+		break; case SERVER_CURSOR: {
+			serverCursor(
+				msg.cursor.oldCellX,
+				msg.cursor.oldCellY,
+				msg.cursor.newCellX,
+				msg.cursor.newCellY
+			);
+		}
+
+		break; default: errx(EX_PROTOCOL, "I don't know what %d means!", msg.type);
+	}
+
+	move(sy, sx);
+	refresh();
 }
 
 static void drawBorder(void) {
-    if (LINES < CELL_ROWS || COLS < CELL_COLS) {
-        endwin();
-        fprintf(stderr, "Sorry, your terminal is too small!\n");
-        fprintf(stderr, "It needs to be at least 80x25 characters.\n");
-        exit(EX_CONFIG);
-    }
-    if (LINES > CELL_ROWS) {
-        mvhline(CELL_ROWS, 0, 0, CELL_COLS);
-    }
-    if (COLS > CELL_COLS) {
-        mvvline(0, CELL_COLS, 0, CELL_ROWS);
-    }
-    if (LINES > CELL_ROWS && COLS > CELL_COLS) {
-        mvaddch(CELL_ROWS, CELL_COLS, ACS_LRCORNER);
-    }
+	if (LINES < CELL_ROWS || COLS < CELL_COLS) {
+		endwin();
+		fprintf(stderr, "Sorry, your terminal is too small!\n");
+		fprintf(stderr, "It needs to be at least 80x25 characters.\n");
+		exit(EX_CONFIG);
+	}
+	if (LINES > CELL_ROWS) {
+		mvhline(CELL_ROWS, 0, 0, CELL_COLS);
+	}
+	if (COLS > CELL_COLS) {
+		mvvline(0, CELL_COLS, 0, CELL_ROWS);
+	}
+	if (LINES > CELL_ROWS && COLS > CELL_COLS) {
+		mvaddch(CELL_ROWS, CELL_COLS, ACS_LRCORNER);
+	}
 }
 
 static void initColors(void) {
-    if (!has_colors()) {
-        endwin();
-        fprintf(
-            stderr,
-            "Sorry, your terminal doesn't support colors!\n"
-            "If you think it does, check TERM.\n"
-        );
-        exit(EX_CONFIG);
-    }
-    start_color();
-    if (COLOR_PAIRS < 64) {
-        endwin();
-        fprintf(
-            stderr,
-            "Sorry, your terminal doesn't support enough color pairs!\n"
-            "If you think it does, check TERM.\n"
-        );
-        exit(EX_CONFIG);
-    }
-    for (int bg = COLOR_BLACK; bg < COLOR_BRIGHT; ++bg) {
-        for (int fg = COLOR_BLACK; fg < COLOR_BRIGHT; ++fg) {
-            init_pair(PAIR_NUMBER(colorAttrs(bg << 4 | fg)), fg, bg);
-        }
-    }
+	if (!has_colors()) {
+		endwin();
+		fprintf(
+			stderr,
+			"Sorry, your terminal doesn't support colors!\n"
+			"If you think it does, check TERM.\n"
+		);
+		exit(EX_CONFIG);
+	}
+	start_color();
+	if (COLOR_PAIRS < 64) {
+		endwin();
+		fprintf(
+			stderr,
+			"Sorry, your terminal doesn't support enough color pairs!\n"
+			"If you think it does, check TERM.\n"
+		);
+		exit(EX_CONFIG);
+	}
+	for (int bg = COLOR_BLACK; bg < COLOR_BRIGHT; ++bg) {
+		for (int fg = COLOR_BLACK; fg < COLOR_BRIGHT; ++fg) {
+			init_pair(PAIR_NUMBER(colorAttrs(bg << 4 | fg)), fg, bg);
+		}
+	}
 }
 
 int main() {
-    client = socket(PF_LOCAL, SOCK_STREAM, 0);
-    if (client < 0) err(EX_OSERR, "socket");
-
-    struct sockaddr_un addr = {
-        .sun_family = AF_LOCAL,
-        .sun_path = "torus.sock",
-    };
-    int error = connect(client, (struct sockaddr *)&addr, sizeof(addr));
-    if (error) err(EX_NOINPUT, "torus.sock");
-
-    initscr();
-    cbreak();
-    noecho();
-    keypad(stdscr, true);
-    set_escdelay(100);
-
-    initColors();
-    drawBorder();
-
-    struct pollfd fds[2] = {
-        { .fd = STDIN_FILENO, .events = POLLIN },
-        { .fd = client, .events = POLLIN },
-    };
-    for (;;) {
-        int nfds = poll(fds, 2, -1);
-        if (nfds < 0 && errno == EINTR) continue;
-        if (nfds < 0) err(EX_IOERR, "poll");
-
-        if (fds[0].revents) readInput();
-        if (fds[1].revents) readMessage();
-    }
+	client = socket(PF_LOCAL, SOCK_STREAM, 0);
+	if (client < 0) err(EX_OSERR, "socket");
+
+	struct sockaddr_un addr = {
+		.sun_family = AF_LOCAL,
+		.sun_path = "torus.sock",
+	};
+	int error = connect(client, (struct sockaddr *)&addr, sizeof(addr));
+	if (error) err(EX_NOINPUT, "torus.sock");
+
+	initscr();
+	cbreak();
+	noecho();
+	keypad(stdscr, true);
+	set_escdelay(100);
+
+	initColors();
+	drawBorder();
+
+	struct pollfd fds[2] = {
+		{ .fd = STDIN_FILENO, .events = POLLIN },
+		{ .fd = client, .events = POLLIN },
+	};
+	for (;;) {
+		int nfds = poll(fds, 2, -1);
+		if (nfds < 0 && errno == EINTR) continue;
+		if (nfds < 0) err(EX_IOERR, "poll");
+
+		if (fds[0].revents) readInput();
+		if (fds[1].revents) readMessage();
+	}
 }