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