4.4BSD/usr/src/contrib/news/inn/lib/dbz.pch

DBZ as distributed by CNEWS has a few bits of lint in it.  They fall into
the following categories:
	1.  There is code after return statements, like
		return(value);
		break;
	2.  If you turn off DBZDEBUG some fluff is left behind.
	3.  A couple of (void) casts should be added to fprintf calls
	    since ferror is checked right after.
	4.  Use "clibrary.h" for many C library declarations, and the
	    POINTER typedef found there.
In addition, DBZ cannot be used with vfork.  (Yes, I agree with all the
other purists that vfork is a crock, but I'm a realist enough to recognize
that it can get some major performance benefits if used in innd.) Applying
this patch makes sure that any files that DBZ opens have the close-on-exec
flag set.

This patch also includes two performance enhancements by Rob Robertson
<rob@violet.berkeley.edu>.  The first is the new dbzwritethrough() routine
that makes the incore mode of DBZ use a write-through cache.  The second
is automatic calculation of the database tags; Craig Leres
<leres@ee.lbl.gov> contributed dbztagmask() based on Rob's code.

This patch also includes the option to memory-map the database using the
mmap() call.  This original version of that code was by David Robinson,
formerly <david@elroy.jpl.nasa.gov> now <david.robinson@sun.com> (January,
1993).

Apply the following diff by using the "patch" program.  The Makefile
will normally do this for you automatically.

DBZ is great, and Jon and Henry (and the others mentioned in the source)
deserve a lot of credit for it.

*** ../dbz/dbz.c	Wed Oct 16 10:50:15 1991
--- dbz.c	Fri Jan 22 09:34:06 1993
***************
*** 12,17 ****
--- 12,24 ----
  
  Major reworking by Henry Spencer as part of the C News project.
  
