xref: /openbsd-src/games/hack/hack.save.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: hack.save.c,v 1.9 2009/10/27 23:59:25 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <signal.h>
67 #include <unistd.h>
68 #include "hack.h"
69 
70 extern char genocided[60];	/* defined in Decl.c */
71 extern char fut_geno[60];	/* idem */
72 extern char SAVEF[], nul[];
73 extern char pl_character[PL_CSIZ];
74 
75 static int dosave0(int);
76 
77 int
78 dosave()
79 {
80 	if(dosave0(0)) {
81 		settty("Be seeing you ...\n");
82 		exit(0);
83 	}
84 	return(0);
85 }
86 
87 void
88 hackhangup(int notused)
89 {
90 	(void) dosave0(1);
91 	exit(1);
92 }
93 
94 /* returns 1 if save successful */
95 static int
96 dosave0(int hu)
97 {
98 	int fd, ofd;
99 	int tmp;		/* not register ! */
100 
101 	(void) signal(SIGHUP, SIG_IGN);
102 	(void) signal(SIGINT, SIG_IGN);
103 	if((fd = creat(SAVEF, FMASK)) < 0) {
104 		if(!hu) pline("Cannot open save file. (Continue or Quit)");
105 		(void) unlink(SAVEF);		/* ab@unido */
106 		return(0);
107 	}
108 	if(flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
109 		u.uluck--;			/* and unido!ab */
110 	savelev(fd,dlevel);
111 	saveobjchn(fd, invent);
112 	saveobjchn(fd, fcobj);
113 	savemonchn(fd, fallen_down);
114 	tmp = getuid();
115 	bwrite(fd, (char *) &tmp, sizeof tmp);
116 	bwrite(fd, (char *) &flags, sizeof(struct flag));
117 	bwrite(fd, (char *) &dlevel, sizeof dlevel);
118 	bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
119 	bwrite(fd, (char *) &moves, sizeof moves);
120 	bwrite(fd, (char *) &u, sizeof(struct you));
121 	if(u.ustuck)
122 		bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
123 	bwrite(fd, (char *) pl_character, sizeof pl_character);
124 	bwrite(fd, (char *) genocided, sizeof genocided);
125 	bwrite(fd, (char *) fut_geno, sizeof fut_geno);
126 	savenames(fd);
127 	for(tmp = 1; tmp <= maxdlevel; tmp++) {
128 		extern int hackpid;
129 		extern boolean level_exists[];
130 
131 		if(tmp == dlevel || !level_exists[tmp]) continue;
132 		glo(tmp);
133 		if((ofd = open(lock, O_RDONLY)) < 0) {
134 		    if(!hu) pline("Error while saving: cannot read %s.", lock);
135 		    (void) close(fd);
136 		    (void) unlink(SAVEF);
137 		    if(!hu) done("tricked");
138 		    return(0);
139 		}
140 		getlev(ofd, hackpid, tmp);
141 		(void) close(ofd);
142 		bwrite(fd, (char *) &tmp, sizeof tmp);	/* level number */
143 		savelev(fd,tmp);			/* actual level */
144 		(void) unlink(lock);
145 	}
146 	(void) close(fd);
147 	glo(dlevel);
148 	(void) unlink(lock);	/* get rid of current level --jgm */
149 	glo(0);
150 	(void) unlink(lock);
151 	return(1);
152 }
153 
154 int
155 dorecover(int fd)
156 {
157 	int nfd;
158 	int tmp;		/* not a register ! */
159 	unsigned mid;		/* idem */
160 	struct obj *otmp;
161 	extern boolean restoring;
162 
163 	restoring = TRUE;
164 	getlev(fd, 0, 0);
165 	invent = restobjchn(fd);
166 	for(otmp = invent; otmp; otmp = otmp->nobj)
167 		if(otmp->owornmask)
168 			setworn(otmp, otmp->owornmask);
169 	fcobj = restobjchn(fd);
170 	fallen_down = restmonchn(fd);
171 	mread(fd, (char *) &tmp, sizeof tmp);
172 	if(tmp != getuid()) {		/* strange ... */
173 		(void) close(fd);
174 		(void) unlink(SAVEF);
175 		puts("Saved game was not yours.");
176 		restoring = FALSE;
177 		return(0);
178 	}
179 	mread(fd, (char *) &flags, sizeof(struct flag));
180 	mread(fd, (char *) &dlevel, sizeof dlevel);
181 	mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
182 	mread(fd, (char *) &moves, sizeof moves);
183 	mread(fd, (char *) &u, sizeof(struct you));
184 	if(u.ustuck)
185 		mread(fd, (char *) &mid, sizeof mid);
186 	mread(fd, (char *) pl_character, sizeof pl_character);
187 	mread(fd, (char *) genocided, sizeof genocided);
188 	mread(fd, (char *) fut_geno, sizeof fut_geno);
189 	restnames(fd);
190 	while(1) {
191 		if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp)
192 			break;
193 		getlev(fd, 0, tmp);
194 		glo(tmp);
195 		if((nfd = creat(lock, FMASK)) < 0)
196 			panic("Cannot open temp file %s!\n", lock);
197 		savelev(nfd,tmp);
198 		(void) close(nfd);
199 	}
200 	(void) lseek(fd, (off_t)0, SEEK_SET);
201 	getlev(fd, 0, 0);
202 	(void) close(fd);
203 	(void) unlink(SAVEF);
204 	if(Punished) {
205 		for(otmp = fobj; otmp; otmp = otmp->nobj)
206 			if(otmp->olet == CHAIN_SYM) goto chainfnd;
207 		panic("Cannot find the iron chain?");
208 	chainfnd:
209 		uchain = otmp;
210 		if(!uball){
211 			for(otmp = fobj; otmp; otmp = otmp->nobj)
212 				if(otmp->olet == BALL_SYM && otmp->spe)
213 					goto ballfnd;
214 			panic("Cannot find the iron ball?");
215 		ballfnd:
216 			uball = otmp;
217 		}
218 	}
219 	if(u.ustuck) {
220 		struct monst *mtmp;
221 
222 		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
223 			if(mtmp->m_id == mid) goto monfnd;
224 		panic("Cannot find the monster ustuck.");
225 	monfnd:
226 		u.ustuck = mtmp;
227 	}
228 #ifndef QUEST
229 	setsee();  /* only to recompute seelx etc. - these weren't saved */
230 #endif /* QUEST */
231 	docrt();
232 	restoring = FALSE;
233 	return(1);
234 }
235 
236 struct obj *
237 restobjchn(int fd)
238 {
239 	struct obj *otmp, *otmp2;
240 	struct obj *first = 0;
241 	int xl;
242 #ifdef lint
243 	/* suppress "used before set" warning from lint */
244 	otmp2 = 0;
245 #endif /* lint */
246 	while(1) {
247 		mread(fd, (char *) &xl, sizeof(xl));
248 		if(xl == -1) break;
249 		otmp = newobj(xl);
250 		if(!first) first = otmp;
251 		else otmp2->nobj = otmp;
252 		mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj));
253 		if(!otmp->o_id) otmp->o_id = flags.ident++;
254 		otmp2 = otmp;
255 	}
256 	if(first && otmp2->nobj){
257 		impossible("Restobjchn: error reading objchn.");
258 		otmp2->nobj = 0;
259 	}
260 	return(first);
261 }
262 
263 struct monst *
264 restmonchn(int fd)
265 {
266 	struct monst *mtmp, *mtmp2;
267 	struct monst *first = 0;
268 	int xl;
269 
270 	struct permonst *monbegin;
271 	long differ;
272 
273 	mread(fd, (char *)&monbegin, sizeof(monbegin));
274 	differ = (char *)(&mons[0]) - (char *)(monbegin);
275 
276 #ifdef lint
277 	/* suppress "used before set" warning from lint */
278 	mtmp2 = 0;
279 #endif /* lint */
280 	while(1) {
281 		mread(fd, (char *) &xl, sizeof(xl));
282 		if(xl == -1) break;
283 		mtmp = newmonst(xl);
284 		if(!first) first = mtmp;
285 		else mtmp2->nmon = mtmp;
286 		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
287 		if(!mtmp->m_id)
288 			mtmp->m_id = flags.ident++;
289 		mtmp->data = (struct permonst *)
290 			((char *) mtmp->data + differ);
291 		if(mtmp->minvent)
292 			mtmp->minvent = restobjchn(fd);
293 		mtmp2 = mtmp;
294 	}
295 	if(first && mtmp2->nmon){
296 		impossible("Restmonchn: error reading monchn.");
297 		mtmp2->nmon = 0;
298 	}
299 	return(first);
300 }
301