1*fe7fbef8Sdholland /* $NetBSD: hack.save.c,v 1.16 2011/08/06 20:42:43 dholland Exp $ */
23ea4a95cSchristos
3210cab45Smycroft /*
41c7f94e5Sjsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm * Amsterdam
61c7f94e5Sjsm * All rights reserved.
71c7f94e5Sjsm *
81c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm * met:
111c7f94e5Sjsm *
121c7f94e5Sjsm * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm * this list of conditions and the following disclaimer.
141c7f94e5Sjsm *
151c7f94e5Sjsm * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm *
191c7f94e5Sjsm * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm * promote products derived from this software without specific prior
221c7f94e5Sjsm * written permission.
231c7f94e5Sjsm *
241c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm */
361c7f94e5Sjsm
371c7f94e5Sjsm /*
381c7f94e5Sjsm * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm * All rights reserved.
401c7f94e5Sjsm *
411c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm * modification, are permitted provided that the following conditions
431c7f94e5Sjsm * are met:
441c7f94e5Sjsm * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm * notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm * derived from this software without specific prior written permission.
511c7f94e5Sjsm *
521c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
551c7f94e5Sjsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62210cab45Smycroft */
63210cab45Smycroft
643ea4a95cSchristos #include <sys/cdefs.h>
65210cab45Smycroft #ifndef lint
66*fe7fbef8Sdholland __RCSID("$NetBSD: hack.save.c,v 1.16 2011/08/06 20:42:43 dholland Exp $");
67210cab45Smycroft #endif /* not lint */
6861f28255Scgd
6961f28255Scgd #include <signal.h>
703ea4a95cSchristos #include <stdlib.h>
7142fb1b9dScgd #include <unistd.h>
723ea4a95cSchristos #include <fcntl.h>
733ea4a95cSchristos #include "hack.h"
743ea4a95cSchristos #include "extern.h"
7561f28255Scgd
769b92b189Sdholland static int dosave0(int);
7761f28255Scgd
783ea4a95cSchristos int
dosave(void)791fa8a9a6Sdholland dosave(void)
803ea4a95cSchristos {
8161f28255Scgd if (dosave0(0)) {
8261f28255Scgd settty("Be seeing you ...\n");
8361f28255Scgd exit(0);
8461f28255Scgd }
8561f28255Scgd return (0);
8661f28255Scgd }
8761f28255Scgd
8861f28255Scgd #ifndef NOSAVEONHANGUP
893ea4a95cSchristos void
hang_up(int n __unused)9098eb8895Sroy hang_up(int n __unused)
913ea4a95cSchristos {
9261f28255Scgd (void) dosave0(1);
9361f28255Scgd exit(1);
9461f28255Scgd }
953ea4a95cSchristos #endif /* NOSAVEONHANGUP */
9661f28255Scgd
9761f28255Scgd /* returns 1 if save successful */
989b92b189Sdholland static int
dosave0(int hu)991fa8a9a6Sdholland dosave0(int hu)
1003ea4a95cSchristos {
1013ea4a95cSchristos int fd, ofd;
1023ea4a95cSchristos int tmp; /* not ! */
10361f28255Scgd
10461f28255Scgd (void) signal(SIGHUP, SIG_IGN);
10561f28255Scgd (void) signal(SIGINT, SIG_IGN);
10661f28255Scgd if ((fd = creat(SAVEF, FMASK)) < 0) {
1073ea4a95cSchristos if (!hu)
1083ea4a95cSchristos pline("Cannot open save file. (Continue or Quit)");
10961f28255Scgd (void) unlink(SAVEF); /* ab@unido */
11061f28255Scgd return (0);
11161f28255Scgd }
11261f28255Scgd if (flags.moonphase == FULL_MOON) /* ut-sally!fletcher */
11361f28255Scgd u.uluck--; /* and unido!ab */
11461f28255Scgd savelev(fd, dlevel);
11561f28255Scgd saveobjchn(fd, invent);
11661f28255Scgd saveobjchn(fd, fcobj);
11761f28255Scgd savemonchn(fd, fallen_down);
11861f28255Scgd tmp = getuid();
1198d5216e8Sdholland bwrite(fd, &tmp, sizeof tmp);
1208d5216e8Sdholland bwrite(fd, &flags, sizeof(struct flag));
1218d5216e8Sdholland bwrite(fd, &dlevel, sizeof dlevel);
1228d5216e8Sdholland bwrite(fd, &maxdlevel, sizeof maxdlevel);
1238d5216e8Sdholland bwrite(fd, &moves, sizeof moves);
1248d5216e8Sdholland bwrite(fd, &u, sizeof(struct you));
12561f28255Scgd if (u.ustuck)
1268d5216e8Sdholland bwrite(fd, &(u.ustuck->m_id), sizeof u.ustuck->m_id);
1278d5216e8Sdholland bwrite(fd, pl_character, sizeof pl_character);
1288d5216e8Sdholland bwrite(fd, genocided, sizeof genocided);
1298d5216e8Sdholland bwrite(fd, fut_geno, sizeof fut_geno);
13061f28255Scgd savenames(fd);
13161f28255Scgd for (tmp = 1; tmp <= maxdlevel; tmp++) {
13261f28255Scgd
1333ea4a95cSchristos if (tmp == dlevel || !level_exists[tmp])
1343ea4a95cSchristos continue;
13561f28255Scgd glo(tmp);
136ab8b6343Sjsm if ((ofd = open(lock, O_RDONLY)) < 0) {
1373ea4a95cSchristos if (!hu)
1383ea4a95cSchristos pline("Error while saving: cannot read %s.", lock);
13961f28255Scgd (void) close(fd);
14061f28255Scgd (void) unlink(SAVEF);
1413ea4a95cSchristos if (!hu)
1423ea4a95cSchristos done("tricked");
14361f28255Scgd return (0);
14461f28255Scgd }
14561f28255Scgd getlev(ofd, hackpid, tmp);
14661f28255Scgd (void) close(ofd);
1478d5216e8Sdholland bwrite(fd, &tmp, sizeof tmp); /* level number */
14861f28255Scgd savelev(fd, tmp); /* actual level */
14961f28255Scgd (void) unlink(lock);
15061f28255Scgd }
15161f28255Scgd (void) close(fd);
15261f28255Scgd glo(dlevel);
15361f28255Scgd (void) unlink(lock); /* get rid of current level --jgm */
15461f28255Scgd glo(0);
15561f28255Scgd (void) unlink(lock);
15661f28255Scgd return (1);
15761f28255Scgd }
15861f28255Scgd
1593ea4a95cSchristos int
dorecover(int fd)1601fa8a9a6Sdholland dorecover(int fd)
16161f28255Scgd {
1623ea4a95cSchristos int nfd;
1633ea4a95cSchristos int tmp; /* not a ! */
16461f28255Scgd unsigned mid; /* idem */
16561f28255Scgd struct obj *otmp;
16661f28255Scgd
16761f28255Scgd restoring = TRUE;
16861f28255Scgd getlev(fd, 0, 0);
16961f28255Scgd invent = restobjchn(fd);
17061f28255Scgd for (otmp = invent; otmp; otmp = otmp->nobj)
17161f28255Scgd if (otmp->owornmask)
17261f28255Scgd setworn(otmp, otmp->owornmask);
17361f28255Scgd fcobj = restobjchn(fd);
17461f28255Scgd fallen_down = restmonchn(fd);
175c8aead89Sdholland mread(fd, &tmp, sizeof tmp);
1763c439f43Sdholland if (tmp != (int) getuid()) { /* strange ... */
17761f28255Scgd (void) close(fd);
17861f28255Scgd (void) unlink(SAVEF);
17961f28255Scgd puts("Saved game was not yours.");
18061f28255Scgd restoring = FALSE;
18161f28255Scgd return (0);
18261f28255Scgd }
183c8aead89Sdholland mread(fd, &flags, sizeof(struct flag));
184c8aead89Sdholland mread(fd, &dlevel, sizeof dlevel);
185c8aead89Sdholland mread(fd, &maxdlevel, sizeof maxdlevel);
186c8aead89Sdholland mread(fd, &moves, sizeof moves);
187c8aead89Sdholland mread(fd, &u, sizeof(struct you));
18861f28255Scgd if (u.ustuck)
189c8aead89Sdholland mread(fd, &mid, sizeof mid);
190c8aead89Sdholland mread(fd, pl_character, sizeof pl_character);
191c8aead89Sdholland mread(fd, genocided, sizeof genocided);
192c8aead89Sdholland mread(fd, fut_geno, sizeof fut_geno);
19361f28255Scgd restnames(fd);
19461f28255Scgd while (1) {
195*fe7fbef8Sdholland if (read(fd, &tmp, sizeof tmp) != sizeof tmp)
19661f28255Scgd break;
19761f28255Scgd getlev(fd, 0, tmp);
19861f28255Scgd glo(tmp);
19961f28255Scgd if ((nfd = creat(lock, FMASK)) < 0)
20061f28255Scgd panic("Cannot open temp file %s!\n", lock);
20161f28255Scgd savelev(nfd, tmp);
20261f28255Scgd (void) close(nfd);
20361f28255Scgd }
204ab8b6343Sjsm (void) lseek(fd, (off_t) 0, SEEK_SET);
20561f28255Scgd getlev(fd, 0, 0);
20661f28255Scgd (void) close(fd);
20761f28255Scgd (void) unlink(SAVEF);
20861f28255Scgd if (Punished) {
20961f28255Scgd for (otmp = fobj; otmp; otmp = otmp->nobj)
2103ea4a95cSchristos if (otmp->olet == CHAIN_SYM)
2113ea4a95cSchristos goto chainfnd;
21261f28255Scgd panic("Cannot find the iron chain?");
21361f28255Scgd chainfnd:
21461f28255Scgd uchain = otmp;
21561f28255Scgd if (!uball) {
21661f28255Scgd for (otmp = fobj; otmp; otmp = otmp->nobj)
21761f28255Scgd if (otmp->olet == BALL_SYM && otmp->spe)
21861f28255Scgd goto ballfnd;
21961f28255Scgd panic("Cannot find the iron ball?");
22061f28255Scgd ballfnd:
22161f28255Scgd uball = otmp;
22261f28255Scgd }
22361f28255Scgd }
22461f28255Scgd if (u.ustuck) {
2253ea4a95cSchristos struct monst *mtmp;
22661f28255Scgd
22761f28255Scgd for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
2283ea4a95cSchristos if (mtmp->m_id == mid)
2293ea4a95cSchristos goto monfnd;
23061f28255Scgd panic("Cannot find the monster ustuck.");
23161f28255Scgd monfnd:
23261f28255Scgd u.ustuck = mtmp;
23361f28255Scgd }
23461f28255Scgd #ifndef QUEST
2353ea4a95cSchristos setsee(); /* only to recompute seelx etc. - these
2363ea4a95cSchristos * weren't saved */
2373ea4a95cSchristos #endif /* QUEST */
23861f28255Scgd docrt();
23961f28255Scgd restoring = FALSE;
24061f28255Scgd return (1);
24161f28255Scgd }
24261f28255Scgd
24361f28255Scgd struct obj *
restobjchn(int fd)2441fa8a9a6Sdholland restobjchn(int fd)
24561f28255Scgd {
2463ea4a95cSchristos struct obj *otmp, *otmp2 = NULL;
2473ea4a95cSchristos struct obj *first = 0;
24861f28255Scgd int xl;
24961f28255Scgd while (1) {
250c8aead89Sdholland mread(fd, &xl, sizeof(xl));
2513ea4a95cSchristos if (xl == -1)
2523ea4a95cSchristos break;
25361f28255Scgd otmp = newobj(xl);
2543ea4a95cSchristos if (!first)
2553ea4a95cSchristos first = otmp;
2563ea4a95cSchristos else
2573ea4a95cSchristos otmp2->nobj = otmp;
258c8aead89Sdholland mread(fd, otmp, (unsigned) xl + sizeof(struct obj));
2593ea4a95cSchristos if (!otmp->o_id)
2603ea4a95cSchristos otmp->o_id = flags.ident++;
26161f28255Scgd otmp2 = otmp;
26261f28255Scgd }
26361f28255Scgd if (first && otmp2->nobj) {
26461f28255Scgd impossible("Restobjchn: error reading objchn.");
26561f28255Scgd otmp2->nobj = 0;
26661f28255Scgd }
26761f28255Scgd return (first);
26861f28255Scgd }
26961f28255Scgd
27061f28255Scgd struct monst *
restmonchn(int fd)2711fa8a9a6Sdholland restmonchn(int fd)
27261f28255Scgd {
2733ea4a95cSchristos struct monst *mtmp, *mtmp2 = NULL;
2743ea4a95cSchristos struct monst *first = 0;
27561f28255Scgd int xl;
27661f28255Scgd
27761f28255Scgd struct permonst *monbegin;
27861f28255Scgd long differ;
27961f28255Scgd
280c8aead89Sdholland mread(fd, &monbegin, sizeof(monbegin));
281ab8b6343Sjsm differ = (const char *) (&mons[0]) - (const char *) (monbegin);
28261f28255Scgd
28361f28255Scgd #ifdef lint
28461f28255Scgd /* suppress "used before set" warning from lint */
28561f28255Scgd mtmp2 = 0;
2863ea4a95cSchristos #endif /* lint */
28761f28255Scgd while (1) {
288c8aead89Sdholland mread(fd, &xl, sizeof(xl));
2893ea4a95cSchristos if (xl == -1)
2903ea4a95cSchristos break;
29161f28255Scgd mtmp = newmonst(xl);
2923ea4a95cSchristos if (!first)
2933ea4a95cSchristos first = mtmp;
2943ea4a95cSchristos else
2953ea4a95cSchristos mtmp2->nmon = mtmp;
296c8aead89Sdholland mread(fd, mtmp, (unsigned) xl + sizeof(struct monst));
29761f28255Scgd if (!mtmp->m_id)
29861f28255Scgd mtmp->m_id = flags.ident++;
299ab8b6343Sjsm mtmp->data = (const struct permonst *)
300ab8b6343Sjsm ((const char *) mtmp->data + differ);
30161f28255Scgd if (mtmp->minvent)
30261f28255Scgd mtmp->minvent = restobjchn(fd);
30361f28255Scgd mtmp2 = mtmp;
30461f28255Scgd }
30561f28255Scgd if (first && mtmp2->nmon) {
30661f28255Scgd impossible("Restmonchn: error reading monchn.");
30761f28255Scgd mtmp2->nmon = 0;
30861f28255Scgd }
30961f28255Scgd return (first);
31061f28255Scgd }
311