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