rogue

Ken Arnold's Rogue
git clone https://git.woozle.org/neale/rogue.git

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