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