Annotation of early-roguelike/rogue4/save.c, Revision 1.1.1.1
1.1 rubenllo 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: #include <time.h>
20: #define KERNEL
21: #include <signal.h>
22: #undef KERNEL
23: #include "rogue.h"
24:
25: void save_file(FILE *savef);
26: extern int rs_save_file(FILE *savef);
27: extern int rs_restore_file(FILE *inf);
28:
29: typedef struct stat STAT;
30:
31: extern char version[], encstr[];
32: extern bool _endwin;
33:
34: STAT sbuf;
35:
36: /*
37: * save_game:
38: * Implement the "save game" command
39: */
40: /* This has to be cleaned up, these goto's are annoying. */
41: bool
42: save_game(void)
43: {
44: register FILE *savef;
45: register int c;
46: char buf[256];
47:
48: /*
49: * get file name
50: */
51: mpos = 0;
52: over:
53: if (file_name[0] != '\0')
54: {
55: for (;;)
56: {
57: if (use_savedir)
58: msg("Save game? ");
59: else
60: msg("save file (%s)? ", file_name);
61: c = getchar();
62: mpos = 0;
63: if (c == ESCAPE)
64: {
65: msg("");
66: return FALSE;
67: }
68: else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
69: break;
70: else
71: msg("please answer Y or N");
72: }
73: if (c == 'y' || c == 'Y')
74: {
75: strcpy(buf, file_name);
76: goto gotfile;
77: }
78: }
79:
80: if (use_savedir)
81: {
82: /* You can't change the savefile if you're using the system
83: savedir, because that means you have privileges. */
84: msg("");
85: return FALSE;
86: }
87:
88: do
89: {
90: mpos = 0;
91: msg("file name: ");
92: buf[0] = '\0';
93: if (get_str(buf, stdscr) == QUIT)
94: {
95: quit:
96: msg("");
97: return FALSE;
98: }
99: mpos = 0;
100: gotfile:
101: /*
102: * test to see if the file exists
103: */
104: if (stat(buf, &sbuf) >= 0)
105: {
106: for (;;)
107: {
108: msg("File exists. Do you wish to overwrite it?");
109: mpos = 0;
110: if ((c = readchar()) == ESCAPE)
111: goto quit;
112: if (c == 'y' || c == 'Y')
113: break;
114: else if (c == 'n' || c == 'N')
115: goto over;
116: else
117: msg("Please answer Y or N");
118: }
119: msg("file name: %s", buf);
120: }
121: strcpy(file_name, buf);
122: if ((savef = fopen(file_name, "w")) == NULL)
123: {
124: msg(strerror(errno)); /* fake perror() */
125: if (use_savedir)
126: return FALSE;
127: }
128: } while (savef == NULL);
129:
130: /*
131: * write out encrpyted file (after a stat)
132: * The fwrite is to force allocation of the buffer before the write
133: */
134: save_file(savef);
135: return TRUE;
136: }
137:
138: /*
139: * auto_save:
140: * Automatically save a file. This is used if a HUP signal is
141: * recieved
142: */
143: void
144: auto_save(int sig)
145: {
146: register FILE *savef;
147:
148: md_ignore_signals();
149:
150: if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)
151: save_file(savef);
152: endwin();
153: exit(1);
154: }
155:
156: /*
157: * save_file:
158: * Write the saved game on the file
159: */
160: void
161: save_file(FILE *savef)
162: {
163: int slines = LINES;
164: int scols = COLS;
165:
166: /*
167: * close any open score file
168: */
169: if (score_file != NULL) {
170: fclose(score_file);
171: score_file = NULL;
172: }
173: move(LINES-1, 0);
174: refresh();
175: fstat(md_fileno(savef), &sbuf);
176: /*
177: * DO NOT DELETE. This forces stdio to allocate the output buffer
178: * so that malloc doesn't get confused on restart
179: */
180: fwrite("junk", 1, 5, savef);
181:
182: fseek(savef, 0L, 0);
183:
184: encwrite(version,strlen(version)+1,savef);
185: encwrite(&slines,sizeof(slines),savef);
186: encwrite(&scols,sizeof(scols),savef);
187: msg("");
188: rs_save_file(savef);
189:
190: fclose(savef);
191: }
192:
193: /*
194: * restore:
195: * Restore a saved game from a file with elaborate checks for file
196: * integrity from cheaters
197: */
198: bool
199: restore(char *file, char **envp)
200: {
201: FILE *inf;
202: register bool syml;
203: extern char **environ;
204: char buf[MAXSTR];
205: STAT sbuf2;
206: int slines, scols;
207:
208: if (strcmp(file, "-r") == 0)
209: file = file_name;
210:
211: #ifdef SIGTSTP
212: /*
213: * If a process can be suspended, this code wouldn't work
214: */
215: signal(SIGTSTP, SIG_IGN);
216: #endif
217:
218: if ((inf = fopen(file, "r")) == NULL)
219: {
220: if (use_savedir && errno == ENOENT)
221: {
222: /* We're using a system savefile which doesn't exist.
223: This isn't a fatal error, it means start a new game. */
224: return TRUE;
225: }
226: perror(file);
227: return FALSE;
228: }
229:
230: fflush(stdout);
231: encread(buf, strlen(version) + 1, inf);
232: if (strcmp(buf, version) != 0)
233: {
234: printf("Sorry, saved game is out of date.\n");
235: return FALSE;
236: }
237:
238: stat(file, &sbuf2);
239: fflush(stdout);
240: syml = issymlink(file);
241:
242: fflush(stdout);
243:
244: encread(&slines,sizeof(slines),inf);
245: encread(&scols,sizeof(scols),inf);
246:
247: /*
248: * we do not close the file so that we will have a hold of the
249: * inode for as long as possible
250: */
251:
252: initscr();
253:
254: if (slines > LINES)
255: {
256: endwin();
257: printf("Sorry, original game was played on a screen with %d lines.\n",slines);
258: printf("Current screen only has %d lines. Unable to restore game\n",LINES);
259: return(FALSE);
260: }
261:
262: if (scols > COLS)
263: {
264: endwin();
265: printf("Sorry, original game was played on a screen with %d columns.\n",scols);
266: printf("Current screen only has %d columns. Unable to restore game\n",COLS);
267: return(FALSE);
268: }
269:
270: hw = newwin(LINES, COLS, 0, 0);
271: keypad(stdscr,1);
272:
273: mpos = 0;
274: mvprintw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
275:
276: if (rs_restore_file(inf) == FALSE)
277: {
278: endwin();
279: printf("Cannot restore file\n");
280: return(FALSE);
281: }
282:
283: if (
284: #ifdef WIZARD
285: !wizard &&
286: #endif
287: md_unlink_open_file(file, inf) < 0)
288: {
289: endwin();
290: printf("Cannot unlink file\n");
291: return FALSE;
292: }
293:
294: /*
295: * defeat multiple restarting from the same place
296: */
297: #ifdef WIZARD
298: if (!wizard)
299: #endif
300: if (sbuf2.st_nlink != 1 || syml)
301: {
302: endwin();
303: printf("Cannot restore from a linked file\n");
304: return FALSE;
305: }
306:
307: if (pstats.s_hpt <= 0) {
308: endwin();
309: printf("This character is already dead.\n");
310: return FALSE;
311: }
312:
313: #ifdef SIGTSTP
314: signal(SIGTSTP, tstp);
315: #endif
316: environ = envp;
317: strcpy(file_name, file);
318: setup();
319: clearok(curscr, TRUE);
320: touchwin(stdscr);
321: srand(md_random_seed());
322: msg("file name: %s", file);
323: status();
324: playit();
325: return 0;
326: }
327:
328: /*
329: * encwrite:
330: * Perform an encrypted write
331: */
332: void
333: encwrite(void *starta, int size, FILE *outf)
334: {
335: register char *ep;
336: register char *start = (char *) starta;
337: ep = encstr;
338:
339: while (size--)
340: {
341: putc(*start++ ^ *ep++, outf);
342: if (*ep == '\0')
343: ep = encstr;
344: }
345: }
346:
347: /*
348: * encread:
349: * Perform an encrypted read
350: */
351: int
352: encread(void *starta, int size, FILE *inf)
353: {
354: register char *ep;
355: register int read_size;
356: register char *start = (char *) starta;
357:
358: if ((read_size = fread(start, 1, size, inf)) == 0)
359: return read_size;
360:
361: ep = encstr;
362:
363: while (size--)
364: {
365: *start++ ^= *ep++;
366: if (*ep == '\0')
367: ep = encstr;
368: }
369:
370: return read_size;
371: }
CVSweb