Source:NetHack 3.4.3/src/files.c

From NetHackWiki
(Redirected from Source:Ref/redirect)
Jump to: navigation, search

Below is the full text to src/files.c from NetHack 3.4.3. To link to a particular line, write [[files.c#line123]], for example.

Top of file

  1. /*	SCCS Id: @(#)files.c	3.4	2003/11/14	*/
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

  1. #include "hack.h"
  2. #include "dlb.h"
  3.  
  4. #ifdef TTY_GRAPHICS
  5. #include "wintty.h" /* more() */
  6. #endif
  7.  
  8. #include <ctype.h>
  9.  
  10. #if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C)
  11. #include <fcntl.h>
  12. #endif
  13.  
  14. #include <errno.h>
  15. #ifdef _MSC_VER	/* MSC 6.0 defines errno quite differently */
  16. # if (_MSC_VER >= 600)
  17. #  define SKIP_ERRNO
  18. # endif
  19. #else
  20. # ifdef NHSTDC
  21. #  define SKIP_ERRNO
  22. # endif
  23. #endif
  24. #ifndef SKIP_ERRNO
  25. # ifdef _DCC
  26. const
  27. # endif
  28. extern int errno;
  29. #endif
  30.  
  31. #if defined(UNIX) && defined(QT_GRAPHICS)
  32. #include <dirent.h>
  33. #endif
  34.  
  35. #if defined(UNIX) || defined(VMS)
  36. #include <signal.h>
  37. #endif
  38.  
  39. #if defined(MSDOS) || defined(OS2) || defined(TOS) || defined(WIN32)
  40. # ifndef GNUDOS
  41. #include <sys\stat.h>
  42. # else
  43. #include <sys/stat.h>
  44. # endif
  45. #endif
  46. #ifndef O_BINARY	/* used for micros, no-op for others */
  47. # define O_BINARY 0
  48. #endif
  49.  
  50. #ifdef PREFIXES_IN_USE
  51. #define FQN_NUMBUF 4
  52. static char fqn_filename_buffer[FQN_NUMBUF][FQN_MAX_FILENAME];
  53. #endif
  54.  
  55. #if !defined(MFLOPPY) && !defined(VMS) && !defined(WIN32)
  56. char bones[] = "bonesnn.xxx";
  57. char lock[PL_NSIZ+14] = "1lock"; /* long enough for uid+name+.99 */
  58. #else
  59. # if defined(MFLOPPY)
  60. char bones[FILENAME];		/* pathname of bones files */
  61. char lock[FILENAME];		/* pathname of level files */
  62. # endif
  63. # if defined(VMS)
  64. char bones[] = "bonesnn.xxx;1";
  65. char lock[PL_NSIZ+17] = "1lock"; /* long enough for _uid+name+.99;1 */
  66. # endif
  67. # if defined(WIN32)
  68. char bones[] = "bonesnn.xxx";
  69. char lock[PL_NSIZ+25];		/* long enough for username+-+name+.99 */
  70. # endif
  71. #endif
  72.  
  73. #if defined(UNIX) || defined(__BEOS__)
  74. #define SAVESIZE	(PL_NSIZ + 13)	/* save/99999player.e */
  75. #else
  76. # ifdef VMS
  77. #define SAVESIZE	(PL_NSIZ + 22)	/* [.save]<uid>player.e;1 */
  78. # else
  79. #  if defined(WIN32)
  80. #define SAVESIZE	(PL_NSIZ + 40)	/* username-player.NetHack-saved-game */
  81. #  else
  82. #define SAVESIZE	FILENAME	/* from macconf.h or pcconf.h */
  83. #  endif
  84. # endif
  85. #endif
  86.  
  87. char SAVEF[SAVESIZE];	/* holds relative path of save file from playground */
  88. #ifdef MICRO
  89. char SAVEP[SAVESIZE];	/* holds path of directory for save file */
  90. #endif
  91.  
  92. #ifdef HOLD_LOCKFILE_OPEN
  93. struct level_ftrack {
  94. int init;
  95. int fd;					/* file descriptor for level file     */
  96. int oflag;				/* open flags                         */
  97. boolean nethack_thinks_it_is_open;	/* Does NetHack think it's open?       */
  98. } lftrack;
  99. # if defined(WIN32)
  100. #include <share.h>
  101. # endif
  102. #endif /*HOLD_LOCKFILE_OPEN*/
  103.  
  104. #ifdef WIZARD
  105. #define WIZKIT_MAX 128
  106. static char wizkit[WIZKIT_MAX];
  107. STATIC_DCL FILE *NDECL(fopen_wizkit_file);
  108. #endif
  109.  
  110. #ifdef AMIGA
  111. extern char PATH[];	/* see sys/amiga/amidos.c */
  112. extern char bbs_id[];
  113. static int lockptr;
  114. # ifdef __SASC_60
  115. #include <proto/dos.h>
  116. # endif
  117.  
  118. #include <libraries/dos.h>
  119. extern void FDECL(amii_set_text_font, ( char *, int ));
  120. #endif
  121.  
  122. #if defined(WIN32) || defined(MSDOS)
  123. static int lockptr;
  124. # ifdef MSDOS
  125. #define Delay(a) msleep(a)
  126. # endif
  127. #define Close close
  128. #ifndef WIN_CE
  129. #define DeleteFile unlink
  130. #endif
  131. #endif
  132.  
  133. #ifdef MAC
  134. # define unlink macunlink
  135. #endif
  136.  
  137. #ifdef USER_SOUNDS
  138. extern char *sounddir;
  139. #endif
  140.  
  141. extern int n_dgns;		/* from dungeon.c */
  142.  
  143. STATIC_DCL char *FDECL(set_bonesfile_name, (char *,d_level*));
  144. STATIC_DCL char *NDECL(set_bonestemp_name);
  145. #ifdef COMPRESS
  146. STATIC_DCL void FDECL(redirect, (const char *,const char *,FILE *,BOOLEAN_P));
  147. STATIC_DCL void FDECL(docompress_file, (const char *,BOOLEAN_P));
  148. #endif
  149. STATIC_DCL char *FDECL(make_lockname, (const char *,char *));
  150. STATIC_DCL FILE *FDECL(fopen_config_file, (const char *));
  151. STATIC_DCL int FDECL(get_uchars, (FILE *,char *,char *,uchar *,BOOLEAN_P,int,const char *));
  152. int FDECL(parse_config_line, (FILE *,char *,char *,char *));
  153. #ifdef NOCWD_ASSUMPTIONS
  154. STATIC_DCL void FDECL(adjust_prefix, (char *, int));
  155. #endif
  156. #ifdef SELF_RECOVER
  157. STATIC_DCL boolean FDECL(copy_bytes, (int, int));
  158. #endif
  159. #ifdef HOLD_LOCKFILE_OPEN
  160. STATIC_DCL int FDECL(open_levelfile_exclusively, (const char *, int, int));
  161. #endif

fname_encode

  1. /*
  2. * fname_encode()
  3. *
  4. *   Args:
  5. *	legal		zero-terminated list of acceptable file name characters
  6. *	quotechar	lead-in character used to quote illegal characters as hex digits
  7. *	s		string to encode
  8. *	callerbuf	buffer to house result
  9. *	bufsz		size of callerbuf
  10. *
  11. *   Notes:
  12. *	The hex digits 0-9 and A-F are always part of the legal set due to
  13. *	their use in the encoding scheme, even if not explicitly included in 'legal'.
  14. *
  15. *   Sample:
  16. *	The following call:
  17. *	    (void)fname_encode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
  18. *				'%', "This is a % test!", buf, 512);
  19. *	results in this encoding:
  20. *	    "This%20is%20a%20%25%20test%21"
  21. */
  22. char *
  23. fname_encode(legal, quotechar, s, callerbuf, bufsz)
  24. const char *legal;
  25. char quotechar;
  26. char *s, *callerbuf;
  27. int bufsz;
  28. {
  29. 	char *sp, *op;
  30. 	int cnt = 0;
  31. 	static char hexdigits[] = "0123456789ABCDEF";
  32.  
  33. 	sp = s;
  34. 	op = callerbuf;
  35. 	*op = '\0';
  36.  
  37. 	while (*sp) {
  38. 		/* Do we have room for one more character or encoding? */
  39. 		if ((bufsz - cnt) <= 4) return callerbuf;
  40.  
  41. 		if (*sp == quotechar) {
  42. 			(void)sprintf(op, "%c%02X", quotechar, *sp);
  43. 			 op += 3;
  44. 			 cnt += 3;
  45. 		} else if ((index(legal, *sp) != 0) || (index(hexdigits, *sp) != 0)) {
  46. 			*op++ = *sp;
  47. 			*op = '\0';
  48. 			cnt++;
  49. 		} else {
  50. 			(void)sprintf(op,"%c%02X", quotechar, *sp);
  51. 			op += 3;
  52. 			cnt += 3;
  53. 		}
  54. 		sp++;
  55. 	}
  56. 	return callerbuf;
  57. }

fname_decode

  1. /*
  2. * fname_decode()
  3. *
  4. *   Args:
  5. *	quotechar	lead-in character used to quote illegal characters as hex digits
  6. *	s		string to decode
  7. *	callerbuf	buffer to house result
  8. *	bufsz		size of callerbuf
  9. */
  10. char *
  11. fname_decode(quotechar, s, callerbuf, bufsz)
  12. char quotechar;
  13. char *s, *callerbuf;
  14. int bufsz;
  15. {
  16. 	char *sp, *op;
  17. 	int k,calc,cnt = 0;
  18. 	static char hexdigits[] = "0123456789ABCDEF";
  19.  
  20. 	sp = s;
  21. 	op = callerbuf;
  22. 	*op = '\0';
  23. 	calc = 0;
  24.  
  25. 	while (*sp) {
  26. 		/* Do we have room for one more character? */
  27. 		if ((bufsz - cnt) <= 2) return callerbuf;
  28. 		if (*sp == quotechar) {
  29. 			sp++;
  30. 			for (k=0; k < 16; ++k) if (*sp == hexdigits[k]) break;
  31. 			if (k >= 16) return callerbuf;	/* impossible, so bail */
  32. 			calc = k << 4; 
  33. 			sp++;
  34. 			for (k=0; k < 16; ++k) if (*sp == hexdigits[k]) break;
  35. 			if (k >= 16) return callerbuf;	/* impossible, so bail */
  36. 			calc += k; 
  37. 			sp++;
  38. 			*op++ = calc;
  39. 			*op = '\0';
  40. 		} else {
  41. 			*op++ = *sp++;
  42. 			*op = '\0';
  43. 		}
  44. 		cnt++;
  45. 	}
  46. 	return callerbuf;
  47. }

fqname

  1. #ifndef PREFIXES_IN_USE
  2. /*ARGSUSED*/
  3. #endif
  4. const char *
  5. fqname(basename, whichprefix, buffnum)
  6. const char *basename;
  7. int whichprefix, buffnum;
  8. {
  9. #ifndef PREFIXES_IN_USE
  10. 	return basename;
  11. #else
  12. 	if (!basename || whichprefix < 0 || whichprefix >= PREFIX_COUNT)
  13. 		return basename;
  14. 	if (!fqn_prefix[whichprefix])
  15. 		return basename;
  16. 	if (buffnum < 0 || buffnum >= FQN_NUMBUF) {
  17. 		impossible("Invalid fqn_filename_buffer specified: %d",
  18. 								buffnum);
  19. 		buffnum = 0;
  20. 	}
  21. 	if (strlen(fqn_prefix[whichprefix]) + strlen(basename) >=
  22. 						    FQN_MAX_FILENAME) {
  23. 		impossible("fqname too long: %s + %s", fqn_prefix[whichprefix],
  24. 						basename);
  25. 		return basename;	/* XXX */
  26. 	}
  27. 	Strcpy(fqn_filename_buffer[buffnum], fqn_prefix[whichprefix]);
  28. 	return strcat(fqn_filename_buffer[buffnum], basename);
  29. #endif
  30. }

validate_prefix_locations

  1. /* reasonbuf must be at least BUFSZ, supplied by caller */
  2. /*ARGSUSED*/
  3. int
  4. validate_prefix_locations(reasonbuf)
  5. char *reasonbuf;
  6. {
  7. #if defined(NOCWD_ASSUMPTIONS)
  8. 	FILE *fp;
  9. 	const char *filename;
  10. 	int prefcnt, failcount = 0;
  11. 	char panicbuf1[BUFSZ], panicbuf2[BUFSZ], *details;
  12.  
  13. 	if (reasonbuf) reasonbuf[0] = '\0';
  14. 	for (prefcnt = 1; prefcnt < PREFIX_COUNT; prefcnt++) {
  15. 		/* don't test writing to configdir or datadir; they're readonly */
  16. 		if (prefcnt == CONFIGPREFIX || prefcnt == DATAPREFIX) continue;
  17. 		filename = fqname("validate", prefcnt, 3);
  18. 		if ((fp = fopen(filename, "w"))) {
  19. 			fclose(fp);
  20. 			(void) unlink(filename);
  21. 		} else {
  22. 			if (reasonbuf) {
  23. 				if (failcount) Strcat(reasonbuf,", ");
  24. 				Strcat(reasonbuf, fqn_prefix_names[prefcnt]);
  25. 			}
  26. 			/* the paniclog entry gets the value of errno as well */
  27. 			Sprintf(panicbuf1,"Invalid %s", fqn_prefix_names[prefcnt]);
  28. #if defined (NHSTDC) && !defined(NOTSTDC)
  29. 			if (!(details = strerror(errno)))
  30. #endif
  31. 			details = "";
  32. 			Sprintf(panicbuf2,"\"%s\", (%d) %s",
  33. 				fqn_prefix[prefcnt], errno, details);
  34. 			paniclog(panicbuf1, panicbuf2);
  35. 			failcount++;
  36. 		}	
  37. 	}
  38. 	if (failcount)
  39. 		return 0;
  40. 	else
  41. #endif
  42. 	return 1;
  43. }

fopen_datafile

  1. /* fopen a file, with OS-dependent bells and whistles */
  2. /* NOTE: a simpler version of this routine also exists in util/dlb_main.c */
  3. FILE *
  4. fopen_datafile(filename, mode, prefix)
  5. const char *filename, *mode;
  6. int prefix;
  7. {
  8. 	FILE *fp;
  9.  
  10. 	filename = fqname(filename, prefix, prefix == TROUBLEPREFIX ? 3 : 0);
  11. #ifdef VMS	/* essential to have punctuation, to avoid logical names */
  12. {
  13. 	char tmp[BUFSIZ];
  14.  
  15. 	if (!index(filename, '.') && !index(filename, ';'))
  16. 		filename = strcat(strcpy(tmp, filename), ";0");
  17. 	fp = fopen(filename, mode, "mbc=16");
  18. }
  19. #else
  20. 	fp = fopen(filename, mode);
  21. #endif
  22. 	return fp;
  23. }

Level file handling

  1. /* ----------  BEGIN LEVEL FILE HANDLING ----------- */

set_lock_and_bones

  1. #ifdef MFLOPPY
  2. /* Set names for bones[] and lock[] */
  3. void
  4. set_lock_and_bones()
  5. {
  6. 	if (!ramdisk) {
  7. 		Strcpy(levels, permbones);
  8. 		Strcpy(bones, permbones);
  9. 	}
  10. 	append_slash(permbones);
  11. 	append_slash(levels);
  12. #ifdef AMIGA
  13. 	strncat(levels, bbs_id, PATHLEN);
  14. #endif
  15. 	append_slash(bones);
  16. 	Strcat(bones, "bonesnn.*");
  17. 	Strcpy(lock, levels);
  18. #ifndef AMIGA
  19. 	Strcat(lock, alllevels);
  20. #endif
  21. 	return;
  22. }
  23. #endif /* MFLOPPY */

set_levelfile_name

  1. /* Construct a file name for a level-type file, which is of the form
  2. * something.level (with any old level stripped off).
  3. * This assumes there is space on the end of 'file' to append
  4. * a two digit number.  This is true for 'level'
  5. * but be careful if you use it for other things -dgk
  6. */
  7. void
  8. set_levelfile_name(file, lev)
  9. char *file;
  10. int lev;
  11. {
  12. 	char *tf;
  13.  
  14. 	tf = rindex(file, '.');
  15. 	if (!tf) tf = eos(file);
  16. 	Sprintf(tf, ".%d", lev);
  17. #ifdef VMS
  18. 	Strcat(tf, ";1");
  19. #endif
  20. 	return;
  21. }

create_levelfile

  1. int
  2. create_levelfile(lev, errbuf)
  3. int lev;
  4. char errbuf[];
  5. {
  6. 	int fd;
  7. 	const char *fq_lock;
  8.  
  9. 	if (errbuf) *errbuf = '\0';
  10. 	set_levelfile_name(lock, lev);
  11. 	fq_lock = fqname(lock, LEVELPREFIX, 0);
  12.  
  13. #if defined(MICRO) || defined(WIN32)
  14. 	/* Use O_TRUNC to force the file to be shortened if it already
  15. 	 * exists and is currently longer.
  16. 	 */
  17. # ifdef HOLD_LOCKFILE_OPEN
  18. 	if (lev == 0)
  19. 		fd = open_levelfile_exclusively(fq_lock, lev,
  20. 				O_WRONLY |O_CREAT | O_TRUNC | O_BINARY);
  21. 	else
  22. # endif
  23. 	fd = open(fq_lock, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK);
  24. #else
  25. # ifdef MAC
  26. 	fd = maccreat(fq_lock, LEVL_TYPE);
  27. # else
  28. 	fd = creat(fq_lock, FCMASK);
  29. # endif
  30. #endif /* MICRO || WIN32 */
  31.  
  32. 	if (fd >= 0)
  33. 	    level_info[lev].flags |= LFILE_EXISTS;
  34. 	else if (errbuf)	/* failure explanation */
  35. 	    Sprintf(errbuf,
  36. 		    "Cannot create file \"%s\" for level %d (errno %d).",
  37. 		    lock, lev, errno);
  38.  
  39. 	return fd;
  40. }

open_levelfile

  1. int
  2. open_levelfile(lev, errbuf)
  3. int lev;
  4. char errbuf[];
  5. {
  6. 	int fd;
  7. 	const char *fq_lock;
  8.  
  9. 	if (errbuf) *errbuf = '\0';
  10. 	set_levelfile_name(lock, lev);
  11. 	fq_lock = fqname(lock, LEVELPREFIX, 0);
  12. #ifdef MFLOPPY
  13. 	/* If not currently accessible, swap it in. */
  14. 	if (level_info[lev].where != ACTIVE)
  15. 		swapin_file(lev);
  16. #endif
  17. #ifdef MAC
  18. 	fd = macopen(fq_lock, O_RDONLY | O_BINARY, LEVL_TYPE);
  19. #else
  20. # ifdef HOLD_LOCKFILE_OPEN
  21. 	if (lev == 0)
  22. 		fd = open_levelfile_exclusively(fq_lock, lev, O_RDONLY | O_BINARY );
  23. 	else
  24. # endif
  25. 	fd = open(fq_lock, O_RDONLY | O_BINARY, 0);
  26. #endif
  27.  
  28. 	/* for failure, return an explanation that our caller can use;
  29. 	   settle for `lock' instead of `fq_lock' because the latter
  30. 	   might end up being too big for nethack's BUFSZ */
  31. 	if (fd < 0 && errbuf)
  32. 	    Sprintf(errbuf,
  33. 		    "Cannot open file \"%s\" for level %d (errno %d).",
  34. 		    lock, lev, errno);
  35.  
  36. 	return fd;
  37. }

delete_levelfile

  1. void
  2. delete_levelfile(lev)
  3. int lev;
  4. {
  5. 	/*
  6. 	 * Level 0 might be created by port specific code that doesn't
  7. 	 * call create_levfile(), so always assume that it exists.
  8. 	 */
  9. 	if (lev == 0 || (level_info[lev].flags & LFILE_EXISTS)) {
  10. 		set_levelfile_name(lock, lev);
  11. #ifdef HOLD_LOCKFILE_OPEN
  12. 		if (lev == 0) really_close();
  13. #endif
  14. 		(void) unlink(fqname(lock, LEVELPREFIX, 0));
  15. 		level_info[lev].flags &= ~LFILE_EXISTS;
  16. 	}
  17. }

clearlocks

  1. void
  2. clearlocks()
  3. {
  4. #if !defined(PC_LOCKING) && defined(MFLOPPY) && !defined(AMIGA)
  5. 	eraseall(levels, alllevels);
  6. 	if (ramdisk)
  7. 		eraseall(permbones, alllevels);
  8. #else
  9. 	register int x;
  10.  
  11. # if defined(UNIX) || defined(VMS)
  12. 	(void) signal(SIGHUP, SIG_IGN);
  13. # endif
  14. 	/* can't access maxledgerno() before dungeons are created -dlc */
  15. 	for (x = (n_dgns ? maxledgerno() : 0); x >= 0; x--)
  16. 		delete_levelfile(x);	/* not all levels need be present */
  17. #endif
  18. }

open_levelfile_exclusively

  1. #ifdef HOLD_LOCKFILE_OPEN
  2. STATIC_OVL int
  3. open_levelfile_exclusively(name, lev, oflag)
  4. const char *name;
  5. int lev, oflag;
  6. {
  7. 	int reslt, fd;
  8. 	if (!lftrack.init) {
  9. 		lftrack.init = 1;
  10. 		lftrack.fd = -1;
  11. 	}
  12. 	if (lftrack.fd >= 0) {
  13. 		/* check for compatible access */
  14. 		if (lftrack.oflag == oflag) {
  15. 			fd = lftrack.fd;
  16. 			reslt = lseek(fd, 0L, SEEK_SET);
  17. 			if (reslt == -1L)
  18. 			    panic("open_levelfile_exclusively: lseek failed %d", errno);
  19. 			lftrack.nethack_thinks_it_is_open = TRUE;
  20. 		} else {
  21. 			really_close();
  22. 			fd = sopen(name, oflag,SH_DENYRW, FCMASK);
  23. 			lftrack.fd = fd;
  24. 			lftrack.oflag = oflag;
  25. 			lftrack.nethack_thinks_it_is_open = TRUE;
  26. 		}
  27. 	} else {
  28. 			fd = sopen(name, oflag,SH_DENYRW, FCMASK);
  29. 			lftrack.fd = fd;
  30. 			lftrack.oflag = oflag;
  31. 			if (fd >= 0)
  32. 			    lftrack.nethack_thinks_it_is_open = TRUE;
  33. 	}
  34. 	return fd;
  35. }

really_close

  1. void
  2. really_close()
  3. {
  4. 	int fd = lftrack.fd;
  5. 	lftrack.nethack_thinks_it_is_open = FALSE;
  6. 	lftrack.fd = -1;
  7. 	lftrack.oflag = 0;
  8. 	(void)_close(fd);
  9. 	return;
  10. }

close

  1. int
  2. close(fd)
  3. int fd;
  4. {
  5. 	if (lftrack.fd == fd) {
  6. 		really_close();	/* close it, but reopen it to hold it */
  7. 		fd = open_levelfile(0, (char *)0);
  8. 		lftrack.nethack_thinks_it_is_open = FALSE;
  9. 		return 0;
  10. 	}
  11. 	return _close(fd);
  12. }
  13. #endif
  14.  
  15. /* ----------  END LEVEL FILE HANDLING ----------- */

Bones file handling

  1. /* ----------  BEGIN BONES FILE HANDLING ----------- */

set_bonesfile_name

  1. /* set up "file" to be file name for retrieving bones, and return a
  2. * bonesid to be read/written in the bones file.
  3. */
  4. STATIC_OVL char *
  5. set_bonesfile_name(file, lev)
  6. char *file;
  7. d_level *lev;
  8. {
  9. 	s_level *sptr;
  10. 	char *dptr;
  11.  
  12. 	Sprintf(file, "bon%c%s", dungeons[lev->dnum].boneid,
  13. 			In_quest(lev) ? urole.filecode : "0");
  14. 	dptr = eos(file);
  15. 	if ((sptr = Is_special(lev)) != 0)
  16. 	    Sprintf(dptr, ".%c", sptr->boneid);
  17. 	else
  18. 	    Sprintf(dptr, ".%d", lev->dlevel);
  19. #ifdef VMS
  20. 	Strcat(dptr, ";1");
  21. #endif
  22. 	return(dptr-2);
  23. }

set_bonestemp_name

  1. /* set up temporary file name for writing bones, to avoid another game's
  2. * trying to read from an uncompleted bones file.  we want an uncontentious
  3. * name, so use one in the namespace reserved for this game's level files.
  4. * (we are not reading or writing level files while writing bones files, so
  5. * the same array may be used instead of copying.)
  6. */
  7. STATIC_OVL char *
  8. set_bonestemp_name()
  9. {
  10. 	char *tf;
  11.  
  12. 	tf = rindex(lock, '.');
  13. 	if (!tf) tf = eos(lock);
  14. 	Sprintf(tf, ".bn");
  15. #ifdef VMS
  16. 	Strcat(tf, ";1");
  17. #endif
  18. 	return lock;
  19. }

create_bonesfile

  1. int
  2. create_bonesfile(lev, bonesid, errbuf)
  3. d_level *lev;
  4. char **bonesid;
  5. char errbuf[];
  6. {
  7. 	const char *file;
  8. 	int fd;
  9.  
  10. 	if (errbuf) *errbuf = '\0';
  11. 	*bonesid = set_bonesfile_name(bones, lev);
  12. 	file = set_bonestemp_name();
  13. 	file = fqname(file, BONESPREFIX, 0);
  14.  
  15. #if defined(MICRO) || defined(WIN32)
  16. 	/* Use O_TRUNC to force the file to be shortened if it already
  17. 	 * exists and is currently longer.
  18. 	 */
  19. 	fd = open(file, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK);
  20. #else
  21. # ifdef MAC
  22. 	fd = maccreat(file, BONE_TYPE);
  23. # else
  24. 	fd = creat(file, FCMASK);
  25. # endif
  26. #endif
  27. 	if (fd < 0 && errbuf) /* failure explanation */
  28. 	    Sprintf(errbuf,
  29. 		    "Cannot create bones \"%s\", id %s (errno %d).",
  30. 		    lock, *bonesid, errno);
  31.  
  32. # if defined(VMS) && !defined(SECURE)
  33. 	/*
  34. 	   Re-protect bones file with world:read+write+execute+delete access.
  35. 	   umask() doesn't seem very reliable; also, vaxcrtl won't let us set
  36. 	   delete access without write access, which is what's really wanted.
  37. 	   Can't simply create it with the desired protection because creat
  38. 	   ANDs the mask with the user's default protection, which usually
  39. 	   denies some or all access to world.
  40. 	 */
  41. 	(void) chmod(file, FCMASK | 007);  /* allow other users full access */
  42. # endif /* VMS && !SECURE */
  43.  
  44. 	return fd;
  45. }

cancel_bonesfile

  1. #ifdef MFLOPPY
  2. /* remove partial bonesfile in process of creation */
  3. void
  4. cancel_bonesfile()
  5. {
  6. 	const char *tempname;
  7.  
  8. 	tempname = set_bonestemp_name();
  9. 	tempname = fqname(tempname, BONESPREFIX, 0);
  10. 	(void) unlink(tempname);
  11. }
  12. #endif /* MFLOPPY */

commit_bonesfile

  1. /* move completed bones file to proper name */
  2. void
  3. commit_bonesfile(lev)
  4. d_level *lev;
  5. {
  6. 	const char *fq_bones, *tempname;
  7. 	int ret;
  8.  
  9. 	(void) set_bonesfile_name(bones, lev);
  10. 	fq_bones = fqname(bones, BONESPREFIX, 0);
  11. 	tempname = set_bonestemp_name();
  12. 	tempname = fqname(tempname, BONESPREFIX, 1);
  13.  
  14. #if (defined(SYSV) && !defined(SVR4)) || defined(GENIX)
  15. 	/* old SYSVs don't have rename.  Some SVR3's may, but since they
  16. 	 * also have link/unlink, it doesn't matter. :-)
  17. 	 */
  18. 	(void) unlink(fq_bones);
  19. 	ret = link(tempname, fq_bones);
  20. 	ret += unlink(tempname);
  21. #else
  22. 	ret = rename(tempname, fq_bones);
  23. #endif
  24. #ifdef WIZARD
  25. 	if (wizard && ret != 0)
  26. 		pline("couldn't rename %s to %s.", tempname, fq_bones);
  27. #endif
  28. }

open_bonesfile

  1. int
  2. open_bonesfile(lev, bonesid)
  3. d_level *lev;
  4. char **bonesid;
  5. {
  6. 	const char *fq_bones;
  7. 	int fd;
  8.  
  9. 	*bonesid = set_bonesfile_name(bones, lev);
  10. 	fq_bones = fqname(bones, BONESPREFIX, 0);
  11. 	uncompress(fq_bones);	/* no effect if nonexistent */
  12. #ifdef MAC
  13. 	fd = macopen(fq_bones, O_RDONLY | O_BINARY, BONE_TYPE);
  14. #else
  15. 	fd = open(fq_bones, O_RDONLY | O_BINARY, 0);
  16. #endif
  17. 	return fd;
  18. }

delete_bonesfile

  1. int
  2. delete_bonesfile(lev)
  3. d_level *lev;
  4. {
  5. 	(void) set_bonesfile_name(bones, lev);
  6. 	return !(unlink(fqname(bones, BONESPREFIX, 0)) < 0);
  7. }

compress_bonesfile

  1. /* assume we're compressing the recently read or created bonesfile, so the
  2. * file name is already set properly */
  3. void
  4. compress_bonesfile()
  5. {
  6. 	compress(fqname(bones, BONESPREFIX, 0));
  7. }
  8.  
  9. /* ----------  END BONES FILE HANDLING ----------- */

Save file handling

  1. /* ----------  BEGIN SAVE FILE HANDLING ----------- */

set_savefile_name

  1. /* set savefile name in OS-dependent manner from pre-existing plname,
  2. * avoiding troublesome characters */
  3. void
  4. set_savefile_name()
  5. {
  6. #if defined(WIN32)
  7. 	char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
  8. #endif
  9. #ifdef VMS
  10. 	Sprintf(SAVEF, "[.save]%d%s", getuid(), plname);
  11. 	regularize(SAVEF+7);
  12. 	Strcat(SAVEF, ";1");
  13. #else
  14. # if defined(MICRO)
  15. 	Strcpy(SAVEF, SAVEP);
  16. #  ifdef AMIGA
  17. 	strncat(SAVEF, bbs_id, PATHLEN);
  18. #  endif
  19. 	{
  20. 		int i = strlen(SAVEP);
  21. #  ifdef AMIGA
  22. 		/* plname has to share space with SAVEP and ".sav" */
  23. 		(void)strncat(SAVEF, plname, FILENAME - i - 4);
  24. #  else
  25. 		(void)strncat(SAVEF, plname, 8);
  26. #  endif
  27. 		regularize(SAVEF+i);
  28. 	}
  29. 	Strcat(SAVEF, ".sav");
  30. # else
  31. #  if defined(WIN32)
  32. 	/* Obtain the name of the logged on user and incorporate
  33. 	 * it into the name. */
  34. 	Sprintf(fnamebuf, "%s-%s", get_username(0), plname);
  35. 	(void)fname_encode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.",
  36. 				'%', fnamebuf, encodedfnamebuf, BUFSZ);
  37. 	Sprintf(SAVEF, "%s.NetHack-saved-game", encodedfnamebuf);
  38. #  else
  39. 	Sprintf(SAVEF, "save/%d%s", (int)getuid(), plname);
  40. 	regularize(SAVEF+5);	/* avoid . or / in name */
  41. #  endif /* WIN32 */
  42. # endif	/* MICRO */
  43. #endif /* VMS   */
  44. }

save_savefile_name

  1. #ifdef INSURANCE
  2. void
  3. save_savefile_name(fd)
  4. int fd;
  5. {
  6. 	(void) write(fd, (genericptr_t) SAVEF, sizeof(SAVEF));
  7. }
  8. #endif

set_error_savefile

  1. #if defined(WIZARD) && !defined(MICRO)
  2. /* change pre-existing savefile name to indicate an error savefile */
  3. void
  4. set_error_savefile()
  5. {
  6. # ifdef VMS
  7. {
  8. 	char *semi_colon = rindex(SAVEF, ';');
  9. 	if (semi_colon) *semi_colon = '\0';
  10. }
  11. 	Strcat(SAVEF, ".e;1");
  12. # else
  13. #  ifdef MAC
  14. 	Strcat(SAVEF, "-e");
  15. #  else
  16. 	Strcat(SAVEF, ".e");
  17. #  endif
  18. # endif
  19. }
  20. #endif

create_savefile

  1. /* create save file, overwriting one if it already exists */
  2. int
  3. create_savefile()
  4. {
  5. 	const char *fq_save;
  6. 	int fd;
  7.  
  8. 	fq_save = fqname(SAVEF, SAVEPREFIX, 0);
  9. #if defined(MICRO) || defined(WIN32)
  10. 	fd = open(fq_save, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
  11. #else
  12. # ifdef MAC
  13. 	fd = maccreat(fq_save, SAVE_TYPE);
  14. # else
  15. 	fd = creat(fq_save, FCMASK);
  16. # endif
  17. # if defined(VMS) && !defined(SECURE)
  18. 	/*
  19. 	   Make sure the save file is owned by the current process.  That's
  20. 	   the default for non-privileged users, but for priv'd users the
  21. 	   file will be owned by the directory's owner instead of the user.
  22. 	 */
  23. #  ifdef getuid	/*(see vmsunix.c)*/
  24. #   undef getuid
  25. #  endif
  26. 	(void) chown(fq_save, getuid(), getgid());
  27. # endif /* VMS && !SECURE */
  28. #endif	/* MICRO */
  29.  
  30. 	return fd;
  31. }

open_savefile

  1. /* open savefile for reading */
  2. int
  3. open_savefile()
  4. {
  5. 	const char *fq_save;
  6. 	int fd;
  7.  
  8. 	fq_save = fqname(SAVEF, SAVEPREFIX, 0);
  9. #ifdef MAC
  10. 	fd = macopen(fq_save, O_RDONLY | O_BINARY, SAVE_TYPE);
  11. #else
  12. 	fd = open(fq_save, O_RDONLY | O_BINARY, 0);
  13. #endif
  14. 	return fd;
  15. }

delete_savefile

  1. /* delete savefile */
  2. int
  3. delete_savefile()
  4. {
  5. 	(void) unlink(fqname(SAVEF, SAVEPREFIX, 0));
  6. 	return 0;	/* for restore_saved_game() (ex-xxxmain.c) test */
  7. }

restore_saved_game

  1. /* try to open up a save file and prepare to restore it */
  2. int
  3. restore_saved_game()
  4. {
  5. 	const char *fq_save;
  6. 	int fd;
  7.  
  8. 	set_savefile_name();
  9. #ifdef MFLOPPY
  10. 	if (!saveDiskPrompt(1))
  11. 	    return -1;
  12. #endif /* MFLOPPY */
  13. 	fq_save = fqname(SAVEF, SAVEPREFIX, 0);
  14.  
  15. 	uncompress(fq_save);
  16. 	if ((fd = open_savefile()) < 0) return fd;
  17.  
  18. 	if (!uptodate(fd, fq_save)) {
  19. 	    (void) close(fd),  fd = -1;
  20. 	    (void) delete_savefile();
  21. 	}
  22. 	return fd;
  23. }

plname_from_file

  1. #if defined(UNIX) && defined(QT_GRAPHICS)
  2. /*ARGSUSED*/
  3. static char*
  4. plname_from_file(filename)
  5. const char* filename;
  6. {
  7. #ifdef STORE_PLNAME_IN_FILE
  8. int fd;
  9. char* result = 0;
  10.  
  11. Strcpy(SAVEF,filename);
  12. #ifdef COMPRESS_EXTENSION
  13. SAVEF[strlen(SAVEF)-strlen(COMPRESS_EXTENSION)] = '\0';
  14. #endif
  15. uncompress(SAVEF);
  16. if ((fd = open_savefile()) >= 0) {
  17. 	if (uptodate(fd, filename)) {
  18. 	    char tplname[PL_NSIZ];
  19. 	    mread(fd, (genericptr_t) tplname, PL_NSIZ);
  20. 	    result = strdup(tplname);
  21. 	}
  22. 	(void) close(fd);
  23. }
  24. compress(SAVEF);
  25.  
  26. return result;
  27. #else
  28. # if defined(UNIX) && defined(QT_GRAPHICS)
  29. /* Name not stored in save file, so we have to extract it from
  30. the filename, which loses information
  31. (eg. "/", "_", and "." characters are lost. */
  32. int k;
  33. int uid;
  34. char name[64]; /* more than PL_NSIZ */
  35. #ifdef COMPRESS_EXTENSION
  36. #define EXTSTR COMPRESS_EXTENSION
  37. #else
  38. #define EXTSTR ""
  39. #endif
  40. if ( sscanf( filename, "%*[^/]/%d%63[^.]" EXTSTR, &uid, name ) == 2 ) {
  41. #undef EXTSTR
  42. /* "_" most likely means " ", which certainly looks nicer */
  43. 	for (k=0; name[k]; k++)
  44. 	    if ( name[k]=='_' )
  45. 		name[k]=' ';
  46. 	return strdup(name);
  47. } else
  48. # endif
  49. {
  50. 	return 0;
  51. }
  52. #endif
  53. }
  54. #endif /* defined(UNIX) && defined(QT_GRAPHICS) */

get_saved_games

  1. char**
  2. get_saved_games()
  3. {
  4. #if defined(UNIX) && defined(QT_GRAPHICS)
  5. int myuid=getuid();
  6. struct dirent **namelist;
  7. int n = scandir("save", &namelist, 0, alphasort);;
  8. if ( n > 0 ) {
  9. 	int i,j=0;
  10. 	char** result = (char**)alloc((n+1)*sizeof(char*)); /* at most */
  11. 	for (i=0; i<n; i++) {
  12. 	    int uid;
  13. 	    char name[64]; /* more than PL_NSIZ */
  14. 	    if ( sscanf( namelist[i]->d_name, "%d%63s", &uid, name ) == 2 ) {
  15. 		if ( uid == myuid ) {
  16. 		    char filename[BUFSZ];
  17. 		    char* r;
  18. 		    Sprintf(filename,"save/%d%s",uid,name);
  19. 		    r = plname_from_file(filename);
  20. 		    if ( r )
  21. 			result[j++] = r;
  22. 		}
  23. 	    }
  24. 	}
  25. 	result[j++] = 0;
  26. 	return result;
  27. } else
  28. #endif
  29. {
  30. 	return 0;
  31. }
  32. }

free_saved_games

  1. void
  2. free_saved_games(saved)
  3. char** saved;
  4. {
  5. if ( saved ) {
  6. 	int i=0;
  7. 	while (saved[i]) free((genericptr_t)saved[i++]);
  8. 	free((genericptr_t)saved);
  9. }
  10. }
  11.  
  12.  
  13. /* ----------  END SAVE FILE HANDLING ----------- */

File compression handling

  1. /* ----------  BEGIN FILE COMPRESSION HANDLING ----------- */

redirect

  1. #ifdef COMPRESS
  2.  
  3. STATIC_OVL void
  4. redirect(filename, mode, stream, uncomp)
  5. const char *filename, *mode;
  6. FILE *stream;
  7. boolean uncomp;
  8. {
  9. 	if (freopen(filename, mode, stream) == (FILE *)0) {
  10. 		(void) fprintf(stderr, "freopen of %s for %scompress failed\n",
  11. 			filename, uncomp ? "un" : "");
  12. 		terminate(EXIT_FAILURE);
  13. 	}
  14. }

docompress_file

  1. /*
  2. * using system() is simpler, but opens up security holes and causes
  3. * problems on at least Interactive UNIX 3.0.1 (SVR3.2), where any
  4. * setuid is renounced by /bin/sh, so the files cannot be accessed.
  5. *
  6. * cf. child() in unixunix.c.
  7. */
  8. STATIC_OVL void
  9. docompress_file(filename, uncomp)
  10. const char *filename;
  11. boolean uncomp;
  12. {
  13. 	char cfn[80];
  14. 	FILE *cf;
  15. 	const char *args[10];
  16. # ifdef COMPRESS_OPTIONS
  17. 	char opts[80];
  18. # endif
  19. 	int i = 0;
  20. 	int f;
  21. # ifdef TTY_GRAPHICS
  22. 	boolean istty = !strncmpi(windowprocs.name, "tty", 3);
  23. # endif
  24.  
  25. 	Strcpy(cfn, filename);
  26. # ifdef COMPRESS_EXTENSION
  27. 	Strcat(cfn, COMPRESS_EXTENSION);
  28. # endif
  29. 	/* when compressing, we know the file exists */
  30. 	if (uncomp) {
  31. 	    if ((cf = fopen(cfn, RDBMODE)) == (FILE *)0)
  32. 		    return;
  33. 	    (void) fclose(cf);
  34. 	}
  35.  
  36. 	args[0] = COMPRESS;
  37. 	if (uncomp) args[++i] = "-d";	/* uncompress */
  38. # ifdef COMPRESS_OPTIONS
  39. 	{
  40. 	    /* we can't guarantee there's only one additional option, sigh */
  41. 	    char *opt;
  42. 	    boolean inword = FALSE;
  43.  
  44. 	    Strcpy(opts, COMPRESS_OPTIONS);
  45. 	    opt = opts;
  46. 	    while (*opt) {
  47. 		if ((*opt == ' ') || (*opt == '\t')) {
  48. 		    if (inword) {
  49. 			*opt = '\0';
  50. 			inword = FALSE;
  51. 		    }
  52. 		} else if (!inword) {
  53. 		    args[++i] = opt;
  54. 		    inword = TRUE;
  55. 		}
  56. 		opt++;
  57. 	    }
  58. 	}
  59. # endif
  60. 	args[++i] = (char *)0;
  61.  
  62. # ifdef TTY_GRAPHICS
  63. 	/* If we don't do this and we are right after a y/n question *and*
  64. 	 * there is an error message from the compression, the 'y' or 'n' can
  65. 	 * end up being displayed after the error message.
  66. 	 */
  67. 	if (istty)
  68. 	    mark_synch();
  69. # endif
  70. 	f = fork();
  71. 	if (f == 0) {	/* child */
  72. # ifdef TTY_GRAPHICS
  73. 		/* any error messages from the compression must come out after
  74. 		 * the first line, because the more() to let the user read
  75. 		 * them will have to clear the first line.  This should be
  76. 		 * invisible if there are no error messages.
  77. 		 */
  78. 		if (istty)
  79. 		    raw_print("");
  80. # endif
  81. 		/* run compressor without privileges, in case other programs
  82. 		 * have surprises along the line of gzip once taking filenames
  83. 		 * in GZIP.
  84. 		 */
  85. 		/* assume all compressors will compress stdin to stdout
  86. 		 * without explicit filenames.  this is true of at least
  87. 		 * compress and gzip, those mentioned in config.h.
  88. 		 */
  89. 		if (uncomp) {
  90. 			redirect(cfn, RDBMODE, stdin, uncomp);
  91. 			redirect(filename, WRBMODE, stdout, uncomp);
  92. 		} else {
  93. 			redirect(filename, RDBMODE, stdin, uncomp);
  94. 			redirect(cfn, WRBMODE, stdout, uncomp);
  95. 		}
  96. 		(void) setgid(getgid());
  97. 		(void) setuid(getuid());
  98. 		(void) execv(args[0], (char *const *) args);
  99. 		perror((char *)0);
  100. 		(void) fprintf(stderr, "Exec to %scompress %s failed.\n",
  101. 			uncomp ? "un" : "", filename);
  102. 		terminate(EXIT_FAILURE);
  103. 	} else if (f == -1) {
  104. 		perror((char *)0);
  105. 		pline("Fork to %scompress %s failed.",
  106. 			uncomp ? "un" : "", filename);
  107. 		return;
  108. 	}
  109. 	(void) signal(SIGINT, SIG_IGN);
  110. 	(void) signal(SIGQUIT, SIG_IGN);
  111. 	(void) wait((int *)&i);
  112. 	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
  113. # ifdef WIZARD
  114. 	if (wizard) (void) signal(SIGQUIT, SIG_DFL);
  115. # endif
  116. 	if (i == 0) {
  117. 	    /* (un)compress succeeded: remove file left behind */
  118. 	    if (uncomp)
  119. 		(void) unlink(cfn);
  120. 	    else
  121. 		(void) unlink(filename);
  122. 	} else {
  123. 	    /* (un)compress failed; remove the new, bad file */
  124. 	    if (uncomp) {
  125. 		raw_printf("Unable to uncompress %s", filename);
  126. 		(void) unlink(filename);
  127. 	    } else {
  128. 		/* no message needed for compress case; life will go on */
  129. 		(void) unlink(cfn);
  130. 	    }
  131. #ifdef TTY_GRAPHICS
  132. 	    /* Give them a chance to read any error messages from the
  133. 	     * compression--these would go to stdout or stderr and would get
  134. 	     * overwritten only in tty mode.  It's still ugly, since the
  135. 	     * messages are being written on top of the screen, but at least
  136. 	     * the user can read them.
  137. 	     */
  138. 	    if (istty)
  139. 	    {
  140. 		clear_nhwindow(WIN_MESSAGE);
  141. 		more();
  142. 		/* No way to know if this is feasible */
  143. 		/* doredraw(); */
  144. 	    }
  145. #endif
  146. 	}
  147. }
  148. #endif	/* COMPRESS */

compress

  1. /* compress file */
  2. void
  3. compress(filename)
  4. const char *filename;
  5. {
  6. #ifndef COMPRESS
  7. #if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
  8. # pragma unused(filename)
  9. #endif
  10. #else
  11. 	docompress_file(filename, FALSE);
  12. #endif
  13. }

uncompress

  1. /* uncompress file if it exists */
  2. void
  3. uncompress(filename)
  4. const char *filename;
  5. {
  6. #ifndef COMPRESS
  7. #if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
  8. # pragma unused(filename)
  9. #endif
  10. #else
  11. 	docompress_file(filename, TRUE);
  12. #endif
  13. }
  14.  
  15. /* ----------  END FILE COMPRESSION HANDLING ----------- */

File locking handling

  1. /* ----------  BEGIN FILE LOCKING HANDLING ----------- */
  2.  
  3. static int nesting = 0;
  4.  
  5. #ifdef NO_FILE_LINKS	/* implies UNIX */
  6. static int lockfd;	/* for lock_file() to pass to unlock_file() */
  7. #endif
  8.  
  9. #define HUP	if (!program_state.done_hup)

make_lockname

  1. STATIC_OVL char *
  2. make_lockname(filename, lockname)
  3. const char *filename;
  4. char *lockname;
  5. {
  6. #if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
  7. # pragma unused(filename,lockname)
  8. 	return (char*)0;
  9. #else
  10. # if defined(UNIX) || defined(VMS) || defined(AMIGA) || defined(WIN32) || defined(MSDOS)
  11. #  ifdef NO_FILE_LINKS
  12. 	Strcpy(lockname, LOCKDIR);
  13. 	Strcat(lockname, "/");
  14. 	Strcat(lockname, filename);
  15. #  else
  16. 	Strcpy(lockname, filename);
  17. #  endif
  18. #  ifdef VMS
  19. {
  20. 	char *semi_colon = rindex(lockname, ';');
  21. 	if (semi_colon) *semi_colon = '\0';
  22. }
  23. 	Strcat(lockname, ".lock;1");
  24. #  else
  25. 	Strcat(lockname, "_lock");
  26. #  endif
  27. 	return lockname;
  28. # else
  29. 	lockname[0] = '\0';
  30. 	return (char*)0;
  31. # endif  /* UNIX || VMS || AMIGA || WIN32 || MSDOS */
  32. #endif
  33. }

lock_file

  1. /* lock a file */
  2. boolean
  3. lock_file(filename, whichprefix, retryct)
  4. const char *filename;
  5. int whichprefix;
  6. int retryct;
  7. {
  8. #if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
  9. # pragma unused(filename, retryct)
  10. #endif
  11. 	char locknambuf[BUFSZ];
  12. 	const char *lockname;
  13.  
  14. 	nesting++;
  15. 	if (nesting > 1) {
  16. 	    impossible("TRIED TO NEST LOCKS");
  17. 	    return TRUE;
  18. 	}
  19.  
  20. 	lockname = make_lockname(filename, locknambuf);
  21. 	filename = fqname(filename, whichprefix, 0);
  22. #ifndef NO_FILE_LINKS	/* LOCKDIR should be subsumed by LOCKPREFIX */
  23. 	lockname = fqname(lockname, LOCKPREFIX, 2);
  24. #endif
  25.  
  26. #if defined(UNIX) || defined(VMS)
  27. # ifdef NO_FILE_LINKS
  28. 	while ((lockfd = open(lockname, O_RDWR|O_CREAT|O_EXCL, 0666)) == -1) {
  29. # else
  30. 	while (link(filename, lockname) == -1) {
  31. # endif
  32. 	    register int errnosv = errno;
  33.  
  34. 	    switch (errnosv) {	/* George Barbanis */
  35. 	    case EEXIST:
  36. 		if (retryct--) {
  37. 		    HUP raw_printf(
  38. 			    "Waiting for access to %s.  (%d retries left).",
  39. 			    filename, retryct);
  40. # if defined(SYSV) || defined(ULTRIX) || defined(VMS)
  41. 		    (void)
  42. # endif
  43. 			sleep(1);
  44. 		} else {
  45. 		    HUP (void) raw_print("I give up.  Sorry.");
  46. 		    HUP raw_printf("Perhaps there is an old %s around?",
  47. 					lockname);
  48. 		    nesting--;
  49. 		    return FALSE;
  50. 		}
  51.  
  52. 		break;
  53. 	    case ENOENT:
  54. 		HUP raw_printf("Can't find file %s to lock!", filename);
  55. 		nesting--;
  56. 		return FALSE;
  57. 	    case EACCES:
  58. 		HUP raw_printf("No write permission to lock %s!", filename);
  59. 		nesting--;
  60. 		return FALSE;
  61. # ifdef VMS			/* c__translate(vmsfiles.c) */
  62. 	    case EPERM:
  63. 		/* could be misleading, but usually right */
  64. 		HUP raw_printf("Can't lock %s due to directory protection.",
  65. 			       filename);
  66. 		nesting--;
  67. 		return FALSE;
  68. # endif
  69. 	    default:
  70. 		HUP perror(lockname);
  71. 		HUP raw_printf(
  72. 			     "Cannot lock %s for unknown reason (%d).",
  73. 			       filename, errnosv);
  74. 		nesting--;
  75. 		return FALSE;
  76. 	    }
  77.  
  78. 	}
  79. #endif  /* UNIX || VMS */
  80.  
  81. #if defined(AMIGA) || defined(WIN32) || defined(MSDOS)
  82. # ifdef AMIGA
  83. #define OPENFAILURE(fd) (!fd)
  84. lockptr = 0;
  85. # else
  86. #define OPENFAILURE(fd) (fd < 0)
  87. lockptr = -1;
  88. # endif
  89. while (--retryct && OPENFAILURE(lockptr)) {
  90. # if defined(WIN32) && !defined(WIN_CE)
  91. 	lockptr = sopen(lockname, O_RDWR|O_CREAT, SH_DENYRW, S_IWRITE);
  92. # else
  93. 	(void)DeleteFile(lockname); /* in case dead process was here first */
  94. #  ifdef AMIGA
  95. 	lockptr = Open(lockname,MODE_NEWFILE);
  96. #  else
  97. 	lockptr = open(lockname, O_RDWR|O_CREAT|O_EXCL, S_IWRITE);
  98. #  endif
  99. # endif
  100. 	if (OPENFAILURE(lockptr)) {
  101. 	    raw_printf("Waiting for access to %s.  (%d retries left).",
  102. 			filename, retryct);
  103. 	    Delay(50);
  104. 	}
  105. }
  106. if (!retryct) {
  107. 	raw_printf("I give up.  Sorry.");
  108. 	nesting--;
  109. 	return FALSE;
  110. }
  111. #endif /* AMIGA || WIN32 || MSDOS */
  112. 	return TRUE;
  113. }
  114.  
  115.  
  116. #ifdef VMS	/* for unlock_file, use the unlink() routine in vmsunix.c */
  117. # ifdef unlink
  118. #  undef unlink
  119. # endif
  120. # define unlink(foo) vms_unlink(foo)
  121. #endif

unlock_file

  1. /* unlock file, which must be currently locked by lock_file */
  2. void
  3. unlock_file(filename)
  4. const char *filename;
  5. #if defined(macintosh) && (defined(__SC__) || defined(__MRC__))
  6. # pragma unused(filename)
  7. #endif
  8. {
  9. 	char locknambuf[BUFSZ];
  10. 	const char *lockname;
  11.  
  12. 	if (nesting == 1) {
  13. 		lockname = make_lockname(filename, locknambuf);
  14. #ifndef NO_FILE_LINKS	/* LOCKDIR should be subsumed by LOCKPREFIX */
  15. 		lockname = fqname(lockname, LOCKPREFIX, 2);
  16. #endif
  17.  
  18. #if defined(UNIX) || defined(VMS)
  19. 		if (unlink(lockname) < 0)
  20. 			HUP raw_printf("Can't unlink %s.", lockname);
  21. # ifdef NO_FILE_LINKS
  22. 		(void) close(lockfd);
  23. # endif
  24.  
  25. #endif  /* UNIX || VMS */
  26.  
  27. #if defined(AMIGA) || defined(WIN32) || defined(MSDOS)
  28. 		if (lockptr) Close(lockptr);
  29. 		DeleteFile(lockname);
  30. 		lockptr = 0;
  31. #endif /* AMIGA || WIN32 || MSDOS */
  32. 	}
  33.  
  34. 	nesting--;
  35. }
  36.  
  37. /* ----------  END FILE LOCKING HANDLING ----------- */

Config file handling

  1. /* ----------  BEGIN CONFIG FILE HANDLING ----------- */
  2.  
  3. const char *configfile =
  4. #ifdef UNIX
  5. 			".nethackrc";
  6. #else
  7. # if defined(MAC) || defined(__BEOS__)
  8. 			"NetHack Defaults";
  9. # else
  10. #  if defined(MSDOS) || defined(WIN32)
  11. 			"defaults.nh";
  12. #  else
  13. 			"NetHack.cnf";
  14. #  endif
  15. # endif
  16. #endif
  17.  
  18.  
  19. #ifdef MSDOS
  20. /* conflict with speed-dial under windows
  21. * for XXX.cnf file so support of NetHack.cnf
  22. * is for backward compatibility only.
  23. * Preferred name (and first tried) is now defaults.nh but
  24. * the game will try the old name if there
  25. * is no defaults.nh.
  26. */
  27. const char *backward_compat_configfile = "nethack.cnf"; 
  28. #endif
  29.  
  30. #ifndef MFLOPPY
  31. #define fopenp fopen
  32. #endif

fopen_config_file

  1. STATIC_OVL FILE *
  2. fopen_config_file(filename)
  3. const char *filename;
  4. {
  5. 	FILE *fp;
  6. #if defined(UNIX) || defined(VMS)
  7. 	char	tmp_config[BUFSZ];
  8. 	char *envp;
  9. #endif
  10.  
  11. 	/* "filename" is an environment variable, so it should hang around */
  12. 	/* if set, it is expected to be a full path name (if relevant) */
  13. 	if (filename) {
  14. #ifdef UNIX
  15. 		if (access(filename, 4) == -1) {
  16. 			/* 4 is R_OK on newer systems */
  17. 			/* nasty sneaky attempt to read file through
  18. 			 * NetHack's setuid permissions -- this is the only
  19. 			 * place a file name may be wholly under the player's
  20. 			 * control
  21. 			 */
  22. 			raw_printf("Access to %s denied (%d).",
  23. 					filename, errno);
  24. 			wait_synch();
  25. 			/* fall through to standard names */
  26. 		} else
  27. #endif
  28. 		if ((fp = fopenp(filename, "r")) != (FILE *)0) {
  29. 		    configfile = filename;
  30. 		    return(fp);
  31. #if defined(UNIX) || defined(VMS)
  32. 		} else {
  33. 		    /* access() above probably caught most problems for UNIX */
  34. 		    raw_printf("Couldn't open requested config file %s (%d).",
  35. 					filename, errno);
  36. 		    wait_synch();
  37. 		    /* fall through to standard names */
  38. #endif
  39. 		}
  40. 	}
  41.  
  42. #if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32)
  43. 	if ((fp = fopenp(fqname(configfile, CONFIGPREFIX, 0), "r"))
  44. 								!= (FILE *)0)
  45. 		return(fp);
  46. # ifdef MSDOS
  47. 	else if ((fp = fopenp(fqname(backward_compat_configfile,
  48. 					CONFIGPREFIX, 0), "r")) != (FILE *)0)
  49. 		return(fp);
  50. # endif
  51. #else
  52. 	/* constructed full path names don't need fqname() */
  53. # ifdef VMS
  54. 	if ((fp = fopenp(fqname("nethackini", CONFIGPREFIX, 0), "r"))
  55. 								!= (FILE *)0) {
  56. 		configfile = "nethackini";
  57. 		return(fp);
  58. 	}
  59. 	if ((fp = fopenp("sys$login:nethack.ini", "r")) != (FILE *)0) {
  60. 		configfile = "nethack.ini";
  61. 		return(fp);
  62. 	}
  63.  
  64. 	envp = nh_getenv("HOME");
  65. 	if (!envp)
  66. 		Strcpy(tmp_config, "NetHack.cnf");
  67. 	else
  68. 		Sprintf(tmp_config, "%s%s", envp, "NetHack.cnf");
  69. 	if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
  70. 		return(fp);
  71. # else	/* should be only UNIX left */
  72. 	envp = nh_getenv("HOME");
  73. 	if (!envp)
  74. 		Strcpy(tmp_config, configfile);
  75. 	else
  76. 		Sprintf(tmp_config, "%s/%s", envp, configfile);
  77. 	if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
  78. 		return(fp);
  79. # if defined(__APPLE__)
  80. 	/* try an alternative */
  81. 	if (envp) {
  82. 		Sprintf(tmp_config, "%s/%s", envp, "Library/Preferences/NetHack Defaults");
  83. 		if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
  84. 			return(fp);
  85. 		Sprintf(tmp_config, "%s/%s", envp, "Library/Preferences/NetHack Defaults.txt");
  86. 		if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
  87. 			return(fp);
  88. 	}
  89. # endif
  90. 	if (errno != ENOENT) {
  91. 	    char *details;
  92.  
  93. 	    /* e.g., problems when setuid NetHack can't search home
  94. 	     * directory restricted to user */
  95.  
  96. #if defined (NHSTDC) && !defined(NOTSTDC)
  97. 	    if ((details = strerror(errno)) == 0)
  98. #endif
  99. 		details = "";
  100. 	    raw_printf("Couldn't open default config file %s %s(%d).",
  101. 		       tmp_config, details, errno);
  102. 	    wait_synch();
  103. 	}
  104. # endif
  105. #endif
  106. 	return (FILE *)0;
  107.  
  108. }

get_uchars

  1. /*
  2. * Retrieve a list of integers from a file into a uchar array.
  3. *
  4. * NOTE: zeros are inserted unless modlist is TRUE, in which case the list
  5. *  location is unchanged.  Callers must handle zeros if modlist is FALSE.
  6. */
  7. STATIC_OVL int
  8. get_uchars(fp, buf, bufp, list, modlist, size, name)
  9. FILE *fp;		/* input file pointer */
  10. char *buf;		/* read buffer, must be of size BUFSZ */
  11. char *bufp;		/* current pointer */
  12. uchar *list;	/* return list */
  13. boolean modlist;	/* TRUE: list is being modified in place */
  14. int  size;		/* return list size */
  15. const char *name;		/* name of option for error message */
  16. {
  17. unsigned int num = 0;
  18. int count = 0;
  19. boolean havenum = FALSE;
  20.  
  21. while (1) {
  22. 	switch(*bufp) {
  23. 	    case ' ':  case '\0':
  24. 	    case '\t': case '\n':
  25. 		if (havenum) {
  26. 		    /* if modifying in place, don't insert zeros */
  27. 		    if (num || !modlist) list[count] = num;
  28. 		    count++;
  29. 		    num = 0;
  30. 		    havenum = FALSE;
  31. 		}
  32. 		if (count == size || !*bufp) return count;
  33. 		bufp++;
  34. 		break;
  35.  
  36. 	    case '0': case '1': case '2': case '3':
  37. 	    case '4': case '5': case '6': case '7':
  38. 	    case '8': case '9':
  39. 		havenum = TRUE;
  40. 		num = num*10 + (*bufp-'0');
  41. 		bufp++;
  42. 		break;
  43.  
  44. 	    case '\\':
  45. 		if (fp == (FILE *)0)
  46. 		    goto gi_error;
  47. 		do  {
  48. 		    if (!fgets(buf, BUFSZ, fp)) goto gi_error;
  49. 		} while (buf[0] == '#');
  50. 		bufp = buf;
  51. 		break;
  52.  
  53. 	    default:
  54. gi_error:
  55. 		raw_printf("Syntax error in %s", name);
  56. 		wait_synch();
  57. 		return count;
  58. 	}
  59. }
  60. /*NOTREACHED*/
  61. }

adjust_prefix

  1. #ifdef NOCWD_ASSUMPTIONS
  2. STATIC_OVL void
  3. adjust_prefix(bufp, prefixid)
  4. char *bufp;
  5. int prefixid;
  6. {
  7. 	char *ptr;
  8.  
  9. 	if (!bufp) return;
  10. 	/* Backward compatibility, ignore trailing ;n */ 
  11. 	if ((ptr = index(bufp, ';')) != 0) *ptr = '\0';
  12. 	if (strlen(bufp) > 0) {
  13. 		fqn_prefix[prefixid] = (char *)alloc(strlen(bufp)+2);
  14. 		Strcpy(fqn_prefix[prefixid], bufp);
  15. 		append_slash(fqn_prefix[prefixid]);
  16. 	}
  17. }
  18. #endif
  19.  
  20. #define match_varname(INP,NAM,LEN) match_optname(INP, NAM, LEN, TRUE)

parse_config_line

  1. /*ARGSUSED*/
  2. int
  3. parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)
  4. FILE		*fp;
  5. char		*buf;
  6. char		*tmp_ramdisk;
  7. char		*tmp_levels;
  8. {
  9. #if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
  10. # pragma unused(tmp_ramdisk,tmp_levels)
  11. #endif
  12. 	char		*bufp, *altp;
  13. 	uchar   translate[MAXPCHARS];
  14. 	int   len;
  15.  
  16. 	if (*buf == '#')
  17. 		return 1;
  18.  
  19. 	/* remove trailing whitespace */
  20. 	bufp = eos(buf);
  21. 	while (--bufp > buf && isspace(*bufp))
  22. 		continue;
  23.  
  24. 	if (bufp <= buf)
  25. 		return 1;		/* skip all-blank lines */
  26. 	else
  27. 		*(bufp + 1) = '\0';	/* terminate line */
  28.  
  29. 	/* find the '=' or ':' */
  30. 	bufp = index(buf, '=');
  31. 	altp = index(buf, ':');
  32. 	if (!bufp || (altp && altp < bufp)) bufp = altp;
  33. 	if (!bufp) return 0;
  34.  
  35. 	/* skip  whitespace between '=' and value */
  36. 	do { ++bufp; } while (isspace(*bufp));
  37.  
  38. 	/* Go through possible variables */
  39. 	/* some of these (at least LEVELS and SAVE) should now set the
  40. 	 * appropriate fqn_prefix[] rather than specialized variables
  41. 	 */
  42. 	if (match_varname(buf, "OPTIONS", 4)) {
  43. 		parseoptions(bufp, TRUE, TRUE);
  44. 		if (plname[0])		/* If a name was given */
  45. 			plnamesuffix();	/* set the character class */
  46. #ifdef AUTOPICKUP_EXCEPTIONS
  47. 	} else if (match_varname(buf, "AUTOPICKUP_EXCEPTION", 5)) {
  48. 		add_autopickup_exception(bufp);
  49. #endif
  50. #ifdef NOCWD_ASSUMPTIONS
  51. 	} else if (match_varname(buf, "HACKDIR", 4)) {
  52. 		adjust_prefix(bufp, HACKPREFIX);
  53. 	} else if (match_varname(buf, "LEVELDIR", 4) ||
  54. 		   match_varname(buf, "LEVELS", 4)) {
  55. 		adjust_prefix(bufp, LEVELPREFIX);
  56. 	} else if (match_varname(buf, "SAVEDIR", 4)) {
  57. 		adjust_prefix(bufp, SAVEPREFIX);
  58. 	} else if (match_varname(buf, "BONESDIR", 5)) {
  59. 		adjust_prefix(bufp, BONESPREFIX);
  60. 	} else if (match_varname(buf, "DATADIR", 4)) {
  61. 		adjust_prefix(bufp, DATAPREFIX);
  62. 	} else if (match_varname(buf, "SCOREDIR", 4)) {
  63. 		adjust_prefix(bufp, SCOREPREFIX);
  64. 	} else if (match_varname(buf, "LOCKDIR", 4)) {
  65. 		adjust_prefix(bufp, LOCKPREFIX);
  66. 	} else if (match_varname(buf, "CONFIGDIR", 4)) {
  67. 		adjust_prefix(bufp, CONFIGPREFIX);
  68. 	} else if (match_varname(buf, "TROUBLEDIR", 4)) {
  69. 		adjust_prefix(bufp, TROUBLEPREFIX);
  70. #else /*NOCWD_ASSUMPTIONS*/
  71. # ifdef MICRO
  72. 	} else if (match_varname(buf, "HACKDIR", 4)) {
  73. 		(void) strncpy(hackdir, bufp, PATHLEN-1);
  74. #  ifdef MFLOPPY
  75. 	} else if (match_varname(buf, "RAMDISK", 3)) {
  76. 				/* The following ifdef is NOT in the wrong
  77. 				 * place.  For now, we accept and silently
  78. 				 * ignore RAMDISK */
  79. #   ifndef AMIGA
  80. 		(void) strncpy(tmp_ramdisk, bufp, PATHLEN-1);
  81. #   endif
  82. #  endif
  83. 	} else if (match_varname(buf, "LEVELS", 4)) {
  84. 		(void) strncpy(tmp_levels, bufp, PATHLEN-1);
  85.  
  86. 	} else if (match_varname(buf, "SAVE", 4)) {
  87. #  ifdef MFLOPPY
  88. 		extern	int saveprompt;
  89. #  endif
  90. 		char *ptr;
  91. 		if ((ptr = index(bufp, ';')) != 0) {
  92. 			*ptr = '\0';
  93. #  ifdef MFLOPPY
  94. 			if (*(ptr+1) == 'n' || *(ptr+1) == 'N') {
  95. 				saveprompt = FALSE;
  96. 			}
  97. #  endif
  98. 		}
  99. # ifdef	MFLOPPY
  100. 		else
  101. 		    saveprompt = flags.asksavedisk;
  102. # endif
  103.  
  104. 		(void) strncpy(SAVEP, bufp, SAVESIZE-1);
  105. 		append_slash(SAVEP);
  106. # endif /* MICRO */
  107. #endif /*NOCWD_ASSUMPTIONS*/
  108.  
  109. 	} else if (match_varname(buf, "NAME", 4)) {
  110. 	    (void) strncpy(plname, bufp, PL_NSIZ-1);
  111. 	    plnamesuffix();
  112. 	} else if (match_varname(buf, "ROLE", 4) ||
  113. 		   match_varname(buf, "CHARACTER", 4)) {
  114. 	    if ((len = str2role(bufp)) >= 0)
  115. 	    	flags.initrole = len;
  116. 	} else if (match_varname(buf, "DOGNAME", 3)) {
  117. 	    (void) strncpy(dogname, bufp, PL_PSIZ-1);
  118. 	} else if (match_varname(buf, "CATNAME", 3)) {
  119. 	    (void) strncpy(catname, bufp, PL_PSIZ-1);
  120.  
  121. 	} else if (match_varname(buf, "BOULDER", 3)) {
  122. 	    (void) get_uchars(fp, buf, bufp, &iflags.bouldersym, TRUE,
  123. 			      1, "BOULDER");
  124. 	} else if (match_varname(buf, "GRAPHICS", 4)) {
  125. 	    len = get_uchars(fp, buf, bufp, translate, FALSE,
  126. 			     MAXPCHARS, "GRAPHICS");
  127. 	    assign_graphics(translate, len, MAXPCHARS, 0);
  128. 	} else if (match_varname(buf, "DUNGEON", 4)) {
  129. 	    len = get_uchars(fp, buf, bufp, translate, FALSE,
  130. 			     MAXDCHARS, "DUNGEON");
  131. 	    assign_graphics(translate, len, MAXDCHARS, 0);
  132. 	} else if (match_varname(buf, "TRAPS", 4)) {
  133. 	    len = get_uchars(fp, buf, bufp, translate, FALSE,
  134. 			     MAXTCHARS, "TRAPS");
  135. 	    assign_graphics(translate, len, MAXTCHARS, MAXDCHARS);
  136. 	} else if (match_varname(buf, "EFFECTS", 4)) {
  137. 	    len = get_uchars(fp, buf, bufp, translate, FALSE,
  138. 			     MAXECHARS, "EFFECTS");
  139. 	    assign_graphics(translate, len, MAXECHARS, MAXDCHARS+MAXTCHARS);
  140.  
  141. 	} else if (match_varname(buf, "OBJECTS", 3)) {
  142. 	    /* oc_syms[0] is the RANDOM object, unused */
  143. 	    (void) get_uchars(fp, buf, bufp, &(oc_syms[1]), TRUE,
  144. 					MAXOCLASSES-1, "OBJECTS");
  145. 	} else if (match_varname(buf, "MONSTERS", 3)) {
  146. 	    /* monsyms[0] is unused */
  147. 	    (void) get_uchars(fp, buf, bufp, &(monsyms[1]), TRUE,
  148. 					MAXMCLASSES-1, "MONSTERS");
  149. 	} else if (match_varname(buf, "WARNINGS", 5)) {
  150. 	    (void) get_uchars(fp, buf, bufp, translate, FALSE,
  151. 					WARNCOUNT, "WARNINGS");
  152. 	    assign_warnings(translate);
  153. #ifdef WIZARD
  154. 	} else if (match_varname(buf, "WIZKIT", 6)) {
  155. 	    (void) strncpy(wizkit, bufp, WIZKIT_MAX-1);
  156. #endif
  157. #ifdef AMIGA
  158. 	} else if (match_varname(buf, "FONT", 4)) {
  159. 		char *t;
  160.  
  161. 		if( t = strchr( buf+5, ':' ) )
  162. 		{
  163. 		    *t = 0;
  164. 		    amii_set_text_font( buf+5, atoi( t + 1 ) );
  165. 		    *t = ':';
  166. 		}
  167. 	} else if (match_varname(buf, "PATH", 4)) {
  168. 		(void) strncpy(PATH, bufp, PATHLEN-1);
  169. 	} else if (match_varname(buf, "DEPTH", 5)) {
  170. 		extern int amii_numcolors;
  171. 		int val = atoi( bufp );
  172. 		amii_numcolors = 1L << min( DEPTH, val );
  173. 	} else if (match_varname(buf, "DRIPENS", 7)) {
  174. 		int i, val;
  175. 		char *t;
  176. 		for (i = 0, t = strtok(bufp, ",/"); t != (char *)0;
  177. 				i < 20 && (t = strtok((char*)0, ",/")), ++i) {
  178. 			sscanf(t, "%d", &val );
  179. 			flags.amii_dripens[i] = val;
  180. 		}
  181. 	} else if (match_varname(buf, "SCREENMODE", 10 )) {
  182. 		extern long amii_scrnmode;
  183. 		if (!stricmp(bufp,"req"))
  184. 		    amii_scrnmode = 0xffffffff; /* Requester */
  185. 		else if( sscanf(bufp, "%x", &amii_scrnmode) != 1 )
  186. 		    amii_scrnmode = 0;
  187. 	} else if (match_varname(buf, "MSGPENS", 7)) {
  188. 		extern int amii_msgAPen, amii_msgBPen;
  189. 		char *t = strtok(bufp, ",/");
  190. 		if( t )
  191. 		{
  192. 		    sscanf(t, "%d", &amii_msgAPen);
  193. 		    if( t = strtok((char*)0, ",/") )
  194. 				sscanf(t, "%d", &amii_msgBPen);
  195. 		}
  196. 	} else if (match_varname(buf, "TEXTPENS", 8)) {
  197. 		extern int amii_textAPen, amii_textBPen;
  198. 		char *t = strtok(bufp, ",/");
  199. 		if( t )
  200. 		{
  201. 		    sscanf(t, "%d", &amii_textAPen);
  202. 		    if( t = strtok((char*)0, ",/") )
  203. 				sscanf(t, "%d", &amii_textBPen);
  204. 		}
  205. 	} else if (match_varname(buf, "MENUPENS", 8)) {
  206. 		extern int amii_menuAPen, amii_menuBPen;
  207. 		char *t = strtok(bufp, ",/");
  208. 		if( t )
  209. 		{
  210. 		    sscanf(t, "%d", &amii_menuAPen);
  211. 		    if( t = strtok((char*)0, ",/") )
  212. 				sscanf(t, "%d", &amii_menuBPen);
  213. 		}
  214. 	} else if (match_varname(buf, "STATUSPENS", 10)) {
  215. 		extern int amii_statAPen, amii_statBPen;
  216. 		char *t = strtok(bufp, ",/");
  217. 		if( t )
  218. 		{
  219. 		    sscanf(t, "%d", &amii_statAPen);
  220. 		    if( t = strtok((char*)0, ",/") )
  221. 				sscanf(t, "%d", &amii_statBPen);
  222. 		}
  223. 	} else if (match_varname(buf, "OTHERPENS", 9)) {
  224. 		extern int amii_otherAPen, amii_otherBPen;
  225. 		char *t = strtok(bufp, ",/");
  226. 		if( t )
  227. 		{
  228. 		    sscanf(t, "%d", &amii_otherAPen);
  229. 		    if( t = strtok((char*)0, ",/") )
  230. 				sscanf(t, "%d", &amii_otherBPen);
  231. 		}
  232. 	} else if (match_varname(buf, "PENS", 4)) {
  233. 		extern unsigned short amii_init_map[ AMII_MAXCOLORS ];
  234. 		int i;
  235. 		char *t;
  236.  
  237. 		for (i = 0, t = strtok(bufp, ",/");
  238. 			i < AMII_MAXCOLORS && t != (char *)0;
  239. 			t = strtok((char *)0, ",/"), ++i)
  240. 		{
  241. 			sscanf(t, "%hx", &amii_init_map[i]);
  242. 		}
  243. 		amii_setpens( amii_numcolors = i );
  244. 	} else if (match_varname(buf, "FGPENS", 6)) {
  245. 		extern int foreg[ AMII_MAXCOLORS ];
  246. 		int i;
  247. 		char *t;
  248.  
  249. 		for (i = 0, t = strtok(bufp, ",/");
  250. 			i < AMII_MAXCOLORS && t != (char *)0;
  251. 			t = strtok((char *)0, ",/"), ++i)
  252. 		{
  253. 			sscanf(t, "%d", &foreg[i]);
  254. 		}
  255. 	} else if (match_varname(buf, "BGPENS", 6)) {
  256. 		extern int backg[ AMII_MAXCOLORS ];
  257. 		int i;
  258. 		char *t;
  259.  
  260. 		for (i = 0, t = strtok(bufp, ",/");
  261. 			i < AMII_MAXCOLORS && t != (char *)0;
  262. 			t = strtok((char *)0, ",/"), ++i)
  263. 		{
  264. 			sscanf(t, "%d", &backg[i]);
  265. 		}
  266. #endif
  267. #ifdef USER_SOUNDS
  268. 	} else if (match_varname(buf, "SOUNDDIR", 8)) {
  269. 		sounddir = (char *)strdup(bufp);
  270. 	} else if (match_varname(buf, "SOUND", 5)) {
  271. 		add_sound_mapping(bufp);
  272. #endif
  273. #ifdef QT_GRAPHICS
  274. 	/* These should move to wc_ options */
  275. 	} else if (match_varname(buf, "QT_TILEWIDTH", 12)) {
  276. 		extern char *qt_tilewidth;
  277. 		if (qt_tilewidth == NULL)	
  278. 			qt_tilewidth=(char *)strdup(bufp);
  279. 	} else if (match_varname(buf, "QT_TILEHEIGHT", 13)) {
  280. 		extern char *qt_tileheight;
  281. 		if (qt_tileheight == NULL)	
  282. 			qt_tileheight=(char *)strdup(bufp);
  283. 	} else if (match_varname(buf, "QT_FONTSIZE", 11)) {
  284. 		extern char *qt_fontsize;
  285. 		if (qt_fontsize == NULL)
  286. 			qt_fontsize=(char *)strdup(bufp);
  287. 	} else if (match_varname(buf, "QT_COMPACT", 10)) {
  288. 		extern int qt_compact_mode;
  289. 		qt_compact_mode = atoi(bufp);
  290. #endif
  291. 	} else
  292. 		return 0;
  293. 	return 1;
  294. }

can_read_file

  1. #ifdef USER_SOUNDS
  2. boolean
  3. can_read_file(filename)
  4. const char *filename;
  5. {
  6. 	return (access(filename, 4) == 0);
  7. }
  8. #endif /* USER_SOUNDS */

read_config_file

  1. void
  2. read_config_file(filename)
  3. const char *filename;
  4. {
  5. #define tmp_levels	(char *)0
  6. #define tmp_ramdisk	(char *)0
  7.  
  8. #if defined(MICRO) || defined(WIN32)
  9. #undef tmp_levels
  10. 	char	tmp_levels[PATHLEN];
  11. # ifdef MFLOPPY
  12. #  ifndef AMIGA
  13. #undef tmp_ramdisk
  14. 	char	tmp_ramdisk[PATHLEN];
  15. #  endif
  16. # endif
  17. #endif
  18. 	char	buf[4*BUFSZ];
  19. 	FILE	*fp;
  20.  
  21. 	if (!(fp = fopen_config_file(filename))) return;
  22.  
  23. #if defined(MICRO) || defined(WIN32)
  24. # ifdef MFLOPPY
  25. #  ifndef AMIGA
  26. 	tmp_ramdisk[0] = 0;
  27. #  endif
  28. # endif
  29. 	tmp_levels[0] = 0;
  30. #endif
  31. 	/* begin detection of duplicate configfile options */
  32. 	set_duplicate_opt_detection(1);
  33.  
  34. 	while (fgets(buf, 4*BUFSZ, fp)) {
  35. 		if (!parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)) {
  36. 			raw_printf("Bad option line:  \"%.50s\"", buf);
  37. 			wait_synch();
  38. 		}
  39. 	}
  40. 	(void) fclose(fp);
  41.  
  42. 	/* turn off detection of duplicate configfile options */
  43. 	set_duplicate_opt_detection(0);
  44.  
  45. #if defined(MICRO) && !defined(NOCWD_ASSUMPTIONS)
  46. 	/* should be superseded by fqn_prefix[] */
  47. # ifdef MFLOPPY
  48. 	Strcpy(permbones, tmp_levels);
  49. #  ifndef AMIGA
  50. 	if (tmp_ramdisk[0]) {
  51. 		Strcpy(levels, tmp_ramdisk);
  52. 		if (strcmp(permbones, levels))		/* if not identical */
  53. 			ramdisk = TRUE;
  54. 	} else
  55. #  endif /* AMIGA */
  56. 		Strcpy(levels, tmp_levels);
  57.  
  58. 	Strcpy(bones, levels);
  59. # endif /* MFLOPPY */
  60. #endif /* MICRO */
  61. 	return;
  62. }

fopen_wizkit_file

  1. #ifdef WIZARD
  2. STATIC_OVL FILE *
  3. fopen_wizkit_file()
  4. {
  5. 	FILE *fp;
  6. #if defined(VMS) || defined(UNIX)
  7. 	char	tmp_wizkit[BUFSZ];
  8. #endif
  9. 	char *envp;
  10.  
  11. 	envp = nh_getenv("WIZKIT");
  12. 	if (envp && *envp) (void) strncpy(wizkit, envp, WIZKIT_MAX - 1);
  13. 	if (!wizkit[0]) return (FILE *)0;
  14.  
  15. #ifdef UNIX
  16. 	if (access(wizkit, 4) == -1) {
  17. 		/* 4 is R_OK on newer systems */
  18. 		/* nasty sneaky attempt to read file through
  19. 		 * NetHack's setuid permissions -- this is a
  20. 		 * place a file name may be wholly under the player's
  21. 		 * control
  22. 		 */
  23. 		raw_printf("Access to %s denied (%d).",
  24. 				wizkit, errno);
  25. 		wait_synch();
  26. 		/* fall through to standard names */
  27. 	} else
  28. #endif
  29. 	if ((fp = fopenp(wizkit, "r")) != (FILE *)0) {
  30. 	    return(fp);
  31. #if defined(UNIX) || defined(VMS)
  32. 	} else {
  33. 	    /* access() above probably caught most problems for UNIX */
  34. 	    raw_printf("Couldn't open requested config file %s (%d).",
  35. 				wizkit, errno);
  36. 	    wait_synch();
  37. #endif
  38. 	}
  39.  
  40. #if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32)
  41. 	if ((fp = fopenp(fqname(wizkit, CONFIGPREFIX, 0), "r"))
  42. 								!= (FILE *)0)
  43. 		return(fp);
  44. #else
  45. # ifdef VMS
  46. 	envp = nh_getenv("HOME");
  47. 	if (envp)
  48. 		Sprintf(tmp_wizkit, "%s%s", envp, wizkit);
  49. 	else
  50. 		Sprintf(tmp_wizkit, "%s%s", "sys$login:", wizkit);
  51. 	if ((fp = fopenp(tmp_wizkit, "r")) != (FILE *)0)
  52. 		return(fp);
  53. # else	/* should be only UNIX left */
  54. 	envp = nh_getenv("HOME");
  55. 	if (envp)
  56. 		Sprintf(tmp_wizkit, "%s/%s", envp, wizkit);
  57. 	else 	Strcpy(tmp_wizkit, wizkit);
  58. 	if ((fp = fopenp(tmp_wizkit, "r")) != (FILE *)0)
  59. 		return(fp);
  60. 	else if (errno != ENOENT) {
  61. 		/* e.g., problems when setuid NetHack can't search home
  62. 		 * directory restricted to user */
  63. 		raw_printf("Couldn't open default wizkit file %s (%d).",
  64. 					tmp_wizkit, errno);
  65. 		wait_synch();
  66. 	}
  67. # endif
  68. #endif
  69. 	return (FILE *)0;
  70. }

read_wizkit

  1. void
  2. read_wizkit()
  3. {
  4. 	FILE *fp;
  5. 	char *ep, buf[BUFSZ];
  6. 	struct obj *otmp;
  7. 	boolean bad_items = FALSE, skip = FALSE;
  8.  
  9. 	if (!wizard || !(fp = fopen_wizkit_file())) return;
  10.  
  11. 	while (fgets(buf, (int)(sizeof buf), fp)) {
  12. 	    ep = index(buf, '\n');
  13. 	    if (skip) {	/* in case previous line was too long */
  14. 		if (ep) skip = FALSE; /* found newline; next line is normal */
  15. 	    } else {
  16. 		if (!ep) skip = TRUE; /* newline missing; discard next fgets */
  17. 		else *ep = '\0';		/* remove newline */
  18.  
  19. 		if (buf[0]) {
  20. 			otmp = readobjnam(buf, (struct obj *)0, FALSE);
  21. 			if (otmp) {
  22. 			    if (otmp != &zeroobj)
  23. 				otmp = addinv(otmp);
  24. 			} else {
  25. 			    /* .60 limits output line width to 79 chars */
  26. 			    raw_printf("Bad wizkit item: \"%.60s\"", buf);
  27. 			    bad_items = TRUE;
  28. 			}
  29. 		}
  30. 	    }
  31. 	}
  32. 	if (bad_items)
  33. 	    wait_synch();
  34. 	(void) fclose(fp);
  35. 	return;
  36. }
  37.  
  38. #endif /*WIZARD*/
  39.  
  40. /* ----------  END CONFIG FILE HANDLING ----------- */

Scoreboard creation

  1. /* ----------  BEGIN SCOREBOARD CREATION ----------- */

check_recordfile

  1. /* verify that we can write to the scoreboard file; if not, try to create one */
  2. void
  3. check_recordfile(dir)
  4. const char *dir;
  5. {
  6. #if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
  7. # pragma unused(dir)
  8. #endif
  9. 	const char *fq_record;
  10. 	int fd;
  11.  
  12. #if defined(UNIX) || defined(VMS)
  13. 	fq_record = fqname(RECORD, SCOREPREFIX, 0);
  14. 	fd = open(fq_record, O_RDWR, 0);
  15. 	if (fd >= 0) {
  16. # ifdef VMS	/* must be stream-lf to use UPDATE_RECORD_IN_PLACE */
  17. 		if (!file_is_stmlf(fd)) {
  18. 		    raw_printf(
  19. 		  "Warning: scoreboard file %s is not in stream_lf format",
  20. 				fq_record);
  21. 		    wait_synch();
  22. 		}
  23. # endif
  24. 	    (void) close(fd);	/* RECORD is accessible */
  25. 	} else if ((fd = open(fq_record, O_CREAT|O_RDWR, FCMASK)) >= 0) {
  26. 	    (void) close(fd);	/* RECORD newly created */
  27. # if defined(VMS) && !defined(SECURE)
  28. 	    /* Re-protect RECORD with world:read+write+execute+delete access. */
  29. 	    (void) chmod(fq_record, FCMASK | 007);
  30. # endif /* VMS && !SECURE */
  31. 	} else {
  32. 	    raw_printf("Warning: cannot write scoreboard file %s", fq_record);
  33. 	    wait_synch();
  34. 	}
  35. #endif  /* !UNIX && !VMS */
  36. #if defined(MICRO) || defined(WIN32)
  37. 	char tmp[PATHLEN];
  38.  
  39. # ifdef OS2_CODEVIEW   /* explicit path on opening for OS/2 */
  40. 	/* how does this work when there isn't an explicit path or fopenp
  41. 	 * for later access to the file via fopen_datafile? ? */
  42. 	(void) strncpy(tmp, dir, PATHLEN - 1);
  43. 	tmp[PATHLEN-1] = '\0';
  44. 	if ((strlen(tmp) + 1 + strlen(RECORD)) < (PATHLEN - 1)) {
  45. 		append_slash(tmp);
  46. 		Strcat(tmp, RECORD);
  47. 	}
  48. 	fq_record = tmp;
  49. # else
  50. 	Strcpy(tmp, RECORD);
  51. 	fq_record = fqname(RECORD, SCOREPREFIX, 0);
  52. # endif
  53.  
  54. 	if ((fd = open(fq_record, O_RDWR)) < 0) {
  55. 	    /* try to create empty record */
  56. # if defined(AZTEC_C) || defined(_DCC) || (defined(__GNUC__) && defined(__AMIGA__))
  57. 	    /* Aztec doesn't use the third argument */
  58. 	    /* DICE doesn't like it */
  59. 	    if ((fd = open(fq_record, O_CREAT|O_RDWR)) < 0) {
  60. # else
  61. 	    if ((fd = open(fq_record, O_CREAT|O_RDWR, S_IREAD|S_IWRITE)) < 0) {
  62. # endif
  63. 	raw_printf("Warning: cannot write record %s", tmp);
  64. 		wait_synch();
  65. 	    } else
  66. 		(void) close(fd);
  67. 	} else		/* open succeeded */
  68. 	    (void) close(fd);
  69. #else /* MICRO || WIN32*/
  70.  
  71. # ifdef MAC
  72. 	/* Create the "record" file, if necessary */
  73. 	fq_record = fqname(RECORD, SCOREPREFIX, 0);
  74. 	fd = macopen (fq_record, O_RDWR | O_CREAT, TEXT_TYPE);
  75. 	if (fd != -1) macclose (fd);
  76. # endif /* MAC */
  77.  
  78. #endif /* MICRO || WIN32*/
  79. }
  80.  
  81. /* ----------  END SCOREBOARD CREATION ----------- */

Panic/possible log

  1. /* ----------  BEGIN PANIC/IMPOSSIBLE LOG ----------- */

paniclog

  1. /*ARGSUSED*/
  2. void
  3. paniclog(type, reason)
  4. const char *type;	/* panic, impossible, trickery */
  5. const char *reason;	/* explanation */
  6. {
  7. #ifdef PANICLOG
  8. 	FILE *lfile;
  9. 	char buf[BUFSZ];
  10.  
  11. 	if (!program_state.in_paniclog) {
  12. 		program_state.in_paniclog = 1;
  13. 		lfile = fopen_datafile(PANICLOG, "a", TROUBLEPREFIX);
  14. 		if (lfile) {
  15. 		    (void) fprintf(lfile, "%s %08ld: %s %s\n",
  16. 				   version_string(buf), yyyymmdd((time_t)0L),
  17. 				   type, reason);
  18. 		    (void) fclose(lfile);
  19. 		}
  20. 		program_state.in_paniclog = 0;
  21. 	}
  22. #endif /* PANICLOG */
  23. 	return;
  24. }
  25.  
  26. /* ----------  END PANIC/IMPOSSIBLE LOG ----------- */

Internal recover

  1. #ifdef SELF_RECOVER
  2.  
  3. /* ----------  BEGIN INTERNAL RECOVER ----------- */

recover_savefile

  1. boolean
  2. recover_savefile()
  3. {
  4. 	int gfd, lfd, sfd;
  5. 	int lev, savelev, hpid;
  6. 	xchar levc;
  7. 	struct version_info version_data;
  8. 	int processed[256];
  9. 	char savename[SAVESIZE], errbuf[BUFSZ];
  10.  
  11. 	for (lev = 0; lev < 256; lev++)
  12. 		processed[lev] = 0;
  13.  
  14. 	/* level 0 file contains:
  15. 	 *	pid of creating process (ignored here)
  16. 	 *	level number for current level of save file
  17. 	 *	name of save file nethack would have created
  18. 	 *	and game state
  19. 	 */
  20. 	gfd = open_levelfile(0, errbuf);
  21. 	if (gfd < 0) {
  22. 	    raw_printf("%s\n", errbuf);
  23. 	    return FALSE;
  24. 	}
  25. 	if (read(gfd, (genericptr_t) &hpid, sizeof hpid) != sizeof hpid) {
  26. 	    raw_printf(
  27. "\nCheckpoint data incompletely written or subsequently clobbered. Recovery impossible.");
  28. 	    (void)close(gfd);
  29. 	    return FALSE;
  30. 	}
  31. 	if (read(gfd, (genericptr_t) &savelev, sizeof(savelev))
  32. 							!= sizeof(savelev)) {
  33. 	    raw_printf("\nCheckpointing was not in effect for %s -- recovery impossible.\n",
  34. 			lock);
  35. 	    (void)close(gfd);
  36. 	    return FALSE;
  37. 	}
  38. 	if ((read(gfd, (genericptr_t) savename, sizeof savename)
  39. 		!= sizeof savename) ||
  40. 	    (read(gfd, (genericptr_t) &version_data, sizeof version_data)
  41. 		!= sizeof version_data)) {
  42. 	    raw_printf("\nError reading %s -- can't recover.\n", lock);
  43. 	    (void)close(gfd);
  44. 	    return FALSE;
  45. 	}
  46.  
  47. 	/* save file should contain:
  48. 	 *	version info
  49. 	 *	current level (including pets)
  50. 	 *	(non-level-based) game state
  51. 	 *	other levels
  52. 	 */
  53. 	set_savefile_name();
  54. 	sfd = create_savefile();
  55. 	if (sfd < 0) {
  56. 	    raw_printf("\nCannot recover savefile %s.\n", SAVEF);
  57. 	    (void)close(gfd);
  58. 	    return FALSE;
  59. 	}
  60.  
  61. 	lfd = open_levelfile(savelev, errbuf);
  62. 	if (lfd < 0) {
  63. 	    raw_printf("\n%s\n", errbuf);
  64. 	    (void)close(gfd);
  65. 	    (void)close(sfd);
  66. 	    delete_savefile();
  67. 	    return FALSE;
  68. 	}
  69.  
  70. 	if (write(sfd, (genericptr_t) &version_data, sizeof version_data)
  71. 		!= sizeof version_data) {
  72. 	    raw_printf("\nError writing %s; recovery failed.", SAVEF);
  73. 	    (void)close(gfd);
  74. 	    (void)close(sfd);
  75. 	    delete_savefile();
  76. 	    return FALSE;
  77. 	}
  78.  
  79. 	if (!copy_bytes(lfd, sfd)) {
  80. 		(void) close(lfd);
  81. 		(void) close(sfd);
  82. 		delete_savefile();
  83. 		return FALSE;
  84. 	}
  85. 	(void)close(lfd);
  86. 	processed[savelev] = 1;
  87.  
  88. 	if (!copy_bytes(gfd, sfd)) {
  89. 		(void) close(lfd);
  90. 		(void) close(sfd);
  91. 		delete_savefile();
  92. 		return FALSE;
  93. 	}
  94. 	(void)close(gfd);
  95. 	processed[0] = 1;
  96.  
  97. 	for (lev = 1; lev < 256; lev++) {
  98. 		/* level numbers are kept in xchars in save.c, so the
  99. 		 * maximum level number (for the endlevel) must be < 256
  100. 		 */
  101. 		if (lev != savelev) {
  102. 			lfd = open_levelfile(lev, (char *)0);
  103. 			if (lfd >= 0) {
  104. 				/* any or all of these may not exist */
  105. 				levc = (xchar) lev;
  106. 				write(sfd, (genericptr_t) &levc, sizeof(levc));
  107. 				if (!copy_bytes(lfd, sfd)) {
  108. 					(void) close(lfd);
  109. 					(void) close(sfd);
  110. 					delete_savefile();
  111. 					return FALSE;
  112. 				}
  113. 				(void)close(lfd);
  114. 				processed[lev] = 1;
  115. 			}
  116. 		}
  117. 	}
  118. 	(void)close(sfd);
  119.  
  120. #ifdef HOLD_LOCKFILE_OPEN
  121. 	really_close();
  122. #endif
  123. 	/*
  124. 	 * We have a successful savefile!
  125. 	 * Only now do we erase the level files.
  126. 	 */
  127. 	for (lev = 0; lev < 256; lev++) {
  128. 		if (processed[lev]) {
  129. 			const char *fq_lock;
  130. 			set_levelfile_name(lock, lev);
  131. 			fq_lock = fqname(lock, LEVELPREFIX, 3);
  132. 			(void) unlink(fq_lock);
  133. 		}
  134. 	}
  135. 	return TRUE;
  136. }

copy_bytes

  1. boolean
  2. copy_bytes(ifd, ofd)
  3. int ifd, ofd;
  4. {
  5. 	char buf[BUFSIZ];
  6. 	int nfrom, nto;
  7.  
  8. 	do {
  9. 		nfrom = read(ifd, buf, BUFSIZ);
  10. 		nto = write(ofd, buf, nfrom);
  11. 		if (nto != nfrom) return FALSE;
  12. 	} while (nfrom == BUFSIZ);
  13. 	return TRUE;
  14. }
  15.  
  16. /* ----------  END INTERNAL RECOVER ----------- */
  17. #endif /*SELF_RECOVER*/
  18.  
  19. /*files.c*/