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