xref: /titanic_51/usr/src/cmd/ldap/common/ldapmodify.c (revision ffc33b8444621a25dae0cdf94f8cd8a39af8c239)
17c478bd9Sstevel@tonic-gate /*
2*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
87c478bd9Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
97c478bd9Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
107c478bd9Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
137c478bd9Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
147c478bd9Sstevel@tonic-gate  * implied. See the License for the specific language governing
157c478bd9Sstevel@tonic-gate  * rights and limitations under the License.
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
187c478bd9Sstevel@tonic-gate  * March 31, 1998.
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
217c478bd9Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
227c478bd9Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
237c478bd9Sstevel@tonic-gate  * Rights Reserved.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  * Contributor(s):
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /* ldapmodify.c - generic program to modify or add entries using LDAP */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include "ldaptool.h"
317c478bd9Sstevel@tonic-gate #include "fileurl.h"
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
347c478bd9Sstevel@tonic-gate #include <locale.h>
357c478bd9Sstevel@tonic-gate #include "ldif.h"
367c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
397c478bd9Sstevel@tonic-gate #define gettext(s) s
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate static int		newval, contoper, force, valsfromfiles, display_binary_values;
437c478bd9Sstevel@tonic-gate static int		ldif_version = -1;	/* -1 => unknown version */
447c478bd9Sstevel@tonic-gate static char		*rejfile = NULL;
457c478bd9Sstevel@tonic-gate static char		*bulkimport_suffix = NULL;
467c478bd9Sstevel@tonic-gate static int		ldapmodify_quiet = 0;
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
497c478bd9Sstevel@tonic-gate static int		error = 0, replace, nbthreads = 1;
507c478bd9Sstevel@tonic-gate static int		thr_create_errors = 0;
517c478bd9Sstevel@tonic-gate static pthread_mutex_t	read_mutex = {0};
527c478bd9Sstevel@tonic-gate static pthread_mutex_t	wait_mutex = {0};
537c478bd9Sstevel@tonic-gate static pthread_cond_t	wait_cond  = {0};
547c478bd9Sstevel@tonic-gate #else
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  * For Solaris, ld is defined local to process() because
577c478bd9Sstevel@tonic-gate  * multiple threads restricts Solaris from using a global
587c478bd9Sstevel@tonic-gate  * ld variable.
597c478bd9Sstevel@tonic-gate  * Solaris uses multiple threads to create multiple
607c478bd9Sstevel@tonic-gate  * ldap connections if nbthreads > 1 (i.e -l option).
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate static LDAP		*ld;
637c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #define LDAPMOD_MAXLINE		4096
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /* strings found in replog/LDIF entries (mostly lifted from slurpd/slurp.h) */
687c478bd9Sstevel@tonic-gate #define T_REPLICA_STR		"replica"
697c478bd9Sstevel@tonic-gate #define T_DN_STR		"dn"
707c478bd9Sstevel@tonic-gate #define T_VERSION_STR		"version"
717c478bd9Sstevel@tonic-gate #define T_CHANGETYPESTR         "changetype"
727c478bd9Sstevel@tonic-gate #define T_ADDCTSTR		"add"
737c478bd9Sstevel@tonic-gate #define T_MODIFYCTSTR		"modify"
747c478bd9Sstevel@tonic-gate #define T_DELETECTSTR		"delete"
757c478bd9Sstevel@tonic-gate #define T_RENAMECTSTR		"rename"	/* non-standard */
767c478bd9Sstevel@tonic-gate #define T_MODDNCTSTR		"moddn"
777c478bd9Sstevel@tonic-gate #define T_MODRDNCTSTR		"modrdn"
787c478bd9Sstevel@tonic-gate #define T_MODOPADDSTR		"add"
797c478bd9Sstevel@tonic-gate #define T_MODOPREPLACESTR	"replace"
807c478bd9Sstevel@tonic-gate #define T_MODOPDELETESTR	"delete"
817c478bd9Sstevel@tonic-gate #define T_MODSEPSTR		"-"
827c478bd9Sstevel@tonic-gate #define T_NEWRDNSTR		"newrdn"
837c478bd9Sstevel@tonic-gate #define	T_NEWSUPERIORSTR	"newsuperior"
847c478bd9Sstevel@tonic-gate #define	T_NEWPARENTSTR		"newparent"
857c478bd9Sstevel@tonic-gate #define T_DELETEOLDRDNSTR	"deleteoldrdn"
867c478bd9Sstevel@tonic-gate #define T_NEWSUPERIORSTR        "newsuperior"
877c478bd9Sstevel@tonic-gate #define T_NEWPARENTSTR          "newparent"	/* non-standard */
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /* bulk import */
907c478bd9Sstevel@tonic-gate #define	BULKIMPORT_START_OID	"2.16.840.1.113730.3.5.7"
917c478bd9Sstevel@tonic-gate #define	BULKIMPORT_STOP_OID	"2.16.840.1.113730.3.5.8"
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate static int process( void *arg );
947c478bd9Sstevel@tonic-gate static void options_callback( int option, char *optarg );
957c478bd9Sstevel@tonic-gate static void addmodifyop( LDAPMod ***pmodsp, int modop, char *attr,
967c478bd9Sstevel@tonic-gate 	char *value, int vlen );
977c478bd9Sstevel@tonic-gate static void freepmods( LDAPMod **pmods );
987c478bd9Sstevel@tonic-gate static char *read_one_record( FILE *fp );
997c478bd9Sstevel@tonic-gate static char *strdup_and_trim( char *s );
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1027c478bd9Sstevel@tonic-gate static int process_ldapmod_rec( LDAP *ld, char *rbuf );
1037c478bd9Sstevel@tonic-gate static int process_ldif_rec( LDAP *ld, char *rbuf );
1047c478bd9Sstevel@tonic-gate static int domodify( LDAP *ld, char *dn, LDAPMod **pmods, int newentry );
1057c478bd9Sstevel@tonic-gate static int dodelete( LDAP *ld, char *dn );
1067c478bd9Sstevel@tonic-gate static int dorename( LDAP *ld, char *dn, char *newrdn, char *newparent,
1077c478bd9Sstevel@tonic-gate 	int deleteoldrdn );
1087c478bd9Sstevel@tonic-gate #else
1097c478bd9Sstevel@tonic-gate static int process_ldapmod_rec( char *rbuf );
1107c478bd9Sstevel@tonic-gate static int process_ldif_rec( char *rbuf );
1117c478bd9Sstevel@tonic-gate static int domodify( char *dn, LDAPMod **pmods, int newentry );
1127c478bd9Sstevel@tonic-gate static int dodelete( char *dn );
1137c478bd9Sstevel@tonic-gate static int dorename( char *dn, char *newrdn, char *newparent,
1147c478bd9Sstevel@tonic-gate 	int deleteoldrdn );
1157c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate static void
1187c478bd9Sstevel@tonic-gate usage( void )
1197c478bd9Sstevel@tonic-gate {
1207c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("usage: %s [options]\n"), ldaptool_progname );
1217c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("options:\n") );
1227c478bd9Sstevel@tonic-gate     ldaptool_common_usage( 0 );
1237c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -c\t\tcontinuous mode (do not stop on errors)\n") );
1247c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -A\t\tdisplay non-ASCII values in conjunction with -v\n") );
1257c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -f file\tread modifications from file (default: standard input)\n") );
1267c478bd9Sstevel@tonic-gate     if ( strcmp( ldaptool_progname, "ldapmodify" ) == 0 ){
1277c478bd9Sstevel@tonic-gate 	fprintf( stderr, gettext("    -a\t\tadd entries\n") );
1287c478bd9Sstevel@tonic-gate     }
1297c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -b\t\tread values that start with / from files (for bin attrs)\n") );
1307c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -F\t\tforce application of all changes, regardless of\n") );
1317c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("      \t\treplica lines\n") );
1327c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -e rejfile\tsave rejected entries in \"rejfile\"\n") );
1337c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -B suffix\tbulk import to \"suffix\"\n"));
1347c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -q\t\tbe quiet when adding/modifying entries\n") );
1357c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1367c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -r\t\treplace values\n"));
1377c478bd9Sstevel@tonic-gate     fprintf( stderr, gettext("    -l nb-connections\tnumber of LDAP connections\n"));
1387c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
1397c478bd9Sstevel@tonic-gate     exit( LDAP_PARAM_ERROR );
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate int
1447c478bd9Sstevel@tonic-gate main( int argc, char **argv )
1457c478bd9Sstevel@tonic-gate {
1467c478bd9Sstevel@tonic-gate     int		optind, i;
147*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     int		rc;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1507c478bd9Sstevel@tonic-gate     char *locale = setlocale(LC_ALL, "");
1517c478bd9Sstevel@tonic-gate     textdomain(TEXT_DOMAIN);
1527c478bd9Sstevel@tonic-gate #endif
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate #ifdef notdef
1557c478bd9Sstevel@tonic-gate #ifdef HPUX11
1567c478bd9Sstevel@tonic-gate #ifndef __LP64__
1577c478bd9Sstevel@tonic-gate 	_main( argc, argv);
1587c478bd9Sstevel@tonic-gate #endif /* __LP64_ */
1597c478bd9Sstevel@tonic-gate #endif /* HPUX11 */
1607c478bd9Sstevel@tonic-gate #endif
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate     valsfromfiles = display_binary_values = 0;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1657c478bd9Sstevel@tonic-gate     optind = ldaptool_process_args( argc, argv, "aAbcFe:B:qrl:", 0,
1667c478bd9Sstevel@tonic-gate 	    options_callback );
1677c478bd9Sstevel@tonic-gate #else
1687c478bd9Sstevel@tonic-gate     optind = ldaptool_process_args( argc, argv, "aAbcFe:B:q", 0,
1697c478bd9Sstevel@tonic-gate 	    options_callback );
1707c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate     if ( optind == -1 ) {
1747c478bd9Sstevel@tonic-gate 	usage();
1757c478bd9Sstevel@tonic-gate     }
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate     if ( !newval && strcmp( ldaptool_progname, "ldapadd" ) == 0 ) {
1787c478bd9Sstevel@tonic-gate 	newval = 1;
1797c478bd9Sstevel@tonic-gate     }
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate     if ( ldaptool_fp == NULL ) {
1827c478bd9Sstevel@tonic-gate 	ldaptool_fp = stdin;
1837c478bd9Sstevel@tonic-gate     }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate     if ( argc - optind != 0 ) {
1867c478bd9Sstevel@tonic-gate 	usage();
1877c478bd9Sstevel@tonic-gate     }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1907c478bd9Sstevel@tonic-gate     /* trivial case */
191*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     if ( nbthreads == 1 ) {
192*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 	rc = process(NULL);
193*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 	/* check for and report output error */
194*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 	fflush( stdout );
195*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 	rc = ldaptool_check_ferror( stdout, rc,
196*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 		gettext("output error (output might be incomplete)") );
197*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 	return( rc );
198*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     }
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate     for ( i=0; i<nbthreads; ++i ) {
2017c478bd9Sstevel@tonic-gate  	if ( thr_create(NULL, 0, process, NULL, NULL, NULL) != 0 )
2027c478bd9Sstevel@tonic-gate 		++thr_create_errors;
2037c478bd9Sstevel@tonic-gate     }
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate     if ( thr_create_errors < nbthreads )
2067c478bd9Sstevel@tonic-gate     	while ( thr_join(0, NULL, NULL) == 0 );
2077c478bd9Sstevel@tonic-gate     else
2087c478bd9Sstevel@tonic-gate 	error = -1;
209*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     rc = error;
210*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     /* check for and report output error */
211*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     fflush( stdout );
212*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     rc = ldaptool_check_ferror( stdout, rc,
213*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 		gettext("output error (output might be incomplete)") );
214*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     return( rc );
2157c478bd9Sstevel@tonic-gate #else
216*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     rc = process(NULL);
217*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     /* check for and report output error */
218*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     fflush( stdout );
219*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     rc = ldaptool_check_ferror( stdout, rc,
220*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 		gettext("output error (output might be incomplete)") );
221*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India     return( rc );
2227c478bd9Sstevel@tonic-gate #endif  /* SOLARIS_LDAP_CMD */
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
2267c478bd9Sstevel@tonic-gate #define	exit(a)	\
2277c478bd9Sstevel@tonic-gate 	if (nbthreads > 1) { \
2287c478bd9Sstevel@tonic-gate     		mutex_lock(&read_mutex); \
2297c478bd9Sstevel@tonic-gate 		error |= a; \
2307c478bd9Sstevel@tonic-gate     		mutex_unlock(&read_mutex); \
2317c478bd9Sstevel@tonic-gate 		thr_exit(&error); \
2327c478bd9Sstevel@tonic-gate 	} else { \
2337c478bd9Sstevel@tonic-gate 		exit(a); \
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate #endif  /* SOLARIS_LDAP_CMD */
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate static int
2387c478bd9Sstevel@tonic-gate process( void *arg )
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate     char	*rbuf, *saved_rbuf, *start, *p, *q;
2417c478bd9Sstevel@tonic-gate     FILE	*rfp = NULL;
2427c478bd9Sstevel@tonic-gate     int		rc, use_ldif, deref;
2437c478bd9Sstevel@tonic-gate     LDAPControl	*ldctrl;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
2467c478bd9Sstevel@tonic-gate     LDAP	*ld;
2477c478bd9Sstevel@tonic-gate #endif  /* SOLARIS_LDAP_CMD */
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate     ld = ldaptool_ldap_init( 0 );
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate     if ( !ldaptool_not ) {
2527c478bd9Sstevel@tonic-gate 	deref = LDAP_DEREF_NEVER;	/* this seems prudent */
2537c478bd9Sstevel@tonic-gate 	ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
2547c478bd9Sstevel@tonic-gate     }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate     ldaptool_bind( ld );
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate     if (( ldctrl = ldaptool_create_manage_dsait_control()) != NULL ) {
2597c478bd9Sstevel@tonic-gate 	ldaptool_add_control_to_array( ldctrl, ldaptool_request_ctrls);
2607c478bd9Sstevel@tonic-gate     }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate     if ((ldctrl = ldaptool_create_proxyauth_control(ld)) !=NULL) {
2637c478bd9Sstevel@tonic-gate 	ldaptool_add_control_to_array( ldctrl, ldaptool_request_ctrls);
2647c478bd9Sstevel@tonic-gate     }
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate     rc = 0;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate     /* turn on bulk import?*/
2697c478bd9Sstevel@tonic-gate     if (bulkimport_suffix) {
2707c478bd9Sstevel@tonic-gate 	struct berval	bv, *retdata;
2717c478bd9Sstevel@tonic-gate 	char		*retoid;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	bv.bv_val = bulkimport_suffix;
2747c478bd9Sstevel@tonic-gate 	bv.bv_len = strlen(bulkimport_suffix);
2757c478bd9Sstevel@tonic-gate 	if ((rc = ldap_extended_operation_s(ld,
2767c478bd9Sstevel@tonic-gate 	    BULKIMPORT_START_OID, &bv, NULL,
2777c478bd9Sstevel@tonic-gate 	    NULL, &retoid, &retdata)) != 0) {
2787c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Error: unable to service "
2797c478bd9Sstevel@tonic-gate 		    "extended operation request\n\t'%s' for "
2807c478bd9Sstevel@tonic-gate 		    "bulk import\n\t(error:%d:'%s')\n"),
2817c478bd9Sstevel@tonic-gate 		    BULKIMPORT_START_OID, rc, ldap_err2string(rc));
2827c478bd9Sstevel@tonic-gate 		return (rc);
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 	if (retoid)
2857c478bd9Sstevel@tonic-gate 		ldap_memfree(retoid);
2867c478bd9Sstevel@tonic-gate 	if (retdata)
2877c478bd9Sstevel@tonic-gate 		ber_bvfree(retdata);
2887c478bd9Sstevel@tonic-gate     }
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate     while (( rc == 0 || contoper ) &&
2917c478bd9Sstevel@tonic-gate 		( rbuf = read_one_record( ldaptool_fp )) != NULL ) {
2927c478bd9Sstevel@tonic-gate 	/*
2937c478bd9Sstevel@tonic-gate 	 * we assume record is ldif/slapd.replog if the first line
2947c478bd9Sstevel@tonic-gate 	 * has a colon that appears to the left of any equal signs, OR
2957c478bd9Sstevel@tonic-gate 	 * if the first line consists entirely of digits (an entry id)
2967c478bd9Sstevel@tonic-gate 	 */
2977c478bd9Sstevel@tonic-gate 	use_ldif = ( p = strchr( rbuf, ':' )) != NULL &&
2987c478bd9Sstevel@tonic-gate 		( q = strchr( rbuf, '\n' )) != NULL && p < q &&
2997c478bd9Sstevel@tonic-gate 		(( q = strchr( rbuf, '=' )) == NULL || p < q );
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	start = rbuf;
3027c478bd9Sstevel@tonic-gate 	saved_rbuf = strdup( rbuf );
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	if ( !use_ldif && ( q = strchr( rbuf, '\n' )) != NULL ) {
3057c478bd9Sstevel@tonic-gate 	    for ( p = rbuf; p < q; ++p ) {
3067c478bd9Sstevel@tonic-gate 		if ( !isdigit( *p )) {
3077c478bd9Sstevel@tonic-gate 		    break;
3087c478bd9Sstevel@tonic-gate 		}
3097c478bd9Sstevel@tonic-gate 	    }
3107c478bd9Sstevel@tonic-gate 	    if ( p >= q ) {
3117c478bd9Sstevel@tonic-gate 		use_ldif = 1;
3127c478bd9Sstevel@tonic-gate 		start = q + 1;
3137c478bd9Sstevel@tonic-gate 	    }
3147c478bd9Sstevel@tonic-gate 	}
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
3177c478bd9Sstevel@tonic-gate 	if ( use_ldif ) {
3187c478bd9Sstevel@tonic-gate 	    rc = process_ldif_rec( ld, start );
3197c478bd9Sstevel@tonic-gate 	} else {
3207c478bd9Sstevel@tonic-gate 	    rc = process_ldapmod_rec( ld, start );
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate #else
3237c478bd9Sstevel@tonic-gate 	if ( use_ldif ) {
3247c478bd9Sstevel@tonic-gate 	    rc = process_ldif_rec( start );
3257c478bd9Sstevel@tonic-gate 	} else {
3267c478bd9Sstevel@tonic-gate 	    rc = process_ldapmod_rec( start );
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	if ( rc != LDAP_SUCCESS && rejfile != NULL ) {
3317c478bd9Sstevel@tonic-gate 	    /* Write this record to the reject file */
3327c478bd9Sstevel@tonic-gate 	    int newfile = 0;
3337c478bd9Sstevel@tonic-gate 	    struct stat stbuf;
3347c478bd9Sstevel@tonic-gate 	    if ( stat( rejfile, &stbuf ) < 0 ) {
3357c478bd9Sstevel@tonic-gate 		if ( errno == ENOENT ) {
3367c478bd9Sstevel@tonic-gate 		    newfile = 1;
3377c478bd9Sstevel@tonic-gate 		}
3387c478bd9Sstevel@tonic-gate 	    }
3397c478bd9Sstevel@tonic-gate 	    if (( rfp = ldaptool_open_file( rejfile, "a" )) == NULL ) {
3407c478bd9Sstevel@tonic-gate 		fprintf( stderr, gettext("Cannot open error file \"%s\" - "
3417c478bd9Sstevel@tonic-gate 			"erroneous entries will not be saved\n"), rejfile );
3427c478bd9Sstevel@tonic-gate 		rejfile = NULL;
3437c478bd9Sstevel@tonic-gate 	    } else {
3447c478bd9Sstevel@tonic-gate 		if ( newfile == 0 ) {
3457c478bd9Sstevel@tonic-gate 		    fputs( "\n", rfp );
3467c478bd9Sstevel@tonic-gate 		}
3477c478bd9Sstevel@tonic-gate 		fprintf( rfp, gettext("# Error: %s\n"), ldap_err2string( rc ));
3487c478bd9Sstevel@tonic-gate 		fputs( saved_rbuf, rfp );
3497c478bd9Sstevel@tonic-gate 		fclose( rfp );
3507c478bd9Sstevel@tonic-gate 		rfp = NULL;
3517c478bd9Sstevel@tonic-gate 	    }
3527c478bd9Sstevel@tonic-gate 	}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	free( rbuf );
3557c478bd9Sstevel@tonic-gate 	free( saved_rbuf );
3567c478bd9Sstevel@tonic-gate     }
3577c478bd9Sstevel@tonic-gate     ldaptool_reset_control_array( ldaptool_request_ctrls );
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate     /* turn off bulk import?*/
3607c478bd9Sstevel@tonic-gate     if (bulkimport_suffix) {
3617c478bd9Sstevel@tonic-gate 	struct berval	bv, *retdata;
3627c478bd9Sstevel@tonic-gate 	char		*retoid;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	bv.bv_val = "";
3657c478bd9Sstevel@tonic-gate 	bv.bv_len = 0;
3667c478bd9Sstevel@tonic-gate 	if ((rc = ldap_extended_operation_s(ld,
3677c478bd9Sstevel@tonic-gate 	    BULKIMPORT_STOP_OID, &bv, NULL,
3687c478bd9Sstevel@tonic-gate 	    NULL, &retoid, &retdata)) != 0) {
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Error: unable to service "
3717c478bd9Sstevel@tonic-gate 		    "extended operation request\n\t '%s' for "
3727c478bd9Sstevel@tonic-gate 		    "bulk import\n\t(rc:%d:'%s')\n"),
3737c478bd9Sstevel@tonic-gate 		    BULKIMPORT_STOP_OID, rc, ldap_err2string(rc));
3747c478bd9Sstevel@tonic-gate 		return (rc);
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 	if (retoid)
3777c478bd9Sstevel@tonic-gate 		ldap_memfree(retoid);
3787c478bd9Sstevel@tonic-gate 	if (retdata)
3797c478bd9Sstevel@tonic-gate 		ber_bvfree(retdata);
3807c478bd9Sstevel@tonic-gate     }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
3837c478bd9Sstevel@tonic-gate     mutex_lock(&read_mutex);
3847c478bd9Sstevel@tonic-gate #endif
3857c478bd9Sstevel@tonic-gate     ldaptool_cleanup( ld );
3867c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
3877c478bd9Sstevel@tonic-gate     mutex_unlock(&read_mutex);
3887c478bd9Sstevel@tonic-gate #endif
3897c478bd9Sstevel@tonic-gate     return( rc );
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate static void
3947c478bd9Sstevel@tonic-gate options_callback( int option, char *optarg )
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate     switch( option ) {
3977c478bd9Sstevel@tonic-gate     case 'a':	/* add */
3987c478bd9Sstevel@tonic-gate 	newval = 1;
3997c478bd9Sstevel@tonic-gate 	break;
4007c478bd9Sstevel@tonic-gate     case 'b':	/* read values from files (for binary attributes) */
4017c478bd9Sstevel@tonic-gate 	valsfromfiles = 1;
4027c478bd9Sstevel@tonic-gate 	break;
4037c478bd9Sstevel@tonic-gate     case 'A':	/* display non-ASCII values when -v is used */
4047c478bd9Sstevel@tonic-gate 	display_binary_values = 1;
4057c478bd9Sstevel@tonic-gate 	break;
4067c478bd9Sstevel@tonic-gate     case 'c':	/* continuous operation */
4077c478bd9Sstevel@tonic-gate 	contoper = 1;
4087c478bd9Sstevel@tonic-gate 	break;
4097c478bd9Sstevel@tonic-gate     case 'F':	/* force all changes records to be used */
4107c478bd9Sstevel@tonic-gate 	force = 1;
4117c478bd9Sstevel@tonic-gate 	break;
4127c478bd9Sstevel@tonic-gate     case 'e':
4137c478bd9Sstevel@tonic-gate 	rejfile = strdup( optarg );
4147c478bd9Sstevel@tonic-gate 	break;
4157c478bd9Sstevel@tonic-gate     case 'B':	/* bulk import option */
4167c478bd9Sstevel@tonic-gate 	bulkimport_suffix = strdup( optarg );
4177c478bd9Sstevel@tonic-gate 	break;
4187c478bd9Sstevel@tonic-gate     case 'q':	/* quiet mode on add/modify operations */
4197c478bd9Sstevel@tonic-gate 	ldapmodify_quiet = 1;
4207c478bd9Sstevel@tonic-gate 	break;
4217c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4227c478bd9Sstevel@tonic-gate     case 'r':	/* default is to replace rather than add values */
4237c478bd9Sstevel@tonic-gate 	replace = 1;
4247c478bd9Sstevel@tonic-gate 	break;
4257c478bd9Sstevel@tonic-gate     case 'l':
4267c478bd9Sstevel@tonic-gate 	nbthreads = atoi(optarg);
4277c478bd9Sstevel@tonic-gate 	break;
4287c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
4297c478bd9Sstevel@tonic-gate     default:
4307c478bd9Sstevel@tonic-gate 	usage();
4317c478bd9Sstevel@tonic-gate     }
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate static int
4377c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4387c478bd9Sstevel@tonic-gate process_ldif_rec( LDAP *ld, char *rbuf )
4397c478bd9Sstevel@tonic-gate #else
4407c478bd9Sstevel@tonic-gate process_ldif_rec( char *rbuf )
4417c478bd9Sstevel@tonic-gate #endif
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate     char	*line, *dn, *type, *value, *newrdn, *newparent, *p;
4447c478bd9Sstevel@tonic-gate     char	*ctrl_oid=NULL, *ctrl_value=NULL;
4457c478bd9Sstevel@tonic-gate     int 	ctrl_criticality=1;
4467c478bd9Sstevel@tonic-gate     LDAPControl *ldctrl;
4477c478bd9Sstevel@tonic-gate     int		rc, linenum, vlen, modop, replicaport;
4487c478bd9Sstevel@tonic-gate     int		expect_modop, expect_sep, expect_chgtype_or_control, expect_newrdn;
4497c478bd9Sstevel@tonic-gate     int		expect_deleteoldrdn, expect_newparent, rename, moddn;
4507c478bd9Sstevel@tonic-gate     int		deleteoldrdn, saw_replica, use_record, new_entry, delete_entry;
4517c478bd9Sstevel@tonic-gate     int         got_all, got_value;
4527c478bd9Sstevel@tonic-gate     LDAPMod	**pmods;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate     new_entry = newval;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate     rc = got_all = saw_replica = delete_entry = expect_modop = 0;
4577c478bd9Sstevel@tonic-gate     expect_deleteoldrdn = expect_newrdn = expect_newparent = expect_sep = 0;
4587c478bd9Sstevel@tonic-gate     expect_chgtype_or_control = linenum = got_value = rename = moddn = 0;
4597c478bd9Sstevel@tonic-gate     deleteoldrdn = 1;
4607c478bd9Sstevel@tonic-gate     use_record = force;
4617c478bd9Sstevel@tonic-gate     pmods = NULL;
4627c478bd9Sstevel@tonic-gate     dn = newrdn = newparent = NULL;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4657c478bd9Sstevel@tonic-gate     while ( rc == 0 && ( line = str_getline( &rbuf )) != NULL ) {
4667c478bd9Sstevel@tonic-gate #else
4677c478bd9Sstevel@tonic-gate     while ( rc == 0 && ( line = ldif_getline( &rbuf )) != NULL ) {
4687c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
4697c478bd9Sstevel@tonic-gate 	++linenum;
4707c478bd9Sstevel@tonic-gate 	if ( expect_sep && strcasecmp( line, T_MODSEPSTR ) == 0 ) {
4717c478bd9Sstevel@tonic-gate 	    expect_sep = 0;
4727c478bd9Sstevel@tonic-gate 	    expect_modop = 1;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	    /*If we see a separator in the input stream,
4757c478bd9Sstevel@tonic-gate 	     but we didn't get a value from the last modify
4767c478bd9Sstevel@tonic-gate 	     then we have to fill pmods with an empty value*/
4777c478bd9Sstevel@tonic-gate 	    if (modop == LDAP_MOD_REPLACE && !got_value){
4787c478bd9Sstevel@tonic-gate 	      addmodifyop( &pmods, modop, value, NULL, 0);
4797c478bd9Sstevel@tonic-gate 	    }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	    got_value = 0;
4827c478bd9Sstevel@tonic-gate 	    continue;
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4867c478bd9Sstevel@tonic-gate 	if ( str_parse_line( line, &type, &value, &vlen ) < 0 ) {
4877c478bd9Sstevel@tonic-gate #else
4887c478bd9Sstevel@tonic-gate 	if ( ldif_parse_line( line, &type, &value, &vlen ) < 0 ) {
4897c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
4907c478bd9Sstevel@tonic-gate 	    fprintf( stderr, gettext("%s: invalid format (line %d of entry: %s)\n"),
4917c478bd9Sstevel@tonic-gate 		    ldaptool_progname, linenum, dn == NULL ? "" : dn );
4927c478bd9Sstevel@tonic-gate 	    fprintf( stderr, gettext("%s: line contents: (%s)\n"),
4937c478bd9Sstevel@tonic-gate 		    ldaptool_progname, line );
4947c478bd9Sstevel@tonic-gate 	    rc = LDAP_PARAM_ERROR;
4957c478bd9Sstevel@tonic-gate 	    break;
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate evaluate_line:
4997c478bd9Sstevel@tonic-gate 	if ( dn == NULL ) {
5007c478bd9Sstevel@tonic-gate 	    if ( !use_record && strcasecmp( type, T_REPLICA_STR ) == 0 ) {
5017c478bd9Sstevel@tonic-gate 		++saw_replica;
5027c478bd9Sstevel@tonic-gate 		if (( p = strchr( value, ':' )) == NULL ) {
5037c478bd9Sstevel@tonic-gate 		    replicaport = LDAP_PORT;
5047c478bd9Sstevel@tonic-gate 		} else {
5057c478bd9Sstevel@tonic-gate 		    *p++ = '\0';
5067c478bd9Sstevel@tonic-gate 		    replicaport = atoi( p );
5077c478bd9Sstevel@tonic-gate 		}
5087c478bd9Sstevel@tonic-gate 		if ( strcasecmp( value, ldaptool_host ) == 0 &&
5097c478bd9Sstevel@tonic-gate 			replicaport == ldaptool_port ) {
5107c478bd9Sstevel@tonic-gate 		    use_record = 1;
5117c478bd9Sstevel@tonic-gate 		}
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	    } else if ( strcasecmp( type, T_DN_STR ) == 0 ) {
5147c478bd9Sstevel@tonic-gate 		if (( dn = strdup( value )) == NULL ) {
5157c478bd9Sstevel@tonic-gate 		    perror( "strdup" );
5167c478bd9Sstevel@tonic-gate 		    exit( LDAP_NO_MEMORY );
5177c478bd9Sstevel@tonic-gate 		}
5187c478bd9Sstevel@tonic-gate 		expect_chgtype_or_control = 1;
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	    } else if ( strcasecmp( type, T_VERSION_STR ) == 0 ) {
5217c478bd9Sstevel@tonic-gate 		ldif_version = atoi( value );
5227c478bd9Sstevel@tonic-gate 		if ( ldif_version != LDIF_VERSION_ONE ) {
5237c478bd9Sstevel@tonic-gate 		    fprintf( stderr, gettext("%s:  LDIF version %d is not supported;"
5247c478bd9Sstevel@tonic-gate 			" use version: %d\n"), ldaptool_progname, ldif_version,
5257c478bd9Sstevel@tonic-gate 			LDIF_VERSION_ONE );
5267c478bd9Sstevel@tonic-gate 		    exit( LDAP_PARAM_ERROR );
5277c478bd9Sstevel@tonic-gate 		}
5287c478bd9Sstevel@tonic-gate 		if ( ldaptool_verbose ) {
5297c478bd9Sstevel@tonic-gate 		    printf( gettext("Processing a version %d LDIF file...\n"),
5307c478bd9Sstevel@tonic-gate 			    ldif_version );
5317c478bd9Sstevel@tonic-gate 		}
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 		/* Now check if there's something left to process   */
5347c478bd9Sstevel@tonic-gate 		/* and if not, go get the new record, else continue */
5357c478bd9Sstevel@tonic-gate 		if ( *rbuf == '\0' ) {
5367c478bd9Sstevel@tonic-gate 			return( 0 );
5377c478bd9Sstevel@tonic-gate 		}
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	    } else if ( !saw_replica ) {
5407c478bd9Sstevel@tonic-gate 		printf( gettext("%s: skipping change record: no dn: line\n"),
5417c478bd9Sstevel@tonic-gate 			ldaptool_progname );
5427c478bd9Sstevel@tonic-gate 		return( 0 );
5437c478bd9Sstevel@tonic-gate 	    }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	    continue; /* skip all lines until we see "dn:" */
5467c478bd9Sstevel@tonic-gate 	}
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	if ( expect_chgtype_or_control ) {
5497c478bd9Sstevel@tonic-gate 	    expect_chgtype_or_control = 0;
5507c478bd9Sstevel@tonic-gate 	    if ( !use_record && saw_replica ) {
5517c478bd9Sstevel@tonic-gate 		printf( gettext("%s: skipping change record for entry: %s\n\t(LDAP host/port does not match replica: lines)\n"),
5527c478bd9Sstevel@tonic-gate 			ldaptool_progname, dn );
5537c478bd9Sstevel@tonic-gate 		free( dn );
5547c478bd9Sstevel@tonic-gate 		return( 0 );
5557c478bd9Sstevel@tonic-gate 	    }
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
5587c478bd9Sstevel@tonic-gate 	    if ( strcasecmp( type, "control" ) == 0 ) {
5597c478bd9Sstevel@tonic-gate 		value = strdup_and_trim( value );
5607c478bd9Sstevel@tonic-gate 		if (ldaptool_parse_ctrl_arg(value, ' ', &ctrl_oid,
5617c478bd9Sstevel@tonic-gate 			&ctrl_criticality, &ctrl_value, &vlen)) {
5627c478bd9Sstevel@tonic-gate 			    usage();
5637c478bd9Sstevel@tonic-gate 		}
5647c478bd9Sstevel@tonic-gate         	ldctrl = calloc(1,sizeof(LDAPControl));
5657c478bd9Sstevel@tonic-gate         	if (ctrl_value) {
5667c478bd9Sstevel@tonic-gate         	    rc = ldaptool_berval_from_ldif_value( ctrl_value, vlen,
5677c478bd9Sstevel@tonic-gate 			 &(ldctrl->ldctl_value),
5687c478bd9Sstevel@tonic-gate 			 1 /* recognize file URLs */, 0 /* always try file */,
5697c478bd9Sstevel@tonic-gate             		 1 /* report errors */ );
5707c478bd9Sstevel@tonic-gate         	    if ((rc = ldaptool_fileurlerr2ldaperr( rc )) != LDAP_SUCCESS) {
5717c478bd9Sstevel@tonic-gate             		fprintf( stderr, gettext("Unable to parse %s\n"), ctrl_value);
5727c478bd9Sstevel@tonic-gate             		usage();
5737c478bd9Sstevel@tonic-gate         	    }
5747c478bd9Sstevel@tonic-gate         	}
5757c478bd9Sstevel@tonic-gate         	ldctrl->ldctl_oid = ctrl_oid;
5767c478bd9Sstevel@tonic-gate         	ldctrl->ldctl_iscritical = ctrl_criticality;
5777c478bd9Sstevel@tonic-gate         	ldaptool_add_control_to_array(ldctrl, ldaptool_request_ctrls);
5787c478bd9Sstevel@tonic-gate 		expect_chgtype_or_control = 1;
5797c478bd9Sstevel@tonic-gate 		continue;
5807c478bd9Sstevel@tonic-gate 	    }
5817c478bd9Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	    if ( strcasecmp( type, T_CHANGETYPESTR ) == 0 ) {
5847c478bd9Sstevel@tonic-gate 		value = strdup_and_trim( value );
5857c478bd9Sstevel@tonic-gate 		if ( strcasecmp( value, T_MODIFYCTSTR ) == 0 ) {
5867c478bd9Sstevel@tonic-gate 		    new_entry = 0;
5877c478bd9Sstevel@tonic-gate 		    expect_modop = 1;
5887c478bd9Sstevel@tonic-gate 		} else if ( strcasecmp( value, T_ADDCTSTR ) == 0 ) {
5897c478bd9Sstevel@tonic-gate 		    new_entry = 1;
5907c478bd9Sstevel@tonic-gate 		    modop = LDAP_MOD_ADD;
5917c478bd9Sstevel@tonic-gate 		} else if ( strcasecmp( value, T_MODRDNCTSTR ) == 0 ) {
5927c478bd9Sstevel@tonic-gate 		    expect_newrdn = 1;
5937c478bd9Sstevel@tonic-gate 		    moddn = 1;
5947c478bd9Sstevel@tonic-gate 		} else if ( strcasecmp( value, T_MODDNCTSTR ) == 0 ) {
5957c478bd9Sstevel@tonic-gate 		    expect_newrdn = 1;
5967c478bd9Sstevel@tonic-gate 		    moddn = 1;
5977c478bd9Sstevel@tonic-gate 		} else if ( strcasecmp( value, T_RENAMECTSTR ) == 0 ) {
5987c478bd9Sstevel@tonic-gate 		    expect_newrdn = 1;
5997c478bd9Sstevel@tonic-gate 		    rename = 1;
6007c478bd9Sstevel@tonic-gate 		} else if ( strcasecmp( value, T_DELETECTSTR ) == 0 ) {
6017c478bd9Sstevel@tonic-gate 		    got_all = delete_entry = 1;
6027c478bd9Sstevel@tonic-gate 		} else {
6037c478bd9Sstevel@tonic-gate 		    fprintf( stderr,
6047c478bd9Sstevel@tonic-gate 			    gettext("%s:  unknown %s \"%s\" (line %d of entry: %s)\n"),
6057c478bd9Sstevel@tonic-gate 			    ldaptool_progname, T_CHANGETYPESTR, value,
6067c478bd9Sstevel@tonic-gate 			    linenum, dn );
6077c478bd9Sstevel@tonic-gate 		    rc = LDAP_PARAM_ERROR;
6087c478bd9Sstevel@tonic-gate 		}
6097c478bd9Sstevel@tonic-gate 		free( value );
6107c478bd9Sstevel@tonic-gate 		continue;
6117c478bd9Sstevel@tonic-gate 	    } else if ( newval ) {		/*  missing changetype => add */
6127c478bd9Sstevel@tonic-gate 		new_entry = 1;
6137c478bd9Sstevel@tonic-gate 		modop = LDAP_MOD_ADD;
6147c478bd9Sstevel@tonic-gate 	    } else {
6157c478bd9Sstevel@tonic-gate 	      /*The user MUST put in changetype: blah
6167c478bd9Sstevel@tonic-gate 	       unless adding a new entry with either -a or ldapadd*/
6177c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("%s: Missing changetype operation specification.\n\tThe dn line must be followed by \"changetype: operation\"\n\t(unless ldapmodify is called with -a option)\n\twhere operation is add|delete|modify|modrdn|moddn|rename\n\t\"%s\" is not a valid changetype operation specification\n\t(line %d of entry %s)\n"),
6187c478bd9Sstevel@tonic-gate 		ldaptool_progname, type, linenum, dn);
6197c478bd9Sstevel@tonic-gate 		rc = LDAP_PARAM_ERROR;
6207c478bd9Sstevel@tonic-gate 		/*expect_modop = 1;	 missing changetype => modify */
6217c478bd9Sstevel@tonic-gate 	    }
6227c478bd9Sstevel@tonic-gate 	}
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	if ( expect_modop ) {
6257c478bd9Sstevel@tonic-gate 	    expect_modop = 0;
6267c478bd9Sstevel@tonic-gate 	    expect_sep = 1;
6277c478bd9Sstevel@tonic-gate 	    if ( strcasecmp( type, T_MODOPADDSTR ) == 0 ) {
6287c478bd9Sstevel@tonic-gate 		modop = LDAP_MOD_ADD;
6297c478bd9Sstevel@tonic-gate 		continue;
6307c478bd9Sstevel@tonic-gate 	    } else if ( strcasecmp( type, T_MODOPREPLACESTR ) == 0 ) {
6317c478bd9Sstevel@tonic-gate 		modop = LDAP_MOD_REPLACE;
6327c478bd9Sstevel@tonic-gate 		continue;
6337c478bd9Sstevel@tonic-gate 	    } else if ( strcasecmp( type, T_MODOPDELETESTR ) == 0 ) {
6347c478bd9Sstevel@tonic-gate 		modop = LDAP_MOD_DELETE;
6357c478bd9Sstevel@tonic-gate 		addmodifyop( &pmods, modop, value, NULL, 0 );
6367c478bd9Sstevel@tonic-gate 		continue;
6377c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
6387c478bd9Sstevel@tonic-gate 	    }  else { /* no modify op: use default */
6397c478bd9Sstevel@tonic-gate 		modop = replace ? LDAP_MOD_REPLACE : LDAP_MOD_ADD;
6407c478bd9Sstevel@tonic-gate 	    }
6417c478bd9Sstevel@tonic-gate #else
6427c478bd9Sstevel@tonic-gate 	    }  else { /*Bug 27479. Remove default add operation*/
6437c478bd9Sstevel@tonic-gate 	      fprintf(stderr, gettext("%s: Invalid parameter \"%s\" specified for changetype modify (line %d of entry %s)\n"),
6447c478bd9Sstevel@tonic-gate 		      ldaptool_progname, type, linenum, dn);
6457c478bd9Sstevel@tonic-gate 	      rc = LDAP_PARAM_ERROR;
6467c478bd9Sstevel@tonic-gate 	    }
6477c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 	  }
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	if ( expect_newrdn ) {
6527c478bd9Sstevel@tonic-gate 	    if ( strcasecmp( type, T_NEWRDNSTR ) == 0 ) {
6537c478bd9Sstevel@tonic-gate 		if ( *value == '\0' ) {
6547c478bd9Sstevel@tonic-gate 		    fprintf( stderr,
6557c478bd9Sstevel@tonic-gate 			    gettext("%s: newrdn value missing (line %d of entry: %s)\n"),
6567c478bd9Sstevel@tonic-gate 			    ldaptool_progname, linenum, dn == NULL ? "" : dn );
6577c478bd9Sstevel@tonic-gate 		    rc = LDAP_PARAM_ERROR;
6587c478bd9Sstevel@tonic-gate 		} else if (( newrdn = strdup( value )) == NULL ) {
6597c478bd9Sstevel@tonic-gate 		    perror( "strdup" );
6607c478bd9Sstevel@tonic-gate 		    exit( LDAP_NO_MEMORY );
6617c478bd9Sstevel@tonic-gate 		} else {
6627c478bd9Sstevel@tonic-gate 		    expect_newrdn = 0;
6637c478bd9Sstevel@tonic-gate 		    if ( rename ) {
6647c478bd9Sstevel@tonic-gate 			expect_newparent = 1;
6657c478bd9Sstevel@tonic-gate 		    } else {
6667c478bd9Sstevel@tonic-gate 			expect_deleteoldrdn = 1;
6677c478bd9Sstevel@tonic-gate 		    }
6687c478bd9Sstevel@tonic-gate 		}
6697c478bd9Sstevel@tonic-gate 	    } else {
6707c478bd9Sstevel@tonic-gate 		fprintf( stderr, gettext("%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n"),
6717c478bd9Sstevel@tonic-gate 			ldaptool_progname, T_NEWRDNSTR, type, linenum, dn );
6727c478bd9Sstevel@tonic-gate 		rc = LDAP_PARAM_ERROR;
6737c478bd9Sstevel@tonic-gate 	    }
6747c478bd9Sstevel@tonic-gate 	} else if ( expect_newparent ) {
6757c478bd9Sstevel@tonic-gate 	    expect_newparent = 0;
6767c478bd9Sstevel@tonic-gate 	    if ( rename ) {
6777c478bd9Sstevel@tonic-gate 		expect_deleteoldrdn = 1;
6787c478bd9Sstevel@tonic-gate 	    }
6797c478bd9Sstevel@tonic-gate 	    if ( strcasecmp( type, T_NEWPARENTSTR ) == 0
6807c478bd9Sstevel@tonic-gate 		    || strcasecmp( type, T_NEWSUPERIORSTR ) == 0 ) {
6817c478bd9Sstevel@tonic-gate 		if (( newparent = strdup( value )) == NULL ) {
6827c478bd9Sstevel@tonic-gate 		    perror( "strdup" );
6837c478bd9Sstevel@tonic-gate 		    exit( LDAP_NO_MEMORY );
6847c478bd9Sstevel@tonic-gate 		}
6857c478bd9Sstevel@tonic-gate 	    } else {
6867c478bd9Sstevel@tonic-gate 		/* Since this is an optional argument for rename/moddn, cause
6877c478bd9Sstevel@tonic-gate 		 * the current line to be re-evaluated if newparent doesn't
6887c478bd9Sstevel@tonic-gate 		 * follow deleteoldrdn.
6897c478bd9Sstevel@tonic-gate 		 */
6907c478bd9Sstevel@tonic-gate 		newparent = NULL;
6917c478bd9Sstevel@tonic-gate 		goto evaluate_line;
6927c478bd9Sstevel@tonic-gate 	    }
6937c478bd9Sstevel@tonic-gate 	} else if ( expect_deleteoldrdn ) {
6947c478bd9Sstevel@tonic-gate 	    if ( strcasecmp( type, T_DELETEOLDRDNSTR ) == 0 ) {
6957c478bd9Sstevel@tonic-gate 		if ( *value == '\0' ) {
6967c478bd9Sstevel@tonic-gate 		    fprintf( stderr,
6977c478bd9Sstevel@tonic-gate 			    gettext("%s: missing 0 or 1 (line %d of entry: %s)\n"),
6987c478bd9Sstevel@tonic-gate 			    ldaptool_progname, linenum, dn == NULL ? "" : dn );
6997c478bd9Sstevel@tonic-gate 		    rc = LDAP_PARAM_ERROR;
7007c478bd9Sstevel@tonic-gate 		} else {
7017c478bd9Sstevel@tonic-gate 		    deleteoldrdn = ( *value == '0' ) ? 0 : 1;
7027c478bd9Sstevel@tonic-gate 		    expect_deleteoldrdn = 0;
7037c478bd9Sstevel@tonic-gate 		    if ( moddn ) {
7047c478bd9Sstevel@tonic-gate 			expect_newparent = 1;
7057c478bd9Sstevel@tonic-gate 		    }
7067c478bd9Sstevel@tonic-gate 		}
7077c478bd9Sstevel@tonic-gate 	    } else {
7087c478bd9Sstevel@tonic-gate 		fprintf( stderr, gettext("%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n"),
7097c478bd9Sstevel@tonic-gate 			ldaptool_progname, T_DELETEOLDRDNSTR, type, linenum,
7107c478bd9Sstevel@tonic-gate 			dn );
7117c478bd9Sstevel@tonic-gate 		rc = LDAP_PARAM_ERROR;
7127c478bd9Sstevel@tonic-gate 	    }
7137c478bd9Sstevel@tonic-gate 	    got_all = 1;
7147c478bd9Sstevel@tonic-gate 	} else if ( got_all ) {
7157c478bd9Sstevel@tonic-gate 	    fprintf( stderr,
7167c478bd9Sstevel@tonic-gate 		    gettext("%s: extra lines at end (line %d of entry %s)\n"),
7177c478bd9Sstevel@tonic-gate 		    ldaptool_progname, linenum, dn );
7187c478bd9Sstevel@tonic-gate 	    rc = LDAP_PARAM_ERROR;
7197c478bd9Sstevel@tonic-gate 	    got_all = 1;
7207c478bd9Sstevel@tonic-gate 	} else {
7217c478bd9Sstevel@tonic-gate 	    addmodifyop( &pmods, modop, type, value, vlen );
7227c478bd9Sstevel@tonic-gate 	    /*There was a value to replace*/
7237c478bd9Sstevel@tonic-gate 	    got_value = 1;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	}
7267c478bd9Sstevel@tonic-gate     }
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate     if ( rc == 0 ) {
7297c478bd9Sstevel@tonic-gate 	if ( delete_entry ) {
7307c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7317c478bd9Sstevel@tonic-gate 	    rc = dodelete( ld, dn );
7327c478bd9Sstevel@tonic-gate #else
7337c478bd9Sstevel@tonic-gate 	    rc = dodelete( dn );
7347c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
7357c478bd9Sstevel@tonic-gate 	} else if ( newrdn != NULL ) {
7367c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7377c478bd9Sstevel@tonic-gate 	    rc = dorename( ld, dn, newrdn, newparent, deleteoldrdn );
7387c478bd9Sstevel@tonic-gate #else
7397c478bd9Sstevel@tonic-gate 	    rc = dorename( dn, newrdn, newparent, deleteoldrdn );
7407c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
7417c478bd9Sstevel@tonic-gate 	    rename = 0;
7427c478bd9Sstevel@tonic-gate 	} else {
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	  /*Patch to fix Bug 22183
7457c478bd9Sstevel@tonic-gate 	    If pmods is null, then there is no
7467c478bd9Sstevel@tonic-gate 	    attribute to replace, so we alloc
7477c478bd9Sstevel@tonic-gate 	    an empty pmods*/
7487c478bd9Sstevel@tonic-gate 	  if (modop == LDAP_MOD_REPLACE && !got_value && expect_sep){
7497c478bd9Sstevel@tonic-gate 	    addmodifyop( &pmods, modop, value, NULL, 0);
7507c478bd9Sstevel@tonic-gate 	  }/*End Patch*/
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7547c478bd9Sstevel@tonic-gate 	  rc = domodify( ld, dn, pmods, new_entry );
7557c478bd9Sstevel@tonic-gate #else
7567c478bd9Sstevel@tonic-gate 	  rc = domodify( dn, pmods, new_entry );
7577c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
7587c478bd9Sstevel@tonic-gate 	}
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	if ( rc == LDAP_SUCCESS ) {
7617c478bd9Sstevel@tonic-gate 	    rc = 0;
7627c478bd9Sstevel@tonic-gate 	}
7637c478bd9Sstevel@tonic-gate     }
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate     if ( dn != NULL ) {
7667c478bd9Sstevel@tonic-gate 	free( dn );
7677c478bd9Sstevel@tonic-gate     }
7687c478bd9Sstevel@tonic-gate     if ( newrdn != NULL ) {
7697c478bd9Sstevel@tonic-gate 	free( newrdn );
7707c478bd9Sstevel@tonic-gate     }
7717c478bd9Sstevel@tonic-gate     if ( newparent != NULL ) {
7727c478bd9Sstevel@tonic-gate 	free( newparent );
7737c478bd9Sstevel@tonic-gate     }
7747c478bd9Sstevel@tonic-gate     if ( pmods != NULL ) {
7757c478bd9Sstevel@tonic-gate 	freepmods( pmods );
7767c478bd9Sstevel@tonic-gate     }
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate     return( rc );
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate static int
7837c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7847c478bd9Sstevel@tonic-gate process_ldapmod_rec( LDAP *ld, char *rbuf )
7857c478bd9Sstevel@tonic-gate #else
7867c478bd9Sstevel@tonic-gate process_ldapmod_rec( char *rbuf )
7877c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
7887c478bd9Sstevel@tonic-gate {
7897c478bd9Sstevel@tonic-gate     char	*line, *dn, *p, *q, *attr, *value;
7907c478bd9Sstevel@tonic-gate     int		rc, linenum, modop;
7917c478bd9Sstevel@tonic-gate     LDAPMod	**pmods;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate     pmods = NULL;
7947c478bd9Sstevel@tonic-gate     dn = NULL;
7957c478bd9Sstevel@tonic-gate     linenum = 0;
7967c478bd9Sstevel@tonic-gate     line = rbuf;
7977c478bd9Sstevel@tonic-gate     rc = 0;
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate     while ( rc == 0 && rbuf != NULL && *rbuf != '\0' ) {
8007c478bd9Sstevel@tonic-gate 	++linenum;
8017c478bd9Sstevel@tonic-gate 	if (( p = strchr( rbuf, '\n' )) == NULL ) {
8027c478bd9Sstevel@tonic-gate 	    rbuf = NULL;
8037c478bd9Sstevel@tonic-gate 	} else {
8047c478bd9Sstevel@tonic-gate 	    if ( *(p-1) == '\\' ) {	/* lines ending in '\' are continued */
8057c478bd9Sstevel@tonic-gate 		strcpy( p - 1, p );
8067c478bd9Sstevel@tonic-gate 		rbuf = p;
8077c478bd9Sstevel@tonic-gate 		continue;
8087c478bd9Sstevel@tonic-gate 	    }
8097c478bd9Sstevel@tonic-gate 	    *p++ = '\0';
8107c478bd9Sstevel@tonic-gate 	    rbuf = p;
8117c478bd9Sstevel@tonic-gate 	}
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	if ( dn == NULL ) {	/* first line contains DN */
8147c478bd9Sstevel@tonic-gate 	    if (( dn = strdup( line )) == NULL ) {
8157c478bd9Sstevel@tonic-gate 		perror( "strdup" );
8167c478bd9Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
8177c478bd9Sstevel@tonic-gate 	    }
8187c478bd9Sstevel@tonic-gate 	} else {
8197c478bd9Sstevel@tonic-gate 	    if (( p = strchr( line, '=' )) == NULL ) {
8207c478bd9Sstevel@tonic-gate 		value = NULL;
8217c478bd9Sstevel@tonic-gate 		p = line + strlen( line );
8227c478bd9Sstevel@tonic-gate 	    } else {
8237c478bd9Sstevel@tonic-gate 		*p++ = '\0';
8247c478bd9Sstevel@tonic-gate 		value = p;
8257c478bd9Sstevel@tonic-gate 	    }
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	    for ( attr = line; *attr != '\0' && isspace( *attr ); ++attr ) {
8287c478bd9Sstevel@tonic-gate 		;	/* skip attribute leading white space */
8297c478bd9Sstevel@tonic-gate 	    }
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	    for ( q = p - 1; q > attr && isspace( *q ); --q ) {
8327c478bd9Sstevel@tonic-gate 		*q = '\0';	/* remove attribute trailing white space */
8337c478bd9Sstevel@tonic-gate 	    }
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	    if ( value != NULL ) {
8367c478bd9Sstevel@tonic-gate 		while ( isspace( *value )) {
8377c478bd9Sstevel@tonic-gate 		    ++value;		/* skip value leading white space */
8387c478bd9Sstevel@tonic-gate 		}
8397c478bd9Sstevel@tonic-gate 		for ( q = value + strlen( value ) - 1; q > value &&
8407c478bd9Sstevel@tonic-gate 			isspace( *q ); --q ) {
8417c478bd9Sstevel@tonic-gate 		    *q = '\0';	/* remove value trailing white space */
8427c478bd9Sstevel@tonic-gate 		}
8437c478bd9Sstevel@tonic-gate 		if ( *value == '\0' ) {
8447c478bd9Sstevel@tonic-gate 		    value = NULL;
8457c478bd9Sstevel@tonic-gate 		}
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	    }
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	    if ( value == NULL && newval ) {
8507c478bd9Sstevel@tonic-gate 		fprintf( stderr, gettext("%s: missing value on line %d (attr is %s)\n"),
8517c478bd9Sstevel@tonic-gate 			ldaptool_progname, linenum, attr );
8527c478bd9Sstevel@tonic-gate 		rc = LDAP_PARAM_ERROR;
8537c478bd9Sstevel@tonic-gate 	    } else {
8547c478bd9Sstevel@tonic-gate 		 switch ( *attr ) {
8557c478bd9Sstevel@tonic-gate 		case '-':
8567c478bd9Sstevel@tonic-gate 		    modop = LDAP_MOD_DELETE;
8577c478bd9Sstevel@tonic-gate 		    ++attr;
8587c478bd9Sstevel@tonic-gate 		    break;
8597c478bd9Sstevel@tonic-gate 		case '+':
8607c478bd9Sstevel@tonic-gate 		    modop = LDAP_MOD_ADD;
8617c478bd9Sstevel@tonic-gate 		    ++attr;
8627c478bd9Sstevel@tonic-gate 		    break;
8637c478bd9Sstevel@tonic-gate 		default:
8647c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
8657c478bd9Sstevel@tonic-gate 		    modop = replace ? LDAP_MOD_REPLACE : LDAP_MOD_ADD;
8667c478bd9Sstevel@tonic-gate #else
8677c478bd9Sstevel@tonic-gate 		    /*Bug 27479. Remove the add default*/
8687c478bd9Sstevel@tonic-gate 		      fprintf(stderr, gettext("%s: Invalid parameter specified for changetype modify (line %d of entry %s)\n"),
8697c478bd9Sstevel@tonic-gate 		      ldaptool_progname, linenum, dn);
8707c478bd9Sstevel@tonic-gate 		      rc = LDAP_PARAM_ERROR;
8717c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
8727c478bd9Sstevel@tonic-gate 		}
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 		addmodifyop( &pmods, modop, attr, value,
8757c478bd9Sstevel@tonic-gate 			( value == NULL ) ? 0 : strlen( value ));
8767c478bd9Sstevel@tonic-gate 	    }
8777c478bd9Sstevel@tonic-gate 	}
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	line = rbuf;
8807c478bd9Sstevel@tonic-gate     }
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate     if ( rc == 0 ) {
8837c478bd9Sstevel@tonic-gate 	if ( dn == NULL ) {
8847c478bd9Sstevel@tonic-gate 	    rc = LDAP_PARAM_ERROR;
8857c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
8867c478bd9Sstevel@tonic-gate 	} else if (( rc = domodify( ld, dn, pmods, newval )) == LDAP_SUCCESS ){
8877c478bd9Sstevel@tonic-gate #else
8887c478bd9Sstevel@tonic-gate 	} else if (( rc = domodify( dn, pmods, newval )) == LDAP_SUCCESS ){
8897c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
8907c478bd9Sstevel@tonic-gate 	  rc = 0;
8917c478bd9Sstevel@tonic-gate 	}
8927c478bd9Sstevel@tonic-gate       }
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate     if ( pmods != NULL ) {
8957c478bd9Sstevel@tonic-gate 	freepmods( pmods );
8967c478bd9Sstevel@tonic-gate     }
8977c478bd9Sstevel@tonic-gate     if ( dn != NULL ) {
8987c478bd9Sstevel@tonic-gate 	free( dn );
8997c478bd9Sstevel@tonic-gate     }
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate     return( rc );
9027c478bd9Sstevel@tonic-gate }
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate static void
9067c478bd9Sstevel@tonic-gate addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
9077c478bd9Sstevel@tonic-gate {
9087c478bd9Sstevel@tonic-gate     LDAPMod		**pmods;
9097c478bd9Sstevel@tonic-gate     int			i, j, rc;
9107c478bd9Sstevel@tonic-gate     struct berval	*bvp;
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate     pmods = *pmodsp;
9137c478bd9Sstevel@tonic-gate     modop |= LDAP_MOD_BVALUES;
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate     i = 0;
9167c478bd9Sstevel@tonic-gate     if ( pmods != NULL ) {
9177c478bd9Sstevel@tonic-gate 	for ( ; pmods[ i ] != NULL; ++i ) {
9187c478bd9Sstevel@tonic-gate 	    if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
9197c478bd9Sstevel@tonic-gate 		    pmods[ i ]->mod_op == modop ) {
9207c478bd9Sstevel@tonic-gate 		break;
9217c478bd9Sstevel@tonic-gate 	    }
9227c478bd9Sstevel@tonic-gate 	}
9237c478bd9Sstevel@tonic-gate     }
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate     if ( pmods == NULL || pmods[ i ] == NULL ) {
9267c478bd9Sstevel@tonic-gate 	if (( pmods = (LDAPMod **)LDAPTOOL_SAFEREALLOC( pmods, (i + 2) *
9277c478bd9Sstevel@tonic-gate 		sizeof( LDAPMod * ))) == NULL ) {
9287c478bd9Sstevel@tonic-gate 	    perror( "realloc" );
9297c478bd9Sstevel@tonic-gate 	    exit( LDAP_NO_MEMORY );
9307c478bd9Sstevel@tonic-gate 	}
9317c478bd9Sstevel@tonic-gate 	*pmodsp = pmods;
9327c478bd9Sstevel@tonic-gate 	pmods[ i + 1 ] = NULL;
9337c478bd9Sstevel@tonic-gate 	if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
9347c478bd9Sstevel@tonic-gate 		== NULL ) {
9357c478bd9Sstevel@tonic-gate 	    perror( "calloc" );
9367c478bd9Sstevel@tonic-gate 	    exit( LDAP_NO_MEMORY );
9377c478bd9Sstevel@tonic-gate 	}
9387c478bd9Sstevel@tonic-gate 	pmods[ i ]->mod_op = modop;
9397c478bd9Sstevel@tonic-gate 	if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
9407c478bd9Sstevel@tonic-gate 	    perror( "strdup" );
9417c478bd9Sstevel@tonic-gate 	    exit( LDAP_NO_MEMORY );
9427c478bd9Sstevel@tonic-gate 	}
9437c478bd9Sstevel@tonic-gate     }
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate     if ( value != NULL ) {
9467c478bd9Sstevel@tonic-gate 	j = 0;
9477c478bd9Sstevel@tonic-gate 	if ( pmods[ i ]->mod_bvalues != NULL ) {
9487c478bd9Sstevel@tonic-gate 	    for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
9497c478bd9Sstevel@tonic-gate 		;
9507c478bd9Sstevel@tonic-gate 	    }
9517c478bd9Sstevel@tonic-gate 	}
9527c478bd9Sstevel@tonic-gate 	if (( pmods[ i ]->mod_bvalues = (struct berval **)
9537c478bd9Sstevel@tonic-gate 		LDAPTOOL_SAFEREALLOC( pmods[ i ]->mod_bvalues,
9547c478bd9Sstevel@tonic-gate 		(j + 2) * sizeof( struct berval * ))) == NULL ) {
9557c478bd9Sstevel@tonic-gate 	    perror( "realloc" );
9567c478bd9Sstevel@tonic-gate 	    exit( LDAP_NO_MEMORY );
9577c478bd9Sstevel@tonic-gate 	}
9587c478bd9Sstevel@tonic-gate 	pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
9597c478bd9Sstevel@tonic-gate 	if (( bvp = (struct berval *)malloc( sizeof( struct berval )))
9607c478bd9Sstevel@tonic-gate 		== NULL ) {
9617c478bd9Sstevel@tonic-gate 	    perror( "malloc" );
9627c478bd9Sstevel@tonic-gate 	    exit( LDAP_NO_MEMORY );
9637c478bd9Sstevel@tonic-gate 	}
9647c478bd9Sstevel@tonic-gate 	pmods[ i ]->mod_bvalues[ j ] = bvp;
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate #ifdef notdef
9677c478bd9Sstevel@tonic-gate 	if (ldaptool_verbose) {
9687c478bd9Sstevel@tonic-gate 		printf(gettext("%s: value: %s vlen: %d\n"), "ldapmodify", value, vlen);
9697c478bd9Sstevel@tonic-gate 	}
9707c478bd9Sstevel@tonic-gate #endif
9717c478bd9Sstevel@tonic-gate 	rc = ldaptool_berval_from_ldif_value( value, vlen, bvp,
9727c478bd9Sstevel@tonic-gate 		    ( ldif_version >= LDIF_VERSION_ONE ), valsfromfiles,
9737c478bd9Sstevel@tonic-gate 			1 /* report errors */ );
9747c478bd9Sstevel@tonic-gate 	if ( rc != LDAPTOOL_FILEURL_SUCCESS ) {
9757c478bd9Sstevel@tonic-gate 	    exit( ldaptool_fileurlerr2ldaperr( rc ));
9767c478bd9Sstevel@tonic-gate 	}
9777c478bd9Sstevel@tonic-gate     }
9787c478bd9Sstevel@tonic-gate }
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate static int
9827c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
9837c478bd9Sstevel@tonic-gate domodify( LDAP *ld, char *dn, LDAPMod **pmods, int newentry )
9847c478bd9Sstevel@tonic-gate #else
9857c478bd9Sstevel@tonic-gate domodify( char *dn, LDAPMod **pmods, int newentry )
9867c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
9877c478bd9Sstevel@tonic-gate {
9887c478bd9Sstevel@tonic-gate     int			i, j, notascii, op;
9897c478bd9Sstevel@tonic-gate     struct berval	*bvp;
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate     if ( pmods == NULL ) {
9927c478bd9Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: no attributes to change or add (entry %s)\n"),
9937c478bd9Sstevel@tonic-gate 		ldaptool_progname, dn );
9947c478bd9Sstevel@tonic-gate 	return( LDAP_PARAM_ERROR );
9957c478bd9Sstevel@tonic-gate     }
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate     if ( ldaptool_verbose ) {
9987c478bd9Sstevel@tonic-gate 	for ( i = 0; pmods[ i ] != NULL; ++i ) {
9997c478bd9Sstevel@tonic-gate 	    op = pmods[ i ]->mod_op & ~LDAP_MOD_BVALUES;
10007c478bd9Sstevel@tonic-gate 	    printf( gettext("%s %s:\n"), op == LDAP_MOD_REPLACE ?
10017c478bd9Sstevel@tonic-gate 		    gettext("replace") : op == LDAP_MOD_ADD ?
10027c478bd9Sstevel@tonic-gate 		    gettext("add") : gettext("delete"), pmods[ i ]->mod_type );
10037c478bd9Sstevel@tonic-gate 	    if ( pmods[ i ]->mod_bvalues != NULL ) {
10047c478bd9Sstevel@tonic-gate 		for ( j = 0; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
10057c478bd9Sstevel@tonic-gate 		    bvp = pmods[ i ]->mod_bvalues[ j ];
10067c478bd9Sstevel@tonic-gate 		    notascii = 0;
10077c478bd9Sstevel@tonic-gate 		    if ( !display_binary_values ) {
10087c478bd9Sstevel@tonic-gate 			notascii = !ldaptool_berval_is_ascii( bvp );
10097c478bd9Sstevel@tonic-gate 		    }
10107c478bd9Sstevel@tonic-gate 		    if ( notascii ) {
10117c478bd9Sstevel@tonic-gate 			printf( gettext("\tNOT ASCII (%ld bytes)\n"), bvp->bv_len );
10127c478bd9Sstevel@tonic-gate 		    } else {
10137c478bd9Sstevel@tonic-gate 			printf( "\t%s\n", bvp->bv_val );
10147c478bd9Sstevel@tonic-gate 		    }
10157c478bd9Sstevel@tonic-gate 		}
10167c478bd9Sstevel@tonic-gate 	    }
10177c478bd9Sstevel@tonic-gate 	}
10187c478bd9Sstevel@tonic-gate     }
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate     if ( !ldapmodify_quiet) {
10217c478bd9Sstevel@tonic-gate 	if ( newentry ) {
10227c478bd9Sstevel@tonic-gate 	    printf( gettext("%sadding new entry %s\n"),
10237c478bd9Sstevel@tonic-gate 		ldaptool_not ? "!" : "", dn );
10247c478bd9Sstevel@tonic-gate 	} else {
10257c478bd9Sstevel@tonic-gate 	    printf( gettext("%smodifying entry %s\n"),
10267c478bd9Sstevel@tonic-gate 		ldaptool_not ? "!" : "", dn );
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate     }
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate     if ( !ldaptool_not ) {
10317c478bd9Sstevel@tonic-gate 	if ( newentry ) {
10327c478bd9Sstevel@tonic-gate 	unsigned int	sleep_interval = 2; /* seconds */
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
10357c478bd9Sstevel@tonic-gate 	    /* Backward compatibility with old Solaris command */
10367c478bd9Sstevel@tonic-gate 	    unsigned int nb = 0;
10377c478bd9Sstevel@tonic-gate 	    timestruc_t to;
10387c478bd9Sstevel@tonic-gate 	    while ((i = ldaptool_add_ext_s( ld, dn, pmods,
10397c478bd9Sstevel@tonic-gate 			ldaptool_request_ctrls, NULL, "ldap_add" ))
10407c478bd9Sstevel@tonic-gate 			!= LDAP_SUCCESS) {
10417c478bd9Sstevel@tonic-gate 		if (i == LDAP_BUSY) {
10427c478bd9Sstevel@tonic-gate 			if ( sleep_interval > 3600 ) {
10437c478bd9Sstevel@tonic-gate 				printf(gettext("ldap_add: Unable to complete "
10447c478bd9Sstevel@tonic-gate 						"request.  Server is too "
10457c478bd9Sstevel@tonic-gate 						"busy servicing other "
10467c478bd9Sstevel@tonic-gate 						"requests\n"));
10477c478bd9Sstevel@tonic-gate 				break;
10487c478bd9Sstevel@tonic-gate 			}
10497c478bd9Sstevel@tonic-gate 			if ( !ldapmodify_quiet ) {
10507c478bd9Sstevel@tonic-gate 				printf(gettext("ldap_add: LDAP_BUSY returned "
10517c478bd9Sstevel@tonic-gate 						"by server.  Will retry "
10527c478bd9Sstevel@tonic-gate 						"operation in %d seconds\n"),
10537c478bd9Sstevel@tonic-gate 						sleep_interval);
10547c478bd9Sstevel@tonic-gate 			}
10557c478bd9Sstevel@tonic-gate 			sleep( sleep_interval );
10567c478bd9Sstevel@tonic-gate 			sleep_interval *= 2;
10577c478bd9Sstevel@tonic-gate 		} else if (i == LDAP_NO_SUCH_OBJECT) {
10587c478bd9Sstevel@tonic-gate 			/*
10597c478bd9Sstevel@tonic-gate 			 * Wait for the parent entry to be created by
10607c478bd9Sstevel@tonic-gate 			 * another thread. Do not retry more than the
10617c478bd9Sstevel@tonic-gate 			 * number of threads.
10627c478bd9Sstevel@tonic-gate 			 */
10637c478bd9Sstevel@tonic-gate 			++nb;
10647c478bd9Sstevel@tonic-gate 			if (nb >= nbthreads)
10657c478bd9Sstevel@tonic-gate 				break;
10667c478bd9Sstevel@tonic-gate 			mutex_lock(&wait_mutex);
10677c478bd9Sstevel@tonic-gate 			to.tv_sec = 5;
10687c478bd9Sstevel@tonic-gate 			to.tv_nsec = 0;
10697c478bd9Sstevel@tonic-gate 			if (cond_reltimedwait(&wait_cond, &wait_mutex, &to)
10707c478bd9Sstevel@tonic-gate 				== ETIME) {
10717c478bd9Sstevel@tonic-gate 					nb = nbthreads; /* last chance */
10727c478bd9Sstevel@tonic-gate 			}
10737c478bd9Sstevel@tonic-gate 			mutex_unlock(&wait_mutex);
10747c478bd9Sstevel@tonic-gate 		} else {
10757c478bd9Sstevel@tonic-gate 			break;
10767c478bd9Sstevel@tonic-gate 		}
10777c478bd9Sstevel@tonic-gate 	    }
10787c478bd9Sstevel@tonic-gate 	    cond_broadcast(&wait_cond);
10797c478bd9Sstevel@tonic-gate #else
10807c478bd9Sstevel@tonic-gate 	    while ((i = ldaptool_add_ext_s( ld, dn, pmods,
10817c478bd9Sstevel@tonic-gate 			ldaptool_request_ctrls, NULL, "ldap_add" ))
10827c478bd9Sstevel@tonic-gate 			== LDAP_BUSY) {
10837c478bd9Sstevel@tonic-gate 		if ( sleep_interval > 3600 ) {
10847c478bd9Sstevel@tonic-gate 			printf("ldap_add: Unable to complete request. ");
10857c478bd9Sstevel@tonic-gate 			printf("Server is too ");
10867c478bd9Sstevel@tonic-gate 			printf("busy servicing other requests\n");
10877c478bd9Sstevel@tonic-gate 			break;
10887c478bd9Sstevel@tonic-gate 		}
10897c478bd9Sstevel@tonic-gate 		if ( !ldapmodify_quiet ) {
10907c478bd9Sstevel@tonic-gate 			printf("ldap_add: LDAP_BUSY returned by server. ");
10917c478bd9Sstevel@tonic-gate 			printf("Will retry operation ");
10927c478bd9Sstevel@tonic-gate 			printf("in %d seconds\n", sleep_interval);
10937c478bd9Sstevel@tonic-gate 		}
10947c478bd9Sstevel@tonic-gate 		sleep( sleep_interval );
10957c478bd9Sstevel@tonic-gate 		sleep_interval *= 2;
10967c478bd9Sstevel@tonic-gate 	    }
10977c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
10987c478bd9Sstevel@tonic-gate 	} else {
10997c478bd9Sstevel@tonic-gate 	    i = ldaptool_modify_ext_s( ld, dn, pmods, ldaptool_request_ctrls,
11007c478bd9Sstevel@tonic-gate 		    NULL, "ldap_modify" );
11017c478bd9Sstevel@tonic-gate 	}
11027c478bd9Sstevel@tonic-gate 	if ( i == LDAP_SUCCESS && ldaptool_verbose ) {
11037c478bd9Sstevel@tonic-gate 	    printf( gettext("modify complete\n") );
11047c478bd9Sstevel@tonic-gate 	}
11057c478bd9Sstevel@tonic-gate     } else {
11067c478bd9Sstevel@tonic-gate 	i = LDAP_SUCCESS;
11077c478bd9Sstevel@tonic-gate     }
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate     if ( !ldapmodify_quiet) {
11107c478bd9Sstevel@tonic-gate 	putchar( '\n' );
11117c478bd9Sstevel@tonic-gate     }
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate     return( i );
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate static int
11187c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
11197c478bd9Sstevel@tonic-gate dodelete( LDAP *ld, char *dn )
11207c478bd9Sstevel@tonic-gate #else
11217c478bd9Sstevel@tonic-gate dodelete( char *dn )
11227c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
11237c478bd9Sstevel@tonic-gate {
11247c478bd9Sstevel@tonic-gate     int	rc;
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate     printf( gettext("%sdeleting entry %s\n"), ldaptool_not ? "!" : "", dn );
11277c478bd9Sstevel@tonic-gate     if ( !ldaptool_not ) {
11287c478bd9Sstevel@tonic-gate 	if (( rc = ldaptool_delete_ext_s( ld, dn, ldaptool_request_ctrls,
11297c478bd9Sstevel@tonic-gate 		NULL, "ldap_delete" )) == LDAP_SUCCESS && ldaptool_verbose ) {
11307c478bd9Sstevel@tonic-gate 	    printf( gettext("delete complete") );
11317c478bd9Sstevel@tonic-gate 	}
11327c478bd9Sstevel@tonic-gate     } else {
11337c478bd9Sstevel@tonic-gate 	rc = LDAP_SUCCESS;
11347c478bd9Sstevel@tonic-gate     }
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate     putchar( '\n' );
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate     return( rc );
11397c478bd9Sstevel@tonic-gate }
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate static int
11437c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
11447c478bd9Sstevel@tonic-gate dorename( LDAP *ld, char *dn, char *newrdn, char *newparent, int deleteoldrdn )
11457c478bd9Sstevel@tonic-gate #else
11467c478bd9Sstevel@tonic-gate dorename( char *dn, char *newrdn, char *newparent, int deleteoldrdn )
11477c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
11487c478bd9Sstevel@tonic-gate {
11497c478bd9Sstevel@tonic-gate     int	rc;
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate     if ( ldaptool_verbose ) {
11527c478bd9Sstevel@tonic-gate 	if ( newparent == NULL ) {
11537c478bd9Sstevel@tonic-gate 	    printf(deleteoldrdn ?
11547c478bd9Sstevel@tonic-gate 		  gettext("new RDN: %s (do not keep existing values)\n"):
11557c478bd9Sstevel@tonic-gate 		  gettext("new RDN: %s (keep existing values)\n"));
11567c478bd9Sstevel@tonic-gate 	} else {
11577c478bd9Sstevel@tonic-gate 	    printf(deleteoldrdn ?
11587c478bd9Sstevel@tonic-gate 		  gettext("new RDN: %s, new parent %s ( do not keep existing values)\n"):
11597c478bd9Sstevel@tonic-gate 		  gettext("new RDN: %s, new parent %s ( keep existing values)\n"));
11607c478bd9Sstevel@tonic-gate 	}
11617c478bd9Sstevel@tonic-gate     }
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate     printf( gettext("%smodifying RDN of entry %s%s\n"),
11647c478bd9Sstevel@tonic-gate 	    ldaptool_not ? "!" : "", dn, ( newparent == NULL ) ? "" :
11657c478bd9Sstevel@tonic-gate 	    gettext(" and/or moving it beneath a new parent\n") );
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate     if ( !ldaptool_not ) {
11687c478bd9Sstevel@tonic-gate 	if (( rc = ldaptool_rename_s( ld, dn, newrdn, newparent, deleteoldrdn,
11697c478bd9Sstevel@tonic-gate 		ldaptool_request_ctrls, NULL, "ldap_rename" )) == LDAP_SUCCESS
11707c478bd9Sstevel@tonic-gate 		&& ldaptool_verbose ) {
11717c478bd9Sstevel@tonic-gate 	    printf( gettext("rename completed\n") );
11727c478bd9Sstevel@tonic-gate 	}
11737c478bd9Sstevel@tonic-gate     } else {
11747c478bd9Sstevel@tonic-gate 	rc = LDAP_SUCCESS;
11757c478bd9Sstevel@tonic-gate     }
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate     putchar( '\n' );
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate     return( rc );
11807c478bd9Sstevel@tonic-gate }
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate static void
11847c478bd9Sstevel@tonic-gate freepmods( LDAPMod **pmods )
11857c478bd9Sstevel@tonic-gate {
11867c478bd9Sstevel@tonic-gate     int	i;
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate     for ( i = 0; pmods[ i ] != NULL; ++i ) {
11897c478bd9Sstevel@tonic-gate 	if ( pmods[ i ]->mod_bvalues != NULL ) {
11907c478bd9Sstevel@tonic-gate 	    ber_bvecfree( pmods[ i ]->mod_bvalues );
11917c478bd9Sstevel@tonic-gate 	}
11927c478bd9Sstevel@tonic-gate 	if ( pmods[ i ]->mod_type != NULL ) {
11937c478bd9Sstevel@tonic-gate 	    free( pmods[ i ]->mod_type );
11947c478bd9Sstevel@tonic-gate 	}
11957c478bd9Sstevel@tonic-gate 	free( pmods[ i ] );
11967c478bd9Sstevel@tonic-gate     }
11977c478bd9Sstevel@tonic-gate     free( pmods );
11987c478bd9Sstevel@tonic-gate }
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate static char *
12027c478bd9Sstevel@tonic-gate read_one_record( FILE *fp )
12037c478bd9Sstevel@tonic-gate {
12047c478bd9Sstevel@tonic-gate     int         len, gotnothing;
12057c478bd9Sstevel@tonic-gate     char        *buf, line[ LDAPMOD_MAXLINE ];
12067c478bd9Sstevel@tonic-gate     int		lcur, lmax;
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate     lcur = lmax = 0;
12097c478bd9Sstevel@tonic-gate     buf = NULL;
12107c478bd9Sstevel@tonic-gate     gotnothing = 1;
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
12137c478bd9Sstevel@tonic-gate     mutex_lock(&read_mutex);
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate     if (fp == NULL) {
12167c478bd9Sstevel@tonic-gate     	mutex_unlock(&read_mutex);
12177c478bd9Sstevel@tonic-gate 	return(NULL);
12187c478bd9Sstevel@tonic-gate     }
12197c478bd9Sstevel@tonic-gate #endif
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate     while ( fgets( line, sizeof(line), fp ) != NULL ) {
12227c478bd9Sstevel@tonic-gate 	if ( (len = strlen( line )) < 2 ) {
12237c478bd9Sstevel@tonic-gate 	    if ( gotnothing ) {
12247c478bd9Sstevel@tonic-gate 		continue;
12257c478bd9Sstevel@tonic-gate 	    } else {
12267c478bd9Sstevel@tonic-gate 		break;
12277c478bd9Sstevel@tonic-gate 	    }
12287c478bd9Sstevel@tonic-gate 	}
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 	/* Check if the blank line starts with '\r' (CR) */
12317c478bd9Sstevel@tonic-gate 	if ( ((len = strlen( line )) == 2) && (line[0] == '\r') ) {
12327c478bd9Sstevel@tonic-gate 	    if ( gotnothing ) {
12337c478bd9Sstevel@tonic-gate 		continue;
12347c478bd9Sstevel@tonic-gate 	    } else {
12357c478bd9Sstevel@tonic-gate 		break;
12367c478bd9Sstevel@tonic-gate 	      }
12377c478bd9Sstevel@tonic-gate 	}
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 	if ( *line == '#' ) {
12407c478bd9Sstevel@tonic-gate 	    continue;			/* skip comment lines */
12417c478bd9Sstevel@tonic-gate 	}
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 	gotnothing = 0;
12447c478bd9Sstevel@tonic-gate         if ( lcur + len + 1 > lmax ) {
12457c478bd9Sstevel@tonic-gate             lmax = LDAPMOD_MAXLINE
12467c478bd9Sstevel@tonic-gate 		    * (( lcur + len + 1 ) / LDAPMOD_MAXLINE + 1 );
12477c478bd9Sstevel@tonic-gate 	    if (( buf = (char *)LDAPTOOL_SAFEREALLOC( buf, lmax )) == NULL ) {
12487c478bd9Sstevel@tonic-gate 		perror( "realloc" );
12497c478bd9Sstevel@tonic-gate 		#ifdef SOLARIS_LDAP_CMD
12507c478bd9Sstevel@tonic-gate     			mutex_unlock(&read_mutex);
12517c478bd9Sstevel@tonic-gate 		#endif
12527c478bd9Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
12537c478bd9Sstevel@tonic-gate 	    }
12547c478bd9Sstevel@tonic-gate         }
12557c478bd9Sstevel@tonic-gate         strcpy( buf + lcur, line );
12567c478bd9Sstevel@tonic-gate         lcur += len;
12577c478bd9Sstevel@tonic-gate     }
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
12607c478bd9Sstevel@tonic-gate     mutex_unlock(&read_mutex);
12617c478bd9Sstevel@tonic-gate #endif
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate     return( buf );
12647c478bd9Sstevel@tonic-gate }
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate /*
12687c478bd9Sstevel@tonic-gate  * strdup and trim trailing blanks
12697c478bd9Sstevel@tonic-gate  */
12707c478bd9Sstevel@tonic-gate static char *
12717c478bd9Sstevel@tonic-gate strdup_and_trim( char *s )
12727c478bd9Sstevel@tonic-gate {
12737c478bd9Sstevel@tonic-gate     char	*p;
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate     if (( s = strdup( s )) == NULL ) {
12767c478bd9Sstevel@tonic-gate 	perror( "strdup" );
12777c478bd9Sstevel@tonic-gate 	exit( LDAP_NO_MEMORY );
12787c478bd9Sstevel@tonic-gate     }
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate     p = s + strlen( s ) - 1;
12817c478bd9Sstevel@tonic-gate     while ( p >= s && isspace( *p )) {
12827c478bd9Sstevel@tonic-gate 	--p;
12837c478bd9Sstevel@tonic-gate     }
12847c478bd9Sstevel@tonic-gate     *++p = '\0';
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate     return( s );
12877c478bd9Sstevel@tonic-gate }
1288