jfh@rpp386.cactus.org (John F. Haugh II) (01/14/90)
[ The preceding version of this thing was cancelled after someone noticed it didn't compile. This is what I get for adding "one last feature" at the last moment and then failing to recompile ... ] This is the beta-test release of my DBM command line toolkit. There are no man pages [ what do you expect, this is a beta release ]. You are expected to read the source code for answers ;-) There are several command line interface programs in here. They are: dbmstore - store a record under a key in a database dbmfetch - fetch a record with a key from a database dbmedit - fetch a record, call an editor, and write the record back. dbmdelete - remove a record using a key from a database dbmfirstkey - return the first key in the database, a logical rewind. dbmnextkey - return the key following the supplied key. dbmkeys - list all of the keys in the database. The general syntax is <command name> <database name> <database key> All of the commands, except dbmfirstkey, expect a key to be provided on the command line. Data is either output on standard output, or input from standard input. There are not options to read or write to or from files. Both data and keys may contain octal-escapes for non-printing characters. The DBM editor will edit dbm files which contain binary data. And here is the source code ... ---- cut here ---- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Makefile # dbmdelete.c # dbmstore.c # dbmfetch.c # dbmedit.sh # dbmkeys.c # dbmfrstkey.c # dbmnextkey.c # This archive created: Sat Jan 13 11:45:47 1990 # By: John F. Haugh II (River Parishes Programming, Austin TX) export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else cat << \SHAR_EOF > 'Makefile' # @(#)Makefile 1.2 01:23:12 1/12/90 # # Makefile for dbmtools # # Copyright John F. Haugh II # All rights reserved. # # This software may be copied for non-commercial uses. # Use at your own risk. # #CFLAGS = -g #LDFLAGS = -g CFLAGS = -O LDFLAGS = -s LIBS = -ldbm # The default Make rules can't get a .sh file, and neglect to make # the output read-only in the .c case .sh~.sh: $(GET) $(GFLAGS) -p $< > $*.sh chmod a-w $*.sh .c~.c: $(GET) $(GFLAGS) -p $< > $*.c chmod a-w $*.c FILES = Makefile dbmdelete.c dbmstore.c dbmfetch.c dbmedit.sh \ dbmkeys.c dbmfrstkey.c dbmnextkey.c EXECS = dbmdelete dbmstore dbmfetch dbmedit dbmkeys dbmfirstkey dbmnextkey all: $(EXECS) dbmdelete: dbmdelete.o cc -o dbmdelete $(LDFLAGS) dbmdelete.o $(LIBS) dbmstore: dbmstore.o cc -o dbmstore $(LDFLAGS) dbmstore.o $(LIBS) dbmfetch: dbmfetch.o cc -o dbmfetch $(LDFLAGS) dbmfetch.o $(LIBS) dbmedit: dbmedit.sh cp dbmedit.sh dbmedit chmod +rx dbmedit dbmkeys: dbmkeys.o cc -o dbmkeys $(LDFLAGS) dbmkeys.o $(LIBS) dbmfirstkey: dbmfrstkey.o cc -o dbmfirstkey $(LDFLAGS) dbmfrstkey.o $(LIBS) dbmnextkey: dbmnextkey.o cc -o dbmnextkey $(LDFLAGS) dbmnextkey.o $(LIBS) shar: dbmtools.sh dbmtools.sh: $(FILES) shar $(FILES) > dbmtools.sh clean: rm -f *.o a.out core clobber: clean rm -f $(EXECS) SHAR_EOF fi if test -f 'dbmdelete.c' then echo shar: "will not over-write existing file 'dbmdelete.c'" else cat << \SHAR_EOF > 'dbmdelete.c' /* * Copyright 1990 John F. Haugh II * All rights reserved. * * This software may be reproduced for non-commercial uses. * Use at your own risk. */ /* * @(#)dbmdelete.c 1.1 09:36:19 1/8/90 * * Name: dbmdelete * * Purpose: delete a record from a DBM file * * Description: * dbmdelete is a command line interface to the DBM library * and provides the ability to remove individual records. * * Return Values: * 0 if everything is OK, 1 for everything else */ #include <dbm.h> #include <stdio.h> main (argc, argv) int argc; char **argv; { datum key; /* * Check for proper number of arguments. The first argument is * the name of the database with no .dir or .pag. The second * argument is the literal key to search for, sorry, no binary * keys just yet. */ if (argc != 3) { fprintf (stderr, "usage: dbmdelete database key\n"); exit (1); } /* * Open the named database. It must already exist. */ if (dbminit (argv[1])) { perror (argv[1]); exit (1); } /* * All keys right now are character strings. Point at the * argument and provide its length. */ key.dptr = argv[2]; key.dsize = strlen (argv[2]); /* * Call the low-level DBM library routine to kill off * the record. Report an error if one occurs. */ if (delete (key)) { fprintf (stderr, "%s: can't delete\n", argv[2]); exit (1); } exit (0); } SHAR_EOF fi if test -f 'dbmstore.c' then echo shar: "will not over-write existing file 'dbmstore.c'" else cat << \SHAR_EOF > 'dbmstore.c' /* * Copyright 1990 John F. Haugh II * All rights reserved. * * This software may be reproduced for non-commercial uses. * Use at your own risk. */ /* * @(#)dbmstore.c 1.3 11:45:23 1/13/90 * * Name: dbmstore * * Purpose: store a new record, or update an existing record * * Description: * dbmstore reads a record full of data and stores it in the * database under the supplied key. The record can be either * a completely new record, or a pre-existing record. * * Return Values: * 0 for success, 1 for all errors. */ #include <dbm.h> #include <stdio.h> main (argc, argv) int argc; char **argv; { int c; int len; int i, j; datum value; datum key; char keybuf[BUFSIZ]; char buf[BUFSIZ]; /* * Check the argument. The first argument is the name of the * database, the second is the key to store the record under. * The key may have octal values for characters. */ if (argc != 3) { fprintf (stderr, "usage: dbmstore database key\n"); exit (1); } /* * Open the database, reporting any errors that are found. */ if (dbminit (argv[1])) { perror (argv[1]); exit (1); } /* * Unquote the key. The quoted text is in argv[2] and is * copied one character at a time into keybuf[]. A quoted * character begins with '\' and has three octal digits * following it. */ for (i = j = 0;i < strlen (argv[2]);i++) { if (argv[2][i] == '\\') { c = (((argv[2][i + 1] - '0') << 3) + ((argv[2][i + 2] - '0')) << 3) + (argv[2][i + 3] - '0'); i += 3; } else { c = argv[2][i]; } keybuf[j++] = c; } key.dptr = keybuf; key.dsize = j; /* * Unquotify the input stream. Read from stdin until * EOF is reached, converting any quoted characters as * we go ... */ for (len = 0;len < BUFSIZ && (c = getchar ()) != EOF;len++) { if (c == '\\') { c = ((getchar () - '0') << 6); c += ((getchar () - '0') << 3); c += (getchar () - '0'); } buf[len] = c; } value.dptr = buf; value.dsize = len; /* * Store the new record under the key. If there is an error * report it using the quotified key value to avoid confusion. */ if (store (key, value)) { fprintf (stderr, "%s: can't store\n", argv[2]); exit (1); } exit (0); } SHAR_EOF fi if test -f 'dbmfetch.c' then echo shar: "will not over-write existing file 'dbmfetch.c'" else cat << \SHAR_EOF > 'dbmfetch.c' /* * Copyright 1990 John F. Haugh II * All rights reserved. * * This software may be reproduced for non-commercial uses. * Use at your own risk. */ /* * @(#)dbmfetch.c 1.2 01:23:20 1/12/90 * * Name: dbmfetch * * Purpose: Retrieving a single record from a DBM database * * Description: * dbmfetch retrieves a single record from a DBM database * using the user supplied command line key. * * Return Values: * 0 if the key is found, 1 for all errors. */ #include <dbm.h> #include <stdio.h> #include <ctype.h> main (argc, argv) int argc; char **argv; { int i; datum value; datum key; /* * Count the arguments. First argument is a database name * without .dir or .pag. Second argument is the literal * key used to look up the record. */ if (argc != 3) { fprintf (stderr, "usage: dbmfetch database key\n"); exit (1); } /* * Open the database. It must already exist or an error * is reported. */ if (dbminit (argv[1])) { perror (argv[1]); exit (1); } /* * Initialize the key datum structure and use it to lookup * the desired record in the database. */ key.dptr = argv[2]; key.dsize = strlen (argv[2]); value = fetch (key); /* * See if a value was actually returned, if so, print out * the string itself. It is assumed the string is terminated * with a newline, so one isn't printed. */ if (value.dptr == 0) { fprintf (stderr, "%s: not found\n", argv[2]); exit (1); } for (i = 0;i < value.dsize;i++) { if (! isascii (value.dptr[i]) || (! isprint (value.dptr[i]) && ! isspace (value.dptr[i])) || value.dptr[i] == '\\') printf ("\\%03.3o", value.dptr[i] & 0377); else putchar (value.dptr[i]); } exit (0); } SHAR_EOF fi if test -f 'dbmedit.sh' then echo shar: "will not over-write existing file 'dbmedit.sh'" else cat << \SHAR_EOF > 'dbmedit.sh' # # @(#)dbmedit.sh 1.2 01:23:18 1/12/90 # # Edit a DBM entry # # Copyright 1990 John F. Haugh II # All rights reserved. # # This software may be copied for non-commercial uses. # Use at your own risk. # TEMP=/tmp/dbmedit$$ trap 'rm -f $TEMP ; exit $rc' 0 1 2 3 15 if [ "$EDITOR" = "" ] then EDITOR=/usr/bin/vi fi # # Check for proper number of arguments # if [ $# != 2 ] then echo usage: $0 database key 1>&2 rc=1 exit fi # # Check for the database existing # if [ ! -f $1.dir -o ! -f $1.pag ] then echo $0: The database $1 does not exist 1>&2 rc=1 exit fi # # Get the value from the database and shove the # user into their favorite editor. Ignore the # error return since the key may not exist just # yet and the user wants to create it. # dbmfetch $1 "$2" > $TEMP 2>&1 $EDITOR $TEMP rc=$? if [ $rc != 0 ] then echo $0: Error editing $1 record "$2" 1>&2 exit fi # # Store the value back into the database # dbmstore $1 "$2" < $TEMP rc=$? exit SHAR_EOF fi if test -f 'dbmkeys.c' then echo shar: "will not over-write existing file 'dbmkeys.c'" else cat << \SHAR_EOF > 'dbmkeys.c' /* * Copyright 1990 John F. Haugh II * All rights reserved. * * This software may be reproduced for non-commercial uses. * Use at your own risk. */ /* * @(#)dbmkeys.c 1.2 01:23:22 1/12/90 * * Name: dbmkeys * * Purpose: list all database keys * * Description: * dbmkeys outputs all of the keys in the database. This * can be used to select keys for some operation. * * Return Values: * 0 if no errors are detected, 1 otherwise. */ #include <dbm.h> #include <stdio.h> #include <ctype.h> main (argc, argv) int argc; char **argv; { int i; datum key; /* * Check the arguments. The name of the database must be * given and the database must already exist. */ if (argc != 2) { fprintf (stderr, "usage: dbmkeys database\n"); exit (1); } /* * Open the database and report and error if one occurs. */ if (dbminit (argv[1])) { perror (argv[1]); exit (1); } /* * Walk through the entire database printing out all of the * keys, quoting any special characters as we go. */ for (key = firstkey ();key.dptr != 0;key = nextkey (key)) { for (i = 0;i < key.dsize;i++) { if (! isascii (key.dptr[i]) || (! isprint (key.dptr[i]) && ! isspace (key.dptr[i])) || key.dptr[i] == '\\') printf ("\\%03.3o", key.dptr[i] & 0377); else putchar (key.dptr[i]); } putchar ('\n'); } exit (0); } SHAR_EOF fi if test -f 'dbmfrstkey.c' then echo shar: "will not over-write existing file 'dbmfrstkey.c'" else cat << \SHAR_EOF > 'dbmfrstkey.c' /* * Copyright 1990 John F. Haugh II * All rights reserved. * * This software may be reproduced for non-commercial uses. * Use at your own risk. */ /* * @(#)dbmfrstkey.c 1.2 01:23:21 1/12/90 * * Name: dbmfirstkey * * Purpose: return the first key in the database * * Description: * Returns the first key in a DBM database. This key may * later be used as input to dbmnextkey to return successive * keys from the database. * * Return Values: * 0 if the first key was found, 1 for all other errors. */ #include <dbm.h> #include <stdio.h> #include <ctype.h> main (argc, argv) int argc; char **argv; { int i; datum key; /* * Check the arguments. Must include the name of the database, * which must already exist. */ if (argc != 2) { fprintf (stderr, "usage: dbmfirstkey database\n"); exit (1); } /* * Initialize the database and return an error message if there * is some problem opening the database. */ if (dbminit (argv[1])) { perror (argv[1]); exit (1); } /* * Fetch the first key from the database and return it to the * user. Quote all non-printable characters while you're at it. */ key = firstkey (); for (i = 0;i < key.dsize;i++) { if (! isascii (key.dptr[i]) || (! isprint (key.dptr[i]) && ! isspace (key.dptr[i])) || key.dptr[i] == '\\') printf ("\\%03.3o", key.dptr[i] & 0377); else putchar (key.dptr[i]); } putchar ('\n'); exit (0); } SHAR_EOF fi if test -f 'dbmnextkey.c' then echo shar: "will not over-write existing file 'dbmnextkey.c'" else cat << \SHAR_EOF > 'dbmnextkey.c' /* * Copyright 1990 John F. Haugh II * All rights reserved. * * This software may be reproduced for non-commercial uses. * Use at your own risk. */ /* * @(#)dbmnextkey.c 1.3 11:45:21 1/13/90 * * Name: dbmnextkey * * Purpose: return the next key after the supplied argument * * Description: * dbmnextkey returns the next key in the database after the * supplied argument, or nothing if no key was found. This * can be used to walk through the database one key at a time. * * Return Values: * 0 for success, 1 for all errors */ #include <dbm.h> #include <stdio.h> #include <ctype.h> main (argc, argv) int argc; char **argv; { int i; int j; int c; datum next; datum key; char buf[BUFSIZ]; /* * Check the arguments. The first is the name of a database, * which must already exist. The second is the key to search * for. It may contain quoted characters. */ if (argc != 3) { fprintf (stderr, "usage: dbmfetch database key\n"); exit (1); } /* * Open the database and report any errors which may occur. */ if (dbminit (argv[1])) { perror (argv[1]); exit (1); } /* * Unquote the key. The quoted text is in argv[2] and is * copied one character at a time into buf[]. A quoted * character begins with '\' and has three octal digits * following it. */ for (i = j = 0;i < strlen (argv[2]);i++) { if (argv[2][i] == '\\') { c = (((argv[2][i + 1] - '0') << 3) + ((argv[2][i + 2] - '0')) << 3) + (argv[2][i + 3] - '0'); i += 3; } else { c = argv[2][i]; } buf[j++] = c; } /* * Initialize the key structure. The unquotified key is * now in buf[] and the length is in j. */ key.dptr = buf; key.dsize = j; /* * Get the next key from the database. If the data pointer * is null there are no more keys. */ next = nextkey (key); if (next.dptr == 0) exit (0); /* * Output the new quotified key. */ for (i = 0;i < next.dsize;i++) { if (! isascii (next.dptr[i]) || (! isprint (next.dptr[i]) && ! isspace (next.dptr[i])) || next.dptr[i] == '\\') printf ("\\%03.3o", next.dptr[i] & 0377); else putchar (next.dptr[i]); } exit (0); } SHAR_EOF fi exit 0 # End of shell archive -- John F. Haugh II UUCP: ...!cs.utexas.edu!rpp386!jfh Ma Bell: (512) 832-8832 Domain: jfh@rpp386.cactus.org