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