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