mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-31 20:19:34 -05:00
Includes support for update referral for each replicated backend. Reworked replication test to use update referral. Includes major rewrite of response encoding codes (result.c). Includes reworked alias support and eliminates old suffix alias codes (can be emulated using named alias). Includes (untested) support for the Manage DSA IT control. Works in LDAPv2 world. Still testing in LDAPv3 world. Added default referral (test009) test.
808 lines
17 KiB
C
808 lines
17 KiB
C
#include "portable.h"
|
|
|
|
#include <stdio.h>
|
|
#include <limits.h>
|
|
|
|
#include <ac/stdlib.h>
|
|
#include <ac/socket.h>
|
|
#include <ac/string.h>
|
|
#include <ac/ctype.h>
|
|
#include <ac/time.h>
|
|
#include <ac/unistd.h>
|
|
#include <ac/wait.h>
|
|
|
|
#ifdef HAVE_SYS_RESOURCE_H
|
|
#include <sys/resource.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
#include <sys/param.h>
|
|
#endif
|
|
#include <sys/stat.h>
|
|
|
|
#ifdef HAVE_FCNTL_H
|
|
#include <fcntl.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_IO_H
|
|
#include <io.h>
|
|
#endif
|
|
|
|
#include "ldap_defaults.h"
|
|
#include "../slap.h"
|
|
#include "../back-ldbm/back-ldbm.h"
|
|
|
|
static struct dbcache *openchoice(char c, int mode, int verbose, char **fname);
|
|
static void print_entry(FILE *fp, char c, Datum *key, char *klabel, Datum *data, char *dlabel);
|
|
static void free_and_close(struct dbcache *dbc, Datum key, Datum data);
|
|
static void edit_entry(char c, Datum *data);
|
|
static void get_keydata(FILE *fp, char c, Datum *key, Datum *data);
|
|
|
|
static struct dbcache *dbc;
|
|
static LDBM dbp;
|
|
static Backend *be = NULL;
|
|
|
|
int
|
|
main( int argc, char **argv )
|
|
{
|
|
char buf[256];
|
|
Datum savekey, key, data, last;
|
|
char *fname;
|
|
ID id;
|
|
ID_BLOCK *idl;
|
|
Backend *tbe;
|
|
int i;
|
|
char *tailorfile;
|
|
|
|
#ifdef HAVE_BERKELEY_DB2
|
|
DBC *cursorp;
|
|
#endif
|
|
|
|
ldbm_datum_init( savekey );
|
|
ldbm_datum_init( key );
|
|
ldbm_datum_init( data );
|
|
ldbm_datum_init( last );
|
|
|
|
tailorfile = SLAPD_DEFAULT_CONFIGFILE;
|
|
while ( (i = getopt( argc, argv, "d:f:" )) != EOF ) {
|
|
switch ( i ) {
|
|
case 'd': /* turn on debugging */
|
|
ldap_debug = atoi( optarg );
|
|
break;
|
|
|
|
case 'f': /* specify a tailor file */
|
|
tailorfile = strdup( optarg );
|
|
break;
|
|
|
|
default:
|
|
fprintf( stderr,
|
|
"usage: %s [-d level] [-f slapdconfigfile]\n",
|
|
argv[0] );
|
|
exit( -1 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* initialize stuff and figure out which backend we're dealing with
|
|
*/
|
|
|
|
slap_init(SLAP_TOOL_MODE, "ldbmtest");
|
|
read_config( tailorfile );
|
|
slap_startup(-1);
|
|
|
|
while ( 1 ) {
|
|
printf( "dbtest: " );
|
|
|
|
if ( fgets( buf, sizeof(buf), stdin ) == NULL )
|
|
break;
|
|
|
|
switch ( buf[0] ) {
|
|
case 'c': /* create an index */
|
|
fname = NULL;
|
|
if ( (dbc = openchoice( buf[1], LDBM_READER, 0,
|
|
&fname )) != NULL ) {
|
|
printf( "Already exists\n" );
|
|
ldbm_close( dbc->dbc_db );
|
|
break;
|
|
}
|
|
if ( (dbc = openchoice( buf[1], LDBM_WRCREAT, 1,
|
|
&fname )) != NULL ) {
|
|
ldbm_close( dbc->dbc_db );
|
|
}
|
|
break;
|
|
|
|
case 'l': /* lookup somethig in an index */
|
|
if ( (dbc = openchoice( buf[1], LDBM_READER, 1, NULL ))
|
|
== NULL ) {
|
|
continue;
|
|
}
|
|
|
|
get_keydata( stdin, buf[1], &key, NULL );
|
|
data = ldbm_fetch( dbc->dbc_db, key );
|
|
print_entry( stdout, buf[1], &key, "key: ", &data,
|
|
"data:\n" );
|
|
|
|
free_and_close( dbc, key, data );
|
|
break;
|
|
|
|
case 'L': /* get all blocks for a key from an index */
|
|
if ( (dbc = openchoice( buf[1], LDBM_READER, 1, NULL ))
|
|
== NULL ) {
|
|
continue;
|
|
}
|
|
|
|
get_keydata( stdin, buf[1], &key, NULL );
|
|
if ( (idl = idl_fetch( be, dbc, key )) != NULL ) {
|
|
data.dptr = (char *) idl;
|
|
data.dsize = (ID_BLOCK_NMAX(idl) + 1) * sizeof(ID);
|
|
print_entry( stdout, buf[1], &key, "key: ",
|
|
&data, "data:\n" );
|
|
}
|
|
free_and_close( dbc, key, data );
|
|
break;
|
|
|
|
case 't': /* traverse */
|
|
case 'T': /* traverse - keys only */
|
|
if ( (dbc = openchoice( buf[1], LDBM_READER, 1, NULL ))
|
|
== NULL ) {
|
|
perror( "openchoice" );
|
|
continue;
|
|
}
|
|
|
|
savekey.dptr = NULL;
|
|
#ifdef HAVE_BERKELEY_DB2
|
|
for ( key = ldbm_firstkey( dbc->dbc_db, &cursorp );
|
|
key.dptr != NULL;
|
|
key = ldbm_nextkey( dbc->dbc_db, key, cursorp ) )
|
|
#else
|
|
for ( key = ldbm_firstkey( dbc->dbc_db );
|
|
key.dptr != NULL;
|
|
key = ldbm_nextkey( dbc->dbc_db, key ) )
|
|
#endif
|
|
{
|
|
if ( savekey.dptr != NULL )
|
|
ldbm_datum_free( dbc->dbc_db, savekey );
|
|
savekey = key;
|
|
|
|
data = ldbm_fetch( dbc->dbc_db, key );
|
|
|
|
if ( buf[0] == 't' ) {
|
|
print_entry( stdout, buf[1], &key,
|
|
"key: ", &data, "data:\n" );
|
|
} else {
|
|
print_entry( stdout, buf[1], &key,
|
|
"key: ", NULL, NULL );
|
|
}
|
|
|
|
if ( data.dptr != NULL ) {
|
|
ldbm_datum_free( dbc->dbc_db, data );
|
|
}
|
|
}
|
|
if ( savekey.dptr != NULL )
|
|
ldbm_datum_free( dbc->dbc_db, savekey );
|
|
|
|
ldbm_close( dbc->dbc_db );
|
|
break;
|
|
|
|
case 'x': /* delete an entry */
|
|
if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
|
|
== NULL ) {
|
|
continue;
|
|
}
|
|
|
|
get_keydata( stdin, buf[1], &key, NULL );
|
|
|
|
if ( ldbm_delete( dbc->dbc_db, key ) != 0 ) {
|
|
if ( ldbm_errno( dbc->dbc_db ) == 0 ) {
|
|
perror( "ldbm_delete" );
|
|
} else {
|
|
fprintf( stderr, "db_errno %d",
|
|
ldbm_errno( dbc->dbc_db ) );
|
|
}
|
|
}
|
|
|
|
data.dptr = NULL;
|
|
free_and_close( dbc, key, data );
|
|
break;
|
|
|
|
#ifndef HAVE_WINSOCK
|
|
case 'e': /* edit an entry */
|
|
if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
|
|
== NULL ) {
|
|
continue;
|
|
}
|
|
|
|
get_keydata( stdin, buf[1], &key, NULL );
|
|
|
|
data = ldbm_fetch( dbc->dbc_db, key );
|
|
if ( data.dptr == NULL ) {
|
|
if ( ldbm_errno( dbc->dbc_db ) == 0 ) {
|
|
perror( "ldbm_fetch" );
|
|
} else {
|
|
fprintf( stderr, "db_errno %d\n",
|
|
ldbm_errno( dbc->dbc_db ) );
|
|
}
|
|
free_and_close( dbc, key, data );
|
|
break;
|
|
}
|
|
|
|
edit_entry( buf[1], &data );
|
|
|
|
if ( data.dptr == NULL ) {
|
|
if ( ldbm_delete( dbc->dbc_db, key ) != 0 ) {
|
|
perror( "ldbm_delete" );
|
|
}
|
|
} else if ( ldbm_store( dbc->dbc_db, key, data,
|
|
LDBM_REPLACE ) != 0 ) {
|
|
if ( ldbm_errno( dbc->dbc_db ) == 0 ) {
|
|
perror( "ldbm_store" );
|
|
} else {
|
|
fprintf( stderr, "db_errno %d\n",
|
|
ldbm_errno( dbc->dbc_db ) );
|
|
}
|
|
}
|
|
|
|
free_and_close( dbc, key, data );
|
|
break;
|
|
#endif
|
|
|
|
case 'a': /* add an entry */
|
|
if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
|
|
== NULL ) {
|
|
continue;
|
|
}
|
|
|
|
get_keydata( stdin, buf[1], &key, &data );
|
|
|
|
if ( ldbm_store( dbc->dbc_db, key, data, LDBM_INSERT )
|
|
!= 0 ) {
|
|
if ( ldbm_errno( dbc->dbc_db ) == 0 ) {
|
|
perror( "ldbm_store" );
|
|
} else {
|
|
fprintf( stderr, "db_errno %d\n",
|
|
ldbm_errno( dbc->dbc_db ) );
|
|
}
|
|
}
|
|
|
|
free_and_close( dbc, key, data );
|
|
break;
|
|
|
|
case 'i': /* insert an id into an index entry */
|
|
if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
|
|
== NULL ) {
|
|
continue;
|
|
}
|
|
|
|
get_keydata( stdin, buf[1], &key, &data );
|
|
|
|
idl = (ID_BLOCK *) data.dptr;
|
|
for ( id = idl_firstid( idl ); id != NOID;
|
|
id = idl_nextid( idl, id ) ) {
|
|
if ( idl_insert_key( be, dbc, key, id )
|
|
!= 0 ) {
|
|
fprintf( stderr,
|
|
"idl_insert_key (%s) %ld failed\n",
|
|
key.dptr, id );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
free_and_close( dbc, key, data );
|
|
break;
|
|
|
|
case 'b': /* select a backend by suffix */
|
|
printf( "suffix: " );
|
|
fflush( stdout );
|
|
if ( fgets( buf, sizeof(buf), stdin ) == NULL ) {
|
|
exit( 0 );
|
|
} else {
|
|
buf[strlen( buf ) - 1] = '\0';
|
|
}
|
|
(void) dn_normalize_case( buf );
|
|
if ( (tbe = select_backend( buf )) == NULL ) {
|
|
fprintf( stderr, "unknown suffix \"%s\"\n",
|
|
buf );
|
|
} else {
|
|
be = tbe;
|
|
}
|
|
break;
|
|
|
|
case 'B': /* print current suffix */
|
|
if ( be == NULL ) {
|
|
printf( "no current backend\n" );
|
|
} else {
|
|
printf( "current backend has suffix \"%s\"\n",
|
|
be->be_suffix[0] );
|
|
}
|
|
break;
|
|
|
|
case 'C': /* produce concordance of an index */
|
|
if ( (dbc = openchoice( 'i', LDBM_READER, 1, NULL ))
|
|
== NULL ) {
|
|
continue;
|
|
}
|
|
|
|
last.dptr = NULL;
|
|
|
|
#ifdef HAVE_BERKELEY_DB2
|
|
for ( key = ldbm_firstkey( dbp, &cursorp );
|
|
key.dptr != NULL;
|
|
key = ldbm_nextkey( dbp, last, cursorp ) )
|
|
#else
|
|
for ( key = ldbm_firstkey( dbp ); key.dptr != NULL;
|
|
key = ldbm_nextkey( dbp, last ) )
|
|
#endif
|
|
{
|
|
if ( last.dptr != NULL ) {
|
|
ldbm_datum_free( dbp, last );
|
|
}
|
|
last = key;
|
|
printf( "key(%d): (%s)\n", key.dsize,
|
|
key.dptr );
|
|
}
|
|
|
|
free_and_close( dbc, key, last );
|
|
break;
|
|
|
|
default:
|
|
printf( "commands: l<c> => lookup index\n" );
|
|
printf( " L<c> => lookup index (all)\n" );
|
|
printf( " t<c> => traverse index\n" );
|
|
printf( " T<c> => traverse index keys\n" );
|
|
printf( " x<c> => delete from index\n" );
|
|
printf( " e<c> => edit index entry\n" );
|
|
printf( " a<c> => add index entry\n" );
|
|
printf( " c<c> => create index\n" );
|
|
printf( " i<c> => insert ids into index\n" );
|
|
printf( " b => change default backend\n" );
|
|
printf( " B => print default backend\n" );
|
|
printf( "where <c> is a char selecting the index:\n" );
|
|
printf( " c => id2children\n" );
|
|
printf( " d => dn2id\n" );
|
|
printf( " e => id2entry\n" );
|
|
printf( " f => arbitrary file\n" );
|
|
printf( " i => attribute index\n" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
slap_shutdown(-1);
|
|
slap_destroy();
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
static void
|
|
free_and_close( struct dbcache *dbc, Datum key, Datum data )
|
|
{
|
|
ldbm_cache_really_close( be, dbc );
|
|
if ( key.dptr != NULL )
|
|
ldbm_datum_free( dbp, key );
|
|
if ( data.dptr != NULL )
|
|
ldbm_datum_free( dbp, data );
|
|
}
|
|
|
|
static int
|
|
dnid_cmp( const void *a, const void *b )
|
|
{
|
|
return( *(const long int *)a - *(const long int *)b );
|
|
}
|
|
|
|
static char *
|
|
myrealloc( char *p, int size )
|
|
{
|
|
if ( p == NULL )
|
|
return( (char *) malloc( size ) );
|
|
else
|
|
return( (char *) realloc( p, size ) );
|
|
}
|
|
|
|
static void
|
|
get_idlist( FILE *fp, Datum *data )
|
|
{
|
|
char buf[20];
|
|
int i, fd, tty;
|
|
ID_BLOCK *p;
|
|
unsigned int psize, pmax;
|
|
unsigned int nmax, nids;
|
|
|
|
fd = fileno( fp );
|
|
tty = isatty( fd );
|
|
|
|
p = NULL;
|
|
psize = 2 * sizeof(ID);
|
|
pmax = 0;
|
|
nmax = 0;
|
|
nids = 0;
|
|
i = 0;
|
|
while ( 1 ) {
|
|
if ( tty )
|
|
printf( "id? " );
|
|
if ( fgets( buf, sizeof(buf), fp ) == NULL || buf[0] == '\n' )
|
|
break;
|
|
if ( strncmp( buf, "nmax=", 5 ) == 0 ) {
|
|
nmax = atol( buf + 5 );
|
|
continue;
|
|
}
|
|
|
|
if ( psize + sizeof(ID) > pmax ) {
|
|
pmax += BUFSIZ;
|
|
p = (ID_BLOCK *) myrealloc( (char *) p, pmax );
|
|
}
|
|
|
|
if ( strncmp( buf, "nids=0", 6 ) == 0 ) {
|
|
nids = NOID;
|
|
continue;
|
|
}
|
|
|
|
ID_BLOCK_ID(p,i++) = atol( buf );
|
|
psize += sizeof(ID);
|
|
}
|
|
if ( nmax == 0 ) {
|
|
if ( tty ) {
|
|
nmax = i;
|
|
printf( "%d IDs entered. Max number of ids? [%d] ", i,
|
|
i );
|
|
if ( fgets( buf, sizeof(buf), fp ) != NULL &&
|
|
isdigit( (unsigned char) buf[0] ) ) {
|
|
nmax = atol( buf );
|
|
}
|
|
} else {
|
|
nmax = i;
|
|
}
|
|
}
|
|
if ( i > 0 ) {
|
|
ID_BLOCK_NMAX(p) = nmax;
|
|
if ( nids != 0 ) {
|
|
ID_BLOCK_NIDS(p) = 0;
|
|
ID_BLOCK_ID(p,i) = NOID;
|
|
} else {
|
|
ID_BLOCK_NIDS(p) = i;
|
|
}
|
|
|
|
qsort( (void *) &ID_BLOCK_ID(p, 0), i, sizeof(ID), dnid_cmp );
|
|
}
|
|
|
|
data->dptr = (char *) p;
|
|
data->dsize = (nmax + ID_BLOCK_IDS_OFFSET) * sizeof(ID);
|
|
}
|
|
|
|
static void
|
|
get_entry( FILE *fp, Datum *data )
|
|
{
|
|
char buf[BUFSIZ];
|
|
char *p;
|
|
unsigned int pmax, psize, len;
|
|
int fd;
|
|
|
|
fd = fileno( fp );
|
|
if ( isatty( fd ) )
|
|
printf( "Enter entry, <cr><cr> to end:\n" );
|
|
|
|
p = NULL;
|
|
pmax = psize = 0;
|
|
while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
|
|
len = strlen( buf );
|
|
if ( psize + strlen( buf ) > pmax ) {
|
|
pmax += BUFSIZ;
|
|
p = myrealloc( p, pmax );
|
|
}
|
|
if ( psize == 0 )
|
|
strcpy( p, buf );
|
|
else
|
|
strcat( p, buf );
|
|
psize += len;
|
|
|
|
if ( buf[0] == '\n' )
|
|
break;
|
|
}
|
|
|
|
data->dptr = p;
|
|
data->dsize = psize + 1;
|
|
}
|
|
|
|
#ifndef HAVE_WINSOCK
|
|
static void
|
|
edit_entry( char c, Datum *data )
|
|
{
|
|
int fd, pid;
|
|
char tmpname[20];
|
|
FILE *fp;
|
|
#ifndef HAVE_WAITPID
|
|
WAITSTATUSTYPE status;
|
|
#endif
|
|
|
|
strcpy( tmpname, "/tmp/dbtestXXXXXX" );
|
|
#ifndef HAVE_MKSTEMP
|
|
if ( (fd = open( mktemp( tmpname ), O_RDWR, 0600 )) == -1 ) {
|
|
perror( tmpname );
|
|
return;
|
|
}
|
|
#else
|
|
if ( (fd = mkstemp( tmpname )) == -1 ) {
|
|
perror( tmpname );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
fp = fdopen( fd, "w" );
|
|
print_entry( fp, c, NULL, NULL, data, NULL );
|
|
fflush( fp );
|
|
|
|
pid = fork();
|
|
|
|
if ( pid == -1 ) {
|
|
perror( "fork" );
|
|
return;
|
|
} else if ( pid == 0 ) {
|
|
char *editor;
|
|
|
|
if ( (editor = getenv( "EDITOR" )) == NULL ) {
|
|
editor = LDAP_EDITOR;
|
|
}
|
|
execl( editor, editor, tmpname, NULL );
|
|
perror( "execl" );
|
|
exit( 1 );
|
|
}
|
|
|
|
fclose( fp );
|
|
|
|
#ifdef HAVE_WAITPID
|
|
if ( waitpid( (pid_t) -1, NULL, WAIT_FLAGS ) < 0 )
|
|
#else
|
|
if ( wait3( (pid_t) -1, &status, WAIT_FLAGS, 0 ) < 0 )
|
|
#endif
|
|
{
|
|
perror( "wait" );
|
|
return;
|
|
}
|
|
|
|
if ( (fp = fopen( tmpname, "r" )) == NULL ) {
|
|
perror( tmpname );
|
|
return;
|
|
}
|
|
if ( data->dptr != NULL ) {
|
|
ldbm_datum_free( NULL, *data );
|
|
}
|
|
get_keydata( fp, c, NULL, data );
|
|
fclose( fp );
|
|
unlink( tmpname );
|
|
}
|
|
#endif
|
|
|
|
static struct dbcache *
|
|
openfile( char *name, int namesiz, int mode, int verbose, char c )
|
|
{
|
|
struct dbcache *dbc;
|
|
|
|
if ( name == NULL || *name == '\0' ) {
|
|
if ( c == 'f' ) {
|
|
printf( " file: " );
|
|
if ( fgets( name, namesiz, stdin ) == NULL )
|
|
exit( 0 );
|
|
name[strlen( name ) - 1] = '\0';
|
|
} else {
|
|
printf( " attr: " );
|
|
if ( fgets( name, namesiz, stdin ) == NULL )
|
|
exit( 0 );
|
|
name[strlen( name ) - 1] = '\0';
|
|
}
|
|
}
|
|
|
|
if ( (dbc = ldbm_cache_open( be, name, (c == 'f') ? "" : LDBM_SUFFIX,
|
|
LDBM_READER )) == NULL ) {
|
|
perror( name );
|
|
} else {
|
|
dbp = dbc->dbc_db;
|
|
}
|
|
|
|
return( dbc );
|
|
}
|
|
|
|
static struct dbcache *
|
|
openchoice( char c, int mode, int verbose, char **fname )
|
|
{
|
|
static char name[MAXPATHLEN];
|
|
|
|
switch ( c ) {
|
|
case 'c': /* id2children */
|
|
sprintf( name, "id2children" );
|
|
break;
|
|
case 'd': /* dn2id */
|
|
sprintf( name, "dn2id" );
|
|
break;
|
|
case 'e': /* id2entry */
|
|
sprintf( name, "id2entry" );
|
|
break;
|
|
case 'f': /* arbitrary file */
|
|
case 'i': /* index */
|
|
if ( fname != NULL && *fname != NULL ) {
|
|
strcpy( name, *fname );
|
|
} else {
|
|
name[0] = '\0';
|
|
}
|
|
break;
|
|
default:
|
|
printf( "specify one of [fdeci] to select file\n" );
|
|
return( NULL );
|
|
break;
|
|
}
|
|
if ( fname != NULL ) {
|
|
*fname = name;
|
|
}
|
|
|
|
return( openfile( name, MAXPATHLEN, mode, verbose, c ) );
|
|
}
|
|
|
|
static void
|
|
print_entry(
|
|
FILE *fp,
|
|
char c,
|
|
Datum *key,
|
|
char *klabel,
|
|
Datum *data,
|
|
char *dlabel
|
|
)
|
|
{
|
|
ID id;
|
|
ID_BLOCK *idl;
|
|
unsigned int i;
|
|
char msg[2];
|
|
|
|
if ( data != NULL && data->dptr == NULL ) {
|
|
msg[0] = c;
|
|
msg[1] = '\0';
|
|
|
|
if ( ldbm_errno( dbp ) == 0 )
|
|
perror( msg );
|
|
else
|
|
fprintf( stderr, "%s: db_errno %d\n", msg,
|
|
ldbm_errno( dbp ) );
|
|
return;
|
|
}
|
|
|
|
switch ( c ) {
|
|
case 'd': /* dn2id - key is dn, data is dnid */
|
|
if ( key != NULL )
|
|
fprintf( fp, "%s%s (len %d)\n", klabel, key->dptr,
|
|
key->dsize );
|
|
if ( data != NULL ) {
|
|
SAFEMEMCPY( (char *) &id, data->dptr, sizeof(ID) );
|
|
fprintf( fp, "%s%ld\n", dlabel ? dlabel : "", id );
|
|
}
|
|
break;
|
|
|
|
case 'e': /* id2entry - key is dnid, data is entry */
|
|
if ( key != NULL ) {
|
|
SAFEMEMCPY( (char *) &id, key->dptr, sizeof(ID) );
|
|
fprintf( fp, "%s %ld\n", klabel, id );
|
|
}
|
|
if ( data != NULL ) {
|
|
if ( dlabel ) {
|
|
fprintf( fp, "data length: %d\n", data->dsize );
|
|
fputs( dlabel, fp );
|
|
}
|
|
fputs( data->dptr, fp );
|
|
}
|
|
break;
|
|
|
|
case 'c':
|
|
case 'i': /* index - key is string, data is dnid[] */
|
|
if ( key != NULL )
|
|
fprintf( fp, "%s%s (len %d)\n", klabel, key->dptr,
|
|
key->dsize );
|
|
if ( data != NULL ) {
|
|
idl = (ID_BLOCK *) data->dptr;
|
|
|
|
if ( dlabel )
|
|
fprintf( fp, "%s\tnmax=%ld\n\tncur=%ld\n", dlabel,
|
|
ID_BLOCK_NMAX(idl), ID_BLOCK_NIDS(idl) );
|
|
|
|
if ( ID_BLOCK_INDIRECT( idl ) ) {
|
|
for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) {
|
|
fprintf( fp, "\t%ld\n", ID_BLOCK_ID(idl, i) );
|
|
}
|
|
} else if ( ID_BLOCK_ALLIDS( idl ) ) {
|
|
fprintf( fp, "\tALLIDS (1..%ld)\n",
|
|
ID_BLOCK_NIDS(idl) - 1 );
|
|
} else {
|
|
for ( i = 0; i < ID_BLOCK_NIDS(idl); i++ ) {
|
|
fprintf( fp, "\t%ld\n", ID_BLOCK_ID(idl,i) );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'f': /* arbitrary file - assume key & data are strings */
|
|
if ( key != NULL )
|
|
fprintf( fp, "%s%s\n", klabel, key->dptr );
|
|
if ( data != NULL ) {
|
|
fprintf( fp, "%s%s\n", dlabel ? dlabel : "",
|
|
data->dptr );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fprintf( stderr, "specify [deci] to select a file\n" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
get_keydata( FILE *fp, char c, Datum *key, Datum *data )
|
|
{
|
|
static char kbuf[BUFSIZ], dbuf[BUFSIZ];
|
|
long n;
|
|
int fd, tty;
|
|
|
|
fd = fileno( fp );
|
|
tty = isatty( fd );
|
|
|
|
switch ( c ) {
|
|
case 'd': /* dn2id - key is dn, data is dnid */
|
|
if ( key != NULL ) {
|
|
if ( tty )
|
|
printf( " dn: " );
|
|
if ( fgets( kbuf, sizeof(kbuf), fp ) == NULL ) {
|
|
exit( 0 );
|
|
}
|
|
kbuf[strlen( kbuf ) - 1] = '\0';
|
|
key->dptr = strdup( kbuf );
|
|
key->dsize = strlen( kbuf ) + 1;
|
|
}
|
|
|
|
if ( data != NULL ) {
|
|
if ( tty )
|
|
printf( " dnid: " );
|
|
if ( fgets( dbuf, sizeof(dbuf), fp ) == NULL ) {
|
|
exit( 0 );
|
|
}
|
|
n = atol( dbuf );
|
|
data->dptr = (char *) malloc( sizeof(n) );
|
|
memcpy( data->dptr, (char *) &n, sizeof(n) );
|
|
data->dsize = sizeof(n);
|
|
}
|
|
break;
|
|
|
|
case 'e': /* id2entry - key is dnid, data is entry */
|
|
if ( key != NULL ) {
|
|
if ( tty )
|
|
printf( " dnid: " );
|
|
if ( fgets( kbuf, sizeof(kbuf), fp ) == NULL ) {
|
|
exit( 0 );
|
|
}
|
|
n = atol( kbuf );
|
|
key->dptr = (char *) malloc( sizeof(n) );
|
|
memcpy( key->dptr, (char *) &n, sizeof(n) );
|
|
key->dsize = sizeof(n);
|
|
}
|
|
|
|
if ( data != NULL ) {
|
|
get_entry( fp, data );
|
|
}
|
|
break;
|
|
|
|
case 'c': /* id2children - key is string dnid, data is dnid[] */
|
|
case 'i': /* index - key is string, data is dnid[] */
|
|
if ( key != NULL ) {
|
|
if ( tty )
|
|
printf( " key: " );
|
|
if ( fgets( kbuf, sizeof(kbuf), fp ) == NULL ) {
|
|
exit( 0 );
|
|
}
|
|
kbuf[strlen( kbuf ) - 1] = '\0';
|
|
key->dptr = strdup( kbuf );
|
|
key->dsize = strlen( kbuf ) + 1;
|
|
}
|
|
|
|
if ( data != NULL ) {
|
|
get_idlist( fp, data );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "specify [deci] to select file type\n");
|
|
break;
|
|
}
|
|
}
|
|
|