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.3 2005/04/29 09:22:57 joerg 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 sighup = signal(SIGHUP, SIG_IGN); 147 sigint = signal(SIGINT, SIG_IGN); 148 for (n = TIMEOUT; --n >= 0;) { 149 #ifdef LOCK_EX 150 if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0) 151 break; 152 if (errno != EWOULDBLOCK) 153 return -1; 154 #else 155 if (link(sync_file, sync_lock) >= 0) 156 break; 157 if (errno != EEXIST) 158 return -1; 159 #endif 160 sleep(1); 161 } 162 if (n <= 0) 163 return -1; 164 (void) fseek(sync_fp, sync_seek, 0); 165 for (;;) { 166 switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) { 167 case 3: 168 break; 169 case EOF: 170 goto out; 171 default: 172 goto bad; 173 } 174 if (shipnum < 0 || shipnum >= cc->vessels) 175 goto bad; 176 if (isstr != 0 && isstr != 1) 177 goto bad; 178 if (isstr) { 179 char *p; 180 for (p = buf;;) { 181 switch (*p++ = getc(sync_fp)) { 182 case '\n': 183 p--; 184 case EOF: 185 break; 186 default: 187 if (p >= buf + sizeof buf) 188 p--; 189 continue; 190 } 191 break; 192 } 193 *p = 0; 194 for (p = buf; *p == ' '; p++) 195 ; 196 a = (long)p; 197 b = c = d = 0; 198 } else 199 if (fscanf(sync_fp, "%d%d%d%d", &a, &b, &c, &d) != 4) 200 goto bad; 201 if (sync_update(type, SHIP(shipnum), a, b, c, d) < 0) 202 goto bad; 203 } 204 bad: 205 erred++; 206 out: 207 if (!erred && sync_bp != sync_buf) { 208 (void) fseek(sync_fp, 0L, 2); 209 (void) fwrite(sync_buf, sizeof *sync_buf, sync_bp - sync_buf, 210 sync_fp); 211 (void) fflush(sync_fp); 212 sync_bp = sync_buf; 213 } 214 sync_seek = ftell(sync_fp); 215 #ifdef LOCK_EX 216 (void) flock(fileno(sync_fp), LOCK_UN); 217 #else 218 (void) unlink(sync_lock); 219 #endif 220 (void) signal(SIGHUP, sighup); 221 (void) signal(SIGINT, sigint); 222 return erred ? -1 : 0; 223 } 224 225 sync_update(type, ship, a, b, c, d) 226 int type; 227 struct ship *ship; 228 long a, b, c, d; 229 { 230 switch (type) { 231 case W_DBP: { 232 struct BP *p = &ship->file->DBP[a]; 233 p->turnsent = b; 234 p->toship = SHIP(c); 235 p->mensent = d; 236 break; 237 } 238 case W_OBP: { 239 struct BP *p = &ship->file->OBP[a]; 240 p->turnsent = b; 241 p->toship = SHIP(c); 242 p->mensent = d; 243 break; 244 } 245 case W_FOUL: { 246 struct snag *p = &ship->file->foul[a]; 247 if (SHIP(a)->file->dir == 0) 248 break; 249 if (p->sn_count++ == 0) 250 p->sn_turn = turn; 251 ship->file->nfoul++; 252 break; 253 } 254 case W_GRAP: { 255 struct snag *p = &ship->file->grap[a]; 256 if (SHIP(a)->file->dir == 0) 257 break; 258 if (p->sn_count++ == 0) 259 p->sn_turn = turn; 260 ship->file->ngrap++; 261 break; 262 } 263 case W_UNFOUL: { 264 struct snag *p = &ship->file->foul[a]; 265 if (p->sn_count > 0) { 266 if (b) { 267 ship->file->nfoul -= p->sn_count; 268 p->sn_count = 0; 269 } else { 270 ship->file->nfoul--; 271 p->sn_count--; 272 } 273 } 274 break; 275 } 276 case W_UNGRAP: { 277 struct snag *p = &ship->file->grap[a]; 278 if (p->sn_count > 0) { 279 if (b) { 280 ship->file->ngrap -= p->sn_count; 281 p->sn_count = 0; 282 } else { 283 ship->file->ngrap--; 284 p->sn_count--; 285 } 286 } 287 break; 288 } 289 case W_SIGNAL: 290 if (mode == MODE_PLAYER) { 291 if (nobells) 292 Signal("%s (%c%c): %s", ship, a); 293 else 294 Signal("\7%s (%c%c): %s", ship, a); 295 } 296 break; 297 case W_CREW: { 298 struct shipspecs *s = ship->specs; 299 s->crew1 = a; 300 s->crew2 = b; 301 s->crew3 = c; 302 break; 303 } 304 case W_CAPTAIN: 305 (void) strncpy(ship->file->captain, (char *)a, 306 sizeof ship->file->captain - 1); 307 ship->file->captain[sizeof ship->file->captain - 1] = 0; 308 break; 309 case W_CAPTURED: 310 if (a < 0) 311 ship->file->captured = 0; 312 else 313 ship->file->captured = SHIP(a); 314 break; 315 case W_CLASS: 316 ship->specs->class = a; 317 break; 318 case W_DRIFT: 319 ship->file->drift = a; 320 break; 321 case W_EXPLODE: 322 if ((ship->file->explode = a) == 2) 323 ship->file->dir = 0; 324 break; 325 case W_FS: 326 ship->file->FS = a; 327 break; 328 case W_GUNL: { 329 struct shipspecs *s = ship->specs; 330 s->gunL = a; 331 s->carL = b; 332 break; 333 } 334 case W_GUNR: { 335 struct shipspecs *s = ship->specs; 336 s->gunR = a; 337 s->carR = b; 338 break; 339 } 340 case W_HULL: 341 ship->specs->hull = a; 342 break; 343 case W_MOVE: 344 (void) strncpy(ship->file->movebuf, (char *)a, 345 sizeof ship->file->movebuf - 1); 346 ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0; 347 break; 348 case W_PCREW: 349 ship->file->pcrew = a; 350 break; 351 case W_POINTS: 352 ship->file->points = a; 353 break; 354 case W_QUAL: 355 ship->specs->qual = a; 356 break; 357 case W_RIGG: { 358 struct shipspecs *s = ship->specs; 359 s->rig1 = a; 360 s->rig2 = b; 361 s->rig3 = c; 362 s->rig4 = d; 363 break; 364 } 365 case W_RIG1: 366 ship->specs->rig1 = a; 367 break; 368 case W_RIG2: 369 ship->specs->rig2 = a; 370 break; 371 case W_RIG3: 372 ship->specs->rig3 = a; 373 break; 374 case W_RIG4: 375 ship->specs->rig4 = a; 376 break; 377 case W_COL: 378 ship->file->col = a; 379 break; 380 case W_DIR: 381 ship->file->dir = a; 382 break; 383 case W_ROW: 384 ship->file->row = a; 385 break; 386 case W_SINK: 387 if ((ship->file->sink = a) == 2) 388 ship->file->dir = 0; 389 break; 390 case W_STRUCK: 391 ship->file->struck = a; 392 break; 393 case W_TA: 394 ship->specs->ta = a; 395 break; 396 case W_ALIVE: 397 alive = 1; 398 break; 399 case W_TURN: 400 turn = a; 401 break; 402 case W_WIND: 403 winddir = a; 404 windspeed = b; 405 break; 406 case W_BEGIN: 407 (void) strcpy(ship->file->captain, "begin"); 408 people++; 409 break; 410 case W_END: 411 *ship->file->captain = 0; 412 ship->file->points = 0; 413 people--; 414 break; 415 case W_DDEAD: 416 hasdriver = 0; 417 break; 418 default: 419 fprintf(stderr, "sync_update: unknown type %d\r\n", type); 420 return -1; 421 } 422 return 0; 423 } 424