diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 11:11:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 11:11:40 +0000 |
commit | 7731832751ab9f3c6ddeb66f186d3d7fa1934a6d (patch) | |
tree | e91015872543a59be2aad26c2fea02e41b57005d /servers/slapd/shell-backends | |
parent | Initial commit. (diff) | |
download | openldap-upstream/2.4.57+dfsg.tar.xz openldap-upstream/2.4.57+dfsg.zip |
Adding upstream version 2.4.57+dfsg.upstream/2.4.57+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'servers/slapd/shell-backends')
-rw-r--r-- | servers/slapd/shell-backends/Makefile.in | 40 | ||||
-rw-r--r-- | servers/slapd/shell-backends/passwd-shell.c | 207 | ||||
-rw-r--r-- | servers/slapd/shell-backends/shellutil.c | 396 | ||||
-rw-r--r-- | servers/slapd/shell-backends/shellutil.h | 123 |
4 files changed, 766 insertions, 0 deletions
diff --git a/servers/slapd/shell-backends/Makefile.in b/servers/slapd/shell-backends/Makefile.in new file mode 100644 index 0000000..d032ead --- /dev/null +++ b/servers/slapd/shell-backends/Makefile.in @@ -0,0 +1,40 @@ +# Makefile.in for shell-backends +# $OpenLDAP$ +## This work is part of OpenLDAP Software <http://www.openldap.org/>. +## +## Copyright 1998-2021 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## <http://www.OpenLDAP.org/license.html>. + +PROGRAMS = passwd-shell + +SRCS = passwd-shell.c shellutil.c +XSRCS = pwd-version.c +OBJS = passwd-shell.o shellutil.o + +LDAP_INCDIR= ../../../include +LDAP_LIBDIR= ../../../libraries + +BUILD_OPT = "--enable-shell" +BUILD_SRV = @BUILD_SHELL@ + +all-local-srv: $(PROGRAMS) + +# create programs also when using modules +depend-mod: depend-yes +all-mod: all-yes +install-mod: install-yes + +passwd-shell: pwd-version.o + $(CC) $(LDFLAGS) -o $@ $(OBJS) pwd-version.o $(LIBS) + +pwd-version.c: $(OBJS) $(LDAP_LIBDEPEND) + @-$(RM) $@ + $(MKVERSION) passwd-shell > $@ diff --git a/servers/slapd/shell-backends/passwd-shell.c b/servers/slapd/shell-backends/passwd-shell.c new file mode 100644 index 0000000..2414431 --- /dev/null +++ b/servers/slapd/shell-backends/passwd-shell.c @@ -0,0 +1,207 @@ +/* passwd-shell.c - passwd(5) shell-based backend for slapd(8) */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 1998-2021 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). + */ + + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/string.h> +#include <ac/unistd.h> + +#include <pwd.h> + +#include <lber.h> +#include <ldap.h> + +#include "shellutil.h" + +static void pwdfile_search LDAP_P(( struct ldop *op, FILE *ofp )); +static struct ldentry *pw2entry LDAP_P(( struct ldop *op, struct passwd *pw )); + +static char tmpbuf[ MAXLINELEN * 2 ]; + + +int +main( int argc, char **argv ) +{ + int c, errflg; + struct ldop op; + + if (( progname = strrchr( argv[ 0 ], '/' )) == NULL ) { + progname = estrdup( argv[ 0 ] ); + } else { + progname = estrdup( progname + 1 ); + } + + errflg = debugflg = 0; + + while (( c = getopt( argc, argv, "d" )) != EOF ) { + switch( c ) { + case 'd': +#ifdef LDAP_DEBUG + ++debugflg; +#else /* LDAP_DEBUG */ + fprintf( stderr, "%s: compile with -DLDAP_DEBUG for debugging\n", + progname ); +#endif /* LDAP_DEBUG */ + break; + default: + ++errflg; + } + } + + if ( errflg || optind < argc ) { + fprintf( stderr, "usage: %s [-d]\n", progname ); + exit( EXIT_FAILURE ); + } + + debug_printf( "started\n" ); + + (void) memset( (char *)&op, '\0', sizeof( op )); + + if ( parse_input( stdin, stdout, &op ) < 0 ) { + exit( EXIT_SUCCESS ); + } + + if ( op.ldop_op != LDOP_SEARCH ) { + write_result( stdout, LDAP_UNWILLING_TO_PERFORM, NULL, + "Command Not Implemented" ); + exit( EXIT_SUCCESS ); + } + +#ifdef LDAP_DEBUG + dump_ldop( &op ); +#endif /* LDAP_DEBUG */ + + pwdfile_search( &op, stdout ); + + exit( EXIT_SUCCESS ); +} + + +static void +pwdfile_search( struct ldop *op, FILE *ofp ) +{ + struct passwd *pw; + struct ldentry *entry; + int oneentry; + + oneentry = ( strchr( op->ldop_dn, '@' ) != NULL ); + + for ( pw = getpwent(); pw != NULL; pw = getpwent()) { + if (( entry = pw2entry( op, pw )) != NULL ) { + if ( oneentry ) { + if ( strcasecmp( op->ldop_dn, entry->lde_dn ) == 0 ) { + write_entry( op, entry, ofp ); + break; + } + } else if ( test_filter( op, entry ) == LDAP_COMPARE_TRUE ) { + write_entry( op, entry, ofp ); + } + free_entry( entry ); + } + } + endpwent(); + + write_result( ofp, LDAP_SUCCESS, NULL, NULL ); +} + + +static struct ldentry * +pw2entry( struct ldop *op, struct passwd *pw ) +{ + struct ldentry *entry; + struct ldattr *attr; + int i; + + /* + * construct the DN from pw_name + */ + if ( strchr( op->ldop_suffixes[ 0 ], '=' ) != NULL ) { + /* + * X.500 style DN + */ + i = snprintf( tmpbuf, sizeof( tmpbuf ), "cn=%s, %s", pw->pw_name, op->ldop_suffixes[ 0 ] ); + } else { + /* + * RFC-822 style DN + */ + i = snprintf( tmpbuf, sizeof( tmpbuf ), "%s@%s", pw->pw_name, op->ldop_suffixes[ 0 ] ); + } + + if ( i < 0 || i >= sizeof( tmpbuf ) ) { + return NULL; + } + + entry = (struct ldentry *) ecalloc( 1, sizeof( struct ldentry )); + entry->lde_dn = estrdup( tmpbuf ); + + /* + * for now, we simply derive the LDAP attribute values as follows: + * objectClass = person + * uid = pw_name + * sn = pw_name + * cn = pw_name + * cn = pw_gecos (second common name) + */ + entry->lde_attrs = (struct ldattr **)ecalloc( 5, sizeof( struct ldattr * )); + i = 0; + attr = (struct ldattr *)ecalloc( 1, sizeof( struct ldattr )); + attr->lda_name = estrdup( "objectClass" ); + attr->lda_values = (char **)ecalloc( 2, sizeof( char * )); + attr->lda_values[ 0 ] = estrdup( "person" ); + entry->lde_attrs[ i++ ] = attr; + + attr = (struct ldattr *)ecalloc( 1, sizeof( struct ldattr )); + attr->lda_name = estrdup( "uid" ); + attr->lda_values = (char **)ecalloc( 2, sizeof( char * )); + attr->lda_values[ 0 ] = estrdup( pw->pw_name ); + entry->lde_attrs[ i++ ] = attr; + + attr = (struct ldattr *)ecalloc( 1, sizeof( struct ldattr )); + attr->lda_name = estrdup( "sn" ); + attr->lda_values = (char **)ecalloc( 2, sizeof( char * )); + attr->lda_values[ 0 ] = estrdup( pw->pw_name ); + entry->lde_attrs[ i++ ] = attr; + + attr = (struct ldattr *)ecalloc( 1, sizeof( struct ldattr )); + attr->lda_name = estrdup( "cn" ); + attr->lda_values = (char **)ecalloc( 3, sizeof( char * )); + attr->lda_values[ 0 ] = estrdup( pw->pw_name ); + if ( pw->pw_gecos != NULL && *pw->pw_gecos != '\0' ) { + attr->lda_values[ 1 ] = estrdup( pw->pw_gecos ); + } + entry->lde_attrs[ i++ ] = attr; + + return( entry ); +} diff --git a/servers/slapd/shell-backends/shellutil.c b/servers/slapd/shell-backends/shellutil.c new file mode 100644 index 0000000..605114e --- /dev/null +++ b/servers/slapd/shell-backends/shellutil.c @@ -0,0 +1,396 @@ +/* shellutil.c - common routines useful when building shell-based backends */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 1998-2021 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). + */ + + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> +#include <ac/stdarg.h> + +#include <pwd.h> + +#include <ac/ctype.h> +#include <ac/string.h> + +#include <lber.h> +#include <ldap.h> +#include "shellutil.h" + + +int debugflg; +char *progname; + +static struct inputparams ips[] = { + IP_TYPE_SUFFIX, "suffix", + IP_TYPE_BASE, "base", + IP_TYPE_SCOPE, "scope", + IP_TYPE_ALIASDEREF, "deref", + IP_TYPE_SIZELIMIT, "sizelimit", + IP_TYPE_TIMELIMIT, "timelimit", + IP_TYPE_FILTER, "filter", + IP_TYPE_ATTRS, "attrs", + IP_TYPE_ATTRSONLY, "attrsonly", + 0, NULL +}; + + +void +write_result( FILE *fp, int code, char *matched, char *info ) +{ + fprintf( fp, "RESULT\ncode: %d\n", code ); + debug_printf( ">> RESULT\n" ); + debug_printf( ">> code: %d\n", code ); + + if ( matched != NULL ) { + fprintf( fp, "matched: %s\n", matched ); + debug_printf( ">> matched: %s\n", matched ); + } + + if ( info != NULL ) { + fprintf( fp, "info: %s\n", info ); + debug_printf( ">> info: %s\n", info ); + } +} + + +void +write_entry( struct ldop *op, struct ldentry *entry, FILE *ofp ) +{ + struct ldattr **app; + char **valp; + + fprintf( ofp, "dn: %s\n", entry->lde_dn ); + for ( app = entry->lde_attrs; *app != NULL; ++app ) { + if ( attr_requested( (*app)->lda_name, op )) { + for ( valp = (*app)->lda_values; *valp != NULL; ++valp ) { + fprintf( ofp, "%s: %s\n", (*app)->lda_name, *valp ); + } + } + } + fputc( '\n', ofp ); +} + + +int +test_filter( struct ldop *op, struct ldentry *entry ) +{ + return ((random() & 0x07 ) == 0x07) /* XXX random for now */ + ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE; +} + + +int +attr_requested( char *name, struct ldop *op ) +{ + char **ap; + + if ( op->ldop_srch.ldsp_attrs == NULL ) { /* special case */ + return( 1 ); + } + + for ( ap = op->ldop_srch.ldsp_attrs; *ap != NULL; ++ap ) { + if ( strcasecmp( name, *ap ) == 0 ) { + return( 1 ); + } + } + + return( 0 ); +} + + +void +free_entry( struct ldentry *entry ) +{ + struct ldattr **app; + char **valp; + + free( entry->lde_dn ); + + for ( app = entry->lde_attrs; *app != NULL; ++app ) { + for ( valp = (*app)->lda_values; *valp != NULL; ++valp ) { + free( *valp ); + } + free( (*app)->lda_values ); + free( (*app)->lda_name ); + } + + free( entry->lde_attrs ); + free( entry ); +} + + +int +parse_input( FILE *ifp, FILE *ofp, struct ldop *op ) +{ + char *p, *args, line[ MAXLINELEN + 1 ]; + struct inputparams *ip; + + if ( fgets( line, MAXLINELEN, ifp ) == NULL ) { + write_result( ofp, LDAP_OTHER, NULL, "Empty Input" ); + } + line[ strlen( line ) - 1 ] = '\0'; + if ( strncasecmp( line, STR_OP_SEARCH, sizeof( STR_OP_SEARCH ) - 1 ) + != 0 ) { + write_result( ofp, LDAP_UNWILLING_TO_PERFORM, NULL, + "Operation Not Supported" ); + return( -1 ); + } + + op->ldop_op = LDOP_SEARCH; + + while ( fgets( line, MAXLINELEN, ifp ) != NULL ) { + line[ strlen( line ) - 1 ] = '\0'; + debug_printf( "<< %s\n", line ); + + args = line; + if (( ip = find_input_tag( &args )) == NULL ) { + debug_printf( "ignoring %s\n", line ); + continue; + } + + switch( ip->ip_type ) { + case IP_TYPE_SUFFIX: + add_strval( &op->ldop_suffixes, args ); + break; + case IP_TYPE_BASE: + op->ldop_dn = estrdup( args ); + break; + case IP_TYPE_SCOPE: + if ( lutil_atoi( &op->ldop_srch.ldsp_scope, args ) != 0 || + ( op->ldop_srch.ldsp_scope != LDAP_SCOPE_BASE && + op->ldop_srch.ldsp_scope != LDAP_SCOPE_ONELEVEL && + op->ldop_srch.ldsp_scope != LDAP_SCOPE_SUBTREE ) ) + { + write_result( ofp, LDAP_OTHER, NULL, "Bad scope" ); + return( -1 ); + } + break; + case IP_TYPE_ALIASDEREF: + if ( lutil_atoi( &op->ldop_srch.ldsp_aliasderef, args ) != 0 ) { + write_result( ofp, LDAP_OTHER, NULL, "Bad alias deref" ); + return( -1 ); + } + break; + case IP_TYPE_SIZELIMIT: + if ( lutil_atoi( &op->ldop_srch.ldsp_sizelimit, args ) != 0 ) { + write_result( ofp, LDAP_OTHER, NULL, "Bad size limit" ); + return( -1 ); + } + break; + case IP_TYPE_TIMELIMIT: + if ( lutil_atoi( &op->ldop_srch.ldsp_timelimit, args ) != 0 ) { + write_result( ofp, LDAP_OTHER, NULL, "Bad time limit" ); + return( -1 ); + } + break; + case IP_TYPE_FILTER: + op->ldop_srch.ldsp_filter = estrdup( args ); + break; + case IP_TYPE_ATTRSONLY: + op->ldop_srch.ldsp_attrsonly = ( *args != '0' ); + break; + case IP_TYPE_ATTRS: + if ( strcmp( args, "all" ) == 0 ) { + op->ldop_srch.ldsp_attrs = NULL; + } else { + while ( args != NULL ) { + if (( p = strchr( args, ' ' )) != NULL ) { + *p++ = '\0'; + while ( isspace( (unsigned char) *p )) { + ++p; + } + } + add_strval( &op->ldop_srch.ldsp_attrs, args ); + args = p; + } + } + break; + } + } + + if ( op->ldop_suffixes == NULL || op->ldop_dn == NULL || + op->ldop_srch.ldsp_filter == NULL ) { + write_result( ofp, LDAP_OTHER, NULL, + "Required suffix:, base:, or filter: missing" ); + return( -1 ); + } + + return( 0 ); +} + + +struct inputparams * +find_input_tag( char **linep ) /* linep is set to start of args */ +{ + int i; + char *p; + + if (( p = strchr( *linep, ':' )) == NULL || p == *linep ) { + return( NULL ); + } + + for ( i = 0; ips[ i ].ip_type != 0; ++i ) { + if ( strncasecmp( *linep, ips[ i ].ip_tag, p - *linep ) == 0 ) { + while ( isspace( (unsigned char) *(++p) )) { + ; + } + *linep = p; + return( &ips[ i ] ); + } + } + + return( NULL ); +} + + +void +add_strval( char ***sp, char *val ) +{ + int i; + char **vallist; + + vallist = *sp; + + if ( vallist == NULL ) { + i = 0; + } else { + for ( i = 0; vallist[ i ] != NULL; ++i ) { + ; + } + } + + vallist = (char **)erealloc( vallist, ( i + 2 ) * sizeof( char * )); + vallist[ i ] = estrdup( val ); + vallist[ ++i ] = NULL; + *sp = vallist; +} + + +char * +estrdup( char *s ) +{ + char *p; + + if (( p = strdup( s )) == NULL ) { + debug_printf( "strdup failed\n" ); + exit( EXIT_FAILURE ); + } + + return( p ); +} + + +void * +erealloc( void *s, unsigned size ) +{ + char *p; + + if ( s == NULL ) { + p = malloc( size ); + } else { + p = realloc( s, size ); + } + + if ( p == NULL ) { + debug_printf( "realloc( p, %d ) failed\n", size ); + exit( EXIT_FAILURE ); + } + + return( p ); +} + + +char * +ecalloc( unsigned nelem, unsigned elsize ) +{ + char *p; + + if (( p = calloc( nelem, elsize )) == NULL ) { + debug_printf( "calloc( %d, %d ) failed\n", nelem, elsize ); + exit( EXIT_FAILURE ); + } + + return( p ); +} + + +#ifdef LDAP_DEBUG + +/* VARARGS */ +void +debug_printf( const char *fmt, ... ) +{ + va_list ap; + + if ( debugflg ) { + va_start( ap, fmt ); + fprintf( stderr, "%s: ", progname ); + vfprintf( stderr, fmt, ap ); + va_end( ap ); + } +} + + +void +dump_ldop( struct ldop *op ) +{ + if ( !debugflg ) { + return; + } + + debug_printf( "SEARCH operation\n" ); + if ( op->ldop_suffixes == NULL ) { + debug_printf( " suffix: NONE\n" ); + } else { + int i; + for ( i = 0; op->ldop_suffixes[ i ] != NULL; ++i ) { + debug_printf( " suffix: <%s>\n", op->ldop_suffixes[ i ] ); + } + } + debug_printf( " dn: <%s>\n", op->ldop_dn ); + debug_printf( " scope: <%d>\n", op->ldop_srch.ldsp_scope ); + debug_printf( " filter: <%s>\n", op->ldop_srch.ldsp_filter ); + debug_printf( "aliasderef: <%d>\n", op->ldop_srch.ldsp_aliasderef ); + debug_printf( " sizelimit: <%d>\n", op->ldop_srch.ldsp_sizelimit ); + debug_printf( " timelimit: <%d>\n", op->ldop_srch.ldsp_timelimit ); + debug_printf( " attrsonly: <%d>\n", op->ldop_srch.ldsp_attrsonly ); + if ( op->ldop_srch.ldsp_attrs == NULL ) { + debug_printf( " attrs: ALL\n" ); + } else { + int i; + + for ( i = 0; op->ldop_srch.ldsp_attrs[ i ] != NULL; ++i ) { + debug_printf( " attrs: <%s>\n", op->ldop_srch.ldsp_attrs[ i ] ); + } + } +} +#endif /* LDAP_DEBUG */ diff --git a/servers/slapd/shell-backends/shellutil.h b/servers/slapd/shell-backends/shellutil.h new file mode 100644 index 0000000..a359aa2 --- /dev/null +++ b/servers/slapd/shell-backends/shellutil.h @@ -0,0 +1,123 @@ +/* shellutil.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 1998-2021 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). + */ + +#ifndef SHELLUTIL_H +#define SHELLUTIL_H + +#include <ldap_cdefs.h> + +LDAP_BEGIN_DECL + +#define MAXLINELEN 512 + +#define STR_OP_SEARCH "SEARCH" + + +struct inputparams { + int ip_type; +#define IP_TYPE_SUFFIX 0x01 +#define IP_TYPE_BASE 0x02 +#define IP_TYPE_SCOPE 0x03 +#define IP_TYPE_ALIASDEREF 0x04 +#define IP_TYPE_SIZELIMIT 0x05 +#define IP_TYPE_TIMELIMIT 0x06 +#define IP_TYPE_FILTER 0x07 +#define IP_TYPE_ATTRSONLY 0x08 +#define IP_TYPE_ATTRS 0x09 + char *ip_tag; +}; + + +struct ldsrchparms { + int ldsp_scope; + int ldsp_aliasderef; + int ldsp_sizelimit; + int ldsp_timelimit; + int ldsp_attrsonly; + char *ldsp_filter; + char **ldsp_attrs; +}; + + +struct ldop { + int ldop_op; +#define LDOP_SEARCH 0x01 + char **ldop_suffixes; + char *ldop_dn; + union ldapop_params_u { + struct ldsrchparms LDsrchparams; + } ldop_params; +#define ldop_srch ldop_params.LDsrchparams +}; + + +struct ldattr { + char *lda_name; + char **lda_values; +}; + + +struct ldentry { + char *lde_dn; + struct ldattr **lde_attrs; +}; + + +#ifdef LDAP_DEBUG +void debug_printf(const char *, ...) LDAP_GCCATTR((format(printf, 1, 2))); +#else /* LDAP_DEBUG */ +#define debug_printf (void) /* Ignore "arguments" */ +#endif /* LDAP_DEBUG */ + +/* + * function prototypes + */ +void write_result( FILE *fp, int code, char *matched, char *info ); +void write_entry( struct ldop *op, struct ldentry *entry, FILE *ofp ); +int test_filter( struct ldop *op, struct ldentry *entry ); +void free_entry( struct ldentry *entry ); +int attr_requested( char *name, struct ldop *op ); +int parse_input( FILE *ifp, FILE *ofp, struct ldop *op ); +struct inputparams *find_input_tag( char **linep ); +void add_strval( char ***sp, char *val ); +char *ecalloc( unsigned nelem, unsigned elsize ); +void *erealloc( void *s, unsigned size ); +char *estrdup( char *s ); +extern void dump_ldop (struct ldop *op); + + +/* + * global variables + */ +extern int debugflg; +extern char *progname; + +LDAP_END_DECL +#endif |