Source:NetHack 3.3.0/files.c

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

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)files.c	3.3	97/01/26	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6.    #include "dlb.h"  7. 8.   #include   9. 10.  #if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C) 11.  #include   12. #endif 13.  #if defined(UNIX) || defined(VMS) 14.  #include   15. # ifndef SKIP_ERRNO 16.  extern int errno; 17.  # endif 18.  #include   19. #endif 20.   21.   #if defined(MSDOS) || defined(OS2) || defined(TOS) || defined(WIN32) 22.  # ifndef GNUDOS 23.  #include   24. # else 25.  #include   26. # endif 27.  #endif 28.  #ifndef O_BINARY	/* used for micros, no-op for others */ 29.  # define O_BINARY 0 30.  #endif 31.   32.   #if !defined(MFLOPPY) && !defined(VMS) && !defined(WIN32) 33.  char bones[] = "bonesnn.xxx"; 34.  char lock[PL_NSIZ+14] = "1lock"; /* long enough for uid+name+.99 */ 35.  #else 36.  # if defined(MFLOPPY) 37.  char bones[FILENAME];		/* pathname of bones files */ 38.  char lock[FILENAME];		/* pathname of level files */ 39.  # endif 40.  # if defined(VMS) 41.  char bones[] = "bonesnn.xxx;1"; 42.  char lock[PL_NSIZ+17] = "1lock"; /* long enough for _uid+name+.99;1 */ 43.  # endif 44.  # if defined(WIN32) 45.  char bones[] = "bonesnn.xxx"; 46.  char lock[PL_NSIZ+25];		/* long enough for username+.+name+.99 */ 47.  # endif 48.  #endif 49.   50.   #if defined(UNIX) || defined(__BEOS__) 51.  #define SAVESIZE	(PL_NSIZ + 13)	/* save/99999player.e */ 52.  #else 53.  # ifdef VMS 54.  #define SAVESIZE	(PL_NSIZ + 22)	/* [.save] player.e;1 */ 55.  # else 56.  #  if defined(WIN32) 57.  #define SAVESIZE	(PL_NSIZ + 40)	/* username-player.NetHack-saved-game */ 58.  #  else 59.  #define SAVESIZE	FILENAME	/* from macconf.h or pcconf.h */ 60.  #  endif 61.  # endif 62.  #endif 63.   64.   char SAVEF[SAVESIZE];	/* holds relative path of save file from playground */ 65.  #ifdef MICRO 66.  char SAVEP[SAVESIZE];	/* holds path of directory for save file */ 67.  #endif 68.   69.   #ifdef AMIGA 70.  extern char PATH[];	/* see sys/amiga/amidos.c */ 71.  extern char bbs_id[]; 72.  static int lockptr; 73.  # ifdef __SASC_60 74.  #include   75. # endif 76.   77.   #include   78. #endif 79.   80.   #if defined(WIN32) || defined(MSDOS) 81.  static int lockptr; 82.  # ifdef MSDOS 83.  #define Delay(a) msleep(a) 84.  # endif 85.  #define Close close 86.  #define DeleteFile unlink 87.  #endif 88.   89.   extern int n_dgns;		/* from dungeon.c */ 90.   91.   STATIC_DCL char *FDECL(set_bonesfile_name, (char *,d_level*)); 92.  STATIC_DCL char *NDECL(set_bonestemp_name); 93.  STATIC_DCL char *FDECL(make_lockname, (const char *,char *)); 94.  STATIC_DCL FILE *FDECL(fopen_config_file, (const char *)); 95.  STATIC_DCL int FDECL(get_uchars, (FILE *,char *,char *,uchar *,int,const char *)); 96.  int FDECL(parse_config_line, (FILE *,char *,char *,char *)); 97.   98.   #ifdef WIN32 99.  extern void NDECL(dircheck); 100. #endif 101.  102.  /* fopen a file, with OS-dependent bells and whistles */ 103. /* NOTE: a simpler version of this routine also exists in util/dlb_main.c */ 104. FILE * 105. fopen_datafile(filename, mode) 106. const char *filename, *mode; 107. {  108.  	FILE *fp; 109. #ifdef WIN32 110. 	dircheck; 111. #endif 112. #ifdef AMIGA 113. 	fp = fopenp(filename, mode); 114. #else 115. # ifdef VMS	/* essential to have punctuation, to avoid logical names */ 116. 	char tmp[BUFSIZ]; 117.  118.  	if (!index(filename, '.') && !index(filename, ';')) 119. 		filename = strcat(strcpy(tmp, filename), ";0"); 120. 	fp = fopen(filename, mode, "mbc=16"); 121. # else 122. 	fp = fopen(filename, mode); 123. # endif 124. #endif 125. 	return fp; 126. }  127.   128.  /* --  BEGIN LEVEL FILE HANDLING --- */ 129.  130.  #ifdef MFLOPPY 131. /* Set names for bones[] and lock[] */ 132. void 133. set_lock_and_bones 134. {  135.  	if (!ramdisk) { 136. 		Strcpy(levels, permbones); 137. 		Strcpy(bones, permbones); 138. 	}  139.  	append_slash(permbones); 140. 	append_slash(levels); 141. #ifdef AMIGA 142. 	strncat(levels, bbs_id, PATHLEN); 143. #endif 144. 	append_slash(bones); 145. 	Strcat(bones, "bonesnn.*"); 146. 	Strcpy(lock, levels); 147. 	Strcat(lock, alllevels); 148. 	return; 149. }  150.  #endif /* MFLOPPY */ 151.  152.   153.  /* Construct a file name for a level-type file, which is of the form 154.  * something.level (with any old level stripped off). 155.  * This assumes there is space on the end of 'file' to append 156.  * a two digit number. This is true for 'level' 157.  * but be careful if you use it for other things -dgk 158.  */  159.  void 160. set_levelfile_name(file, lev) 161. char *file; 162. int lev; 163. {  164.  	char *tf; 165.  166.  	tf = rindex(file, '.'); 167. 	if (!tf) tf = eos(file); 168. 	Sprintf(tf, ".%d", lev); 169. #ifdef VMS 170. 	Strcat(tf, ";1"); 171. #endif 172. 	return; 173. }  174.   175.  int 176. create_levelfile(lev) 177. int lev; 178. {  179.  	int fd; 180.  181.  #ifdef WIN32 182. 	dircheck; 183. #endif 184. 	set_levelfile_name(lock, lev); 185.  186.  #if defined(MICRO) 187. 	/* Use O_TRUNC to force the file to be shortened if it already 188. 	 * exists and is currently longer. 189. 	 */  190.  	fd = open(lock, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK); 191. #else 192. # ifdef MAC 193. 	fd = maccreat(lock, LEVL_TYPE); 194. # else 195. 	fd = creat(lock, FCMASK); 196. # endif 197. #endif /* MICRO */ 198.  199.  	if (fd >= 0) 200. 	    level_info[lev].flags |= LFILE_EXISTS; 201.  202.  	return fd; 203. }  204.   205.   206.  int 207. open_levelfile(lev) 208. int lev; 209. {  210.  	int fd; 211.  212.  #ifdef WIN32 213. 	dircheck; 214. #endif 215. 	set_levelfile_name(lock, lev); 216. #ifdef MFLOPPY 217. 	/* If not currently accessible, swap it in. */ 218.  	if (level_info[lev].where != ACTIVE) 219. 		swapin_file(lev); 220. #endif 221. #ifdef MAC 222. 	fd = macopen(lock, O_RDONLY | O_BINARY, LEVL_TYPE); 223. #else 224. 	fd = open(lock, O_RDONLY | O_BINARY, 0); 225. #endif 226. 	return fd; 227. }  228.   229.   230.  void 231. delete_levelfile(lev) 232. int lev; 233. {  234.  #ifdef WIN32 235. 	dircheck; 236. #endif 237. 	/*  238.  	 * Level 0 might be created by port specific code that doesn't  239. * call create_levfile, so always assume that it exists. 240. 	 */  241.  	if (lev == 0 || (level_info[lev].flags & LFILE_EXISTS)) { 242. 		set_levelfile_name(lock, lev); 243. 		(void) unlink(lock); 244. 		level_info[lev].flags &= ~LFILE_EXISTS; 245. 	}  246.  }  247.   248.   249.  void 250. clearlocks 251. {  252.  #if defined(MFLOPPY) && !defined(AMIGA) 253. 	eraseall(levels, alllevels); 254. 	if (ramdisk) 255. 		eraseall(permbones, alllevels); 256. #else 257. 	register int x;  258. 259. # if defined(UNIX) || defined(VMS) 260. 	(void) signal(SIGHUP, SIG_IGN); 261. # endif 262. 	/* can't access maxledgerno before dungeons are created -dlc */ 263. 	for (x = (n_dgns ? maxledgerno : 0); x >= 0; x--) 264. 		delete_levelfile(x);	/* not all levels need be present */ 265. #endif 266. }  267.   268.  /* --  END LEVEL FILE HANDLING --- */ 269.  270.   271.  /* --  BEGIN BONES FILE HANDLING --- */ 272.  273.  /* set up "file" to be file name for retrieving bones, and return a  274. * bonesid to be read/written in the bones file. 275.  */  276.  STATIC_OVL char * 277. set_bonesfile_name(file, lev) 278. char *file; 279. d_level *lev; 280. {  281.  	s_level *sptr; 282. 	char *dptr; 283.  284.  	Sprintf(file, "bon%c%s", dungeons[lev->dnum].boneid,  285.  			In_quest(lev) ? urole.filecode : "0"); 286. 	dptr = eos(file); 287. 	if ((sptr = Is_special(lev)) != 0) 288. 	    Sprintf(dptr, ".%c", sptr->boneid); 289. 	else 290. 	    Sprintf(dptr, ".%d", lev->dlevel); 291. #ifdef VMS 292. 	Strcat(dptr, ";1"); 293. #endif 294. 	return(dptr-2); 295. }  296.   297.  /* set up temporary file name for writing bones, to avoid another game's  298. * trying to read from an uncompleted bones file. we want an uncontentious 299.  * name, so use one in the namespace reserved for this game's level files. 300.  * (we are not reading or writing level files while writing bones files, so  301.   * the same array may be used instead of copying.) 302.  */  303.  STATIC_OVL char * 304. set_bonestemp_name 305. {  306.  	char *tf; 307.  308.  	tf = rindex(lock, '.'); 309. 	if (!tf) tf = eos(lock); 310. 	Sprintf(tf, ".bn"); 311. #ifdef VMS 312. 	Strcat(tf, ";1"); 313. #endif 314. 	return lock; 315. }  316.   317.  int 318. create_bonesfile(lev, bonesid) 319. d_level *lev; 320. char **bonesid; 321. {  322.  	char *file; 323. 	int fd; 324.  325.  #ifdef WIN32 326. 	dircheck; 327. #endif 328. 	*bonesid = set_bonesfile_name(bones, lev); 329. 	file = set_bonestemp_name; 330.  331.  #ifdef MICRO 332. 	/* Use O_TRUNC to force the file to be shortened if it already 333. 	 * exists and is currently longer. 334. 	 */  335.  	fd = open(file, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK); 336. #else 337. # ifdef MAC 338. 	fd = maccreat(file, BONE_TYPE); 339. # else 340. 	fd = creat(file, FCMASK); 341. # endif 342. # if defined(VMS) && !defined(SECURE) 343. 	/*  344.  	   Re-protect bones file with world:read+write+execute+delete access. 345. 	   umask doesn't seem very reliable; also, vaxcrtl won't let us set 346. 	   delete access without write access, which is what's really wanted. 347. 	   Can't simply create it with the desired protection because creat 348. 	   ANDs the mask with the user's default protection, which usually 349. 	   denies some or all access to world. 350. 	 */  351.  	(void) chmod(file, FCMASK | 007);  /* allow other users full access */ 352. # endif /* VMS && !SECURE */ 353. #endif /* MICRO */ 354.  355.  	return fd; 356. }  357.   358.  #ifdef MFLOPPY 359. /* remove partial bonesfile in process of creation */ 360. void 361. cancel_bonesfile 362. {  363.  	char *tempname; 364.  365.  	tempname = set_bonestemp_name; 366. 	(void) unlink(tempname); 367. }  368.  #endif /* MFLOPPY */ 369.  370.  /* move completed bones file to proper name */ 371. void 372. commit_bonesfile(lev) 373. d_level *lev; 374. {  375.  	char *tempname; 376. 	int ret; 377.  378.  	(void) set_bonesfile_name(bones, lev); 379. 	tempname = set_bonestemp_name; 380.  381.  #if (defined(SYSV) && !defined(SVR4)) || defined(GENIX) 382. 	/* old SYSVs don't have rename. Some SVR3's may, but since they 383. 	 * also have link/unlink, it doesn't matter. :-) 384.  	 */  385.  	(void) unlink(bones);  386.  	ret = link(tempname, bones);  387.  	ret += unlink(tempname);  388.  #else  389.  	ret = rename(tempname, bones);  390.  #endif  391.  #ifdef WIZARD  392.  	if (wizard && ret != 0)  393.  		pline("couldn't rename %s to %s", tempname, bones);  394.  #endif  395.  }  396.   397.   398.  int  399.  open_bonesfile(lev, bonesid)  400.  d_level *lev;  401.  char **bonesid;  402.  {  403.  	int fd;  404.   405.  #ifdef WIN32  406.  	dircheck;  407.  #endif  408.  	*bonesid = set_bonesfile_name(bones, lev);  409.  	uncompress(bones);	/* no effect if nonexistent */  410.  #ifdef MAC  411.  	fd = macopen(bones, O_RDONLY | O_BINARY, BONE_TYPE);  412.  #else  413.  	fd = open(bones, O_RDONLY | O_BINARY, 0);  414.  #endif  415.  	return fd;  416.  }  417.   418.   419.  int  420.  delete_bonesfile(lev)  421.  d_level *lev;  422.  {  423.  #ifdef WIN32 424. 	dircheck; 425. #endif 426. 	(void) set_bonesfile_name(bones, lev); 427. 	return !(unlink(bones) < 0); 428. }  429.   430.   431.  /* assume we're compressing the recently read or created bonesfile, so the 432.  * file name is already set properly */ 433. void 434. compress_bonesfile 435. {  436.  	compress(bones); 437. }  438.   439.  /* --  END BONES FILE HANDLING --- */ 440.  441.   442.  /* --  BEGIN SAVE FILE HANDLING --- */ 443.  444.  /* set savefile name in OS-dependent manner from pre-existing plname, 445.  * avoiding troublesome characters */ 446. void 447. set_savefile_name 448. {  449.  #ifdef VMS 450. 	Sprintf(SAVEF, "[.save]%d%s", getuid, plname); 451. 	regularize(SAVEF+7); 452. 	Strcat(SAVEF, ";1"); 453. #else 454. # if defined(MICRO) && !defined(WIN32) 455. 	Strcpy(SAVEF, SAVEP); 456. #  ifdef AMIGA 457. 	strncat(SAVEF, bbs_id, PATHLEN); 458. #  endif 459. 	{  460.  		int i = strlen(SAVEP); 461. #  ifdef AMIGA 462. 		/* plname has to share space with SAVEP and ".sav" */ 463. 		(void)strncat(SAVEF, plname, FILENAME - i - 4); 464. #  else 465. 		(void)strncat(SAVEF, plname, 8); 466. #  endif 467. 		regularize(SAVEF+i); 468. 	}  469.  	Strcat(SAVEF, ".sav"); 470. # else 471. #  if defined(WIN32) 472. 	Sprintf(SAVEF,"%s-%s.NetHack-saved-game",get_username(0), plname); 473. #  else 474. 	Sprintf(SAVEF, "save/%d%s", (int)getuid, plname); 475. 	regularize(SAVEF+5);	/* avoid. or / in name */ 476. #  endif /* WIN32 */ 477. # endif	/* MICRO */ 478. #endif /* VMS   */ 479. }  480.   481.  #ifdef INSURANCE 482. void 483. save_savefile_name(fd) 484. int fd; 485. {  486.  	(void) write(fd, (genericptr_t) SAVEF, sizeof(SAVEF)); 487. }  488.  #endif 489.  490.   491.  #if defined(WIZARD) && !defined(MICRO) 492. /* change pre-existing savefile name to indicate an error savefile */ 493. void 494. set_error_savefile 495. {  496.  # ifdef VMS 497.       {  498.  	char *semi_colon = rindex(SAVEF, ';'); 499. 	if (semi_colon) *semi_colon = '\0'; 500.       }  501.  	Strcat(SAVEF, ".e;1"); 502. # else 503. #  ifdef MAC 504. 	Strcat(SAVEF, "-e"); 505. #  else 506. 	Strcat(SAVEF, ".e"); 507. #  endif 508. # endif 509. }  510.  #endif 511.  512.   513.  /* create save file, overwriting one if it already exists */ 514. int 515. create_savefile 516. {  517.  	int fd; 518. #ifdef WIN32 519. 	dircheck; 520. #endif 521. #ifdef AMIGA 522. 	fd = ami_wbench_getsave(O_WRONLY | O_CREAT | O_TRUNC); 523. #else 524. # ifdef MICRO 525. 	fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); 526. # else 527. #  ifdef MAC 528. 	fd = maccreat(SAVEF, SAVE_TYPE); 529. #  else 530. 	fd = creat(SAVEF, FCMASK); 531. #  endif 532. #  if defined(VMS) && !defined(SECURE) 533. 	/*  534.  	   Make sure the save file is owned by the current process. That's 535. the default for non-privileged users, but for priv'd users the 536. 	   file will be owned by the directory's owner instead of the user. 537. 	 */  538.  #   ifdef getuid	/*(see vmsunix.c)*/ 539. #    undef getuid 540. #   endif 541. 	(void) chown(SAVEF, getuid, getgid); 542. #  endif /* VMS && !SECURE */ 543. # endif	/* MICRO */ 544. #endif	/* AMIGA */ 545.  546.  	return fd; 547. }  548.   549.   550.  /* open savefile for reading */ 551. int 552. open_savefile 553. {  554.  	int fd; 555.  556.  #ifdef WIN32 557. 	dircheck; 558. #endif 559. #ifdef AMIGA 560. 	fd = ami_wbench_getsave(O_RDONLY); 561. #else 562. # ifdef MAC 563. 	fd = macopen(SAVEF, O_RDONLY | O_BINARY, SAVE_TYPE); 564. # else 565. 	fd = open(SAVEF, O_RDONLY | O_BINARY, 0); 566. # endif 567. #endif /* AMIGA */ 568. 	return fd; 569. }  570.   571.   572.  /* delete savefile */ 573. int 574. delete_savefile 575. {  576.  #ifdef AMIGA 577. 	ami_wbench_unlink(SAVEF); 578. #endif 579. 	(void) unlink(SAVEF); 580. 	return 0;	/* for restore_saved_game (ex-xxxmain.c) test */ 581. }  582.   583.   584.  /* try to open up a save file and prepare to restore it */ 585. int 586. restore_saved_game 587. {  588.  	int fd; 589. #ifdef WIN32 590. 	dircheck; 591. #endif 592.  593.  	set_savefile_name; 594. #ifdef MFLOPPY 595. 	if (  596.  # ifdef AMIGA  597.  	    !(FromWBench || saveDiskPrompt(1))  598.  # else  599.  	    !saveDiskPrompt(1)  600.  # endif  601.  	  ) return -1; 602. #endif /* MFLOPPY */ 603.  604.  	uncompress(SAVEF); 605. 	if ((fd = open_savefile) < 0) return fd; 606.  607.  	if (!uptodate(fd, SAVEF)) { 608. 	    (void) close(fd),  fd = -1; 609. 	    (void) delete_savefile; 610. 	}  611.  	return fd; 612. }  613.   614.  /* --  END SAVE FILE HANDLING --- */ 615.  616.   617.  /* --  BEGIN FILE COMPRESSION HANDLING --- */ 618.  619.  #ifdef COMPRESS 620.  621.  void 622. redirect(filename, mode, stream, uncomp) 623. char *filename, *mode; 624. FILE *stream; 625. boolean uncomp; 626. {  627.  #ifdef WIN32 628. 	dircheck; 629. #endif 630. 	if (freopen(filename, mode, stream) == (FILE *)0) { 631. 		(void) fprintf(stderr, "freopen of %s for %scompress failed\n",  632.  			filename, uncomp ? "un" : ""); 633. 		terminate(EXIT_FAILURE); 634. 	}  635.  }  636.   637.  /*  638.   * using system is simpler, but opens up security holes and causes 639.  * problems on at least Interactive UNIX 3.0.1 (SVR3.2), where any 640.  * setuid is renounced by /bin/sh, so the files cannot be accessed. 641.  *  642.   * cf. child in unixunix.c. 643. */ 644.  void 645. docompress_file(filename, uncomp) 646. char *filename; 647. boolean uncomp; 648. {  649.  	char cfn[80]; 650. 	FILE *cf; 651. 	const char *args[10]; 652. # ifdef COMPRESS_OPTIONS 653. 	char opts[80]; 654. # endif 655. 	int i = 0; 656. 	int f;  657. 658. #ifdef WIN32 659. 	dircheck; 660. #endif 661. 	Strcpy(cfn, filename); 662. # ifdef COMPRESS_EXTENSION 663. 	Strcat(cfn, COMPRESS_EXTENSION); 664. # endif 665. 	/* when compressing, we know the file exists */ 666. 	if (uncomp) { 667. 	    if ((cf = fopen(cfn, RDBMODE)) == (FILE *)0) 668. 		    return; 669. 	    (void) fclose(cf); 670. 	}  671.   672.  	args[0] = COMPRESS; 673. 	if (uncomp) args[++i] = "-d";	/* uncompress */ 674. # ifdef COMPRESS_OPTIONS 675. 	{  676.  	    /* we can't guarantee there's only one additional option, sigh */ 677. 	    char *opt; 678. 	    boolean inword = FALSE; 679.  680.  	    Strcpy(opts, COMPRESS_OPTIONS); 681. 	    opt = opts; 682. 	    while (*opt) { 683. 		if ((*opt == ' ') || (*opt == '\t')) { 684. 		    if (inword) { 685. 			*opt = '\0'; 686. 			inword = FALSE; 687. 		    }  688.  		} else if (!inword) { 689. 		    args[++i] = opt; 690. 		    inword = TRUE; 691. 		}  692.  		opt++; 693. 	    }  694.  	}  695.  # endif 696. 	args[++i] = (char *)0; 697.  698.  	f = fork; 699. 	if (f == 0) {	/* child */ 700. 		/* run compressor without privileges, in case other programs 701. 		 * have surprises along the line of gzip once taking filenames 702. 		 * in GZIP. 703. 		 */  704.  		/* assume all compressors will compress stdin to stdout 705. 		 * without explicit filenames. this is true of at least 706. 		 * compress and gzip, those mentioned in config.h.  707. */ 708.  		if (uncomp) { 709. 			redirect(cfn, RDBMODE, stdin, uncomp); 710. 			redirect(filename, WRBMODE, stdout, uncomp); 711. 		} else { 712. 			redirect(filename, RDBMODE, stdin, uncomp); 713. 			redirect(cfn, WRBMODE, stdout, uncomp); 714. 		}  715.  		(void) setgid(getgid); 716. 		(void) setuid(getuid); 717. 		(void) execv(args[0], (char *const *) args); 718. 		perror((char *)0); 719. 		(void) fprintf(stderr, "Exec to %scompress %s failed.\n",  720.  			uncomp ? "un" : "", filename); 721. 		terminate(EXIT_FAILURE); 722. 	} else if (f == -1) { 723. 		perror((char *)0); 724. 		pline("Fork to %scompress %s failed.",  725.  			uncomp ? "un" : "", filename); 726. 		return; 727. 	}  728.  	(void) signal(SIGINT, SIG_IGN); 729. 	(void) signal(SIGQUIT, SIG_IGN); 730. 	(void) wait((int *)&i); 731. 	(void) signal(SIGINT, (SIG_RET_TYPE) done1); 732. # ifdef WIZARD 733. 	if (wizard) (void) signal(SIGQUIT, SIG_DFL); 734. # endif 735. 	if (i == 0) { 736. 	    /* (un)compress succeeded: remove file left behind */ 737. 	    if (uncomp) 738. 		(void) unlink(cfn); 739. 	    else 740. 		(void) unlink(filename); 741. 	} else { 742. 	    /* (un)compress failed; remove the new, bad file */ 743. 	    if (uncomp) { 744. 		raw_printf("Unable to uncompress %s", filename); 745. 		(void) unlink(filename); 746. 	    } else { 747. 		/* no message needed for compress case; life will go on */ 748. 		(void) unlink(cfn); 749. 	    }  750.  	}  751.  }  752.  #endif	/* COMPRESS */ 753.  754.  /* compress file */ 755. void 756. compress(filename) 757. const char *filename; 758. #ifdef applec 759. # pragma unused(filename) 760. #endif 761. {  762.  #ifdef COMPRESS 763. 	docompress_file(filename, FALSE); 764. #endif 765. }  766.   767.   768.  /* uncompress file if it exists */ 769. void 770. uncompress(filename) 771. const char *filename; 772. #ifdef applec 773. # pragma unused(filename) 774. #endif 775. {  776.  #ifdef COMPRESS 777. 	docompress_file(filename, TRUE); 778. #endif 779. }  780.   781.  /* --  END FILE COMPRESSION HANDLING --- */ 782.  783.   784.  /* --  BEGIN FILE LOCKING HANDLING --- */ 785.  786.  static int nesting = 0; 787.  788.  #ifdef NO_FILE_LINKS	/* implies UNIX */ 789. static int lockfd;	/* for lock_file to pass to unlock_file */ 790. #endif 791.  792.  #define HUP	if (!program_state.done_hup) 793.  794.  STATIC_OVL char * 795. make_lockname(filename, lockname) 796. const char *filename; 797. char *lockname; 798. {  799.  #if defined(UNIX) || defined(VMS) || defined(AMIGA) || defined(WIN32) || defined(MSDOS) 800. # ifdef NO_FILE_LINKS 801. 	Strcpy(lockname, LOCKDIR); 802. 	Strcat(lockname, "/"); 803. 	Strcat(lockname, filename); 804. # else 805. 	Strcpy(lockname, filename); 806. # endif 807. # ifdef VMS 808.       {  809.  	char *semi_colon = rindex(lockname, ';'); 810. 	if (semi_colon) *semi_colon = '\0'; 811.       }  812.  	Strcat(lockname, ".lock;1"); 813. # else 814. 	Strcat(lockname, "_lock"); 815. # endif 816. 	return lockname; 817. #else 818. 	lockname[0] = '\0'; 819. 	return (char*)0; 820. #endif  /* UNIX || VMS || AMIGA || WIN32 || MSDOS */ 821. }  822.   823.   824.  /* lock a file */ 825. boolean 826. lock_file(filename, retryct) 827. const char *filename; 828. int retryct; 829. #ifdef applec 830. # pragma unused(filename, retryct) 831. #endif 832. {  833.  	char *lockname, locknambuf[BUFSZ]; 834.  835.  #ifdef WIN32 836. 	dircheck; 837. #endif 838. 	nesting++; 839. 	if (nesting > 1) { 840. 	    impossible("TRIED TO NEST LOCKS"); 841. 	    return TRUE; 842. 	}  843.   844.  	lockname = make_lockname(filename, locknambuf); 845.  846.  #if defined(UNIX) || defined(VMS) 847. # ifdef NO_FILE_LINKS 848. 	while ((lockfd = open(lockname, O_RDWR|O_CREAT|O_EXCL, 0666)) == -1) { 849. # else 850. 	while (link(filename, lockname) == -1) { 851. # endif 852. 	    register int errnosv = errno; 853.  854.  	    switch (errnosv) {	/* George Barbanis */ 855. 	    case EEXIST: 856. 		if (retryct--) { 857. 		    HUP raw_printf(  858.  			    "Waiting for access to %s.  (%d retries left).",  859.  			    filename, retryct); 860. # if defined(SYSV) || defined(ULTRIX) || defined(VMS) 861. 		    (void) 862. # endif 863. 			sleep(1); 864. 		} else { 865. 		    HUP (void) raw_print("I give up.  Sorry."); 866. 		    HUP raw_printf("Perhaps there is an old %s around?",  867.  					lockname); 868. 		    nesting--; 869. 		    return FALSE; 870. 		}  871.   872.  		break; 873. 	    case ENOENT: 874. 		HUP raw_printf("Can't find file %s to lock!", filename); 875. 		nesting--; 876. 		return FALSE; 877. 	    case EACCES: 878. 		HUP raw_printf("No write permission to lock %s!", filename); 879. 		nesting--; 880. 		return FALSE; 881. # ifdef VMS			/* c__translate(vmsfiles.c) */ 882. 	    case EPERM: 883. 		/* could be misleading, but usually right */ 884. 		HUP raw_printf("Can't lock %s due to directory protection.",  885.  			       filename); 886. 		nesting--; 887. 		return FALSE; 888. # endif 889. 	    default: 890. 		HUP perror(lockname); 891. 		HUP raw_printf(  892.  			     "Cannot lock %s for unknown reason (%d).",  893.  			       filename, errnosv); 894. 		nesting--; 895. 		return FALSE; 896. 	    }  897.   898.  	}  899.  #endif  /* UNIX || VMS */ 900.  901.  #if defined(AMIGA) || defined(WIN32) || defined(MSDOS) 902.     lockptr = 0; 903.     while (retryct-- && !lockptr) { 904. # ifdef AMIGA 905. 	(void)DeleteFile(lockname); /* in case dead process was here first */ 906. 	lockptr = Open(lockname,MODE_NEWFILE); 907. # else 908. 	lockptr = open(lockname, O_RDWR|O_CREAT|O_EXCL, S_IWRITE); 909. # endif 910. 	if (!lockptr) { 911. 	    raw_printf("Waiting for access to %s.  (%d retries left).",  912.  			filename, retryct); 913. 	    Delay(50); 914. 	}  915.      }  916.      if (!retryct) { 917. 	raw_printf("I give up.  Sorry."); 918. 	nesting--; 919. 	return FALSE; 920.     }  921.  #endif /* AMIGA || WIN32 || MSDOS */ 922. 	return TRUE; 923. }  924.   925.   926.  #ifdef VMS	/* for unlock_file, use the unlink routine in vmsunix.c */ 927. # ifdef unlink 928. #  undef unlink 929. # endif 930. # define unlink(foo) vms_unlink(foo) 931. #endif 932.  933.  /* unlock file, which must be currently locked by lock_file */ 934. void 935. unlock_file(filename) 936. const char *filename; 937. #if defined(applec) 938. # pragma unused(filename) 939. #endif 940. {  941.  	char *lockname, locknambuf[BUFSZ]; 942.  943.  	if (nesting == 1) { 944. 		lockname = make_lockname(filename, locknambuf); 945.  946.  #ifdef WIN32 947. 	dircheck; 948. #endif 949. #if defined(UNIX) || defined(VMS) 950. 		if (unlink(lockname) < 0) 951. 			HUP raw_printf("Can't unlink %s.", lockname); 952. # ifdef NO_FILE_LINKS 953. 		(void) close(lockfd); 954. # endif 955.  956.  #endif  /* UNIX || VMS */ 957.  958.  #if defined(AMIGA) || defined(WIN32) || defined(MSDOS) 959. 		if (lockptr) Close(lockptr); 960. 		DeleteFile(lockname); 961. 		lockptr = 0; 962. #endif /* AMIGA || WIN32 || MSDOS */ 963. 	}  964.   965.  	nesting--; 966. }  967.   968.  /* --  END FILE LOCKING HANDLING --- */ 969.  970.   971.  /* --  BEGIN CONFIG FILE HANDLING --- */ 972.  973.  const char *configfile = 974. #ifdef UNIX 975. 			".nethackrc"; 976. #else 977. # if defined(MAC) || defined(__BEOS__) 978. 			"NetHack Defaults"; 979. # else 980. #  if defined(MSDOS) || defined(WIN32) 981. 			"defaults.nh"; 982. #  else 983. 			"NetHack.cnf"; 984. #  endif 985. # endif 986. #endif 987.  988.   989.  #ifdef MSDOS 990. /* conflict with speed-dial under windows 991.  * for XXX.cnf file so support of NetHack.cnf 992.  * is for backward compatibility only. 993.  * Preferred name (and first tried) is now defaults.nh but 994.  * the game will try the old name if there 995.  * is no defaults.nh. 996.  */  997.  const char *backward_compat_configfile = "nethack.cnf"; 998. #endif 999.  1000. #ifndef MFLOPPY 1001. #define fopenp fopen 1002. #endif 1003. 1004. STATIC_OVL FILE * 1005. fopen_config_file(filename) 1006. const char *filename; 1007. { 1008. 	FILE *fp; 1009. #if defined(UNIX) || defined(VMS) 1010. 	char	tmp_config[BUFSZ]; 1011. #endif 1012. 1013. #ifdef WIN32 1014. 	dircheck; 1015. #endif 1016. 	/* "filename" is an environment variable, so it should hang around */ 1017. 	if (filename) { 1018. #ifdef UNIX 1019. 		if (access(filename, 4) == -1) { 1020. 			/* 4 is R_OK on newer systems */ 1021. 			/* nasty sneaky attempt to read file through 1022. 			 * NetHack's setuid permissions -- this is the only 1023. 			 * place a file name may be wholly under the player's 1024. * control 1025. 			 */ 1026. 			raw_printf("Access to %s denied (%d).",  1027. 					filename, errno); 1028. 			wait_synch; 1029. 			/* fall through to standard names */ 1030. 		} else 1031. #endif 1032. 		if ((fp = fopenp(filename, "r")) != (FILE *)0) { 1033. 			configfile = filename; 1034. 			return(fp); 1035. 		} 1036. 	}  1037.  1038. #if defined(MICRO) || defined(MAC) || defined(__BEOS__) 1039. 	if ((fp = fopenp(configfile, "r")) != (FILE *)0) 1040. 		return(fp); 1041. # ifdef MSDOS 1042. 	else if ((fp = fopenp(backward_compat_configfile, "r")) != (FILE *)0) 1043. 		return(fp); 1044. # endif 1045. #else 1046. # ifdef VMS 1047. 	if ((fp = fopenp("nethackini", "r")) != (FILE *)0) { 1048. 		configfile = "nethackini"; 1049. 		return(fp); 1050. 	} 1051. 	if ((fp = fopenp("sys$login:nethack.ini", "r")) != (FILE *)0) { 1052. 		configfile = "nethack.ini"; 1053. 		return(fp); 1054. 	} 1055. 	Sprintf(tmp_config, "%s%s", getenv("HOME"), "NetHack.cnf"); 1056. 	if ((fp = fopenp(tmp_config, "r")) != (FILE *)0) 1057. 		return(fp); 1058. # else	/* should be only UNIX left */ 1059. 	Sprintf(tmp_config, "%s/%s", getenv("HOME"), ".nethackrc"); 1060. 	if ((fp = fopenp(tmp_config, "r")) != (FILE *)0) 1061. 		return(fp); 1062. # endif 1063. #endif 1064. 	return (FILE *)0; 1065. 1066. }  1067.  1068.  1069. /*  1070.  * Retrieve a list of integers from a file into a uchar array. 1071. *  1072.  * NOTE:  This routine is unable to read a value of 0. 1073. */  1074. STATIC_OVL int 1075. get_uchars(fp, buf, bufp, list, size, name) 1076.    FILE *fp;		/* input file pointer */ 1077.    char *buf;		/* read buffer, must be of size BUFSZ */ 1078.    char *bufp;		/* current pointer */ 1079.    uchar *list;	/* return list */ 1080.    int  size;		/* return list size */ 1081.    const char *name;		/* name of option for error message */ 1082. { 1083.     unsigned int num = 0; 1084.    int count = 0; 1085. 1086.     while (1) { 1087. 	switch(*bufp) { 1088. 	   case ' ':  case '\0': 1089. 	   case '\t': case '\n': 1090. 		if (num) { 1091. 		   list[count++] =  num; 1092. 		   num = 0; 1093. 		} 1094. 		if (count == size || !*bufp) return count; 1095. 		bufp++; 1096. 		break; 1097. 1098. 	    case '0': case '1': case '2': case '3': 1099. 	   case '4': case '5': case '6': case '7': 1100. 	   case '8': case '9': 1101. 		num = num*10 + (*bufp-'0'); 1102. 		bufp++; 1103. 		break; 1104. 1105. 	    case '\\': 1106. 		if (fp == (FILE *)0) 1107. 		   goto gi_error; 1108. 		do { 1109. 		   if (!fgets(buf, BUFSZ, fp)) goto gi_error; 1110. 		} while (buf[0] == '#'); 1111. 		bufp = buf; 1112. 		break; 1113. 1114. 	    default: 1115. gi_error: 1116. 		raw_printf("Syntax error in %s", name); 1117. 		wait_synch; 1118. 		return count; 1119. 	} 1120.     }  1121.     /*NOTREACHED*/ 1122. } 1123.  1124. #define match_varname(INP,NAM,LEN) match_optname(INP, NAM, LEN, TRUE) 1125. 1126. /*ARGSUSED*/ 1127. int 1128. parse_config_line(fp, buf, tmp_ramdisk, tmp_levels) 1129. FILE		*fp; 1130. char		*buf; 1131. char		*tmp_ramdisk; 1132. char		*tmp_levels; 1133. #if defined(applec) 1134. # pragma unused(tmp_ramdisk,tmp_levels) 1135. #endif 1136. { 1137. 	char		*bufp, *altp; 1138. 	uchar  translate[MAXPCHARS]; 1139. 	int  len; 1140. 1141. 	if (*buf == '#') 1142. 		return 1; 1143. 1144. 	/* remove trailing whitespace */ 1145. 	bufp = eos(buf); 1146. 	while (--bufp > buf && isspace(*bufp)) 1147. 		continue; 1148. 1149. 	if (bufp <= buf) 1150. 		return 1;		/* skip all-blank lines */ 1151. 	else 1152. 		*(bufp + 1) = '\0';	/* terminate line */ 1153. 1154. 	/* find the '=' or ':' */ 1155. 	bufp = index(buf, '='); 1156. 	altp = index(buf, ':'); 1157. 	if (!bufp || (altp && altp < bufp)) bufp = altp; 1158. 	if (!bufp) return 0; 1159. 1160. 	/* skip  whitespace between '=' and value */ 1161. 	do { ++bufp; } while (isspace(*bufp)); 1162. 1163. 	/* Go through possible variables */ 1164. 	if (match_varname(buf, "OPTIONS", 4)) { 1165. 		parseoptions(bufp, TRUE, TRUE); 1166. 		if (plname[0])		/* If a name was given */ 1167. 			plnamesuffix;	/* set the character class */ 1168. #ifdef MICRO 1169. 	} else if (match_varname(buf, "HACKDIR", 4)) { 1170. 		(void) strncpy(hackdir, bufp, PATHLEN); 1171. # ifdef MFLOPPY 1172. 	} else if (match_varname(buf, "RAMDISK", 3)) { 1173. 				/* The following ifdef is NOT in the wrong 1174. 				 * place. For now, we accept and silently 1175. 				 * ignore RAMDISK */ 1176. # ifndef AMIGA 1177. 		(void) strncpy(tmp_ramdisk, bufp, PATHLEN); 1178. # endif 1179. # endif 1180. 	} else if (match_varname(buf, "LEVELS", 4)) { 1181. 		(void) strncpy(tmp_levels, bufp, PATHLEN); 1182. 1183. 	} else if (match_varname(buf, "SAVE", 4)) { 1184. # ifdef MFLOPPY 1185. 		extern	int saveprompt; 1186. #endif 1187. 		char *ptr; 1188. 		if ((ptr = index(bufp, ';')) != 0) { 1189. 			*ptr = '\0'; 1190. # ifdef MFLOPPY 1191. 			if (*(ptr+1) == 'n' || *(ptr+1) == 'N') { 1192. 				saveprompt = FALSE; 1193. 			} 1194. # endif 1195. 		} 1196. #ifdef	MFLOPPY 1197. 		else 1198. 		   saveprompt = flags.asksavedisk; 1199. #endif 1200. 1201. 		(void) strncpy(SAVEP, bufp, PATHLEN); 1202. 		append_slash(SAVEP); 1203. #endif /* MICRO */ 1204. 1205. 	} else if (match_varname(buf, "NAME", 4)) { 1206. 	   (void) strncpy(plname, bufp, PL_NSIZ-1); 1207. 	   plnamesuffix; 1208. 	} else if (match_varname(buf, "ROLE", 4) || 1209. 		   match_varname(buf, "CHARACTER", 4)) { 1210. 	   if ((len = str2role(bufp)) >= 0) 1211. 	   	flags.initrole = len; 1212. 	} else if (match_varname(buf, "DOGNAME", 3)) { 1213. 	   (void) strncpy(dogname, bufp, PL_PSIZ-1); 1214. 	} else if (match_varname(buf, "CATNAME", 3)) { 1215. 	   (void) strncpy(catname, bufp, PL_PSIZ-1); 1216. 1217. 	} else if (match_varname(buf, "GRAPHICS", 4)) { 1218. 	   len = get_uchars(fp, buf, bufp, translate, MAXPCHARS, "GRAPHICS"); 1219. 	   assign_graphics(translate, len, MAXPCHARS, 0); 1220. 	} else if (match_varname(buf, "DUNGEON", 4)) { 1221. 	   len = get_uchars(fp, buf, bufp, translate, MAXDCHARS, "DUNGEON"); 1222. 	   assign_graphics(translate, len, MAXDCHARS, 0); 1223. 	} else if (match_varname(buf, "TRAPS", 4)) { 1224. 	   len = get_uchars(fp, buf, bufp, translate, MAXTCHARS, "TRAPS"); 1225. 	   assign_graphics(translate, len, MAXTCHARS, MAXDCHARS); 1226. 	} else if (match_varname(buf, "EFFECTS", 4)) { 1227. 	   len = get_uchars(fp, buf, bufp, translate, MAXECHARS, "EFFECTS"); 1228. 	   assign_graphics(translate, len, MAXECHARS, MAXDCHARS+MAXTCHARS); 1229. 1230. 	} else if (match_varname(buf, "OBJECTS", 3)) { 1231. 	   /* oc_syms[0] is the RANDOM object, unused */ 1232. 	   (void) get_uchars(fp, buf, bufp, &(oc_syms[1]),  1233. 					MAXOCLASSES-1, "OBJECTS"); 1234. 	} else if (match_varname(buf, "MONSTERS", 3)) { 1235. 	   /* monsyms[0] is unused */ 1236. 	   (void) get_uchars(fp, buf, bufp, &(monsyms[1]),  1237. 					MAXMCLASSES-1, "MONSTERS"); 1238. #ifdef AMIGA 1239. 	} else if (match_varname(buf, "FONT", 4)) { 1240. 		char *t; 1241. 		extern void amii_set_text_font( char *, int ); 1242. 1243. 		if( t = strchr( buf+5, ':' ) ) 1244. 		{ 1245. 		    *t = 0; 1246. 		   amii_set_text_font( buf+5, atoi( t + 1 ) ); 1247. 		   *t = ':'; 1248. 		} 1249. 	} else if (match_varname(buf, "PATH", 4)) { 1250. 		(void) strncpy(PATH, bufp, PATHLEN); 1251. #endif 1252. #ifdef AMIGA 1253. 	} else if (match_varname(buf, "DEPTH", 5)) { 1254. 		extern int amii_numcolors; 1255. 		int val = atoi( bufp ); 1256. 		amii_numcolors = 1L << min( DEPTH, val ); 1257. 	} else if (match_varname(buf, "DRIPENS", 7)) { 1258. 		int i, val; 1259. 		char *t; 1260. 		for (i = 0, t = strtok(bufp, ",/"); t != (char *)0; 1261. 				i < 20 && (t = strtok((char*)0, ",/")), ++i) { 1262. 			sscanf(t, "%d", &val ); 1263. 			flags.amii_dripens[i] = val; 1264. 		} 1265. 	} else if (match_varname(buf, "SCREENMODE", 10 )) { 1266. 		extern long amii_scrnmode; 1267. 		if( sscanf(bufp, "%x", &amii_scrnmode) != 1 ) 1268. 			amii_scrnmode = 0; 1269. 	} else if (match_varname(buf, "MSGPENS", 7)) { 1270. 		extern int amii_msgAPen, amii_msgBPen; 1271. 		char *t = strtok(bufp, ",/"); 1272. 		if( t ) 1273. 		{ 1274. 		    sscanf(t, "%d", &amii_msgAPen); 1275. 		   if( t = strtok((char*)0, ",/") ) 1276. 				sscanf(t, "%d", &amii_msgBPen); 1277. 		} 1278. 	} else if (match_varname(buf, "TEXTPENS", 8)) { 1279. 		extern int amii_textAPen, amii_textBPen; 1280. 		char *t = strtok(bufp, ",/"); 1281. 		if( t ) 1282. 		{ 1283. 		    sscanf(t, "%d", &amii_textAPen); 1284. 		   if( t = strtok((char*)0, ",/") ) 1285. 				sscanf(t, "%d", &amii_textBPen); 1286. 		} 1287. 	} else if (match_varname(buf, "MENUPENS", 8)) { 1288. 		extern int amii_menuAPen, amii_menuBPen; 1289. 		char *t = strtok(bufp, ",/"); 1290. 		if( t ) 1291. 		{ 1292. 		    sscanf(t, "%d", &amii_menuAPen); 1293. 		   if( t = strtok((char*)0, ",/") ) 1294. 				sscanf(t, "%d", &amii_menuBPen); 1295. 		} 1296. 	} else if (match_varname(buf, "STATUSPENS", 10)) { 1297. 		extern int amii_statAPen, amii_statBPen; 1298. 		char *t = strtok(bufp, ",/"); 1299. 		if( t ) 1300. 		{ 1301. 		    sscanf(t, "%d", &amii_statAPen); 1302. 		   if( t = strtok((char*)0, ",/") ) 1303. 				sscanf(t, "%d", &amii_statBPen); 1304. 		} 1305. 	} else if (match_varname(buf, "OTHERPENS", 9)) { 1306. 		extern int amii_otherAPen, amii_otherBPen; 1307. 		char *t = strtok(bufp, ",/"); 1308. 		if( t ) 1309. 		{ 1310. 		    sscanf(t, "%d", &amii_otherAPen); 1311. 		   if( t = strtok((char*)0, ",/") ) 1312. 				sscanf(t, "%d", &amii_otherBPen); 1313. 		} 1314. 	} else if (match_varname(buf, "PENS", 4)) { 1315. 		int i; 1316. char *t; 1317. 1318. 		for (i = 0, t = strtok(bufp, ",/"); t != (char *)0;  1319. 				    t = strtok((char *)0, ",/"), ++i) 1320. 		{ 1321. 			sscanf(t, "%hx", &flags.amii_curmap[i]); 1322. 		} 1323. 		amii_setpens( amii_numcolors = i ); 1324. #endif 1325. #ifdef QT_GRAPHICS 1326. 	} else if (match_varname(buf, "QT_TILEWIDTH", 12)) { 1327. 		extern char *qt_tilewidth; 1328. 		if (qt_tilewidth == NULL) 1329. 			qt_tilewidth=(char *)strdup(bufp); 1330. 	} else if (match_varname(buf, "QT_TILEHEIGHT", 13)) { 1331. 		extern char *qt_tileheight; 1332. 		if (qt_tileheight == NULL) 1333. 			qt_tileheight=(char *)strdup(bufp); 1334. 	} else if (match_varname(buf, "QT_FONTSIZE", 11)) { 1335. 		extern char *qt_fontsize; 1336. 		if (qt_fontsize == NULL) 1337. 			qt_fontsize=(char *)strdup(bufp); 1338. #endif 1339. 	} else 1340. 		return 0; 1341. 	return 1; 1342. } 1343.  1344. void 1345. read_config_file(filename) 1346. const char *filename; 1347. { 1348. #define tmp_levels	(char *)0 1349. #define tmp_ramdisk	(char *)0 1350. 1351. #ifdef MICRO 1352. #undef tmp_levels 1353. 	char	tmp_levels[PATHLEN]; 1354. # ifdef MFLOPPY 1355. # ifndef AMIGA 1356. #undef tmp_ramdisk 1357. 	char	tmp_ramdisk[PATHLEN]; 1358. # endif 1359. # endif 1360. #endif 1361. 	char	buf[4*BUFSZ]; 1362. 	FILE	*fp; 1363. #ifdef WIN32 1364. 	dircheck; 1365. #endif 1366. 1367. 	if (!(fp = fopen_config_file(filename))) return; 1368. 1369. #ifdef MICRO 1370. # ifdef MFLOPPY 1371. # ifndef AMIGA 1372. 	tmp_ramdisk[0] = 0; 1373. # endif 1374. # endif 1375. 	tmp_levels[0] = 0; 1376. #endif 1377. 1378. 	while (fgets(buf, 4*BUFSZ, fp)) { 1379. 		if (!parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)) { 1380. 			raw_printf("Bad option line: \"%s\"", buf); 1381. 			wait_synch; 1382. 		} 1383. 	}  1384. 	(void) fclose(fp); 1385. 1386. #ifdef MICRO 1387. # ifdef MFLOPPY 1388. 	Strcpy(permbones, tmp_levels); 1389. # ifndef AMIGA 1390. 	if (tmp_ramdisk[0]) { 1391. 		Strcpy(levels, tmp_ramdisk); 1392. 		if (strcmp(permbones, levels))		/* if not identical */ 1393. 			ramdisk = TRUE; 1394. 	} else 1395. # endif /* AMIGA */ 1396. 		Strcpy(levels, tmp_levels); 1397. 1398. 	Strcpy(bones, levels); 1399. # endif /* MFLOPPY */ 1400. #endif /* MICRO */ 1401. 	return; 1402. } 1403.  1404. /* --  END CONFIG FILE HANDLING --- */ 1405. 1406. /* --  BEGIN SCOREBOARD CREATION --- */ 1407. 1408. /* verify that we can write to the scoreboard file; if not, try to create one */ 1409. void 1410. check_recordfile(dir) 1411. const char *dir; 1412. #if defined(applec) 1413. # pragma unused(dir) 1414. #endif 1415. { 1416. #if defined(UNIX) || defined(VMS) 1417. 	int fd = open(RECORD, O_RDWR, 0); 1418. 1419. 	if (fd >= 0) { 1420. # ifdef VMS	/* must be stream-lf to use UPDATE_RECORD_IN_PLACE */ 1421. 		if (!file_is_stmlf(fd)) { 1422. 		   raw_printf(	/* note: assume VMS dir has trailing punct */  1423. 		  "Warning: scoreboard file %s%s is not in stream_lf format",  1424. 				(dir ? dir : "[]"), RECORD); 1425. 		   wait_synch; 1426. 		} 1427. # endif 1428. 	   (void) close(fd);	/* RECORD is accessible */ 1429. 	} else if ((fd = open(RECORD, O_CREAT|O_RDWR, FCMASK)) >= 0) { 1430. 	   (void) close(fd);	/* RECORD newly created */ 1431. # if defined(VMS) && !defined(SECURE) 1432. 	   /* Re-protect RECORD with world:read+write+execute+delete access. */ 1433. 	    (void) chmod(RECORD, FCMASK | 007); /* allow everyone full access */ 1434. # endif /* VMS && !SECURE */ 1435. 	} else { 1436. 	   raw_printf("Warning: cannot write scoreboard file %s/%s",  1437. 			(dir ? dir : "."), RECORD); 1438. 	   wait_synch; 1439. 	} 1440. #endif  /* !UNIX && !VMS */ 1441. #ifdef MICRO 1442. 	int fd; 1443. 	char tmp[PATHLEN]; 1444. # ifdef WIN32 1445. 	dircheck; 1446. # endif 1447. 1448. # ifdef OS2_CODEVIEW   /* explicit path on opening for OS/2 */ 1449. 	Strcpy(tmp, dir); 1450. 	append_slash(tmp); 1451. 	Strcat(tmp, RECORD); 1452. # else 1453. 	Strcpy(tmp, RECORD); 1454. # endif 1455. 1456. 	if ((fd = open(tmp, O_RDWR)) < 0) { 1457. 	   /* try to create empty record */ 1458. # if defined(AZTEC_C) || defined(_DCC) 1459. 	   /* Aztec doesn't use the third argument */ 1460. 	   /* DICE doesn't like it */ 1461. 	   if ((fd = open(tmp, O_CREAT|O_RDWR)) < 0) { 1462. # else 1463. 	   if ((fd = open(tmp, O_CREAT|O_RDWR, S_IREAD|S_IWRITE)) < 0) { 1464. # endif 1465. 	raw_printf("Warning: cannot write record %s", tmp); 1466. 		wait_synch; 1467. 	   } else 1468. 		(void) close(fd); 1469. 	} else		/* open succeeded */ 1470. 	   (void) close(fd); 1471. #else /* MICRO */ 1472. 1473. # ifdef MAC 1474. 	int fd = macopen ( RECORD, O_RDWR | O_CREAT , TEXT_TYPE ) ; 1475. 1476. 	if ( fd < 0 ) { 1477. 		raw_printf ( "Warning: cannot write %s", RECORD ) ; 1478. 	} else { 1479. 		close ( fd ) ; 1480. 	} 1481. # endif /* MAC */ 1482. 1483. #endif /* MICRO */ 1484. } 1485.  1486. /* --  END SCOREBOARD CREATION --- */ 1487. 1488. /*files.c*/