(linenum→info "unix/slp.c:2238")

bsd-games/2.17/sail/sync.c

    1: /*      $NetBSD: sync.c,v 1.23 2004/09/07 13:20:39 jrf 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. Neither the name of the University nor the names of its contributors
   16:  *    may be used to endorse or promote products derived from this software
   17:  *    without specific prior written permission.
   18:  *
   19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29:  * SUCH DAMAGE.
   30:  */
   31: 
   32: #include <sys/cdefs.h>
   33: #ifndef lint
   34: #if 0
   35: static char sccsid[] = "@(#)sync.c      8.2 (Berkeley) 4/28/95";
   36: #else
   37: __RCSID("$NetBSD: sync.c,v 1.23 2004/09/07 13:20:39 jrf Exp $");
   38: #endif
   39: #endif /* not lint */
   40: 
   41: #include <sys/file.h>
   42: #include <sys/stat.h>
   43: 
   44: #include <fcntl.h>
   45: #include <errno.h>
   46: #include <signal.h>
   47: #include <stdarg.h>
   48: #include <stdio.h>
   49: #include <stdlib.h>
   50: #include <string.h>
   51: #include <time.h>
   52: #include <unistd.h>
   53: #include "extern.h"
   54: #include "pathnames.h"
   55: 
   56: #define BUFSIZE 4096
   57: 
   58: static int      sync_update(int, struct ship *, const char *, long, long, long, long);
   59: 
   60: static const char SF[] = _PATH_SYNC;
   61: static const char LF[] = _PATH_LOCK;
   62: static char sync_buf[BUFSIZE];
   63: static char *sync_bp = sync_buf;
   64: static char sync_lock[sizeof SF];
   65: static char sync_file[sizeof LF];
   66: static long sync_seek;
   67: static FILE *sync_fp;
   68: 
   69: void
   70: fmtship(char *buf, size_t len, const char *fmt, struct ship *ship)
   71: {
   72:         while (*fmt) {
   73:                 if (len-- == 0) {
   74:                         *buf = '\0';
   75:                         return;
   76:                 }
   77:                 if (*fmt == '$' && fmt[1] == '$') {
   78:                         size_t l = snprintf(buf, len, "%s (%c%c)",
   79:                             ship->shipname, colours(ship), sterncolour(ship));
   80:                         buf += l;
   81:                         len -= l - 1;
   82:                         fmt += 2;
   83:                 }
   84:                 else
   85:                         *buf++ = *fmt++;
   86:         }
   87: 
   88:         if (len > 0)
   89:                 *buf = '\0';
   90: }
   91: 
   92: 
   93: /*VARARGS3*/
   94: void
   95: makesignal(struct ship *from, const char *fmt, struct ship *ship, ...)
   96: {
   97:         char message[BUFSIZ];
   98:         char format[BUFSIZ];
   99:         va_list ap;
  100: 
  101:         va_start(ap, ship);
  102:         fmtship(format, sizeof(format), fmt, ship);
  103:         vsprintf(message, format, ap);
  104:         va_end(ap);
  105:         Writestr(W_SIGNAL, from, message);
  106: }
  107: 
  108: /*VARARGS2*/
  109: void
  110: makemsg(struct ship *from, const char *fmt, ...)
  111: {
  112:         char message[BUFSIZ];
  113:         va_list ap;
  114: 
  115:         va_start(ap, fmt);
  116:         vsprintf(message, fmt, ap);
  117:         va_end(ap);
  118:         Writestr(W_SIGNAL, from, message);
  119: }
  120: 
  121: int
  122: sync_exists(int game)
  123: {
  124:         char buf[sizeof sync_file];
  125:         struct stat s;
  126:         time_t t;
  127: 
  128:         sprintf(buf, SF, game);
  129:         time(&t);
  130:         setegid(egid);
  131:         if (stat(buf, &s) < 0) {
  132:                 setegid(gid);
  133:                 return 0;
  134:         }
  135:         if (s.st_mtime < t - 60*60*2) {                /* 2 hours */
  136:                 unlink(buf);
  137:                 sprintf(buf, LF, game);
  138:                 unlink(buf);
  139:                 setegid(gid);
  140:                 return 0;
  141:         } else {
  142:                 setegid(gid);
  143:                 return 1;
  144:         }
  145: }
  146: 
  147: int
  148: sync_open(void)
  149: {
  150:         struct stat tmp;
  151:         if (sync_fp != NULL)
  152:                 fclose(sync_fp);
  153:         sprintf(sync_lock, LF, game);
  154:         sprintf(sync_file, SF, game);
  155:         setegid(egid);
  156:         if (stat(sync_file, &tmp) < 0) {
  157:                 mode_t omask = umask(002);
  158:                 sync_fp = fopen(sync_file, "w+");
  159:                 umask(omask);
  160:         } else
  161:                 sync_fp = fopen(sync_file, "r+");
  162:         setegid(gid);
  163:         if (sync_fp == NULL)
  164:                 return -1;
  165:         sync_seek = 0;
  166:         return 0;
  167: }
  168: 
  169: void
  170: sync_close(int remove)
  171: {
  172:         if (sync_fp != 0)
  173:                 fclose(sync_fp);
  174:         if (remove) {
  175:                 setegid(egid);
  176:                 unlink(sync_file);
  177:                 setegid(gid);
  178:         }
  179: }
  180: 
  181: void
  182: Write(int type, struct ship *ship, long a, long b, long c, long d)
  183: {
  184: 
  185:         sprintf(sync_bp, "%d %d 0 %ld %ld %ld %ld\n",
  186:                        type, ship->file->index, a, b, c, d);
  187:         while (*sync_bp++)
  188:                 ;
  189:         sync_bp--;
  190:         if (sync_bp >= &sync_buf[sizeof sync_buf])
  191:                 abort();
  192:         sync_update(type, ship, NULL, a, b, c, d);
  193: }
  194: 
  195: void
  196: Writestr(int type, struct ship *ship, const char *a)
  197: {
  198:         sprintf(sync_bp, "%d %d 1 %s\n", type, ship->file->index, a);
  199:         while (*sync_bp++)
  200:                 ;
  201:         sync_bp--;
  202:         if (sync_bp >= &sync_buf[sizeof sync_buf])
  203:                 abort();
  204:         sync_update(type, ship, a, 0, 0, 0, 0);
  205: }
  206: 
  207: int
  208: Sync(void)
  209: {
  210:         sig_t sighup, sigint;
  211:         int n;
  212:         int type, shipnum, isstr;
  213:         char *astr;
  214:         long a, b, c, d;
  215:         char buf[80];
  216:         char erred = 0;
  217: 
  218:         sighup = signal(SIGHUP, SIG_IGN);
  219:         sigint = signal(SIGINT, SIG_IGN);
  220:         for (n = TIMEOUT; --n >= 0;) {
  221: #ifdef LOCK_EX
  222:                 if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0)
  223:                         break;
  224:                 if (errno != EWOULDBLOCK)
  225:                         return -1;
  226: #else
  227:                 setegid(egid);
  228:                 if (link(sync_file, sync_lock) >= 0) {
  229:                         setegid(gid);
  230:                         break;
  231:                 }
  232:                 setegid(gid);
  233:                 if (errno != EEXIST)
  234:                         return -1;
  235: #endif
  236:                 sleep(1);
  237:         }
  238:         if (n <= 0)
  239:                 return -1;
  240:         fseek(sync_fp, sync_seek, SEEK_SET);
  241:         for (;;) {
  242:                 switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) {
  243:                 case 3:
  244:                         break;
  245:                 case EOF:
  246:                         goto out;
  247:                 default:
  248:                         goto bad;
  249:                 }
  250:                 if (shipnum < 0 || shipnum >= cc->vessels)
  251:                         goto bad;
  252:                 if (isstr != 0 && isstr != 1)
  253:                         goto bad;
  254:                 if (isstr) {
  255:                         char *p;
  256:                         for (p = buf;;) {
  257:                                 switch (*p++ = getc(sync_fp)) {
  258:                                 case '\n':
  259:                                         p--;
  260:                                 case EOF:
  261:                                         break;
  262:                                 default:
  263:                                         if (p >= buf + sizeof buf)
  264:                                                 p--;
  265:                                         continue;
  266:                                 }
  267:                                 break;
  268:                         }
  269:                         *p = 0;
  270:                         for (p = buf; *p == ' '; p++)
  271:                                 ;
  272:                         astr = p;
  273:                         a = b = c = d = 0;
  274:                 } else {
  275:                         if (fscanf(sync_fp, "%ld%ld%ld%ld", &a, &b, &c, &d) != 4)
  276:                                 goto bad;
  277:                         astr = NULL;
  278:                 }
  279:                 if (sync_update(type, SHIP(shipnum), astr, a, b, c, d) < 0)
  280:                         goto bad;
  281:         }
  282: bad:
  283:         erred++;
  284: out:
  285:         if (!erred && sync_bp != sync_buf) {
  286:                 fseek(sync_fp, 0L, SEEK_END);
  287:                 fwrite(sync_buf, sizeof *sync_buf, sync_bp - sync_buf,
  288:                         sync_fp);
  289:                 fflush(sync_fp);
  290:                 sync_bp = sync_buf;
  291:         }
  292:         sync_seek = ftell(sync_fp);
  293: #ifdef LOCK_EX
  294:         flock(fileno(sync_fp), LOCK_UN);
  295: #else
  296:         setegid(egid);
  297:         unlink(sync_lock);
  298:         setegid(gid);
  299: #endif
  300:         signal(SIGHUP, sighup);
  301:         signal(SIGINT, sigint);
  302:         return erred ? -1 : 0;
  303: }
  304: 
  305: static int
  306: sync_update(int type, struct ship *ship, const char *astr, long a, long b, long c, long d)
  307: {
  308:         switch (type) {
  309:         case W_DBP: {
  310:                 struct BP *p = &ship->file->DBP[a];
  311:                 p->turnsent = b;
  312:                 p->toship = SHIP(c);
  313:                 p->mensent = d;
  314:                 break;
  315:                 }
  316:         case W_OBP: {
  317:                 struct BP *p = &ship->file->OBP[a];
  318:                 p->turnsent = b;
  319:                 p->toship = SHIP(c);
  320:                 p->mensent = d;
  321:                 break;
  322:                 }
  323:         case W_FOUL: {
  324:                 struct snag *p = &ship->file->foul[a];
  325:                 if (SHIP(a)->file->dir == 0)
  326:                         break;
  327:                 if (p->sn_count++ == 0)
  328:                         p->sn_turn = turn;
  329:                 ship->file->nfoul++;
  330:                 break;
  331:                 }
  332:         case W_GRAP: {
  333:                 struct snag *p = &ship->file->grap[a];
  334:                 if (SHIP(a)->file->dir == 0)
  335:                         break;
  336:                 if (p->sn_count++ == 0)
  337:                         p->sn_turn = turn;
  338:                 ship->file->ngrap++;
  339:                 break;
  340:                 }
  341:         case W_UNFOUL: {
  342:                 struct snag *p = &ship->file->foul[a];
  343:                 if (p->sn_count > 0) {
  344:                         if (b) {
  345:                                 ship->file->nfoul -= p->sn_count;
  346:                                 p->sn_count = 0;
  347:                         } else {
  348:                                 ship->file->nfoul--;
  349:                                 p->sn_count--;
  350:                         }
  351:                 }
  352:                 break;
  353:                 }
  354:         case W_UNGRAP: {
  355:                 struct snag *p = &ship->file->grap[a];
  356:                 if (p->sn_count > 0) {
  357:                         if (b) {
  358:                                 ship->file->ngrap -= p->sn_count;
  359:                                 p->sn_count = 0;
  360:                         } else {
  361:                                 ship->file->ngrap--;
  362:                                 p->sn_count--;
  363:                         }
  364:                 }
  365:                 break;
  366:                 }
  367:         case W_SIGNAL:
  368:                 if (mode == MODE_PLAYER) {
  369:                         if (nobells)
  370:                                 Signal("$$: %s", ship, astr);
  371:                         else
  372:                                 Signal("\7$$: %s", ship, astr);
  373:                 }
  374:                 break;
  375:         case W_CREW: {
  376:                 struct shipspecs *s = ship->specs;
  377:                 s->crew1 = a;
  378:                 s->crew2 = b;
  379:                 s->crew3 = c;
  380:                 break;
  381:                 }
  382:         case W_CAPTAIN:
  383:                 strlcpy(ship->file->captain, astr,
  384:                         sizeof ship->file->captain);
  385:                 break;
  386:         case W_CAPTURED:
  387:                 if (a < 0)
  388:                         ship->file->captured = 0;
  389:                 else
  390:                         ship->file->captured = SHIP(a);
  391:                 break;
  392:         case W_CLASS:
  393:                 ship->specs->class = a;
  394:                 break;
  395:         case W_DRIFT:
  396:                 ship->file->drift = a;
  397:                 break;
  398:         case W_EXPLODE:
  399:                 if ((ship->file->explode = a) == 2)
  400:                         ship->file->dir = 0;
  401:                 break;
  402:         case W_FS:
  403:                 ship->file->FS = a;
  404:                 break;
  405:         case W_GUNL: {
  406:                 struct shipspecs *s = ship->specs;
  407:                 s->gunL = a;
  408:                 s->carL = b;
  409:                 break;
  410:                 }
  411:         case W_GUNR: {
  412:                 struct shipspecs *s = ship->specs;
  413:                 s->gunR = a;
  414:                 s->carR = b;
  415:                 break;
  416:                 }
  417:         case W_HULL:
  418:                 ship->specs->hull = a;
  419:                 break;
  420:         case W_MOVE:
  421:                 strlcpy(ship->file->movebuf, astr,
  422:                         sizeof ship->file->movebuf);
  423:                 break;
  424:         case W_PCREW:
  425:                 ship->file->pcrew = a;
  426:                 break;
  427:         case W_POINTS:
  428:                 ship->file->points = a;
  429:                 break;
  430:         case W_QUAL:
  431:                 ship->specs->qual = a;
  432:                 break;
  433:         case W_RIGG: {
  434:                 struct shipspecs *s = ship->specs;
  435:                 s->rig1 = a;
  436:                 s->rig2 = b;
  437:                 s->rig3 = c;
  438:                 s->rig4 = d;
  439:                 break;
  440:                 }
  441:         case W_RIG1:
  442:                 ship->specs->rig1 = a;
  443:                 break;
  444:         case W_RIG2:
  445:                 ship->specs->rig2 = a;
  446:                 break;
  447:         case W_RIG3:
  448:                 ship->specs->rig3 = a;
  449:                 break;
  450:         case W_RIG4:
  451:                 ship->specs->rig4 = a;
  452:                 break;
  453:         case W_COL:
  454:                 ship->file->col = a;
  455:                 break;
  456:         case W_DIR:
  457:                 ship->file->dir = a;
  458:                 break;
  459:         case W_ROW:
  460:                 ship->file->row = a;
  461:                 break;
  462:         case W_SINK:
  463:                 if ((ship->file->sink = a) == 2)
  464:                         ship->file->dir = 0;
  465:                 break;
  466:         case W_STRUCK:
  467:                 ship->file->struck = a;
  468:                 break;
  469:         case W_TA:
  470:                 ship->specs->ta = a;
  471:                 break;
  472:         case W_ALIVE:
  473:                 alive = 1;
  474:                 break;
  475:         case W_TURN:
  476:                 turn = a;
  477:                 break;
  478:         case W_WIND:
  479:                 winddir = a;
  480:                 windspeed = b;
  481:                 break;
  482:         case W_BEGIN:
  483:                 strcpy(ship->file->captain, "begin");
  484:                 people++;
  485:                 break;
  486:         case W_END:
  487:                 *ship->file->captain = 0;
  488:                 ship->file->points = 0;
  489:                 people--;
  490:                 break;
  491:         case W_DDEAD:
  492:                 hasdriver = 0;
  493:                 break;
  494:         default:
  495:                 fprintf(stderr, "sync_update: unknown type %d\r\n", type);
  496:                 return -1;
  497:         }
  498:         return 0;
  499: }
Syntax (Markdown)