Browse Source

Tabify source

And other style changes.
June 4 months ago
parent
commit
eb420c49bb
Signed by: Curtis McEnroe <june@causal.agency> GPG Key ID: CEA2F97ADCFCD77C
10 changed files with 916 additions and 919 deletions
  1. 0
    2
      Makefile
  2. 10
    10
      README
  3. 331
    332
      client.c
  4. 122
    122
      help.c
  5. 2
    2
      index.html
  6. 73
    73
      merge.c
  7. 18
    18
      meta.c
  8. 282
    282
      server.c
  9. 9
    9
      sshd_config
  10. 69
    69
      torus.h

+ 0
- 2
Makefile View File

@@ -45,5 +45,3 @@ tags: *.h *.c
45 45
 
46 46
 clean:
47 47
 	rm -f tags $(BINS) termcap termcap.db chroot.tar
48
-
49
-.PHONY: all clean

+ 10
- 10
README View File

@@ -2,14 +2,14 @@ Welcome to ascii.town!
2 2
 
3 3
 This software targets FreeBSD and Darwin.
4 4
 
5
-    torus.h        Shared structures and message protocol.
6
-    server.c       Maps torus.dat and listens on torus.sock.
7
-    client.c       Curses client.
8
-    help.c         Automated client which redraws a helpful banner.
9
-    meta.c         Exports metadata from data file to CSV.
10
-    merge.c        Interactively merges two data files.
11
-    snapshot.sh    Snapshots data file, appropriate for cron.
5
+	torus.h        Shared structures and message protocol.
6
+	server.c       Maps torus.dat and listens on torus.sock.
7
+	client.c       Curses client.
8
+	help.c         Automated client which redraws a helpful banner.
9
+	meta.c         Exports metadata from data file to CSV.
10
+	merge.c        Interactively merges two data files.
11
+	snapshot.sh    Snapshots data file, appropriate for cron.
12 12
 
13
-    sshd_config    Anonymous login to chrooted client.
14
-    termcap.diff   Patch for bright colors in xterm and rxvt.
15
-    index.html     Friendly directions.
13
+	sshd_config    Anonymous login to chrooted client.
14
+	termcap.diff   Patch for bright colors in xterm and rxvt.
15
+	index.html     Friendly directions.

+ 331
- 332
client.c View File

