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