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