@@ -1,4 +1,4 @@
1
-/* Copyright (c) 2017, Curtis McEnroe <curtis@cmcenroe.me>
1
+/* Copyright (C) 2017  Curtis McEnroe <june@causal.agency>
2 2
  *
3 3
  * This program is free software: you can redistribute it and/or modify
4 4
  * it under the terms of the GNU Affero General Public License as published by
@@ -30,398 +30,397 @@
30 30
 #include "torus.h"
31 31
 
32 32
 enum {
33
-    ESC = 0x1B,
34
-    DEL = 0x7F,
33
+	ESC = 0x1B,
34
+	DEL = 0x7F,
35 35
 };
36 36
 
37 37
 static int client;
38 38
 
39 39
 static void clientMessage(struct ClientMessage msg) {
40
-    ssize_t size = send(client, &msg, sizeof(msg), 0);
41
-    if (size < 0) err(EX_IOERR, "send");
40
+	ssize_t size = send(client, &msg, sizeof(msg), 0);
41
+	if (size < 0) err(EX_IOERR, "send");
42 42
 }
43 43
 
44 44
 static void clientMove(int8_t dx, int8_t dy) {
45
-    struct ClientMessage msg = {
46
-        .type = CLIENT_MOVE,
47
-        .move = { .dx = dx, .dy = dy },
48
-    };
49
-    clientMessage(msg);
45
+	struct ClientMessage msg = {
46
+		.type = CLIENT_MOVE,
47
+		.move = { .dx = dx, .dy = dy },
48
+	};
49
+	clientMessage(msg);
50 50
 }
51 51
 
52 52
 static void clientPut(uint8_t color, char cell) {
53
-    struct ClientMessage msg = {
54
-        .type = CLIENT_PUT,
55
-        .put = { .color = color, .cell = cell },
56
-    };
57
-    clientMessage(msg);
53
+	struct ClientMessage msg = {
54
+		.type = CLIENT_PUT,
55
+		.put = { .color = color, .cell = cell },
56
+	};
57
+	clientMessage(msg);
58 58
 }
59 59
 
60 60
 static void clientSpawn(uint8_t spawn) {
61
-    struct ClientMessage msg = {
62
-        .type = CLIENT_SPAWN,
63
-        .spawn = spawn,
64
-    };
65
-    clientMessage(msg);
61
+	struct ClientMessage msg = {
62
+		.type = CLIENT_SPAWN,
63
+		.spawn = spawn,
64
+	};
65
+	clientMessage(msg);
66 66
 }
67 67
 
68 68
 static chtype colorAttrs(uint8_t color) {
69
-    uint8_t bright = color & COLOR_BRIGHT;
70
-    uint8_t fg = color & 0x07;
71
-    uint8_t bg = color & 0x70;
72
-    return COLOR_PAIR(bg >> 1 | fg) | (bright ? A_BOLD : 0);
69
+	uint8_t bright = color & COLOR_BRIGHT;
70
+	uint8_t fg = color & 0x07;
71
+	uint8_t bg = color & 0x70;
72
+	return COLOR_PAIR(bg >> 1 | fg) | (bright ? A_BOLD : 0);
73 73
 }
74 74
 
75 75
 static uint8_t attrsColor(chtype attrs) {
76
-    chtype bright = attrs & A_BOLD;
77
-    short fg = PAIR_NUMBER(attrs) & 007;
78
-    short bg = PAIR_NUMBER(attrs) & 070;
79
-    return bg << 1 | fg | (bright ? COLOR_BRIGHT : 0);
76
+	chtype bright = attrs & A_BOLD;
77
+	short fg = PAIR_NUMBER(attrs) & 007;
78
+	short bg = PAIR_NUMBER(attrs) & 070;
79
+	return bg << 1 | fg | (bright ? COLOR_BRIGHT : 0);
80 80
 }
81 81
 
82 82
 static struct {
83
-    int8_t speed;
84
-    uint8_t color;
85
-    enum {
86
-        MODE_NORMAL,
87
-        MODE_INSERT,
88
-        MODE_REPLACE,
89
-        MODE_PUT,
90
-        MODE_DRAW,
91
-    } mode;
92
-    int8_t dx;
93
-    int8_t dy;
94
-    uint8_t len;
95
-    char draw;
83
+	int8_t speed;
84
+	uint8_t color;
85
+	enum {
86
+		MODE_NORMAL,
87
+		MODE_INSERT,
88
+		MODE_REPLACE,
89
+		MODE_PUT,
90
+		MODE_DRAW,
91
+	} mode;
92
+	int8_t dx;
93
+	int8_t dy;
94
+	uint8_t len;
95
+	char draw;
96 96
 } input = {
97
-    .speed = 1,
98
-    .color = COLOR_WHITE,
99
-    .dx = 1,
97
+	.speed = 1,
98
+	.color = COLOR_WHITE,
99
+	.dx = 1,
100 100
 };
101 101
 
102 102
 static void colorFg(uint8_t fg) {
103
-    input.color = (input.color & 0xF8) | fg;
103
+	input.color = (input.color & 0xF8) | fg;
104 104
 }
105 105
 
106 106
 static void colorBg(uint8_t bg) {
107
-    input.color = (input.color & 0x0F) | (bg << 4);
107
+	input.color = (input.color & 0x0F) | (bg << 4);
108 108
 }
109 109
 
110 110
 static void colorInvert(void) {
111
-    input.color =
112
-        (input.color & 0x08) |
113
-        ((input.color & 0x07) << 4) |
114
-        ((input.color & 0x70) >> 4);
111
+	input.color =
112
+		(input.color & 0x08) |
113
+		((input.color & 0x07) << 4) |
114
+		((input.color & 0x70) >> 4);
115 115
 }
116 116
 
117 117
 static void insertMode(int8_t dx, int8_t dy) {
118
-    input.mode = MODE_INSERT;
119
-    input.dx = dx;
120
-    input.dy = dy;
121
-    input.len = 0;
118
+	input.mode = MODE_INSERT;
119
+	input.dx = dx;
120
+	input.dy = dy;
121
+	input.len = 0;
122 122
 }
123 123
 
124 124
 static void swapCell(int8_t dx, int8_t dy) {
125
-    uint8_t aColor = attrsColor(inch());
126
-    char aCell = inch() & A_CHARTEXT;
127
-
128
-    int sy, sx;
129
-    getyx(stdscr, sy, sx);
130
-    move(sy + dy, sx + dx);
131
-    uint8_t bColor = attrsColor(inch());
132
-    char bCell = inch() & A_CHARTEXT;
133
-    move(sy, sx);
134
-
135
-    clientPut(bColor, bCell);
136
-    clientMove(dx, dy);
137
-    clientPut(aColor, aCell);
125
+	uint8_t aColor = attrsColor(inch());
126
+	char aCell = inch() & A_CHARTEXT;
127
+
128
+	int sy, sx;
129
+	getyx(stdscr, sy, sx);
130
+	move(sy + dy, sx + dx);
131
+	uint8_t bColor = attrsColor(inch());
132
+	char bCell = inch() & A_CHARTEXT;
133
+	move(sy, sx);
134
+
135
+	clientPut(bColor, bCell);
136
+	clientMove(dx, dy);
137
+	clientPut(aColor, aCell);
138 138
 }
139 139
 
140 140
 static void readInput(void) {
141
-    int c = getch();
142
-
143
-    if (input.mode == MODE_INSERT) {
144
-        if (c == ESC) {
145
-            input.mode = MODE_NORMAL;
146
-            clientMove(-input.dx, -input.dy);
147
-        } else if (!input.dx && !input.dy) {
148
-            switch (c) {
149
-                case 'h': insertMode(-1,  0); break;
150
-                case 'j': insertMode( 0,  1); break;
151
-                case 'k': insertMode( 0, -1); break;
152
-                case 'l': insertMode( 1,  0); break;
153
-                case 'y': insertMode(-1, -1); break;
154
-                case 'u': insertMode( 1, -1); break;
155
-                case 'b': insertMode(-1,  1); break;
156
-                case 'n': insertMode( 1,  1); break;
157
-            }
158
-        } else if (c == '\b' || c == DEL) {
159
-            clientMove(-input.dx, -input.dy);
160
-            clientPut(input.color, ' ');
161
-            input.len--;
162
-        } else if (c == '\n') {
163
-            clientMove(input.dy, input.dx);
164
-            clientMove(-input.dx * input.len, -input.dy * input.len);
165
-            input.len = 0;
166
-        } else if (isprint(c)) {
167
-            clientPut(input.color, c);
168
-            clientMove(input.dx, input.dy);
169
-            input.len++;
170
-        }
171
-        return;
172
-    }
173
-
174
-    if (input.mode == MODE_REPLACE) {
175
-        if (isprint(c)) clientPut(attrsColor(inch()), c);
176
-        input.mode = MODE_NORMAL;
177
-        return;
178
-    }
179
-
180
-    if (input.mode == MODE_PUT) {
181
-        if (isprint(c)) clientPut(input.color, c);
182
-        input.mode = MODE_NORMAL;
183
-        return;
184
-    }
185
-
186
-    if (input.mode == MODE_DRAW && !input.draw) {
187
-        if (c == ESC) input.mode = MODE_NORMAL;
188
-        if (isprint(c)) {
189
-            input.draw = c;
190
-            clientPut(input.color, c);
191
-        }
192
-        return;
193
-    }
194
-
195
-    switch (c) {
196
-        case ESC: input.mode = MODE_NORMAL; break;
197
-
198
-        case 'q': endwin(); exit(EX_OK);
199
-        case 'Q': {
200
-            if ((input.color & 0x07) < SPAWNS_LEN) {
201
-                clientSpawn(input.color & 0x07);
202
-            } else {
203
-                clientSpawn(0);
204
-            }
205
-        } break;
206
-
207
-        case 'a': clientMove(1, 0); // fallthrough
208
-        case 'i': insertMode(1, 0); break;
209
-        case 'I': insertMode(0, 0); break;
210
-        case 'r': input.mode = MODE_REPLACE; break;
211
-        case 'p': input.mode = MODE_PUT; break;
212
-        case 'R': input.mode = MODE_DRAW; input.draw = 0; break;
213
-        case 'x': clientPut(attrsColor(inch()), ' '); break;
214
-
215
-        case '~': {
216
-            clientPut(input.color, inch() & A_CHARTEXT);
217
-            clientMove(input.dx, input.dy);
218
-        } break;
219
-
220
-        case '[': if (input.speed > 1) input.speed--; break;
221
-        case ']': if (input.speed < 4) input.speed++; break;
222
-
223
-        case 'h': clientMove(-input.speed,            0); break;
224
-        case 'j': clientMove(           0,  input.speed); break;
225
-        case 'k': clientMove(           0, -input.speed); break;
226
-        case 'l': clientMove( input.speed,            0); break;
227
-        case 'y': clientMove(-input.speed, -input.speed); break;
228
-        case 'u': clientMove( input.speed, -input.speed); break;
229
-        case 'b': clientMove(-input.speed,  input.speed); break;
230
-        case 'n': clientMove( input.speed,  input.speed); break;
231
-
232
-        case 'H': swapCell(-1,  0); break;
233
-        case 'J': swapCell( 0,  1); break;
234
-        case 'K': swapCell( 0, -1); break;
235
-        case 'L': swapCell( 1,  0); break;
236
-        case 'Y': swapCell(-1, -1); break;
237
-        case 'U': swapCell( 1, -1); break;
238
-        case 'B': swapCell(-1,  1); break;
239
-        case 'N': swapCell( 1,  1); break;
240
-
241
-        case '`': input.color = attrsColor(inch()); break;
242
-
243
-        case '0': colorFg(COLOR_BLACK);   break;
244
-        case '1': colorFg(COLOR_RED);     break;
245
-        case '2': colorFg(COLOR_GREEN);   break;
246
-        case '3': colorFg(COLOR_YELLOW);  break;
247
-        case '4': colorFg(COLOR_BLUE);    break;
248
-        case '5': colorFg(COLOR_MAGENTA); break;
249
-        case '6': colorFg(COLOR_CYAN);    break;
250
-        case '7': colorFg(COLOR_WHITE);   break;
251
-
252
-        case ')': colorBg(COLOR_BLACK);   break;
253
-        case '!': colorBg(COLOR_RED);     break;
254
-        case '@': colorBg(COLOR_GREEN);   break;
255
-        case '#': colorBg(COLOR_YELLOW);  break;
256
-        case '$': colorBg(COLOR_BLUE);    break;
257
-        case '%': colorBg(COLOR_MAGENTA); break;
258
-        case '^': colorBg(COLOR_CYAN);    break;
259
-        case '&': colorBg(COLOR_WHITE);   break;
260
-
261
-        case '*':
262
-        case '8': input.color ^= COLOR_BRIGHT; break;
263
-
264
-        case '(':
265
-        case '9': colorInvert(); break;
266
-
267
-        case KEY_LEFT:  clientMove(-1,  0); break;
268
-        case KEY_DOWN:  clientMove( 0,  1); break;
269
-        case KEY_UP:    clientMove( 0, -1); break;
270
-        case KEY_RIGHT: clientMove( 1,  0); break;
271
-    }
272
-
273
-    if (input.mode == MODE_DRAW && input.draw) clientPut(input.color, input.draw);
141
+	int c = getch();
142
+
143
+	if (input.mode == MODE_INSERT) {
144
+		if (c == ESC) {
145
+			input.mode = MODE_NORMAL;
146
+			clientMove(-input.dx, -input.dy);
147
+		} else if (!input.dx && !input.dy) {
148
+			switch (c) {
149
+				break; case 'h': insertMode(-1,  0);
150
+				break; case 'j': insertMode( 0,  1);
151
+				break; case 'k': insertMode( 0, -1);
152
+				break; case 'l': insertMode( 1,  0);
153
+				break; case 'y': insertMode(-1, -1);
154
+				break; case 'u': insertMode( 1, -1);
155
+				break; case 'b': insertMode(-1,  1);
156
+				break; case 'n': insertMode( 1,  1);
157
+			}
158
+		} else if (c == '\b' || c == DEL) {
159
+			clientMove(-input.dx, -input.dy);
160
+			clientPut(input.color, ' ');
161
+			input.len--;
162
+		} else if (c == '\n') {
163
+			clientMove(input.dy, input.dx);
164
+			clientMove(-input.dx * input.len, -input.dy * input.len);
165
+			input.len = 0;
166
+		} else if (isprint(c)) {
167
+			clientPut(input.color, c);
168
+			clientMove(input.dx, input.dy);
169
+			input.len++;
170
+		}
171
+		return;
172
+	}
173
+
174
+	if (input.mode == MODE_REPLACE) {
175
+		if (isprint(c)) clientPut(attrsColor(inch()), c);
176
+		input.mode = MODE_NORMAL;
177
+		return;
178
+	}
179
+
180
+	if (input.mode == MODE_PUT) {
181
+		if (isprint(c)) clientPut(input.color, c);
182
+		input.mode = MODE_NORMAL;
183
+		return;
184
+	}
185
+
186
+	if (input.mode == MODE_DRAW && !input.draw) {
187
+		if (c == ESC) input.mode = MODE_NORMAL;
188
+		if (isprint(c)) {
189
+			input.draw = c;
190
+			clientPut(input.color, c);
191
+		}
192
+		return;
193
+	}
194
+
195
+	switch (c) {
196
+		break; case ESC: input.mode = MODE_NORMAL;
197
+
198
+		break; case 'q': endwin(); exit(EX_OK);
199
+		break; case 'Q': {
200
+			if ((input.color & 0x07) < SPAWNS_LEN) {
201
+				clientSpawn(input.color & 0x07);
202
+			} else {
203
+				clientSpawn(0);
204
+			}
205
+		}
206
+
207
+		break; case 'i': insertMode(1, 0);
208
+		break; case 'a': clientMove(1, 0); insertMode(1, 0);
209
+		break; case 'I': insertMode(0, 0);
210
+		break; case 'r': input.mode = MODE_REPLACE;
211
+		break; case 'p': input.mode = MODE_PUT;
212
+		break; case 'R': input.mode = MODE_DRAW; input.draw = 0;
213
+		break; case 'x': clientPut(attrsColor(inch()), ' ');
214
+
215
+		break; case '~': {
216
+			clientPut(input.color, inch() & A_CHARTEXT);
217
+			clientMove(input.dx, input.dy);
218
+		}
219
+
220
+		break; case '[': if (input.speed > 1) input.speed--;
221
+		break; case ']': if (input.speed < 4) input.speed++;
222
+
223
+		break; case 'h': clientMove(-input.speed,            0);
224
+		break; case 'j': clientMove(           0,  input.speed);
225
+		break; case 'k': clientMove(           0, -input.speed);
226
+		break; case 'l': clientMove( input.speed,            0);
227
+		break; case 'y': clientMove(-input.speed, -input.speed);
228
+		break; case 'u': clientMove( input.speed, -input.speed);
229
+		break; case 'b': clientMove(-input.speed,  input.speed);
230
+		break; case 'n': clientMove( input.speed,  input.speed);
231
+
232
+		break; case 'H': swapCell(-1,  0);
233
+		break; case 'J': swapCell( 0,  1);
234
+		break; case 'K': swapCell( 0, -1);
235
+		break; case 'L': swapCell( 1,  0);
236
+		break; case 'Y': swapCell(-1, -1);
237
+		break; case 'U': swapCell( 1, -1);
238
+		break; case 'B': swapCell(-1,  1);
239
+		break; case 'N': swapCell( 1,  1);
240
+
241
+		break; case '`': input.color = attrsColor(inch());
242
+
243
+		break; case '0': colorFg(COLOR_BLACK);
244
+		break; case '1': colorFg(COLOR_RED);
245
+		break; case '2': colorFg(COLOR_GREEN);
246
+		break; case '3': colorFg(COLOR_YELLOW);
247
+		break; case '4': colorFg(COLOR_BLUE);
248
+		break; case '5': colorFg(COLOR_MAGENTA);
249
+		break; case '6': colorFg(COLOR_CYAN);
250
+		break; case '7': colorFg(COLOR_WHITE);
251
+
252
+		break; case ')': colorBg(COLOR_BLACK);
253
+		break; case '!': colorBg(COLOR_RED);
254
+		break; case '@': colorBg(COLOR_GREEN);
255
+		break; case '#': colorBg(COLOR_YELLOW);
256
+		break; case '$': colorBg(COLOR_BLUE);
257
+		break; case '%': colorBg(COLOR_MAGENTA);
258
+		break; case '^': colorBg(COLOR_CYAN);
259
+		break; case '&': colorBg(COLOR_WHITE);
260
+
261
+		break; case '*': case '8': input.color ^= COLOR_BRIGHT;
262
+
263
+		break; case '(': case '9': colorInvert();
264
+
265
+		break; case KEY_LEFT:  clientMove(-1,  0);
266
+		break; case KEY_DOWN:  clientMove( 0,  1);
267
+		break; case KEY_UP:    clientMove( 0, -1);
268
+		break; case KEY_RIGHT: clientMove( 1,  0);
269
+	}
270
+
271
+	if (input.mode == MODE_DRAW && input.draw) clientPut(input.color, input.draw);
274 272
 }
275 273
 
276 274
 static void serverPut(uint8_t x, uint8_t y, uint8_t color, char cell) {
277
-    mvaddch(y, x, colorAttrs(color) | cell);
275
+	mvaddch(y, x, colorAttrs(color) | cell);
278 276
 }
279 277
 
280 278
 static void serverTile(void) {
281
-    struct Tile tile;
282
-    ssize_t size = recv(client, &tile, sizeof(tile), 0);
283
-    if (size < 0) err(EX_IOERR, "recv");
284
-    if ((size_t)size < sizeof(tile)) {
285
-        errx(EX_PROTOCOL, "This tile isn't big enough...");
286
-    }
287
-
288
-    for (int y = 0; y < CELL_ROWS; ++y) {
289
-        for (int x = 0; x < CELL_COLS; ++x) {
290
-            serverPut(x, y, tile.colors[y][x], tile.cells[y][x]);
291
-        }
292
-    }
279
+	struct Tile tile;
280
+	ssize_t size = recv(client, &tile, sizeof(tile), 0);
281
+	if (size < 0) err(EX_IOERR, "recv");
282
+	if ((size_t)size < sizeof(tile)) {
283
+		errx(EX_PROTOCOL, "This tile isn't big enough...");
284
+	}
285
+
286
+	for (int y = 0; y < CELL_ROWS; ++y) {
287
+		for (int x = 0; x < CELL_COLS; ++x) {
288
+			serverPut(x, y, tile.colors[y][x], tile.cells[y][x]);
289
+		}
290
+	}
293 291
 }
294 292
 
295 293
 static void serverCursor(uint8_t oldX, uint8_t oldY, uint8_t newX, uint8_t newY) {
296
-    if (oldX != CURSOR_NONE) {
297
-        move(oldY, oldX);
298
-        addch(inch() & ~A_REVERSE);
299
-    }
300
-    if (newX != CURSOR_NONE) {
301
-        move(newY, newX);
302
-        addch(inch() | A_REVERSE);
303
-    }
294
+	if (oldX != CURSOR_NONE) {
295
+		move(oldY, oldX);
296
+		addch(inch() & ~A_REVERSE);
297
+	}
298
+	if (newX != CURSOR_NONE) {
299
+		move(newY, newX);
300
+		addch(inch() | A_REVERSE);
301
+	}
304 302
 }
305 303
 
306 304
 static void readMessage(void) {
307
-    struct ServerMessage msg;
308
-    ssize_t size = recv(client, &msg, sizeof(msg), 0);
309
-    if (size < 0) err(EX_IOERR, "recv");
310
-    if ((size_t)size < sizeof(msg)) errx(EX_PROTOCOL, "A message was cut short.");
311
-
312
-    int sy, sx;
313
-    getyx(stdscr, sy, sx);
314
-
315
-    switch (msg.type) {
316
-        case SERVER_TILE: {
317
-            serverTile();
318
-        } break;
319
-
320
-        case SERVER_MOVE: {
321
-            move(msg.move.cellY, msg.move.cellX);
322
-            refresh();
323
-        } return;
324
-
325
-        case SERVER_PUT: {
326
-            serverPut(
327
-                msg.put.cellX,
328
-                msg.put.cellY,
329
-                msg.put.color,
330
-                msg.put.cell
331
-            );
332
-        } break;
333
-
334
-        case SERVER_CURSOR: {
335
-            serverCursor(
336
-                msg.cursor.oldCellX,
337
-                msg.cursor.oldCellY,
338
-                msg.cursor.newCellX,
339
-                msg.cursor.newCellY
340
-            );
341
-        } break;
342
-
343
-        default: errx(EX_PROTOCOL, "I don't know what %d means!", msg.type);
344
-    }
345
-
346
-    move(sy, sx);
347
-    refresh();
305
+	struct ServerMessage msg;
306
+	ssize_t size = recv(client, &msg, sizeof(msg), 0);
307
+	if (size < 0) err(EX_IOERR, "recv");
308
+	if ((size_t)size < sizeof(msg)) errx(EX_PROTOCOL, "A message was cut short.");
309
+
310
+	int sy, sx;
311
+	getyx(stdscr, sy, sx);
312
+
313
+	switch (msg.type) {
314
+		break; case SERVER_TILE: {
315
+			serverTile();
316
+		}
317
+
318
+		break; case SERVER_MOVE: {
319
+			move(msg.move.cellY, msg.move.cellX);
320
+			refresh();
321
+			return;
322
+		}
323
+
324
+		break; case SERVER_PUT: {
325
+			serverPut(
326
+				msg.put.cellX,
327
+				msg.put.cellY,
328
+				msg.put.color,
329
+				msg.put.cell
330
+			);
331
+		}
332
+
333
+		break; case SERVER_CURSOR: {
334
+			serverCursor(
335
+				msg.cursor.oldCellX,
336
+				msg.cursor.oldCellY,
337
+				msg.cursor.newCellX,
338
+				msg.cursor.newCellY
339
+			);
340
+		}
341
+
342
+		break; default: errx(EX_PROTOCOL, "I don't know what %d means!", msg.type);
343
+	}
344
+
345
+	move(sy, sx);
346
+	refresh();
348 347
 }
349 348
 
350 349
 static void drawBorder(void) {
351
-    if (LINES < CELL_ROWS || COLS < CELL_COLS) {
352
-        endwin();
353
-        fprintf(stderr, "Sorry, your terminal is too small!\n");
354
-        fprintf(stderr, "It needs to be at least 80x25 characters.\n");
355
-        exit(EX_CONFIG);
356
-    }
357
-    if (LINES > CELL_ROWS) {
358
-        mvhline(CELL_ROWS, 0, 0, CELL_COLS);
359
-    }
360
-    if (COLS > CELL_COLS) {
361
-        mvvline(0, CELL_COLS, 0, CELL_ROWS);
362
-    }
363
-    if (LINES > CELL_ROWS && COLS > CELL_COLS) {
364
-        mvaddch(CELL_ROWS, CELL_COLS, ACS_LRCORNER);
365
-    }
350
+	if (LINES < CELL_ROWS || COLS < CELL_COLS) {
351
+		endwin();
352
+		fprintf(stderr, "Sorry, your terminal is too small!\n");
353
+		fprintf(stderr, "It needs to be at least 80x25 characters.\n");
354
+		exit(EX_CONFIG);
355
+	}
356
+	if (LINES > CELL_ROWS) {
357
+		mvhline(CELL_ROWS, 0, 0, CELL_COLS);
358
+	}
359
+	if (COLS > CELL_COLS) {
360
+		mvvline(0, CELL_COLS, 0, CELL_ROWS);
361
+	}
362
+	if (LINES > CELL_ROWS && COLS > CELL_COLS) {
363
+		mvaddch(CELL_ROWS, CELL_COLS, ACS_LRCORNER);
364
+	}
366 365
 }
367 366
 
368 367
 static void initColors(void) {
369
-    if (!has_colors()) {
370
-        endwin();
371
-        fprintf(
372
-            stderr,
373
-            "Sorry, your terminal doesn't support colors!\n"
374
-            "If you think it does, check TERM.\n"
375
-        );
376
-        exit(EX_CONFIG);
377
-    }
378
-    start_color();
379
-    if (COLOR_PAIRS < 64) {
380
-        endwin();
381
-        fprintf(
382
-            stderr,
383
-            "Sorry, your terminal doesn't support enough color pairs!\n"
384
-            "If you think it does, check TERM.\n"
385
-        );
386
-        exit(EX_CONFIG);
387
-    }
388
-    for (int bg = COLOR_BLACK; bg < COLOR_BRIGHT; ++bg) {
389
-        for (int fg = COLOR_BLACK; fg < COLOR_BRIGHT; ++fg) {
390
-            init_pair(PAIR_NUMBER(colorAttrs(bg << 4 | fg)), fg, bg);
391
-        }
392
-    }
368
+	if (!has_colors()) {
369
+		endwin();
370
+		fprintf(
371
+			stderr,
372
+			"Sorry, your terminal doesn't support colors!\n"
373
+			"If you think it does, check TERM.\n"
374
+		);
375
+		exit(EX_CONFIG);
376
+	}
377
+	start_color();
378
+	if (COLOR_PAIRS < 64) {
379
+		endwin();
380
+		fprintf(
381
+			stderr,
382
+			"Sorry, your terminal doesn't support enough color pairs!\n"
383
+			"If you think it does, check TERM.\n"
384
+		);
385
+		exit(EX_CONFIG);
386
+	}
387
+	for (int bg = COLOR_BLACK; bg < COLOR_BRIGHT; ++bg) {
388
+		for (int fg = COLOR_BLACK; fg < COLOR_BRIGHT; ++fg) {
389
+			init_pair(PAIR_NUMBER(colorAttrs(bg << 4 | fg)), fg, bg);
390
+		}
391
+	}
393 392
 }
394 393
 
395 394
 int main() {
396
-    client = socket(PF_LOCAL, SOCK_STREAM, 0);
397
-    if (client < 0) err(EX_OSERR, "socket");
398
-
399
-    struct sockaddr_un addr = {
400
-        .sun_family = AF_LOCAL,
401
-        .sun_path = "torus.sock",
402
-    };
403
-    int error = connect(client, (struct sockaddr *)&addr, sizeof(addr));
404
-    if (error) err(EX_NOINPUT, "torus.sock");
405
-
406
-    initscr();
407
-    cbreak();
408
-    noecho();
409
-    keypad(stdscr, true);
410
-    set_escdelay(100);
411
-
412
-    initColors();
413
-    drawBorder();
414
-
415
-    struct pollfd fds[2] = {
416
-        { .fd = STDIN_FILENO, .events = POLLIN },
417
-        { .fd = client, .events = POLLIN },
418
-    };
419
-    for (;;) {
420
-        int nfds = poll(fds, 2, -1);
421
-        if (nfds < 0 && errno == EINTR) continue;
422
-        if (nfds < 0) err(EX_IOERR, "poll");
423
-
424
-        if (fds[0].revents) readInput();
425
-        if (fds[1].revents) readMessage();
426
-    }
395
+	client = socket(PF_LOCAL, SOCK_STREAM, 0);
396
+	if (client < 0) err(EX_OSERR, "socket");
397
+
398
+	struct sockaddr_un addr = {
399
+		.sun_family = AF_LOCAL,
400
+		.sun_path = "torus.sock",
401
+	};
402
+	int error = connect(client, (struct sockaddr *)&addr, sizeof(addr));
403
+	if (error) err(EX_NOINPUT, "torus.sock");
404
+
405
+	initscr();
406
+	cbreak();
407
+	noecho();
408
+	keypad(stdscr, true);
409
+	set_escdelay(100);
410
+
411
+	initColors();
412
+	drawBorder();
413
+
414
+	struct pollfd fds[2] = {
415
+		{ .fd = STDIN_FILENO, .events = POLLIN },
416
+		{ .fd = client, .events = POLLIN },
417
+	};
418
+	for (;;) {
419
+		int nfds = poll(fds, 2, -1);
420
+		if (nfds < 0 && errno == EINTR) continue;
421
+		if (nfds < 0) err(EX_IOERR, "poll");
422
+
423
+		if (fds[0].revents) readInput();
424
+		if (fds[1].revents) readMessage();
425
+	}
427 426
 }

+ 122
- 122
help.c View File

@@ -1,4 +1,4 @@
1
-/* Copyright (c) 2017, Curtis McEnroe <curtis@cmcenroe.me>
1
+/* Copyright (C) 2017  Curtis McEnroe <june@causal.agency>
2 2
  *
3 3
  * This program is free software: you can redistribute it and/or modify
4 4
  * it under the terms of the GNU Affero General Public License as published by
@@ -26,37 +26,37 @@
26 26
 static int client;
27 27
 
28 28
 static void clientMessage(struct ClientMessage msg) {
29
-    ssize_t size = send(client, &msg, sizeof(msg), 0);
30
-    if (size < 0) err(EX_IOERR, "send");
29
+	ssize_t size = send(client, &msg, sizeof(msg), 0);
30
+	if (size < 0) err(EX_IOERR, "send");
31 31
 }
32 32
 
33 33
 static void clientMove(int8_t dx, int8_t dy) {
34
-    struct ClientMessage msg = {
35
-        .type = CLIENT_MOVE,
36
-        .move = { .dx = dx, .dy = dy },
37
-    };
38
-    clientMessage(msg);
34
+	struct ClientMessage msg = {
35
+		.type = CLIENT_MOVE,
36
+		.move = { .dx = dx, .dy = dy },
37
+	};
38
+	clientMessage(msg);
39 39
 }
40 40
 
41 41
 static void clientPut(uint8_t color, char cell) {
42
-    struct ClientMessage msg = {
43
-        .type = CLIENT_PUT,
44
-        .put = { .color = color, .cell = cell },
45
-    };
46
-    clientMessage(msg);
42
+	struct ClientMessage msg = {
43
+		.type = CLIENT_PUT,
44
+		.put = { .color = color, .cell = cell },
45
+	};
46
+	clientMessage(msg);
47 47
 }
48 48
 
49 49
 static const useconds_t DELAY = 50000;
50 50
 
51 51
 enum {
52
-    R = COLOR_RED,
53
-    G = COLOR_GREEN,
54
-    Y = COLOR_YELLOW,
55
-    B = COLOR_BLUE,
56
-    M = COLOR_MAGENTA,
57
-    C = COLOR_CYAN,
58
-    W = COLOR_WHITE,
59
-    I = COLOR_BRIGHT | COLOR_WHITE,
52
+	R = COLOR_RED,
53
+	G = COLOR_GREEN,
54
+	Y = COLOR_YELLOW,
55
+	B = COLOR_BLUE,
56
+	M = COLOR_MAGENTA,
57
+	C = COLOR_CYAN,
58
+	W = COLOR_WHITE,
59
+	I = COLOR_BRIGHT | COLOR_WHITE,
60 60
 };
61 61
 
62 62
 static void h(void) { clientMove(-1,  0); usleep(DELAY); }
@@ -69,116 +69,116 @@ static void b(void) { clientMove(-1,  1); usleep(DELAY); }
69 69
 static void n(void) { clientMove( 1,  1); usleep(DELAY); }
70 70
 
71 71
 static void p(uint8_t color, char cell) {
72
-    clientPut(color, cell);
73
-    usleep(DELAY);
72
+	clientPut(color, cell);
73
+	usleep(DELAY);
74 74
 }
75 75
 
76 76
 static uint8_t len;
77 77
 
78 78
 static void s(uint8_t color, const char *str) {
79
-    for (; *str; ++len, ++str) {
80
-        clientPut(color, *str);
81
-        clientMove(1, 0);
82
-        usleep(DELAY);
83
-    }
79
+	for (; *str; ++len, ++str) {
80
+		clientPut(color, *str);
81
+		clientMove(1, 0);
82
+		usleep(DELAY);
83
+	}
84 84
 }
85 85
 
86 86
 static void r(void) {
87
-    clientMove(-len, 1);
88
-    usleep(DELAY);
89
-    len = 0;
87
+	clientMove(-len, 1);
88
+	usleep(DELAY);
89
+	len = 0;
90 90
 }
91 91
 
92 92
 int main() {
93
-    client = socket(PF_LOCAL, SOCK_STREAM, 0);
94
-    if (client < 0) err(EX_OSERR, "socket");
95
-
96
-    struct sockaddr_un addr = {
97
-        .sun_family = AF_LOCAL,
98
-        .sun_path = "torus.sock",
99
-    };
100
-    int error = connect(client, (struct sockaddr *)&addr, sizeof(addr));
101
-    if (error) err(EX_NOINPUT, "torus.sock");
102
-
103
-    pid_t pid = fork();
104
-    if (pid < 0) err(EX_OSERR, "fork");
105
-
106
-    if (!pid) {
107
-        for (;;) {
108
-            char buf[4096];
109
-            ssize_t size = recv(client, buf, sizeof(buf), 0);
110
-            if (size < 0) err(EX_IOERR, "recv");
111
-            if (!size) return EX_OK;
112
-        }
113
-    }
114
-
115
-    clientMove(-CELL_INIT_X, -CELL_INIT_Y);
116
-    clientMove(28, 0);
117
-
118
-    for (;;) {
119
-        for (int i = 0; i < 10; ++i) {
120
-            clientMove(0, 1);
121
-            usleep(DELAY / 5);
122
-        }
123
-        for (int i = 0; i < 11; ++i) {
124
-            for (int j = 0; j < 28; ++j) {
125
-                clientPut(W, ' ');
126
-                if (i % 2) clientMove(1, 0);
127
-                else clientMove(-1, 0);
128
-                usleep(DELAY / 5);
129
-            }
130
-            clientPut(W, ' ');
131
-            if (i != 10) clientMove(0, -1);
132
-            usleep(DELAY / 5);
133
-        }
134
-
135
-        j(); l(); l();
136
-        s(W, "Welcome to "); s(I, "ascii.town"); s(W, "!"); r();
137
-        r(); r();
138
-
139
-        n(); n(); s(W, "o-"); s(I, "l");
140
-        h(); b(); p(W, '\\'); n(); p(I, 'n');
141
-        y(); h(); p(W, '|'); j(); p(I, 'j');
142
-        y(); p(W, '/'); b(); p(I, 'b');
143
-        k(); u(); p(W, '-'); h(); p(I, 'h');
144
-        u(); p(W, '\\'); y(); p(I, 'y');
145
-        n(); l(); p(W, '|'); k(); p(I, 'k');
146
-        n(); p(W, '/');  u(); p(I, 'u');
147
-
148
-        u(); s(W, "    "); len = 0;
149
-
150
-        s(I, "q "); s(W, "quit");    r();
151
-        s(I, "i "); s(W, "insert");  r();
152
-        s(I, "r "); s(W, "replace"); r();
153
-        s(I, "R "); s(W, "draw");    r();
154
-        s(I, "~ "); s(W, "color");   r();
155
-        s(I, "` "); s(W, "pipette"); r();
156
-        s(I, "* "); s(W, "bright");
157
-
158
-        s(W, "     "); len = 0;
159
-
160
-        clientPut(W, '7'); k();
161
-        clientPut(C, '6'); k();
162
-        clientPut(M, '5'); k();
163
-        clientPut(B, '4'); k();
164
-        clientPut(Y, '3'); k();
165
-        clientPut(G, '2'); k();
166
-        clientPut(R, '1'); k();
167
-
168
-        l(); n();
169
-
170
-        clientPut(R << 4, '!'); j();
171
-        clientPut(G << 4, '@'); j();
172
-        clientPut(Y << 4, '#'); j();
173
-        clientPut(B << 4, '$'); j();
174
-        clientPut(M << 4, '%'); j();
175
-        clientPut(C << 4, '^'); j();
176
-        clientPut(W << 4, '&'); j();
177
-
178
-        h(); k(); k(); k(); k(); k(); k(); k(); k(); k(); h();
179
-
180
-        sleep(30);
181
-
182
-        u(); l(); l(); l();
183
-    }
93
+	client = socket(PF_LOCAL, SOCK_STREAM, 0);
94
+	if (client < 0) err(EX_OSERR, "socket");
95
+
96
+	struct sockaddr_un addr = {
97
+		.sun_family = AF_LOCAL,
98
+		.sun_path = "torus.sock",
99
+	};
100
+	int error = connect(client, (struct sockaddr *)&addr, sizeof(addr));
101
+	if (error) err(EX_NOINPUT, "torus.sock");
102
+
103
+	pid_t pid = fork();
104
+	if (pid < 0) err(EX_OSERR, "fork");
105
+
106
+	if (!pid) {
107
+		for (;;) {
108
+			char buf[4096];
109
+			ssize_t size = recv(client, buf, sizeof(buf), 0);
110
+			if (size < 0) err(EX_IOERR, "recv");
111
+			if (!size) return EX_OK;
112
+		}
113
+	}
114
+
115
+	clientMove(-CELL_INIT_X, -CELL_INIT_Y);
116
+	clientMove(28, 0);
117
+
118
+	for (;;) {
119
+		for (int i = 0; i < 10; ++i) {
120
+			clientMove(0, 1);
121
+			usleep(DELAY / 5);
122
+		}
123
+		for (int i = 0; i < 11; ++i) {
124
+			for (int j = 0; j < 28; ++j) {
125
+				clientPut(W, ' ');
126
+				if (i % 2) clientMove(1, 0);
127
+				else clientMove(-1, 0);
128
+				usleep(DELAY / 5);
129
+			}
130
+			clientPut(W, ' ');
131
+			if (i != 10) clientMove(0, -1);
132
+			usleep(DELAY / 5);
133
+		}
134
+
135
+		j(); l(); l();
136
+		s(W, "Welcome to "); s(I, "ascii.town"); s(W, "!"); r();
137
+		r(); r();
138
+
139
+		n(); n(); s(W, "o-"); s(I, "l");
140
+		h(); b(); p(W, '\\'); n(); p(I, 'n');
141
+		y(); h(); p(W, '|'); j(); p(I, 'j');
142
+		y(); p(W, '/'); b(); p(I, 'b');
143
+		k(); u(); p(W, '-'); h(); p(I, 'h');
144
+		u(); p(W, '\\'); y(); p(I, 'y');
145
+		n(); l(); p(W, '|'); k(); p(I, 'k');
146
+		n(); p(W, '/');  u(); p(I, 'u');
147
+
148
+		u(); s(W, "    "); len = 0;
149
+
150
+		s(I, "q "); s(W, "quit");    r();
151
+		s(I, "i "); s(W, "insert");  r();
152
+		s(I, "r "); s(W, "replace"); r();
153
+		s(I, "R "); s(W, "draw");    r();
154
+		s(I, "~ "); s(W, "color");   r();
155
+		s(I, "` "); s(W, "pipette"); r();
156
+		s(I, "* "); s(W, "bright");
157
+
158
+		s(W, "     "); len = 0;
159
+
160
+		clientPut(W, '7'); k();
161
+		clientPut(C, '6'); k();
162
+		clientPut(M, '5'); k();
163
+		clientPut(B, '4'); k();
164
+		clientPut(Y, '3'); k();
165
+		clientPut(G, '2'); k();
166
+		clientPut(R, '1'); k();
167
+
168
+		l(); n();
169
+
170
+		clientPut(R << 4, '!'); j();
171
+		clientPut(G << 4, '@'); j();
172
+		clientPut(Y << 4, '#'); j();
173
+		clientPut(B << 4, '$'); j();
174
+		clientPut(M << 4, '%'); j();
175
+		clientPut(C << 4, '^'); j();
176
+		clientPut(W << 4, '&'); j();
177
+
178
+		h(); k(); k(); k(); k(); k(); k(); k(); k(); k(); h();
179
+
180
+		sleep(30);
181
+
182
+		u(); l(); l(); l();
183
+	}
184 184
 }

+ 2
- 2
index.html View File

@@ -4,11 +4,11 @@
4 4
 Hey there, friend. This should get you there.
5 5
 <p>
6 6
 <code>
7
-    ssh torus@ascii.town
7
+	ssh torus@ascii.town
8 8
 </code>
9 9
 <p>
10 10
 You can also take a detour and play NetHack.
11 11
 <p>
12 12
 <code>
13
-    ssh nethack@ascii.town
13
+	ssh nethack@ascii.town
14 14
 </code>

+ 73
- 73
merge.c View File

@@ -1,4 +1,4 @@
1
-/* Copyright (c) 2017, Curtis McEnroe <curtis@cmcenroe.me>
1
+/* Copyright (C) 2017  Curtis McEnroe <june@causal.agency>
2 2
  *
3 3
  * This program is free software: you can redistribute it and/or modify
4 4
  * it under the terms of the GNU Affero General Public License as published by
@@ -23,79 +23,79 @@
23 23
 #include "torus.h"
24 24
 
25 25
 static void drawTile(int offsetY, const struct Tile *tile) {
26
-    for (uint8_t y = 0; y < CELL_ROWS; ++y) {
27
-        for (uint8_t x = 0; x < CELL_COLS; ++x) {
28
-            uint8_t color = tile->colors[y][x];
29
-            char cell = tile->cells[y][x];
30
-
31
-            int attrs = COLOR_PAIR(color & ~COLOR_BRIGHT);
32
-            if (color & COLOR_BRIGHT) attrs |= A_BOLD;
33
-            mvaddch(offsetY + y, x, attrs | cell);
34
-        }
35
-    }
26
+	for (uint8_t y = 0; y < CELL_ROWS; ++y) {
27
+		for (uint8_t x = 0; x < CELL_COLS; ++x) {
28
+			uint8_t color = tile->colors[y][x];
29
+			char cell = tile->cells[y][x];
30
+
31
+			int attrs = COLOR_PAIR(color & ~COLOR_BRIGHT);
32
+			if (color & COLOR_BRIGHT) attrs |= A_BOLD;
33
+			mvaddch(offsetY + y, x, attrs | cell);
34
+		}
35
+	}
36 36
 }
37 37
 
38 38
 int main(int argc, char *argv[]) {
39
-    if (argc != 4) return EX_USAGE;
40
-
41
-    FILE *fileA = fopen(argv[1], "r");
42
-    if (!fileA) err(EX_NOINPUT, "%s", argv[1]);
43
-
44
-    FILE *fileB = fopen(argv[2], "r");
45
-    if (!fileB) err(EX_NOINPUT, "%s", argv[2]);
46
-
47
-    FILE *fileC = fopen(argv[3], "w");
48
-    if (!fileC) err(EX_CANTCREAT, "%s", argv[3]);
49
-
50
-    initscr();
51
-    cbreak();
52
-    noecho();
53
-    keypad(stdscr, true);
54
-    set_escdelay(100);
55
-
56
-    start_color();
57
-    for (int bg = COLOR_BLACK; bg < COLOR_BRIGHT; ++bg) {
58
-        for (int fg = COLOR_BLACK; fg < COLOR_BRIGHT; ++fg) {
59
-            init_pair(bg << 4 | fg, fg, bg);
60
-        }
61
-    }
62
-
63
-    mvhline(CELL_ROWS, 0, 0, CELL_COLS);
64
-    mvhline(CELL_ROWS * 2 + 1, 0, 0, CELL_COLS);
65
-    mvvline(0, CELL_COLS, 0, CELL_ROWS * 2 + 1);
66
-    mvaddch(CELL_ROWS, CELL_COLS, ACS_RTEE);
67
-    mvaddch(CELL_ROWS * 2 + 1, CELL_COLS, ACS_LRCORNER);
68
-
69
-    struct Tile tileA, tileB;
70
-    for (;;) {
71
-        size_t countA = fread(&tileA, sizeof(tileA), 1, fileA);
72
-        if (ferror(fileA)) err(EX_IOERR, "%s", argv[1]);
73
-
74
-        size_t countB = fread(&tileB, sizeof(tileB), 1, fileB);
75
-        if (ferror(fileB)) err(EX_IOERR, "%s", argv[2]);
76
-
77
-        if (!countA && !countB) break;
78
-        if (!countA || !countB) errx(EX_DATAERR, "different size inputs");
79
-
80
-        const struct Tile *tileC = (tileA.accessTime > tileB.accessTime)
81
-            ? &tileA
82
-            : &tileB;
83
-
84
-        if (tileA.modifyTime != tileB.modifyTime) {
85
-            drawTile(0, &tileA);
86
-            drawTile(CELL_ROWS + 1, &tileB);
87
-            move(CELL_ROWS * 2 + 2, 0);
88
-            refresh();
89
-
90
-            int c;
91
-            do { c = getch(); } while (c != 'a' && c != 'b');
92
-            tileC = (c == 'a') ? &tileA : &tileB;
93
-        }
94
-
95
-        fwrite(tileC, sizeof(*tileC), 1, fileC);
96
-        if (ferror(fileC)) err(EX_IOERR, "%s", argv[3]);
97
-    }
98
-
99
-    endwin();
100
-    return EX_OK;
39
+	if (argc != 4) return EX_USAGE;
40
+
41
+	FILE *fileA = fopen(argv[1], "r");
42
+	if (!fileA) err(EX_NOINPUT, "%s", argv[1]);
43
+
44
+	FILE *fileB = fopen(argv[2], "r");
45
+	if (!fileB) err(EX_NOINPUT, "%s", argv[2]);
46
+
47
+	FILE *fileC = fopen(argv[3], "w");
48
+	if (!fileC) err(EX_CANTCREAT, "%s", argv[3]);
49
+
50
+	initscr();
51
+	cbreak();
52
+	noecho();
53
+	keypad(stdscr, true);
54
+	set_escdelay(100);
55
+
56
+	start_color();
57
+	for (int bg = COLOR_BLACK; bg < COLOR_BRIGHT; ++bg) {
58
+		for (int fg = COLOR_BLACK; fg < COLOR_BRIGHT; ++fg) {
59
+			init_pair(bg << 4 | fg, fg, bg);
60
+		}
61
+	}
62
+
63
+	mvhline(CELL_ROWS, 0, 0, CELL_COLS);
64
+	mvhline(CELL_ROWS * 2 + 1, 0, 0, CELL_COLS);
65
+	mvvline(0, CELL_COLS, 0, CELL_ROWS * 2 + 1);
66
+	mvaddch(CELL_ROWS, CELL_COLS, ACS_RTEE);
67
+	mvaddch(CELL_ROWS * 2 + 1, CELL_COLS, ACS_LRCORNER);
68
+
69
+	struct Tile tileA, tileB;
70
+	for (;;) {
71
+		size_t countA = fread(&tileA, sizeof(tileA), 1, fileA);
72
+		if (ferror(fileA)) err(EX_IOERR, "%s", argv[1]);
73
+
74
+		size_t countB = fread(&tileB, sizeof(tileB), 1, fileB);
75
+		if (ferror(fileB)) err(EX_IOERR, "%s", argv[2]);
76
+
77
+		if (!countA && !countB) break;
78
+		if (!countA || !countB) errx(EX_DATAERR, "different size inputs");
79
+
80
+		const struct Tile *tileC = (tileA.accessTime > tileB.accessTime)
81
+			? &tileA
82
+			: &tileB;
83
+
84
+		if (tileA.modifyTime != tileB.modifyTime) {
85
+			drawTile(0, &tileA);
86
+			drawTile(CELL_ROWS + 1, &tileB);
87
+			move(CELL_ROWS * 2 + 2, 0);
88
+			refresh();
89
+
90
+			int c;
91
+			do { c = getch(); } while (c != 'a' && c != 'b');
92
+			tileC = (c == 'a') ? &tileA : &tileB;
93
+		}
94
+
95
+		fwrite(tileC, sizeof(*tileC), 1, fileC);
96
+		if (ferror(fileC)) err(EX_IOERR, "%s", argv[3]);
97
+	}
98
+
99
+	endwin();
100
+	return EX_OK;
101 101
 }

+ 18
- 18
meta.c View File

@@ -1,4 +1,4 @@
1
-/* Copyright (c) 2017, Curtis McEnroe <curtis@cmcenroe.me>
1
+/* Copyright (C) 2017  Curtis McEnroe <june@causal.agency>
2 2
  *
3 3
  * This program is free software: you can redistribute it and/or modify
4 4
  * it under the terms of the GNU Affero General Public License as published by
@@ -21,22 +21,22 @@
21 21
 #include "torus.h"
22 22
 
23 23
 int main() {
24
-    printf("tileX,tileY,createTime,modifyCount,modifyTime,accessCount,accessTime\n");
25
-    for (int i = 0;; ++i) {
26
-        struct Tile tile;
27
-        size_t count = fread(&tile, sizeof(tile), 1, stdin);
28
-        if (ferror(stdin)) err(EX_IOERR, "(stdin)");
29
-        if (!count) return EX_OK;
24
+	printf("tileX,tileY,createTime,modifyCount,modifyTime,accessCount,accessTime\n");
25
+	for (int i = 0;; ++i) {
26
+		struct Tile tile;
27
+		size_t count = fread(&tile, sizeof(tile), 1, stdin);
28
+		if (ferror(stdin)) err(EX_IOERR, "(stdin)");
29
+		if (!count) return EX_OK;
30 30
 
31
-        printf(
32
-            "%d,%d,%ld,%u,%ld,%u,%ld\n",
33
-            i % TILE_COLS,
34
-            i / TILE_COLS,
35
-            tile.createTime,
36
-            tile.modifyCount,
37
-            tile.modifyTime,
38
-            tile.accessCount,
39
-            tile.accessTime
40
-        );
41
-    }
31
+		printf(
32
+			"%d,%d,%ld,%u,%ld,%u,%ld\n",
33
+			i % TILE_COLS,
34
+			i / TILE_COLS,
35
+			tile.createTime,
36
+			tile.modifyCount,
37
+			tile.modifyTime,
38
+			tile.accessCount,
39
+			tile.accessTime
40
+		);
41
+	}
42 42
 }

+ 282
- 282
server.c View File

@@ -1,4 +1,4 @@
1
-/* Copyright (c) 2017, Curtis McEnroe <curtis@cmcenroe.me>
1
+/* Copyright (C) 2017  Curtis McEnroe <june@causal.agency>
2 2
  *
3 3
  * This program is free software: you can redistribute it and/or modify
4 4
  * it under the terms of the GNU Affero General Public License as published by
@@ -38,337 +38,337 @@
38 38
 static struct Tile *tiles;
39 39
 
40 40
 static void tilesMap(void) {
41
-    int fd = open("torus.dat", O_CREAT | O_RDWR, 0644);
42
-    if (fd < 0) err(EX_CANTCREAT, "torus.dat");
41
+	int fd = open("torus.dat", O_CREAT | O_RDWR, 0644);
42
+	if (fd < 0) err(EX_CANTCREAT, "torus.dat");
43 43
 
44
-    int error = ftruncate(fd, TILES_SIZE);
45
-    if (error) err(EX_IOERR, "ftruncate");
44
+	int error = ftruncate(fd, TILES_SIZE);
45
+	if (error) err(EX_IOERR, "ftruncate");
46 46
 
47
-    tiles = mmap(NULL, TILES_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
48
-    if (tiles == MAP_FAILED) err(EX_OSERR, "mmap");
47
+	tiles = mmap(NULL, TILES_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
48
+	if (tiles == MAP_FAILED) err(EX_OSERR, "mmap");
49 49
 
50
-    error = madvise(tiles, TILES_SIZE, MADV_RANDOM);
51
-    if (error) err(EX_OSERR, "madvise");
50
+	error = madvise(tiles, TILES_SIZE, MADV_RANDOM);
51
+	if (error) err(EX_OSERR, "madvise");
52 52
 
53 53
 #ifdef MADV_NOCORE
54
-    error = madvise(tiles, TILES_SIZE, MADV_NOCORE);
55
-    if (error) err(EX_OSERR, "madvise");
54
+	error = madvise(tiles, TILES_SIZE, MADV_NOCORE);
55
+	if (error) err(EX_OSERR, "madvise");
56 56
 #endif
57 57
 }
58 58
 
59 59
 static struct Tile *tileGet(uint32_t tileX, uint32_t tileY) {
60
-    struct Tile *tile = &tiles[tileY * TILE_ROWS + tileX];
61
-    if (!tile->createTime) {
62
-        memset(tile->cells, ' ', CELLS_SIZE);
63
-        memset(tile->colors, COLOR_WHITE, CELLS_SIZE);
64
-        tile->createTime = time(NULL);
65
-    }
66
-    return tile;
60
+	struct Tile *tile = &tiles[tileY * TILE_ROWS + tileX];
61
+	if (!tile->createTime) {
62
+		memset(tile->cells, ' ', CELLS_SIZE);
63
+		memset(tile->colors, COLOR_WHITE, CELLS_SIZE);
64
+		tile->createTime = time(NULL);
65
+	}
66
+	return tile;
67 67
 }
68 68
 
69 69
 static struct Tile *tileAccess(uint32_t tileX, uint32_t tileY) {
70
-    struct Tile *tile = tileGet(tileX, tileY);
71
-    tile->accessTime = time(NULL);
72
-    tile->accessCount++;
73
-    return tile;
70
+	struct Tile *tile = tileGet(tileX, tileY);
71
+	tile->accessTime = time(NULL);
72
+	tile->accessCount++;
73
+	return tile;
74 74
 }
75 75
 
76 76
 static struct Tile *tileModify(uint32_t tileX, uint32_t tileY) {
77
-    struct Tile *tile = tileGet(tileX, tileY);
78
-    tile->modifyTime = time(NULL);
79
-    tile->modifyCount++;
80
-    return tile;
77
+	struct Tile *tile = tileGet(tileX, tileY);
78
+	tile->modifyTime = time(NULL);
79
+	tile->modifyCount++;
80
+	return tile;
81 81
 }
82 82
 
83 83
 static struct Client {
84
-    int fd;
84
+	int fd;
85 85
 
86
-    uint32_t tileX;
87
-    uint32_t tileY;
88
-    uint8_t cellX;
89
-    uint8_t cellY;
86
+	uint32_t tileX;
87
+	uint32_t tileY;
88
+	uint8_t cellX;
89
+	uint8_t cellY;
90 90
 
91
-    struct Client *prev;
92
-    struct Client *next;
91
+	struct Client *prev;
92
+	struct Client *next;
93 93
 } *clientHead;
94 94
 
95 95
 static struct Client *clientAdd(int fd) {
96
-    struct Client *client = malloc(sizeof(*client));
97
-    if (!client) err(EX_OSERR, "malloc");
98
-
99
-    client->fd = fd;
100
-    client->tileX = TILE_VOID_X;
101
-    client->tileY = TILE_VOID_Y;
102
-    client->cellX = CELL_INIT_X;
103
-    client->cellY = CELL_INIT_Y;
104
-
105
-    client->prev = NULL;
106
-    if (clientHead) {
107
-        clientHead->prev = client;
108
-        client->next = clientHead;
109
-    } else {
110
-        client->next = NULL;
111
-    }
112
-    clientHead = client;
113
-
114
-    return client;
96
+	struct Client *client = malloc(sizeof(*client));
97
+	if (!client) err(EX_OSERR, "malloc");
98
+
99
+	client->fd = fd;
100
+	client->tileX = TILE_VOID_X;
101
+	client->tileY = TILE_VOID_Y;
102
+	client->cellX = CELL_INIT_X;
103
+	client->cellY = CELL_INIT_Y;
104
+
105
+	client->prev = NULL;
106
+	if (clientHead) {
107
+		clientHead->prev = client;
108
+		client->next = clientHead;
109
+	} else {
110
+		client->next = NULL;
111
+	}
112
+	clientHead = client;
113
+
114
+	return client;
115 115
 }
116 116
 
117 117
 static bool clientSend(const struct Client *client, struct ServerMessage msg) {
118
-    ssize_t size = send(client->fd, &msg, sizeof(msg), 0);
119
-    if (size < 0) return false;
118
+	ssize_t size = send(client->fd, &msg, sizeof(msg), 0);
119
+	if (size < 0) return false;
120 120
 
121
-    if (msg.type == SERVER_TILE) {
122
-        struct Tile *tile = tileAccess(client->tileX, client->tileY);
123
-        size = send(client->fd, tile, sizeof(*tile), 0);
124
-        if (size < 0) return false;
125
-    }
121
+	if (msg.type == SERVER_TILE) {
122
+		struct Tile *tile = tileAccess(client->tileX, client->tileY);
123
+		size = send(client->fd, tile, sizeof(*tile), 0);
124
+		if (size < 0) return false;
125
+	}
126 126
 
127
-    return true;
127
+	return true;
128 128
 }
129 129
 
130 130
 static void clientCast(const struct Client *origin, struct ServerMessage msg) {
131
-    for (struct Client *client = clientHead; client; client = client->next) {
132
-        if (client == origin) continue;
133
-        if (client->tileX != origin->tileX) continue;
134
-        if (client->tileY != origin->tileY) continue;
135
-        clientSend(client, msg);
136
-    }
131
+	for (struct Client *client = clientHead; client; client = client->next) {
132
+		if (client == origin) continue;
133
+		if (client->tileX != origin->tileX) continue;
134
+		if (client->tileY != origin->tileY) continue;
135
+		clientSend(client, msg);
136
+	}
137 137
 }
138 138
 
139 139
 static void clientRemove(struct Client *client) {
140
-    if (client->prev) client->prev->next = client->next;
141
-    if (client->next) client->next->prev = client->prev;
142
-    if (clientHead == client) clientHead = client->next;
143
-
144
-    struct ServerMessage msg = {
145
-        .type = SERVER_CURSOR,
146
-        .cursor = {
147
-            .oldCellX = client->cellX, .oldCellY = client->cellY,
148
-            .newCellX = CURSOR_NONE,   .newCellY = CURSOR_NONE,
149
-        },
150
-    };
151
-    clientCast(client, msg);
152
-
153
-    close(client->fd);
154
-    free(client);
140
+	if (client->prev) client->prev->next = client->next;
141
+	if (client->next) client->next->prev = client->prev;
142
+	if (clientHead == client) clientHead = client->next;
143
+
144
+	struct ServerMessage msg = {
145
+		.type = SERVER_CURSOR,
146
+		.cursor = {
147
+			.oldCellX = client->cellX, .oldCellY = client->cellY,
148
+			.newCellX = CURSOR_NONE,   .newCellY = CURSOR_NONE,
149
+		},
150
+	};
151
+	clientCast(client, msg);
152
+
153
+	close(client->fd);
154
+	free(client);
155 155
 }
156 156
 
157 157
 static bool clientCursors(const struct Client *client) {
158
-    struct ServerMessage msg = {
159
-        .type = SERVER_CURSOR,
160
-        .cursor = { .oldCellX = CURSOR_NONE, .oldCellY = CURSOR_NONE },
161
-    };
162
-
163
-    for (struct Client *friend = clientHead; friend; friend = friend->next) {
164
-        if (friend == client) continue;
165
-        if (friend->tileX != client->tileX) continue;
166
-        if (friend->tileY != client->tileY) continue;
167
-
168
-        msg.cursor.newCellX = friend->cellX;
169
-        msg.cursor.newCellY = friend->cellY;
170
-        if (!clientSend(client, msg)) return false;
171
-    }
172
-    return true;
158
+	struct ServerMessage msg = {
159
+		.type = SERVER_CURSOR,
160
+		.cursor = { .oldCellX = CURSOR_NONE, .oldCellY = CURSOR_NONE },
161
+	};
162
+
163
+	for (struct Client *friend = clientHead; friend; friend = friend->next) {
164
+		if (friend == client) continue;
165
+		if (friend->tileX != client->tileX) continue;
166
+		if (friend->tileY != client->tileY) continue;
167
+
168
+		msg.cursor.newCellX = friend->cellX;
169
+		msg.cursor.newCellY = friend->cellY;
170
+		if (!clientSend(client, msg)) return false;
171
+	}
172
+	return true;
173 173
 }
174 174
 
175 175
 static bool clientUpdate(const struct Client *client, const struct Client *old) {
176
-    struct ServerMessage msg = {
177
-        .type = SERVER_MOVE,
178
-        .move = { .cellX = client->cellX, .cellY = client->cellY },
179
-    };
180
-    if (!clientSend(client, msg)) return false;
181
-
182
-    if (client->tileX != old->tileX || client->tileY != old->tileY) {
183
-        msg.type = SERVER_TILE;
184
-        if (!clientSend(client, msg)) return false;
185
-
186
-        if (!clientCursors(client)) return false;
187
-
188
-        msg = (struct ServerMessage) {
189
-            .type = SERVER_CURSOR,
190
-            .cursor = {
191
-                .oldCellX = old->cellX,  .oldCellY = old->cellY,
192
-                .newCellX = CURSOR_NONE, .newCellY = CURSOR_NONE,
193
-            },
194
-        };
195
-        clientCast(old, msg);
196
-
197
-        msg = (struct ServerMessage) {
198
-            .type = SERVER_CURSOR,
199
-            .cursor = {
200
-                .oldCellX = CURSOR_NONE,   .oldCellY = CURSOR_NONE,
201
-                .newCellX = client->cellX, .newCellY = client->cellY,
202
-            },
203
-        };
204
-        clientCast(client, msg);
205
-
206
-    } else {
207
-        msg = (struct ServerMessage) {
208
-            .type = SERVER_CURSOR,
209
-            .cursor = {
210
-                .oldCellX = old->cellX,    .oldCellY = old->cellY,
211
-                .newCellX = client->cellX, .newCellY = client->cellY,
212
-            },
213
-        };
214
-        clientCast(client, msg);
215
-    }
216
-
217
-    return true;
176
+	struct ServerMessage msg = {
177
+		.type = SERVER_MOVE,
178
+		.move = { .cellX = client->cellX, .cellY = client->cellY },
179
+	};
180
+	if (!clientSend(client, msg)) return false;
181
+
182
+	if (client->tileX != old->tileX || client->tileY != old->tileY) {
183
+		msg.type = SERVER_TILE;
184
+		if (!clientSend(client, msg)) return false;
185
+
186
+		if (!clientCursors(client)) return false;
187
+
188
+		msg = (struct ServerMessage) {
189
+			.type = SERVER_CURSOR,
190
+			.cursor = {
191
+				.oldCellX = old->cellX,  .oldCellY = old->cellY,
192
+				.newCellX = CURSOR_NONE, .newCellY = CURSOR_NONE,
193
+			},
194
+		};
195
+		clientCast(old, msg);
196
+
197
+		msg = (struct ServerMessage) {
198
+			.type = SERVER_CURSOR,
199
+			.cursor = {
200
+				.oldCellX = CURSOR_NONE,   .oldCellY = CURSOR_NONE,
201
+				.newCellX = client->cellX, .newCellY = client->cellY,
202
+			},
203
+		};
204
+		clientCast(client, msg);
205
+
206
+	} else {
207
+		msg = (struct ServerMessage) {
208
+			.type = SERVER_CURSOR,
209
+			.cursor = {
210
+				.oldCellX = old->cellX,    .oldCellY = old->cellY,
211
+				.newCellX = client->cellX, .newCellY = client->cellY,
212
+			},
213
+		};
214
+		clientCast(client, msg);
215
+	}
216
+
217
+	return true;
218 218
 }
219 219
 
220 220
 static bool clientSpawn(struct Client *client, uint8_t spawn) {
221
-    if (spawn >= SPAWNS_LEN) return false;
222
-    struct Client old = *client;
223
-    client->tileX = SPAWNS[spawn].tileX;
224
-    client->tileY = SPAWNS[spawn].tileY;
225
-    client->cellX = CELL_INIT_X;
226
-    client->cellY = CELL_INIT_Y;
227
-    return clientUpdate(client, &old);
221
+	if (spawn >= SPAWNS_LEN) return false;
222
+	struct Client old = *client;
223
+	client->tileX = SPAWNS[spawn].tileX;
224
+	client->tileY = SPAWNS[spawn].tileY;
225
+	client->cellX = CELL_INIT_X;
226
+	client->cellY = CELL_INIT_Y;
227
+	return clientUpdate(client, &old);
228 228
 }
229 229
 
230 230
 static bool clientMove(struct Client *client, int8_t dx, int8_t dy) {
231
-    struct Client old = *client;
232
-
233
-    if (dx > CELL_COLS - client->cellX) dx = CELL_COLS - client->cellX;
234
-    if (dx < -client->cellX - 1)        dx = -client->cellX - 1;
235
-    if (dy > CELL_ROWS - client->cellY) dy = CELL_ROWS - client->cellY;
236
-    if (dy < -client->cellY - 1)        dy = -client->cellY - 1;
237
-
238
-    client->cellX += dx;
239
-    client->cellY += dy;
240
-
241
-    if (client->cellX == CELL_COLS) {
242
-        client->tileX++;
243
-        client->cellX = 0;
244
-    }
245
-    if (client->cellX == UINT8_MAX) {
246
-        client->tileX--;
247
-        client->cellX = CELL_COLS - 1;
248
-    }
249
-    if (client->cellY == CELL_ROWS) {
250
-        client->tileY++;
251
-        client->cellY = 0;
252
-    }
253
-    if (client->cellY == UINT8_MAX) {
254
-        client->tileY--;
255
-        client->cellY = CELL_ROWS - 1;
256
-    }
257
-
258
-    if (client->tileX == TILE_COLS)  client->tileX = 0;
259
-    if (client->tileX == UINT32_MAX) client->tileX = TILE_COLS - 1;
260
-    if (client->tileY == TILE_ROWS)  client->tileY = 0;
261
-    if (client->tileY == UINT32_MAX) client->tileY = TILE_ROWS - 1;
262
-
263
-    assert(client->cellX < CELL_COLS);
264
-    assert(client->cellY < CELL_ROWS);
265
-    assert(client->tileX < TILE_COLS);
266
-    assert(client->tileY < TILE_ROWS);
267
-
268
-    return clientUpdate(client, &old);
231
+	struct Client old = *client;
232
+
233
+	if (dx > CELL_COLS - client->cellX) dx = CELL_COLS - client->cellX;
234
+	if (dx < -client->cellX - 1)        dx = -client->cellX - 1;
235
+	if (dy > CELL_ROWS - client->cellY) dy = CELL_ROWS - client->cellY;
236
+	if (dy < -client->cellY - 1)        dy = -client->cellY - 1;
237
+
238
+	client->cellX += dx;
239
+	client->cellY += dy;
240
+
241
+	if (client->cellX == CELL_COLS) {
242
+		client->tileX++;
243
+		client->cellX = 0;
244
+	}
245
+	if (client->cellX == UINT8_MAX) {
246
+		client->tileX--;
247
+		client->cellX = CELL_COLS - 1;
248
+	}
249
+	if (client->cellY == CELL_ROWS) {
250
+		client->tileY++;
251
+		client->cellY = 0;
252
+	}
253
+	if (client->cellY == UINT8_MAX) {
254
+		client->tileY--;
255
+		client->cellY = CELL_ROWS - 1;
256
+	}
257
+
258
+	if (client->tileX == TILE_COLS)  client->tileX = 0;
259
+	if (client->tileX == UINT32_MAX) client->tileX = TILE_COLS - 1;
260
+	if (client->tileY == TILE_ROWS)  client->tileY = 0;
261
+	if (client->tileY == UINT32_MAX) client->tileY = TILE_ROWS - 1;
262
+
263
+	assert(client->cellX < CELL_COLS);
264
+	assert(client->cellY < CELL_ROWS);
265
+	assert(client->tileX < TILE_COLS);
266
+	assert(client->tileY < TILE_ROWS);
267
+
268
+	return clientUpdate(client, &old);
269 269
 }
270 270
 
271 271
 static bool clientPut(const struct Client *client, uint8_t color, char cell) {
272
-    struct Tile *tile = tileModify(client->tileX, client->tileY);
273
-    tile->colors[client->cellY][client->cellX] = color;
274
-    tile->cells[client->cellY][client->cellX] = cell;
275
-
276
-    struct ServerMessage msg = {
277
-        .type = SERVER_PUT,
278
-        .put = {
279
-            .cellX = client->cellX,
280
-            .cellY = client->cellY,
281
-            .color = color,
282
-            .cell = cell,
283
-        },
284
-    };
285
-    bool success = clientSend(client, msg);
286
-    clientCast(client, msg);
287
-    return success;
272
+	struct Tile *tile = tileModify(client->tileX, client->tileY);
273
+	tile->colors[client->cellY][client->cellX] = color;
274
+	tile->cells[client->cellY][client->cellX] = cell;
275
+
276
+	struct ServerMessage msg = {
277
+		.type = SERVER_PUT,
278
+		.put = {
279
+			.cellX = client->cellX,
280
+			.cellY = client->cellY,
281
+			.color = color,
282
+			.cell = cell,
283
+		},
284
+	};
285
+	bool success = clientSend(client, msg);
286
+	clientCast(client, msg);
287
+	return success;
288 288
 }
289 289
 
290 290
 int main() {
291
-    int error;
292
-
293
-    tilesMap();
294
-
295
-    int server = socket(PF_LOCAL, SOCK_STREAM, 0);
296
-    if (server < 0) err(EX_OSERR, "socket");
297
-
298
-    error = unlink("torus.sock");
299
-    if (error && errno != ENOENT) err(EX_IOERR, "torus.sock");
300
-
301
-    struct sockaddr_un addr = {
302
-        .sun_family = AF_LOCAL,
303
-        .sun_path = "torus.sock",
304
-    };
305
-    error = bind(server, (struct sockaddr *)&addr, sizeof(addr));
306
-    if (error) err(EX_CANTCREAT, "torus.sock");
307
-
308
-    error = listen(server, 0);
309
-    if (error) err(EX_OSERR, "listen");
310
-
311
-    int kq = kqueue();
312
-    if (kq < 0) err(EX_OSERR, "kqueue");
313
-
314
-    struct kevent event = {
315
-        .ident = server,
316
-        .filter = EVFILT_READ,
317
-        .flags = EV_ADD,
318
-    };
319
-    int nevents = kevent(kq, &event, 1, NULL, 0, NULL);
320
-    if (nevents < 0) err(EX_OSERR, "kevent");
321
-
322
-    for (;;) {
323
-        nevents = kevent(kq, NULL, 0, &event, 1, NULL);
324
-        if (nevents < 0) err(EX_IOERR, "kevent");
325
-
326
-        if (!event.udata) {
327
-            int fd = accept(server, NULL, NULL);
328
-            if (fd < 0) err(EX_IOERR, "accept");
329
-            fcntl(fd, F_SETFL, O_NONBLOCK);
330
-
331
-            int on = 1;
332
-            error = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
333
-            if (error) err(EX_IOERR, "setsockopt");
334
-
335
-            struct Client *client = clientAdd(fd);
336
-
337
-            struct kevent event = {
338
-                .ident = fd,
339
-                .filter = EVFILT_READ,
340
-                .flags = EV_ADD,
341
-                .udata = client,
342
-            };
343
-            nevents = kevent(kq, &event, 1, NULL, 0, NULL);
344
-            if (nevents < 0) err(EX_IOERR, "kevent");
345
-
346
-            if (!clientSpawn(client, 0)) clientRemove(client);
347
-
348
-            continue;
349
-        }
350
-
351
-        struct Client *client = event.udata;
352
-        if (event.flags & EV_EOF) {
353
-            clientRemove(client);
354
-            continue;
355
-        }
356
-
357
-        struct ClientMessage msg;
358
-        ssize_t size = recv(client->fd, &msg, sizeof(msg), 0);
359
-        if (size != sizeof(msg)) {
360
-            clientRemove(client);
361
-            continue;
362
-        }
363
-
364
-        bool success = false;
365
-        if (msg.type == CLIENT_MOVE) {
366
-            success = clientMove(client, msg.move.dx, msg.move.dy);
367
-        } else if (msg.type == CLIENT_PUT) {
368
-            success = clientPut(client, msg.put.color, msg.put.cell);
369
-        } else if (msg.type == CLIENT_SPAWN) {
370
-            success = clientSpawn(client, msg.spawn);
371
-        }
372
-        if (!success) clientRemove(client);
373
-    }
291
+	int error;
292
+
293
+	tilesMap();
294
+
295
+	int server = socket(PF_LOCAL, SOCK_STREAM, 0);
296
+	if (server < 0) err(EX_OSERR, "socket");
297
+
298
+	error = unlink("torus.sock");
299
+	if (error && errno != ENOENT) err(EX_IOERR, "torus.sock");
300
+
301
+	struct sockaddr_un addr = {
302
+		.sun_family = AF_LOCAL,
303
+		.sun_path = "torus.sock",
304
+	};
305
+	error = bind(server, (struct sockaddr *)&addr, sizeof(addr));
306
+	if (error) err(EX_CANTCREAT, "torus.sock");
307
+
308
+	error = listen(server, 0);
309
+	if (error) err(EX_OSERR, "listen");
310
+
311
+	int kq = kqueue();
312
+	if (kq < 0) err(EX_OSERR, "kqueue");
313
+
314
+	struct kevent event = {
315
+		.ident = server,
316
+		.filter = EVFILT_READ,
317
+		.flags = EV_ADD,
318
+	};
319
+	int nevents = kevent(kq, &event, 1, NULL, 0, NULL);
320
+	if (nevents < 0) err(EX_OSERR, "kevent");
321
+
322
+	for (;;) {
323
+		nevents = kevent(kq, NULL, 0, &event, 1, NULL);
324
+		if (nevents < 0) err(EX_IOERR, "kevent");
325
+
326
+		if (!event.udata) {
327
+			int fd = accept(server, NULL, NULL);
328
+			if (fd < 0) err(EX_IOERR, "accept");
329
+			fcntl(fd, F_SETFL, O_NONBLOCK);
330
+
331
+			int on = 1;
332
+			error = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
333
+			if (error) err(EX_IOERR, "setsockopt");
334
+
335
+			struct Client *client = clientAdd(fd);
336
+
337
+			struct kevent event = {
338
+				.ident = fd,
339
+				.filter = EVFILT_READ,
340
+				.flags = EV_ADD,
341
+				.udata = client,
342
+			};
343
+			nevents = kevent(kq, &event, 1, NULL, 0, NULL);
344
+			if (nevents < 0) err(EX_IOERR, "kevent");
345
+
346
+			if (!clientSpawn(client, 0)) clientRemove(client);
347
+
348
+			continue;
349
+		}
350
+
351
+		struct Client *client = event.udata;
352
+		if (event.flags & EV_EOF) {
353
+			clientRemove(client);
354
+			continue;
355
+		}
356
+
357
+		struct ClientMessage msg;
358
+		ssize_t size = recv(client->fd, &msg, sizeof(msg), 0);
359
+		if (size != sizeof(msg)) {
360
+			clientRemove(client);
361
+			continue;
362
+		}
363
+
364
+		bool success = false;
365
+		if (msg.type == CLIENT_MOVE) {
366
+			success = clientMove(client, msg.move.dx, msg.move.dy);
367
+		} else if (msg.type == CLIENT_PUT) {
368
+			success = clientPut(client, msg.put.color, msg.put.cell);
369
+		} else if (msg.type == CLIENT_SPAWN) {
370
+			success = clientSpawn(client, msg.spawn);
371
+		}
372
+		if (!success) clientRemove(client);
373
+	}
374 374
 }

+ 9
- 9
sshd_config View File

@@ -1,13 +1,13 @@
1 1
 UsePAM no
2 2
 
3 3
 Match User torus
4
-    PasswordAuthentication yes
5
-    PermitEmptyPasswords yes
6
-    ChrootDirectory /home/torus
7
-    ForceCommand client
4
+	PasswordAuthentication yes
5
+	PermitEmptyPasswords yes
6
+	ChrootDirectory /home/torus
7
+	ForceCommand client
8 8
 
9
-    AllowAgentForwarding no
10
-    AllowTcpForwarding no
11
-    AllowStreamLocalForwarding no
12
-    MaxSessions 1
13
-    X11Forwarding no
9
+	AllowAgentForwarding no
10
+	AllowTcpForwarding no
11
+	AllowStreamLocalForwarding no
12
+	MaxSessions 1
13
+	X11Forwarding no

+ 69
- 69
torus.h View File

@@ -1,4 +1,4 @@
1
-/* Copyright (c) 2017, Curtis McEnroe <curtis@cmcenroe.me>
1
+/* Copyright (C) 2017  Curtis McEnroe <june@causal.agency>
2 2
  *
3 3
  * This program is free software: you can redistribute it and/or modify
4 4
  * it under the terms of the GNU Affero General Public License as published by
@@ -34,20 +34,20 @@
34 34
 #undef COLOR_WHITE
35 35
 
36 36
 enum {
37
-    COLOR_BLACK,
38
-    COLOR_RED,
39
-    COLOR_GREEN,
40
-    COLOR_YELLOW,
41
-    COLOR_BLUE,
42
-    COLOR_MAGENTA,
43
-    COLOR_CYAN,
44
-    COLOR_WHITE,
45
-    COLOR_BRIGHT,
37
+	COLOR_BLACK,
38
+	COLOR_RED,
39
+	COLOR_GREEN,
40
+	COLOR_YELLOW,
41
+	COLOR_BLUE,
42
+	COLOR_MAGENTA,
43
+	COLOR_CYAN,
44
+	COLOR_WHITE,
45
+	COLOR_BRIGHT,
46 46
 };
47 47
 
48 48
 enum {
49
-    CELL_ROWS = 25,
50
-    CELL_COLS = 80,
49
+	CELL_ROWS = 25,
50
+	CELL_COLS = 80,
51 51
 };
52 52
 static const size_t CELLS_SIZE = sizeof(char[CELL_ROWS][CELL_COLS]);
53 53
 
@@ -55,21 +55,21 @@ static const uint8_t CELL_INIT_X = CELL_COLS / 2;
55 55
 static const uint8_t CELL_INIT_Y = CELL_ROWS / 2;
56 56
 
57 57
 struct ALIGNED(4096) Tile {
58
-    time_t createTime;
59
-    time_t modifyTime;
60
-    char ALIGNED(16) cells[CELL_ROWS][CELL_COLS];
61
-    uint8_t ALIGNED(16) colors[CELL_ROWS][CELL_COLS];
62
-    uint32_t modifyCount;
63
-    uint32_t accessCount;
64
-    time_t accessTime;
58
+	time_t createTime;
59
+	time_t modifyTime;
60
+	char ALIGNED(16) cells[CELL_ROWS][CELL_COLS];
61
+	uint8_t ALIGNED(16) colors[CELL_ROWS][CELL_COLS];
62
+	uint32_t modifyCount;
63
+	uint32_t accessCount;
64
+	time_t accessTime;
65 65
 };
66
-static_assert(4096 == sizeof(struct Tile), "struct File is page-sized");
66
+static_assert(4096 == sizeof(struct Tile), "struct Tile is page-sized");
67 67
 static_assert(16 == offsetof(struct Tile, cells), "stable cells offset");
68 68
 static_assert(2016 == offsetof(struct Tile, colors), "stable colors offset");
69 69
 
70 70
 enum {
71
-    TILE_ROWS = 512,
72
-    TILE_COLS = 512,
71
+	TILE_ROWS = 512,
72
+	TILE_COLS = 512,
73 73
 };
74 74
 static const size_t TILES_SIZE = sizeof(struct Tile[TILE_ROWS][TILE_COLS]);
75 75
 
@@ -77,61 +77,61 @@ static const uint32_t TILE_VOID_X = UINT32_MAX;
77 77
 static const uint32_t TILE_VOID_Y = UINT32_MAX;
78 78
 
79 79
 static const struct {
80
-    uint32_t tileX;
81
-    uint32_t tileY;
80
+	uint32_t tileX;
81
+	uint32_t tileY;
82 82
 } SPAWNS[] = {
83
-    { 0, 0 },
84
-    { TILE_COLS * 3 / 4, TILE_ROWS * 3 / 4 }, // NW
85
-    { TILE_COLS * 1 / 4, TILE_ROWS * 3 / 4 }, // NE
86
-    { TILE_COLS * 1 / 4, TILE_ROWS * 1 / 4 }, // SE
87
-    { TILE_COLS * 3 / 4, TILE_ROWS * 1 / 4 }, // SW
83
+	{ 0, 0 },
84
+	{ TILE_COLS * 3 / 4, TILE_ROWS * 3 / 4 }, // NW
85
+	{ TILE_COLS * 1 / 4, TILE_ROWS * 3 / 4 }, // NE
86
+	{ TILE_COLS * 1 / 4, TILE_ROWS * 1 / 4 }, // SE
87
+	{ TILE_COLS * 3 / 4, TILE_ROWS * 1 / 4 }, // SW
88 88
 };
89 89
 static const size_t SPAWNS_LEN = sizeof(SPAWNS) / sizeof(SPAWNS[0]);
90 90
 
91 91
 struct ServerMessage {
92
-    enum PACKED {
93
-        SERVER_TILE,
94
-        SERVER_MOVE,
95
-        SERVER_PUT,
96
-        SERVER_CURSOR,
97
-    } type;
98
-    union {
99
-        struct {
100
-            uint8_t cellX;
101
-            uint8_t cellY;
102
-        } move;
103
-        struct {
104
-            uint8_t cellX;
105
-            uint8_t cellY;
106
-            uint8_t color;
107
-            char cell;
108
-        } put;
109
-        struct {
110
-            uint8_t oldCellX;
111
-            uint8_t oldCellY;
112
-            uint8_t newCellX;
113
-            uint8_t newCellY;
114
-        } cursor;
115
-    };
92
+	enum PACKED {
93
+		SERVER_TILE,
94
+		SERVER_MOVE,
95
+		SERVER_PUT,
96
+		SERVER_CURSOR,
97
+	} type;
98
+	union {
99
+		struct {
100
+			uint8_t cellX;
101
+			uint8_t cellY;
102
+		} move;
103
+		struct {
104
+			uint8_t cellX;
105
+			uint8_t cellY;
106
+			uint8_t color;
107
+			char cell;
108
+		} put;
109
+		struct {
110
+			uint8_t oldCellX;
111
+			uint8_t oldCellY;
112
+			uint8_t newCellX;
113
+			uint8_t newCellY;
114
+		} cursor;
115
+	};
116 116
 };
117 117
 
118 118
 static const uint8_t CURSOR_NONE = UINT8_MAX;
119 119
 
120 120
 struct ClientMessage {
121
-    enum PACKED {
122
-        CLIENT_MOVE,
123
-        CLIENT_PUT,
124
-        CLIENT_SPAWN,
125
-    } type;
126
-    union {
127
-        struct {
128
-            int8_t dx;
129
-            int8_t dy;
130
-        } move;
131
-        struct {
132
-            uint8_t color;
133
-            char cell;
134
-        } put;
135
-        uint8_t spawn;
136
-    };
121
+	enum PACKED {
122
+		CLIENT_MOVE,
123
+		CLIENT_PUT,
124
+		CLIENT_SPAWN,
125
+	} type;
126
+	union {
127
+		struct {
128
+			int8_t dx;
129
+			int8_t dy;
130
+		} move;
131
+		struct {
132
+			uint8_t color;
133
+			char cell;
134
+		} put;
135
+		uint8_t spawn;
136
+	};
137 137
 };

Loading…
Cancel
Save