Dumbdb: string based database library

Robert Osborne robert at isgtec.UUCP
Sat Jun 1 06:12:01 AEST 1991


This is a simple database (sequential searching only) where a list of
null terminated strings is an 'entry'.   It's pretty stupid but for
some applications (probably only mine :-) it really fits the bill.
Undoubtably this will fail to pass The News Administrator @ wolves
standards and I'll get more mail from him accusing me of plagiarism
and telling me not to post trivial code.

Rob.
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 05/31/1991 19:49 UTC by robert at isgtec.UUCP
# Source directory /tmp_mnt/home/joker1/robert/cvs/dumbdb/try
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    633 -rw-rw-r-- Makefile
#    404 -rw-rw-r-- README
#   1758 -rw-rw-r-- tst.c
#   1717 -rw-rw-r-- lock.c
#   3704 -rw-rw-r-- dumbdb.3
#   7713 -rw-rw-r-- dumbdb.c
#    682 -rw-rw-r-- dumbdb.h
#
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
# $Id: Makefile,v 1.10 1991/04/30 19:16:29 robert Exp $
#
install: libdumbdb.a
X	cp libdumbdb.a /usr/local/contrib/lib
X	@-ranlib /usr/local/contrib/lib/libdumbdb.a
X	cp dumbdb.h /usr/local/contrib/src/include
X
tst.install: libdumbdb.a
X	cp libdumbdb.a $(HOME)/cvs/toBB/$(MACHINE)
X	@-ranlib  $(HOME)/cvs/toBB/$(MACHINE)/libdumbdb.a
X	cp dumbdb.h $(HOME)/cvs/toBB/$(MACHINE)
X
libdumbdb.a: dumbdb.o lock.o
X	ar cr libdumbdb.a dumbdb.o lock.o
X	@-ranlib libdumbdb.a
X	
tst: tst.o dumbdb.o lock.o
X	$(CC) -o tst tst.o dumbdb.o lock.o
X
lock: lock.c
X	$(CC) -DTEST_LOCK -g -o lock lock.c
X		
clean:
X	rm -rf libdumbdb.a tst.o dumbdb.o lock.o lock tst
SHAR_EOF
chmod 0664 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 633 -eq "$Wc_c" ||
	echo 'Makefile: original size 633, current size' "$Wc_c"
fi
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
	echo 'x - skipping README (File already exists)'
else
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
Dumbdb: Release 1.0
-------------------
X
I place this in the Public Domain.
Should compile on practically anything,  we use it everyday on
X
X	Sun0S, AIX, Ultrix, Irix and Ctix
X
I've played around with it on Dos using Turbo C.
X
If you compile it on a SGI (Irix) note that I defined the symbol
SGI to get around the void * problem.
X
I wrote a man page so it must be reliable :-).
X
Robert Osborne,  May 1991
SHAR_EOF
chmod 0664 README ||
echo 'restore of README failed'
Wc_c="`wc -c < 'README'`"
test 404 -eq "$Wc_c" ||
	echo 'README: original size 404, current size' "$Wc_c"
fi
# ============= tst.c ==============
if test -f 'tst.c' -a X"$1" != X"-c"; then
	echo 'x - skipping tst.c (File already exists)'
