Mercurial > hg > early-roguelike
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/save.c Thu Nov 25 12:21:41 2010 +0000 @@ -0,0 +1,339 @@ +/* + * save and restore routines + * + * @(#)save.c 9.0 (rdk) 7/17/84 + * + * Super-Rogue + * Copyright (C) 1984 Robert D. Kindelberger + * All rights reserved. + * + * Based on "Rogue: Exploring the Dungeons of Doom" + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include <unistd.h> +#include <ctype.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <errno.h> +#include "rogue.h" +#include "rogue.ext" + +#ifdef BSD +#define srand48(seed) srandom(seed) +#endif + +EXTCHAR version[]; +EXTCHAR *ctime(); + +typedef struct stat STAT; +STAT sbuf; + +/* + * ignore: + * Ignore ALL signals possible + */ +ignore() +{ + int i; + + for (i = 0; i < NSIG; i++) + signal(i, SIG_IGN); +} + +/* + * save_game: + * Save the current game + */ +save_game() +{ + reg FILE *savef; + reg int c; + char buf[LINLEN]; + + mpos = 0; + if (file_name[0] != '\0') { + msg("Save file (%s)? ", file_name); + do { + c = wgetch(cw); + if(c == ESCAPE) { + msg(""); + return FALSE; + } + } while (c != 'n' && c != 'y'); + mpos = 0; + if (c == 'y') + goto gotfile; + } + msg("File name: "); + mpos = 0; + buf[0] = '\0'; + if (get_str(buf, cw) == QUIT) { + msg(""); + return FALSE; + } + msg(""); + strcpy(file_name, buf); +gotfile: + c = dosave(); /* try to save this game */ + if (c == FALSE) + msg("Could not save game to file %s", file_name); + return c; +} + +/* + * auto_save: + * Automatically save a game + */ +void +auto_save(int a) +{ + dosave(); /* save this game */ + byebye(1); /* so long for now */ +} + +/* + * game_err: + * When an error occurs. Set error flag and save game. + */ +void +game_err(int a) +{ + int ok; + + ok = dosave(); /* try to save this game */ + clear(); + refresh(); + endwin(); + + printf("\nInternal error !!!\n\nYour game was "); + if (ok) + printf("saved."); + else + printf("NOT saveable."); + + fflush(stdout); + +#ifdef SIGIOT + signal(SIGIOT, SIG_DFL); /* allow core dump signal */ +#endif + + abort(); /* cause core dump */ + byebye(3); +} + +/* + * dosave: + * Set UID back to user and save the game + */ +dosave() +{ + FILE *savef; + + ignore(); + setuid(playuid); + setgid(playgid); + umask(022); + + if (file_name[0] != '\0') { + if ((savef = fopen(file_name,"w")) != NULL) + { + save_file(savef); + return TRUE; + } + } + return FALSE; +} + +/* + * save_file: + * Do the actual save of this game to a file + */ +save_file(savef) +FILE *savef; +{ + reg int fnum; + int slines = LINES; + int scols = COLS; + +#ifdef __DJGPP__ /* st_ino w/ DJGPP under WinXP broken */ + _djstat_flags |= _STAT_INODE; /* so turn off computing it for now */ +#endif + + /* + * force allocation of the buffer now so that inodes, etc + * can be checked when restoring saved games. + */ + fnum = fileno(savef); + fstat(fnum, &sbuf); + write(fnum, "RDK", 4); + lseek(fnum, 0L, 0); + encwrite(version,strlen(version)+1,savef); + encwrite(&sbuf.st_ino,sizeof(sbuf.st_ino),savef); + encwrite(&sbuf.st_dev,sizeof(sbuf.st_dev),savef); + encwrite(&sbuf.st_ctime,sizeof(sbuf.st_ctime),savef); + encwrite(&sbuf.st_mtime,sizeof(sbuf.st_mtime),savef); + encwrite(&slines,sizeof(slines),savef); + encwrite(&scols,sizeof(scols),savef); + msg(""); + rs_save_file(savef); + close(fnum); + signal(SIGINT, byebye); + signal(SIGQUIT, byebye); + wclear(cw); + draw(cw); +} + +/* + * restore: + * Restore a saved game from a file + */ +restore(file, envp) +char *file, **envp; +{ + register inf, pid; + int ret_status; +#ifndef _AIX + extern char **environ; +#endif +#ifdef __DJGPP__ /* st_ino w/ DJGPP under WinXP broken */ + _djstat_flags |= _STAT_INODE; /* so turn off computing it for now */ +#endif + char buf[LINLEN]; + STAT sbuf2; + int slines, scols; + + if ((inf = open(file, O_RDONLY)) < 0) { + printf("Cannot read save game %s\n",file); + return FALSE; + } + + encread(buf, strlen(version) + 1, inf); + + if (strcmp(buf, version) != 0) { + printf("Sorry, saved game version is out of date.\n"); + return FALSE; + } + + fstat(inf, &sbuf2); + + encread(&sbuf.st_ino,sizeof(sbuf.st_ino), inf); + encread(&sbuf.st_dev,sizeof(sbuf.st_dev), inf); + encread(&sbuf.st_ctime,sizeof(sbuf.st_ctime), inf); + encread(&sbuf.st_mtime,sizeof(sbuf.st_mtime), inf); + encread(&slines,sizeof(slines),inf); + encread(&scols,sizeof(scols),inf); + + /* + * 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; + } + } + +#ifdef __INTERIX + setenv("TERM","interix"); +#endif + + initscr(); + + if (slines > LINES) + { + endwin(); + printf("Sorry, original game was played on a screen with %d lines.\n",slines); + printf("Current screen only has %d lines. Unable to restore game\n",LINES); + return(FALSE); + } + + if (scols > COLS) + { + endwin(); + printf("Sorry, original game was played on a screen with %d columns.\n", scols); + printf("Current screen only has %d columns. Unable to restore game\n",COLS); + return(FALSE); + } + + cw = newwin(LINES, COLS, 0, 0); + mw = newwin(LINES, COLS, 0, 0); + hw = newwin(LINES, COLS, 0, 0); + + 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) + { + endwin(); + printf("Cannot restore from a linked file\n"); + return FALSE; + } + } + + if (rs_restore_file(inf) == FALSE) + { + endwin(); + printf("Cannot restore file\n"); + return(FALSE); + } + +#if defined(__CYGWIN__) || defined(__DJGPP__) + close(inf); +#endif + if (!wizard) + { +#ifndef __DJGPP__ + endwin(); + while((pid = fork()) < 0) + sleep(1); + + /* set id to unlink file */ + if(pid == 0) + { + setuid(playuid); + setgid(playgid); + unlink(file); + exit(0); + } + /* wait for unlink to finish */ + else + { + while(wait(&ret_status) != pid) + continue; + if (ret_status < 0) + { + printf("Cannot unlink file\n"); + return FALSE; + } + } +#else + if (unlink(file) < 0) + { + printf("Cannot unlink file\n"); + return FALSE; + } +#endif + + } + + environ = envp; + + strcpy(file_name, file); + setup(); + restscr(cw); + srand48(getpid()); + playit(); +}