xref: /openbsd-src/games/hack/hack.save.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: hack.save.c,v 1.8 2006/10/11 20:56:59 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 #ifndef lint
65 static const char rcsid[] = "$OpenBSD: hack.save.c,v 1.8 2006/10/11 20:56:59 deraadt Exp $";
66 #endif /* not lint */
67 
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <signal.h>
71 #include <unistd.h>
72 #include "hack.h"
73 
74 extern char genocided[60];	/* defined in Decl.c */
75 extern char fut_geno[60];	/* idem */
76 extern char SAVEF[], nul[];
77 extern char pl_character[PL_CSIZ];
78 
79 static int dosave0(int);
80 
81 int
82 dosave()
83 {
84 	if(dosave0(0)) {
85 		settty("Be seeing you ...\n");
86 		exit(0);
87 	}
88 	return(0);
89 }
90 
91 void
92 hackhangup(int notused)
93 {
94 	(void) dosave0(1);
95 	exit(1);
96 }
97 
98 /* returns 1 if save successful */
99 static int
100 dosave0(int hu)
101 {
102 	int fd, ofd;
103 	int tmp;		/* not register ! */
104 
105 	(void) signal(SIGHUP, SIG_IGN);
106 	(void) signal(SIGINT, SIG_IGN);
107 	if((fd = creat(SAVEF, FMASK)) < 0) {
108 		if(!hu) pline("Cannot open save file. (Continue or Quit)");
109 		(void) unlink(SAVEF);		/* ab@unido */
110 		return(0);
111 	}
112 	if(flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
113 		u.uluck--;			/* and unido!ab */
114 	savelev(fd,dlevel);
115 	saveobjchn(fd, invent);
116 	saveobjchn(fd, fcobj);
117 	savemonchn(fd, fallen_down);
118 	tmp = getuid();
119 	bwrite(fd, (char *) &tmp, sizeof tmp);
120 	bwrite(fd, (char *) &flags, sizeof(struct flag));
121 	bwrite(fd, (char *) &dlevel, sizeof dlevel);
122 	bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
123 	bwrite(fd, (char *) &moves, sizeof moves);
124 	bwrite(fd, (char *) &u, sizeof(struct you));
125 	if(u.ustuck)
126 		bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
127 	bwrite(fd, (char *) pl_character, sizeof pl_character);
128 	bwrite(fd, (char *) genocided, sizeof genocided);
129 	bwrite(fd, (char *) fut_geno, sizeof fut_geno);
130 	savenames(fd);
131 	for(tmp = 1; tmp <= maxdlevel; tmp++) {
132 		extern int hackpid;
133 		extern boolean level_exists[];
134 
135 		if(tmp == dlevel || !level_exists[tmp]) continue;
136 		glo(tmp);
137 		if((ofd = open(lock, O_RDONLY)) < 0) {
138 		    if(!hu) pline("Error while saving: cannot read %s.", lock);
139 		    (void) close(fd);
140 		    (void) unlink(SAVEF);
141 		    if(!hu) done("tricked");
142 		    return(0);
143 		}
144 		getlev(ofd, hackpid, tmp);
145 		(void) close(ofd);
146 		bwrite(fd, (char *) &tmp, sizeof tmp);	/* level number */
147 		savelev(fd,tmp);			/* actual level */
148 		(void) unlink(lock);
149 	}
150 	(void) close(fd);
151 	glo(dlevel);
152 	(void) unlink(lock);	/* get rid of current level --jgm */
153 	glo(0);
154 	(void) unlink(lock);
155 	return(1);
156 }
157 
158 int
159 dorecover(int fd)
160 {
161 	int nfd;
162 	int tmp;		/* not a register ! */
163 	unsigned mid;		/* idem */
164 	struct obj *otmp;
165 	extern boolean restoring;
166 
167 	restoring = TRUE;
168 	getlev(fd, 0, 0);
169 	invent = restobjchn(fd);
170 	for(otmp = invent; otmp; otmp = otmp->nobj)
171 		if(otmp->owornmask)
172 			setworn(otmp, otmp->owornmask);
173 	fcobj = restobjchn(fd);
174 	fallen_down = restmonchn(fd);
175 	mread(fd, (char *) &tmp, sizeof tmp);
176 	if(tmp != getuid()) {		/* strange ... */
177 		(void) close(fd);
178 		(void) unlink(SAVEF);
179 		puts("Saved game was not yours.");
180 		restoring = FALSE;
181 		return(0);
182 	}
183 	mread(fd, (char *) &flags, sizeof(struct flag));
184 	mread(fd, (char *) &dlevel, sizeof dlevel);
185 	mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
186 	mread(fd, (char *) &moves, sizeof moves);
187 	mread(fd, (char *) &u, sizeof(struct you));
188 	if(u.ustuck)
189 		mread(fd, (char *) &mid, sizeof mid);
190 	mread(fd, (char *) pl_character, sizeof pl_character);
191 	mread(fd, (char *) genocided, sizeof genocided);
192 	mread(fd, (char *) fut_geno, sizeof fut_geno);
193 	restnames(fd);
194 	while(1) {
195 		if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp)
196 			break;
197 		getlev(fd, 0, tmp);
198 		glo(tmp);
199 		if((nfd = creat(lock, FMASK)) < 0)
200 			panic("Cannot open temp file %s!\n", lock);
201 		savelev(nfd,tmp);
202 		(void) close(nfd);
203 	}
204 	(void) lseek(fd, (off_t)0, SEEK_SET);
205 	getlev(fd, 0, 0);
206 	(void) close(fd);
207 	(void) unlink(SAVEF);
208 	if(Punished) {
209 		for(otmp = fobj; otmp; otmp = otmp->nobj)
210 			if(otmp->olet == CHAIN_SYM) goto chainfnd;
211 		panic("Cannot find the iron chain?");
212 	chainfnd:
213 		uchain = otmp;
214 		if(!uball){
215 			for(otmp = fobj; otmp; otmp = otmp->nobj)
216 				if(otmp->olet == BALL_SYM && otmp->spe)
217 					goto ballfnd;
218 			panic("Cannot find the iron ball?");
219 		ballfnd:
220 			uball = otmp;
221 		}
222 	}
223 	if(u.ustuck) {
224 		struct monst *mtmp;
225 
226 		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
227 			if(mtmp->m_id == mid) goto monfnd;
228 		panic("Cannot find the monster ustuck.");
229 	monfnd:
230 		u.ustuck = mtmp;
231 	}
232 #ifndef QUEST
233 	setsee();  /* only to recompute seelx etc. - these weren't saved */
234 #endif /* QUEST */
235 	docrt();
236 	restoring = FALSE;
237 	return(1);
238 }
239 
240 struct obj *
241 restobjchn(int fd)
242 {
243 	struct obj *otmp, *otmp2;
244 	struct obj *first = 0;
245 	int xl;
246 #ifdef lint
247 	/* suppress "used before set" warning from lint */
248 	otmp2 = 0;
249 #endif /* lint */
250 	while(1) {
251 		mread(fd, (char *) &xl, sizeof(xl));
252 		if(xl == -1) break;
253 		otmp = newobj(xl);
254 		if(!first) first = otmp;
255 		else otmp2->nobj = otmp;
256 		mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj));
257 		if(!otmp->o_id) otmp->o_id = flags.ident++;
258 		otmp2 = otmp;
259 	}
260 	if(first && otmp2->nobj){
261 		impossible("Restobjchn: error reading objchn.");
262 		otmp2->nobj = 0;
263 	}
264 	return(first);
265 }
266 
267 struct monst *
268 restmonchn(int fd)
269 {
270 	struct monst *mtmp, *mtmp2;
271 	struct monst *first = 0;
272 	int xl;
273 
274 	struct permonst *monbegin;
275 	long differ;
276 
277 	mread(fd, (char *)&monbegin, sizeof(monbegin));
278 	differ = (char *)(&mons[0]) - (char *)(monbegin);
279 
280 #ifdef lint
281 	/* suppress "used before set" warning from lint */
282 	mtmp2 = 0;
283 #endif /* lint */
284 	while(1) {
285 		mread(fd, (char *) &xl, sizeof(xl));
286 		if(xl == -1) break;
287 		mtmp = newmonst(xl);
288 		if(!first) first = mtmp;
289 		else mtmp2->nmon = mtmp;
290 		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
291 		if(!mtmp->m_id)
292 			mtmp->m_id = flags.ident++;
293 		mtmp->data = (struct permonst *)
294 			((char *) mtmp->data + differ);
295 		if(mtmp->minvent)
296 			mtmp->minvent = restobjchn(fd);
297 		mtmp2 = mtmp;
298 	}
299 	if(first && mtmp2->nmon){
300 		impossible("Restmonchn: error reading monchn.");
301 		mtmp2->nmon = 0;
302 	}
303 	return(first);
304 }
305