1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 #if 0 36 static char sccsid[] = "@(#)sync.c 8.1 (Berkeley) 5/31/93"; 37 #endif 38 static const char rcsid[] = 39 "$FreeBSD: src/games/sail/sync.c,v 1.9 1999/11/30 03:49:38 billf Exp $"; 40 #endif /* not lint */ 41 42 #include "externs.h" 43 #include <sys/file.h> 44 #include <sys/errno.h> 45 46 #define BUFSIZE 4096 47 48 static char sync_buf[BUFSIZE]; 49 static char *sync_bp = sync_buf; 50 static char sync_lock[25]; 51 static char sync_file[25]; 52 static long sync_seek; 53 static FILE *sync_fp; 54 #define SF "/tmp/#sailsink.%d" 55 #define LF "/tmp/#saillock.%d" 56 57 /*VARARGS3*/ 58 makesignal(from, fmt, ship, a, b, c) 59 struct ship *from; 60 char *fmt; 61 struct ship *ship; 62 { 63 char message[80]; 64 65 if (ship == 0) 66 (void) sprintf(message, fmt, a, b, c); 67 else 68 (void) sprintf(message, fmt, 69 ship->shipname, colours(ship), 70 sterncolour(ship), a, b, c); 71 Write(W_SIGNAL, from, 1, (long)message, 0, 0, 0); 72 } 73 74 #include <sys/types.h> 75 #include <sys/stat.h> 76 sync_exists(game) 77 int game; 78 { 79 char buf[sizeof sync_file]; 80 struct stat s; 81 time_t t; 82 83 (void) sprintf(buf, SF, game); 84 (void) time(&t); 85 if (stat(buf, &s) < 0) 86 return 0; 87 if (s.st_mtime < t - 60*60*2) { /* 2 hours */ 88 (void) unlink(buf); 89 (void) sprintf(buf, LF, game); 90 (void) unlink(buf); 91 return 0; 92 } else 93 return 1; 94 } 95 96 sync_open() 97 { 98 if (sync_fp != NULL) 99 (void) fclose(sync_fp); 100 (void) sprintf(sync_lock, LF, game); 101 (void) sprintf(sync_file, SF, game); 102 if (access(sync_file, 0) < 0) { 103 int omask = umask(issetuid ? 077 : 011); 104 sync_fp = fopen(sync_file, "w+"); 105 (void) umask(omask); 106 } else 107 sync_fp = fopen(sync_file, "r+"); 108 if (sync_fp == NULL) 109 return -1; 110 sync_seek = 0; 111 return 0; 112 } 113 114 sync_close(remove) 115 char remove; 116 { 117 if (sync_fp != 0) 118 (void) fclose(sync_fp); 119 if (remove) 120 (void) unlink(sync_file); 121 } 122 123 Write(type, ship, isstr, a, b, c, d) 124 int type; 125 struct ship *ship; 126 char isstr; 127 int a, b, c, d; 128 { 129 if (isstr) 130 (void) sprintf(sync_bp, "%d %d %d %s\n", 131 type, ship->file->index, isstr, (char *)a); 132 else 133 (void) sprintf(sync_bp, "%d %d %d %d %d %d %d\n", 134 type, ship->file->index, isstr, a, b, c, d); 135 while (*sync_bp++) 136 ; 137 sync_bp--; 138 if (sync_bp >= &sync_buf[sizeof sync_buf]) 139 abort(); 140 (void) sync_update(type, ship, a, b, c, d); 141 } 142 143 Sync() 144 { 145 sig_t sighup, sigint; 146 int n; 147 int type, shipnum, isstr, a, b, c, d; 148 char buf[80]; 149 char erred = 0; 150 extern errno; 151 152 sighup = signal(SIGHUP, SIG_IGN); 153 sigint = signal(SIGINT, SIG_IGN); 154 for (n = TIMEOUT; --n >= 0;) { 155 #ifdef LOCK_EX 156 if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0) 157 break; 158 if (errno != EWOULDBLOCK) 159 return -1; 160 #else 161 if (link(sync_file, sync_lock) >= 0) 162 break; 163 if (errno != EEXIST) 164 return -1; 165 #endif 166 sleep(1); 167 } 168 if (n <= 0) 169 return -1; 170 (void) fseek(sync_fp, sync_seek, 0); 171 for (;;) { 172 switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) { 173 case 3: 174 break; 175 case EOF: 176 goto out; 177 default: 178 goto bad; 179 } 180 if (shipnum < 0 || shipnum >= cc->vessels) 181 goto bad; 182 if (isstr != 0 && isstr != 1) 183 goto bad; 184 if (isstr) { 185 char *p; 186 for (p = buf;;) { 187 switch (*p++ = getc(sync_fp)) { 188 case '\n': 189 p--; 190 case EOF: 191 break; 192 default: 193 if (p >= buf + sizeof buf) 194 p--; 195 continue; 196 } 197 break; 198 } 199 *p = 0; 200 for (p = buf; *p == ' '; p++) 201 ; 202 a = (long)p; 203 b = c = d = 0; 204 } else 205 if (fscanf(sync_fp, "%d%d%d%d", &a, &b, &c, &d) != 4) 206 goto bad; 207 if (sync_update(type, SHIP(shipnum), a, b, c, d) < 0) 208 goto bad; 209 } 210 bad: 211 erred++; 212 out: 213 if (!erred && sync_bp != sync_buf) { 214 (void) fseek(sync_fp, 0L, 2); 215 (void) fwrite(sync_buf, sizeof *sync_buf, sync_bp - sync_buf, 216 sync_fp); 217 (void) fflush(sync_fp); 218 sync_bp = sync_buf; 219 } 220 sync_seek = ftell(sync_fp); 221 #ifdef LOCK_EX 222 (void) flock(fileno(sync_fp), LOCK_UN); 223 #else 224 (void) unlink(sync_lock); 225 #endif 226 (void) signal(SIGHUP, sighup); 227 (void) signal(SIGINT, sigint); 228 return erred ? -1 : 0; 229 } 230 231 sync_update(type, ship, a, b, c, d) 232 int type; 233 struct ship *ship; 234 long a, b, c, d; 235 { 236 switch (type) { 237 case W_DBP: { 238 struct BP *p = &ship->file->DBP[a]; 239 p->turnsent = b; 240 p->toship = SHIP(c); 241 p->mensent = d; 242 break; 243 } 244 case W_OBP: { 245 struct BP *p = &ship->file->OBP[a]; 246 p->turnsent = b; 247 p->toship = SHIP(c); 248 p->mensent = d; 249 break; 250 } 251 case W_FOUL: { 252 struct snag *p = &ship->file->foul[a]; 253 if (SHIP(a)->file->dir == 0) 254 break; 255 if (p->sn_count++ == 0) 256 p->sn_turn = turn; 257 ship->file->nfoul++; 258 break; 259 } 260 case W_GRAP: { 261 struct snag *p = &ship->file->grap[a]; 262 if (SHIP(a)->file->dir == 0) 263 break; 264 if (p->sn_count++ == 0) 265 p->sn_turn = turn; 266 ship->file->ngrap++; 267 break; 268 } 269 case W_UNFOUL: { 270 struct snag *p = &ship->file->foul[a]; 271 if (p->sn_count > 0) { 272 if (b) { 273 ship->file->nfoul -= p->sn_count; 274 p->sn_count = 0; 275 } else { 276 ship->file->nfoul--; 277 p->sn_count--; 278 } 279 } 280 break; 281 } 282 case W_UNGRAP: { 283 struct snag *p = &ship->file->grap[a]; 284 if (p->sn_count > 0) { 285 if (b) { 286 ship->file->ngrap -= p->sn_count; 287 p->sn_count = 0; 288 } else { 289 ship->file->ngrap--; 290 p->sn_count--; 291 } 292 } 293 break; 294 } 295 case W_SIGNAL: 296 if (mode == MODE_PLAYER) { 297 if (nobells) 298 Signal("%s (%c%c): %s", ship, a); 299 else 300 Signal("\7%s (%c%c): %s", ship, a); 301 } 302 break; 303 case W_CREW: { 304 struct shipspecs *s = ship->specs; 305 s->crew1 = a; 306 s->crew2 = b; 307 s->crew3 = c; 308 break; 309 } 310 case W_CAPTAIN: 311 (void) strncpy(ship->file->captain, (char *)a, 312 sizeof ship->file->captain - 1); 313 ship->file->captain[sizeof ship->file->captain - 1] = 0; 314 break; 315 case W_CAPTURED: 316 if (a < 0) 317 ship->file->captured = 0; 318 else 319 ship->file->captured = SHIP(a); 320 break; 321 case W_CLASS: 322 ship->specs->class = a; 323 break; 324 case W_DRIFT: 325 ship->file->drift = a; 326 break; 327 case W_EXPLODE: 328 if ((ship->file->explode = a) == 2) 329 ship->file->dir = 0; 330 break; 331 case W_FS: 332 ship->file->FS = a; 333 break; 334 case W_GUNL: { 335 struct shipspecs *s = ship->specs; 336 s->gunL = a; 337 s->carL = b; 338 break; 339 } 340 case W_GUNR: { 341 struct shipspecs *s = ship->specs; 342 s->gunR = a; 343 s->carR = b; 344 break; 345 } 346 case W_HULL: 347 ship->specs->hull = a; 348 break; 349 case W_MOVE: 350 (void) strncpy(ship->file->movebuf, (char *)a, 351 sizeof ship->file->movebuf - 1); 352 ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0; 353 break; 354 case W_PCREW: 355 ship->file->pcrew = a; 356 break; 357 case W_POINTS: 358 ship->file->points = a; 359 break; 360 case W_QUAL: 361 ship->specs->qual = a; 362 break; 363 case W_RIGG: { 364 struct shipspecs *s = ship->specs; 365 s->rig1 = a; 366 s->rig2 = b; 367 s->rig3 = c; 368 s->rig4 = d; 369 break; 370 } 371 case W_RIG1: 372 ship->specs->rig1 = a; 373 break; 374 case W_RIG2: 375 ship->specs->rig2 = a; 376 break; 377 case W_RIG3: 378 ship->specs->rig3 = a; 379 break; 380 case W_RIG4: 381 ship->specs->rig4 = a; 382 break; 383 case W_COL: 384 ship->file->col = a; 385 break; 386 case W_DIR: 387 ship->file->dir = a; 388 break; 389 case W_ROW: 390 ship->file->row = a; 391 break; 392 case W_SINK: 393 if ((ship->file->sink = a) == 2) 394 ship->file->dir = 0; 395 break; 396 case W_STRUCK: 397 ship->file->struck = a; 398 break; 399 case W_TA: 400 ship->specs->ta = a; 401 break; 402 case W_ALIVE: 403 alive = 1; 404 break; 405 case W_TURN: 406 turn = a; 407 break; 408 case W_WIND: 409 winddir = a; 410 windspeed = b; 411 break; 412 case W_BEGIN: 413 (void) strcpy(ship->file->captain, "begin"); 414 people++; 415 break; 416 case W_END: 417 *ship->file->captain = 0; 418 ship->file->points = 0; 419 people--; 420 break; 421 case W_DDEAD: 422 hasdriver = 0; 423 break; 424 default: 425 fprintf(stderr, "sync_update: unknown type %d\r\n", type); 426 return -1; 427 } 428 return 0; 429 } 430