Neale Pickett
·
2013-07-18
solve.c
1/*
2 * save and restore routines
3 *
4 * @(#)solve.c 4.33 (Berkeley) 06/01/83
5 */
6
7#include <curses.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <errno.h>
11#include <signal.h>
12#include <unistd.h>
13#include "netprot.h"
14#include "netwait.h"
15#define NSIG 32
16
17typedef struct stat STAT;
18
19extern char version[], encstr[];
20
21#ifdef attron
22# define CE clr_eol
23#else attron
24extern bool _endwin;
25#endif attron
26
27static char Frob;
28
29static STAT Sbuf;
30
31/*
32 * save_game:
33 * Implement the "save game" command
34 */
35void
36save_game(void)
37{
38 FILE *savef;
39 int c;
40 auto char buf[MAXSTR];
41
42 /*
43 * get file name
44 */
45 Mpos = 0;
46over:
47 if (File_name[0] != '\0')
48 {
49 for (;;)
50 {
51 msg("save file (%s)? ", File_name);
52 c = getchar();
53 Mpos = 0;
54 if (c == ESCAPE)
55 {
56 msg("");
57 return;
58 }
59 else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
60 break;
61 else
62 msg("please answer Y or N");
63 }
64 if (c == 'y' || c == 'Y')
65 {
66 addstr("Yes\n");
67 refresh();
68 strcpy(buf, File_name);
69 goto gotfile;
70 }
71 }
72
73 do
74 {
75 Mpos = 0;
76 msg("file name: ");
77 buf[0] = '\0';
78 if (get_str(buf, stdscr) == QUIT)
79 {
80quit_it:
81 msg("");
82 return;
83 }
84 Mpos = 0;
85gotfile:
86 /*
87 * test to see if the file exists
88 */
89 if (stat(buf, &Sbuf) >= 0)
90 {
91 for (;;)
92 {
93 msg("File exists. Do you wish to overwrite it?");
94 Mpos = 0;
95 if ((c = readchar()) == ESCAPE)
96 goto quit_it;
97 if (c == 'y' || c == 'Y')
98 break;
99 else if (c == 'n' || c == 'N')
100 goto over;
101 else
102 msg("Please answer Y or N");
103 }
104 msg("file name: %s", buf);
105 unlink(File_name);
106 }
107 strcpy(File_name, buf);
108 if ((savef = fopen(File_name, "w")) == NULL)
109 msg(strerror(errno));
110 } while (savef == NULL);
111
112 save_file(savef);
113 /* NOTREACHED */
114}
115
116/*
117 * auto_save:
118 * Automatically save a file. This is used if a HUP signal is
119 * recieved
120 */
121void
122auto_save(int sig)
123{
124 FILE *savef;
125 int i;
126
127 for (i = 0; i < NSIG; i++)
128 signal(i, SIG_IGN);
129 if (File_name[0] != '\0' && ((savef = fopen(File_name, "w")) != NULL ||
130 (unlink(File_name) >= 0 && (savef = fopen(File_name, "w")) != NULL)))
131 save_file(savef);
132 exit(0);
133}
134
135/*
136 * save_file:
137 * Write the saved game on the file
138 */
139void
140save_file(FILE *savef)
141{
142 int _putchar();
143
144 mvcur(0, COLS - 1, LINES - 1, 0);
145 putchar('\n');
146 endwin();
147 resetltchars();
148 chmod(File_name, 0400);
149 /*
150 * DO NOT DELETE. This forces stdio to allocate the output buffer
151 * so that malloc doesn't get confused on restart
152 */
153 Frob = 0;
154 fwrite(&Frob, sizeof Frob, 1, savef);
155
156#ifndef attron
157 _endwin = TRUE;
158#endif attron
159 fstat(fileno(savef), &Sbuf);
160 encwrite(version, ((char *) sbrk(0) - version), savef);
161 printf("pointer is: %ld\n",ftell(savef));
162/*
163 fseek(savef, (long) (char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version), SEEK_SET);
164*/
165 fseek(savef, (long) ((char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version))%100+1000000, SEEK_SET);
166 printf("pointer is: %ld\n",ftell(savef));
167 fflush(savef);
168 printf("pointer is: %ld\n",ftell(savef));
169 fstat(fileno(savef), &Sbuf);
170 fwrite(&Sbuf.st_ctime, sizeof Sbuf.st_ctime, 1, savef);
171 fclose(savef);
172 exit(0);
173}
174
175/*
176 * restore:
177 * Restore a saved game from a file with elaborate checks for file
178 * integrity from cheaters
179 */
180bool
181restore(char *file, char **envp)
182{
183 int inf;
184 bool syml;
185 char *sp;
186 char fb;
187 extern char **environ;
188 auto char buf[MAXSTR];
189 auto STAT sbuf2;
190
191 if (strcmp(file, "-r") == 0)
192 file = File_name;
193
194#ifdef SIGTSTP
195 /*
196 * If a process can be suspended, this code wouldn't work
197 */
198# ifdef SIG_HOLD
199 signal(SIGTSTP, SIG_HOLD);
200# else
201 signal(SIGTSTP, SIG_IGN);
202# endif
203#endif
204
205 if ((inf = open(file, 0)) < 0)
206 {
207 perror(file);
208 return FALSE;
209 }
210 fstat(inf, &sbuf2);
211 syml = is_symlink(file);
212 if (
213#ifdef MASTER
214 !Wizard &&
215#endif
216 unlink(file) < 0)
217 {
218 printf("Cannot unlink file\n");
219 return FALSE;
220 }
221
222 fflush(stdout);
223 read(inf, &Frob, sizeof Frob);
224 fb = Frob;
225 encread(buf, (unsigned) strlen(version) + 1, inf);
226 if (strcmp(buf, version) != 0)
227 {
228 printf("Sorry, saved game is out of date.\n");
229 return FALSE;
230 }
231
232 sbuf2.st_size -= sizeof Frob;
233 brk(version + sbuf2.st_size);
234 lseek(inf, (long) sizeof Frob, 0);
235 Frob = fb;
236 encread(version, (unsigned int) sbuf2.st_size, inf);
237/*
238 lseek(inf, (long) (char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version), 0);
239*/
240 lseek(inf, (long) ((char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version))%100+1000000, 0);
241 read(inf, &Sbuf.st_ctime, sizeof Sbuf.st_ctime);
242 /*
243 * we do not close the file so that we will have a hold of the
244 * inode for as long as possible
245 */
246
247#ifdef MASTER
248 if (!Wizard)
249#endif
250 if (sbuf2.st_ino != Sbuf.st_ino || sbuf2.st_dev != Sbuf.st_dev)
251 {
252 printf("Sorry, saved game is not in the same file.\n");
253 return FALSE;
254 }
255 else if (sbuf2.st_ctime - Sbuf.st_ctime > 15)
256 {
257 printf("Sorry, file has been touched, so this score won't be recorded\n");
258 Noscore = TRUE;
259 }
260 Mpos = 0;
261/* printw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); */
262/*
263 printw("%s: %s", file, ctime(&sbuf2.st_mtime));
264*/
265
266 /*
267 * defeat multiple restarting from the same place
268 */
269#ifdef MASTER
270 if (!Wizard)
271#endif
272 if (sbuf2.st_nlink != 1 || syml)
273 {
274 printf("Cannot restore from a linked file\n");
275 return FALSE;
276 }
277
278 if (Pstats.s_hpt <= 0)
279 {
280 printf("\"He's dead, Jim\"\n");
281 return FALSE;
282 }
283#ifdef SIGTSTP
284 signal(SIGTSTP, tstp);
285#endif
286
287 environ = envp;
288 gettmode();
289 if ((sp = getenv("TERM")) == NULL) {
290 fprintf(stderr, "no TERM variable");
291 exit(1);
292 }
293 setterm(sp);
294 strcpy(File_name, file);
295 initscr(); /* Start up cursor package */
296 setup();
297 clearok(curscr, TRUE);
298 srand(getpid());
299 msg("file name: %s", file);
300 playit();
301 /*NOTREACHED*/
302}
303
304/*
305 * encwrite:
306 * Perform an encrypted write
307 */
308void
309encwrite(char *start, unsigned int size, FILE *outf)
310{
311 char *e1, *e2, fb;
312 int temp;
313 extern char statlist[];
314
315 e1 = encstr;
316 e2 = statlist;
317 fb = Frob;
318
319 while (size--)
320 {
321 putc(*start++ ^ *e1 ^ *e2 ^ fb, outf);
322 temp = *e1++;
323 fb += temp * *e2++;
324 if (*e1 == '\0')
325 e1 = encstr;
326 if (*e2 == '\0')
327 e2 = statlist;
328 }
329}
330
331/*
332 * encread:
333 * Perform an encrypted read
334 */
335encread(char *start, unsigned int size, int inf)
336{
337 char *e1, *e2, fb;
338 int temp, read_size;
339 extern char statlist[];
340
341 fb = Frob;
342
343 if ((read_size = read(inf, start, size)) == 0 || read_size == -1)
344 return;
345
346 e1 = encstr;
347 e2 = statlist;
348
349 while (size--)
350 {
351 *start++ ^= *e1 ^ *e2 ^ fb;
352 temp = *e1++;
353 fb += temp * *e2++;
354 if (*e1 == '\0')
355 e1 = encstr;
356 if (*e2 == '\0')
357 e2 = statlist;
358 }
359}
360
361#ifdef SCOREFILE
362/*
363 * read_scrore
364 * Read in the score file
365 */
366rd_score(SCORE *top_ten, int fd)
367{
368 encread((char *) top_ten, numscores * sizeof (SCORE), fd);
369}
370
371/*
372 * write_scrore
373 * Read in the score file
374 */
375wr_score(SCORE *top_ten, FILE *outf)
376{
377 encwrite((char *) top_ten, numscores * sizeof (SCORE), outf);
378}
379#endif