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