+ Minor lint and CodeCenter (Saber) fluff removal by Rich $alz (March, 1991).
+ Non-portable CloseOnExec() calls added by Rich $alz (September, 1991).
+ Added "writethrough" and tagmask calculation code from
+ <rob@violet.berkeley.edu> and <leres@ee.lbl.gov> by Rich $alz (December, 1992).
+ Merged in MMAP code by David Robinson, formerly <david@elroy.jpl.nasa.gov>
+ now <david.robinson@sun.com> (January, 1993).
+ 
  These routines replace dbm as used by the usenet news software
  (it's not a full dbm replacement by any means).  It's fast and
  simple.  It contains no AT&T code.
***************
*** 24,30 ****
  
  #include <stdio.h>
  #include <sys/types.h>
! #include <string.h>
  #include <ctype.h>
  #include <errno.h>
  #ifndef __STDC__
--- 31,37 ----
  
  #include <stdio.h>
  #include <sys/types.h>
! #include <sys/stat.h>
  #include <ctype.h>
  #include <errno.h>
  #ifndef __STDC__
***************
*** 31,36 ****
--- 38,44 ----
  extern int errno;
  #endif
  #include <dbz.h>
+ #include "clibrary.h"
  
  /*
   * #ifdef index.  "LIA" = "leave it alone unless you know what you're doing".
***************
*** 50,56 ****
--- 58,67 ----
   * MAXRUN	length of run which shifts to next table (see below) (LIA)
   * OVERFLOW	long-int arithmetic overflow must be avoided, will trap
   * NOBUFFER	do not buffer hash-table i/o, B News locking is defective
+  * MMAP		Use SunOS style mmap() for efficient incore
   */
+ /* SUPPRESS 530 *//* Empty body for statement */
+ /* SUPPRESS 701 on free *//* Conflicting declaration */
  
  #ifdef FUNNYSEEKS
  #include <unistd.h>
***************
*** 203,208 ****
--- 214,237 ----
  static void mybytemap();
  static of_t bytemap();
  
+ /*
+  * Using mmap() is a more efficent way of keeping the .pag file incore.  On
+  * average, it cuts the number of system calls and buffer copies in half.
+  * It also allows one copy to be shared among many processes without
+  * consuming any extra resources.
+  */
+ #ifdef MMAP
+ #include <sys/mman.h>
+ #ifdef MAP_FILE
+ #define MAP__ARG	(MAP_FILE | MAP_SHARED)
+ #else
+ #define MAP__ARG	(MAP_SHARED)
+ #endif
+ #ifndef INCORE
+ #define INCORE
+ #endif
+ #endif
+ 
  /* 
   * For a program that makes many, many references to the database, it
   * is a large performance win to keep the table in core, if it will fit.
***************
*** 228,233 ****
--- 257,270 ----
  #endif
  
  /*
+  * Write to filesystem even if incore?  This replaces a single multi-
+  * megabyte write when doing a dbzsync with a multi-byte write each
+  * time an article is added.  On most systems, this will give an overall
+  * performance boost.
+  */
+ static int writethrough = 0;
+ 
+ /*
   * Stdio buffer for .pag reads.  Buffering more than about 16 does not help
   * significantly at the densities we try to maintain, and the much larger
   * buffers that most stdios default to are much more expensive to fill.
***************
*** 298,316 ****
   * alternative (under most compilers) is to pack around 2K of unused
   * strings -- there's just no way to get rid of them.
   */
- static int debug;			/* controlled by dbzdebug() */
  #ifdef DBZDEBUG
! #define DEBUG(args) if (debug) { (void) printf args ; }
  #else
  #define	DEBUG(args)	;
  #endif
  
  /* externals used */
  extern char *malloc();
  extern char *calloc();
  extern void free();		/* ANSI C; some old implementations say int */
  extern int atoi();
  extern long atol();
  
  /* misc. forwards */
  static long hash();
--- 335,358 ----
   * alternative (under most compilers) is to pack around 2K of unused
   * strings -- there's just no way to get rid of them.
   */
  #ifdef DBZDEBUG
! static int debug;			/* controlled by dbzdebug() */
! #define DEBUG(args) if (debug) { (void) printf args ; } else
  #else
  #define	DEBUG(args)	;
  #endif
  
  /* externals used */
+ #if	0
+ extern char *memcpy();
+ extern char *memchr();
  extern char *malloc();
  extern char *calloc();
  extern void free();		/* ANSI C; some old implementations say int */
+ #endif	/* 0 */
  extern int atoi();
  extern long atol();
+ extern void CloseOnExec();
  
  /* misc. forwards */
  static long hash();
***************
*** 336,342 ****
--- 378,386 ----
  static of_t *corepag;		/* incore version of .pag file, if any */
  static FILE *bufpagf;		/* well-buffered pagf, for incore rewrite */
  static of_t *getcore();
+ #ifndef MMAP
  static int putcore();
+ #endif
  static int written;		/* has a store() been done? */
  
  /*
***************
*** 391,399 ****
  	default:
  		DEBUG(("dbzfresh case map `%c' unknown\n", cmap));
  		return(-1);
- 		break;
  	}
! 	switch (tagmask) {
  	case 0:			/* default */
  		break;
  	case 1:			/* no tags */
--- 435,442 ----
  	default:
  		DEBUG(("dbzfresh case map `%c' unknown\n", cmap));
  		return(-1);
  	}
