1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
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
40:
41: #include <sys/file.h>
42: #include <sys/stat.h>
43:
44: #include <fcntl.h>
45: #include <errno.h>
46: #include <signal.h>
47: #include <stdarg.h>
48: #include <stdio.h>
49: #include <stdlib.h>
50: #include <string.h>
51: #include <time.h>
52: #include <unistd.h>
53: #include "extern.h"
54: #include "pathnames.h"
55:
56: #define BUFSIZE 4096
57:
58: static int sync_update(int, struct ship *, const char *, long, long, long, long);
59:
60: static const char SF[] = _PATH_SYNC;
61: static const char LF[] = _PATH_LOCK;
62: static char sync_buf[BUFSIZE];
63: static char *sync_bp = sync_buf;
64: static char sync_lock[sizeof SF];
65: static char sync_file[sizeof LF];
66: static long sync_seek;
67: static FILE *sync_fp;
68:
69: void
70: fmtship(char *buf, size_t len, const char *fmt, struct ship *ship)
71: {
72: while (*fmt) {
73: if (len-- == 0) {
74: *buf = '\0';
75: return;
76: }
77: if (*fmt == '$' && fmt[1] == '$') {
78: size_t l = snprintf(buf, len, "%s (%c%c)",
79: ship->shipname, colours(ship), sterncolour(ship));
80: buf += l;
81: len -= l - 1;
82: fmt += 2;
83: }
84: else
85: *buf++ = *fmt++;
86: }
87:
88: if (len > 0)
89: *buf = '\0';
90: }
91:
92:
93:
94: void
95: makesignal(struct ship *from, const char *fmt, struct ship *ship, ...)
96: {
97: char message[BUFSIZ];
98: char format[BUFSIZ];
99: va_list ap;
100:
101: va_start(ap, ship);
102: fmtship(format, sizeof(format), fmt, ship);
103: vsprintf(message, format, ap);
104: va_end(ap);
105: Writestr(W_SIGNAL, from, message);
106: }
107:
108:
109: void
110: makemsg(struct ship *from, const char *fmt, ...)
111: {
112: char message[BUFSIZ];
113: va_list ap;
114:
115: va_start(ap, fmt);
116: vsprintf(message, fmt, ap);
117: va_end(ap);
118: Writestr(W_SIGNAL, from, message);
119: }
120:
121: int
122: sync_exists(int game)
123: {
124: char buf[sizeof sync_file];
125: struct stat s;
126: time_t t;
127:
128: sprintf(buf, SF, game);
129: time(&t);
130: setegid(egid);
131: if (stat(buf, &s) < 0) {
132: setegid(gid);
133: return 0;
134: }
135: if (s.st_mtime < t - 60*60*2) {
136: unlink(buf);
137: sprintf(buf, LF, game);
138: unlink(buf);
139: setegid(gid);
140: return 0;
141: } else {
142: setegid(gid);
143: return 1;
144: }
145: }
146:
147: int
148: sync_open(void)
149: {
150: struct stat tmp;
151: if (sync_fp != NULL)
152: fclose(sync_fp);
153: sprintf(sync_lock, LF, game);
154: sprintf(sync_file, SF, game);
155: setegid(egid);
156: if (stat(sync_file, &tmp) < 0) {
157: mode_t omask = umask(002);
158: sync_fp = fopen(sync_file, "w+");
159: umask(omask);
160: } else
161: sync_fp = fopen(sync_file, "r+");
162: setegid(gid);
163: if (sync_fp == NULL)
164: return -1;
165: sync_seek = 0;
166: return 0;
167: }
168:
169: void
170: sync_close(int remove)
171: {
172: if (sync_fp != 0)
173: fclose(sync_fp);
174: if (remove) {
175: setegid(egid);
176: unlink(sync_file);
177: setegid(gid);
178: }
179: }
180:
181: void
182: Write(int type, struct ship *ship, long a, long b, long c, long d)
183: {
184:
185: sprintf(sync_bp, "%d %d 0 %ld %ld %ld %ld\n",
186: type, ship->file->index, a, b, c, d);
187: while (*sync_bp++)
188: ;
189: sync_bp--;
190: if (sync_bp >= &sync_buf[sizeof sync_buf])
191: abort();
192: sync_update(type, ship, NULL, a, b, c, d);
193: }
194:
195: void
196: Writestr(int type, struct ship *ship, const char *a)
197: {
198: sprintf(sync_bp, "%d %d 1 %s\n", type, ship->file->index, a);
199: while (*sync_bp++)
200: ;
201: sync_bp--;
202: if (sync_bp >= &sync_buf[sizeof sync_buf])
203: abort();
204: sync_update(type, ship, a, 0, 0, 0, 0);
205: }
206:
207: int
208: Sync(void)
209: {
210: sig_t sighup, sigint;
211: int n;
212: int type, shipnum, isstr;
213: char *astr;
214: long a, b, c, d;
215: char buf[80];
216: char erred = 0;
217:
218: sighup = signal(SIGHUP, SIG_IGN);
219: sigint = signal(SIGINT, SIG_IGN);
220: for (n = TIMEOUT; --n >= 0;) {
221: #ifdef LOCK_EX
222: if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0)
223: break;
224: if (errno != EWOULDBLOCK)
225: return -1;
226: #else
227: setegid(egid);
228: if (link(sync_file, sync_lock) >= 0) {
229: setegid(gid);
230: break;
231: }
232: setegid(gid);
233: if (errno != EEXIST)
234: return -1;
235: #endif
236: sleep(1);
237: }
238: if (n <= 0)
239: return -1;
240: fseek(sync_fp, sync_seek, SEEK_SET);
241: for (;;) {
242: switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) {
243: case 3:
244: break;
245: case EOF:
246: goto out;
247: default:
248: goto bad;
249: }
250: if (shipnum < 0 || shipnum >= cc->vessels)
251: goto bad;
252: if (isstr != 0 && isstr != 1)
253: goto bad;
254: if (isstr) {
255: char *p;
256: for (p = buf;;) {
257: switch (*p++ = getc(sync_fp)) {
258: case '\n':
259: p--;
260: case EOF:
261: break;
262: default:
263: if (p >= buf + sizeof buf)
264: p--;
265: continue;
266: }
267: break;
268: }
269: *p = 0;
270: for (p = buf; *p == ' '; p++)
271: ;
272: astr = p;
273: a = b = c = d = 0;
274: } else {
275: if (fscanf(sync_fp, "%ld%ld%ld%ld", &a, &b, &c, &d) != 4)
276: goto bad;
277: astr = NULL;
278: }
279: if (sync_update(type, SHIP(shipnum), astr, a, b, c, d) < 0)
280: goto bad;
281: }
282: bad:
283: erred++;
284: out:
285: if (!erred && sync_bp != sync_buf) {
286: fseek(sync_fp, 0L, SEEK_END);
287: fwrite(sync_buf, sizeof *sync_buf, sync_bp - sync_buf,
288: sync_fp);
289: fflush(sync_fp);
290: sync_bp = sync_buf;
291: }
292: sync_seek = ftell(sync_fp);
293: #ifdef LOCK_EX
294: flock(fileno(sync_fp), LOCK_UN);
295: #else
296: setegid(egid);
297: unlink(sync_lock);
298: setegid(gid);
299: #endif
300: signal(SIGHUP, sighup);
301: signal(SIGINT, sigint);
302: return erred ? -1 : 0;
303: }
304:
305: static int
306: sync_update(int type, struct ship *ship, const char *astr, long a, long b, long c, long d)
307: {
308: switch (type) {
309: case W_DBP: {
310: struct BP *p = &ship->file->DBP[a];
311: p->turnsent = b;
312: p->toship = SHIP(c);
313: p->mensent = d;
314: break;
315: }
316: case W_OBP: {
317: struct BP *p = &ship->file->OBP[a];
318: p->turnsent = b;
319: p->toship = SHIP(c);
320: p->mensent = d;
321: break;
322: }
323: case W_FOUL: {
324: struct snag *p = &ship->file->foul[a];
325: if (SHIP(a)->file->dir == 0)
326: break;
327: if (p->sn_count++ == 0)
328: p->sn_turn = turn;
329: ship->file->nfoul++;
330: break;
331: }
332: case W_GRAP: {
333: struct snag *p = &ship->file->grap[a];
334: if (SHIP(a)->file->dir == 0)
335: break;
336: if (p->sn_count++ == 0)
337: p->sn_turn = turn;
338: ship->file->ngrap++;
339: break;
340: }
341: case W_UNFOUL: {
342: struct snag *p = &ship->file->foul[a];
343: if (p->sn_count > 0) {
344: if (b) {
345: ship->file->nfoul -= p->sn_count;
346: p->sn_count = 0;
347: } else {
348: ship->file->nfoul--;
349: p->sn_count--;
350: }
351: }
352: break;
353: }
354: case W_UNGRAP: {
355: struct snag *p = &ship->file->grap[a];
356: if (p->sn_count > 0) {
357: if (b) {
358: ship->file->ngrap -= p->sn_count;
359: p->sn_count = 0;
360: } else {
361: ship->file->ngrap--;
362: p->sn_count--;
363: }
364: }
365: break;
366: }
367: case W_SIGNAL:
368: if (mode == MODE_PLAYER) {
369: if (nobells)
370: Signal("$$: %s", ship, astr);
371: else
372: Signal("\7$$: %s", ship, astr);
373: }
374: break;
375: case W_CREW: {
376: struct shipspecs *s = ship->specs;
377: s->crew1 = a;
378: s->crew2 = b;
379: s->crew3 = c;
380: break;
381: }
382: case W_CAPTAIN:
383: strlcpy(ship->file->captain, astr,
384: sizeof ship->file->captain);
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: strlcpy(ship->file->movebuf, astr,
422: sizeof ship->file->movebuf);
423: break;
424: case W_PCREW:
425: ship->file->pcrew = a;
426: break;
427: case W_POINTS:
428: ship->file->points = a;
429: break;
430: case W_QUAL:
431: ship->specs->qual = a;
432: break;
433: case W_RIGG: {
434: struct shipspecs *s = ship->specs;
435: s->rig1 = a;
436: s->rig2 = b;
437: s->rig3 = c;
438: s->rig4 = d;
439: break;
440: }
441: case W_RIG1:
442: ship->specs->rig1 = a;
443: break;
444: case W_RIG2:
445: ship->specs->rig2 = a;
446: break;
447: case W_RIG3:
448: ship->specs->rig3 = a;
449: break;
450: case W_RIG4:
451: ship->specs->rig4 = a;
452: break;
453: case W_COL:
454: ship->file->col = a;
455: break;
456: case W_DIR:
457: ship->file->dir = a;
458: break;
459: case W_ROW:
460: ship->file->row = a;
461: break;
462: case W_SINK:
463: if ((ship->file->sink = a) == 2)
464: ship->file->dir = 0;
465: break;
466: case W_STRUCK:
467: ship->file->struck = a;
468: break;
469: case W_TA:
470: ship->specs->ta = a;
471: break;
472: case W_ALIVE:
473: alive = 1;
474: break;
475: case W_TURN:
476: turn = a;
477: break;
478: case W_WIND:
479: winddir = a;
480: windspeed = b;
481: break;
482: case W_BEGIN:
483: strcpy(ship->file->captain, "begin");
484: people++;
485: break;
486: case W_END:
487: *ship->file->captain = 0;
488: ship->file->points = 0;
489: people--;
490: break;
491: case W_DDEAD:
492: hasdriver = 0;
493: break;
494: default:
495: fprintf(stderr, "sync_update: unknown type %d\r\n", type);
496: return -1;
497: }
498: return 0;
499: }