]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - sail/sync.c
Include <sys/stat.h>.
[bsdgames-darwin.git] / sail / sync.c
1 /* $NetBSD: sync.c,v 1.22 2004/01/27 20:27:59 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. 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.22 2004/01/27 20:27:59 jsm 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 strncpy(ship->file->captain, astr,
383 sizeof ship->file->captain - 1);
384 ship->file->captain[sizeof ship->file->captain - 1] = 0;
385 break;
386 case W_CAPTURED:
387 if (a < 0)
388 ship->file->captured = 0;
389 else
390 ship->file->captured = SHIP(a);
391 break;
392 case W_CLASS:
393 ship->specs->class = a;
394 break;
395 case W_DRIFT:
396 ship->file->drift = a;
397 break;
398 case W_EXPLODE:
399 if ((ship->file->explode = a) == 2)
400 ship->file->dir = 0;
401 break;
402 case W_FS:
403 ship->file->FS = a;
404 break;
405 case W_GUNL: {
406 struct shipspecs *s = ship->specs;
407 s->gunL = a;
408 s->carL = b;
409 break;
410 }
411 case W_GUNR: {
412 struct shipspecs *s = ship->specs;
413 s->gunR = a;
414 s->carR = b;
415 break;
416 }
417 case W_HULL:
418 ship->specs->hull = a;
419 break;
420 case W_MOVE:
421 strncpy(ship->file->movebuf, astr,
422 sizeof ship->file->movebuf - 1);
423 ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0;
424 break;
425 case W_PCREW:
426 ship->file->pcrew = a;
427 break;
428 case W_POINTS:
429 ship->file->points = a;
430 break;
431 case W_QUAL:
432 ship->specs->qual = a;
433 break;
434 case W_RIGG: {
435 struct shipspecs *s = ship->specs;
436 s->rig1 = a;
437 s->rig2 = b;
438 s->rig3 = c;
439 s->rig4 = d;
440 break;
441 }
442 case W_RIG1:
443 ship->specs->rig1 = a;
444 break;
445 case W_RIG2:
446 ship->specs->rig2 = a;
447 break;
448 case W_RIG3:
449 ship->specs->rig3 = a;
450 break;
451 case W_RIG4:
452 ship->specs->rig4 = a;
453 break;
454 case W_COL:
455 ship->file->col = a;
456 break;
457 case W_DIR:
458 ship->file->dir = a;
459 break;
460 case W_ROW:
461 ship->file->row = a;
462 break;
463 case W_SINK:
464 if ((ship->file->sink = a) == 2)
465 ship->file->dir = 0;
466 break;
467 case W_STRUCK:
468 ship->file->struck = a;
469 break;
470 case W_TA:
471 ship->specs->ta = a;
472 break;
473 case W_ALIVE:
474 alive = 1;
475 break;
476 case W_TURN:
477 turn = a;
478 break;
479 case W_WIND:
480 winddir = a;
481 windspeed = b;
482 break;
483 case W_BEGIN:
484 strcpy(ship->file->captain, "begin");
485 people++;
486 break;
487 case W_END:
488 *ship->file->captain = 0;
489 ship->file->points = 0;
490 people--;
491 break;
492 case W_DDEAD:
493 hasdriver = 0;
494 break;
495 default:
496 fprintf(stderr, "sync_update: unknown type %d\r\n", type);
497 return -1;
498 }
499 return 0;
500 }