Source:NetHack 3.1.0/files.c

Below is the full text to files.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/12/07	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   #include   8. 9.   #if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C) 10.  #include   11. #endif 12.  #if defined(UNIX) || defined(VMS) 13.  #include   14. # ifndef SKIP_ERRNO 15.  extern int errno; 16.  # endif 17.  #include   18. #endif 19.   20.   #if defined(MSDOS) || defined(OS2) || defined(TOS) 21.  # ifndef GNUDOS 22.  #include   23. # else 24.  #include   25. # endif 26.  #endif 27.  #ifndef O_BINARY	/* used for micros, no-op for others */ 28.  # define O_BINARY 0 29.  #endif 30.   31.   #ifdef MFLOPPY 32.  char bones[FILENAME];		/* pathname of bones files */ 33.  char lock[FILENAME];		/* pathname of level files */ 34.  #else 35.  static char bones[] = "bonesnn.xxxx"; 36.  # ifdef VMS 37.  char lock[PL_NSIZ+17] = "1lock"; /* long enough for _uid+name+.99;1 */ 38.  # else 39.  char lock[PL_NSIZ+14] = "1lock"; /* long enough for uid+name+.99 */ 40.  # endif 41.  #endif 42.   43.   #ifdef MAC 44.  #include   45. MacDirs theDirs ; 46.  #endif 47.   48.   #ifdef UNIX 49.  #define SAVESIZE	(PL_NSIZ + 13)	/* save/99999player.e */ 50.  #else 51.  # ifdef VMS 52.  #define SAVESIZE	(PL_NSIZ + 22)	/* [.save] player.e;1 */ 53.  # else 54.  #define SAVESIZE	FILENAME	/* from macconf.h or pcconf.h */ 55.  # endif 56.  #endif 57.   58.   char SAVEF[SAVESIZE];	/* holds relative path of save file from playground */ 59.  #ifdef MICRO 60.  char SAVEP[SAVESIZE];	/* holds path of directory for save file */ 61.  #endif 62.  #ifdef AMIGA 63.  extern char PATH[];	/* see sys/amiga/amidos.c */ 64.  #endif 65.   66.   static char * FDECL(set_bonesfile_name, (char *,d_level*)); 67.   68.   /* fopen a file, with OS-dependent bells and whistles */ 69.  FILE * 70.  fopen_datafile(filename, mode) 71.  const char *filename, *mode; 72.  {  73.   	FILE *fp; 74.  #ifdef AMIGA 75.  	fp = fopenp(filename, mode); 76.  #else 77.  # ifdef VMS	/* essential to have punctuation, to avoid logical names */ 78.  	char tmp[BUFSIZ]; 79.   80.   	if (!index(filename, '.') && !index(filename, ';')) 81.  		filename = strcat(strcpy(tmp, filename), ";0"); 82.  	fp = fopen(filename, mode, "mbc=16"); 83.  # else 84.  	fp = fopen(filename, mode); 85.  # endif 86.  #endif 87.  	return fp; 88.  }  89.    90.    91.   /* --  BEGIN LEVEL FILE HANDLING --- */ 92.   93.   #ifdef MFLOPPY 94.  /* Set names for bones[] and lock[] */ 95.  void 96.  set_lock_and_bones 97.  {  98.   	if (!ramdisk) { 99.  		Strcpy(levels, permbones); 100. 		Strcpy(bones, permbones); 101. 	}  102.  	append_slash(permbones); 103. 	append_slash(levels); 104. 	append_slash(bones); 105. 	Strcat(bones, "bonesnn.*"); 106. 	Strcpy(lock, levels); 107. 	Strcat(lock, alllevels); 108. 	return; 109. }  110.  #endif /* MFLOPPY */ 111.  112.   113.  /* Construct a file name for a level-type file, which is of the form 114.  * something.level (with any old level stripped off). 115.  * This assumes there is space on the end of 'file' to append 116.  * a two digit number. This is true for 'level' 117.  * but be careful if you use it for other things -dgk 118.  */  119.  void 120. set_levelfile_name(file, lev) 121. char *file; 122. int lev; 123. {  124.  	char *tf; 125.  126.  	tf = rindex(file, '.'); 127. 	if (!tf) tf = eos(file); 128. 	Sprintf(tf, ".%d", lev); 129. #ifdef VMS 130. 	Strcat(tf, ";1"); 131. #endif 132. 	return; 133. }  134.   135.  int 136. create_levelfile(lev) 137. int lev; 138. {  139.  	int fd; 140.  141.  	set_levelfile_name(lock, lev); 142.  143.  #if defined(MICRO) 144. 	/* Use O_TRUNC to force the file to be shortened if it already 145. 	 * exists and is currently longer. 146. 	 */  147.  	fd = open(lock, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK); 148. #else 149. #ifdef MAC 150. 	fd = maccreat ( lock, LEVL_TYPE ) ; 151. #else /* MAC */ 152. 	fd = creat(lock, FCMASK); 153. #endif /* MAC */ 154. #endif /* MICRO */ 155.  156.  	return fd; 157. }  158.   159.   160.  int 161. open_levelfile(lev) 162. int lev; 163. {  164.  	int fd; 165.  166.  	set_levelfile_name(lock, lev); 167. #ifdef MFLOPPY 168. 	/* If not currently accessible, swap it in. */ 169.  	if (fileinfo[lev].where != ACTIVE) 170. 		swapin_file(lev); 171. #endif 172. # ifdef MAC 173. 	fd = macopen ( lock, O_RDONLY | O_BINARY , LEVL_TYPE ) ; 174. # else /* MAC */ 175. 	fd = open(lock, O_RDONLY | O_BINARY, 0); 176. # endif /* MAC */ 177. 	return fd; 178. }  179.   180.   181.  void 182. delete_levelfile(lev) 183. int lev; 184. {  185.  	set_levelfile_name(lock, lev); 186. 	(void) unlink(lock); 187. }  188.   189.   190.  void 191. clearlocks 192. {  193.  #ifdef MFLOPPY 194. 	eraseall(levels, alllevels); 195. # ifndef AMIGA 196. 	if (ramdisk) 197. 		eraseall(permbones, alllevels); 198. # endif 199. #else 200. 	register int x;  201. 202. # if defined(UNIX) || defined(VMS) 203. 	(void) signal(SIGHUP, SIG_IGN); 204. # endif 205. 	for (x = maxledgerno; x >= 0; x--) 206. 		delete_levelfile(x);	/* not all levels need be present */ 207. #endif 208. }  209.   210.  /* --  END LEVEL FILE HANDLING --- */ 211.  212.   213.  /* --  BEGIN BONES FILE HANDLING --- */ 214.  215.  static char * 216. set_bonesfile_name(file, lev) 217. char *file; 218. d_level *lev; 219. {  220.  	char *dptr = rindex(file, '.'); 221. 	s_level *sptr; 222.  223.  	if (!dptr) dptr = eos(file); 224. 	*(dptr-2) = dungeons[lev->dnum].boneid; 225. #ifdef MULDGN 226. 	*(dptr-1) = In_quest(lev) ? pl_character[0] : '0'; 227. #else 228. 	*(dptr-1) = '0'; 229. #endif 230. 	if ((sptr = Is_special(lev)) != 0) 231. 	    Sprintf(dptr, ".%c", sptr->boneid); 232. 	else 233. 	    Sprintf(dptr, ".%d", lev->dlevel); 234. #ifdef VMS 235. 	Strcat(dptr, ";1"); 236. #endif 237. 	return(dptr-2); 238. }  239.   240.  int 241. create_bonesfile(lev, bonesid) 242. d_level *lev; 243. char **bonesid; 244. {  245.  	int fd; 246.  247.  	*bonesid = set_bonesfile_name(bones, lev); 248.  249.  #ifdef MICRO 250. 	/* Use O_TRUNC to force the file to be shortened if it already 251. 	 * exists and is currently longer. 252. 	 */  253.  	fd = open(bones, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK); 254. #else 255. # ifdef MAC 256. 	fd = maccreat ( bones, BONE_TYPE ) ; 257. # else /* MAC */ 258. 	fd = creat(bones, FCMASK); 259. # endif /* MAC */ 260. #  if defined(VMS) && !defined(SECURE) 261. 	/*  262.  	   Re-protect bones file with world:read+write+execute+delete access. 263. 	   umask doesn't seem very reliable; also, vaxcrtl won't let us set 264. 	   delete access without write access, which is what's really wanted. 265. 	   Can't simply create it with the desired protection because creat 266. 	   ANDs the mask with the user's default protection, which usually 267. 	   denies some or all access to world. 268. 	 */  269.  	(void) chmod(bones, FCMASK | 007);  /* allow other users full access */ 270. #  endif /* VMS && !SECURE */ 271. #endif /* MICRO */ 272.  273.  	return fd; 274. }  275.   276.   277.  int 278. open_bonesfile(lev, bonesid) 279. d_level *lev; 280. char **bonesid; 281. {  282.  	int fd; 283.  284.  	*bonesid = set_bonesfile_name(bones, lev); 285. 	uncompress(bones);	/* no effect if nonexistent */ 286. #ifdef MAC 287. 	fd = macopen ( bones, O_RDONLY | O_BINARY , BONE_TYPE ) ; 288. #else 289. 	fd = open(bones, O_RDONLY | O_BINARY, 0); 290. #endif 291. 	return fd; 292. }  293.   294.   295.  int 296. delete_bonesfile(lev) 297. d_level *lev; 298. {  299.  	(void) set_bonesfile_name(bones, lev); 300. 	return !(unlink(bones) < 0); 301. }  302.   303.   304.  /* assume we're compressing the recently read or created bonesfile, so the 305.  * file name is already set properly */ 306. void 307. compress_bonesfile 308. {  309.  	compress(bones); 310. }  311.   312.  /* --  END BONES FILE HANDLING --- */ 313.  314.   315.  /* --  BEGIN SAVE FILE HANDLING --- */ 316.  317.  /* set savefile name in OS-dependent manner from pre-existing plname, 318.  * avoiding troublesome characters */ 319. void 320. set_savefile_name 321. {  322.  #ifdef VMS 323. 	Sprintf(SAVEF, "[.save]%d%s", getuid, plname); 324. 	regularize(SAVEF+7); 325. 	Strcat(SAVEF, ";1"); 326. #else 327. # ifdef MICRO 328. 	Strcpy(SAVEF, SAVEP); 329. 	{  330.  		int i = strlen(SAVEP); 331. #  ifdef AMIGA 332. 		/* plname has to share space with SAVEP and ".sav" */ 333. 		(void)strncat(SAVEF, plname, FILENAME - i - 4); 334. #  else 335. 		(void)strncat(SAVEF, plname, 8); 336. #  endif 337. 		regularize(SAVEF+i); 338. 	}  339.  	Strcat(SAVEF, ".sav"); 340. # else 341. 	Sprintf(SAVEF, "save/%d%s", (int)getuid, plname); 342. 	regularize(SAVEF+5);	/* avoid. or / in name */ 343. # endif 344. #endif 345. }  346.   347.  #ifdef INSURANCE 348. void 349. save_savefile_name(fd) 350. int fd; 351. {  352.  	(void) write(fd, (genericptr_t) SAVEF, sizeof(SAVEF)); 353. }  354.  #endif 355.  356.   357.  #if defined(WIZARD) && !defined(MICRO) 358. /* change pre-existing savefile name to indicate an error savefile */ 359. void 360. set_error_savefile 361. {  362.  # ifdef VMS 363.       {  364.  	char *semi_colon = rindex(SAVEF, ';'); 365. 	if (semi_colon) *semi_colon = '\0'; 366.       }  367.  	Strcat(SAVEF, ".e;1"); 368. # else 369. #ifdef MAC 370. 	Strcat(SAVEF, "-e"); 371. #else 372. 	Strcat(SAVEF, ".e"); 373. #endif 374. # endif 375. }  376.  #endif 377.  378.   379.  /* create save file, overwriting one if it already exists */ 380. int 381. create_savefile 382. {  383.  	int fd; 384. # ifdef AMIGA 385. 	fd = ami_wbench_getsave(O_WRONLY | O_CREAT | O_TRUNC); 386. # else 387. #  ifdef MICRO 388. 	fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); 389. #  else 390. #   ifdef MAC 391. 	fd = creat(SAVEF, SAVE_TYPE); 392. #   else /* MAC */ 393. 	fd = creat(SAVEF, FCMASK); 394. #   endif /* MAC */ 395. #   if defined(VMS) && !defined(SECURE) 396. 	/*  397.  	   Make sure the save file is owned by the current process. That's 398. the default for non-privileged users, but for priv'd users the 399. 	   file will be owned by the directory's owner instead of the user. 400. 	 */  401.  #    ifdef getuid	/*(see vmsunix.c)*/ 402. #     undef getuid 403. #    endif 404. 	(void) chown(SAVEF, getuid, getgid); 405. #   endif /* VMS && !SECURE */ 406. #  endif 407. # endif 408.  409.  	return fd; 410. }  411.   412.   413.  /* open savefile for reading */ 414. int 415. open_savefile 416. {  417.  	int fd; 418.  419.  #ifdef AMIGA 420. 	fd = ami_wbench_getsave(O_RDONLY); 421. #else 422. # ifdef MAC 423. 	fd = macopen ( SAVEF, O_RDONLY , SAVE_TYPE ) ; 424. # else /* MAC */ 425. 	fd = open(SAVEF, O_RDONLY, 0); 426. # endif /* MAC */ 427. #endif /* AMIGA */ 428. 	return fd; 429. }  430.   431.   432.  /* delete savefile */ 433. int 434. delete_savefile 435. {  436.  #ifdef AMIGA 437. 	ami_wbench_unlink(SAVEF); 438. #endif 439. 	(void) unlink(SAVEF); 440. 	return 0;	/* for xxxmain.c test */ 441. }  442.   443.   444.  /* --  END SAVE FILE HANDLING --- */ 445.  446.   447.  /* --  BEGIN FILE COMPRESSION HANDLING --- */ 448.  449.  /* compress file */ 450. void 451. compress(filename) 452. const char *filename; 453. {  454.  #ifdef COMPRESS 455. 	char cmd[80]; 456.  457.  	Strcpy(cmd, COMPRESS); 458. 	Strcat(cmd, " "); 459. # ifdef COMPRESS_OPTIONS 460. 	Strcat(cmd, COMPRESS_OPTIONS); 461. 	Strcat(cmd, " "); 462. # endif 463. 	Strcat(cmd,filename); 464. 	(void) system(cmd); 465. #endif 466. }  467.   468.   469.  /* uncompress file if it exists */ 470. void 471. uncompress(filename) 472. const char *filename; 473. {  474.  #ifdef COMPRESS 475. 	char cmd[80], cfn[80]; 476. 	int fd; 477.  478.  	Strcpy(cfn,filename); 479. 	Strcat(cfn,".Z"); 480. 	if((fd = open(cfn,O_RDONLY)) >= 0) { 481. 	    (void) close(fd); 482. 	    Strcpy(cmd, COMPRESS); 483. 	    Strcat(cmd, " -d ");        /* uncompress */ 484. # ifdef COMPRESS_OPTIONS 485. 	    Strcat(cmd, COMPRESS_OPTIONS); 486. 	    Strcat(cmd, " "); 487. # endif 488. 	    Strcat(cmd,cfn); 489. 	    (void) system(cmd); 490. 	}  491.  #endif 492. }  493.   494.  /* --  END FILE COMPRESSION HANDLING --- */ 495.  496.   497.  /* --  BEGIN FILE LOCKING HANDLING --- */ 498.  499.  #ifdef NO_FILE_LINKS	/* implies UNIX */ 500. static int lockfd;	/* for lock_file to pass to unlock_file */ 501. #endif 502.  503.  #if defined(UNIX) || defined(VMS) 504. #define HUP	if(!done_hup) 505.  506.  static char * 507. make_lockname(filename) 508. const char *filename; 509. {  510.  	static char lockname[BUFSZ]; 511.  512.  # ifdef NO_FILE_LINKS 513. 	Strcpy(lockname, LOCKDIR); 514. 	Strcat(lockname, "/"); 515. 	Strcat(lockname, filename); 516. # else 517. 	Strcpy(lockname, filename); 518. # endif 519. # ifdef VMS 520.       {  521.  	char *semi_colon = rindex(lockname, ';'); 522. 	if (semi_colon) *semi_colon = '\0'; 523.       }  524.  	Strcat(lockname, ".lock;1"); 525. # else 526. 	Strcat(lockname, "_lock"); 527. # endif 528. 	return lockname; 529. }  530.  #endif  /* UNIX || VMS */ 531.  532.   533.  /* lock a file */ 534. boolean 535. lock_file(filename, retryct) 536. const char *filename; 537. int retryct; 538. {  539.  #if defined(UNIX) || defined(VMS) 540. 	char *lockname; 541.  542.  	lockname = make_lockname(filename); 543.  544.  # ifdef NO_FILE_LINKS 545. 	while ((lockfd = open(lockname, O_RDWR|O_CREAT|O_EXCL, 0666)) == -1) { 546. # else 547. 	while (link(filename, lockname) == -1) { 548. # endif 549. 		register int errnosv = errno; 550.  551.  		switch (errnosv) {	/* George Barbanis */ 552. 		    case ENOENT: 553. 			HUP raw_printf("Can't find file %s to lock!", filename); 554. 			return FALSE; 555. 		    case EACCES: 556. 			HUP raw_printf("No write permission to lock %s!",  557.  				       filename); 558. 			return FALSE; 559. 		    case EEXIST: 560. 			break;	/* retry checks below */ 561. 		    default: 562. 			HUP perror(lockname); 563. 			HUP raw_printf(  564.  				     "Cannot lock %s for unknown reason (%d).",  565.  				       filename, errnosv); 566. 			return FALSE; 567. 		}  568.   569.  		if (!retryct--) { 570. 			HUP (void) raw_print("I give up.  Sorry."); 571. 			HUP raw_printf("Perhaps there is an old %s around?",  572.  				       lockname); 573. 			return FALSE; 574. 		}  575.   576.  		HUP raw_printf("Waiting for access to %s.  (%d retries left).",  577.  			       filename, retryct); 578. # if defined(SYSV) || defined(ULTRIX) || defined(VMS) 579. 		(void) 580. # endif 581. 			sleep(1); 582. 	}  583.  #endif  /* UNIX || VMS */ 584. 	return TRUE; 585. }  586.   587.   588.  #ifdef VMS	/* for unlock_file, use the unlink routine in vmsunix.c */ 589. # ifdef unlink 590. #  undef unlink 591. # endif 592. # define unlink(foo) vms_unlink(foo) 593. #endif 594.  595.  /* unlock file, which must be currently locked by lock_file */ 596. void 597. unlock_file(filename) 598. const char *filename; 599. {  600.  #if defined(UNIX) || defined(VMS) 601. 	char *lockname; 602.  603.  	lockname = make_lockname(filename); 604.  605.  	if (unlink(lockname) < 0) 606. 		HUP raw_printf("Can't unlink %s.", lockname); 607. # ifdef NO_FILE_LINKS 608. 	(void) close(lockfd); 609. # endif 610.  611.  #endif  /* UNIX || VMS */ 612. }  613.   614.  /* --  END FILE LOCKING HANDLING --- */ 615.  616.   617.  /* --  BEGIN CONFIG FILE HANDLING --- */ 618.  619.  const char *configfile = 620. #ifdef UNIX 621. 			".nethackrc"; 622. #else 623. #ifdef MAC 624. 			"NetHack defaults"; 625. #else 626. 			"NetHack.cnf"; 627. #endif 628. #endif 629.  630.  static FILE *FDECL(fopen_config_file, (const char *)); 631. static int FDECL(get_uchars, (FILE *, char *, char *, uchar *, int, const char *)); 632. int FDECL(parse_config_line, (FILE *, char *, char *, char *)); 633.  634.  #ifndef MFLOPPY 635. #define fopenp fopen 636. #endif 637.  638.  static FILE * 639. fopen_config_file(filename) 640. const char *filename; 641. {  642.  	FILE *fp; 643. #if defined(UNIX) || defined(VMS) 644. 	char	tmp_config[BUFSZ]; 645. #endif 646.  647.  	/* "filename" is an environment variable, so it should hang around */ 648. 	if (filename && ((fp = fopenp(filename, "r")) != (FILE *)0)) { 649. 		configfile = filename; 650. 		return(fp); 651. 	}  652.   653.  #if defined(MICRO) || defined(MAC) 654. 	if ((fp = fopenp(configfile, "r")) != (FILE *)0) 655. 		return(fp); 656. #else 657. # ifdef VMS 658. 	if ((fp = fopenp("nethackini", "r")) != (FILE *)0) { 659. 		configfile = "nethackini"; 660. 		return(fp); 661. 	}  662.  	if ((fp = fopenp("sys$login:nethack.ini", "r")) != (FILE *)0) { 663. 		configfile = "nethack.ini"; 664. 		return(fp); 665. 	}  666.  	Sprintf(tmp_config, "%s%s", getenv("HOME"), "NetHack.cnf"); 667. 	if ((fp = fopenp(tmp_config, "r")) != (FILE *)0) 668. 		return(fp); 669. # else	/* should be only UNIX left */ 670. 	Sprintf(tmp_config, "%s/%s", getenv("HOME"), ".nethackrc"); 671. 	if ((fp = fopenp(tmp_config, "r")) != (FILE *)0) 672. 		return(fp); 673. # endif 674. #endif 675. 	return (FILE *)0; 676.  677.  }  678.   679.   680.  /*  681.   * Retrieve a list of integers from a file into a uchar array. 682.  *  683.   * NOTE:  This routine is unable to read a value of 0. 684.  */  685.  static int 686. get_uchars(fp, buf, bufp, list, size, name) 687.     FILE *fp;		/* input file pointer */ 688.     char *buf;		/* read buffer, must be of size BUFSZ */ 689.     char *bufp;		/* current pointer */ 690.     uchar *list;	/* return list */ 691.     int  size;		/* return list size */ 692.     const char *name;		/* name of option for error message */ 693. {  694.      unsigned int num = 0; 695.     int count = 0; 696.  697.      while (1) { 698. 	switch(*bufp) { 699. 	    case ' ':  case '\0': 700. 	    case '\t': case '\n': 701. 		if (num) { 702. 		    list[count++] =  num; 703. 		    num = 0; 704. 		}  705.  		if (count == size || !*bufp) return count; 706. 		bufp++; 707. 		break; 708.  709.  	    case '0': case '1': case '2': case '3': 710. 	    case '4': case '5': case '6': case '7': 711. 	    case '8': case '9': 712. 		num = num*10 + (*bufp-'0'); 713. 		bufp++; 714. 		break; 715.  716.  	    case '\\': 717. 	    	if (fp == (FILE *)0) 718. 		    goto gi_error; 719. 		do  { 720. 		    if (!fgets(buf, BUFSZ, fp)) goto gi_error; 721. 		} while (buf[0] == '#'); 722. 		bufp = buf; 723. 		break; 724.  725.  	    default: 726. gi_error: 727. 		raw_printf("Syntax error in %s", name); 728. 		wait_synch; 729. 		return count; 730. 	}  731.      }  732.      /*NOTREACHED*/ 733. }  734.   735.  /*ARGSUSED*/ 736. int 737. parse_config_line(fp, buf, tmp_ramdisk, tmp_levels) 738. FILE		*fp; 739. char		*buf; 740. char		*tmp_ramdisk; 741. char		*tmp_levels; 742. {  743.  	char		*bufp, *altp; 744.  745.  	if (*buf == '#') 746. 		return 1; 747.  748.  	/* remove trailing whitespace */ 749. 	bufp = eos(buf); 750. 	while (--bufp > buf && isspace(*bufp)) 751. 		continue; 752.  753.  	if (bufp <= buf) 754. 		return 1;		/* skip all-blank lines */ 755. 	else 756. 		*(bufp + 1) = '\0';	/* terminate line */ 757.  758.  	/* find the '=' or ':' */ 759. 	bufp = index(buf, '='); 760. 	altp = index(buf, ':'); 761. 	if (!bufp || (altp && altp < bufp)) bufp = altp; 762. 	if (!bufp) return 0; 763.  764.  	/* skip  whitespace between '=' and value */ 765. 	do { ++bufp; } while (isspace(*bufp)); 766.  767.  	/* Go through possible variables */ 768. 	if (!strncmpi(buf, "OPTIONS", 4)) { 769. 		parseoptions(bufp, TRUE, TRUE); 770. 		if (plname[0])		/* If a name was given */ 771. 			plnamesuffix;	/* set the character class */ 772. #ifdef MICRO 773. 	} else if (!strncmpi(buf, "HACKDIR", 4)) { 774. 		(void) strncpy(hackdir, bufp, PATHLEN); 775. # ifdef MFLOPPY 776. 	} else if (!strncmpi(buf, "RAMDISK", 3)) { 777. 				/* The following ifdef is NOT in the wrong 778. 				 * place. For now, we accept and silently 779. 				 * ignore RAMDISK */ 780. #  ifndef AMIGA 781. 		(void) strncpy(tmp_ramdisk, bufp, PATHLEN); 782. #  endif 783. # endif 784. 	} else if (!strncmpi(buf, "LEVELS", 4)) { 785. 		(void) strncpy(tmp_levels, bufp, PATHLEN); 786.  787.  	} else if (!strncmpi(buf, "SAVE", 4)) { 788. 		char *ptr; 789. 		if (ptr = index(bufp, ';')) { 790. 			*ptr = '\0'; 791. # ifdef MFLOPPY 792. 			if (*(ptr+1) == 'n' || *(ptr+1) == 'N') { 793. 				extern	int saveprompt; 794. 				saveprompt = FALSE; 795. 			}  796.  # endif 797.     }  798.  		(void) strncpy(SAVEP, bufp, PATHLEN); 799. 		append_slash(SAVEP); 800. #endif /* MICRO */ 801. 	} else if(!strncmpi(buf, "CHARACTER", 4)) { 802. 	    (void) strncpy(pl_character, bufp, PL_CSIZ); 803. 	} else if(!strncmpi(buf, "DOGNAME", 3)) { 804. 	    (void) strncpy(dogname, bufp, 62); 805. 	} else if(!strncmpi(buf, "CATNAME", 3)) { 806. 	    (void) strncpy(catname, bufp, 62); 807. 	} else if(!strncmpi(buf, "NAME", 4)) { 808. 	    (void) strncpy(plname, bufp, PL_NSIZ); 809. 	    plnamesuffix; 810. 	} else if (!strncmpi(buf, "GRAPHICS", 4)) { 811. 	    uchar   translate[MAXPCHARS]; 812. 	    int   len; 813.  814.  	    len = get_uchars(fp, buf, bufp, translate,  815.  					MAXPCHARS, "GRAPHICS"); 816. 	    assign_graphics(translate, len); 817. 	} else if (!strncmpi(buf, "OBJECTS", 3)) { 818. 	    /* oc_syms[0] is the RANDOM object, unused */ 819. 	    (void) get_uchars(fp, buf, bufp, &(oc_syms[1]),  820.  					MAXOCLASSES-1, "OBJECTS"); 821. 	} else if (!strncmpi(buf, "MONSTERS", 3)) { 822. 	    /* monsyms[0] is unused */ 823. 	    (void) get_uchars(fp, buf, bufp, &(monsyms[1]),  824.  					MAXMCLASSES-1, "MONSTERS"); 825. #ifdef AMIGA 826. 	} else if (!strncmpi(buf, "PATH", 4)) { 827. 		(void) strncpy(PATH, bufp, PATHLEN); 828. 	} else if (!strncmpi(buf, "PENS", 3)) { 829. 		int i;  830. char *t; 831. 		extern unsigned short amii_curmap[]; 832. 		for (i = 0, t = strtok(bufp, ",");  833.  				t && i < 8;  834.  				t = strtok(NULL, ","), ++i) { 835. 			sscanf(t, "%hx", &amii_curmap[i]); 836. 		}  837.  		amii_setpens; 838. #endif 839. 	} else 840. 		return 0; 841. 	return 1; 842. }  843.   844.  void 845. read_config_file(filename) 846. const char *filename; 847. {  848.  #define tmp_levels	(char *)0 849. #define tmp_ramdisk	(char *)0 850.  851.  #ifdef MICRO 852. #undef tmp_levels 853. 	char	tmp_levels[PATHLEN]; 854. # ifdef MFLOPPY 855. #  ifndef AMIGA 856. #undef tmp_ramdisk 857. 	char	tmp_ramdisk[PATHLEN]; 858. #  endif 859. # endif 860. #endif 861. 	char	buf[BUFSZ]; 862. 	FILE	*fp; 863.  864.  #if defined(MAC) 865. 	{  866.  		long nul = 0L ; 867. 		Str255 volName ; 868. 		/*  869.  		 * We should try and get this data from a rsrc, in the profile file 870. 		 * the user double-clicked... This data should be saved with the 871. 		 * save file in the resource fork, AND be saveable in "stationery" 872. 		 */  873.  		GetVol ( volName, & theDirs . dataRefNum ) ; 874. 		GetWDInfo ( theDirs . dataRefNum, & theDirs . dataRefNum , & theDirs .  875.  			dataDirID , & nul ) ; 876. 		if ( volName [ 0 ] > 31 ) volName [ 0 ] = 31 ; 877. 		for ( nul = 1 ; nul <= volName [ 0 ] ; nul ++ ) { 878. 			if ( volName [ nul ] == ':' ) { 879. 				volName [ nul ] = 0 ; 880. 				volName [ 0 ] = nul - 1 ; 881. 				break ; 882. 			}  883.  		}  884.  		BlockMove ( volName, theDirs . dataName , 32L ) ; 885. 	}  886.  #endif /* MAC */ 887.  888.  	if (!(fp = fopen_config_file(filename))) return; 889.  890.  #ifdef MICRO 891. # ifdef MFLOPPY 892. #  ifndef AMIGA 893. 	tmp_ramdisk[0] = 0; 894. #  endif 895. # endif 896. 	tmp_levels[0] = 0; 897. #endif 898.  899.  	while (fgets(buf, BUFSZ, fp)) { 900. 		if (!parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)) { 901. 			raw_printf("Bad option line:  \"%s\"", buf); 902. 			wait_synch; 903. 		}  904.  	}  905.  	(void) fclose(fp); 906.  907.  #ifdef MICRO 908. # ifdef MFLOPPY 909. 	Strcpy(permbones, tmp_levels); 910. #  ifndef AMIGA 911. 	if (tmp_ramdisk[0]) { 912. 		Strcpy(levels, tmp_ramdisk); 913. 		if (strcmp(permbones, levels))		/* if not identical */ 914. 			ramdisk = TRUE; 915. 	} else 916. #  endif /* AMIGA */ 917. 		Strcpy(levels, tmp_levels); 918.  919.  	Strcpy(bones, levels); 920. # endif /* MFLOPPY */ 921. #endif /* MICRO */ 922. 	return; 923. }  924.   925.  /* --  END CONFIG FILE HANDLING --- */ 926.  927.  /* --  BEGIN SCOREBOARD CREATION --- */ 928.  929.  /* verify that we can write to the scoreboard file; if not, try to create one */ 930. void 931. check_recordfile(dir) 932. const char *dir; 933. {  934.  #if defined(UNIX) || defined(VMS) 935. 	int fd = open(RECORD, O_RDWR, 0); 936.  937.  	if (fd >= 0) { 938. # ifdef VMS	/* must be stream-lf to use UPDATE_RECORD_IN_PLACE */ 939. 		if (!file_is_stmlf(fd)) { 940. 		    raw_printf(	/* note: assume VMS dir has trailing punct */  941.  		  "Warning: scoreboard file %s%s is not in stream_lf format",  942.  				(dir ? dir : "[]"), RECORD); 943. 		    wait_synch; 944. 		}  945.  # endif 946. 	    (void) close(fd);	/* RECORD is accessible */ 947. 	} else if ((fd = open(RECORD, O_CREAT|O_RDWR, FCMASK)) >= 0) { 948. 	    (void) close(fd);	/* RECORD newly created */ 949. # if defined(VMS) && !defined(SECURE) 950. 	    /* Re-protect RECORD with world:read+write+execute+delete access. */ 951.  	    (void) chmod(RECORD, FCMASK | 007); /* allow everyone full access */ 952. # endif /* VMS && !SECURE */ 953. 	} else { 954. 	    raw_printf("Warning: cannot write scoreboard file %s/%s",  955.  			(dir ? dir : "."), RECORD); 956. 	    wait_synch; 957. 	}  958.  #endif  /* !UNIX && !VMS */ 959.  960.  #ifdef MICRO 961. 	int fd; 962. 	char tmp[PATHLEN]; 963.  964.  # ifdef OS2_CODEVIEW   /* explicit path on opening for OS/2 */ 965. 	Strcpy(tmp, dir); 966. 	append_slash(tmp); 967. 	Strcat(tmp, RECORD); 968. # else 969. 	Strcpy(tmp, RECORD); 970. # endif 971.  972.  	if ((fd = open(tmp, O_RDWR)) < 0) { 973. 	    /* try to create empty record */ 974. # ifdef AZTEC_C 975. 	    /* Aztec doesn't use the third argument */ 976. 	    if ((fd = open(tmp, O_CREAT|O_RDWR)) < 0) { 977. # else 978. 	    if ((fd = open(tmp, O_CREAT|O_RDWR, S_IREAD|S_IWRITE)) < 0) { 979. # endif 980.         raw_printf("Warning: cannot write record %s", tmp); 981. 		wait_synch; 982. 	    } else 983. 		(void) close(fd); 984. 	} else		/* open succeeded */ 985. 	    (void) close(fd); 986. #else /* MICRO */ 987.  988.  # ifdef MAC 989. 	int fd = macopen ( RECORD, O_RDWR | O_CREAT , TEXT_TYPE ) ; 990.  991.  	if ( fd < 0 ) { 992. 		raw_printf ( "Warning: cannot write %s", RECORD ) ; 993. 	} else { 994. 		close ( fd ) ; 995. 	}  996.  # endif /* MAC */ 997.  998.  #endif /* MICRO */ 999. }  1000.  1001. /* --  END SCOREBOARD CREATION --- */ 1002. 1003.  1004. /*files.c*/