Mercurial > hg > early-roguelike
comparison rogue4/save.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Sat, 24 Oct 2009 16:52:52 +0000 |
parents | |
children | 63b9fd7d70ce |
comparison
equal
deleted
inserted
replaced
11:949d558c2162 | 12:9535a08ddc39 |
---|---|
1 /* | |
2 * save and restore routines | |
3 * | |
4 * @(#)save.c 4.15 (Berkeley) 5/10/82 | |
5 * | |
6 * Rogue: Exploring the Dungeons of Doom | |
7 * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman | |
8 * All rights reserved. | |
9 * | |
10 * See the file LICENSE.TXT for full copyright and licensing information. | |
11 */ | |
12 | |
13 #include <curses.h> | |
14 #include <sys/types.h> | |
15 #include <sys/stat.h> | |
16 #include <errno.h> | |
17 #include <string.h> | |
18 #include <stdlib.h> | |
19 #define KERNEL | |
20 #include <signal.h> | |
21 #undef KERNEL | |
22 #include "rogue.h" | |
23 | |
24 typedef struct stat STAT; | |
25 | |
26 extern char version[], encstr[]; | |
27 extern bool _endwin; | |
28 | |
29 STAT sbuf; | |
30 | |
31 /* | |
32 * save_game: | |
33 * Implement the "save game" command | |
34 */ | |
35 save_game() | |
36 { | |
37 register FILE *savef; | |
38 register int c; | |
39 char buf[MAXSTR]; | |
40 | |
41 /* | |
42 * get file name | |
43 */ | |
44 mpos = 0; | |
45 over: | |
46 if (file_name[0] != '\0') | |
47 { | |
48 for (;;) | |
49 { | |
50 msg("save file (%s)? ", file_name); | |
51 c = getchar(); | |
52 mpos = 0; | |
53 if (c == ESCAPE) | |
54 { | |
55 msg(""); | |
56 return FALSE; | |
57 } | |
58 else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y') | |
59 break; | |
60 else | |
61 msg("please answer Y or N"); | |
62 } | |
63 if (c == 'y' || c == 'Y') | |
64 { | |
65 strcpy(buf, file_name); | |
66 goto gotfile; | |
67 } | |
68 } | |
69 | |
70 do | |
71 { | |
72 mpos = 0; | |
73 msg("file name: "); | |
74 buf[0] = '\0'; | |
75 if (get_str(buf, stdscr) == QUIT) | |
76 { | |
77 quit: | |
78 msg(""); | |
79 return FALSE; | |
80 } | |
81 mpos = 0; | |
82 gotfile: | |
83 /* | |
84 * test to see if the file exists | |
85 */ | |
86 if (stat(buf, &sbuf) >= 0) | |
87 { | |
88 for (;;) | |
89 { | |
90 msg("File exists. Do you wish to overwrite it?"); | |
91 mpos = 0; | |
92 if ((c = readchar()) == ESCAPE) | |
93 goto quit; | |
94 if (c == 'y' || c == 'Y') | |
95 break; | |
96 else if (c == 'n' || c == 'N') | |
97 goto over; | |
98 else | |
99 msg("Please answer Y or N"); | |
100 } | |
101 msg("file name: %s", buf); | |
102 } | |
103 strcpy(file_name, buf); | |
104 if ((savef = fopen(file_name, "w")) == NULL) | |
105 msg(strerror(errno)); /* fake perror() */ | |
106 } while (savef == NULL); | |
107 | |
108 /* | |
109 * write out encrpyted file (after a stat) | |
110 * The fwrite is to force allocation of the buffer before the write | |
111 */ | |
112 save_file(savef); | |
113 return TRUE; | |
114 } | |
115 | |
116 /* | |
117 * auto_save: | |
118 * Automatically save a file. This is used if a HUP signal is | |
119 * recieved | |
120 */ | |
121 void | |
122 auto_save(int sig) | |
123 { | |
124 register FILE *savef; | |
125 | |
126 md_ignore_signals(); | |
127 | |
128 if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL) | |
129 save_file(savef); | |
130 endwin(); | |
131 exit(1); | |
132 } | |
133 | |
134 /* | |
135 * save_file: | |
136 * Write the saved game on the file | |
137 */ | |
138 save_file(savef) | |
139 register FILE *savef; | |
140 { | |
141 int slines = LINES; | |
142 int scols = COLS; | |
143 | |
144 /* | |
145 * close any open score file | |
146 */ | |
147 close(fd); | |
148 move(LINES-1, 0); | |
149 refresh(); | |
150 fstat(md_fileno(savef), &sbuf); | |
151 /* | |
152 * DO NOT DELETE. This forces stdio to allocate the output buffer | |
153 * so that malloc doesn't get confused on restart | |
154 */ | |
155 fwrite("junk", 1, 5, savef); | |
156 | |
157 fseek(savef, 0L, 0); | |
158 | |
159 encwrite(version,strlen(version)+1,savef); | |
160 encwrite(&sbuf.st_ino,sizeof(sbuf.st_ino),savef); | |
161 encwrite(&sbuf.st_dev,sizeof(sbuf.st_dev),savef); | |
162 encwrite(&sbuf.st_ctime,sizeof(sbuf.st_ctime),savef); | |
163 encwrite(&sbuf.st_mtime,sizeof(sbuf.st_mtime),savef); | |
164 encwrite(&slines,sizeof(slines),savef); | |
165 encwrite(&scols,sizeof(scols),savef); | |
166 msg(""); | |
167 rs_save_file(savef); | |
168 | |
169 fclose(savef); | |
170 } | |
171 | |
172 /* | |
173 * restore: | |
174 * Restore a saved game from a file with elaborate checks for file | |
175 * integrity from cheaters | |
176 */ | |
177 restore(file, envp) | |
178 register char *file; | |
179 char **envp; | |
180 { | |
181 register int inf; | |
182 register bool syml; | |
183 extern char **environ; | |
184 char buf[MAXSTR]; | |
185 STAT sbuf2; | |
186 int slines, scols; | |
187 | |
188 if (strcmp(file, "-r") == 0) | |
189 file = file_name; | |
190 | |
191 #ifdef SIGTSTP | |
192 /* | |
193 * If a process can be suspended, this code wouldn't work | |
194 */ | |
195 signal(SIGTSTP, SIG_IGN); | |
196 #endif | |
197 | |
198 if ((inf = open(file, 0)) < 0) | |
199 { | |
200 perror(file); | |
201 return FALSE; | |
202 } | |
203 | |
204 fflush(stdout); | |
205 encread(buf, strlen(version) + 1, inf); | |
206 if (strcmp(buf, version) != 0) | |
207 { | |
208 printf("Sorry, saved game is out of date.\n"); | |
209 return FALSE; | |
210 } | |
211 | |
212 fstat(inf, &sbuf2); | |
213 fflush(stdout); | |
214 syml = issymlink(file); | |
215 if ( | |
216 #ifdef WIZARD | |
217 !wizard && | |
218 #endif | |
219 md_unlink(file) < 0) | |
220 { | |
221 printf("Cannot unlink file\n"); | |
222 return FALSE; | |
223 } | |
224 | |
225 fflush(stdout); | |
226 | |
227 encread(&sbuf.st_ino,sizeof(sbuf.st_ino), inf); | |
228 encread(&sbuf.st_dev,sizeof(sbuf.st_dev), inf); | |
229 encread(&sbuf.st_ctime,sizeof(sbuf.st_ctime), inf); | |
230 encread(&sbuf.st_mtime,sizeof(sbuf.st_mtime), inf); | |
231 encread(&slines,sizeof(slines),inf); | |
232 encread(&scols,sizeof(scols),inf); | |
233 | |
234 /* | |
235 * we do not close the file so that we will have a hold of the | |
236 * inode for as long as possible | |
237 */ | |
238 | |
239 initscr(); | |
240 | |
241 if (slines > LINES) | |
242 { | |
243 printf("Sorry, original game was played on a screen with %d lines.\n",slines); | |
244 printf("Current screen only has %d lines. Unable to restore game\n",LINES); | |
245 return(FALSE); | |
246 } | |
247 | |
248 if (scols > COLS) | |
249 { | |
250 printf("Sorry, original game was played on a screen with %d columns.\n",scols); | |
251 printf("Current screen only has %d columns. Unable to restore game\n",COLS); | |
252 return(FALSE); | |
253 } | |
254 | |
255 hw = newwin(LINES, COLS, 0, 0); | |
256 keypad(stdscr,1); | |
257 | |
258 mpos = 0; | |
259 mvprintw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); | |
260 | |
261 /* | |
262 * defeat multiple restarting from the same place | |
263 */ | |
264 #ifdef WIZARD | |
265 if (!wizard) | |
266 #endif | |
267 if (sbuf2.st_nlink != 1 || syml) | |
268 { | |
269 printf("Cannot restore from a linked file\n"); | |
270 return FALSE; | |
271 } | |
272 | |
273 if (rs_restore_file(inf) == FALSE) | |
274 { | |
275 endwin(); | |
276 printf("Cannot restore file\n"); | |
277 return(FALSE); | |
278 } | |
279 | |
280 #ifdef SIGTSTP | |
281 signal(SIGTSTP, tstp); | |
282 #endif | |
283 environ = envp; | |
284 strcpy(file_name, file); | |
285 setup(); | |
286 clearok(curscr, TRUE); | |
287 touchwin(stdscr); | |
288 srand(getpid()); | |
289 msg("file name: %s", file); | |
290 status(); | |
291 playit(); | |
292 return 0; | |
293 } | |
294 | |
295 /* | |
296 * encwrite: | |
297 * Perform an encrypted write | |
298 */ | |
299 encwrite(starta, size, outf) | |
300 void *starta; | |
301 unsigned int size; | |
302 register FILE *outf; | |
303 { | |
304 register char *ep; | |
305 register char *start = (char *) starta; | |
306 ep = encstr; | |
307 | |
308 while (size--) | |
309 { | |
310 putc(*start++ ^ *ep++, outf); | |
311 if (*ep == '\0') | |
312 ep = encstr; | |
313 } | |
314 } | |
315 | |
316 /* | |
317 * encread: | |
318 * Perform an encrypted read | |
319 */ | |
320 encread(starta, size, inf) | |
321 register void *starta; | |
322 unsigned int size; | |
323 register int inf; | |
324 { | |
325 register char *ep; | |
326 register int read_size; | |
327 register char *start = (char *) starta; | |
328 | |
329 if ((read_size = read(inf, start, size)) == -1 || read_size == 0) | |
330 return read_size; | |
331 | |
332 ep = encstr; | |
333 | |
334 while (size--) | |
335 { | |
336 *start++ ^= *ep++; | |
337 if (*ep == '\0') | |
338 ep = encstr; | |
339 } | |
340 | |
341 return read_size; | |
342 } |