Source:NetHack 3.3.0/files.c

From NetHackWiki
Revision as of 10:41, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.3.0/files.c moved to Source:NetHack 3.3.0/files.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

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.    /*	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 <ctype.h>
9.    
10.   #if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C)
11.   #include <fcntl.h>
12.   #endif
13.   #if defined(UNIX) || defined(VMS)
14.   #include <errno.h>
15.   # ifndef SKIP_ERRNO
16.   extern int errno;
17.   # endif
18.   #include <signal.h>
19.   #endif
20.   
21.   #if defined(MSDOS) || defined(OS2) || defined(TOS) || defined(WIN32)
22.   # ifndef GNUDOS
23.   #include <sys\stat.h>
24.   # else
25.   #include <sys/stat.h>
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]<uid>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 <proto/dos.h>
75.   # endif
76.   
77.   #include <libraries/dos.h>
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*/