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