1 /* $OpenBSD: hack.save.c,v 1.4 2001/08/06 22:59:13 pjanzen Exp $ */ 2 3 /* 4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. 5 */ 6 7 #ifndef lint 8 static char rcsid[] = "$OpenBSD: hack.save.c,v 1.4 2001/08/06 22:59:13 pjanzen Exp $"; 9 #endif /* not lint */ 10 11 #include "hack.h" 12 extern char genocided[60]; /* defined in Decl.c */ 13 extern char fut_geno[60]; /* idem */ 14 #include <signal.h> 15 #include <unistd.h> 16 17 extern char SAVEF[], nul[]; 18 extern char pl_character[PL_CSIZ]; 19 extern struct obj *restobjchn(); 20 extern struct monst *restmonchn(); 21 22 dosave(){ 23 if(dosave0(0)) { 24 settty("Be seeing you ...\n"); 25 exit(0); 26 } 27 #ifdef lint 28 return(0); 29 #endif /* lint */ 30 } 31 32 #ifndef NOSAVEONHANGUP 33 hangup(){ 34 (void) dosave0(1); 35 exit(1); 36 } 37 #endif /* NOSAVEONHANGUP */ 38 39 /* returns 1 if save successful */ 40 dosave0(hu) int hu; { 41 register fd, ofd; 42 int tmp; /* not register ! */ 43 44 (void) signal(SIGHUP, SIG_IGN); 45 (void) signal(SIGINT, SIG_IGN); 46 if((fd = creat(SAVEF, FMASK)) < 0) { 47 if(!hu) pline("Cannot open save file. (Continue or Quit)"); 48 (void) unlink(SAVEF); /* ab@unido */ 49 return(0); 50 } 51 if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ 52 u.uluck--; /* and unido!ab */ 53 savelev(fd,dlevel); 54 saveobjchn(fd, invent); 55 saveobjchn(fd, fcobj); 56 savemonchn(fd, fallen_down); 57 tmp = getuid(); 58 bwrite(fd, (char *) &tmp, sizeof tmp); 59 bwrite(fd, (char *) &flags, sizeof(struct flag)); 60 bwrite(fd, (char *) &dlevel, sizeof dlevel); 61 bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel); 62 bwrite(fd, (char *) &moves, sizeof moves); 63 bwrite(fd, (char *) &u, sizeof(struct you)); 64 if(u.ustuck) 65 bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id); 66 bwrite(fd, (char *) pl_character, sizeof pl_character); 67 bwrite(fd, (char *) genocided, sizeof genocided); 68 bwrite(fd, (char *) fut_geno, sizeof fut_geno); 69 savenames(fd); 70 for(tmp = 1; tmp <= maxdlevel; tmp++) { 71 extern int hackpid; 72 extern boolean level_exists[]; 73 74 if(tmp == dlevel || !level_exists[tmp]) continue; 75 glo(tmp); 76 if((ofd = open(lock, O_RDONLY)) < 0) { 77 if(!hu) pline("Error while saving: cannot read %s.", lock); 78 (void) close(fd); 79 (void) unlink(SAVEF); 80 if(!hu) done("tricked"); 81 return(0); 82 } 83 getlev(ofd, hackpid, tmp); 84 (void) close(ofd); 85 bwrite(fd, (char *) &tmp, sizeof tmp); /* level number */ 86 savelev(fd,tmp); /* actual level */ 87 (void) unlink(lock); 88 } 89 (void) close(fd); 90 glo(dlevel); 91 (void) unlink(lock); /* get rid of current level --jgm */ 92 glo(0); 93 (void) unlink(lock); 94 return(1); 95 } 96 97 dorecover(fd) 98 register fd; 99 { 100 register nfd; 101 int tmp; /* not a register ! */ 102 unsigned mid; /* idem */ 103 struct obj *otmp; 104 extern boolean restoring; 105 106 restoring = TRUE; 107 getlev(fd, 0, 0); 108 invent = restobjchn(fd); 109 for(otmp = invent; otmp; otmp = otmp->nobj) 110 if(otmp->owornmask) 111 setworn(otmp, otmp->owornmask); 112 fcobj = restobjchn(fd); 113 fallen_down = restmonchn(fd); 114 mread(fd, (char *) &tmp, sizeof tmp); 115 if(tmp != getuid()) { /* strange ... */ 116 (void) close(fd); 117 (void) unlink(SAVEF); 118 puts("Saved game was not yours."); 119 restoring = FALSE; 120 return(0); 121 } 122 mread(fd, (char *) &flags, sizeof(struct flag)); 123 mread(fd, (char *) &dlevel, sizeof dlevel); 124 mread(fd, (char *) &maxdlevel, sizeof maxdlevel); 125 mread(fd, (char *) &moves, sizeof moves); 126 mread(fd, (char *) &u, sizeof(struct you)); 127 if(u.ustuck) 128 mread(fd, (char *) &mid, sizeof mid); 129 mread(fd, (char *) pl_character, sizeof pl_character); 130 mread(fd, (char *) genocided, sizeof genocided); 131 mread(fd, (char *) fut_geno, sizeof fut_geno); 132 restnames(fd); 133 while(1) { 134 if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp) 135 break; 136 getlev(fd, 0, tmp); 137 glo(tmp); 138 if((nfd = creat(lock, FMASK)) < 0) 139 panic("Cannot open temp file %s!\n", lock); 140 savelev(nfd,tmp); 141 (void) close(nfd); 142 } 143 (void) lseek(fd, (off_t)0, 0); 144 getlev(fd, 0, 0); 145 (void) close(fd); 146 (void) unlink(SAVEF); 147 if(Punished) { 148 for(otmp = fobj; otmp; otmp = otmp->nobj) 149 if(otmp->olet == CHAIN_SYM) goto chainfnd; 150 panic("Cannot find the iron chain?"); 151 chainfnd: 152 uchain = otmp; 153 if(!uball){ 154 for(otmp = fobj; otmp; otmp = otmp->nobj) 155 if(otmp->olet == BALL_SYM && otmp->spe) 156 goto ballfnd; 157 panic("Cannot find the iron ball?"); 158 ballfnd: 159 uball = otmp; 160 } 161 } 162 if(u.ustuck) { 163 register struct monst *mtmp; 164 165 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 166 if(mtmp->m_id == mid) goto monfnd; 167 panic("Cannot find the monster ustuck."); 168 monfnd: 169 u.ustuck = mtmp; 170 } 171 #ifndef QUEST 172 setsee(); /* only to recompute seelx etc. - these weren't saved */ 173 #endif /* QUEST */ 174 docrt(); 175 restoring = FALSE; 176 return(1); 177 } 178 179 struct obj * 180 restobjchn(fd) 181 register fd; 182 { 183 register struct obj *otmp, *otmp2; 184 register struct obj *first = 0; 185 int xl; 186 #ifdef lint 187 /* suppress "used before set" warning from lint */ 188 otmp2 = 0; 189 #endif /* lint */ 190 while(1) { 191 mread(fd, (char *) &xl, sizeof(xl)); 192 if(xl == -1) break; 193 otmp = newobj(xl); 194 if(!first) first = otmp; 195 else otmp2->nobj = otmp; 196 mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj)); 197 if(!otmp->o_id) otmp->o_id = flags.ident++; 198 otmp2 = otmp; 199 } 200 if(first && otmp2->nobj){ 201 impossible("Restobjchn: error reading objchn."); 202 otmp2->nobj = 0; 203 } 204 return(first); 205 } 206 207 struct monst * 208 restmonchn(fd) 209 register fd; 210 { 211 register struct monst *mtmp, *mtmp2; 212 register struct monst *first = 0; 213 int xl; 214 215 struct permonst *monbegin; 216 long differ; 217 218 mread(fd, (char *)&monbegin, sizeof(monbegin)); 219 differ = (char *)(&mons[0]) - (char *)(monbegin); 220 221 #ifdef lint 222 /* suppress "used before set" warning from lint */ 223 mtmp2 = 0; 224 #endif /* lint */ 225 while(1) { 226 mread(fd, (char *) &xl, sizeof(xl)); 227 if(xl == -1) break; 228 mtmp = newmonst(xl); 229 if(!first) first = mtmp; 230 else mtmp2->nmon = mtmp; 231 mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 232 if(!mtmp->m_id) 233 mtmp->m_id = flags.ident++; 234 mtmp->data = (struct permonst *) 235 ((char *) mtmp->data + differ); 236 if(mtmp->minvent) 237 mtmp->minvent = restobjchn(fd); 238 mtmp2 = mtmp; 239 } 240 if(first && mtmp2->nmon){ 241 impossible("Restmonchn: error reading monchn."); 242 mtmp2->nmon = 0; 243 } 244 return(first); 245 } 246