xref: /csrg-svn/games/sail/sync.c (revision 18706)
1*18706Sedward /*
2*18706Sedward  * Copyright (c) 1983 Regents of the University of California,
3*18706Sedward  * All rights reserved.  Redistribution permitted subject to
4*18706Sedward  * the terms of the Berkeley Software License Agreement.
5*18706Sedward  */
6*18706Sedward 
715207Sedward #ifndef lint
8*18706Sedward static	char *sccsid = "@(#)sync.c	2.10 85/04/23";
915207Sedward #endif
1015207Sedward 
1115207Sedward #include "externs.h"
1216081Sedward #include <sys/file.h>
1316081Sedward #include <sys/errno.h>
1415207Sedward 
1518249Sedward #define BUFSIZE 4096
1618249Sedward 
1715207Sedward static char sync_buf[BUFSIZE];
1815901Sedward static char *sync_bp = sync_buf;
1915207Sedward static char sync_lock[25];
2015207Sedward static char sync_file[25];
2115207Sedward static long sync_seek;
2215207Sedward static FILE *sync_fp;
2315207Sedward #define SF "/tmp/#sailsink.%d"
2415207Sedward #define LF "/tmp/#saillock.%d"
2515207Sedward 
2615207Sedward /*VARARGS3*/
2715207Sedward makesignal(from, fmt, ship, a, b, c)
2818249Sedward 	struct ship *from;
2918249Sedward 	char *fmt;
3018249Sedward 	register struct ship *ship;
3115207Sedward {
3215207Sedward 	char message[80];
3315207Sedward 
3415207Sedward 	if (ship == 0)
3515207Sedward 		(void) sprintf(message, fmt, a, b, c);
3615207Sedward 	else
3715207Sedward 		(void) sprintf(message, fmt,
3815207Sedward 			ship->shipname, colours(ship),
3915207Sedward 			sterncolour(ship), a, b, c);
4015207Sedward 	Write(W_SIGNAL, from, 1, (int)message, 0, 0, 0);
4115207Sedward }
4215207Sedward 
4315312Sedward #include <sys/types.h>
4415312Sedward #include <sys/stat.h>
4515207Sedward sync_exists(game)
4615207Sedward {
4715207Sedward 	char buf[sizeof sync_file];
4815312Sedward 	struct stat s;
4915312Sedward 	time_t t;
5015207Sedward 
5115207Sedward 	(void) sprintf(buf, SF, game);
5215723Sedward 	(void) time(&t);
5315312Sedward 	if (stat(buf, &s) < 0)
5415312Sedward 		return 0;
5515312Sedward 	if (s.st_mtime < t - 60*60*2) {		/* 2 hours */
5615723Sedward 		(void) unlink(buf);
5716081Sedward 		(void) sprintf(buf, LF, game);
5816081Sedward 		(void) unlink(buf);
5915312Sedward 		return 0;
6015312Sedward 	} else
6115312Sedward 		return 1;
6215207Sedward }
6315207Sedward 
6415207Sedward sync_open()
6515207Sedward {
6618590Sedward 	if (sync_fp != NULL)
6718590Sedward 		(void) fclose(sync_fp);
6818590Sedward 	(void) sprintf(sync_lock, LF, game);
6918590Sedward 	(void) sprintf(sync_file, SF, game);
7018590Sedward 	if (access(sync_file, 0) < 0) {
7118590Sedward 		int omask = umask(issetuid ? 077 : 011);
7218590Sedward 		sync_fp = fopen(sync_file, "w+");
7318590Sedward 		(void) umask(omask);
7418590Sedward 	} else
7518590Sedward 		sync_fp = fopen(sync_file, "r+");
7618590Sedward 	if (sync_fp == NULL)
7718590Sedward 		return -1;
7815207Sedward 	sync_seek == 0;
7915249Sedward 	return 0;
8015207Sedward }
8115207Sedward 
8215207Sedward sync_close(remove)
8318249Sedward 	char remove;
8415207Sedward {
8515352Sedward 	if (sync_fp != 0)
8615352Sedward 		(void) fclose(sync_fp);
8715207Sedward 	if (remove)
8815207Sedward 		(void) unlink(sync_file);
8915207Sedward }
9015207Sedward 
9115207Sedward Write(type, ship, isstr, a, b, c, d)
9218249Sedward 	int type;
9318249Sedward 	struct ship *ship;
9418249Sedward 	char isstr;
9518249Sedward 	int a, b, c, d;
9615207Sedward {
9715207Sedward 	if (isstr)
9815901Sedward 		(void) sprintf(sync_bp, "%d %d %d %s\n",
9915723Sedward 			type, ship->file->index, isstr, a);
10015207Sedward 	else
10115901Sedward 		(void) sprintf(sync_bp, "%d %d %d %d %d %d %d\n",
10215723Sedward 			type, ship->file->index, isstr, a, b, c, d);
10315901Sedward 	while (*sync_bp++)
10415207Sedward 		;
10515901Sedward 	sync_bp--;
10615901Sedward 	if (sync_bp >= &sync_buf[sizeof sync_buf])
10715207Sedward 		abort();
10816081Sedward 	(void) sync_update(type, ship, a, b, c, d);
10915207Sedward }
11015207Sedward 
11115207Sedward Sync()
11215207Sedward {
11315207Sedward 	int (*sig1)(), (*sig2)();
11416425Sedward 	register n;
11515207Sedward 	int type, shipnum, isstr, a, b, c, d;
11616081Sedward 	char buf[80];
11716081Sedward 	char erred = 0;
11816081Sedward 	extern errno;
11915207Sedward 
12015207Sedward 	sig1 = signal(SIGHUP, SIG_IGN);
12115207Sedward 	sig2 = signal(SIGINT, SIG_IGN);
12216425Sedward 	for (n = TIMEOUT; --n >= 0;) {
12316081Sedward #ifdef LOCK_EX
12416081Sedward 		if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0)
12516081Sedward 			break;
12616081Sedward 		if (errno != EWOULDBLOCK)
12716081Sedward 			return -1;
12816081Sedward #else
12916081Sedward 		if (link(sync_file, sync_lock) >= 0)
13016081Sedward 			break;
13116081Sedward 		if (errno != EEXIST)
13216081Sedward 			return -1;
13316081Sedward #endif
13416425Sedward 		sleep(1);
13516081Sedward 	}
13616425Sedward 	if (n <= 0)
13716081Sedward 		return -1;
13815207Sedward 	(void) fseek(sync_fp, sync_seek, 0);
13916081Sedward 	for (;;) {
14016081Sedward 		switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) {
14116081Sedward 		case 3:
14216081Sedward 			break;
14316081Sedward 		case EOF:
14416081Sedward 			goto out;
14516081Sedward 		default:
14616081Sedward 			goto bad;
14716081Sedward 		}
14816081Sedward 		if (shipnum < 0 || shipnum >= cc->vessels)
14916081Sedward 			goto bad;
15016081Sedward 		if (isstr != 0 && isstr != 1)
15116081Sedward 			goto bad;
15215207Sedward 		if (isstr) {
15316081Sedward 			register char *p;
15415207Sedward 			for (p = buf;;) {
15515207Sedward 				switch (*p++ = getc(sync_fp)) {
15615207Sedward 				case '\n':
15715207Sedward 					p--;
15815207Sedward 				case EOF:
15915207Sedward 					break;
16015207Sedward 				default:
16116081Sedward 					if (p >= buf + sizeof buf)
16216081Sedward 						p--;
16315207Sedward 					continue;
16415207Sedward 				}
16515207Sedward 				break;
16615207Sedward 			}
16715207Sedward 			*p = 0;
16815207Sedward 			for (p = buf; *p == ' '; p++)
16915207Sedward 				;
17015207Sedward 			a = (int)p;
17115207Sedward 			b = c = d = 0;
17215207Sedward 		} else
17316081Sedward 			if (fscanf(sync_fp, "%d%d%d%d", &a, &b, &c, &d) != 4)
17416081Sedward 				goto bad;
17516081Sedward 		if (sync_update(type, SHIP(shipnum), a, b, c, d) < 0)
17616081Sedward 			goto bad;
17715207Sedward 	}
17816081Sedward bad:
17916081Sedward 	erred++;
18016081Sedward out:
18116081Sedward 	if (!erred && sync_bp != sync_buf) {
18215207Sedward 		(void) fseek(sync_fp, 0L, 2);
18315207Sedward 		(void) fputs(sync_buf, sync_fp);
18415207Sedward 		(void) fflush(sync_fp);
18515901Sedward 		sync_bp = sync_buf;
18615207Sedward 	}
18715207Sedward 	sync_seek = ftell(sync_fp);
18816081Sedward #ifdef LOCK_EX
18916081Sedward 	(void) flock(fileno(sync_fp), LOCK_UN);
19016081Sedward #else
19115207Sedward 	(void) unlink(sync_lock);
19216081Sedward #endif
19315207Sedward 	(void) signal(SIGHUP, sig1);
19415207Sedward 	(void) signal(SIGINT, sig2);
19516081Sedward 	return erred ? -1 : 0;
19615207Sedward }
19715207Sedward 
19815207Sedward sync_update(type, ship, a, b, c, d)
19918249Sedward 	int type;
20018249Sedward 	register struct ship *ship;
20118249Sedward 	int a, b, c, d;
20215207Sedward {
20315207Sedward 	switch (type) {
20415207Sedward 	case W_DBP: {
20515207Sedward 		register struct BP *p = &ship->file->DBP[a];
20615207Sedward 		p->turnsent = b;
20715207Sedward 		p->toship = SHIP(c);
20815207Sedward 		p->mensent = d;
20915207Sedward 		break;
21015207Sedward 		}
21115207Sedward 	case W_OBP: {
21215207Sedward 		register struct BP *p = &ship->file->OBP[a];
21315207Sedward 		p->turnsent = b;
21415207Sedward 		p->toship = SHIP(c);
21515207Sedward 		p->mensent = d;
21615207Sedward 		break;
21715207Sedward 		}
21815207Sedward 	case W_FOUL: {
21915723Sedward 		register struct snag *p = &ship->file->foul[a];
22015723Sedward 		if (SHIP(a)->file->dir == 0)
22115723Sedward 			break;
22215723Sedward 		if (p->sn_count++ == 0)
22315723Sedward 			p->sn_turn = turn;
22415723Sedward 		ship->file->nfoul++;
22515207Sedward 		break;
22615207Sedward 		}
22715207Sedward 	case W_GRAP: {
22815723Sedward 		register struct snag *p = &ship->file->grap[a];
22915723Sedward 		if (SHIP(a)->file->dir == 0)
23015723Sedward 			break;
23115723Sedward 		if (p->sn_count++ == 0)
23215723Sedward 			p->sn_turn = turn;
23315723Sedward 		ship->file->ngrap++;
23415207Sedward 		break;
23515207Sedward 		}
23615723Sedward 	case W_UNFOUL: {
23715723Sedward 		register struct snag *p = &ship->file->foul[a];
23815723Sedward 		if (p->sn_count > 0)
23915723Sedward 			if (b) {
24015723Sedward 				ship->file->nfoul -= p->sn_count;
24115723Sedward 				p->sn_count = 0;
24215723Sedward 			} else {
24315723Sedward 				ship->file->nfoul--;
24415723Sedward 				p->sn_count--;
24515723Sedward 			}
24615723Sedward 		break;
24715723Sedward 		}
24815723Sedward 	case W_UNGRAP: {
24915723Sedward 		register struct snag *p = &ship->file->grap[a];
25015723Sedward 		if (p->sn_count > 0)
25115723Sedward 			if (b) {
25215723Sedward 				ship->file->ngrap -= p->sn_count;
25315723Sedward 				p->sn_count = 0;
25415723Sedward 			} else {
25515723Sedward 				ship->file->ngrap--;
25615723Sedward 				p->sn_count--;
25715723Sedward 			}
25815723Sedward 		break;
25915723Sedward 		}
26015207Sedward 	case W_SIGNAL:
26118249Sedward 		if (mode == MODE_PLAYER)
26218670Sedward 			if (nobells)
26318670Sedward 				Signal("%s (%c%c): %s", ship, a);
26418670Sedward 			else
26518670Sedward 				Signal("\7%s (%c%c): %s", ship, a);
26615207Sedward 		break;
26715207Sedward 	case W_CREW: {
26815207Sedward 		register struct shipspecs *s = ship->specs;
26915207Sedward 		s->crew1 = a;
27015207Sedward 		s->crew2 = b;
27115207Sedward 		s->crew3 = c;
27215207Sedward 		break;
27315207Sedward 		}
27415207Sedward 	case W_CAPTAIN:
27515207Sedward 		(void) strncpy(ship->file->captain, (char *)a,
27615207Sedward 			sizeof ship->file->captain - 1);
27715207Sedward 		ship->file->captain[sizeof ship->file->captain - 1] = 0;
27815207Sedward 		break;
27915207Sedward 	case W_CAPTURED:
28015315Sedward 		if (a < 0)
28115315Sedward 			ship->file->captured = 0;
28215315Sedward 		else
28315315Sedward 			ship->file->captured = SHIP(a);
28415207Sedward 		break;
28515207Sedward 	case W_CLASS:
28615207Sedward 		ship->specs->class = a;
28715207Sedward 		break;
28815207Sedward 	case W_DRIFT:
28915207Sedward 		ship->file->drift = a;
29015207Sedward 		break;
29115207Sedward 	case W_EXPLODE:
29215207Sedward 		if ((ship->file->explode = a) == 2)
29315207Sedward 			ship->file->dir = 0;
29415207Sedward 		break;
29515207Sedward 	case W_FS:
29615207Sedward 		ship->file->FS = a;
29715207Sedward 		break;
29815207Sedward 	case W_GUNL: {
29915207Sedward 		register struct shipspecs *s = ship->specs;
30015207Sedward 		s->gunL = a;
30115207Sedward 		s->carL = b;
30215207Sedward 		break;
30315207Sedward 		}
30415207Sedward 	case W_GUNR: {
30515207Sedward 		register struct shipspecs *s = ship->specs;
30615207Sedward 		s->gunR = a;
30715207Sedward 		s->carR = b;
30815207Sedward 		break;
30915207Sedward 		}
31015207Sedward 	case W_HULL:
31115207Sedward 		ship->specs->hull = a;
31215207Sedward 		break;
31315723Sedward 	case W_MOVE:
31415723Sedward 		(void) strncpy(ship->file->movebuf, (char *)a,
31515723Sedward 			sizeof ship->file->movebuf - 1);
31615723Sedward 		ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0;
31715207Sedward 		break;
31815207Sedward 	case W_PCREW:
31915207Sedward 		ship->file->pcrew = a;
32015207Sedward 		break;
32115207Sedward 	case W_POINTS:
32215207Sedward 		ship->file->points = a;
32315207Sedward 		break;
32415207Sedward 	case W_QUAL:
32515207Sedward 		ship->specs->qual = a;
32615207Sedward 		break;
32715207Sedward 	case W_RIGG: {
32815207Sedward 		register struct shipspecs *s = ship->specs;
32915207Sedward 		s->rig1 = a;
33015207Sedward 		s->rig2 = b;
33115207Sedward 		s->rig3 = c;
33215207Sedward 		s->rig4 = d;
33315207Sedward 		break;
33415207Sedward 		}
33515207Sedward 	case W_RIG1:
33615207Sedward 		ship->specs->rig1 = a;
33715207Sedward 		break;
33815207Sedward 	case W_RIG2:
33915207Sedward 		ship->specs->rig2 = a;
34015207Sedward 		break;
34115207Sedward 	case W_RIG3:
34215207Sedward 		ship->specs->rig3 = a;
34315207Sedward 		break;
34415207Sedward 	case W_RIG4:
34515207Sedward 		ship->specs->rig4 = a;
34615207Sedward 		break;
34715723Sedward 	case W_COL:
34815207Sedward 		ship->file->col = a;
34915207Sedward 		break;
35015723Sedward 	case W_DIR:
35115207Sedward 		ship->file->dir = a;
35215207Sedward 		break;
35315723Sedward 	case W_ROW:
35415207Sedward 		ship->file->row = a;
35515207Sedward 		break;
35615207Sedward 	case W_SINK:
35715207Sedward 		if ((ship->file->sink = a) == 2)
35815207Sedward 			ship->file->dir = 0;
35915207Sedward 		break;
36015207Sedward 	case W_STRUCK:
36115207Sedward 		ship->file->struck = a;
36215207Sedward 		break;
36315207Sedward 	case W_TA:
36415207Sedward 		ship->specs->ta = a;
36515207Sedward 		break;
36615207Sedward 	case W_ALIVE:
36715207Sedward 		alive = 1;
36815207Sedward 		break;
36915207Sedward 	case W_TURN:
37015207Sedward 		turn = a;
37115207Sedward 		break;
37215207Sedward 	case W_WIND:
37315207Sedward 		winddir = a;
37415207Sedward 		windspeed = b;
37515207Sedward 		break;
37615207Sedward 	case W_BEGIN:
37715207Sedward 		(void) strcpy(ship->file->captain, "begin");
37815207Sedward 		people++;
37915207Sedward 		break;
38015207Sedward 	case W_END:
38116081Sedward 		*ship->file->captain = 0;
38216081Sedward 		ship->file->points = 0;
38315207Sedward 		people--;
38415207Sedward 		break;
38516081Sedward 	case W_DDEAD:
38616081Sedward 		hasdriver = 0;
38716081Sedward 		break;
38815207Sedward 	default:
38916081Sedward 		fprintf(stderr, "sync_update: unknown type %d\r\n", type);
39016081Sedward 		return -1;
39115207Sedward 	}
39216081Sedward 	return 0;
39315207Sedward }
394