! 	switch ((int)tagmask) {
  	case 0:			/* default */
  		break;
  	case 1:			/* no tags */
***************
*** 418,424 ****
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "w");
! 	free(fn);
  	if (f == NULL) {
  		DEBUG(("dbzfresh: unable to write config\n"));
  		return(-1);
--- 461,467 ----
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "w");
! 	free((POINTER)fn);
  	if (f == NULL) {
  		DEBUG(("dbzfresh: unable to write config\n"));
  		return(-1);
***************
*** 437,443 ****
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "w");
! 	free(fn);
  	if (f == NULL) {
  		DEBUG(("dbzfresh: unable to create/truncate .pag file\n"));
  		return(-1);
--- 480,486 ----
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "w");
! 	free((POINTER)fn);
  	if (f == NULL) {
  		DEBUG(("dbzfresh: unable to create/truncate .pag file\n"));
  		return(-1);
***************
*** 522,527 ****
--- 565,572 ----
  	register FILE *f;
  	register int newtable;
  	register of_t newsize;
+ 	struct stat sb;
+ 	register of_t m;
  
  	if (pagf != NULL) {
  		DEBUG(("dbzagain: database already open\n"));
***************
*** 533,539 ****
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "r");
! 	free(fn);
  	if (f == NULL) {
  		DEBUG(("dbzagain: cannot open old .dir file\n"));
  		return(-1);
--- 578,584 ----
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "r");
! 	free((POINTER)fn);
  	if (f == NULL) {
  		DEBUG(("dbzagain: cannot open old .dir file\n"));
  		return(-1);
***************
*** 545,550 ****
--- 590,608 ----
  		return(-1);
  	}
  
+ 	/* calculate tagging from old file */
+ 	if (stat(oldname, &sb) != -1) {
+ 		 for (m = 1, i = 0; m < sb.st_size; i++, m <<= 1)
+ 			 continue;
+ 		 
+ 		 /* if we had more tags than the default, use the new data */
+ 		 if ((c.tagmask | c.tagenb) && m > (1 << TAGSHIFT)) {
+ 			  c.tagshift = i;
+ 			  c.tagmask = (~(unsigned long)0) >> (i + 1);
+ 			  c.tagenb = (c.tagmask << 1) & ~c.tagmask;
+ 		 }
+ 	}
+ 
  	/* tinker with it */
  	top = 0;
  	newtable = 0;
***************
*** 570,576 ****
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "w");
! 	free(fn);
  	if (f == NULL) {
  		DEBUG(("dbzagain: unable to write new .dir\n"));
  		return(-1);
--- 628,634 ----
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "w");
! 	free((POINTER)fn);
  	if (f == NULL) {
  		DEBUG(("dbzagain: unable to write new .dir\n"));
  		return(-1);
***************
*** 587,593 ****
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "w");
! 	free(fn);
  	if (f == NULL) {
  		DEBUG(("dbzagain: unable to create/truncate .pag file\n"));
  		return(-1);
--- 645,651 ----
  	if (fn == NULL)
  		return(-1);
  	f = fopen(fn, "w");
! 	free((POINTER)fn);
  	if (f == NULL) {
  		DEBUG(("dbzagain: unable to create/truncate .pag file\n"));
  		return(-1);
***************
*** 629,639 ****
  		dirronly = 1;
  	} else
  		dirronly = 0;
! 	free(dirfname);
  	if (dirf == NULL) {
  		DEBUG(("dbminit: can't open .dir file\n"));
  		return(-1);
  	}
  
  	/* open the .pag file */
  	pagfname = enstring(name, pag);
--- 687,698 ----
  		dirronly = 1;
  	} else
  		dirronly = 0;
! 	free((POINTER)dirfname);
  	if (dirf == NULL) {
  		DEBUG(("dbminit: can't open .dir file\n"));
  		return(-1);
  	}
+ 	CloseOnExec((int)fileno(dirf), 1);
  
  	/* open the .pag file */
  	pagfname = enstring(name, pag);
***************
*** 647,653 ****
  		if (pagf == NULL) {
  			DEBUG(("dbminit: .pag open failed\n"));
  			(void) fclose(dirf);
! 			free(pagfname);
  			return(-1);
  		}
  		pagronly = 1;
--- 706,712 ----
  		if (pagf == NULL) {
  			DEBUG(("dbminit: .pag open failed\n"));
  			(void) fclose(dirf);
! 			free((POINTER)pagfname);
  			return(-1);
  		}
  		pagronly = 1;
***************
*** 655,660 ****
--- 714,721 ----
  		pagronly = 1;
  	else
  		pagronly = 0;