else
echo 'x - extracting tst.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'tst.c' &&
#include <stdio.h>
#include "dumbdb.h"
X
char *entry1[] = { "entry1 key", "value1", "value2", "value3" };
char *entry2[] = { "entry2 key", "value1", "value2", "value3" };
char *entry3[] = { "entry2 key", "value1", "value2", "value3" };
char *entry4[] = { "entry2 key", "value1", "value2", "value3" };
char *entry5[] = { "entry2 key", "value1", "value2", "value3" };
X
main()
{
X	FILE *fp;
X	dumbDB stuff;
X	int ret;
X	char buffer[3000];
X	char *argv[10];
X	int i;
X
X	printf("opening...");
X	stuff = open_dumbdb("dumb", "U");
X	dumbdb_add_entry(stuff, 4, entry1);
X	dumbdb_add_entry(stuff, 4, entry2);
X	dumbdb_add_entry(stuff, 4, entry3);
X	ret = dumbdb_first_entry(stuff, buffer, 4, argv);
X	i = 0;
X	while( ret != -1 ) {
X		printf("[%d]<%s><%s><%s><%s>\n", i++,
X				argv[0], argv[1], argv[2], argv[3]);
X		ret = dumbdb_next_entry(stuff, buffer, 4, argv);
X	}
X	ret = dumbdb_first_entry(stuff, buffer, 4, argv);
X	dumbdb_add_entry(stuff, 4, entry4);
X	dumbdb_add_entry(stuff, 4, entry5);
X	ret = dumbdb_first_entry(stuff, buffer, 4, argv);
X	i = 0;
X	while( ret != -1 ) {
X		printf("[%d]<%s><%s><%s><%s>\n", i++,
X				argv[0], argv[1], argv[2], argv[3]);
X		ret = dumbdb_next_entry(stuff, buffer, 4, argv);
X	}
X	close_dumbdb(stuff);
X	stuff = open_dumbdb("dumb", "U");
X	ret = dumbdb_first_entry(stuff, buffer, 4, argv);
X	i = 0;
X	while( ret != -1 ) {
X		printf("[%d]<%s><%s><%s><%s>\n", i++,
X				argv[0], argv[1], argv[2], argv[3]);
X		ret = dumbdb_next_entry(stuff, buffer, 4, argv);
X	}
X	close_dumbdb(stuff);
X	stuff = open_dumbdb("dumb", "U");
X	ret = dumbdb_find_and_replace(stuff, buffer, 4, argv);
X	i = 0;
X	while( ret != -1 ) {
X		printf("[%d]<%s><%s><%s><%s>\n", i++,
X				argv[0], argv[1], argv[2], argv[3]);
X		ret = dumbdb_next_entry(stuff, buffer, 4, argv);
X	}
X	close_dumbdb(stuff);
}
SHAR_EOF
chmod 0664 tst.c ||
echo 'restore of tst.c failed'
Wc_c="`wc -c < 'tst.c'`"
test 1758 -eq "$Wc_c" ||
	echo 'tst.c: original size 1758, current size' "$Wc_c"
fi
# ============= lock.c ==============
if test -f 'lock.c' -a X"$1" != X"-c"; then
	echo 'x - skipping lock.c (File already exists)'
else
echo 'x - extracting lock.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'lock.c' &&
/*
** Lock 'file' using a 'file'.lck protocol.
**
** This is public domain.
** Robert Osborne.
**
** $Id: lock.c,v 1.1 1991/04/30 19:16:26 robert Exp $
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
X
lock_file(path, oldest, sec)
X	char *path;				/* file we want to 'lock' */
X	unsigned int oldest;	/* delete file if older than oldest */
X	unsigned int sec;		/* seconds we are willing to wait */
{
X	char lpath[1024];
X	int locked = 0;
X	struct stat buf;
X	time_t age = 0;
X	FILE *fp;
X	
X	sprintf(lpath, "%s.lck", path);
X	
X	while( ! locked )
X	{
X		if( stat(lpath, &buf) == -1 )
X		{
X			if( (fp = fopen(lpath, "w")) == (FILE *) 0 )
X			{
X				return 0;
X			}
X			fclose(fp);
X			return 1;
X		}
X
X		/* get the age of file */
X		if( age == 0 )
X		{
X			age = time((long *)0) - buf.st_mtime;
X		}
X
#ifdef TEST_LOCK
X		printf("age=%ld\n", age);
#endif
X		if( age > oldest )
X		{
X			unlink(lpath);
X			continue;
X		}
X		
X		if( sec == 0 ) break;
X		sleep(1);
X		sec--;
X		age++;
X	}
X	return locked;
}
X
unlock_file(path)
X	char *path;				/* file we want to 'unlock' */
{
X	char lpath[1024];
X	struct stat buf;
X	
X	sprintf(lpath, "%s.lck", path);
X	unlink(lpath);
}
#ifdef TEST_LOCK
main(argc,argv)
X	int argc;
X	char *argv[];
{
X	extern char *optarg;
X	extern int optind;
X	int c;
X	int age = 100;
X	int sec = 2;
X
X	while((c=getopt(argc, argv, "?Hs:a:LU")) != EOF ) {
X		switch(c) {
X		case 's':
X			sec = atoi(optarg);
X			break;
X		case 'a':
X			age = atoi(optarg);
X			break;
X		case 'L':
X			if( lock_file("test", age, sec) )
X				printf("lock success\n");
X			else
X				printf("lock failed\n");
X			break;
X		case 'U':
X			unlock_file("test");
X			break;
X		default:
X			fprintf(stderr, "usage: %s [ -s seconds -a age]  -L | -U\n",
X					argv[0]);
X		}
X	}
X
}
#endif
SHAR_EOF
chmod 0664 lock.c ||
echo 'restore of lock.c failed'
Wc_c="`wc -c < 'lock.c'`"
test 1717 -eq "$Wc_c" ||
	echo 'lock.c: original size 1717, current size' "$Wc_c"
