comparison srogue/save.c @ 36:2128c7dc8a40

Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 25 Nov 2010 12:21:41 +0000
parents
children 34d7a614855e
comparison
equal deleted inserted replaced
35:05018c63a721 36:2128c7dc8a40
1 /*
2 * save and restore routines
3 *
4 * @(#)save.c 9.0 (rdk) 7/17/84
5 *
6 * Super-Rogue
7 * Copyright (C) 1984 Robert D. Kindelberger
8 * All rights reserved.
9 *
10 * Based on "Rogue: Exploring the Dungeons of Doom"
11 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
12 * All rights reserved.
13 *
14 * See the file LICENSE.TXT for full copyright and licensing information.
15 */
16
17 #include <unistd.h>
18 #include <ctype.h>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include "rogue.h"
25 #include "rogue.ext"
26
27 #ifdef BSD
28 #define srand48(seed) srandom(seed)
29 #endif
30
31 EXTCHAR version[];
32 EXTCHAR *ctime();
33
34 typedef struct stat STAT;
35 STAT sbuf;
36
37 /*
38 * ignore:
39 * Ignore ALL signals possible
40 */
41 ignore()
42 {
43 int i;
44
45 for (i = 0; i < NSIG; i++)
46 signal(i, SIG_IGN);
47 }
48
49 /*
50 * save_game:
51 * Save the current game
52 */
53 save_game()
54 {
55 reg FILE *savef;
56 reg int c;
57 char buf[LINLEN];
58
59 mpos = 0;
60 if (file_name[0] != '\0') {
61 msg("Save file (%s)? ", file_name);
62 do {
63 c = wgetch(cw);
64 if(c == ESCAPE) {
65 msg("");
66 return FALSE;
67 }
68 } while (c != 'n' && c != 'y');
69 mpos = 0;
70 if (c == 'y')
71 goto gotfile;
72 }
73 msg("File name: ");
74 mpos = 0;
75 buf[0] = '\0';
76 if (get_str(buf, cw) == QUIT) {
77 msg("");
78 return FALSE;
79 }
80 msg("");
81 strcpy(file_name, buf);
82 gotfile:
83 c = dosave(); /* try to save this game */
84 if (c == FALSE)
85 msg("Could not save game to file %s", file_name);
86 return c;
87 }
88
89 /*
90 * auto_save:
91 * Automatically save a game
92 */
93 void
94 auto_save(int a)
95 {
96 dosave(); /* save this game */
97 byebye(1); /* so long for now */
98 }
99
100 /*
101 * game_err:
102 * When an error occurs. Set error flag and save game.
103 */
104 void
105 game_err(int a)
106 {
107 int ok;
108
109 ok = dosave(); /* try to save this game */
110 clear();
111 refresh();
112 endwin();
113
114 printf("\nInternal error !!!\n\nYour game was ");
115 if (ok)
116 printf("saved.");
117 else
118 printf("NOT saveable.");
119
120 fflush(stdout);
121
122 #ifdef SIGIOT
123 signal(SIGIOT, SIG_DFL); /* allow core dump signal */
124 #endif
125
126 abort(); /* cause core dump */
127 byebye(3);
128 }
129
130 /*
131 * dosave:
132 * Set UID back to user and save the game
133 */
134 dosave()
135 {
136 FILE *savef;
137
138 ignore();
139 setuid(playuid);
140 setgid(playgid);
141 umask(022);
142
143 if (file_name[0] != '\0') {
144 if ((savef = fopen(file_name,"w")) != NULL)
145 {
146 save_file(savef);
147 return TRUE;
148 }
149 }
150 return FALSE;
151 }
152
153 /*
154 * save_file:
155 * Do the actual save of this game to a file
156 */
157 save_file(savef)
158 FILE *savef;
159 {
160 reg int fnum;
161 int slines = LINES;
162 int scols = COLS;
163
164 #ifdef __DJGPP__ /* st_ino w/ DJGPP under WinXP broken */
165 _djstat_flags |= _STAT_INODE; /* so turn off computing it for now */
166 #endif
167
168 /*
169 * force allocation of the buffer now so that inodes, etc
170 * can be checked when restoring saved games.
171 */
172 fnum = fileno(savef);
173 fstat(fnum, &sbuf);
174 write(fnum, "RDK", 4);
175 lseek(fnum, 0L, 0);
176 encwrite(version,strlen(version)+1,savef);
177 encwrite(&sbuf.st_ino,sizeof(sbuf.st_ino),savef);
178 encwrite(&sbuf.st_dev,sizeof(sbuf.st_dev),savef);
179 encwrite(&sbuf.st_ctime,sizeof(sbuf.st_ctime),savef);
180 encwrite(&sbuf.st_mtime,sizeof(sbuf.st_mtime),savef);
181 encwrite(&slines,sizeof(slines),savef);
182 encwrite(&scols,sizeof(scols),savef);
183 msg("");
184 rs_save_file(savef);
185 close(fnum);
186 signal(SIGINT, byebye);
187 signal(SIGQUIT, byebye);
188 wclear(cw);
189 draw(cw);
190 }
191
192 /*
193 * restore:
194 * Restore a saved game from a file
195 */
196 restore(file, envp)
197 char *file, **envp;
198 {
199 register inf, pid;
200 int ret_status;
201 #ifndef _AIX
202 extern char **environ;
203 #endif
204 #ifdef __DJGPP__ /* st_ino w/ DJGPP under WinXP broken */
205 _djstat_flags |= _STAT_INODE; /* so turn off computing it for now */
206 #endif
207 char buf[LINLEN];
208 STAT sbuf2;
209 int slines, scols;
210
211 if ((inf = open(file, O_RDONLY)) < 0) {
212 printf("Cannot read save game %s\n",file);
213 return FALSE;
214 }
215
216 encread(buf, strlen(version) + 1, inf);
217
218 if (strcmp(buf, version) != 0) {
219 printf("Sorry, saved game version is out of date.\n");
220 return FALSE;
221 }
222
223 fstat(inf, &sbuf2);
224
225 encread(&sbuf.st_ino,sizeof(sbuf.st_ino), inf);
226 encread(&sbuf.st_dev,sizeof(sbuf.st_dev), inf);
227 encread(&sbuf.st_ctime,sizeof(sbuf.st_ctime), inf);
228 encread(&sbuf.st_mtime,sizeof(sbuf.st_mtime), inf);
229 encread(&slines,sizeof(slines),inf);
230 encread(&scols,sizeof(scols),inf);
231
232 /*
233 * we do not close the file so that we will have a hold of the
234 * inode for as long as possible
235 */
236
237 if (!wizard)
238 {
239 if(sbuf2.st_ino!=sbuf.st_ino || sbuf2.st_dev!=sbuf.st_dev) {
240 printf("Sorry, saved game is not in the same file.\n");
241 return FALSE;
242 }
243 }
244
245 #ifdef __INTERIX
246 setenv("TERM","interix");
247 #endif
248
249 initscr();
250
251 if (slines > LINES)
252 {
253 endwin();
254 printf("Sorry, original game was played on a screen with %d lines.\n",slines);
255 printf("Current screen only has %d lines. Unable to restore game\n",LINES);
256 return(FALSE);
257 }
258
259 if (scols > COLS)
260 {
261 endwin();
262 printf("Sorry, original game was played on a screen with %d columns.\n", scols);
263 printf("Current screen only has %d columns. Unable to restore game\n",COLS);
264 return(FALSE);
265 }
266
267 cw = newwin(LINES, COLS, 0, 0);
268 mw = newwin(LINES, COLS, 0, 0);
269 hw = newwin(LINES, COLS, 0, 0);
270
271 mpos = 0;
272 mvwprintw(cw, 0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
273
274 /* defeat multiple restarting from the same place */
275
276 if (!wizard)
277 {
278 if (sbuf2.st_nlink != 1)
279 {
280 endwin();
281 printf("Cannot restore from a linked file\n");
282 return FALSE;
283 }
284 }
285
286 if (rs_restore_file(inf) == FALSE)
287 {
288 endwin();
289 printf("Cannot restore file\n");
290 return(FALSE);
291 }
292
293 #if defined(__CYGWIN__) || defined(__DJGPP__)
294 close(inf);
295 #endif
296 if (!wizard)
297 {
298 #ifndef __DJGPP__
299 endwin();
300 while((pid = fork()) < 0)
301 sleep(1);
302
303 /* set id to unlink file */
304 if(pid == 0)
305 {
306 setuid(playuid);
307 setgid(playgid);
308 unlink(file);
309 exit(0);
310 }
311 /* wait for unlink to finish */
312 else
313 {
314 while(wait(&ret_status) != pid)
315 continue;
316 if (ret_status < 0)
317 {
318 printf("Cannot unlink file\n");
319 return FALSE;
320 }
321 }
322 #else
323 if (unlink(file) < 0)
324 {
325 printf("Cannot unlink file\n");
326 return FALSE;
327 }
328 #endif
329
330 }
331
332 environ = envp;
333
334 strcpy(file_name, file);
335 setup();
336 restscr(cw);
337 srand48(getpid());
338 playit();
339 }