+ 	if (pagf != NULL)
+ 		CloseOnExec((int)fileno(pagf), 1);
  #ifdef NOBUFFER
  	/*
  	 * B News does not do adequate locking on its database accesses.
***************
*** 679,690 ****
  		if (basefname == NULL) {
  			(void) fclose(pagf);
  			(void) fclose(dirf);
! 			free(pagfname);
  			pagf = NULL;
  			return(-1);
  		}
  	} else
  		basefname = NULL;
  #ifdef _IOFBF
  	if (basef != NULL)
  		(void) setvbuf(basef, basebuf, _IOFBF, sizeof(basebuf));
--- 740,753 ----
  		if (basefname == NULL) {
  			(void) fclose(pagf);
  			(void) fclose(dirf);
! 			free((POINTER)pagfname);
  			pagf = NULL;
  			return(-1);
  		}
  	} else
  		basefname = NULL;
+ 	if (basef != NULL)
+ 		CloseOnExec((int)fileno(basef), 1);
  #ifdef _IOFBF
  	if (basef != NULL)
  		(void) setvbuf(basef, basebuf, _IOFBF, sizeof(basebuf));
***************
*** 696,702 ****
  		(void) fclose(basef);
  		(void) fclose(pagf);
  		(void) fclose(dirf);
! 		free(pagfname);
  		pagf = NULL;
  		errno = EDOM;	/* kind of a kludge, but very portable */
  		return(-1);
--- 759,765 ----
  		(void) fclose(basef);
  		(void) fclose(pagf);
  		(void) fclose(dirf);
! 		free((POINTER)pagfname);
  		pagf = NULL;
  		errno = EDOM;	/* kind of a kludge, but very portable */
  		return(-1);
***************
*** 714,726 ****
  	s = (size_t)conf.tsize * SOF;
  	if (incore && (of_t)(s/SOF) == conf.tsize) {
  		bufpagf = fopen(pagfname, (pagronly) ? "rb" : "r+b");
! 		if (bufpagf != NULL)
  			corepag = getcore(bufpagf);
  	} else {
  		bufpagf = NULL;
  		corepag = NULL;
  	}
! 	free(pagfname);
  
  	/* misc. setup */
  	crcinit();
--- 777,791 ----
  	s = (size_t)conf.tsize * SOF;
  	if (incore && (of_t)(s/SOF) == conf.tsize) {
  		bufpagf = fopen(pagfname, (pagronly) ? "rb" : "r+b");
! 		if (bufpagf != NULL) {
  			corepag = getcore(bufpagf);
+ 			CloseOnExec((int)fileno(bufpagf), 1);
+ 		}
  	} else {
  		bufpagf = NULL;
  		corepag = NULL;
  	}
! 	free((POINTER)pagfname);
  
  	/* misc. setup */
  	crcinit();
***************
*** 775,781 ****
  		ret = -1;
  	}
  	if (corepag != NULL)
! 		free((char *)corepag);
  	corepag = NULL;
  	if (fclose(basef) == EOF) {
  		DEBUG(("dbmclose: fclose(basef) failed\n"));
--- 840,853 ----
  		ret = -1;
  	}
  	if (corepag != NULL)
! #ifdef MMAP
! 		if (munmap(corepag, (int)conf.tsize * SOF) == -1) {
! 			DEBUG(("dbmclose: munmap failed\n"));
! 			ret = -1;
! 		}
! #else
! 		free((POINTER)corepag);
! #endif
  	corepag = NULL;
  	if (fclose(basef) == EOF) {
  		DEBUG(("dbmclose: fclose(basef) failed\n"));
***************
*** 782,788 ****
  		ret = -1;
  	}
  	if (basefname != NULL)
! 		free(basefname);
  	basef = NULL;
  	pagf = NULL;
  	if (fclose(dirf) == EOF) {
--- 854,860 ----
  		ret = -1;
  	}
  	if (basefname != NULL)
! 		free((POINTER)basefname);
  	basef = NULL;
  	pagf = NULL;
  	if (fclose(dirf) == EOF) {
***************
*** 809,820 ****
  	if (!written)
  		return(0);
  
! 	if (corepag != NULL) {
  		if (putcore(corepag, bufpagf) < 0) {
  			DEBUG(("dbzsync: putcore failed\n"));
  			ret = -1;
  		}
  	}
  	if (!conf.olddbz)
  		if (putconf(dirf, &conf) < 0)
  			ret = -1;
--- 881,894 ----
  	if (!written)
  		return(0);
  
! #ifndef MMAP
! 	if (corepag != NULL && !writethrough) {
  		if (putcore(corepag, bufpagf) < 0) {
  			DEBUG(("dbzsync: putcore failed\n"));
  			ret = -1;
  		}
  	}
+ #endif
  	if (!conf.olddbz)
  		if (putconf(dirf, &conf) < 0)
  			ret = -1;
***************
*** 922,928 ****
  			DEBUG(("fetch: seek failed\n"));
  			return(output);
  		}
