123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- /* $NetBSD: sync.c,v 1.23 2004/09/07 13:20:39 jrf Exp $ */
- /*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #include <sys/cdefs.h>
- #ifndef lint
- #if 0
- static char sccsid[] = "@(#)sync.c 8.2 (Berkeley) 4/28/95";
- #else
- __RCSID("$NetBSD: sync.c,v 1.23 2004/09/07 13:20:39 jrf Exp $");
- #endif
- #endif /* not lint */
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <signal.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include "extern.h"
- #include "pathnames.h"
- #define BUFSIZE 4096
- static int sync_update(int, struct ship *, const char *, long, long, long, long);
- static const char SF[] = _PATH_SYNC;
- static const char LF[] = _PATH_LOCK;
- static char sync_buf[BUFSIZE];
- static char *sync_bp = sync_buf;
- static char sync_lock[sizeof SF];
- static char sync_file[sizeof LF];
- static long sync_seek;
- static FILE *sync_fp;
- void
- fmtship(char *buf, size_t len, const char *fmt, struct ship *ship)
- {
- while (*fmt) {
- if (len-- == 0) {
- *buf = '\0';
- return;
- }
- if (*fmt == '$' && fmt[1] == '$') {
- size_t l = snprintf(buf, len, "%s (%c%c)",
- ship->shipname, colours(ship), sterncolour(ship));
- buf += l;
- len -= l - 1;
- fmt += 2;
- }
- else
- *buf++ = *fmt++;
- }
- if (len > 0)
- *buf = '\0';
- }
- /*VARARGS3*/
- void
- makesignal(struct ship *from, const char *fmt, struct ship *ship, ...)
- {
- char message[BUFSIZ];
- char format[BUFSIZ];
- va_list ap;
- va_start(ap, ship);
- fmtship(format, sizeof(format), fmt, ship);
- vsprintf(message, format, ap);
- va_end(ap);
- Writestr(W_SIGNAL, from, message);
- }
- /*VARARGS2*/
- void
- makemsg(struct ship *from, const char *fmt, ...)
- {
- char message[BUFSIZ];
- va_list ap;
- va_start(ap, fmt);
- vsprintf(message, fmt, ap);
- va_end(ap);
- Writestr(W_SIGNAL, from, message);
- }
- int
- sync_exists(int game)
- {
- char buf[sizeof sync_file];
- struct stat s;
- time_t t;
- sprintf(buf, SF, game);
- time(&t);
- setegid(egid);
- if (stat(buf, &s) < 0) {
- setegid(gid);
- return 0;
- }
- if (s.st_mtime < t - 60*60*2) { /* 2 hours */
- unlink(buf);
- sprintf(buf, LF, game);
- unlink(buf);
- setegid(gid);
- return 0;
- } else {
- setegid(gid);
- return 1;
- }
- }
- int
- sync_open(void)
- {
- struct stat tmp;
- if (sync_fp != NULL)
- fclose(sync_fp);
- sprintf(sync_lock, LF, game);
- sprintf(sync_file, SF, game);
- setegid(egid);
- if (stat(sync_file, &tmp) < 0) {
- mode_t omask = umask(002);
- sync_fp = fopen(sync_file, "w+");
- umask(omask);
- } else
- sync_fp = fopen(sync_file, "r+");
- setegid(gid);
- if (sync_fp == NULL)
- return -1;
- sync_seek = 0;
- return 0;
- }
- void
- sync_close(int remove)
- {
- if (sync_fp != 0)
- fclose(sync_fp);
- if (remove) {
- setegid(egid);
- unlink(sync_file);
- setegid(gid);
- }
- }
- void
- Write(int type, struct ship *ship, long a, long b, long c, long d)
- {
- sprintf(sync_bp, "%d %d 0 %ld %ld %ld %ld\n",
- type, ship->file->index, a, b, c, d);
- while (*sync_bp++)
- ;
- sync_bp--;
- if (sync_bp >= &sync_buf[sizeof sync_buf])
- abort();
- sync_update(type, ship, NULL, a, b, c, d);
- }
- void
- Writestr(int type, struct ship *ship, const char *a)
- {
- sprintf(sync_bp, "%d %d 1 %s\n", type, ship->file->index, a);
- while (*sync_bp++)
- ;
- sync_bp--;
- if (sync_bp >= &sync_buf[sizeof sync_buf])
- abort();
- sync_update(type, ship, a, 0, 0, 0, 0);
- }
- int
- Sync(void)
- {
- sig_t sighup, sigint;
- int n;
- int type, shipnum, isstr;
- char *astr;
- long a, b, c, d;
- char buf[80];
- char erred = 0;
- sighup = signal(SIGHUP, SIG_IGN);
- sigint = signal(SIGINT, SIG_IGN);
- for (n = TIMEOUT; --n >= 0;) {
- #ifdef LOCK_EX
- if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0)
- break;
- if (errno != EWOULDBLOCK)
- return -1;
- #else
- setegid(egid);
- if (link(sync_file, sync_lock) >= 0) {
- setegid(gid);
- break;
- }
- setegid(gid);
- if (errno != EEXIST)
- return -1;
- #endif
- sleep(1);
- }
- if (n <= 0)
- return -1;
- fseek(sync_fp, sync_seek, SEEK_SET);
- for (;;) {
- switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) {
- case 3:
- break;
- case EOF:
- goto out;
- default:
- goto bad;
- }
- if (shipnum < 0 || shipnum >= cc->vessels)
- goto bad;
- if (isstr != 0 && isstr != 1)
- goto bad;
- if (isstr) {
- char *p;
- for (p = buf;;) {
- switch (*p++ = getc(sync_fp)) {
- case '\n':
- p--;
- case EOF:
- break;
- default:
- if (p >= buf + sizeof buf)
- p--;
- continue;
- }
- break;
- }
- *p = 0;
- for (p = buf; *p == ' '; p++)
- ;
- astr = p;
- a = b = c = d = 0;
- } else {
- if (fscanf(sync_fp, "%ld%ld%ld%ld", &a, &b, &c, &d) != 4)
- goto bad;
- astr = NULL;
- }
- if (sync_update(type, SHIP(shipnum), astr, a, b, c, d) < 0)
- goto bad;
- }
- bad:
- erred++;
- out:
- if (!erred && sync_bp != sync_buf) {
- fseek(sync_fp, 0L, SEEK_END);
- fwrite(sync_buf, sizeof *sync_buf, sync_bp - sync_buf,
- sync_fp);
- fflush(sync_fp);
- sync_bp = sync_buf;
- }
- sync_seek = ftell(sync_fp);
- #ifdef LOCK_EX
- flock(fileno(sync_fp), LOCK_UN);
- #else
- setegid(egid);
- unlink(sync_lock);
- setegid(gid);
- #endif
- signal(SIGHUP, sighup);
- signal(SIGINT, sigint);
- return erred ? -1 : 0;
- }
- static int
- sync_update(int type, struct ship *ship, const char *astr, long a, long b, long c, long d)
- {
- switch (type) {
- case W_DBP: {
- struct BP *p = &ship->file->DBP[a];
- p->turnsent = b;
- p->toship = SHIP(c);
- p->mensent = d;
- break;
- }
- case W_OBP: {
- struct BP *p = &ship->file->OBP[a];
- p->turnsent = b;
- p->toship = SHIP(c);
- p->mensent = d;
- break;
- }
- case W_FOUL: {
- struct snag *p = &ship->file->foul[a];
- if (SHIP(a)->file->dir == 0)
- break;
- if (p->sn_count++ == 0)
- p->sn_turn = turn;
- ship->file->nfoul++;
- break;
- }
- case W_GRAP: {
- struct snag *p = &ship->file->grap[a];
- if (SHIP(a)->file->dir == 0)
- break;
- if (p->sn_count++ == 0)
- p->sn_turn = turn;
- ship->file->ngrap++;
- break;
- }
- case W_UNFOUL: {
- struct snag *p = &ship->file->foul[a];
- if (p->sn_count > 0) {
- if (b) {
- ship->file->nfoul -= p->sn_count;
- p->sn_count = 0;
- } else {
- ship->file->nfoul--;
- p->sn_count--;
- }
- }
- break;
- }
- case W_UNGRAP: {
- struct snag *p = &ship->file->grap[a];
- if (p->sn_count > 0) {
- if (b) {
- ship->file->ngrap -= p->sn_count;
- p->sn_count = 0;
- } else {
- ship->file->ngrap--;
- p->sn_count--;
- }
- }
- break;
- }
- case W_SIGNAL:
- if (mode == MODE_PLAYER) {
- if (nobells)
- Signal("$$: %s", ship, astr);
- else
- Signal("\7$$: %s", ship, astr);
- }
- break;
- case W_CREW: {
- struct shipspecs *s = ship->specs;
- s->crew1 = a;
- s->crew2 = b;
- s->crew3 = c;
- break;
- }
- case W_CAPTAIN:
- strlcpy(ship->file->captain, astr,
- sizeof ship->file->captain);
- break;
- case W_CAPTURED:
- if (a < 0)
- ship->file->captured = 0;
- else
- ship->file->captured = SHIP(a);
- break;
- case W_CLASS:
- ship->specs->class = a;
- break;
- case W_DRIFT:
- ship->file->drift = a;
- break;
- case W_EXPLODE:
- if ((ship->file->explode = a) == 2)
- ship->file->dir = 0;
- break;
- case W_FS:
- ship->file->FS = a;
- break;
- case W_GUNL: {
- struct shipspecs *s = ship->specs;
- s->gunL = a;
- s->carL = b;
- break;
- }
- case W_GUNR: {
- struct shipspecs *s = ship->specs;
- s->gunR = a;
- s->carR = b;
- break;
- }
- case W_HULL:
- ship->specs->hull = a;
- break;
- case W_MOVE:
- strlcpy(ship->file->movebuf, astr,
- sizeof ship->file->movebuf);
- break;
- case W_PCREW:
- ship->file->pcrew = a;
- break;
- case W_POINTS:
- ship->file->points = a;
- break;
- case W_QUAL:
- ship->specs->qual = a;
- break;
- case W_RIGG: {
- struct shipspecs *s = ship->specs;
- s->rig1 = a;
- s->rig2 = b;
- s->rig3 = c;
- s->rig4 = d;
- break;
- }
- case W_RIG1:
- ship->specs->rig1 = a;
- break;
- case W_RIG2:
- ship->specs->rig2 = a;
- break;
- case W_RIG3:
- ship->specs->rig3 = a;
- break;
- case W_RIG4:
- ship->specs->rig4 = a;
- break;
- case W_COL:
- ship->file->col = a;
- break;
- case W_DIR:
- ship->file->dir = a;
- break;
- case W_ROW:
- ship->file->row = a;
- break;
- case W_SINK:
- if ((ship->file->sink = a) == 2)
- ship->file->dir = 0;
- break;
- case W_STRUCK:
- ship->file->struck = a;
- break;
- case W_TA:
- ship->specs->ta = a;
- break;
- case W_ALIVE:
- alive = 1;
- break;
- case W_TURN:
- turn = a;
- break;
- case W_WIND:
- winddir = a;
- windspeed = b;
- break;
- case W_BEGIN:
- strcpy(ship->file->captain, "begin");
- people++;
- break;
- case W_END:
- *ship->file->captain = 0;
- ship->file->points = 0;
- people--;
- break;
- case W_DDEAD:
- hasdriver = 0;
- break;
- default:
- fprintf(stderr, "sync_update: unknown type %d\r\n", type);
- return -1;
- }
- return 0;
- }
|