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