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