! 		if (fread(buffer, 1, keysize, basef) != keysize) {
  			DEBUG(("fetch: read failed\n"));
  			return(output);
  		}
--- 996,1002 ----
  			DEBUG(("fetch: seek failed\n"));
  			return(output);
  		}
! 		if (fread((POINTER)buffer, 1, keysize, basef) != keysize) {
  			DEBUG(("fetch: read failed\n"));
  			return(output);
  		}
***************
*** 932,938 ****
  		(void) mapcase(buffer, buffer, keysize);
  		DEBUG(("fetch: buffer (%s) looking for (%s) size = %d\n", 
  						buffer, key.dptr, keysize));
! 		if (memcmp(key.dptr, buffer, cmplen) == 0 &&
  				(*sepp == conf.fieldsep || *sepp == '\0')) {
  			/* we found it */
  			output.dptr = (char *)&key_ptr;
--- 1006,1012 ----
  		(void) mapcase(buffer, buffer, keysize);
  		DEBUG(("fetch: buffer (%s) looking for (%s) size = %d\n", 
  						buffer, key.dptr, keysize));
! 		if (memcmp((POINTER)key.dptr, (POINTER)buffer, cmplen) == 0 &&
  				(*sepp == conf.fieldsep || *sepp == '\0')) {
  			/* we found it */
  			output.dptr = (char *)&key_ptr;
***************
*** 965,976 ****
  		DEBUG(("latebase: still can't open base\n"));
  	} else {
  		DEBUG(("latebase: late open succeeded\n"));
! 		free(basefname);
  		basefname = NULL;
  #ifdef _IOFBF
  		(void) setvbuf(it, basebuf, _IOFBF, sizeof(basebuf));
  #endif
  	}
  	return(it);
  }
  
--- 1039,1052 ----
  		DEBUG(("latebase: still can't open base\n"));
  	} else {
  		DEBUG(("latebase: late open succeeded\n"));
! 		free((POINTER)basefname);
  		basefname = NULL;
  #ifdef _IOFBF
  		(void) setvbuf(it, basebuf, _IOFBF, sizeof(basebuf));
  #endif
  	}
+ 	if (it != NULL)
+ 		CloseOnExec((int)fileno(it), 1);
  	return(it);
  }
  
***************
*** 1034,1040 ****
  	}
  
  	/* copy the value in to ensure alignment */
! 	(void) memcpy((char *)&value, data.dptr, SOF);
  	DEBUG(("store: (%s, %ld)\n", key.dptr, (long)value));
  	if (!okayvalue(value)) {
  		DEBUG(("store: reserved bit or overflow in 0x%lx\n", value));
--- 1110,1116 ----
  	}
  
  	/* copy the value in to ensure alignment */
