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