1 /* $NetBSD: sync.c,v 1.32 2009/03/14 23:12:20 dholland Exp $ */
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)sync.c 8.2 (Berkeley) 4/28/95";
37 __RCSID("$NetBSD: sync.c,v 1.32 2009/03/14 23:12:20 dholland Exp $");
54 #include "pathnames.h"
66 /* W_FILE 8 not used */
100 static void recv_captain(struct ship
*ship
, const char *astr
);
101 static void recv_captured(struct ship
*ship
, long a
);
102 static void recv_class(struct ship
*ship
, long a
);
103 static void recv_crew(struct ship
*ship
, long a
, long b
, long c
);
104 static void recv_dbp(struct ship
*ship
, long a
, long b
, long c
, long d
);
105 static void recv_drift(struct ship
*ship
, long a
);
106 static void recv_explode(struct ship
*ship
, long a
);
107 static void recv_foul(struct ship
*ship
, long a
);
108 static void recv_gunl(struct ship
*ship
, long a
, long b
);
109 static void recv_gunr(struct ship
*ship
, long a
, long b
);
110 static void recv_hull(struct ship
*ship
, long a
);
111 static void recv_move(struct ship
*ship
, const char *astr
);
112 static void recv_obp(struct ship
*ship
, long a
, long b
, long c
, long d
);
113 static void recv_pcrew(struct ship
*ship
, long a
);
114 static void recv_unfoul(struct ship
*ship
, long a
, long b
);
115 static void recv_points(struct ship
*ship
, long a
);
116 static void recv_qual(struct ship
*ship
, long a
);
117 static void recv_ungrap(struct ship
*ship
, long a
, long b
);
118 static void recv_rigg(struct ship
*ship
, long a
, long b
, long c
, long d
);
119 static void recv_col(struct ship
*ship
, long a
);
120 static void recv_dir(struct ship
*ship
, long a
);
121 static void recv_row(struct ship
*ship
, long a
);
122 static void recv_signal(struct ship
*ship
, const char *astr
);
123 static void recv_sink(struct ship
*ship
, long a
);
124 static void recv_struck(struct ship
*ship
, long a
);
125 static void recv_ta(struct ship
*ship
, long a
);
126 static void recv_alive(void);
127 static void recv_turn(long a
);
128 static void recv_wind(long a
, long b
);
129 static void recv_fs(struct ship
*ship
, long a
);
130 static void recv_grap(struct ship
*ship
, long a
);
131 static void recv_rig1(struct ship
*ship
, long a
);
132 static void recv_rig2(struct ship
*ship
, long a
);
133 static void recv_rig3(struct ship
*ship
, long a
);
134 static void recv_rig4(struct ship
*ship
, long a
);
135 static void recv_begin(struct ship
*ship
);
136 static void recv_end(struct ship
*ship
);
137 static void recv_ddead(void);
139 static void Write(int, struct ship
*, long, long, long, long);
140 static void Writestr(int, struct ship
*, const char *);
142 static int sync_update(int, struct ship
*, const char *,
143 long, long, long, long);
145 static char sync_buf
[BUFSIZE
];
146 static char *sync_bp
= sync_buf
;
147 static long sync_seek
;
148 static FILE *sync_fp
;
151 get_sync_file(int scenario_number
)
153 static char sync_file
[NAME_MAX
];
155 snprintf(sync_file
, sizeof(sync_file
), _FILE_SYNC
, scenario_number
);
160 get_lock_file(int scenario_number
)
162 static char sync_lock
[NAME_MAX
];
164 snprintf(sync_lock
, sizeof(sync_lock
), _FILE_LOCK
, scenario_number
);
169 fmtship(char *buf
, size_t len
, const char *fmt
, struct ship
*ship
)
176 if (*fmt
== '$' && fmt
[1] == '$') {
177 size_t l
= snprintf(buf
, len
, "%s (%c%c)",
178 ship
->shipname
, colours(ship
), sterncolour(ship
));
194 makesignal(struct ship
*from
, const char *fmt
, struct ship
*ship
, ...)
196 char message
[BUFSIZ
];
201 fmtship(format
, sizeof(format
), fmt
, ship
);
202 vsnprintf(message
, sizeof(message
), format
, ap
);
204 send_signal(from
, message
);
209 makemsg(struct ship
*from
, const char *fmt
, ...)
211 char message
[BUFSIZ
];
215 vsnprintf(message
, sizeof(message
), fmt
, ap
);
217 send_signal(from
, message
);
221 sync_exists(int gamenum
)
227 path
= get_sync_file(gamenum
);
230 if (stat(path
, &s
) < 0) {
234 if (s
.st_mtime
< t
- 60*60*2) { /* 2 hours */
236 path
= get_lock_file(gamenum
);
249 const char *sync_file
;
250 const char *sync_lock
;
255 sync_file
= get_sync_file(game
);
256 sync_lock
= get_lock_file(game
);
258 if (stat(sync_file
, &tmp
) < 0) {
259 mode_t omask
= umask(002);
260 sync_fp
= fopen(sync_file
, "w+");
263 sync_fp
= fopen(sync_file
, "r+");
272 sync_close(int doremove
)
274 const char *sync_file
;
279 sync_file
= get_sync_file(game
);
287 Write(int type
, struct ship
*ship
, long a
, long b
, long c
, long d
)
289 size_t max
= sizeof(sync_buf
) - (sync_bp
- sync_buf
);
290 int shipindex
= (ship
== NULL
) ? 0 : ship
->file
->index
;
292 snprintf(sync_bp
, max
, "%d %d 0 %ld %ld %ld %ld\n",
293 type
, shipindex
, a
, b
, c
, d
);
297 if (sync_bp
>= &sync_buf
[sizeof sync_buf
])
299 sync_update(type
, ship
, NULL
, a
, b
, c
, d
);
303 Writestr(int type
, struct ship
*ship
, const char *a
)
305 size_t max
= sizeof(sync_buf
) - (sync_bp
- sync_buf
);
306 int shipindex
= (ship
== NULL
) ? 0 : ship
->file
->index
;
308 snprintf(sync_bp
, max
, "%d %d 1 %s\n", type
, shipindex
, a
);
312 if (sync_bp
>= &sync_buf
[sizeof sync_buf
])
314 sync_update(type
, ship
, a
, 0, 0, 0, 0);
320 sig_t sighup
, sigint
;
322 int type
, shipnum
, isstr
;
328 const char *sync_file
;
329 const char *sync_lock
;
332 sighup
= signal(SIGHUP
, SIG_IGN
);
333 sigint
= signal(SIGINT
, SIG_IGN
);
334 for (n
= TIMEOUT
; --n
>= 0;) {
336 if (flock(fileno(sync_fp
), LOCK_EX
|LOCK_NB
) >= 0)
338 if (errno
!= EWOULDBLOCK
)
341 sync_file
= get_sync_file(game
);
342 sync_lock
= get_lock_file(game
);
344 if (link(sync_file
, sync_lock
) >= 0) {
356 fseek(sync_fp
, sync_seek
, SEEK_SET
);
358 switch (fscanf(sync_fp
, "%d%d%d", &type
, &shipnum
, &isstr
)) {
366 if (shipnum
< 0 || shipnum
>= cc
->vessels
)
368 if (isstr
!= 0 && isstr
!= 1)
383 if (p
>= buf
+ sizeof buf
)
390 for (p
= buf
; *p
== ' '; p
++)
395 if (fscanf(sync_fp
, "%ld%ld%ld%ld", &a
, &b
, &c
, &d
)
400 if (sync_update(type
, SHIP(shipnum
), astr
, a
, b
, c
, d
) < 0)
406 if (!erred
&& sync_bp
!= sync_buf
) {
407 fseek(sync_fp
, 0L, SEEK_END
);
408 fwrite(sync_buf
, sizeof *sync_buf
, sync_bp
- sync_buf
,
413 sync_seek
= ftell(sync_fp
);
415 flock(fileno(sync_fp
), LOCK_UN
);
421 signal(SIGHUP
, sighup
);
422 signal(SIGINT
, sigint
);
423 return erred
? -1 : 0;
427 sync_update(int type
, struct ship
*ship
, const char *astr
,
428 long a
, long b
, long c
, long d
)
431 case W_CAPTAIN
: recv_captain(ship
, astr
); break;
432 case W_CAPTURED
: recv_captured(ship
, a
); break;
433 case W_CLASS
: recv_class(ship
, a
); break;
434 case W_CREW
: recv_crew(ship
, a
, b
, c
); break;
435 case W_DBP
: recv_dbp(ship
, a
, b
, c
, d
); break;
436 case W_DRIFT
: recv_drift(ship
, a
); break;
437 case W_EXPLODE
: recv_explode(ship
, a
); break;
438 case W_FOUL
: recv_foul(ship
, a
); break;
439 case W_GUNL
: recv_gunl(ship
, a
, b
); break;
440 case W_GUNR
: recv_gunr(ship
, a
, b
); break;
441 case W_HULL
: recv_hull(ship
, a
); break;
442 case W_MOVE
: recv_move(ship
, astr
); break;
443 case W_OBP
: recv_obp(ship
, a
, b
, c
, d
); break;
444 case W_PCREW
: recv_pcrew(ship
, a
); break;
445 case W_UNFOUL
: recv_unfoul(ship
, a
, b
); break;
446 case W_POINTS
: recv_points(ship
, a
); break;
447 case W_QUAL
: recv_qual(ship
, a
); break;
448 case W_UNGRAP
: recv_ungrap(ship
, a
, b
); break;
449 case W_RIGG
: recv_rigg(ship
, a
, b
, c
, d
); break;
450 case W_COL
: recv_col(ship
, a
); break;
451 case W_DIR
: recv_dir(ship
, a
); break;
452 case W_ROW
: recv_row(ship
, a
); break;
453 case W_SIGNAL
: recv_signal(ship
, astr
); break;
454 case W_SINK
: recv_sink(ship
, a
); break;
455 case W_STRUCK
: recv_struck(ship
, a
); break;
456 case W_TA
: recv_ta(ship
, a
); break;
457 case W_ALIVE
: recv_alive(); break;
458 case W_TURN
: recv_turn(a
); break;
459 case W_WIND
: recv_wind(a
, b
); break;
460 case W_FS
: recv_fs(ship
, a
); break;
461 case W_GRAP
: recv_grap(ship
, a
); break;
462 case W_RIG1
: recv_rig1(ship
, a
); break;
463 case W_RIG2
: recv_rig2(ship
, a
); break;
464 case W_RIG3
: recv_rig3(ship
, a
); break;
465 case W_RIG4
: recv_rig4(ship
, a
); break;
466 case W_BEGIN
: recv_begin(ship
); break;
467 case W_END
: recv_end(ship
); break;
468 case W_DDEAD
: recv_ddead(); break;
470 fprintf(stderr
, "sync_update: unknown type %d\r\n", type
);
481 send_captain(struct ship
*ship
, const char *astr
)
483 Writestr(W_CAPTAIN
, ship
, astr
);
487 send_captured(struct ship
*ship
, long a
)
489 Write(W_CAPTURED
, ship
, a
, 0, 0, 0);
493 send_class(struct ship
*ship
, long a
)
495 Write(W_CLASS
, ship
, a
, 0, 0, 0);
499 send_crew(struct ship
*ship
, long a
, long b
, long c
)
501 Write(W_CREW
, ship
, a
, b
, c
, 0);
505 send_dbp(struct ship
*ship
, long a
, long b
, long c
, long d
)
507 Write(W_DBP
, ship
, a
, b
, c
, d
);
511 send_drift(struct ship
*ship
, long a
)
513 Write(W_DRIFT
, ship
, a
, 0, 0, 0);
517 send_explode(struct ship
*ship
, long a
)
519 Write(W_EXPLODE
, ship
, a
, 0, 0, 0);
523 send_foul(struct ship
*ship
, long a
)
525 Write(W_FOUL
, ship
, a
, 0, 0, 0);
529 send_gunl(struct ship
*ship
, long a
, long b
)
531 Write(W_GUNL
, ship
, a
, b
, 0, 0);
535 send_gunr(struct ship
*ship
, long a
, long b
)
537 Write(W_GUNR
, ship
, a
, b
, 0, 0);
541 send_hull(struct ship
*ship
, long a
)
543 Write(W_HULL
, ship
, a
, 0, 0, 0);
547 send_move(struct ship
*ship
, const char *astr
)
549 Writestr(W_MOVE
, ship
, astr
);
553 send_obp(struct ship
*ship
, long a
, long b
, long c
, long d
)
555 Write(W_OBP
, ship
, a
, b
, c
, d
);
559 send_pcrew(struct ship
*ship
, long a
)
561 Write(W_PCREW
, ship
, a
, 0, 0, 0);
565 send_unfoul(struct ship
*ship
, long a
, long b
)
567 Write(W_UNFOUL
, ship
, a
, b
, 0, 0);
571 send_points(struct ship
*ship
, long a
)
573 Write(W_POINTS
, ship
, a
, 0, 0, 0);
577 send_qual(struct ship
*ship
, long a
)
579 Write(W_QUAL
, ship
, a
, 0, 0, 0);
583 send_ungrap(struct ship
*ship
, long a
, long b
)
585 Write(W_UNGRAP
, ship
, a
, b
, 0, 0);
589 send_rigg(struct ship
*ship
, long a
, long b
, long c
, long d
)
591 Write(W_RIGG
, ship
, a
, b
, c
, d
);
595 send_col(struct ship
*ship
, long a
)
597 Write(W_COL
, ship
, a
, 0, 0, 0);
601 send_dir(struct ship
*ship
, long a
)
603 Write(W_DIR
, ship
, a
, 0, 0, 0);
607 send_row(struct ship
*ship
, long a
)
609 Write(W_ROW
, ship
, a
, 0, 0, 0);
613 send_signal(struct ship
*ship
, const char *astr
)
615 Writestr(W_SIGNAL
, ship
, astr
);
619 send_sink(struct ship
*ship
, long a
)
621 Write(W_SINK
, ship
, a
, 0, 0, 0);
625 send_struck(struct ship
*ship
, long a
)
627 Write(W_STRUCK
, ship
, a
, 0, 0, 0);
631 send_ta(struct ship
*ship
, long a
)
633 Write(W_TA
, ship
, a
, 0, 0, 0);
639 Write(W_ALIVE
, NULL
, 0, 0, 0, 0);
645 Write(W_TURN
, NULL
, a
, 0, 0, 0);
649 send_wind(long a
, long b
)
651 Write(W_WIND
, NULL
, a
, b
, 0, 0);
655 send_fs(struct ship
*ship
, long a
)
657 Write(W_FS
, ship
, a
, 0, 0, 0);
661 send_grap(struct ship
*ship
, long a
)
663 Write(W_GRAP
, ship
, a
, 0, 0, 0);
667 send_rig1(struct ship
*ship
, long a
)
669 Write(W_RIG1
, ship
, a
, 0, 0, 0);
673 send_rig2(struct ship
*ship
, long a
)
675 Write(W_RIG2
, ship
, a
, 0, 0, 0);
679 send_rig3(struct ship
*ship
, long a
)
681 Write(W_RIG3
, ship
, a
, 0, 0, 0);
685 send_rig4(struct ship
*ship
, long a
)
687 Write(W_RIG4
, ship
, a
, 0, 0, 0);
691 send_begin(struct ship
*ship
)
693 Write(W_BEGIN
, ship
, 0, 0, 0, 0);
697 send_end(struct ship
*ship
)
699 Write(W_END
, ship
, 0, 0, 0, 0);
705 Write(W_DDEAD
, NULL
, 0, 0, 0, 0);
710 * Actions upon message receipt
714 recv_captain(struct ship
*ship
, const char *astr
)
716 strlcpy(ship
->file
->captain
, astr
, sizeof ship
->file
->captain
);
720 recv_captured(struct ship
*ship
, long a
)
723 ship
->file
->captured
= 0;
725 ship
->file
->captured
= SHIP(a
);
729 recv_class(struct ship
*ship
, long a
)
731 ship
->specs
->class = a
;
735 recv_crew(struct ship
*ship
, long a
, long b
, long c
)
737 struct shipspecs
*s
= ship
->specs
;
745 recv_dbp(struct ship
*ship
, long a
, long b
, long c
, long d
)
747 struct BP
*p
= &ship
->file
->DBP
[a
];
755 recv_drift(struct ship
*ship
, long a
)
757 ship
->file
->drift
= a
;
761 recv_explode(struct ship
*ship
, long a
)
763 if ((ship
->file
->explode
= a
) == 2)
768 recv_foul(struct ship
*ship
, long a
)
770 struct snag
*p
= &ship
->file
->foul
[a
];
772 if (SHIP(a
)->file
->dir
== 0)
774 if (p
->sn_count
++ == 0)
780 recv_gunl(struct ship
*ship
, long a
, long b
)
782 struct shipspecs
*s
= ship
->specs
;
789 recv_gunr(struct ship
*ship
, long a
, long b
)
791 struct shipspecs
*s
= ship
->specs
;
798 recv_hull(struct ship
*ship
, long a
)
800 ship
->specs
->hull
= a
;
804 recv_move(struct ship
*ship
, const char *astr
)
806 strlcpy(ship
->file
->movebuf
, astr
, sizeof ship
->file
->movebuf
);
810 recv_obp(struct ship
*ship
, long a
, long b
, long c
, long d
)
812 struct BP
*p
= &ship
->file
->OBP
[a
];
820 recv_pcrew(struct ship
*ship
, long a
)
822 ship
->file
->pcrew
= a
;
826 recv_unfoul(struct ship
*ship
, long a
, long b
)
828 struct snag
*p
= &ship
->file
->foul
[a
];
830 if (p
->sn_count
> 0) {
832 ship
->file
->nfoul
-= p
->sn_count
;
842 recv_points(struct ship
*ship
, long a
)
844 ship
->file
->points
= a
;
848 recv_qual(struct ship
*ship
, long a
)
850 ship
->specs
->qual
= a
;
854 recv_ungrap(struct ship
*ship
, long a
, long b
)
856 struct snag
*p
= &ship
->file
->grap
[a
];
858 if (p
->sn_count
> 0) {
860 ship
->file
->ngrap
-= p
->sn_count
;
870 recv_rigg(struct ship
*ship
, long a
, long b
, long c
, long d
)
872 struct shipspecs
*s
= ship
->specs
;
881 recv_col(struct ship
*ship
, long a
)
887 recv_dir(struct ship
*ship
, long a
)
893 recv_row(struct ship
*ship
, long a
)
899 recv_signal(struct ship
*ship
, const char *astr
)
901 if (mode
== MODE_PLAYER
) {
903 Signal("$$: %s", ship
, astr
);
905 Signal("\a$$: %s", ship
, astr
);
910 recv_sink(struct ship
*ship
, long a
)
912 if ((ship
->file
->sink
= a
) == 2)
917 recv_struck(struct ship
*ship
, long a
)
919 ship
->file
->struck
= a
;
923 recv_ta(struct ship
*ship
, long a
)
941 recv_wind(long a
, long b
)
948 recv_fs(struct ship
*ship
, long a
)
954 recv_grap(struct ship
*ship
, long a
)
956 struct snag
*p
= &ship
->file
->grap
[a
];
958 if (SHIP(a
)->file
->dir
== 0)
960 if (p
->sn_count
++ == 0)
966 recv_rig1(struct ship
*ship
, long a
)
968 ship
->specs
->rig1
= a
;
972 recv_rig2(struct ship
*ship
, long a
)
974 ship
->specs
->rig2
= a
;
978 recv_rig3(struct ship
*ship
, long a
)
980 ship
->specs
->rig3
= a
;
984 recv_rig4(struct ship
*ship
, long a
)
986 ship
->specs
->rig4
= a
;
990 recv_begin(struct ship
*ship
)
992 strcpy(ship
->file
->captain
, "begin");
997 recv_end(struct ship
*ship
)
999 *ship
->file
->captain
= 0;
1000 ship
->file
->points
= 0;