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