mirror of https://github.com/nealey/rogue
380 lines
7.1 KiB
C
380 lines
7.1 KiB
C
/*
|
|
* save and restore routines
|
|
*
|
|
* @(#)solve.c 4.33 (Berkeley) 06/01/83
|
|
*/
|
|
|
|
#include <curses.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include "netprot.h"
|
|
#include "netwait.h"
|
|
#define NSIG 32
|
|
|
|
typedef struct stat STAT;
|
|
|
|
extern char version[], encstr[];
|
|
|
|
#ifdef attron
|
|
# define CE clr_eol
|
|
#else attron
|
|
extern bool _endwin;
|
|
#endif attron
|
|
|
|
static char Frob;
|
|
|
|
static STAT Sbuf;
|
|
|
|
/*
|
|
* save_game:
|
|
* Implement the "save game" command
|
|
*/
|
|
void
|
|
save_game(void)
|
|
{
|
|
FILE *savef;
|
|
int c;
|
|
auto char buf[MAXSTR];
|
|
|
|
/*
|
|
* get file name
|
|
*/
|
|
Mpos = 0;
|
|
over:
|
|
if (File_name[0] != '\0')
|
|
{
|
|
for (;;)
|
|
{
|
|
msg("save file (%s)? ", File_name);
|
|
c = getchar();
|
|
Mpos = 0;
|
|
if (c == ESCAPE)
|
|
{
|
|
msg("");
|
|
return;
|
|
}
|
|
else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
|
|
break;
|
|
else
|
|
msg("please answer Y or N");
|
|
}
|
|
if (c == 'y' || c == 'Y')
|
|
{
|
|
addstr("Yes\n");
|
|
refresh();
|
|
strcpy(buf, File_name);
|
|
goto gotfile;
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
Mpos = 0;
|
|
msg("file name: ");
|
|
buf[0] = '\0';
|
|
if (get_str(buf, stdscr) == QUIT)
|
|
{
|
|
quit_it:
|
|
msg("");
|
|
return;
|
|
}
|
|
Mpos = 0;
|
|
gotfile:
|
|
/*
|
|
* test to see if the file exists
|
|
*/
|
|
if (stat(buf, &Sbuf) >= 0)
|
|
{
|
|
for (;;)
|
|
{
|
|
msg("File exists. Do you wish to overwrite it?");
|
|
Mpos = 0;
|
|
if ((c = readchar()) == ESCAPE)
|
|
goto quit_it;
|
|
if (c == 'y' || c == 'Y')
|
|
break;
|
|
else if (c == 'n' || c == 'N')
|
|
goto over;
|
|
else
|
|
msg("Please answer Y or N");
|
|
}
|
|
msg("file name: %s", buf);
|
|
unlink(File_name);
|
|
}
|
|
strcpy(File_name, buf);
|
|
if ((savef = fopen(File_name, "w")) == NULL)
|
|
msg(strerror(errno));
|
|
} while (savef == NULL);
|
|
|
|
save_file(savef);
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
/*
|
|
* auto_save:
|
|
* Automatically save a file. This is used if a HUP signal is
|
|
* recieved
|
|
*/
|
|
void
|
|
auto_save(int sig)
|
|
{
|
|
FILE *savef;
|
|
int i;
|
|
|
|
for (i = 0; i < NSIG; i++)
|
|
signal(i, SIG_IGN);
|
|
if (File_name[0] != '\0' && ((savef = fopen(File_name, "w")) != NULL ||
|
|
(unlink(File_name) >= 0 && (savef = fopen(File_name, "w")) != NULL)))
|
|
save_file(savef);
|
|
exit(0);
|
|
}
|
|
|
|
/*
|
|
* save_file:
|
|
* Write the saved game on the file
|
|
*/
|
|
void
|
|
save_file(FILE *savef)
|
|
{
|
|
int _putchar();
|
|
|
|
mvcur(0, COLS - 1, LINES - 1, 0);
|
|
putchar('\n');
|
|
endwin();
|
|
resetltchars();
|
|
chmod(File_name, 0400);
|
|
/*
|
|
* DO NOT DELETE. This forces stdio to allocate the output buffer
|
|
* so that malloc doesn't get confused on restart
|
|
*/
|
|
Frob = 0;
|
|
fwrite(&Frob, sizeof Frob, 1, savef);
|
|
|
|
#ifndef attron
|
|
_endwin = TRUE;
|
|
#endif attron
|
|
fstat(fileno(savef), &Sbuf);
|
|
encwrite(version, ((char *) sbrk(0) - version), savef);
|
|
printf("pointer is: %ld\n",ftell(savef));
|
|
/*
|
|
fseek(savef, (long) (char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version), SEEK_SET);
|
|
*/
|
|
fseek(savef, (long) ((char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version))%100+1000000, SEEK_SET);
|
|
printf("pointer is: %ld\n",ftell(savef));
|
|
fflush(savef);
|
|
printf("pointer is: %ld\n",ftell(savef));
|
|
fstat(fileno(savef), &Sbuf);
|
|
fwrite(&Sbuf.st_ctime, sizeof Sbuf.st_ctime, 1, savef);
|
|
fclose(savef);
|
|
exit(0);
|
|
}
|
|
|
|
/*
|
|
* restore:
|
|
* Restore a saved game from a file with elaborate checks for file
|
|
* integrity from cheaters
|
|
*/
|
|
bool
|
|
restore(char *file, char **envp)
|
|
{
|
|
int inf;
|
|
bool syml;
|
|
char *sp;
|
|
char fb;
|
|
extern char **environ;
|
|
auto char buf[MAXSTR];
|
|
auto STAT sbuf2;
|
|
|
|
if (strcmp(file, "-r") == 0)
|
|
file = File_name;
|
|
|
|
#ifdef SIGTSTP
|
|
/*
|
|
* If a process can be suspended, this code wouldn't work
|
|
*/
|
|
# ifdef SIG_HOLD
|
|
signal(SIGTSTP, SIG_HOLD);
|
|
# else
|
|
signal(SIGTSTP, SIG_IGN);
|
|
# endif
|
|
#endif
|
|
|
|
if ((inf = open(file, 0)) < 0)
|
|
{
|
|
perror(file);
|
|
return FALSE;
|
|
}
|
|
fstat(inf, &sbuf2);
|
|
syml = is_symlink(file);
|
|
if (
|
|
#ifdef MASTER
|
|
!Wizard &&
|
|
#endif
|
|
unlink(file) < 0)
|
|
{
|
|
printf("Cannot unlink file\n");
|
|
return FALSE;
|
|
}
|
|
|
|
fflush(stdout);
|
|
read(inf, &Frob, sizeof Frob);
|
|
fb = Frob;
|
|
encread(buf, (unsigned) strlen(version) + 1, inf);
|
|
if (strcmp(buf, version) != 0)
|
|
{
|
|
printf("Sorry, saved game is out of date.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
sbuf2.st_size -= sizeof Frob;
|
|
brk(version + sbuf2.st_size);
|
|
lseek(inf, (long) sizeof Frob, 0);
|
|
Frob = fb;
|
|
encread(version, (unsigned int) sbuf2.st_size, inf);
|
|
/*
|
|
lseek(inf, (long) (char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version), 0);
|
|
*/
|
|
lseek(inf, (long) ((char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version))%100+1000000, 0);
|
|
read(inf, &Sbuf.st_ctime, sizeof Sbuf.st_ctime);
|
|
/*
|
|
* we do not close the file so that we will have a hold of the
|
|
* inode for as long as possible
|
|
*/
|
|
|
|
#ifdef MASTER
|
|
if (!Wizard)
|
|
#endif
|
|
if (sbuf2.st_ino != Sbuf.st_ino || sbuf2.st_dev != Sbuf.st_dev)
|
|
{
|
|
printf("Sorry, saved game is not in the same file.\n");
|
|
return FALSE;
|
|
}
|
|
else if (sbuf2.st_ctime - Sbuf.st_ctime > 15)
|
|
{
|
|
printf("Sorry, file has been touched, so this score won't be recorded\n");
|
|
Noscore = TRUE;
|
|
}
|
|
Mpos = 0;
|
|
/* printw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); */
|
|
/*
|
|
printw("%s: %s", file, ctime(&sbuf2.st_mtime));
|
|
*/
|
|
|
|
/*
|
|
* defeat multiple restarting from the same place
|
|
*/
|
|
#ifdef MASTER
|
|
if (!Wizard)
|
|
#endif
|
|
if (sbuf2.st_nlink != 1 || syml)
|
|
{
|
|
printf("Cannot restore from a linked file\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (Pstats.s_hpt <= 0)
|
|
{
|
|
printf("\"He's dead, Jim\"\n");
|
|
return FALSE;
|
|
}
|
|
#ifdef SIGTSTP
|
|
signal(SIGTSTP, tstp);
|
|
#endif
|
|
|
|
environ = envp;
|
|
gettmode();
|
|
if ((sp = getenv("TERM")) == NULL) {
|
|
fprintf(stderr, "no TERM variable");
|
|
exit(1);
|
|
}
|
|
setterm(sp);
|
|
strcpy(File_name, file);
|
|
initscr(); /* Start up cursor package */
|
|
setup();
|
|
clearok(curscr, TRUE);
|
|
srand(getpid());
|
|
msg("file name: %s", file);
|
|
playit();
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
/*
|
|
* encwrite:
|
|
* Perform an encrypted write
|
|
*/
|
|
void
|
|
encwrite(char *start, unsigned int size, FILE *outf)
|
|
{
|
|
char *e1, *e2, fb;
|
|
int temp;
|
|
extern char statlist[];
|
|
|
|
e1 = encstr;
|
|
e2 = statlist;
|
|
fb = Frob;
|
|
|
|
while (size--)
|
|
{
|
|
putc(*start++ ^ *e1 ^ *e2 ^ fb, outf);
|
|
temp = *e1++;
|
|
fb += temp * *e2++;
|
|
if (*e1 == '\0')
|
|
e1 = encstr;
|
|
if (*e2 == '\0')
|
|
e2 = statlist;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* encread:
|
|
* Perform an encrypted read
|
|
*/
|
|
encread(char *start, unsigned int size, int inf)
|
|
{
|
|
char *e1, *e2, fb;
|
|
int temp, read_size;
|
|
extern char statlist[];
|
|
|
|
fb = Frob;
|
|
|
|
if ((read_size = read(inf, start, size)) == 0 || read_size == -1)
|
|
return;
|
|
|
|
e1 = encstr;
|
|
e2 = statlist;
|
|
|
|
while (size--)
|
|
{
|
|
*start++ ^= *e1 ^ *e2 ^ fb;
|
|
temp = *e1++;
|
|
fb += temp * *e2++;
|
|
if (*e1 == '\0')
|
|
e1 = encstr;
|
|
if (*e2 == '\0')
|
|
e2 = statlist;
|
|
}
|
|
}
|
|
|
|
#ifdef SCOREFILE
|
|
/*
|
|
* read_scrore
|
|
* Read in the score file
|
|
*/
|
|
rd_score(SCORE *top_ten, int fd)
|
|
{
|
|
encread((char *) top_ten, numscores * sizeof (SCORE), fd);
|
|
}
|
|
|
|
/*
|
|
* write_scrore
|
|
* Read in the score file
|
|
*/
|
|
wr_score(SCORE *top_ten, FILE *outf)
|
|
{
|
|
encwrite((char *) top_ten, numscores * sizeof (SCORE), outf);
|
|
}
|
|
#endif
|