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 * @(#)sync.c 8.1 (Berkeley) 5/31/93 34 * $FreeBSD: src/games/sail/sync.c,v 1.9 1999/11/30 03:49:38 billf Exp $ 35 * $DragonFly: src/games/sail/sync.c,v 1.2 2003/06/17 04:25:25 dillon Exp $ 36 */ 37 38 #include "externs.h" 39 #include <sys/file.h> 40 #include <sys/errno.h> 41 42 #define BUFSIZE 4096 43 44 static char sync_buf[BUFSIZE]; 45 static char *sync_bp = sync_buf; 46 static char sync_lock[25]; 47 static char sync_file[25]; 48 static long sync_seek; 49 static FILE *sync_fp; 50 #define SF "/tmp/#sailsink.%d" 51 #define LF "/tmp/#saillock.%d" 52 53 /*VARARGS3*/ 54 makesignal(from, fmt, ship, a, b, c) 55 struct ship *from; 56 char *fmt; 57 struct ship *ship; 58 { 59 char message[80]; 60 61 if (ship == 0) 62 (void) sprintf(message, fmt, a, b, c); 63 else 64 (void) sprintf(message, fmt, 65 ship->shipname, colours(ship), 66 sterncolour(ship), a, b, c); 67 Write(W_SIGNAL, from, 1, (long)message, 0, 0, 0); 68 } 69 70 #include <sys/types.h> 71 #include <sys/stat.h> 72 sync_exists(game) 73 int game; 74 { 75 char buf[sizeof sync_file]; 76 struct stat s; 77 time_t t; 78 79 (void) sprintf(buf, SF, game); 80 (void) time(&t); 81 if (stat(buf, &s) < 0) 82 return 0; 83 if (s.st_mtime < t - 60*60*2) { /* 2 hours */ 84 (void) unlink(buf); 85 (void) sprintf(buf, LF, game); 86 (void) unlink(buf); 87 return 0; 88 } else 89 return 1; 90 } 91 92 sync_open() 93 { 94 if (sync_fp != NULL) 95 (void) fclose(sync_fp); 96 (void) sprintf(sync_lock, LF, game); 97 (void) sprintf(sync_file, SF, game); 98 if (access(sync_file, 0) < 0) { 99 int omask = umask(issetuid ? 077 : 011); 100 sync_fp = fopen(sync_file, "w+"); 101 (void) umask(omask); 102 } else 103 sync_fp = fopen(sync_file, "r+"); 104 if (sync_fp == NULL) 105 return -1; 106 sync_seek = 0; 107 return 0; 108 } 109 110 sync_close(remove) 111 char remove; 112 { 113 if (sync_fp != 0) 114 (void) fclose(sync_fp); 115 if (remove) 116 (void) unlink(sync_file); 117 } 118 119 Write(type, ship, isstr, a, b, c, d) 120 int type; 121 struct ship *ship; 122 char isstr; 123 int a, b, c, d; 124 { 125 if (isstr) 126 (void) sprintf(sync_bp, "%d %d %d %s\n", 127 type, ship->file->index, isstr, (char *)a); 128 else 129 (void) sprintf(sync_bp, "%d %d %d %d %d %d %d\n", 130 type, ship->file->index, isstr, a, b, c, d); 131 while (*sync_bp++) 132 ; 133 sync_bp--; 134 if (sync_bp >= &sync_buf[sizeof sync_buf]) 135 abort(); 136 (void) sync_update(type, ship, a, b, c, d); 137 } 138 139 Sync() 140 { 141 sig_t sighup, sigint; 142 int n; 143 int type, shipnum, isstr, a, b, c, d; 144 char buf[80]; 145 char erred = 0; 146 extern errno; 147 148 sighup = signal(SIGHUP, SIG_IGN); 149 sigint = signal(SIGINT, SIG_IGN); 150 for (n = TIMEOUT; --n >= 0;) { 151 #ifdef LOCK_EX 152 if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0) 153 break; 154 if (errno != EWOULDBLOCK) 155 return -1; 156 #else 157 if (link(sync_file, sync_lock) >= 0) 158 break; 159 if (errno != EEXIST) 160 return -1; 161 #endif 162 sleep(1); 163 } 164 if (n <= 0) 165 return -1; 166 (void) fseek(sync_fp, sync_seek, 0); 167 for (;;) { 168 switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) { 169 case 3: 170 break; 171 case EOF: 172 goto out; 173 default: 174 goto bad; 175 } 176 if (shipnum < 0 || shipnum >= cc->vessels) 177 goto bad; 178 if (isstr != 0 && isstr != 1) 179 goto bad; 180 if (isstr) { 181 char *p; 182 for (p = buf;;) { 183 switch (*p++ = getc(sync_fp)) { 184 case '\n': 185 p--; 186 case EOF: 187 break; 188 default: 189 if (p >= buf + sizeof buf) 190 p--; 191 continue; 192 } 193 break; 194 } 195 *p = 0; 196 for (p = buf; *p == ' '; p++) 197 ; 198 a = (long)p; 199 b = c = d = 0; 200 } else 201 if (fscanf(sync_fp, "%d%d%d%d", &a, &b, &c, &d) != 4) 202 goto bad; 203 if (sync_update(type, SHIP(shipnum), a, b, c, d) < 0) 204 goto bad; 205 } 206 bad: 207 erred++; 208 out: 209 if (!erred && sync_bp != sync_buf) { 210 (void) fseek(sync_fp, 0L, 2); 211 (void) fwrite(sync_buf, sizeof *sync_buf, sync_bp - sync_buf, 212 sync_fp); 213 (void) fflush(sync_fp); 214 sync_bp = sync_buf; 215 } 216 sync_seek = ftell(sync_fp); 217 #ifdef LOCK_EX 218 (void) flock(fileno(sync_fp), LOCK_UN); 219 #else 220 (void) unlink(sync_lock); 221 #endif 222 (void) signal(SIGHUP, sighup); 223 (void) signal(SIGINT, sigint); 224 return erred ? -1 : 0; 225 } 226 227 sync_update(type, ship, a, b, c, d) 228 int type; 229 struct ship *ship; 230 long a, b, c, d; 231 { 232 switch (type) { 233 case W_DBP: { 234 struct BP *p = &ship->file->DBP[a]; 235 p->turnsent = b; 236 p->toship = SHIP(c); 237 p->mensent = d; 238 break; 239 } 240 case W_OBP: { 241 struct BP *p = &ship->file->OBP[a]; 242 p->turnsent = b; 243 p->toship = SHIP(c); 244 p->mensent = d; 245 break; 246 } 247 case W_FOUL: { 248 struct snag *p = &ship->file->foul[a]; 249 if (SHIP(a)->file->dir == 0) 250 break; 251 if (p->sn_count++ == 0) 252 p->sn_turn = turn; 253 ship->file->nfoul++; 254 break; 255 } 256 case W_GRAP: { 257 struct snag *p = &ship->file->grap[a]; 258 if (SHIP(a)->file->dir == 0) 259 break; 260 if (p->sn_count++ == 0) 261 p->sn_turn = turn; 262 ship->file->ngrap++; 263 break; 264 } 265 case W_UNFOUL: { 266 struct snag *p = &ship->file->foul[a]; 267 if (p->sn_count > 0) { 268 if (b) { 269 ship->file->nfoul -= p->sn_count; 270 p->sn_count = 0; 271 } else { 272 ship->file->nfoul--; 273 p->sn_count--; 274 } 275 } 276 break; 277 } 278 case W_UNGRAP: { 279 struct snag *p = &ship->file->grap[a]; 280 if (p->sn_count > 0) { 281 if (b) { 282 ship->file->ngrap -= p->sn_count; 283 p->sn_count = 0; 284 } else { 285 ship->file->ngrap--; 286 p->sn_count--; 287 } 288 } 289 break; 290 } 291 case W_SIGNAL: 292 if (mode == MODE_PLAYER) { 293 if (nobells) 294 Signal("%s (%c%c): %s", ship, a); 295 else 296 Signal("\7%s (%c%c): %s", ship, a); 297 } 298 break; 299 case W_CREW: { 300 struct shipspecs *s = ship->specs; 301 s->crew1 = a; 302 s->crew2 = b; 303 s->crew3 = c; 304 break; 305 } 306 case W_CAPTAIN: 307 (void) strncpy(ship->file->captain, (char *)a, 308 sizeof ship->file->captain - 1); 309 ship->file->captain[sizeof ship->file->captain - 1] = 0; 310 break; 311 case W_CAPTURED: 312 if (a < 0) 313 ship->file->captured = 0; 314 else 315 ship->file->captured = SHIP(a); 316 break; 317 case W_CLASS: 318 ship->specs->class = a; 319 break; 320 case W_DRIFT: 321 ship->file->drift = a; 322 break; 323 case W_EXPLODE: 324 if ((ship->file->explode = a) == 2) 325 ship->file->dir = 0; 326 break; 327 case W_FS: 328 ship->file->FS = a; 329 break; 330 case W_GUNL: { 331 struct shipspecs *s = ship->specs; 332 s->gunL = a; 333 s->carL = b; 334 break; 335 } 336 case W_GUNR: { 337 struct shipspecs *s = ship->specs; 338 s->gunR = a; 339 s->carR = b; 340 break; 341 } 342 case W_HULL: 343 ship->specs->hull = a; 344 break; 345 case W_MOVE: 346 (void) strncpy(ship->file->movebuf, (char *)a, 347 sizeof ship->file->movebuf - 1); 348 ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0; 349 break; 350 case W_PCREW: 351 ship->file->pcrew = a; 352 break; 353 case W_POINTS: 354 ship->file->points = a; 355 break; 356 case W_QUAL: 357 ship->specs->qual = a; 358 break; 359 case W_RIGG: { 360 struct shipspecs *s = ship->specs; 361 s->rig1 = a; 362 s->rig2 = b; 363 s->rig3 = c; 364 s->rig4 = d; 365 break; 366 } 367 case W_RIG1: 368 ship->specs->rig1 = a; 369 break; 370 case W_RIG2: 371 ship->specs->rig2 = a; 372 break; 373 case W_RIG3: 374 ship->specs->rig3 = a; 375 break; 376 case W_RIG4: 377 ship->specs->rig4 = a; 378 break; 379 case W_COL: 380 ship->file->col = a; 381 break; 382 case W_DIR: 383 ship->file->dir = a; 384 break; 385 case W_ROW: 386 ship->file->row = a; 387 break; 388 case W_SINK: 389 if ((ship->file->sink = a) == 2) 390 ship->file->dir = 0; 391 break; 392 case W_STRUCK: 393 ship->file->struck = a; 394 break; 395 case W_TA: 396 ship->specs->ta = a; 397 break; 398 case W_ALIVE: 399 alive = 1; 400 break; 401 case W_TURN: 402 turn = a; 403 break; 404 case W_WIND: 405 winddir = a; 406 windspeed = b; 407 break; 408 case W_BEGIN: 409 (void) strcpy(ship->file->captain, "begin"); 410 people++; 411 break; 412 case W_END: 413 *ship->file->captain = 0; 414 ship->file->points = 0; 415 people--; 416 break; 417 case W_DDEAD: 418 hasdriver = 0; 419 break; 420 default: 421 fprintf(stderr, "sync_update: unknown type %d\r\n", type); 422 return -1; 423 } 424 return 0; 425 } 426