sync.c 9.8 KB

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