/* * save and restore routines * * @(#)save.c 3.6 (Berkeley) 4/19/81 */ #include <curses.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include "rogue.h" typedef struct stat STAT; extern char *sys_errlist[], version[], encstr[]; extern bool _endwin; extern int errno; char *sbrk(); STAT sbuf; save_game() { register FILE *savef; register int c; char buf[80]; /* * get file name */ mpos = 0; if (file_name[0] != '\0') { msg("Save file (\"%s\")? ", file_name); do { c = getchar(); } while (c != 'n' && c != 'N' && c != 'y' && c != 'Y'); mpos = 0; if (c == 'y' || c == 'Y') { msg("File name: %s", file_name); goto gotfile; } } do { msg("File name: "); mpos = 0; buf[0] = '\0'; if (get_str(buf, cw) == QUIT) { msg(""); return FALSE; } strcpy(file_name, buf); gotfile: if ((savef = fopen(file_name, "w")) == NULL) msg(sys_errlist[errno]); /* fake perror() */ } while (savef == NULL); /* * write out encrpyted file (after a stat) * The fwrite is to force allocation of the buffer before the write */ save_file(savef); return TRUE; } /* * automatically save a file. This is used if a HUP signal is * recieved */ auto_save() { register FILE *savef; if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL) save_file(savef); exit(1); } /* * write the saved game on the file */ save_file(savef) register FILE *savef; { wmove(cw, LINES-1, 0); draw(cw); fstat(fileno(savef), &sbuf); fwrite("junk", 1, 5, savef); fseek(savef, 0L, 0); _endwin = TRUE; restfile = savef; encwrite(version, sbrk(0) - version, savef); fclose(savef); } restore(file, envp) register char *file; char **envp; { register int inf; extern char **environ; char buf[80]; STAT sbuf2; int chflag = cheating; if (strcmp(file, "-r") == 0) file = file_name; if ((inf = open(file, 0)) < 0) { perror(file); return FALSE; } fflush(stdout); encread(buf, strlen(version) + 1, inf); if (strcmp(buf, version) != 0) { printf("Sorry, saved game is out of date.\n"); return FALSE; } fstat(inf, &sbuf2); fflush(stdout); brk(version + sbuf2.st_size); lseek(inf, 0L, 0); encread(version, (int) sbuf2.st_size, inf); if (restfile) { restfile->_file = -1; fclose(restfile); } /* * we do not close the file so that we will have a hold of the * inode for as long as possible */ if (!wizard) 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.\n"); return FALSE; } mpos = 0; mvwprintw(cw, 0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); /* * defeat multiple restarting from the same place */ if (!wizard) { if (sbuf2.st_nlink != 1) { printf("Cannot restore from a linked file\n"); return FALSE; } if (!cheating) { if (unlink(file) < 0) { printf("Cannot unlink file\n"); return FALSE; } sbuf2.st_ino = 0; stat(file, &sbuf2); /* defeat patching unlink */ if (sbuf2.st_ino == sbuf.st_ino) { printf("Cheater!\n"); return FALSE; } } } cheating |= chflag; environ = envp; if (!My_term && isatty(2)) { register char *sp; _tty_ch = 2; gettmode(); if ((sp = getenv("TERM")) == NULL) sp = Def_term; setterm(sp); } else setterm(Def_term); strcpy(file_name, file); setup(); clearok(curscr, TRUE); touchwin(cw); srand(getpid()); playit(); /*NOTREACHED*/ } /* * perform an encrypted write */ encwrite(start, size, outf) register char *start; unsigned int size; register FILE *outf; { register char *ep; ep = encstr; while (size--) { putc(*start++ ^ *ep++, outf); if (*ep == '\0') ep = encstr; } } /* * perform an encrypted read */ encread(start, size, inf) register char *start; unsigned int size; register int inf; { register char *ep; register int read_size; if ((read_size = read(inf, start, size)) == -1 || read_size == 0) return read_size; ep = encstr; while (size--) { *start++ ^= *ep++; if (*ep == '\0') ep = encstr; } return read_size; }