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