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 }