! 	(void) memcpy((POINTER)&value, (POINTER)data.dptr, SOF);
  	DEBUG(("store: (%s, %ld)\n", key.dptr, (long)value));
  	if (!okayvalue(value)) {
  		DEBUG(("store: reserved bit or overflow in 0x%lx\n", value));
***************
*** 1062,1072 ****
--- 1138,1188 ----
  {
  	register int old = incore;
  
+ #ifndef MMAP
  	incore = value;
+ #endif
  	return(old);
  }
  
  /*
+  - dbzwritethrough - write through the pag file in core
+  */
+ int				/* old setting */
+ dbzwritethrough(value)
+ int value;
+ {
+ 	register int old = writethrough;
+ 
+ 	writethrough = value;
+ 	return(old);
+ }
+ 
+ /*
+  - dbztagmask - calculate the correct tagmask for the given base file size
+  */
+ long
+ dbztagmask(size)
+ register long size;
+ {
+ 	register long m;
+ 	register long tagmask;
+ 	register int i;
+ 
+ 	if (size <= 0)
+ 		return(0L);		/* silly size */
+ 
+ 	for (m = 1, i = 0; m < size; i++, m <<= 1)
+ 		continue;
+ 
+ 	if (m < (1 << TAGSHIFT))
+ 		return(0L);		/* not worth tagging */
+ 
+ 	tagmask = (~(unsigned long)0) >> (i + 1);
+ 	tagmask = tagmask << i;
+ 	return(tagmask);
+ }
+ 
+ /*
   - getconf - get configuration from .dir file
   */
  static int			/* 0 success, -1 failure */
***************
*** 1107,1113 ****
  	if (getno(df, &err) != dbzversion)
  		err = -1;
  	cp->tsize = getno(df, &err);
! 	cp->fieldsep = getno(df, &err);
  	while ((c = getc(df)) == ' ')
  		continue;
  	cp->casemap = c;
--- 1223,1229 ----
  	if (getno(df, &err) != dbzversion)
  		err = -1;
  	cp->tsize = getno(df, &err);
! 	cp->fieldsep = (int)getno(df, &err);
  	while ((c = getc(df)) == ' ')
  		continue;
  	cp->casemap = c;
***************
*** 1124,1129 ****
--- 1240,1246 ----
  		cp->bytemap[i] = getno(df, &err);
  	if (getc(df) != '\n')
  		err = -1;
+ #ifdef DBZDEBUG
  	DEBUG(("size %ld, sep %d, cmap %c, tags 0x%lx/0x%lx<<%d, ", cp->tsize,
  			cp->fieldsep, cp->casemap, cp->tagenb, cp->tagmask,
  			cp->tagshift));
***************
*** 1132,1137 ****
--- 1249,1255 ----
  		DEBUG((" %d", cp->bytemap[i]));
  	}
  	DEBUG(("\n"));
+ #endif
  
  	/* second line, the usages */
  	for (i = 0; i < NUSEDS; i++)
***************
*** 1201,1214 ****
  		DEBUG(("fseek failure in putconf\n"));
  		ret = -1;
  	}
! 	fprintf(f, "dbz %d %ld %d %c %ld %ld %d %d", dbzversion, cp->tsize,
  				cp->fieldsep, cp->casemap, cp->tagenb,
  				cp->tagmask, cp->tagshift, cp->valuesize);
  	for (i = 0; i < cp->valuesize; i++)
! 		fprintf(f, " %d", cp->bytemap[i]);
! 	fprintf(f, "\n");
  	for (i = 0; i < NUSEDS; i++)
! 		fprintf(f, "%ld%c", cp->used[i], (i < NUSEDS-1) ? ' ' : '\n');
  
  	(void) fflush(f);
  	if (ferror(f))
--- 1319,1332 ----
  		DEBUG(("fseek failure in putconf\n"));
  		ret = -1;
  	}
! 	(void) fprintf(f, "dbz %d %ld %d %c %ld %ld %d %d", dbzversion, cp->tsize,
  				cp->fieldsep, cp->casemap, cp->tagenb,
  				cp->tagmask, cp->tagshift, cp->valuesize);
  	for (i = 0; i < cp->valuesize; i++)
! 		(void) fprintf(f, " %d", cp->bytemap[i]);
! 	(void) fprintf(f, "\n");
  	for (i = 0; i < NUSEDS; i++)
! 		(void) fprintf(f, "%ld%c", cp->used[i], (i < NUSEDS-1) ? ' ' : '\n');
  
  	(void) fflush(f);
  	if (ferror(f))
***************
*** 1229,1235 ****
--- 1347,1378 ----
  	register size_t i;
  	register size_t nread;
  	register char *it;
+ #ifdef MMAP
+ 	struct stat st;
  
