Annotation of early-roguelike/rogue4/save.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * save and restore routines
! 3: *
! 4: * @(#)save.c 4.15 (Berkeley) 5/10/82
! 5: *
! 6: * Rogue: Exploring the Dungeons of Doom
! 7: * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
! 8: * All rights reserved.
! 9: *
! 10: * See the file LICENSE.TXT for full copyright and licensing information.
! 11: */
! 12:
! 13: #include <curses.h>
! 14: #include <sys/types.h>
! 15: #include <sys/stat.h>
! 16: #include <errno.h>
! 17: #include <string.h>
! 18: #include <stdlib.h>
! 19: #include <time.h>
! 20: #define KERNEL
! 21: #include <signal.h>
! 22: #undef KERNEL
! 23: #include "rogue.h"
! 24:
! 25: void save_file(FILE *savef);
! 26: extern int rs_save_file(FILE *savef);
! 27: extern int rs_restore_file(FILE *inf);
! 28:
! 29: typedef struct stat STAT;
! 30:
! 31: extern char version[], encstr[];
! 32: extern bool _endwin;
! 33:
! 34: STAT sbuf;
! 35:
! 36: /*
! 37: * save_game:
! 38: * Implement the "save game" command
! 39: */
! 40: /* This has to be cleaned up, these goto's are annoying. */
! 41: bool
! 42: save_game(void)
! 43: {
! 44: register FILE *savef;
! 45: register int c;
! 46: char buf[256];
! 47:
! 48: /*
! 49: * get file name
! 50: */
! 51: mpos = 0;
! 52: over:
! 53: if (file_name[0] != '\0')
! 54: {
! 55: for (;;)
! 56: {
! 57: if (use_savedir)
! 58: msg("Save game? ");
! 59: else
! 60: msg("save file (%s)? ", file_name);
! 61: c = getchar();
! 62: mpos = 0;
! 63: if (c == ESCAPE)
! 64: {
! 65: msg("");
! 66: return FALSE;
! 67: }
! 68: else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
! 69: break;
! 70: else
! 71: msg("please answer Y or N");
! 72: }
! 73: if (c == 'y' || c == 'Y')
! 74: {
! 75: strcpy(buf, file_name);
! 76: goto gotfile;
! 77: }
! 78: }
! 79:
! 80: if (use_savedir)
! 81: {
! 82: /* You can't change the savefile if you're using the system
! 83: savedir, because that means you have privileges. */
! 84: msg("");
! 85: return FALSE;
! 86: }
! 87:
! 88: do
! 89: {
! 90: mpos = 0;
! 91: msg("file name: ");
! 92: buf[0] = '\0';
! 93: if (get_str(buf, stdscr) == QUIT)
! 94: {
! 95: quit:
! 96: msg("");
! 97: return FALSE;
! 98: }
! 99: mpos = 0;
! 100: gotfile:
! 101: /*
! 102: * test to see if the file exists
! 103: */
! 104: if (stat(buf, &sbuf) >= 0)
! 105: {
! 106: for (;;)
! 107: {
! 108: msg("File exists. Do you wish to overwrite it?");
! 109: mpos = 0;
! 110: if ((c = readchar()) == ESCAPE)
! 111: goto quit;
! 112: if (c == 'y' || c == 'Y')
! 113: break;
! 114: else if (c == 'n' || c == 'N')
! 115: goto over;
! 116: else
! 117: msg("Please answer Y or N");
! 118: }
! 119: msg("file name: %s", buf);
! 120: }
! 121: strcpy(file_name, buf);
! 122: if ((savef = fopen(file_name, "w")) == NULL)
! 123: {
! 124: msg(strerror(errno)); /* fake perror() */
! 125: if (use_savedir)
! 126: return FALSE;
! 127: }
! 128: } while (savef == NULL);
! 129:
! 130: /*
! 131: * write out encrpyted file (after a stat)
! 132: * The fwrite is to force allocation of the buffer before the write
! 133: */
! 134: save_file(savef);
! 135: return TRUE;
! 136: }
! 137:
! 138: /*
! 139: * auto_save:
! 140: * Automatically save a file. This is used if a HUP signal is
! 141: * recieved
! 142: */
! 143: void
! 144: auto_save(int sig)
! 145: {
! 146: register FILE *savef;
! 147:
! 148: md_ignore_signals();
! 149:
! 150: if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)
! 151: save_file(savef);
! 152: endwin();
! 153: exit(1);
! 154: }
! 155:
! 156: /*
! 157: * save_file:
! 158: * Write the saved game on the file
! 159: */
! 160: void
! 161: save_file(FILE *savef)
! 162: {
! 163: int slines = LINES;
! 164: int scols = COLS;
! 165:
! 166: /*
! 167: * close any open score file
! 168: */
! 169: if (score_file != NULL) {
! 170: fclose(score_file);
! 171: score_file = NULL;
! 172: }
! 173: move(LINES-1, 0);
! 174: refresh();
! 175: fstat(md_fileno(savef), &sbuf);
! 176: /*
! 177: * DO NOT DELETE. This forces stdio to allocate the output buffer
! 178: * so that malloc doesn't get confused on restart
! 179: */
! 180: fwrite("junk", 1, 5, savef);
! 181:
! 182: fseek(savef, 0L, 0);
! 183:
! 184: encwrite(version,strlen(version)+1,savef);
! 185: encwrite(&slines,sizeof(slines),savef);
! 186: encwrite(&scols,sizeof(scols),savef);
! 187: msg("");
! 188: rs_save_file(savef);
! 189:
! 190: fclose(savef);
! 191: }
! 192:
! 193: /*
! 194: * restore:
! 195: * Restore a saved game from a file with elaborate checks for file
! 196: * integrity from cheaters
! 197: */
! 198: bool
! 199: restore(char *file, char **envp)
! 200: {
! 201: FILE *inf;
! 202: register bool syml;
! 203: extern char **environ;
! 204: char buf[MAXSTR];
! 205: STAT sbuf2;
! 206: int slines, scols;
! 207:
! 208: if (strcmp(file, "-r") == 0)
! 209: file = file_name;
! 210:
! 211: #ifdef SIGTSTP
! 212: /*
! 213: * If a process can be suspended, this code wouldn't work
! 214: */
! 215: signal(SIGTSTP, SIG_IGN);
! 216: #endif
! 217:
! 218: if ((inf = fopen(file, "r")) == NULL)
! 219: {
! 220: if (use_savedir && errno == ENOENT)
! 221: {
! 222: /* We're using a system savefile which doesn't exist.
! 223: This isn't a fatal error, it means start a new game. */
! 224: return TRUE;
! 225: }
! 226: perror(file);
! 227: return FALSE;
! 228: }
! 229:
! 230: fflush(stdout);
! 231: encread(buf, strlen(version) + 1, inf);
! 232: if (strcmp(buf, version) != 0)
! 233: {
! 234: printf("Sorry, saved game is out of date.\n");
! 235: return FALSE;
! 236: }
! 237:
! 238: stat(file, &sbuf2);
! 239: fflush(stdout);
! 240: syml = issymlink(file);
! 241:
! 242: fflush(stdout);
! 243:
! 244: encread(&slines,sizeof(slines),inf);
! 245: encread(&scols,sizeof(scols),inf);
! 246:
! 247: /*
! 248: * we do not close the file so that we will have a hold of the
! 249: * inode for as long as possible
! 250: */
! 251:
! 252: initscr();
! 253:
! 254: if (slines > LINES)
! 255: {
! 256: endwin();
! 257: printf("Sorry, original game was played on a screen with %d lines.\n",slines);
! 258: printf("Current screen only has %d lines. Unable to restore game\n",LINES);
! 259: return(FALSE);
! 260: }
! 261:
! 262: if (scols > COLS)
! 263: {
! 264: endwin();
! 265: printf("Sorry, original game was played on a screen with %d columns.\n",scols);
! 266: printf("Current screen only has %d columns. Unable to restore game\n",COLS);
! 267: return(FALSE);
! 268: }
! 269:
! 270: hw = newwin(LINES, COLS, 0, 0);
! 271: keypad(stdscr,1);
! 272:
! 273: mpos = 0;
! 274: mvprintw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
! 275:
! 276: if (rs_restore_file(inf) == FALSE)
! 277: {
! 278: endwin();
! 279: printf("Cannot restore file\n");
! 280: return(FALSE);
! 281: }
! 282:
! 283: if (
! 284: #ifdef WIZARD
! 285: !wizard &&
! 286: #endif
! 287: md_unlink_open_file(file, inf) < 0)
! 288: {
! 289: endwin();
! 290: printf("Cannot unlink file\n");
! 291: return FALSE;
! 292: }
! 293:
! 294: /*
! 295: * defeat multiple restarting from the same place
! 296: */
! 297: #ifdef WIZARD
! 298: if (!wizard)
! 299: #endif
! 300: if (sbuf2.st_nlink != 1 || syml)
! 301: {
! 302: endwin();
! 303: printf("Cannot restore from a linked file\n");
! 304: return FALSE;
! 305: }
! 306:
! 307: if (pstats.s_hpt <= 0) {
! 308: endwin();
! 309: printf("This character is already dead.\n");
! 310: return FALSE;
! 311: }
! 312:
! 313: #ifdef SIGTSTP
! 314: signal(SIGTSTP, tstp);
! 315: #endif
! 316: environ = envp;
! 317: strcpy(file_name, file);
! 318: setup();
! 319: clearok(curscr, TRUE);
! 320: touchwin(stdscr);
! 321: srand(md_random_seed());
! 322: msg("file name: %s", file);
! 323: status();
! 324: playit();
! 325: return 0;
! 326: }
! 327:
! 328: /*
! 329: * encwrite:
! 330: * Perform an encrypted write
! 331: */
! 332: void
! 333: encwrite(void *starta, int size, FILE *outf)
! 334: {
! 335: register char *ep;
! 336: register char *start = (char *) starta;
! 337: ep = encstr;
! 338:
! 339: while (size--)
! 340: {
! 341: putc(*start++ ^ *ep++, outf);
! 342: if (*ep == '\0')
! 343: ep = encstr;
! 344: }
! 345: }
! 346:
! 347: /*
! 348: * encread:
! 349: * Perform an encrypted read
! 350: */
! 351: int
! 352: encread(void *starta, int size, FILE *inf)
! 353: {
! 354: register char *ep;
! 355: register int read_size;
! 356: register char *start = (char *) starta;
! 357:
! 358: if ((read_size = fread(start, 1, size, inf)) == 0)
! 359: return read_size;
! 360:
! 361: ep = encstr;
! 362:
! 363: while (size--)
! 364: {
! 365: *start++ ^= *ep++;
! 366: if (*ep == '\0')
! 367: ep = encstr;
! 368: }
! 369:
! 370: return read_size;
! 371: }
CVSweb