1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * 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 /*static char sccsid[] = "from: @(#)sync.c 5.6 (Berkeley) 6/1/90";*/ 36 static char rcsid[] = "$Id: sync.c,v 1.2 1993/08/01 18:51:33 mycroft Exp $"; 37 #endif /* not lint */ 38 39 #include "externs.h" 40 #include <sys/file.h> 41 #include <sys/errno.h> 42 43 #define BUFSIZE 4096 44 45 static char sync_buf[BUFSIZE]; 46 static char *sync_bp = sync_buf; 47 static char sync_lock[25]; 48 static char sync_file[25]; 49 static long sync_seek; 50 static FILE *sync_fp; 51 #define SF "/tmp/#sailsink.%d" 52 #define LF "/tmp/#saillock.%d" 53 54 /*VARARGS3*/ 55 makesignal(from, fmt, ship, a, b, c) 56 struct ship *from; 57 char *fmt; 58 register struct ship *ship; 59 { 60 char message[80]; 61 62 if (ship == 0) 63 (void) sprintf(message, fmt, a, b, c); 64 else 65 (void) sprintf(message, fmt, 66 ship->shipname, colours(ship), 67 sterncolour(ship), a, b, c); 68 Write(W_SIGNAL, from, 1, (int)message, 0, 0, 0); 69 } 70 71 #include <sys/types.h> 72 #include <sys/stat.h> 73 sync_exists(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, 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 register 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 register 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 = (int)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 register struct ship *ship; 230 int a, b, c, d; 231 { 232 switch (type) { 233 case W_DBP: { 234 register 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 register 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 register 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 register 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 register 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 break; 276 } 277 case W_UNGRAP: { 278 register struct snag *p = &ship->file->grap[a]; 279 if (p->sn_count > 0) 280 if (b) { 281 ship->file->ngrap -= p->sn_count; 282 p->sn_count = 0; 283 } else { 284 ship->file->ngrap--; 285 p->sn_count--; 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 break; 296 case W_CREW: { 297 register struct shipspecs *s = ship->specs; 298 s->crew1 = a; 299 s->crew2 = b; 300 s->crew3 = c; 301 break; 302 } 303 case W_CAPTAIN: 304 (void) strncpy(ship->file->captain, (char *)a, 305 sizeof ship->file->captain - 1); 306 ship->file->captain[sizeof ship->file->captain - 1] = 0; 307 break; 308 case W_CAPTURED: 309 if (a < 0) 310 ship->file->captured = 0; 311 else 312 ship->file->captured = SHIP(a); 313 break; 314 case W_CLASS: 315 ship->specs->class = a; 316 break; 317 case W_DRIFT: 318 ship->file->drift = a; 319 break; 320 case W_EXPLODE: 321 if ((ship->file->explode = a) == 2) 322 ship->file->dir = 0; 323 break; 324 case W_FS: 325 ship->file->FS = a; 326 break; 327 case W_GUNL: { 328 register struct shipspecs *s = ship->specs; 329 s->gunL = a; 330 s->carL = b; 331 break; 332 } 333 case W_GUNR: { 334 register struct shipspecs *s = ship->specs; 335 s->gunR = a; 336 s->carR = b; 337 break; 338 } 339 case W_HULL: 340 ship->specs->hull = a; 341 break; 342 case W_MOVE: 343 (void) strncpy(ship->file->movebuf, (char *)a, 344 sizeof ship->file->movebuf - 1); 345 ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0; 346 break; 347 case W_PCREW: 348 ship->file->pcrew = a; 349 break; 350 case W_POINTS: 351 ship->file->points = a; 352 break; 353 case W_QUAL: 354 ship->specs->qual = a; 355 break; 356 case W_RIGG: { 357 register struct shipspecs *s = ship->specs; 358 s->rig1 = a; 359 s->rig2 = b; 360 s->rig3 = c; 361 s->rig4 = d; 362 break; 363 } 364 case W_RIG1: 365 ship->specs->rig1 = a; 366 break; 367 case W_RIG2: 368 ship->specs->rig2 = a; 369 break; 370 case W_RIG3: 371 ship->specs->rig3 = a; 372 break; 373 case W_RIG4: 374 ship->specs->rig4 = a; 375 break; 376 case W_COL: 377 ship->file->col = a; 378 break; 379 case W_DIR: 380 ship->file->dir = a; 381 break; 382 case W_ROW: 383 ship->file->row = a; 384 break; 385 case W_SINK: 386 if ((ship->file->sink = a) == 2) 387 ship->file->dir = 0; 388 break; 389 case W_STRUCK: 390 ship->file->struck = a; 391 break; 392 case W_TA: 393 ship->specs->ta = a; 394 break; 395 case W_ALIVE: 396 alive = 1; 397 break; 398 case W_TURN: 399 turn = a; 400 break; 401 case W_WIND: 402 winddir = a; 403 windspeed = b; 404 break; 405 case W_BEGIN: 406 (void) strcpy(ship->file->captain, "begin"); 407 people++; 408 break; 409 case W_END: 410 *ship->file->captain = 0; 411 ship->file->points = 0; 412 people--; 413 break; 414 case W_DDEAD: 415 hasdriver = 0; 416 break; 417 default: 418 fprintf(stderr, "sync_update: unknown type %d\r\n", type); 419 return -1; 420 } 421 return 0; 422 } 423