+ 	if (fstat(fileno(f), &st) == -1) {
+ 		DEBUG(("getcore: fstat failed\n"));
+ 		return(NULL);
+ 	}
+ 	if (((size_t)conf.tsize * SOF) > st.st_size) {
+ 		/* file too small; extend it */
+ 		if (ftruncate((int)fileno(f), conf.tsize * SOF) == -1) {
+ 			DEBUG(("getcore: ftruncate failed\n"));
+ 			return(NULL);
+ 		}
+ 	}
+ 	it = mmap((caddr_t)0, (size_t)conf.tsize * SOF, 
+ 		pagronly ? PROT_READ : PROT_WRITE | PROT_READ, MAP__ARG,
+ 		(int)fileno(f), (off_t)0);
+ 	if (it == (char *)-1) {
+ 		DEBUG(("getcore: mmap failed\n"));
+ 		return(NULL);
+ 	}
+ #ifdef MC_ADVISE
+ 	/* not present in all versions of mmap() */
+ 	madvise(it, (size_t)conf.tsize * SOF, MADV_RANDOM);
+ #endif
+ #else
  	it = malloc((size_t)conf.tsize * SOF);
  	if (it == NULL) {
  		DEBUG(("getcore: malloc failed\n"));
***************
*** 1236,1255 ****
  		return(NULL);
  	}
  
! 	nread = fread(it, SOF, (size_t)conf.tsize, f);
  	if (ferror(f)) {
  		DEBUG(("getcore: read failed\n"));
! 		free(it);
  		return(NULL);
  	}
  
  	p = (of_t *)it + nread;
  	i = (size_t)conf.tsize - nread;
  	while (i-- > 0)
  		*p++ = VACANT;
  	return((of_t *)it);
  }
  
  /*
   - putcore - try to rewrite an in-core table
   */
--- 1379,1402 ----
  		return(NULL);
  	}
  
! 	nread = fread((POINTER)it, SOF, (size_t)conf.tsize, f);
  	if (ferror(f)) {
  		DEBUG(("getcore: read failed\n"));
! 		free((POINTER)it);
  		return(NULL);
  	}
  
+  	/* NOSTRICT *//* Possible pointer alignment problem */
  	p = (of_t *)it + nread;
  	i = (size_t)conf.tsize - nread;
  	while (i-- > 0)
  		*p++ = VACANT;
+ #endif
+  	/* NOSTRICT *//* Possible pointer alignment problem */
  	return((of_t *)it);
  }
  
+ #ifndef MMAP
  /*
   - putcore - try to rewrite an in-core table
   */
***************
*** 1262,1271 ****
  		DEBUG(("fseek failure in putcore\n"));
  		return(-1);
  	}
! 	(void) fwrite((char *)tab, SOF, (size_t)conf.tsize, f);
  	(void) fflush(f);
  	return((ferror(f)) ? -1 : 0);
  }
  
  /*
   - start - set up to start or restart a search
--- 1409,1419 ----
  		DEBUG(("fseek failure in putcore\n"));
  		return(-1);
  	}
! 	(void) fwrite((POINTER)tab, SOF, (size_t)conf.tsize, f);
  	(void) fflush(f);
  	return((ferror(f)) ? -1 : 0);
  }
+ #endif
  
  /*
   - start - set up to start or restart a search
***************
*** 1343,1349 ****
  			}
  
  			/* read it */
! 			if (fread((char *)&val, sizeof(val), 1, pagf) == 1)
  				value = MAPIN(val);
  			else if (ferror(pagf)) {
  				DEBUG(("search: read failed\n"));
--- 1491,1497 ----
  			}
  
  			/* read it */
