Home | History | Annotate | Line # | Download | only in sail
sync.c revision 1.30
      1 /*	$NetBSD: sync.c,v 1.30 2009/03/14 22:52:53 dholland Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1983, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 #if 0
     35 static char sccsid[] = "@(#)sync.c	8.2 (Berkeley) 4/28/95";
     36 #else
     37 __RCSID("$NetBSD: sync.c,v 1.30 2009/03/14 22:52:53 dholland Exp $");
     38 #endif
     39 #endif /* not lint */
     40 
     41 #include <sys/stat.h>
     42 
     43 #include <fcntl.h>
     44 #include <errno.h>
     45 #include <signal.h>
     46 #include <stdarg.h>
     47 #include <stdio.h>
     48 #include <stdlib.h>
     49 #include <string.h>
     50 #include <time.h>
     51 #include <unistd.h>
     52 #include "extern.h"
     53 #include "pathnames.h"
     54 
     55 #define BUFSIZE 4096
     56 
     57 /* Message types */
     58 #define W_CAPTAIN	1
     59 #define W_CAPTURED	2
     60 #define W_CLASS		3
     61 #define W_CREW		4
     62 #define W_DBP		5
     63 #define W_DRIFT		6
     64 #define W_EXPLODE	7
     65 #define W_FILE		8
     66 #define W_FOUL		9
     67 #define W_GUNL		10
     68 #define W_GUNR		11
     69 #define W_HULL		12
     70 #define W_MOVE		13
     71 #define W_OBP		14
     72 #define W_PCREW		15
     73 #define W_UNFOUL	16
     74 #define W_POINTS	17
     75 #define W_QUAL		18
     76 #define W_UNGRAP	19
     77 #define W_RIGG		20
     78 #define W_COL		21
     79 #define W_DIR		22
     80 #define W_ROW		23
     81 #define W_SIGNAL	24
     82 #define W_SINK		25
     83 #define W_STRUCK	26
     84 #define W_TA		27
     85 #define W_ALIVE		28
     86 #define W_TURN		29
     87 #define W_WIND		30
     88 #define W_FS		31
     89 #define W_GRAP		32
     90 #define W_RIG1		33
     91 #define W_RIG2		34
     92 #define W_RIG3		35
     93 #define W_RIG4		36
     94 #define W_BEGIN		37
     95 #define W_END		38
     96 #define W_DDEAD		39
     97 
     98 
     99 static void recv_captain(struct ship *ship, const char *astr);
    100 static void recv_captured(struct ship *ship, long a);
    101 static void recv_class(struct ship *ship, long a);
    102 static void recv_crew(struct ship *ship, long a, long b, long c);
    103 static void recv_dbp(struct ship *ship, long a, long b, long c, long d);
    104 static void recv_drift(struct ship *ship, long a);
    105 static void recv_explode(struct ship *ship, long a);
    106 static void recv_file(void);
    107 static void recv_foul(struct ship *ship, long a);
    108 static void recv_gunl(struct ship *ship, long a, long b);
    109 static void recv_gunr(struct ship *ship, long a, long b);
    110 static void recv_hull(struct ship *ship, long a);
    111 static void recv_move(struct ship *ship, const char *astr);
    112 static void recv_obp(struct ship *ship, long a, long b, long c, long d);
    113 static void recv_pcrew(struct ship *ship, long a);
    114 static void recv_unfoul(struct ship *ship, long a, long b);
    115 static void recv_points(struct ship *ship, long a);
    116 static void recv_qual(struct ship *ship, long a);
    117 static void recv_ungrap(struct ship *ship, long a, long b);
    118 static void recv_rigg(struct ship *ship, long a, long b, long c, long d);
    119 static void recv_col(struct ship *ship, long a);
    120 static void recv_dir(struct ship *ship, long a);
    121 static void recv_row(struct ship *ship, long a);
    122 static void recv_signal(struct ship *ship, const char *astr);
    123 static void recv_sink(struct ship *ship, long a);
    124 static void recv_struck(struct ship *ship, long a);
    125 static void recv_ta(struct ship *ship, long a);
    126 static void recv_alive(void);
    127 static void recv_turn(long a);
    128 static void recv_wind(long a, long b);
    129 static void recv_fs(struct ship *ship, long a);
    130 static void recv_grap(struct ship *ship, long a);
    131 static void recv_rig1(struct ship *ship, long a);
    132 static void recv_rig2(struct ship *ship, long a);
    133 static void recv_rig3(struct ship *ship, long a);
    134 static void recv_rig4(struct ship *ship, long a);
    135 static void recv_begin(struct ship *ship);
    136 static void recv_end(struct ship *ship);
    137 static void recv_ddead(void);
    138 
    139 static void Write(int, struct ship *, long, long, long, long);
    140 static void Writestr(int, struct ship *, const char *);
    141 
    142 static int sync_update(int, struct ship *, const char *,
    143 		       long, long, long, long);
    144 
    145 static const char SF[] = _PATH_SYNC;
    146 static const char LF[] = _PATH_LOCK;
    147 static char sync_buf[BUFSIZE];
    148 static char *sync_bp = sync_buf;
    149 static char sync_lock[sizeof SF];
    150 static char sync_file[sizeof LF];
    151 static long sync_seek;
    152 static FILE *sync_fp;
    153 
    154 void
    155 fmtship(char *buf, size_t len, const char *fmt, struct ship *ship)
    156 {
    157 	while (*fmt) {
    158 		if (len-- == 0) {
    159 			*buf = '\0';
    160 			return;
    161 		}
    162 		if (*fmt == '$' && fmt[1] == '$') {
    163 			size_t l = snprintf(buf, len, "%s (%c%c)",
    164 			    ship->shipname, colours(ship), sterncolour(ship));
    165 			buf += l;
    166 			len -= l - 1;
    167 			fmt += 2;
    168 		}
    169 		else
    170 			*buf++ = *fmt++;
    171 	}
    172 
    173 	if (len > 0)
    174 		*buf = '\0';
    175 }
    176 
    177 
    178 /*VARARGS3*/
    179 void
    180 makesignal(struct ship *from, const char *fmt, struct ship *ship, ...)
    181 {
    182 	char message[BUFSIZ];
    183 	char format[BUFSIZ];
    184 	va_list ap;
    185 
    186 	va_start(ap, ship);
    187 	fmtship(format, sizeof(format), fmt, ship);
    188 	vsnprintf(message, sizeof(message), format, ap);
    189 	va_end(ap);
    190 	send_signal(from, message);
    191 }
    192 
    193 /*VARARGS2*/
    194 void
    195 makemsg(struct ship *from, const char *fmt, ...)
    196 {
    197 	char message[BUFSIZ];
    198 	va_list ap;
    199 
    200 	va_start(ap, fmt);
    201 	vsnprintf(message, sizeof(message), fmt, ap);
    202 	va_end(ap);
    203 	send_signal(from, message);
    204 }
    205 
    206 int
    207 sync_exists(int gamenum)
    208 {
    209 	char buf[sizeof sync_file];
    210 	struct stat s;
    211 	time_t t;
    212 
    213 	snprintf(buf, sizeof(buf), SF, gamenum);
    214 	time(&t);
    215 	setegid(egid);
    216 	if (stat(buf, &s) < 0) {
    217 		setegid(gid);
    218 		return 0;
    219 	}
    220 	if (s.st_mtime < t - 60*60*2) {		/* 2 hours */
    221 		unlink(buf);
    222 		snprintf(buf, sizeof(buf), LF, gamenum);
    223 		unlink(buf);
    224 		setegid(gid);
    225 		return 0;
    226 	} else {
    227 		setegid(gid);
    228 		return 1;
    229 	}
    230 }
    231 
    232 int
    233 sync_open(void)
    234 {
    235 	struct stat tmp;
    236 	if (sync_fp != NULL)
    237 		fclose(sync_fp);
    238 	snprintf(sync_lock, sizeof(sync_lock), LF, game);
    239 	snprintf(sync_file, sizeof(sync_file), SF, game);
    240 	setegid(egid);
    241 	if (stat(sync_file, &tmp) < 0) {
    242 		mode_t omask = umask(002);
    243 		sync_fp = fopen(sync_file, "w+");
    244 		umask(omask);
    245 	} else
    246 		sync_fp = fopen(sync_file, "r+");
    247 	setegid(gid);
    248 	if (sync_fp == NULL)
    249 		return -1;
    250 	sync_seek = 0;
    251 	return 0;
    252 }
    253 
    254 void
    255 sync_close(int doremove)
    256 {
    257 	if (sync_fp != 0)
    258 		fclose(sync_fp);
    259 	if (doremove) {
    260 		setegid(egid);
    261 		unlink(sync_file);
    262 		setegid(gid);
    263 	}
    264 }
    265 
    266 static void
    267 Write(int type, struct ship *ship, long a, long b, long c, long d)
    268 {
    269 	size_t max = sizeof(sync_buf) - (sync_bp - sync_buf);
    270 	int shipindex = (ship == NULL) ? 0 : ship->file->index;
    271 
    272 	snprintf(sync_bp, max, "%d %d 0 %ld %ld %ld %ld\n",
    273 		       type, shipindex, a, b, c, d);
    274 	while (*sync_bp++)
    275 		;
    276 	sync_bp--;
    277 	if (sync_bp >= &sync_buf[sizeof sync_buf])
    278 		abort();
    279 	sync_update(type, ship, NULL, a, b, c, d);
    280 }
    281 
    282 static void
    283 Writestr(int type, struct ship *ship, const char *a)
    284 {
    285 	size_t max = sizeof(sync_buf) - (sync_bp - sync_buf);
    286 	int shipindex = (ship == NULL) ? 0 : ship->file->index;
    287 
    288 	snprintf(sync_bp, max, "%d %d 1 %s\n", type, shipindex, a);
    289 	while (*sync_bp++)
    290 		;
    291 	sync_bp--;
    292 	if (sync_bp >= &sync_buf[sizeof sync_buf])
    293 		abort();
    294 	sync_update(type, ship, a, 0, 0, 0, 0);
    295 }
    296 
    297 int
    298 Sync(void)
    299 {
    300 	sig_t sighup, sigint;
    301 	int n;
    302 	int type, shipnum, isstr;
    303 	char *astr;
    304 	long a, b, c, d;
    305 	char buf[80];
    306 	char erred = 0;
    307 
    308 	sighup = signal(SIGHUP, SIG_IGN);
    309 	sigint = signal(SIGINT, SIG_IGN);
    310 	for (n = TIMEOUT; --n >= 0;) {
    311 #ifdef LOCK_EX
    312 		if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0)
    313 			break;
    314 		if (errno != EWOULDBLOCK)
    315 			return -1;
    316 #else
    317 		setegid(egid);
    318 		if (link(sync_file, sync_lock) >= 0) {
    319 			setegid(gid);
    320 			break;
    321 		}
    322 		setegid(gid);
    323 		if (errno != EEXIST)
    324 			return -1;
    325 #endif
    326 		sleep(1);
    327 	}
    328 	if (n <= 0)
    329 		return -1;
    330 	fseek(sync_fp, sync_seek, SEEK_SET);
    331 	for (;;) {
    332 		switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) {
    333 		case 3:
    334 			break;
    335 		case EOF:
    336 			goto out;
    337 		default:
    338 			goto bad;
    339 		}
    340 		if (shipnum < 0 || shipnum >= cc->vessels)
    341 			goto bad;
    342 		if (isstr != 0 && isstr != 1)
    343 			goto bad;
    344 		if (isstr) {
    345 			int ch;
    346 			char *p;
    347 
    348 			for (p = buf;;) {
    349 				ch = getc(sync_fp);
    350 				*p++ = ch;
    351 				switch (ch) {
    352 				case '\n':
    353 					p--;
    354 				case EOF:
    355 					break;
    356 				default:
    357 					if (p >= buf + sizeof buf)
    358 						p--;
    359 					continue;
    360 				}
    361 				break;
    362 			}
    363 			*p = 0;
    364 			for (p = buf; *p == ' '; p++)
    365 				;
    366 			astr = p;
    367 			a = b = c = d = 0;
    368 		} else {
    369 			if (fscanf(sync_fp, "%ld%ld%ld%ld", &a, &b, &c, &d)
    370 			    != 4)
    371 				goto bad;
    372 			astr = NULL;
    373 		}
    374 		if (sync_update(type, SHIP(shipnum), astr, a, b, c, d) < 0)
    375 			goto bad;
    376 	}
    377 bad:
    378 	erred++;
    379 out:
    380 	if (!erred && sync_bp != sync_buf) {
    381 		fseek(sync_fp, 0L, SEEK_END);
    382 		fwrite(sync_buf, sizeof *sync_buf, sync_bp - sync_buf,
    383 			sync_fp);
    384 		fflush(sync_fp);
    385 		sync_bp = sync_buf;
    386 	}
    387 	sync_seek = ftell(sync_fp);
    388 #ifdef LOCK_EX
    389 	flock(fileno(sync_fp), LOCK_UN);
    390 #else
    391 	setegid(egid);
    392 	unlink(sync_lock);
    393 	setegid(gid);
    394 #endif
    395 	signal(SIGHUP, sighup);
    396 	signal(SIGINT, sigint);
    397 	return erred ? -1 : 0;
    398 }
    399 
    400 static int
    401 sync_update(int type, struct ship *ship, const char *astr,
    402 	    long a, long b, long c, long d)
    403 {
    404 	switch (type) {
    405 	case W_CAPTAIN:  recv_captain(ship, astr);    break;
    406 	case W_CAPTURED: recv_captured(ship, a);      break;
    407 	case W_CLASS:    recv_class(ship, a);         break;
    408 	case W_CREW:     recv_crew(ship, a, b, c);    break;
    409 	case W_DBP:      recv_dbp(ship, a, b, c, d);  break;
    410 	case W_DRIFT:    recv_drift(ship, a);         break;
    411 	case W_EXPLODE:  recv_explode(ship, a);       break;
    412 	case W_FILE:     recv_file();                 break;
    413 	case W_FOUL:     recv_foul(ship, a);          break;
    414 	case W_GUNL:     recv_gunl(ship, a, b);       break;
    415 	case W_GUNR:     recv_gunr(ship, a, b);       break;
    416 	case W_HULL:     recv_hull(ship, a);          break;
    417 	case W_MOVE:     recv_move(ship, astr);       break;
    418 	case W_OBP:      recv_obp(ship, a, b, c, d);  break;
    419 	case W_PCREW:    recv_pcrew(ship, a);         break;
    420 	case W_UNFOUL:   recv_unfoul(ship, a, b);     break;
    421 	case W_POINTS:   recv_points(ship, a);        break;
    422 	case W_QUAL:     recv_qual(ship, a);          break;
    423 	case W_UNGRAP:   recv_ungrap(ship, a, b);     break;
    424 	case W_RIGG:     recv_rigg(ship, a, b, c, d); break;
    425 	case W_COL:      recv_col(ship, a);           break;
    426 	case W_DIR:      recv_dir(ship, a);           break;
    427 	case W_ROW:      recv_row(ship, a);           break;
    428 	case W_SIGNAL:   recv_signal(ship, astr);     break;
    429 	case W_SINK:     recv_sink(ship, a);          break;
    430 	case W_STRUCK:   recv_struck(ship, a);        break;
    431 	case W_TA:       recv_ta(ship, a);            break;
    432 	case W_ALIVE:    recv_alive();                break;
    433 	case W_TURN:     recv_turn(a);                break;
    434 	case W_WIND:     recv_wind(a, b);             break;
    435 	case W_FS:       recv_fs(ship, a);            break;
    436 	case W_GRAP:     recv_grap(ship, a);          break;
    437 	case W_RIG1:     recv_rig1(ship, a);          break;
    438 	case W_RIG2:     recv_rig2(ship, a);          break;
    439 	case W_RIG3:     recv_rig3(ship, a);          break;
    440 	case W_RIG4:     recv_rig4(ship, a);          break;
    441 	case W_BEGIN:    recv_begin(ship);            break;
    442 	case W_END:      recv_end(ship);              break;
    443 	case W_DDEAD:    recv_ddead();                break;
    444 	default:
    445 		fprintf(stderr, "sync_update: unknown type %d\r\n", type);
    446 		return -1;
    447 	}
    448 	return 0;
    449 }
    450 
    451 /*
    452  * Messages to send
    453  */
    454 
    455 void
    456 send_captain(struct ship *ship, const char *astr)
    457 {
    458 	Writestr(W_CAPTAIN, ship, astr);
    459 }
    460 
    461 void
    462 send_captured(struct ship *ship, long a)
    463 {
    464 	Write(W_CAPTURED, ship, a, 0, 0, 0);
    465 }
    466 
    467 void
    468 send_class(struct ship *ship, long a)
    469 {
    470 	Write(W_CLASS, ship, a, 0, 0, 0);
    471 }
    472 
    473 void
    474 send_crew(struct ship *ship, long a, long b, long c)
    475 {
    476 	Write(W_CREW, ship, a, b, c, 0);
    477 }
    478 
    479 void
    480 send_dbp(struct ship *ship, long a, long b, long c, long d)
    481 {
    482 	Write(W_DBP, ship, a, b, c, d);
    483 }
    484 
    485 void
    486 send_drift(struct ship *ship, long a)
    487 {
    488 	Write(W_DRIFT, ship, a, 0, 0, 0);
    489 }
    490 
    491 void
    492 send_explode(struct ship *ship, long a)
    493 {
    494 	Write(W_EXPLODE, ship, a, 0, 0, 0);
    495 }
    496 
    497 void
    498 send_file(void)
    499 {
    500 	Write(W_FILE, NULL, 0, 0, 0, 0);
    501 }
    502 
    503 void
    504 send_foul(struct ship *ship, long a)
    505 {
    506 	Write(W_FOUL, ship, a, 0, 0, 0);
    507 }
    508 
    509 void
    510 send_gunl(struct ship *ship, long a, long b)
    511 {
    512 	Write(W_GUNL, ship, a, b, 0, 0);
    513 }
    514 
    515 void
    516 send_gunr(struct ship *ship, long a, long b)
    517 {
    518 	Write(W_GUNR, ship, a, b, 0, 0);
    519 }
    520 
    521 void
    522 send_hull(struct ship *ship, long a)
    523 {
    524 	Write(W_HULL, ship, a, 0, 0, 0);
    525 }
    526 
    527 void
    528 send_move(struct ship *ship, const char *astr)
    529 {
    530 	Writestr(W_MOVE, ship, astr);
    531 }
    532 
    533 void
    534 send_obp(struct ship *ship, long a, long b, long c, long d)
    535 {
    536 	Write(W_OBP, ship, a, b, c, d);
    537 }
    538 
    539 void
    540 send_pcrew(struct ship *ship, long a)
    541 {
    542 	Write(W_PCREW, ship, a, 0, 0, 0);
    543 }
    544 
    545 void
    546 send_unfoul(struct ship *ship, long a, long b)
    547 {
    548 	Write(W_UNFOUL, ship, a, b, 0, 0);
    549 }
    550 
    551 void
    552 send_points(struct ship *ship, long a)
    553 {
    554 	Write(W_POINTS, ship, a, 0, 0, 0);
    555 }
    556 
    557 void
    558 send_qual(struct ship *ship, long a)
    559 {
    560 	Write(W_QUAL, ship, a, 0, 0, 0);
    561 }
    562 
    563 void
    564 send_ungrap(struct ship *ship, long a, long b)
    565 {
    566 	Write(W_UNGRAP, ship, a, b, 0, 0);
    567 }
    568 
    569 void
    570 send_rigg(struct ship *ship, long a, long b, long c, long d)
    571 {
    572 	Write(W_RIGG, ship, a, b, c, d);
    573 }
    574 
    575 void
    576 send_col(struct ship *ship, long a)
    577 {
    578 	Write(W_COL, ship, a, 0, 0, 0);
    579 }
    580 
    581 void
    582 send_dir(struct ship *ship, long a)
    583 {
    584 	Write(W_DIR, ship, a, 0, 0, 0);
    585 }
    586 
    587 void
    588 send_row(struct ship *ship, long a)
    589 {
    590 	Write(W_ROW, ship, a, 0, 0, 0);
    591 }
    592 
    593 void
    594 send_signal(struct ship *ship, const char *astr)
    595 {
    596 	Writestr(W_SIGNAL, ship, astr);
    597 }
    598 
    599 void
    600 send_sink(struct ship *ship, long a)
    601 {
    602 	Write(W_SINK, ship, a, 0, 0, 0);
    603 }
    604 
    605 void
    606 send_struck(struct ship *ship, long a)
    607 {
    608 	Write(W_STRUCK, ship, a, 0, 0, 0);
    609 }
    610 
    611 void
    612 send_ta(struct ship *ship, long a)
    613 {
    614 	Write(W_TA, ship, a, 0, 0, 0);
    615 }
    616 
    617 void
    618 send_alive(void)
    619 {
    620 	Write(W_ALIVE, NULL, 0, 0, 0, 0);
    621 }
    622 
    623 void
    624 send_turn(long a)
    625 {
    626 	Write(W_TURN, NULL, a, 0, 0, 0);
    627 }
    628 
    629 void
    630 send_wind(long a, long b)
    631 {
    632 	Write(W_WIND, NULL, a, b, 0, 0);
    633 }
    634 
    635 void
    636 send_fs(struct ship *ship, long a)
    637 {
    638 	Write(W_FS, ship, a, 0, 0, 0);
    639 }
    640 
    641 void
    642 send_grap(struct ship *ship, long a)
    643 {
    644 	Write(W_GRAP, ship, a, 0, 0, 0);
    645 }
    646 
    647 void
    648 send_rig1(struct ship *ship, long a)
    649 {
    650 	Write(W_RIG1, ship, a, 0, 0, 0);
    651 }
    652 
    653 void
    654 send_rig2(struct ship *ship, long a)
    655 {
    656 	Write(W_RIG2, ship, a, 0, 0, 0);
    657 }
    658 
    659 void
    660 send_rig3(struct ship *ship, long a)
    661 {
    662 	Write(W_RIG3, ship, a, 0, 0, 0);
    663 }
    664 
    665 void
    666 send_rig4(struct ship *ship, long a)
    667 {
    668 	Write(W_RIG4, ship, a, 0, 0, 0);
    669 }
    670 
    671 void
    672 send_begin(struct ship *ship)
    673 {
    674 	Write(W_BEGIN, ship, 0, 0, 0, 0);
    675 }
    676 
    677 void
    678 send_end(struct ship *ship)
    679 {
    680 	Write(W_END, ship, 0, 0, 0, 0);
    681 }
    682 
    683 void
    684 send_ddead(void)
    685 {
    686 	Write(W_DDEAD, NULL, 0, 0, 0, 0);
    687 }
    688 
    689 
    690 /*
    691  * Actions upon message receipt
    692  */
    693 
    694 static void
    695 recv_captain(struct ship *ship, const char *astr)
    696 {
    697 	strlcpy(ship->file->captain, astr, sizeof ship->file->captain);
    698 }
    699 
    700 static void
    701 recv_captured(struct ship *ship, long a)
    702 {
    703 	if (a < 0)
    704 		ship->file->captured = 0;
    705 	else
    706 		ship->file->captured = SHIP(a);
    707 }
    708 
    709 static void
    710 recv_class(struct ship *ship, long a)
    711 {
    712 	ship->specs->class = a;
    713 }
    714 
    715 static void
    716 recv_crew(struct ship *ship, long a, long b, long c)
    717 {
    718 	struct shipspecs *s = ship->specs;
    719 
    720 	s->crew1 = a;
    721 	s->crew2 = b;
    722 	s->crew3 = c;
    723 }
    724 
    725 static void
    726 recv_dbp(struct ship *ship, long a, long b, long c, long d)
    727 {
    728 	struct BP *p = &ship->file->DBP[a];
    729 
    730 	p->turnsent = b;
    731 	p->toship = SHIP(c);
    732 	p->mensent = d;
    733 }
    734 
    735 static void
    736 recv_drift(struct ship *ship, long a)
    737 {
    738 	ship->file->drift = a;
    739 }
    740 
    741 static void
    742 recv_explode(struct ship *ship, long a)
    743 {
    744 	if ((ship->file->explode = a) == 2)
    745 		ship->file->dir = 0;
    746 }
    747 
    748 // XXX why does this exist?
    749 static void
    750 recv_file(void)
    751 {
    752 }
    753 
    754 static void
    755 recv_foul(struct ship *ship, long a)
    756 {
    757 	struct snag *p = &ship->file->foul[a];
    758 
    759 	if (SHIP(a)->file->dir == 0)
    760 		return;
    761 	if (p->sn_count++ == 0)
    762 		p->sn_turn = turn;
    763 	ship->file->nfoul++;
    764 }
    765 
    766 static void
    767 recv_gunl(struct ship *ship, long a, long b)
    768 {
    769 	struct shipspecs *s = ship->specs;
    770 
    771 	s->gunL = a;
    772 	s->carL = b;
    773 }
    774 
    775 static void
    776 recv_gunr(struct ship *ship, long a, long b)
    777 {
    778 	struct shipspecs *s = ship->specs;
    779 
    780 	s->gunR = a;
    781 	s->carR = b;
    782 }
    783 
    784 static void
    785 recv_hull(struct ship *ship, long a)
    786 {
    787 	ship->specs->hull = a;
    788 }
    789 
    790 static void
    791 recv_move(struct ship *ship, const char *astr)
    792 {
    793 	strlcpy(ship->file->movebuf, astr, sizeof ship->file->movebuf);
    794 }
    795 
    796 static void
    797 recv_obp(struct ship *ship, long a, long b, long c, long d)
    798 {
    799 	struct BP *p = &ship->file->OBP[a];
    800 
    801 	p->turnsent = b;
    802 	p->toship = SHIP(c);
    803 	p->mensent = d;
    804 }
    805 
    806 static void
    807 recv_pcrew(struct ship *ship, long a)
    808 {
    809 	ship->file->pcrew = a;
    810 }
    811 
    812 static void
    813 recv_unfoul(struct ship *ship, long a, long b)
    814 {
    815 	struct snag *p = &ship->file->foul[a];
    816 
    817 	if (p->sn_count > 0) {
    818 		if (b) {
    819 			ship->file->nfoul -= p->sn_count;
    820 			p->sn_count = 0;
    821 		} else {
    822 			ship->file->nfoul--;
    823 			p->sn_count--;
    824 		}
    825 	}
    826 }
    827 
    828 static void
    829 recv_points(struct ship *ship, long a)
    830 {
    831 	ship->file->points = a;
    832 }
    833 
    834 static void
    835 recv_qual(struct ship *ship, long a)
    836 {
    837 	ship->specs->qual = a;
    838 }
    839 
    840 static void
    841 recv_ungrap(struct ship *ship, long a, long b)
    842 {
    843 	struct snag *p = &ship->file->grap[a];
    844 
    845 	if (p->sn_count > 0) {
    846 		if (b) {
    847 			ship->file->ngrap -= p->sn_count;
    848 			p->sn_count = 0;
    849 		} else {
    850 			ship->file->ngrap--;
    851 			p->sn_count--;
    852 		}
    853 	}
    854 }
    855 
    856 static void
    857 recv_rigg(struct ship *ship, long a, long b, long c, long d)
    858 {
    859 	struct shipspecs *s = ship->specs;
    860 
    861 	s->rig1 = a;
    862 	s->rig2 = b;
    863 	s->rig3 = c;
    864 	s->rig4 = d;
    865 }
    866 
    867 static void
    868 recv_col(struct ship *ship, long a)
    869 {
    870 	ship->file->col = a;
    871 }
    872 
    873 static void
    874 recv_dir(struct ship *ship, long a)
    875 {
    876 	ship->file->dir = a;
    877 }
    878 
    879 static void
    880 recv_row(struct ship *ship, long a)
    881 {
    882 	ship->file->row = a;
    883 }
    884 
    885 static void
    886 recv_signal(struct ship *ship, const char *astr)
    887 {
    888 	if (mode == MODE_PLAYER) {
    889 		if (nobells)
    890 			Signal("$$: %s", ship, astr);
    891 		else
    892 			Signal("\a$$: %s", ship, astr);
    893 	}
    894 }
    895 
    896 static void
    897 recv_sink(struct ship *ship, long a)
    898 {
    899 	if ((ship->file->sink = a) == 2)
    900 		ship->file->dir = 0;
    901 }
    902 
    903 static void
    904 recv_struck(struct ship *ship, long a)
    905 {
    906 	ship->file->struck = a;
    907 }
    908 
    909 static void
    910 recv_ta(struct ship *ship, long a)
    911 {
    912 	ship->specs->ta = a;
    913 }
    914 
    915 static void
    916 recv_alive(void)
    917 {
    918 	alive = 1;
    919 }
    920 
    921 static void
    922 recv_turn(long a)
    923 {
    924 	turn = a;
    925 }
    926 
    927 static void
    928 recv_wind(long a, long b)
    929 {
    930 	winddir = a;
    931 	windspeed = b;
    932 }
    933 
    934 static void
    935 recv_fs(struct ship *ship, long a)
    936 {
    937 	ship->file->FS = a;
    938 }
    939 
    940 static void
    941 recv_grap(struct ship *ship, long a)
    942 {
    943 	struct snag *p = &ship->file->grap[a];
    944 
    945 	if (SHIP(a)->file->dir == 0)
    946 		return;
    947 	if (p->sn_count++ == 0)
    948 		p->sn_turn = turn;
    949 	ship->file->ngrap++;
    950 }
    951 
    952 static void
    953 recv_rig1(struct ship *ship, long a)
    954 {
    955 	ship->specs->rig1 = a;
    956 }
    957 
    958 static void
    959 recv_rig2(struct ship *ship, long a)
    960 {
    961 	ship->specs->rig2 = a;
    962 }
    963 
    964 static void
    965 recv_rig3(struct ship *ship, long a)
    966 {
    967 	ship->specs->rig3 = a;
    968 }
    969 
    970 static void
    971 recv_rig4(struct ship *ship, long a)
    972 {
    973 	ship->specs->rig4 = a;
    974 }
    975 
    976 static void
    977 recv_begin(struct ship *ship)
    978 {
    979 	strcpy(ship->file->captain, "begin");
    980 	people++;
    981 }
    982 
    983 static void
    984 recv_end(struct ship *ship)
    985 {
    986 	*ship->file->captain = 0;
    987 	ship->file->points = 0;
    988 	people--;
    989 }
    990 
    991 static void
    992 recv_ddead(void)
    993 {
    994 	hasdriver = 0;
    995 }
    996