fi
# ============= dumbdb.3 ==============
if test -f 'dumbdb.3' -a X"$1" != X"-c"; then
	echo 'x - skipping dumbdb.3 (File already exists)'
else
echo 'x - extracting dumbdb.3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'dumbdb.3' &&
.\"
.\"######################################################
.\"#							#
.\"# File: dumbdb.man					#
.\"# Purpose:						#
.\"#	Man for dumbdb database.			#
.\"#							#
.\"# Author: Robert Osborne				#
.\"#							#
.\"# 	This is Public Domain!  So There.		#
.\"#							#
.\"# $Id: dumbdb.3,v 1.1 1991/05/31 19:20:25 robert Exp $
.\"######################################################
.\"
.TH dumbdb 3 "31 May 1991" "ISG Technologies" Local
.SH NAME
open_dumbdb, close_dumbdb, dumbdb_first_entry, dumbdb_next_entry,
dumbdb_find_first, dumbdb_find_next, dumbdb_add_entry, dumbdb_delete_entries,
dumbdb_find_and_replace, dumbdb - dumb strings database
.SH SYNOPSIS
.nf
.ta 1.0i 2.25i
X
#include	\fB"dumbdb.h"\fR
X
dumbDB	\fBopen_dumbdb\fR	(\fIchar\fR *path, \fIchar\fR *mode)
int	\fBclose_dumbdb\fR	(\fIdumbDB\fR db)
int	\fBdumbdb_first_entry\fR	(\fIdumbDB\fR db, \fIchar\fR *buffer,
X		\fIint\fR argc, \fIchar\fR *argv[])
int	\fBdumbdb_next_entry\fR	(\fIdumbDB\fR db, \fIchar\fR *buffer,
X		\fIint\fR argc, \fIchar\fR *argv[])
int	\fBdumbdb_find_first\fR	(\fIdumbDB\fR db, \fIchar\fR *buffer,
X		\fIint\fR argc, \fIchar\fR *argv[], char *found[])
int	\fBdumbdb_find_next\fR	(\fIdumbDB\fR db, \fIchar\fR *buffer,
X		\fIint\fR argc, \fIchar\fR *argv[], char *found[])
int	\fBdumbdb_add_entry\fR	(\fIdumbDB\fR db,
X		\fIint\fR argc, \fIchar\fR *argv[])
int	\fBdumbdb_delete_entries\fR	(\fIdumbDB\fR db,
X		\fIint\fR argc, \fIchar\fR *argv[])
int	\fBdumbdb_find_and_replace\fR (\fIdumbDB\fR db,
X		\fIint\fR argc, \fIchar\fR *search[], \fIchar\fR *replace[])
X
.SH DESCRIPTION
These functions group together null\-terminated strings in
a database.   Each group must have the same number of strings (ie.
\fIargc\fR must be constant for an individual \fIdumbdb\fR).  This database is
slow (all searches are sequential) and has limited functionality
but it exactly solved the problem I was facing at the time.
.LP
The null is actually written to the file.  For writing a \fBNull\fR string is
treated as "",  for searching a \fBNull\fR matches everything while "" only
matches an empty string.
.LP
\fIbuffer\fR should be declared using the constant  \fBDUMBDB_MAXENTRY\fR.
The maximum
number of null-terminated strings a group can contain is defined by
\fBDUMBDB_MAXFIELDS\fR.   If these values are too small you should probably
look for
a different database.
.TP
\fBopen_dumbdb\fR
\fIpath\fR is the path to the database. \fImode\fR can be "U" for
\fBupdate\fR or "R" for
\fBread\fR.  Note that the string ".lck" is appended to path when
\fBupdate\fRing;
take this into account on systems where this matters.
.TP
\fBclose_dumbdb\fR
free the \fIdumbdb\fR handle,  releases any lock made by \fImode\fR "U".
.TP
\fBdumbdb_first_entry\fR
returns \fIargv\fR filled with the first item in the database.  The actual
strings are placed into \fIbuffer\fR, \fIargv\fR will point into \fIbuffer\fR.
.TP
\fBdumbdb_next_entry\fR
returns \fIargv\fR filled with the next entry in the database.
.TP
\fBdumbdb_find_first\fR
like \fBdumbdb_first_entry\fR except the first entry that compares equal to
\fIargv\fR is returned in \fIfound\fR.
.TP
\fBdumbdb_find_next\fR
returns \fIfound\fR filled with the next entry in the database
that compares equal to
\fIargv\fR.
.TP
\fBdumbdb_add_entry\fR
\fIappends\fR the database with strings in \fIargv\fR.
.TP
\fBdumbdb_delete_entries\fR
delete all entries that match \fIargv\fR.
\fBdumbdb_find_and_replace\fR 
find the entry matching \fIsearch\fR and put \fIreplace\fR there
.SH BUGS
The lock time of the database is a constant, it should be setable.
The argument \fIargc\fR is extraneous, it should be an argument
to \fBopen_dumbdb\fR.
.SH AUTHOR
Robert Osborne, ISG Technologies, 31 May 1991.
SHAR_EOF
chmod 0664 dumbdb.3 ||
echo 'restore of dumbdb.3 failed'
Wc_c="`wc -c < 'dumbdb.3'`"
test 3704 -eq "$Wc_c" ||
	echo 'dumbdb.3: original size 3704, current size' "$Wc_c"