! 			if (fread((POINTER)&val, sizeof(val), 1, pagf) == 1)
  				value = MAPIN(val);
  			else if (ferror(pagf)) {
  				DEBUG(("search: read failed\n"));
***************
*** 1425,1436 ****
  	if (corepag != NULL && place < conf.tsize) {
  		corepag[place] = value;
  		DEBUG(("set: incore\n"));
  		return(0);
  	}
  
  	/* seek to spot */
  	pagpos = -1;		/* invalidate position memory */
! 	if (fseek(pagf, place * SOF, SEEK_SET) != 0) {
  		DEBUG(("set: seek failed\n"));
  		sp->aborted = 1;
  		return(-1);
--- 1573,1589 ----
  	if (corepag != NULL && place < conf.tsize) {
  		corepag[place] = value;
  		DEBUG(("set: incore\n"));
+ #ifdef MMAP
  		return(0);
+ #else
+ 		if (!writethrough)
+ 			return(0);
+ #endif
  	}
  
  	/* seek to spot */
  	pagpos = -1;		/* invalidate position memory */
! 	if (fseek(pagf, (of_t)(place * SOF), SEEK_SET) != 0) {
  		DEBUG(("set: seek failed\n"));
  		sp->aborted = 1;
  		return(-1);
***************
*** 1437,1443 ****
  	}
  
  	/* write in data */
! 	if (fwrite((char *)&value, SOF, 1, pagf) != 1) {
  		DEBUG(("set: write failed\n"));
  		sp->aborted = 1;
  		return(-1);
--- 1590,1596 ----
  	}
  
  	/* write in data */
! 	if (fwrite((POINTER)&value, SOF, 1, pagf) != 1) {
  		DEBUG(("set: write failed\n"));
  		sp->aborted = 1;
  		return(-1);
***************
*** 1474,1479 ****
--- 1627,1633 ----
  	u.o = 1;
  	for (ntodo = (int)SOF; ntodo > 0; ntodo--) {
  		for (i = 0; i < SOF; i++)
+ 			/* SUPPRESS 112 *//* Retrieving char where long is stored */
  			if (u.c[i] != 0)
  				break;
  		if (i == SOF) {
***************
*** 1485,1490 ****
--- 1639,1645 ----
  		}
  		DEBUG(("mybytemap: byte %d\n", i));
  		*--mp = i;
+ 		/* SUPPRESS 112 *//* Retrieving char where long is stored */
  		while (u.c[i] != 0)
  			u.o <<= 1;
  	}
***************
*** 1728,1747 ****
  	switch (conf.casemap) {
  	case '0':		/* unmapped, sensible */
  		return(NULL);
- 		break;
  	case 'C':		/* C News, RFC 822 conformant (approx.) */
! 		p = memchr(s, '@', siz);
  		if (p == NULL)			/* no local/domain split */
  			return(NULL);		/* assume all local */
! 		else if	(p - (s+1) == plen && CISTREQN(s+1, post, plen)) {
  			/* crazy -- "postmaster" is case-insensitive */
  			return(s);
! 		} else
! 			return(p);
! 		break;
  	case '=':		/* 2.11, neither sensible nor conformant */
  		return(s);	/* all case-insensitive */
- 		break;
  	}
  
  	DEBUG(("cipoint: unknown case mapping `%c'\n", conf.casemap));
--- 1883,1899 ----
  	switch (conf.casemap) {
  	case '0':		/* unmapped, sensible */
  		return(NULL);
  	case 'C':		/* C News, RFC 822 conformant (approx.) */
! 		p = memchr((POINTER)s, '@', siz);
  		if (p == NULL)			/* no local/domain split */
  			return(NULL);		/* assume all local */
! 		if (p - (s+1) == plen && CISTREQN(s+1, post, plen)) {
  			/* crazy -- "postmaster" is case-insensitive */
  			return(s);
! 		}
! 		return(p);
  	case '=':		/* 2.11, neither sensible nor conformant */
  		return(s);	/* all case-insensitive */
  	}
  
  	DEBUG(("cipoint: unknown case mapping `%c'\n", conf.casemap));
***************
*** 1751,1766 ****
  /*
   - dbzdebug - control dbz debugging at run time
   */
  int				/* old value */
  dbzdebug(value)
  int value;
  {
- #ifdef DBZDEBUG
  	register int old = debug;
  
  	debug = value;
  	return(old);
- #else
- 	return(-1);
- #endif
  }
--- 1903,1916 ----
  /*
   - dbzdebug - control dbz debugging at run time
   */
+ #ifdef DBZDEBUG
  int				/* old value */
  dbzdebug(value)
  int value;
  {
  	register int old = debug;
  
  	debug = value;
  	return(old);
  }
+ #endif