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