fi
# ============= dumbdb.c ==============
if test -f 'dumbdb.c' -a X"$1" != X"-c"; then
	echo 'x - skipping dumbdb.c (File already exists)'
else
echo 'x - extracting dumbdb.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'dumbdb.c' &&
/*
** Dumbdb:
**  A stupid string based database.  It's slow, it's useless.
**  But it does what I want it to.
**
**	This is public domain.
**	Robert Osborne, May 1991
**
**	$Id: dumbdb.c,v 1.5 1991/04/30 19:16:31 robert Exp $
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef __TURBOC__
#include <sys/param.h>
#include <malloc.h>
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN 512
#endif
#include "dumbdb.h"
X
#define VALID_DUMBDB(ptr) ((ptr) != 0)
X
typedef struct dumbdb {
X	FILE *fp;
X	char *mode;
X	char *path[MAXPATHLEN];
} dumbdb;
X
#define STREQ(a,b) (!strcmp((a),(b)))
dumbDB
open_dumbdb(path,mode)
X	char *path;	/* full path to the dumbdb */
X	char *mode; /* mode "R","U" */
{
X	FILE *fp;
X	dumbdb *ret;
X	struct stat statbuf;
X
X	ret = (dumbdb *)malloc(sizeof(dumbdb));
X	if( ! ret )
X		return (dumbDB) 0;
X
X	strcpy(ret->path,path);
X	if( STREQ(mode,"R") )
X	{
X		ret->mode = "r";
X	}
X	else if( STREQ(mode,"U") )
X	{
X		ret->mode = "a+";
X	}
X	else
X	{
X		free(ret);
X		return (dumbDB) 0;
X	}
X
X	if( *ret->mode == 'a' && !lock_file(ret->path, 240, 5) )
X	{
X		free(ret);
X		return (dumbDB) 0;
X	}
X	
X	ret->fp = fopen(path, ret->mode);
X	if( ret->fp == (FILE *) 0 )
X	{
X		free(ret);
X		return (dumbDB) 0;
X	}
X	strcpy(ret->path, path);
X
X
X	return ret;
}
X
int
close_dumbdb(db)
X	dumbDB db;
{
X	dumbdb *dbp = (dumbdb *) db;
X	int ret;
X	char editpath[MAXPATHLEN];
X
X	if( ! VALID_DUMBDB(dbp) )
X	{
X		return -1;
X	}
X
X	if( dbp->mode[0] == 'a' )
X	{
X		unlock_file(dbp->path);
X	}
X	ret = fclose(dbp->fp);
X	free(dbp);
X	return ret;
}
X
X
/*
** rewind file, and get first entry
*/
dumbdb_first_entry(db, buffer, argc, argv)
X	dumbDB db;
X	char *buffer;
X	int argc;     /* number of '\0' terminated strings to get */
X	char *argv[]; /* pointers to strings within working buffer */
{
X	dumbdb *dbp = (dumbdb *) db;
X
X	if( ! VALID_DUMBDB(dbp) || argc <= 0 )
X	{
X		return -1;
X	}
X
X	if( fseek(dbp->fp, 0L, 0) != 0 )
X	{
X		return -1;
X	}
X
X	return dumbdb_next_entry(db, buffer, argc, argv);
}
/*
** parse the next entry
*/
int
dumbdb_next_entry(db, buffer, argc,argv)
X	dumbDB db;
X	char *buffer;
X	int argc;     /* number of '\0' terminated strings to get */
X	char *argv[]; /* pointers to strings within working buffer */
{
X	dumbdb *dbp = (dumbdb *) db;
X	int c, count;
X
X	if( ! VALID_DUMBDB(dbp) || argc <= 0 )
X	{
X		return -1;
X	}
X
X	count = 1;
X	argv[0] = buffer;
X	while( (c=fgetc(dbp->fp)) != -1 )
X	{
X		*buffer++ = c;
X		if( c == '\0' )
X		{
X			if( count < argc )
X			{
X				argv[count++] = buffer;
X			}
X			else
X			{
X				return 0;
X			}
X		}
X	}
X	return -1;
}
static int
eq_entry(argc,argv1,argv2)
X	int argc;		/* number of strings to compare */
X	char *argv1[];	/* array of strings or null pointers */
X	char *argv2[];	/* db entry to compare no modifiers */
{
X	int i;
X
X	for(i=0; i<argc; i++)
X	{
X		if( argv1[i] == (char *) 0 )
X		{
X			continue;
X		}
X		if( STREQ(argv1[i],argv2[i]) )
X		{
X			continue;
X		}
X		return 0;
X	}
X	return 1;
}
/*
** find a entry that matches the given fields
*/
int
dumbdb_find_first(db,buffer,argc,argv,found)
X	dumbDB db;
X	char *buffer;
X	int argc;     /* number of '\0' terminated strings to add */
X	char *argv[]; /* pointers to strings to add */
X	char *found[]; /* pointer to found strings */
{
X	dumbdb *dbp = (dumbdb *) db;
X	int ret;
X
X	if( ! VALID_DUMBDB(dbp) || argc <= 0 )
X	{
X		return -1;
X	}
X
X	ret = dumbdb_first_entry(db, buffer, argc, found);
X	while( ret == 0 )
X	{
X		if( eq_entry(argc, argv, found) )
X		{
X			return(0);
X		}
X		ret = dumbdb_next_entry(db, buffer, argc, found);
X	}
X	return -1;
}
int
dumbdb_find_next(db,buffer,argc,argv,found)
X	dumbDB db;
X	char *buffer;
X	int argc;     /* number of '\0' terminated strings to add */
X	char *argv[]; /* pointers to strings to add */
X	char *found[]; /* pointer to found strings */
{
X	dumbdb *dbp = (dumbdb *) db;
X	int ret;
X
X	if( ! VALID_DUMBDB(dbp) || argc <= 0 )
X	{
X		return -1;
X	}
X
X	ret = dumbdb_next_entry(db, buffer, argc, found);
X	while( ret == 0 )
X	{
X		if( eq_entry(argc, argv, found) )
X		{
X			return(0);
X		}
X		ret = dumbdb_next_entry(db, buffer, argc, found);
X	}
X	return -1;
}
/*
** add an entry to the end of the list
** NB: dumbdb_find_next or dumbdb_next_entry won't work
**     without a intervening call to dumbdb_first_entry or
**     dumbdb_find_first.
*/
int
dumbdb_add_entry(db,argc,argv)
X	dumbDB db;
X	int argc;     /* number of '\0' terminated strings to add */
X	char *argv[]; /* pointers to strings to add */
{
X	dumbdb *dbp = (dumbdb *) db;
X
X	if( ! VALID_DUMBDB(dbp) || argc <= 0 )
X	{
X		return -1;
X	}
X	if( ! dbp->mode[0] == 'a' )
X	{
X		return -1;
X	}
X
X	if( fseek(dbp->fp, 0L, 2) != 0 )
X	{
X		return -1;
X	}
X
X	while( argc )
X	{
X		if( *argv != (char *) 0 )
X		{
X			fputs(*argv, dbp->fp);
X		}
X		fputc('\0', dbp->fp);
X		argv++;
X		argc--;
X	}
X	return 0;
}
/*
** Acts like a filter and removes all entries that match the
** given entry from the db.
** NB: dumbdb_find_next or dumbdb_next_entry won't work
**     without a intervening call to dumbdb_first_entry or
**     dumbdb_find_first.
*/
int
dumbdb_delete_entries(db,argc,argv)
X	dumbDB db;
X	int argc;     /* number of '\0' terminated strings to add */
X	char *argv[]; /* pointers to entry pattern to delete */
{
X	dumbdb *dbp = (dumbdb *) db;
X	FILE *newfp;
X	int count = 0;
X	int ret;
X	int i;
X	char editpath[MAXPATHLEN];
X	char buffer[DUMBDB_MAXENTRY];
X	char *found[DUMBDB_MAXFIELDS];
X
X	if( ! VALID_DUMBDB(dbp) || argc <= 0 )
X	{
X		return count;
X	}
X	if( ! dbp->mode[0] == 'a' )
X	{
X		return count;
X	}
X	sprintf(editpath, "%s.new", dbp->path);
X	if( (newfp = fopen(editpath, "w+")) == (FILE *) 0 )
X	{
X		return count;
X	}
X
X	ret = dumbdb_first_entry(db, buffer, argc, found);
X	while( ret == 0 )
X	{
X		if( ! eq_entry(argc, argv, found) )
X		{
X			for(i=0; i<argc; i++)
X			{
X				if( found[i] != (char *) 0 )
X				{
X					fputs(found[i], newfp);
X				}
X				fputc('\0', newfp);
X			}
X		}
X		else
X		{
X			count++;
X		}
X		ret = dumbdb_next_entry(db, buffer, argc, found);
X	}
X
X	if( count > 0 )
X	{
X		fclose(dbp->fp);
X		dbp->fp = newfp;
X		unlink(dbp->path);
#ifdef __TURBOC__
X		rename(editpath, dbp->path);
#else
X		link(editpath, dbp->path);
X		unlink(editpath);
#endif
X	}
X	else
X	{
X		fclose(newfp);
X		unlink(editpath);
X	}
X	return count;
}
/*
** Finds the first entry that matchs the search and replaces it.
** NB: dumbdb_find_next or dumbdb_next_entry won't work
**     without a intervening call to dumbdb_first_entry or
**     dumbdb_find_first.
*/
int
dumbdb_find_and_replace(db,argc,search,replace)
X	dumbDB db;
X	int argc;     /* number of '\0' terminated strings to add */
X	char *search[]; /* pointers to entry pattern to delete */
X	char *replace[]; /* pointers to entry pattern to delete */
{
X	dumbdb *dbp = (dumbdb *) db;
X	FILE *newfp;
X	int ret, i, replaced = 1;
X	char editpath[MAXPATHLEN];
X	char buffer[DUMBDB_MAXENTRY];
X	char *found[DUMBDB_MAXFIELDS];
X
X	if( ! VALID_DUMBDB(dbp) || argc <= 0 )
X	{
X		return replaced;
X	}
X	if( ! dbp->mode[0] == 'a' )
X	{
X		return replaced;
X	}
X	sprintf(editpath, "%s.new", dbp->path);
X	if( (newfp = fopen(editpath, "w+")) == (FILE *) 0 )
X	{
X		return replaced;
X	}
X
X	ret = dumbdb_first_entry(db, buffer, argc, found);
X	while( ret == 0 )
X	{
X		if( !replaced || ! eq_entry(argc, search, found) )
X		{
X			for(i=0; i<argc; i++)
X			{
X				if( found[i] != (char *) 0 )
X				{
X					fputs(found[i], newfp);
X				}
X				fputc('\0', newfp);
X			}
X		}
X		else
X		{
X			replaced = 0;
X			for(i=0; i<argc; i++)
X			{
X				if( replace[i] != (char *) 0 )
X				{
X					fputs(replace[i], newfp);
X				}
X				fputc('\0', newfp);
X			}
X		}
X		ret = dumbdb_next_entry(db, buffer, argc, found);
X	}
X
X	if( !replaced )
X	{
X		fclose(dbp->fp);
X		dbp->fp = newfp;
X		unlink(dbp->path);
#ifdef __TURBOC__
X		rename(editpath, dbp->path);
#else
X		link(editpath, dbp->path);
X		unlink(editpath);
#endif
X	}
X	else
X	{
X		fclose(newfp);
X		unlink(editpath);
X	}
X	return replaced;
}
SHAR_EOF
chmod 0664 dumbdb.c ||
echo 'restore of dumbdb.c failed'
Wc_c="`wc -c < 'dumbdb.c'`"
test 7713 -eq "$Wc_c" ||
	echo 'dumbdb.c: original size 7713, current size' "$Wc_c"
