1 /* 2 * Copyright (c) 1983 Regents of the University of California, 3 * All rights reserved. Redistribution permitted subject to 4 * the terms of the Berkeley Software License Agreement. 5 */ 6 7 #ifndef lint 8 static char *sccsid = "@(#)sync.c 2.10 85/04/23"; 9 #endif 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 (*sig1)(), (*sig2)(); 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 sig1 = signal(SIGHUP, SIG_IGN); 121 sig2 = 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) fputs(sync_buf, sync_fp); 184 (void) fflush(sync_fp); 185 sync_bp = sync_buf; 186 } 187 sync_seek = ftell(sync_fp); 188 #ifdef LOCK_EX 189 (void) flock(fileno(sync_fp), LOCK_UN); 190 #else 191 (void) unlink(sync_lock); 192 #endif 193 (void) signal(SIGHUP, sig1); 194 (void) signal(SIGINT, sig2); 195 return erred ? -1 : 0; 196 } 197 198 sync_update(type, ship, a, b, c, d) 199 int type; 200 register struct ship *ship; 201 int a, b, c, d; 202 { 203 switch (type) { 204 case W_DBP: { 205 register struct BP *p = &ship->file->DBP[a]; 206 p->turnsent = b; 207 p->toship = SHIP(c); 208 p->mensent = d; 209 break; 210 } 211 case W_OBP: { 212 register struct BP *p = &ship->file->OBP[a]; 213 p->turnsent = b; 214 p->toship = SHIP(c); 215 p->mensent = d; 216 break; 217 } 218 case W_FOUL: { 219 register struct snag *p = &ship->file->foul[a]; 220 if (SHIP(a)->file->dir == 0) 221 break; 222 if (p->sn_count++ == 0) 223 p->sn_turn = turn; 224 ship->file->nfoul++; 225 break; 226 } 227 case W_GRAP: { 228 register struct snag *p = &ship->file->grap[a]; 229 if (SHIP(a)->file->dir == 0) 230 break; 231 if (p->sn_count++ == 0) 232 p->sn_turn = turn; 233 ship->file->ngrap++; 234 break; 235 } 236 case W_UNFOUL: { 237 register struct snag *p = &ship->file->foul[a]; 238 if (p->sn_count > 0) 239 if (b) { 240 ship->file->nfoul -= p->sn_count; 241 p->sn_count = 0; 242 } else { 243 ship->file->nfoul--; 244 p->sn_count--; 245 } 246 break; 247 } 248 case W_UNGRAP: { 249 register struct snag *p = &ship->file->grap[a]; 250 if (p->sn_count > 0) 251 if (b) { 252 ship->file->ngrap -= p->sn_count; 253 p->sn_count = 0; 254 } else { 255 ship->file->ngrap--; 256 p->sn_count--; 257 } 258 break; 259 } 260 case W_SIGNAL: 261 if (mode == MODE_PLAYER) 262 if (nobells) 263 Signal("%s (%c%c): %s", ship, a); 264 else 265 Signal("\7%s (%c%c): %s", ship, a); 266 break; 267 case W_CREW: { 268 register struct shipspecs *s = ship->specs; 269 s->crew1 = a; 270 s->crew2 = b; 271 s->crew3 = c; 272 break; 273 } 274 case W_CAPTAIN: 275 (void) strncpy(ship->file->captain, (char *)a, 276 sizeof ship->file->captain - 1); 277 ship->file->captain[sizeof ship->file->captain - 1] = 0; 278 break; 279 case W_CAPTURED: 280 if (a < 0) 281 ship->file->captured = 0; 282 else 283 ship->file->captured = SHIP(a); 284 break; 285 case W_CLASS: 286 ship->specs->class = a; 287 break; 288 case W_DRIFT: 289 ship->file->drift = a; 290 break; 291 case W_EXPLODE: 292 if ((ship->file->explode = a) == 2) 293 ship->file->dir = 0; 294 break; 295 case W_FS: 296 ship->file->FS = a; 297 break; 298 case W_GUNL: { 299 register struct shipspecs *s = ship->specs; 300 s->gunL = a; 301 s->carL = b; 302 break; 303 } 304 case W_GUNR: { 305 register struct shipspecs *s = ship->specs; 306 s->gunR = a; 307 s->carR = b; 308 break; 309 } 310 case W_HULL: 311 ship->specs->hull = a; 312 break; 313 case W_MOVE: 314 (void) strncpy(ship->file->movebuf, (char *)a, 315 sizeof ship->file->movebuf - 1); 316 ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0; 317 break; 318 case W_PCREW: 319 ship->file->pcrew = a; 320 break; 321 case W_POINTS: 322 ship->file->points = a; 323 break; 324 case W_QUAL: 325 ship->specs->qual = a; 326 break; 327 case W_RIGG: { 328 register struct shipspecs *s = ship->specs; 329 s->rig1 = a; 330 s->rig2 = b; 331 s->rig3 = c; 332 s->rig4 = d; 333 break; 334 } 335 case W_RIG1: 336 ship->specs->rig1 = a; 337 break; 338 case W_RIG2: 339 ship->specs->rig2 = a; 340 break; 341 case W_RIG3: 342 ship->specs->rig3 = a; 343 break; 344 case W_RIG4: 345 ship->specs->rig4 = a; 346 break; 347 case W_COL: 348 ship->file->col = a; 349 break; 350 case W_DIR: 351 ship->file->dir = a; 352 break; 353 case W_ROW: 354 ship->file->row = a; 355 break; 356 case W_SINK: 357 if ((ship->file->sink = a) == 2) 358 ship->file->dir = 0; 359 break; 360 case W_STRUCK: 361 ship->file->struck = a; 362 break; 363 case W_TA: 364 ship->specs->ta = a; 365 break; 366 case W_ALIVE: 367 alive = 1; 368 break; 369 case W_TURN: 370 turn = a; 371 break; 372 case W_WIND: 373 winddir = a; 374 windspeed = b; 375 break; 376 case W_BEGIN: 377 (void) strcpy(ship->file->captain, "begin"); 378 people++; 379 break; 380 case W_END: 381 *ship->file->captain = 0; 382 ship->file->points = 0; 383 people--; 384 break; 385 case W_DDEAD: 386 hasdriver = 0; 387 break; 388 default: 389 fprintf(stderr, "sync_update: unknown type %d\r\n", type); 390 return -1; 391 } 392 return 0; 393 } 394