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