]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - sail/sync.c
Curses works - define USE_CURSES for BSD44 and don't try to do our own
[bsdgames-darwin.git] / sail / sync.c
1 /* $NetBSD: sync.c,v 1.14 2000/02/09 22:27:56 jsm Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)sync.c 8.2 (Berkeley) 4/28/95";
40 #else
41 __RCSID("$NetBSD: sync.c,v 1.14 2000/02/09 22:27:56 jsm Exp $");
42 #endif
43 #endif /* not lint */
44
45 #include <fcntl.h>
46 #include <errno.h>
47 #ifdef __STDC__
48 #include <stdarg.h>
49 #else
50 #include <varargs.h>
51 #endif
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <time.h>
57 #include "extern.h"
58 #include "pathnames.h"
59
60 #define BUFSIZE 4096
61
62 static const char SF[] = _PATH_SYNC;
63 static const char LF[] = _PATH_LOCK;
64 static char sync_buf[BUFSIZE];
65 static char *sync_bp = sync_buf;
66 static char sync_lock[sizeof SF];
67 static char sync_file[sizeof LF];
68 static long sync_seek;
69 static FILE *sync_fp;
70
71 void
72 fmtship(buf, len, fmt, ship)
73 char *buf;
74 size_t len;
75 const char *fmt;
76 struct ship *ship;
77 {
78 while (*fmt) {
79 if (len-- == 0) {
80 *buf = '\0';
81 return;
82 }
83 if (*fmt == '$' && fmt[1] == '$') {
84 size_t l = snprintf(buf, len, "%s (%c%c)",
85 ship->shipname, colours(ship), sterncolour(ship));
86 buf += l;
87 len -= l - 1;
88 fmt += 2;
89 }
90 else
91 *buf++ = *fmt++;
92 }
93
94 if (len > 0)
95 *buf = '\0';
96 }
97
98
99 /*VARARGS3*/
100 void
101 #ifdef __STDC__
102 makesignal(struct ship *from, const char *fmt, struct ship *ship, ...)
103 #else
104 makesignal(va_alias)
105 va_dcl
106 #endif
107 {
108 char message[BUFSIZ];
109 char format[BUFSIZ];
110 va_list ap;
111 #ifndef __STDC__
112 struct ship *from;
113 const char *fmt;
114 struct ship *ship;
115
116 va_start(ap);
117 from = va_arg(ap, struct ship *);
118 fmt = va_arg(ap, const char *);
119 ship = va_arg(ap, struct ship *);
120 #else
121 va_start(ap, ship);
122 #endif
123 fmtship(format, sizeof(format), fmt, ship);
124 (void) vsprintf(message, format, ap);
125 va_end(ap);
126 Writestr(W_SIGNAL, from, message);
127 }
128
129 void
130 #ifdef __STDC__
131 makemsg(struct ship *from, const char *fmt, ...)
132 #else
133 makemsg(va_alias)
134 va_dcl
135 #endif
136 {
137 char message[BUFSIZ];
138 va_list ap;
139 #ifndef __STDC__
140 struct ship *from;
141 const char *fmt;
142
143 va_start(ap);
144 from = va_arg(ap, struct ship *);
145 fmt = va_arg(ap, const char *);
146 #else
147 va_start(ap, fmt);
148 #endif
149 (void) vsprintf(message, fmt, ap);
150 va_end(ap);
151 Writestr(W_SIGNAL, from, message);
152 }
153
154 int
155 sync_exists(game)
156 int game;
157 {
158 char buf[sizeof sync_file];
159 struct stat s;
160 time_t t;
161
162 (void) sprintf(buf, SF, game);
163 (void) time(&t);
164 setegid(egid);
165 if (stat(buf, &s) < 0) {
166 setegid(gid);
167 return 0;
168 }
169 if (s.st_mtime < t - 60*60*2) { /* 2 hours */
170 (void) unlink(buf);
171 (void) sprintf(buf, LF, game);
172 (void) unlink(buf);
173 setegid(gid);
174 return 0;
175 } else {
176 setegid(gid);
177 return 1;
178 }
179 }
180
181 int
182 sync_open()
183 {
184 struct stat tmp;
185 if (sync_fp != NULL)
186 (void) fclose(sync_fp);
187 (void) sprintf(sync_lock, LF, game);
188 (void) sprintf(sync_file, SF, game);
189 setegid(egid);
190 if (stat(sync_file, &tmp) < 0) {
191 mode_t omask = umask(002);
192 sync_fp = fopen(sync_file, "w+");
193 (void) umask(omask);
194 } else
195 sync_fp = fopen(sync_file, "r+");
196 setegid(gid);
197 if (sync_fp == NULL)
198 return -1;
199 sync_seek = 0;
200 return 0;
201 }
202
203 void
204 sync_close(remove)
205 char remove;
206 {
207 if (sync_fp != 0)
208 (void) fclose(sync_fp);
209 if (remove) {
210 setegid(egid);
211 (void) unlink(sync_file);
212 setegid(gid);
213 }
214 }
215
216 void
217 Write(type, ship, a, b, c, d)
218 int type;
219 struct ship *ship;
220 long a, b, c, d;
221 {
222
223 (void) sprintf(sync_bp, "%d %d 0 %ld %ld %ld %ld\n",
224 type, ship->file->index, a, b, c, d);
225 while (*sync_bp++)
226 ;
227 sync_bp--;
228 if (sync_bp >= &sync_buf[sizeof sync_buf])
229 abort();
230 (void) sync_update(type, ship, NULL, a, b, c, d);
231 }
232
233 void
234 Writestr(type, ship, a)
235 int type;
236 struct ship *ship;
237 const char *a;
238 {
239
240 (void) sprintf(sync_bp, "%d %d 1 %s\n",
241 type, ship->file->index, a);
242 while (*sync_bp++)
243 ;
244 sync_bp--;
245 if (sync_bp >= &sync_buf[sizeof sync_buf])
246 abort();
247 (void) sync_update(type, ship, a, 0, 0, 0, 0);
248 }
249
250 int
251 Sync()
252 {
253 sig_t sighup, sigint;
254 int n;
255 int type, shipnum, isstr;
256 char *astr;
257 long a, b, c, d;
258 char buf[80];
259 char erred = 0;
260
261 sighup = signal(SIGHUP, SIG_IGN);
262 sigint = signal(SIGINT, SIG_IGN);
263 for (n = TIMEOUT; --n >= 0;) {
264 #ifdef LOCK_EX
265 if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0)
266 break;
267 if (errno != EWOULDBLOCK)
268 return -1;
269 #else
270 setegid(egid);
271 if (link(sync_file, sync_lock) >= 0) {
272 setegid(gid);
273 break;
274 }
275 setegid(gid);
276 if (errno != EEXIST)
277 return -1;
278 #endif
279 sleep(1);
280 }
281 if (n <= 0)
282 return -1;
283 (void) fseek(sync_fp, sync_seek, SEEK_SET);
284 for (;;) {
285 switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) {
286 case 3:
287 break;
288 case EOF:
289 goto out;
290 default:
291 goto bad;
292 }
293 if (shipnum < 0 || shipnum >= cc->vessels)
294 goto bad;
295 if (isstr != 0 && isstr != 1)
296 goto bad;
297 if (isstr) {
298 char *p;
299 for (p = buf;;) {
300 switch (*p++ = getc(sync_fp)) {
301 case '\n':
302 p--;
303 case EOF:
304 break;
305 default:
306 if (p >= buf + sizeof buf)
307 p--;
308 continue;
309 }
310 break;
311 }
312 *p = 0;
313 for (p = buf; *p == ' '; p++)
314 ;
315 astr = p;
316 a = b = c = d = 0;
317 } else {
318 if (fscanf(sync_fp, "%ld%ld%ld%ld", &a, &b, &c, &d) != 4)
319 goto bad;
320 astr = NULL;
321 }
322 if (sync_update(type, SHIP(shipnum), astr, a, b, c, d) < 0)
323 goto bad;
324 }
325 bad:
326 erred++;
327 out:
328 if (!erred && sync_bp != sync_buf) {
329 (void) fseek(sync_fp, 0L, SEEK_END);
330 (void) fwrite(sync_buf, sizeof *sync_buf, sync_bp - sync_buf,
331 sync_fp);
332 (void) fflush(sync_fp);
333 sync_bp = sync_buf;
334 }
335 sync_seek = ftell(sync_fp);
336 #ifdef LOCK_EX
337 (void) flock(fileno(sync_fp), LOCK_UN);
338 #else
339 setegid(egid);
340 (void) unlink(sync_lock);
341 setegid(gid);
342 #endif
343 (void) signal(SIGHUP, sighup);
344 (void) signal(SIGINT, sigint);
345 return erred ? -1 : 0;
346 }
347
348 int
349 sync_update(type, ship, astr, a, b, c, d)
350 int type;
351 struct ship *ship;
352 const char *astr;
353 long a, b, c, d;
354 {
355 switch (type) {
356 case W_DBP: {
357 struct BP *p = &ship->file->DBP[a];
358 p->turnsent = b;
359 p->toship = SHIP(c);
360 p->mensent = d;
361 break;
362 }
363 case W_OBP: {
364 struct BP *p = &ship->file->OBP[a];
365 p->turnsent = b;
366 p->toship = SHIP(c);
367 p->mensent = d;
368 break;
369 }
370 case W_FOUL: {
371 struct snag *p = &ship->file->foul[a];
372 if (SHIP(a)->file->dir == 0)
373 break;
374 if (p->sn_count++ == 0)
375 p->sn_turn = turn;
376 ship->file->nfoul++;
377 break;
378 }
379 case W_GRAP: {
380 struct snag *p = &ship->file->grap[a];
381 if (SHIP(a)->file->dir == 0)
382 break;
383 if (p->sn_count++ == 0)
384 p->sn_turn = turn;
385 ship->file->ngrap++;
386 break;
387 }
388 case W_UNFOUL: {
389 struct snag *p = &ship->file->foul[a];
390 if (p->sn_count > 0) {
391 if (b) {
392 ship->file->nfoul -= p->sn_count;
393 p->sn_count = 0;
394 } else {
395 ship->file->nfoul--;
396 p->sn_count--;
397 }
398 }
399 break;
400 }
401 case W_UNGRAP: {
402 struct snag *p = &ship->file->grap[a];
403 if (p->sn_count > 0) {
404 if (b) {
405 ship->file->ngrap -= p->sn_count;
406 p->sn_count = 0;
407 } else {
408 ship->file->ngrap--;
409 p->sn_count--;
410 }
411 }
412 break;
413 }
414 case W_SIGNAL:
415 if (mode == MODE_PLAYER) {
416 if (nobells)
417 Signal("$$: %s", ship, astr);
418 else
419 Signal("\7$$: %s", ship, astr);
420 }
421 break;
422 case W_CREW: {
423 struct shipspecs *s = ship->specs;
424 s->crew1 = a;
425 s->crew2 = b;
426 s->crew3 = c;
427 break;
428 }
429 case W_CAPTAIN:
430 (void) strncpy(ship->file->captain, astr,
431 sizeof ship->file->captain - 1);
432 ship->file->captain[sizeof ship->file->captain - 1] = 0;
433 break;
434 case W_CAPTURED:
435 if (a < 0)
436 ship->file->captured = 0;
437 else
438 ship->file->captured = SHIP(a);
439 break;
440 case W_CLASS:
441 ship->specs->class = a;
442 break;
443 case W_DRIFT:
444 ship->file->drift = a;
445 break;
446 case W_EXPLODE:
447 if ((ship->file->explode = a) == 2)
448 ship->file->dir = 0;
449 break;
450 case W_FS:
451 ship->file->FS = a;
452 break;
453 case W_GUNL: {
454 struct shipspecs *s = ship->specs;
455 s->gunL = a;
456 s->carL = b;
457 break;
458 }
459 case W_GUNR: {
460 struct shipspecs *s = ship->specs;
461 s->gunR = a;
462 s->carR = b;
463 break;
464 }
465 case W_HULL:
466 ship->specs->hull = a;
467 break;
468 case W_MOVE:
469 (void) strncpy(ship->file->movebuf, astr,
470 sizeof ship->file->movebuf - 1);
471 ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0;
472 break;
473 case W_PCREW:
474 ship->file->pcrew = a;
475 break;
476 case W_POINTS:
477 ship->file->points = a;
478 break;
479 case W_QUAL:
480 ship->specs->qual = a;
481 break;
482 case W_RIGG: {
483 struct shipspecs *s = ship->specs;
484 s->rig1 = a;
485 s->rig2 = b;
486 s->rig3 = c;
487 s->rig4 = d;
488 break;
489 }
490 case W_RIG1:
491 ship->specs->rig1 = a;
492 break;
493 case W_RIG2:
494 ship->specs->rig2 = a;
495 break;
496 case W_RIG3:
497 ship->specs->rig3 = a;
498 break;
499 case W_RIG4:
500 ship->specs->rig4 = a;
501 break;
502 case W_COL:
503 ship->file->col = a;
504 break;
505 case W_DIR:
506 ship->file->dir = a;
507 break;
508 case W_ROW:
509 ship->file->row = a;
510 break;
511 case W_SINK:
512 if ((ship->file->sink = a) == 2)
513 ship->file->dir = 0;
514 break;
515 case W_STRUCK:
516 ship->file->struck = a;
517 break;
518 case W_TA:
519 ship->specs->ta = a;
520 break;
521 case W_ALIVE:
522 alive = 1;
523 break;
524 case W_TURN:
525 turn = a;
526 break;
527 case W_WIND:
528 winddir = a;
529 windspeed = b;
530 break;
531 case W_BEGIN:
532 (void) strcpy(ship->file->captain, "begin");
533 people++;
534 break;
535 case W_END:
536 *ship->file->captain = 0;
537 ship->file->points = 0;
538 people--;
539 break;
540 case W_DDEAD:
541 hasdriver = 0;
542 break;
543 default:
544 fprintf(stderr, "sync_update: unknown type %d\r\n", type);
545 return -1;
546 }
547 return 0;
548 }