robert@isgtec.UUCP (Robert Osborne) (06/01/91)
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@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