home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume19
/
cnews2
/
pch14apr90
< prev
next >
Wrap
Internet Message Format
|
1990-06-07
|
48KB
From @uunet.uu.net:henry@zoo.toronto.edu Wed Apr 18 16:57:09 1990
Received: from BBN.COM by pineapple.bbn.com id <AA15136@pineapple.bbn.com>; Wed, 18 Apr 90 16:56:41 -0400
Received: from uunet.UU.NET by BBN.COM id aa17658; 18 Apr 90 16:45 EDT
Received: from zoo.utoronto.ca by uunet.uu.net (5.61/1.14) with SMTP
id AA11936; Wed, 18 Apr 90 16:39:22 -0400
Message-Id: <9004182039.AA11936@uunet.uu.net>
From: henry@zoo.toronto.edu
Date: Wed, 18 Apr 90 14:14:49 EDT
To: uunet!source-patches@uunet.uu.net
Newsgroups: news.software.b,comp.sources.bugs
Subject: C News patch of 14-Apr-1990
Status: R
This is the first of three (!) patches mostly constituting the new dbz.
In addition to that, there have been a few small things. Our old slow
dbm emulation has been deleted. The nntpdiffs directory is gone too:
it corresponds to a version of NNTP which is now obsolete, and current
ones include reasonable C News support anyway. The sample-cron-entries
file now uses your news uid, rather than "news". Various Makefiles and
the like have been amended for dbz. Expire and mkdbm have been altered
to fully exploit the new dbz. Relaynews no longer tries to run dbmclose()
when preparing to execute a control message, because that causes trouble
on old systems which don't have dbmclose() and refuse to do dbminit()
more than once. And there are the usual bits of minor cleanup.
The new dbz is now the default database for C News; there is a fake module
which imitates it using dbm, for those of you who prefer big files and
slow execution. :-) For those unfamiliar with it, dbz -- originally
invented by Jon Zeeff -- implements just the subset of dbm that news
actually wants, and by doing this cleverly, is rather faster than dbm
and has files that are about a twentieth the size of dbm's. This one
is considerably improved over Jon's original, in various ways:
- It's faster (!).
- It handles table overflow gracefully and efficiently.
- It is byte-order independent, for use over networks.
- In-core tables can be selected at run time, not just by special
compilation.
- There are new functions that let the user completely ignore the
ugly case-mapping algorithms, with dbz doing all the work.
- Case mapping is self-contained, so dbz can be used independently
of C News with C-News-compatible mapping.
- There are new functions giving control of dbz's parameters (table
size, case mapping, etc.) when creating a new database.
- It remembers a history of table sizes, so that when expire
rebuilds the database, it can use a size that is likely
to prevent future overflow.
- It uses stdio for i/o, and has generally been overhauled for
portability; it should work on non-Unix systems.
- A shell-level interface (program) is provided.
- The Makefile uses the program to run a thorough regression test.
- It's compatible with old dbz databases, I think.
- It's documented (!).
start of patch 14-Apr-1990
(suggested archive name: `pch14Apr90.Z')
this should be run with patch -p0 <thisfile
Please do the following (there is no easy way we can convince
patch to do this automatically):
rm libfake/dbm.c
rm nntpdiffs/README
rm nntpdiffs/cdiff.1.5.0
rm nntpdiffs/cdiff.1.5.5
rm nntpdiffs/diff/ihave.c
rm nntpdiffs/diff/misc.c
rm nntpdiffs/diff/newnews.c
rm nntpdiffs/diff/serve.c
rm nntpdiffs/src.allnew/batch.c
rm nntpdiffs/src/Makefile
rm nntpdiffs/src/ihave.c
rm nntpdiffs/src/misc.c
rm nntpdiffs/src/newnews.c
rm nntpdiffs/src/serve.c
The following is a complete list of patches to date.
Prereq: 23-Jun-1989
Prereq: 7-Jul-1989
Prereq: 23-Jul-1989
Prereq: 22-Aug-1989
Prereq: 24-Aug-1989
Prereq: 14-Sep-1989
Prereq: 13-Nov-1989
Prereq: 10-Jan-1990
Prereq: 16-Jan-1990
Prereq: 17-Jan-1990
Prereq: 18-Jan-1990
Prereq: 12-Mar-1990
*** PATCHDATES.old Sat Apr 14 20:24:28 1990
--- PATCHDATES Sat Apr 14 20:24:28 1990
***************
*** 1,12 ****
--- 1,13 ----
23-Jun-1989
7-Jul-1989
23-Jul-1989
22-Aug-1989
24-Aug-1989
14-Sep-1989
13-Nov-1989
10-Jan-1990
16-Jan-1990
17-Jan-1990
18-Jan-1990
12-Mar-1990
+ 14-Apr-1990
Changed files, if any:
*** cnpatch/old/README Tue Mar 13 13:41:16 1990
--- README Sat Mar 31 18:32:20 1990
***************
*** 171,176 ****
UUCP connections. However, it does talk to utzoo. Utzoo connects to half
the known universe (well, not quite, but try via allegra, att, attcan,
! attunix, decvax, dptcdc, floyd, hoptoad, kitty, linus, mnetor, pyramid,
! suncan, utai, utgpu, watmath, or yunexus).
Geoff Collyer
--- 171,176 ----
UUCP connections. However, it does talk to utzoo. Utzoo connects to half
the known universe (well, not quite, but try via allegra, att, attcan,
! decvax, floyd, hoptoad, kitty, linus, mnetor, pyramid, suncan, utai, utgpu,
! watmath, or yunexus).
Geoff Collyer
*** cnpatch/old/conf/Makefile Tue Jan 16 17:58:28 1990
--- conf/Makefile Sat Mar 31 21:11:47 1990
***************
*** 13,20 ****
LIBS = ../libcnews.a
LIBDIRS = libbig libbsd42 libc libcnews libfake \
! libsmall libstdio libusg libv7 libv8
DIRS = batch conf expire h hfake input $(LIBDIRS) misc relay rna
CMPDIRS = batch conf expire input man misc relay rna
! RDIRS = batch expire input relay
SHS = doit.root doit.bin doit.news again.root
--- 13,20 ----
LIBS = ../libcnews.a
LIBDIRS = libbig libbsd42 libc libcnews libfake \
! libsmall libstdio libusg libv7 libv8 dbz
DIRS = batch conf expire h hfake input $(LIBDIRS) misc relay rna
CMPDIRS = batch conf expire input man misc relay rna
! RDIRS = batch dbz expire input relay
SHS = doit.root doit.bin doit.news again.root
***************
*** 43,46 ****
--- 43,47 ----
: too late for h and hfake, include has already been built
-egrep '^(h|hfake)/' subst.hs subst.gc >junk
+ : so test to make sure they do not need it
test ! -s junk ;
rm -f junk
***************
*** 97,101 ****
rm -f spacefor.sgi spacefor.xenix queuelen.pre
rm -f config mailname organization server whoami hostname errlog
! rm -f substitutions history history.pag history.dir active localgroups
rm -f log mailpaths sys cron rc setnewsids setnewsids.o spacefor.bsd
rm -rf replyusepath spacefor queuelen junk save
--- 98,102 ----
rm -f spacefor.sgi spacefor.xenix queuelen.pre
rm -f config mailname organization server whoami hostname errlog
! rm -f history history.pag history.dir active localgroups
rm -f log mailpaths sys cron rc setnewsids setnewsids.o spacefor.bsd
rm -rf replyusepath spacefor queuelen junk save
***************
*** 110,114 ****
spotless: gclean
rm -f $(SHS)
! rm -f substs
lclean:
--- 111,115 ----
spotless: gclean
rm -f $(SHS)
! rm -f substs substitutions
lclean:
*** cnpatch/old/conf/build Tue Mar 13 13:41:17 1990
--- conf/build Sun Apr 1 01:52:36 1990
***************
*** 135,141 ****
needucb=`yesno 'on your system. Is that right' yes`
else
! echo 'It appears that /usr/ucb does not exist or is not'
! echo 'needed for normal operation on your system. Is that'
! tmp=`yesno 'right' yes`
case "$tmp" in
yes) needucb=no ;;
--- 135,141 ----
needucb=`yesno 'on your system. Is that right' yes`
else
! echo 'It appears that /usr/ucb does not exist or that no'
! echo 'standard programs live there (and only there) on your'
! tmp=`yesno 'system. Is that right' yes`
case "$tmp" in
yes) needucb=no ;;
***************
*** 303,323 ****
esac
done
! has=`notinlist "$fake" dbm.o`
! tmp=`yesno 'Does your system have the "dbm" library' $has`
case "$tmp" in
! yes) dbmopt=`ask 'What is the compile option needed to get it' ${dbmopt--ldbm}`
has=`notinlist "$fake" dbmclose.o`
! tmp=`yesno 'Does your dbm have a dbmclose() function' $has`
case "$tmp" in
no) newfake="$newfake dbmclose.o" ;;
esac
;;
- no) newfake="$newfake dbm.o dbmclose.o"
- dbmopt=
- echo "Okay, we'll fake it for you. You might want to look at"
- echo "contrib/dbz, which is a probably-superior fake that we have"
- echo "not examined closely."
- ;;
esac
fake="$newfake"
--- 303,335 ----
esac
done
!
! echo
! has=`notinlist "$fake" dbz.o`
! echo 'The news system uses a database package, typically the old "dbm"'
! echo 'library from Version 7 or a lookalike, as an indexing system. We'
! echo 'supply a version of the "dbz" library which is faster than "dbm"'
! echo 'and uses much less disk space. This is usually the best thing to'
! echo 'use, unless you have major backward-compatibility problems. Do you'
! tmp=`yesno 'want to use our "dbz" library' $has`
case "$tmp" in
! yes) dbzlib=dbz
! dbmopt=
! storeval=yes
! ;;
! no) echo 'Presumably you want to use the dbm library or some local'
! echo 'equivalent, then. What is the compile option, or filename,'
! dbmopt=`ask 'needed to get it' ${dbmopt--ldbm}`
! newfake="$newfake dbz.o" # make dbm look like dbz
! dbzlib=
has=`notinlist "$fake" dbmclose.o`
! tmp=`yesno 'Does your dbm/dbz have a dbmclose() function' $has`
case "$tmp" in
no) newfake="$newfake dbmclose.o" ;;
esac
+ echo 'Does the store() function in your dbm/dbz return a'
+ storeval=`yesno 'value (some old dbms did not)' ${storeval-yes}`
;;
esac
+
fake="$newfake"
***************
*** 339,350 ****
esac
- case "$dbmopt" in
- '') storeval=yes ;;
- *) echo
- echo 'Does the store() function in your dbm library return a'
- storeval=`yesno 'value (some old ones did not)' ${storeval-yes}`
- ;;
- esac
-
has=`notinlist "$fake" strchr.o`
case "$has" in
--- 351,354 ----
***************
*** 754,758 ****
*) ccc="$ccc POST='$postlibs'" ;;
esac
! echo "for dir in lib$unixkind lib$addrsize libc libcnews $libstdio"
echo "do"
echo " cd ../\$dir"
--- 758,762 ----
*) ccc="$ccc POST='$postlibs'" ;;
esac
! echo "for dir in lib$unixkind lib$addrsize libc libcnews $libstdio $dbzlib"
echo "do"
echo " cd ../\$dir"
***************
*** 790,797 ****
;;
esac
! case "$dbmopt" in
! '') dbm= ;;
! *) dbm="DBM=$dbmopt" ;;
! esac
echo "for dir in $pgmdirs"
echo "do"
--- 794,798 ----
;;
esac
! dbm="DBM=$dbmopt"
echo "for dir in $pgmdirs"
echo "do"
***************
*** 844,857 ****
echo "cat >cron <<'!'"
cat <<!
! 15 * 1-31 * 0-6 su news -c '$newsbin/input/newsrun'
! 30 8 1-31 * 1-5 su news -c '$newsbin/input/newsrunning off'
! 00 17 1-31 * 1-5 su news -c '$newsbin/input/newsrunning on'
! 40 * 1-31 * 0-6 su news -c '$newsbin/batch/sendbatches'
! 59 0 1-31 * 0-6 su news -c '$newsbin/expire/doexpire $a'
! 10 8 1-31 * 0-6 su news -c '$newsbin/maint/newsdaily'
! 00 5,13,21 1-31 * 0-6 su news -c '$newsbin/maint/newswatch'
!
echo "!"
! echo "echo 'su news -c $newsbin/maint/newsboot' >rc"
echo ": done"
echo 'case "$1" in'
--- 845,858 ----
echo "cat >cron <<'!'"
cat <<!
! 15 * 1-31 * 0-6 su $newsuid -c '$newsbin/input/newsrun'
! 30 8 1-31 * 1-5 su $newsuid -c '$newsbin/input/newsrunning off'
! 00 17 1-31 * 1-5 su $newsuid -c '$newsbin/input/newsrunning on'
! 40 * 1-31 * 0-6 su $newsuid -c '$newsbin/batch/sendbatches'
! 59 0 1-31 * 0-6 su $newsuid -c '$newsbin/expire/doexpire $a'
! 10 8 1-31 * 0-6 su $newsuid -c '$newsbin/maint/newsdaily'
! 00 5,13,21 1-31 * 0-6 su $newsuid -c '$newsbin/maint/newswatch'
!
echo "!"
! echo "echo 'su $newsuid -c $newsbin/maint/newsboot' >rc"
echo ": done"
echo 'case "$1" in'
*** cnpatch/old/expire/Makefile Tue Jan 16 17:58:29 1990
--- expire/Makefile Thu Apr 5 14:17:41 1990
***************
*** 4,8 ****
LINTFLAGS = -I../include
JUNKLINT = 'possible pointer align'
! DBM = -ldbm
LIBS= ../libcnews.a
THEM = expire histdups histinfo histslash mkdbm mkhistory \
--- 4,8 ----
LINTFLAGS = -I../include
JUNKLINT = 'possible pointer align'
! DBM =
LIBS= ../libcnews.a
THEM = expire histdups histinfo histslash mkdbm mkhistory \
***************
*** 38,42 ****
expire: expire.o $(LIBS)
! $(CC) $(CFLAGS) $(LDFLAGS) expire.o $(PRE) $(LIBS) $(DBM) $(POST) -o $@
histinfo: histinfo.o $(LIBS)
--- 38,42 ----
expire: expire.o $(LIBS)
! $(CC) $(CFLAGS) $(LDFLAGS) expire.o $(PRE) $(DBM) $(LIBS) $(POST) -o $@
histinfo: histinfo.o $(LIBS)
*** cnpatch/old/expire/expire.c Tue Mar 13 13:41:18 1990
--- expire/expire.c Fri Apr 6 01:17:42 1990
***************
*** 21,24 ****
--- 21,25 ----
#include "fgetmfs.h"
#include "case.h"
+ #include "dbz.h"
#ifndef EPOCH
***************
*** 26,36 ****
#endif
-
- /* structure for dbm */
- typedef struct {
- char *dptr;
- int dsize;
- } datum;
-
#define DAY ((double)24*60*60)
--- 27,30 ----
***************
*** 77,81 ****
int verbose = 0; /* report statistics */
int rebuild = 1; /* rebuild history files */
- int violate = 0; /* non-rfc822 case-sensitive messageIDs */
int getdgrump = 0; /* report un-getdate()able expiry dates */
--- 71,74 ----
***************
*** 201,207 ****
rebuild = 0;
break;
- case 'V': /* non-rfc822 dualcase messageIDs */
- violate = 1;
- break;
case 'g': /* report getdate() failures on expiry dates */
getdgrump = 1;
--- 194,197 ----
***************
*** 453,458 ****
(void) fclose(eufopen("history.n.dir", "w"));
(void) fclose(eufopen("history.n.pag", "w"));
! if (dbminit("history.n") < 0)
! fail("dbminit(history.n) failed", "");
}
--- 443,449 ----
(void) fclose(eufopen("history.n.dir", "w"));
(void) fclose(eufopen("history.n.pag", "w"));
! (void) dbzincore(1);
! if (dbzagain("history.n", "history") < 0)
! fail("dbzagain(history.n) failed", "");
}
***************
*** 470,478 ****
/* make the DBM entry */
*nameend = '\0';
! if (!violate)
! lhs.dptr = rfc822ize(strsave(line));
! else
! lhs.dptr = strsave(line);
! *nameend = '\t';
lhs.dsize = strlen(lhs.dptr)+1;
here = ftell(new);
--- 461,465 ----
/* make the DBM entry */
*nameend = '\0';
! lhs.dptr = line;
lhs.dsize = strlen(lhs.dptr)+1;
here = ftell(new);
***************
*** 480,487 ****
rhs.dsize = sizeof(here);
errno = 0;
! ret = store(lhs, rhs);
if (ret < 0)
fail("dbm failure on `%s'", line);
! free(lhs.dptr);
/* and the history entry */
--- 467,474 ----
rhs.dsize = sizeof(here);
errno = 0;
! ret = dbzstore(lhs, rhs);
if (ret < 0)
fail("dbm failure on `%s'", line);
! *nameend = '\t';
/* and the history entry */
***************
*** 497,501 ****
if (rebuild) {
eufclose(new, "history.n");
! dbmclose();
}
--- 484,489 ----
if (rebuild) {
eufclose(new, "history.n");
! if (dbmclose() < 0)
! fail("dbmclose() failed", "");
}
*** cnpatch/old/expire/mkdbm.c Wed Jan 10 19:10:25 1990
--- expire/mkdbm.c Fri Apr 6 01:31:06 1990
***************
*** 6,14 ****
#include "alloc.h"
#include "fgetmfs.h"
! #include "case.h"
char *progname = "mkdbm";
- typedef struct { char *dptr; int dsize; } datum;
main(argc, argv)
--- 6,13 ----
#include "alloc.h"
#include "fgetmfs.h"
! #include "dbz.h"
char *progname = "mkdbm";
main(argc, argv)
***************
*** 31,34 ****
--- 30,34 ----
(void) close(creat(str3save(argv[1], ".", "dir"), 0666));
(void) close(creat(str3save(argv[1], ".", "pag"), 0666));
+ (void) dbzincore(1);
if (dbminit(argv[1]) < 0)
error("unable to do dbminit(`%s')", argv[1]);
***************
*** 47,51 ****
*scan = '\0';
- rfc822ize(line);
lhs.dptr = line;
lhs.dsize = strlen(line) + 1;
--- 47,50 ----
***************
*** 52,56 ****
rhs.dptr = (char *)&place;
rhs.dsize = sizeof place;
! if (store(lhs, rhs) < 0)
fprintf(stderr, "dbm failure `%.50s' @ %ld\n", line, place);
free(line);
--- 51,55 ----
rhs.dptr = (char *)&place;
rhs.dsize = sizeof place;
! if (dbzstore(lhs, rhs) < 0)
fprintf(stderr, "dbm failure `%.50s' @ %ld\n", line, place);
free(line);
*** cnpatch/old/h/Makefile Thu Aug 24 16:39:51 1989
--- h/Makefile Sat Mar 31 21:13:50 1990
***************
*** 1,4 ****
I = ../include
! INCLS = $(I)/alloc.h $(I)/config.h $(I)/fgetmfs.h $(I)/libc.h $(I)/news.h $(I)/case.h
all: $(INCLS)
--- 1,5 ----
I = ../include
! INCLS = $(I)/alloc.h $(I)/config.h $(I)/fgetmfs.h $(I)/libc.h $(I)/news.h \
! $(I)/case.h $(I)/dbz.h
all: $(INCLS)
***************
*** 14,17 ****
--- 15,20 ----
$(I)/case.h: case.h
cp case.h $@
+ $(I)/dbz.h: dbz.h
+ cp dbz.h $@
$(I)/news.h: news.h newshsed
sed -f newshsed news.h >$@
*** cnpatch/old/input/newsspool.c Thu Sep 14 16:03:36 1989
--- input/newsspool.c Mon Mar 26 17:37:50 1990
***************
*** 290,294 ****
setgid(getgid());
setuid(getuid());
! fprintf(stderr, "%s: renouncing setuid due to nonstandard `%s'\n",
progname, reason);
}
--- 290,294 ----
setgid(getgid());
setuid(getuid());
! fprintf(stderr, "%s: renouncing setuid due to nonstandard `%s' in environment\n",
progname, reason);
}
*** cnpatch/old/libfake/Makefile Tue Mar 13 13:41:21 1990
--- libfake/Makefile Sat Apr 14 20:12:25 1990
***************
*** 5,11 ****
SHELL = /bin/sh
! ALL = dbm.o fsync.o getopt.o memchr.o memcmp.o memcpy.o \
memset.o mkdir.o putenv.o strchr.o strcspn.o strpbrk.o strrchr.o \
! strspn.o strtok.o symlink.o dbmclose.o
# beware -- build knows about NEEDED
--- 5,11 ----
SHELL = /bin/sh
! ALL = fsync.o getopt.o memchr.o memcmp.o memcpy.o \
memset.o mkdir.o putenv.o strchr.o strcspn.o strpbrk.o strrchr.o \
! strspn.o strtok.o symlink.o dbmclose.o dbz.o
# beware -- build knows about NEEDED
*** cnpatch/old/man/newsbatch.8 Tue Mar 13 13:41:24 1990
--- man/newsbatch.8 Sat Apr 14 20:22:12 1990
***************
*** 7,11 ****
.\" =()<.ds m @<NEWSMASTER>@>()=
.ds m usenet
! .TH NEWSBATCH 8 "13 Jan 1990"
.BY "C News"
.SH NAME
--- 7,11 ----
.\" =()<.ds m @<NEWSMASTER>@>()=
.ds m usenet
! .TH NEWSBATCH 8 "14 April 1990"
.BY "C News"
.SH NAME
***************
*** 301,302 ****
--- 301,309 ----
(see \fInewsaux\fR(8)) does not know about multicast groups.
Also, \fIviauuxl\fR has not been tested well.
+ .PP
+ .I Viarsh
+ does not incorporate a spooling subsystem,
+ so a slow site stalls the entire batching system
+ and a non-responding site loses news.
+ It is not recommended for bulk transmission or where high reliability
+ is essential.
*** cnpatch/old/misc/Makefile Tue Mar 13 13:41:25 1990
--- misc/Makefile Thu Apr 5 16:59:03 1990
***************
*** 3,7 ****
CFLAGS = $(DEFS) $(COPTS) -I../include
LIBS = ../libcnews.a
! DBM = -ldbm
LINTFLAGS = $(DEFS) -ha
RN = ../relay
--- 3,7 ----
CFLAGS = $(DEFS) $(COPTS) -I../include
LIBS = ../libcnews.a
! DBM =
LINTFLAGS = $(DEFS) -ha
RN = ../relay
*** cnpatch/old/misc/addfeed Tue Jan 16 17:58:25 1990
--- misc/addfeed Mon Apr 2 13:04:01 1990
***************
*** 1,4 ****
#! /bin/sh
! # addgroup - add a newsgroup, locally only
# =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
--- 1,4 ----
#! /bin/sh
! # addfeed - add an outbound feed
# =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
*** cnpatch/old/relay/README.relay Tue Jun 20 19:01:44 1989
--- relay/README.relay Fri Mar 16 11:29:54 1990
***************
*** 19,24 ****
directories and I encourage this.
! If you plan to run rn, you'll need the rn patches to allow Xref: to
! work without Relay-Version:, which has been banished.
You will need to put your site name in /usr/lib/news/mailname (../conf/build
--- 19,25 ----
directories and I encourage this.
! If you plan to run rn, you'll need a recent rn which honours Xref: in
! the absence of Relay-Version:, which has been banished. patchlevel 40
! or greater should be fine; patchlevel 40 works here.
You will need to put your site name in /usr/lib/news/mailname (../conf/build
*** cnpatch/old/relay/caches.c Tue Mar 13 13:41:27 1990
--- relay/caches.c Fri Mar 30 17:03:01 1990
***************
*** 8,17 ****
#include "active.h"
#include "caches.h"
- #include "history.h"
#include "transmit.h"
statust
! synccaches() /* force in-core caches to disk */
{
! return actsync() | trclose() | closehist();
}
--- 8,16 ----
#include "active.h"
#include "caches.h"
#include "transmit.h"
statust
! synccaches() /* force dirty in-core caches to disk */
{
! return actsync() | trclose();
}
*** cnpatch/old/relay/hdrdefs.c Tue Mar 13 13:41:28 1990
--- relay/hdrdefs.c Mon Mar 19 12:41:03 1990
***************
*** 15,19 ****
#include "hdrint.h" /* may define "const" or REALSTDC */
#ifdef REALSTDC
! #include <stdlib.h> /* may define offsetof */
#endif /* REALSTDC */
--- 15,19 ----
#include "hdrint.h" /* may define "const" or REALSTDC */
#ifdef REALSTDC
! #include <stddef.h> /* defines offsetof */
#endif /* REALSTDC */
*** cnpatch/old/relay/procart.c Tue Jan 16 17:58:41 1990
--- relay/procart.c Wed Apr 4 15:10:24 1990
***************
*** 305,309 ****
} else if (msgid[0] != '<' || msgid[strlen(msgid)-1] != '>') {
prefuse(art);
! (void) printf("<> brackets missing in Message-ID\n");
} else if (alreadyseen(msgid)) {
prefuse(art);
--- 305,309 ----
} else if (msgid[0] != '<' || msgid[strlen(msgid)-1] != '>') {
prefuse(art);
! (void) printf("Message-ID not bracketed by <>\n");
} else if (alreadyseen(msgid)) {
prefuse(art);
*** cnpatch/old/relay/regress/out/stderr Thu Sep 14 16:03:50 1989
--- relay/regress/out/stderr Sat Mar 31 21:34:24 1990
***************
*** 1 ****
! ./relaynews: warning: renouncing setuid due to nonstandard `NEWSARTS'
--- 1 ----
! ./relaynews: warning: renouncing setuid due to nonstandard `NEWSARTS' in environment
*** cnpatch/old/relay/relaynews.c Tue Jan 16 17:58:42 1990
--- relay/relaynews.c Fri Mar 30 17:03:06 1990
***************
*** 122,125 ****
--- 122,126 ----
status |= synccaches(); /* being cautious: write & close caches */
+ status |= closehist();
(void) fflush(stdout); /* log file */
(void) fflush(stderr); /* errlog file */
***************
*** 263,267 ****
userealids = YES;
(void) fprintf(stderr,
! "%s: warning: renouncing setuid due to nonstandard `%s'\n",
progname, reason);
}
--- 264,268 ----
userealids = YES;
(void) fprintf(stderr,
! "%s: warning: renouncing setuid due to nonstandard `%s' in environment\n",
progname, reason);
}
*** cnpatch/old/relay/sh/inews Tue Jan 16 17:58:42 1990
--- relay/sh/inews Wed Apr 4 23:59:38 1990
***************
*** 249,253 ****
echo 'default %s') |
sed -n "1{s/^[^ ]*[ ][ ]*//
! s/%s/` echo $ng | tr . - `/p;q;}" \
>$modroute
moderator="`cat $modroute `"
--- 249,253 ----
echo 'default %s') |
sed -n "1{s/^[^ ]*[ ][ ]*//
! s/%s/` echo $ng | tr . - `/;p;q;}" \
>$modroute
moderator="`cat $modroute `"
Files that are new:
new dbz/Makefile (patch can't create, so diff against null):
Index: dbz/Makefile
*** cnpatch/old/dbz/Makefile Sat Apr 14 20:29:03 1990
--- dbz/Makefile Thu Apr 12 17:13:39 1990
***************
*** 0 ****
--- 1,156 ----
+ COPTS = -O
+ FLAGS = -I../include
+ # -lc before libcnews.a so we get fread etc. from system
+ DBMLIBS = -lc ../libcnews.a
+ RFC = -DHAVERFCIZE
+ DEBUG = -DDBZDEBUG
+ CFLAGS = $(COPTS) $(FLAGS)
+ LINTFLAGS = -h $(FLAGS) $(DEBUG) $(RFC)
+ LDFLAGS =
+
+ # database sizes for performance tests, regression, and regression prime-find
+ TSIZE=12007
+ RSIZE=4019
+ RPSIZE=3012
+
+ # history files for regression and performance tests
+ RHIST=hist3.3
+ R2HIST=hist10
+ THIST=hist13
+
+ it: dbz.o
+
+ all: dbz.o dbz
+
+ u: dbz.o
+ ar ruv ../libcnews.a dbz.o
+ cmp dbz.h ../h/dbz.h
+
+ t: tdbz fake
+
+ lint:
+ lint $(LINTFLAGS) dbzmain.c dbz.c
+
+ rdbz.o: dbz.c
+ cp dbz.c rdbz.c
+ $(CC) $(CFLAGS) $(DEBUG) -DDEFSIZE=$(RSIZE) -c rdbz.c
+ rm rdbz.c
+
+ rdbzmain.o: dbzmain.c
+ cp dbzmain.c rdbzmain.c
+ $(CC) $(CFLAGS) $(RFC) -c rdbzmain.c
+ rm rdbzmain.c
+
+ tdbz.o: dbz.c
+ cp dbz.c tdbz.c
+ $(CC) $(CFLAGS) -DDEFSIZE=$(TSIZE) -c tdbz.c
+ rm tdbz.c
+
+ dbz: dbzmain.o dbz.o
+ $(CC) $(CFLAGS) $(LDFLAGS) dbzmain.o dbz.o -o $@
+
+ tdbz: dbzmain.o tdbz.o
+ $(CC) $(CFLAGS) $(LDFLAGS) dbzmain.o tdbz.o -o $@
+
+ rdbz: rdbzmain.o rdbz.o
+ $(CC) $(CFLAGS) $(LDFLAGS) rdbzmain.o rdbz.o $(DBMLIBS) -o $@
+
+ fake: fake.o random.o
+ $(CC) $(CFLAGS) $(LDFLAGS) fake.o random.o -o $@
+
+ byteflip: byteflip.o
+ $(CC) $(CFLAGS) $(LDFLAGS) byteflip.o -o $@
+
+ hist10: fake
+ fake -t -e 75 10000 >$@
+
+ hist3.3: fake
+ fake -t -e 75 3300 >$@
+
+ hist13: fake
+ fake -t -e 75 13000 >$@
+
+ r: rdbz $(RHIST) $(R2HIST) byteflip getmap revbytes altbytes
+ : 'WARNING: creates about 2MB of debris; do "make rclean" afterward'
+ rm -f dbase dbase[23] dbase.* dbase[23].*
+ test ! -d xx || rmdir xx
+ : crude check of synthetic history file
+ ( sed 25q $(RHIST) ; tail -25 $(RHIST) ) >histjunk
+ cmp histjunk firstlast25
+ rm histjunk
+ : basic tests, exercising as many options as possible
+ cp $(RHIST) dbase
+ mkdir xx
+ chmod -w xx
+ rdbz -E 1000 -0 -M -i -S -u -U -C xx dbase
+ rmdir xx
+ sed '/> 0/d' $(RHIST) >dbase.used
+ test "`cat dbase.used | wc -l`" -eq "`sed -n '2s/ .*//p' dbase.dir`" ;
+ cp $(RHIST) dbase2
+ rdbz -E 1000 -0 -p $(RPSIZE) -t ' ' dbase2
+ cmp $(RHIST) dbase
+ cmp dbase dbase2
+ cmp dbase.dir dbase2.dir
+ cmp dbase.pag dbase2.pag
+ rdbz -E 1000 -0 -c dbase
+ rdbz -E 1000 -0 -c -i -q -M -U dbase
+ : build a database and then add to it
+ sed 1000q $(RHIST) >dbase2
+ sed 1,1000d $(RHIST) >dbase2.add
+ rdbz -E 1000 -0 dbase2
+ rdbz -E 1000 -0 -a dbase2 dbase2.add
+ cmp dbase dbase2
+ cmp dbase.dir dbase2.dir
+ cmp dbase.pag dbase2.pag
+ : build based on existing one, test extraction and readonly files
+ rdbz -E 1000 -0 -f dbase dbase2
+ test "`cat dbase.used | wc -l`" -eq "`awk 'NR==2{print $$1}' dbase2.dir`" ;
+ test "`cat dbase.used | wc -l`" -eq "`awk 'NR==2{print $$2}' dbase2.dir`" ;
+ chmod -w dbase2.dir dbase2.pag
+ rdbz -E 1000 -x dbase2 dbase >dbase.temp
+ cmp dbase.used dbase.temp
+ : try some small case perversions
+ sed 's/\(@[^ ]*\)A/\1a/' dbase >dbase.ick
+ rdbz -E 1000 -x dbase2 dbase.ick >dbase.temp
+ cmp dbase.used dbase.temp
+ sed -n 's/A\([^ ]*@\)/a\1/p' dbase >dbase.ick
+ rdbz -x dbase2 dbase.ick >dbase.temp
+ test ! -s dbase.temp ;
+ rm -f dbase2.dir dbase2.pag
+ : try it without tags, case-insensitive, with case perversions
+ rdbz -E 1000 -0 -p '0 b 1' dbase2
+ tr '[A-M][n-z]' '[a-m][N-Z]' <dbase2 >dbase.ick
+ rdbz -E 1000 -x dbase2 dbase.ick >dbase.temp
+ cmp dbase.used dbase.temp
+ rm -f dbase.temp dbase.ick
+ : test various perversions of byte ordering
+ awk -f revbytes dbase.dir >dbase2.dir
+ chmod +x getmap
+ byteflip `getmap dbase.dir` `getmap dbase2.dir` <dbase.pag >dbase2.pag
+ cp dbase dbase2
+ rdbz -E 1000 -0 -c dbase2
+ awk -f altbytes dbase.dir >dbase2.dir
+ dd conv=swab <dbase.pag >dbase2.pag
+ rdbz -E 1000 -0 -c dbase2
+ cp dbase2 dbase3
+ rdbz -E 1000 -0 -f dbase2 dbase3
+ rdbz -E 1000 -0 -c dbase3
+ test " `getmap dbase2.dir`" = " `getmap dbase3.dir`" ;
+ : test massive overflow, throw in case sensitivity and tag mask
+ cp $(R2HIST) dbase
+ rdbz -E 1000 -0 -p '0 0 7ff00000' dbase
+ rdbz -E 1000 -0 -cq dbase
+ sed 100q dbase | egrep '[aA].* ' | tr aA Aa >dbase.ick
+ rdbz -x dbase dbase.ick >dbase.temp
+ test ! -s dbase.temp ;
+ : success!
+
+ rclean:
+ rm -f dbase dbase[23] dbase.* dbase[23].* fake fake.o random.o
+ rm -f rdbz rdbz.o rdbzmain.o $(RHIST) $(R2HIST) byteflip byteflip.o
+ rm -f histjunk core
+ test ! -d xx || rmdir xx
+
+ clean: rclean
+ rm -f *.o dbz [a-z]dbz [a-z][a-z]dbz junk* PostScript.out
+ rm -f hist* dbase* *.bak mon.out gmon.out core dbm.h
new dbz/README (patch can't create, so diff against null):
Index: dbz/README
*** cnpatch/old/dbz/README Sat Apr 14 20:29:04 1990
--- dbz/README Thu Apr 12 17:14:33 1990
***************
*** 0 ****
--- 1,13 ----
+ This is the new, improved, lemon-freshened :-) dbz.
+
+ Just "make" will get you dbz.o and the dbz program. "make r" runs an
+ extensive set of regression tests; most of the mysterious oddments lying
+ around here are to do with that. "make rclean" cleans up after "make r".
+
+ You probably want to inspect the #ifdef list early in dbz.c before
+ compiling, although the defaults should work all right on most systems.
+
+ If you are not building this as part of C News, you will need to change
+ the -I option in FLAGS in the Makefile to "-I.", and delete the DBMLIBS
+ and RFC lines entirely. That will break some of the regression tests;
+ at some point I'll fix this.
new dbz/altbytes (patch can't create, so diff against null):
Index: dbz/altbytes
*** cnpatch/old/dbz/altbytes Sat Apr 14 20:29:04 1990
--- dbz/altbytes Thu Apr 12 16:34:59 1990
***************
*** 0 ****
--- 1,7 ----
+ NR == 1 {
+ printf "%s %s %s %s %s %s %s %s %s", $1, $2, $3, $4, $5, $6, $7, $8, $9
+ for (i = 10; i <= NF; i += 2)
+ printf " %s %s", $(i+1), $i
+ printf "\n"
+ }
+ NR > 1 { print }
new dbz/byteflip.c (patch can't create, so diff against null):
Index: dbz/byteflip.c
*** cnpatch/old/dbz/byteflip.c Sat Apr 14 20:29:04 1990
--- dbz/byteflip.c Sat Mar 31 19:24:20 1990
***************
*** 0 ****
--- 1,33 ----
+ #include <stdio.h>
+
+ #define MAXWORD 32
+
+ main(argc, argv)
+ int argc;
+ char *argv[];
+ {
+ register int len;
+ int inmap[MAXWORD];
+ int outmap[MAXWORD];
+ char in[MAXWORD];
+ char out[MAXWORD];
+ register int i;
+ register int a;
+
+ a = 1;
+ len = atoi(argv[a++]);
+ if (len > MAXWORD)
+ abort(); /* kind of drastic... */
+ for (i = 0; i < len; i++)
+ inmap[i] = atoi(argv[a++]);
+ if (atoi(argv[a++]) != len)
+ abort();
+ for (i = 0; i < len; i++)
+ outmap[i] = atoi(argv[a++]);
+
+ while (fread(in, 1, len, stdin) == len) {
+ for (i = 0; i < len; i++)
+ out[outmap[i]] = in[inmap[i]];
+ fwrite(out, 1, len, stdout);
+ }
+ }
new dbz/dbz.1 (patch can't create, so diff against null):
Index: dbz/dbz.1
*** cnpatch/old/dbz/dbz.1 Sat Apr 14 20:29:05 1990
--- dbz/dbz.1 Thu Apr 12 18:14:50 1990
***************
*** 0 ****
--- 1,205 ----
+ .TH DBZ 1 "12 April 1990"
+ .BY "C News"
+ .SH NAME
+ dbz \- operate on dbz databases of text
+ .SH SYNOPSIS
+ .B dbz
+ [
+ .BR \- { axc }
+ ] [
+ .B \-t
+ c
+ ] [
+ .B \-l
+ length
+ ] [
+ .BR \- { qiue }
+ ] [
+ .B \-f
+ old
+ ] [
+ .B \-p
+ parms
+ ] database file ...
+ .SH DESCRIPTION
+ .I Dbz
+ is a shell-level interface to the
+ .IR dbz (3z)
+ database routines for indexed access to a text file.
+ .PP
+ The
+ .I database
+ file must be a text file,
+ one line per database record,
+ with the key the first field on the line.
+ The
+ .B \-t
+ option sets the field-separator character; the default is tab.
+ Setting the separator character to NUL (with
+ .BR "\-t\ ''" )
+ makes the whole line the key.
+ Lines must not exceed 1023 bytes in length including the newline;
+ this limit can be increased with the
+ .B \-l
+ option.
+ The limitations and restrictions of
+ .IR dbz (3z)
+ must also be observed.
+ .PP
+ In the absence of options,
+ .I dbz
+ creates a
+ .IR dbz (3z)
+ index for the database;
+ the index comprises files
+ .IB database .pag
+ and
+ .IB database .dir
+ in the same directory.
+ Any previous index is silently overwritten.
+ The
+ .BR \-a ,
+ .BR \-x ,
+ and
+ .B \-c
+ options specify other operations.
+ .PP
+ With
+ .BR \-a ,
+ .I dbz
+ appends lines from the
+ .IR file (s)
+ (standard input if none)
+ to the database, updating both the
+ text file and the indexes.
+ .PP
+ With
+ .BR \-x ,
+ .I dbz
+ reads keys from the
+ .IR file (s)
+ (standard input if none)
+ and prints (on standard output) the corresponding lines, if any,
+ from the database.
+ The input is in the form of database lines, although only the keys are
+ significant.
+ .PP
+ With
+ .BR \-c ,
+ .I dbz
+ checks the database for internal consistency.
+ The
+ .B \-q
+ option causes this check to be done more quickly but less thoroughly
+ (each key is looked up in the index, but no check is made to be sure
+ that the index entry points to the right place).
+ .PP
+ The
+ .B \-i
+ option suppresses the use of
+ .IR dbz (3z)'s
+ .I incore
+ facility.
+ This makes accesses slower, but keeps the files current
+ during updating
+ and reduces
+ startup/shutdown overhead.
+ .PP
+ Normally,
+ .I dbz
+ checks whether a key is already in the database before adding it.
+ The
+ .B \-u
+ option suppresses this check, speeding things up at the expense of safety.
+ .PP
+ A new index is normally created with default size,
+ case mapping, and tagging.
+ The default size is right for 90-100,000 records.
+ The default case mapping is right for RFC822 message-ids.
+ See
+ .IR dbz (3z)
+ for what tagging is about.
+ (Note, these defaults can be changed when
+ .IR dbz (3z)
+ is installed.)
+ .PP
+ If the
+ .B \-f
+ option is given,
+ size, case mapping, and tagging
+ are instead initialized based on the
+ database
+ .IR old .
+ This is mostly useful when
+ creating a new generation of an existing database.
+ (See the description of
+ .I dbzagain
+ in
+ .IR dbz (3z)
+ for details.)
+ .PP
+ If the
+ .B \-p
+ option is given, the
+ .I parms
+ string specifies the size, case mapping, and tagging.
+ If
+ .I parms
+ is a single decimal number,
+ that is taken as the expected number of records
+ in the index, with case mapping and tagging defaulted.
+ Alternatively,
+ .I parms
+ can be three fields\(ema decimal number, a case-mapping code character, and a
+ hexadecimal tag mask\(emseparated by white space.
+ The decimal number is, again, the expected number of records;
+ 0 means ``use the default''.
+ See
+ .IR dbz (3z)
+ for possible choices of case-mapping code,
+ but in particular,
+ .B 0
+ means ``no case mapping''.
+ See
+ .IR dbz (3z)
+ for details on tag masks;
+ 0 means ``use the default''.
+ .PP
+ If the
+ .B \-e
+ option is given, the decimal number in
+ .B \-p
+ is taken to be the exact table size, not the expected number of records,
+ and invocation of
+ .I dbzsize
+ (see
+ .IR dbz (3z))
+ to predict a good size for that number of records is suppressed.
+ .PP
+ The
+ .B \&.pag
+ file is normally 5-6 bytes per record (based on the estimate given to
+ .B \-p
+ or the previous history of the
+ .B \-f
+ database).
+ The
+ .B \&.dir
+ file is tiny.
+ .SH SEE ALSO
+ dbz(3z)
+ .SH HISTORY
+ Written at U of Toronto by Henry Spencer, for the C News project.
+ See
+ .IR dbz (3z)
+ for the history of the underlying database routines.
+ .SH BUGS
+ There are a number of undocumented options with obscure effects,
+ meant for debugging and regression testing of
+ .IR dbz (3z).
+ .PP
+ Permissions for the index files probably ought to be taken from those
+ of the base file.
+ .PP
+ The line-length limit is a blemish, alleviated only slightly by
+ .BR \-l .
new dbz/dbz.3z (patch can't create, so diff against null):
Index: dbz/dbz.3z
*** cnpatch/old/dbz/dbz.3z Sat Apr 14 20:29:05 1990
--- dbz/dbz.3z Thu Apr 12 18:14:20 1990
***************
*** 0 ****
--- 1,509 ----
+ .TH DBZ 3Z "12 April 1990"
+ .BY "C News"
+ .SH NAME
+ dbminit, fetch, store, dbmclose \- somewhat dbm-compatible database routines
+ .br
+ dbzfresh, dbzagain, dbzfetch, dbzstore \- database routines
+ .br
+ dbzsize, dbzincore, dbzdebug \- database routines
+ .SH SYNOPSIS
+ .nf
+ .B #include <dbz.h>
+ .PP
+ .B dbminit(base)
+ .B char *base;
+ .PP
+ .B datum
+ .B fetch(key)
+ .B datum key;
+ .PP
+ .B store(key, value)
+ .B datum key;
+ .B datum value;
+ .PP
+ .B dbmclose()
+ .PP
+ .B dbzfresh(base, size, fieldsep, cmap, tagmask)
+ .B char *base;
+ .B long size;
+ .B int fieldsep;
+ .B int cmap;
+ .B long tagmask;
+ .PP
+ .B dbzagain(base, oldbase)
+ .B char *base;
+ .B char *oldbase;
+ .PP
+ .B datum
+ .B dbzfetch(key)
+ .B datum key;
+ .PP
+ .B dbzstore(key, value)
+ .B datum key;
+ .B datum value;
+ .PP
+ .B dbzsync()
+ .PP
+ .B long
+ .B dbzsize(nentries)
+ .B long nentries;
+ .PP
+ .B dbzincore(newvalue)
+ .PP
+ .B dbzdebug(newvalue)
+ .SH DESCRIPTION
+ These functions provide an indexing system for rapid random access to a
+ text file (the
+ .I base
+ .IR file ).
+ Subject to certain constraints, they are compatible with
+ .IR dbm (3),
+ although they also provide some extensions.
+ .PP
+ In principle,
+ .I dbz
+ stores key-value pairs, where both key and value are arbitrary sequences
+ of bytes, specified to the functions by
+ values of type
+ .IR datum ,
+ typedefed in the header file to be a structure with members
+ .I dptr
+ (a value of type
+ .I char *
+ pointing to the bytes)
+ and
+ .I dsize
+ (a value of type
+ .I int
+ indicating how long the byte sequence is).
+ .PP
+ In practice,
+ .I dbz
+ is more restricted than
+ .IR dbm .
+ A
+ .I dbz
+ database
+ must be an index into a base file,
+ with the database
+ .IR value s
+ being
+ .IR fseek (3)
+ offsets into the base file.
+ Each such
+ .I value
+ must ``point to'' a place in the base file where the corresponding
+ .I key
+ sequence is found.
+ A key can be no longer than
+ .SM DBZMAXKEY
+ (a constant defined in the header file) bytes.
+ No key can be an initial subsequence of another,
+ which in most applications requires that keys be
+ either bracketed or terminated in some way (see the
+ discussion of the
+ .I fieldsep
+ parameter of
+ .IR dbzfresh ,
+ below,
+ for a fine point on terminators).
+ .PP
+ .I Dbminit
+ opens a database,
+ an index into the base file
+ .IR base ,
+ consisting of files
+ .IB base .dir
+ and
+ .IB base .pag
+ which must already exist.
+ (If the database is new, they should be zero-length files.)
+ Subsequent accesses go to that database until
+ .I dbmclose
+ is called to close the database.
+ The base file need not exist at the time of the
+ .IR dbminit ,
+ but it must exist before accesses are attempted.
+ .PP
+ .I Fetch
+ searches the database for the specified
+ .IR key ,
+ returning the corresponding
+ .IR value
+ if any.
+ .I Store
+ stores the
+ .IR key - value
+ pair in the database.
+ .I Store
+ will fail unless the database files are writeable.
+ See below for a complication arising from case mapping.
+ .PP
+ .I Dbzfresh
+ is a variant of
+ .I dbminit
+ for creating a new database with more control over details.
+ Unlike for
+ .IR dbminit ,
+ the database files need not exist:
+ they will be created if necessary,
+ and truncated in any case.
+ .PP
+ .IR Dbzfresh 's
+ .I size
+ parameter specifies the size of the first hash table within the database,
+ in key-value pairs.
+ Performance will be best if
+ .I size
+ is a prime number and
+ the number of key-value pairs stored in the database does not exceed
+ about 75% of
+ .IR size .
+ (The
+ .I dbzsize
+ function, given the expected number of key-value pairs,
+ will suggest a database size that meets these criteria.)
+ Assuming that an
+ .I fseek
+ offset is 4 bytes,
+ the
+ .B .pag
+ file will be
+ .RI 4* size
+ bytes
+ (the
+ .B .dir
+ file is tiny and roughly constant in size)
+ until
+ the number of key-value pairs exceeds about 80% of
+ .IR size .
+ (Nothing awful will happen if the database grows beyond 100% of
+ .IR size ,
+ but accesses will slow down somewhat and the
+ .B .pag
+ file will grow somewhat.)
+ .PP
+ .IR Dbzfresh 's
+ .I fieldsep
+ parameter specifies the field separator in the base file.
+ If this is not
+ NUL (0), and the last character of a
+ .I key
+ argument is NUL, that NUL compares equal to either a NUL or a
+ .I fieldsep
+ in the base file.
+ This permits use of NUL to terminate key strings without requiring that
+ NULs appear in the base file.
+ The
+ .I fieldsep
+ of a database created with
+ .I dbminit
+ is the horizontal-tab character.
+ .PP
+ For use in news systems, various forms of case mapping (e.g. uppercase to
+ lowercase) in keys are available.
+ The
+ .I cmap
+ parameter to
+ .I dbzfresh
+ is a single character specifying which of several mapping algorithms to use.
+ Available algorithms are:
+ .RS
+ .TP
+ .B 0
+ case-sensitive: no case mapping
+ .TP
+ .B B
+ same as
+ .B 0
+ .TP
+ .B NUL
+ same as
+ .B 0
+ .TP
+ .B =
+ case-insensitive: uppercase and lowercase equivalent
+ .TP
+ .B b
+ same as
+ .B =
+ .TP
+ .B C
+ RFC822 message-ID rules, case-sensitive before `@' (with certain exceptions)
+ and case-insensitive after
+ .TP
+ .B ?
+ whatever the local default is, normally
+ .B C
+ .RE
+ .PP
+ Mapping algorithm
+ .B 0
+ (no mapping) is faster than the others and is overwhelmingly the correct
+ choice for most applications.
+ Unless compatibility constraints interfere, it is more efficient to pre-map
+ the keys, storing mapped keys in the base file, than to have
+ .I dbz
+ do the mapping on every search.
+ .PP
+ For historical reasons,
+ .I fetch
+ and
+ .I store
+ expect their
+ .I key
+ arguments to be pre-mapped, but expect unmapped keys in the base file.
+ .I Dbzfetch
+ and
+ .I dbzstore
+ do the same jobs but handle all case mapping internally,
+ so the customer need not worry about it.
+ .PP
+ .I Dbz
+ stores only the database
+ .IR value s
+ in its files, relying on reference to the base file to confirm a hit on a key.
+ References to the base file can be minimized, greatly speeding up searches,
+ if a little bit of information about the keys can be stored in the
+ .I dbz
+ files.
+ This is ``free'' if there are some unused bits in an
+ .I fseek
+ offset,
+ so that the offset can be
+ .I tagged
+ with some information about the key.
+ The
+ .I tagmask
+ parameter of
+ .I dbzfresh
+ allows specifying the location of unused bits.
+ .I Tagmask
+ should be a mask with
+ one group of
+ contiguous
+ .B 1
+ bits.
+ The bits in the mask should
+ be unused (0) in
+ .I most
+ offsets.
+ The bit immediately above the mask (the
+ .I flag
+ bit) should be unused (0) in
+ .I all
+ offsets;
+ .I (dbz)store
+ will reject attempts to store a key-value pair in which the
+ .I value
+ has the flag bit on.
+ Apart from this restriction, tagging is invisible to the user.
+ As a special case, a
+ .I tagmask
+ of 1 means ``no tagging'', for use with enormous base files or
+ on systems with unusual offset representations.
+ .PP
+ A
+ .I size
+ of 0
+ given to
+ .I dbzfresh
+ is synonymous with the local default;
+ the normal default is suitable for tables of 90-100,000
+ key-value pairs.
+ A
+ .I cmap
+ of 0 (NUL) is synonymous with the character
+ .BR 0 ,
+ signifying no case mapping
+ (note that the character
+ .B ?
+ specifies the local default mapping,
+ normally
+ .BR C ).
+ A
+ .I tagmask
+ of 0 is synonymous with the local default tag mask,
+ normally 0x7f000000 (specifying the top bit in a 32-bit offset
+ as the flag bit, and the next 7 bits as the mask,
+ which is suitable for base files up to circa 24MB).
+ Calling
+ .I dbminit(name)
+ with the database files empty is equivalent to calling
+ .IR dbzfresh(name,0,'\et','?',0) .
+ .PP
+ When databases are regenerated periodically, as in news,
+ it is simplest to pick the parameters for a new database based on the old one.
+ This also permits some memory of past sizes of the old database, so that
+ a new database size can be chosen to cover expected fluctuations.
+ .I Dbzagain
+ is a variant of
+ .I dbminit
+ for creating a new database as a new generation of an old database.
+ The database files for
+ .I oldbase
+ must exist.
+ .I Dbzagain
+ is equivalent to calling
+ .I dbzfresh
+ with the same field separator, case mapping, and tag mask as the old database,
+ and a
+ .I size
+ equal to the result of applying
+ .I dbzsize
+ to the largest number of entries in the
+ .I oldbase
+ database and its previous 10 generations.
+ .PP
+ When many accesses are being done by the same program,
+ .I dbz
+ is massively faster if its first hash table is in memory.
+ If an internal flag is 1,
+ an attempt is made to read the table in when
+ the database is opened, and
+ .I dbmclose
+ writes it out to disk again (if it was read successfully and
+ has been modified).
+ .I Dbzincore
+ sets the flag to
+ .I newvalue
+ (which should be 0 or 1)
+ and returns the previous value;
+ this does not affect the status of a database that has already been opened.
+ The default is 0.
+ The attempt to read the table in may fail due to memory shortage;
+ in this case
+ .I dbz
+ quietly falls back on its default behavior.
+ .IR Store s
+ to an in-memory database are not (in general) written out to the file
+ until
+ .IR dbmclose
+ or
+ .IR dbzsync ,
+ so if robustness in the presence of crashes
+ or concurrent accesses
+ is crucial, in-memory databases
+ should probably be avoided.
+ .PP
+ .I Dbzsync
+ causes all buffers etc. to be flushed out to the files.
+ It is typically used as a precaution against crashes or concurrent accesses
+ when a
+ .IR dbz -using
+ process will be running for a long time.
+ It is a somewhat expensive operation,
+ especially
+ for an in-memory database.
+ .PP
+ If
+ .I dbz
+ has been compiled with debugging facilities available (which makes it
+ bigger and a bit slower),
+ .I dbzdebug
+ alters the value (and returns the previous value) of an internal flag
+ which (when 1; default is 0) causes
+ verbose and cryptic debugging output on standard output.
+ .PP
+ Concurrent reading of databases is fairly safe,
+ but there is no (inter)locking,
+ so concurrent updating is not.
+ .PP
+ The database files include a record of the byte order of the processor
+ creating the database, and accesses by processors with different byte
+ order will work, although they will be slightly slower.
+ Byte order is preserved by
+ .IR dbzagain .
+ However,
+ agreement on the size and internal structure of an
+ .I fseek
+ offset is necessary, as is consensus on
+ the character set.
+ .PP
+ An open database occupies three
+ .I stdio
+ streams and their corresponding file descriptors;
+ a fourth is needed for an in-memory database.
+ Memory consumption is negligible (except for
+ .I stdio
+ buffers) except for in-memory databases.
+ .SH SEE ALSO
+ dbz(1), dbm(3)
+ .SH DIAGNOSTICS
+ Functions returning
+ .I int
+ values return 0 for success, \-1 for failure.
+ Functions returning
+ .I datum
+ values return a value with
+ .I dptr
+ set to NULL for failure.
+ .SH HISTORY
+ The original
+ .I dbz
+ was written by
+ Jon Zeeff (zeeff@b-tech.ann-arbor.mi.us).
+ Later contributions by David Butler and Mark Moraes.
+ Extensive reworking,
+ including this documentation,
+ by Henry Spencer (henry@zoo.toronto.edu) as
+ part of the C News project.
+ Hashing function by Peter Honeyman.
+ .SH BUGS
+ The
+ .I dptr
+ members of returned
+ .I datum
+ values point to static storage which is overwritten by later calls.
+ .PP
+ Unlike
+ .IR dbm ,
+ .I dbz
+ will misbehave if an existing key-value pair is `overwritten' by
+ a new
+ .I (dbz)store
+ with the same key.
+ The user is responsible for avoiding this by using
+ .I (dbz)fetch
+ first to check for duplicates;
+ an internal optimization remembers the result of the
+ first search so there is minimal overhead in this.
+ .PP
+ Waiting until after
+ .I dbminit
+ to bring the base file into existence
+ will fail if
+ .IR chdir (2)
+ has been used meanwhile.
+ .PP
+ The RFC822 case mapper implements only a first approximation to the
+ hideously-complex RFC822 case rules.
+ .PP
+ The prime finder in
+ .I dbzsize
+ is not particularly quick.
+ .PP
+ Should implement the
+ .I dbm
+ functions
+ .IR delete ,
+ .IR firstkey ,
+ and
+ .IR nextkey .
+ .PP
+ On C implementations which trap integer overflow,
+ .I dbz
+ will refuse to
+ .I (dbz)store
+ an
+ .I fseek
+ offset equal to the greatest
+ representable
+ positive number,
+ as this would cause overflow in the biased representation used.
+ .PP
+ .I Dbzagain
+ perhaps ought to notice when many offsets
+ in the old database were
+ too big for
+ tagging, and shrink the tag mask to match.
end of patch 14-Apr-1990