fi
# ============= dumbdb.h ==============
if test -f 'dumbdb.h' -a X"$1" != X"-c"; then
	echo 'x - skipping dumbdb.h (File already exists)'
else
echo 'x - extracting dumbdb.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'dumbdb.h' &&
/*
X *	File:	dumbdb.h
X *
X *	In the Public Domain.
X *  Robert Osborne, May 1991
X *
X * $Id$
X */
X
#ifndef DUMBDB_H
#define DUMBDB_H
X
#define DUMBDB_MAXENTRY 5000
#define DUMBDB_MAXFIELDS  50
#ifdef SGI
typedef char *dumbDB;
#else
typedef void *dumbDB;
#endif
#ifdef __STDC__
dumbDB open_dumbdb(char *path,char *mode);
int close_dumbdb(dumbDB db);
int dumbdb_first_entry(dumbDB db, char *buffer, int argc, char *argv[]);
int dumbdb_next_entry(dumbDB db, char *buffer, int argc, char *argv[]);
int dumbdb_add_entry(dumbDB db, int argc,char *argv[]);
#else
dumbDB open_dumbdb();
int close_dumbdb();
int dumbdb_first_entry();
int dumbdb_next_entry();
int dumbdb_add_entry();
#endif
X
#endif
SHAR_EOF
chmod 0664 dumbdb.h ||
echo 'restore of dumbdb.h failed'
Wc_c="`wc -c < 'dumbdb.h'`"
test 682 -eq "$Wc_c" ||
	echo 'dumbdb.h: original size 682, current size' "$Wc_c"
fi
exit 0



More information about the Alt.sources mailing list