Source:NetHack 3.1.0/files.c

From NetHackWiki
Revision as of 06:30, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.1.0/files.c moved to Source:NetHack 3.1.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.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

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