10Sstevel@tonic-gate /*
2*8097SSreedhar.Chalamalasetti@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate /*
70Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
80Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
90Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
100Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
110Sstevel@tonic-gate *
120Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
130Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
140Sstevel@tonic-gate * implied. See the License for the specific language governing
150Sstevel@tonic-gate * rights and limitations under the License.
160Sstevel@tonic-gate *
170Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
180Sstevel@tonic-gate * March 31, 1998.
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
210Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
220Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
230Sstevel@tonic-gate * Rights Reserved.
240Sstevel@tonic-gate *
250Sstevel@tonic-gate * Contributor(s):
260Sstevel@tonic-gate */
270Sstevel@tonic-gate
280Sstevel@tonic-gate /* ldapmodify.c - generic program to modify or add entries using LDAP */
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include "ldaptool.h"
310Sstevel@tonic-gate #include "fileurl.h"
320Sstevel@tonic-gate
330Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
340Sstevel@tonic-gate #include <locale.h>
350Sstevel@tonic-gate #include "ldif.h"
360Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
370Sstevel@tonic-gate
380Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
390Sstevel@tonic-gate #define gettext(s) s
400Sstevel@tonic-gate #endif
410Sstevel@tonic-gate
420Sstevel@tonic-gate static int newval, contoper, force, valsfromfiles, display_binary_values;
430Sstevel@tonic-gate static int ldif_version = -1; /* -1 => unknown version */
440Sstevel@tonic-gate static char *rejfile = NULL;
450Sstevel@tonic-gate static char *bulkimport_suffix = NULL;
460Sstevel@tonic-gate static int ldapmodify_quiet = 0;
470Sstevel@tonic-gate
480Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
490Sstevel@tonic-gate static int error = 0, replace, nbthreads = 1;
500Sstevel@tonic-gate static int thr_create_errors = 0;
510Sstevel@tonic-gate static pthread_mutex_t read_mutex = {0};
520Sstevel@tonic-gate static pthread_mutex_t wait_mutex = {0};
530Sstevel@tonic-gate static pthread_cond_t wait_cond = {0};
540Sstevel@tonic-gate #else
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate * For Solaris, ld is defined local to process() because
570Sstevel@tonic-gate * multiple threads restricts Solaris from using a global
580Sstevel@tonic-gate * ld variable.
590Sstevel@tonic-gate * Solaris uses multiple threads to create multiple
600Sstevel@tonic-gate * ldap connections if nbthreads > 1 (i.e -l option).
610Sstevel@tonic-gate */
620Sstevel@tonic-gate static LDAP *ld;
630Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
640Sstevel@tonic-gate
650Sstevel@tonic-gate #define LDAPMOD_MAXLINE 4096
660Sstevel@tonic-gate
670Sstevel@tonic-gate /* strings found in replog/LDIF entries (mostly lifted from slurpd/slurp.h) */
680Sstevel@tonic-gate #define T_REPLICA_STR "replica"
690Sstevel@tonic-gate #define T_DN_STR "dn"
700Sstevel@tonic-gate #define T_VERSION_STR "version"
710Sstevel@tonic-gate #define T_CHANGETYPESTR "changetype"
720Sstevel@tonic-gate #define T_ADDCTSTR "add"
730Sstevel@tonic-gate #define T_MODIFYCTSTR "modify"
740Sstevel@tonic-gate #define T_DELETECTSTR "delete"
750Sstevel@tonic-gate #define T_RENAMECTSTR "rename" /* non-standard */
760Sstevel@tonic-gate #define T_MODDNCTSTR "moddn"
770Sstevel@tonic-gate #define T_MODRDNCTSTR "modrdn"
780Sstevel@tonic-gate #define T_MODOPADDSTR "add"
790Sstevel@tonic-gate #define T_MODOPREPLACESTR "replace"
800Sstevel@tonic-gate #define T_MODOPDELETESTR "delete"
810Sstevel@tonic-gate #define T_MODSEPSTR "-"
820Sstevel@tonic-gate #define T_NEWRDNSTR "newrdn"
830Sstevel@tonic-gate #define T_NEWSUPERIORSTR "newsuperior"
840Sstevel@tonic-gate #define T_NEWPARENTSTR "newparent"
850Sstevel@tonic-gate #define T_DELETEOLDRDNSTR "deleteoldrdn"
860Sstevel@tonic-gate #define T_NEWSUPERIORSTR "newsuperior"
870Sstevel@tonic-gate #define T_NEWPARENTSTR "newparent" /* non-standard */
880Sstevel@tonic-gate
890Sstevel@tonic-gate /* bulk import */
900Sstevel@tonic-gate #define BULKIMPORT_START_OID "2.16.840.1.113730.3.5.7"
910Sstevel@tonic-gate #define BULKIMPORT_STOP_OID "2.16.840.1.113730.3.5.8"
920Sstevel@tonic-gate
930Sstevel@tonic-gate static int process( void *arg );
940Sstevel@tonic-gate static void options_callback( int option, char *optarg );
950Sstevel@tonic-gate static void addmodifyop( LDAPMod ***pmodsp, int modop, char *attr,
960Sstevel@tonic-gate char *value, int vlen );
970Sstevel@tonic-gate static void freepmods( LDAPMod **pmods );
980Sstevel@tonic-gate static char *read_one_record( FILE *fp );
990Sstevel@tonic-gate static char *strdup_and_trim( char *s );
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1020Sstevel@tonic-gate static int process_ldapmod_rec( LDAP *ld, char *rbuf );
1030Sstevel@tonic-gate static int process_ldif_rec( LDAP *ld, char *rbuf );
1040Sstevel@tonic-gate static int domodify( LDAP *ld, char *dn, LDAPMod **pmods, int newentry );
1050Sstevel@tonic-gate static int dodelete( LDAP *ld, char *dn );
1060Sstevel@tonic-gate static int dorename( LDAP *ld, char *dn, char *newrdn, char *newparent,
1070Sstevel@tonic-gate int deleteoldrdn );
1080Sstevel@tonic-gate #else
1090Sstevel@tonic-gate static int process_ldapmod_rec( char *rbuf );
1100Sstevel@tonic-gate static int process_ldif_rec( char *rbuf );
1110Sstevel@tonic-gate static int domodify( char *dn, LDAPMod **pmods, int newentry );
1120Sstevel@tonic-gate static int dodelete( char *dn );
1130Sstevel@tonic-gate static int dorename( char *dn, char *newrdn, char *newparent,
1140Sstevel@tonic-gate int deleteoldrdn );
1150Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate static void
usage(void)1180Sstevel@tonic-gate usage( void )
1190Sstevel@tonic-gate {
1200Sstevel@tonic-gate fprintf( stderr, gettext("usage: %s [options]\n"), ldaptool_progname );
1210Sstevel@tonic-gate fprintf( stderr, gettext("options:\n") );
1220Sstevel@tonic-gate ldaptool_common_usage( 0 );
1230Sstevel@tonic-gate fprintf( stderr, gettext(" -c\t\tcontinuous mode (do not stop on errors)\n") );
1240Sstevel@tonic-gate fprintf( stderr, gettext(" -A\t\tdisplay non-ASCII values in conjunction with -v\n") );
1250Sstevel@tonic-gate fprintf( stderr, gettext(" -f file\tread modifications from file (default: standard input)\n") );
1260Sstevel@tonic-gate if ( strcmp( ldaptool_progname, "ldapmodify" ) == 0 ){
1270Sstevel@tonic-gate fprintf( stderr, gettext(" -a\t\tadd entries\n") );
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate fprintf( stderr, gettext(" -b\t\tread values that start with / from files (for bin attrs)\n") );
1300Sstevel@tonic-gate fprintf( stderr, gettext(" -F\t\tforce application of all changes, regardless of\n") );
1310Sstevel@tonic-gate fprintf( stderr, gettext(" \t\treplica lines\n") );
1320Sstevel@tonic-gate fprintf( stderr, gettext(" -e rejfile\tsave rejected entries in \"rejfile\"\n") );
1330Sstevel@tonic-gate fprintf( stderr, gettext(" -B suffix\tbulk import to \"suffix\"\n"));
1340Sstevel@tonic-gate fprintf( stderr, gettext(" -q\t\tbe quiet when adding/modifying entries\n") );
1350Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1360Sstevel@tonic-gate fprintf( stderr, gettext(" -r\t\treplace values\n"));
1370Sstevel@tonic-gate fprintf( stderr, gettext(" -l nb-connections\tnumber of LDAP connections\n"));
1380Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
1390Sstevel@tonic-gate exit( LDAP_PARAM_ERROR );
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate int
main(int argc,char ** argv)1440Sstevel@tonic-gate main( int argc, char **argv )
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate int optind, i;
147*8097SSreedhar.Chalamalasetti@Sun.COM int rc;
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1500Sstevel@tonic-gate char *locale = setlocale(LC_ALL, "");
1510Sstevel@tonic-gate textdomain(TEXT_DOMAIN);
1520Sstevel@tonic-gate #endif
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate #ifdef notdef
1550Sstevel@tonic-gate #ifdef HPUX11
1560Sstevel@tonic-gate #ifndef __LP64__
1570Sstevel@tonic-gate _main( argc, argv);
1580Sstevel@tonic-gate #endif /* __LP64_ */
1590Sstevel@tonic-gate #endif /* HPUX11 */
1600Sstevel@tonic-gate #endif
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate valsfromfiles = display_binary_values = 0;
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1650Sstevel@tonic-gate optind = ldaptool_process_args( argc, argv, "aAbcFe:B:qrl:", 0,
1660Sstevel@tonic-gate options_callback );
1670Sstevel@tonic-gate #else
1680Sstevel@tonic-gate optind = ldaptool_process_args( argc, argv, "aAbcFe:B:q", 0,
1690Sstevel@tonic-gate options_callback );
1700Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate if ( optind == -1 ) {
1740Sstevel@tonic-gate usage();
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate if ( !newval && strcmp( ldaptool_progname, "ldapadd" ) == 0 ) {
1780Sstevel@tonic-gate newval = 1;
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate if ( ldaptool_fp == NULL ) {
1820Sstevel@tonic-gate ldaptool_fp = stdin;
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate if ( argc - optind != 0 ) {
1860Sstevel@tonic-gate usage();
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1900Sstevel@tonic-gate /* trivial case */
191*8097SSreedhar.Chalamalasetti@Sun.COM if ( nbthreads == 1 ) {
192*8097SSreedhar.Chalamalasetti@Sun.COM rc = process(NULL);
193*8097SSreedhar.Chalamalasetti@Sun.COM /* check for and report output error */
194*8097SSreedhar.Chalamalasetti@Sun.COM fflush( stdout );
195*8097SSreedhar.Chalamalasetti@Sun.COM rc = ldaptool_check_ferror( stdout, rc,
196*8097SSreedhar.Chalamalasetti@Sun.COM gettext("output error (output might be incomplete)") );
197*8097SSreedhar.Chalamalasetti@Sun.COM return( rc );
198*8097SSreedhar.Chalamalasetti@Sun.COM }
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate for ( i=0; i<nbthreads; ++i ) {
2010Sstevel@tonic-gate if ( thr_create(NULL, 0, process, NULL, NULL, NULL) != 0 )
2020Sstevel@tonic-gate ++thr_create_errors;
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate if ( thr_create_errors < nbthreads )
2060Sstevel@tonic-gate while ( thr_join(0, NULL, NULL) == 0 );
2070Sstevel@tonic-gate else
2080Sstevel@tonic-gate error = -1;
209*8097SSreedhar.Chalamalasetti@Sun.COM rc = error;
210*8097SSreedhar.Chalamalasetti@Sun.COM /* check for and report output error */
211*8097SSreedhar.Chalamalasetti@Sun.COM fflush( stdout );
212*8097SSreedhar.Chalamalasetti@Sun.COM rc = ldaptool_check_ferror( stdout, rc,
213*8097SSreedhar.Chalamalasetti@Sun.COM gettext("output error (output might be incomplete)") );
214*8097SSreedhar.Chalamalasetti@Sun.COM return( rc );
2150Sstevel@tonic-gate #else
216*8097SSreedhar.Chalamalasetti@Sun.COM rc = process(NULL);
217*8097SSreedhar.Chalamalasetti@Sun.COM /* check for and report output error */
218*8097SSreedhar.Chalamalasetti@Sun.COM fflush( stdout );
219*8097SSreedhar.Chalamalasetti@Sun.COM rc = ldaptool_check_ferror( stdout, rc,
220*8097SSreedhar.Chalamalasetti@Sun.COM gettext("output error (output might be incomplete)") );
221*8097SSreedhar.Chalamalasetti@Sun.COM return( rc );
2220Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
2260Sstevel@tonic-gate #define exit(a) \
2270Sstevel@tonic-gate if (nbthreads > 1) { \
2280Sstevel@tonic-gate mutex_lock(&read_mutex); \
2290Sstevel@tonic-gate error |= a; \
2300Sstevel@tonic-gate mutex_unlock(&read_mutex); \
2310Sstevel@tonic-gate thr_exit(&error); \
2320Sstevel@tonic-gate } else { \
2330Sstevel@tonic-gate exit(a); \
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate static int
process(void * arg)2380Sstevel@tonic-gate process( void *arg )
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate char *rbuf, *saved_rbuf, *start, *p, *q;
2410Sstevel@tonic-gate FILE *rfp = NULL;
2420Sstevel@tonic-gate int rc, use_ldif, deref;
2430Sstevel@tonic-gate LDAPControl *ldctrl;
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
2460Sstevel@tonic-gate LDAP *ld;
2470Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate ld = ldaptool_ldap_init( 0 );
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate if ( !ldaptool_not ) {
2520Sstevel@tonic-gate deref = LDAP_DEREF_NEVER; /* this seems prudent */
2530Sstevel@tonic-gate ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate ldaptool_bind( ld );
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate if (( ldctrl = ldaptool_create_manage_dsait_control()) != NULL ) {
2590Sstevel@tonic-gate ldaptool_add_control_to_array( ldctrl, ldaptool_request_ctrls);
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate if ((ldctrl = ldaptool_create_proxyauth_control(ld)) !=NULL) {
2630Sstevel@tonic-gate ldaptool_add_control_to_array( ldctrl, ldaptool_request_ctrls);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate rc = 0;
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate /* turn on bulk import?*/
2690Sstevel@tonic-gate if (bulkimport_suffix) {
2700Sstevel@tonic-gate struct berval bv, *retdata;
2710Sstevel@tonic-gate char *retoid;
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate bv.bv_val = bulkimport_suffix;
2740Sstevel@tonic-gate bv.bv_len = strlen(bulkimport_suffix);
2750Sstevel@tonic-gate if ((rc = ldap_extended_operation_s(ld,
2760Sstevel@tonic-gate BULKIMPORT_START_OID, &bv, NULL,
2770Sstevel@tonic-gate NULL, &retoid, &retdata)) != 0) {
2780Sstevel@tonic-gate fprintf(stderr, gettext("Error: unable to service "
2790Sstevel@tonic-gate "extended operation request\n\t'%s' for "
2800Sstevel@tonic-gate "bulk import\n\t(error:%d:'%s')\n"),
2810Sstevel@tonic-gate BULKIMPORT_START_OID, rc, ldap_err2string(rc));
2820Sstevel@tonic-gate return (rc);
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate if (retoid)
2850Sstevel@tonic-gate ldap_memfree(retoid);
2860Sstevel@tonic-gate if (retdata)
2870Sstevel@tonic-gate ber_bvfree(retdata);
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate while (( rc == 0 || contoper ) &&
2910Sstevel@tonic-gate ( rbuf = read_one_record( ldaptool_fp )) != NULL ) {
2920Sstevel@tonic-gate /*
2930Sstevel@tonic-gate * we assume record is ldif/slapd.replog if the first line
2940Sstevel@tonic-gate * has a colon that appears to the left of any equal signs, OR
2950Sstevel@tonic-gate * if the first line consists entirely of digits (an entry id)
2960Sstevel@tonic-gate */
2970Sstevel@tonic-gate use_ldif = ( p = strchr( rbuf, ':' )) != NULL &&
2980Sstevel@tonic-gate ( q = strchr( rbuf, '\n' )) != NULL && p < q &&
2990Sstevel@tonic-gate (( q = strchr( rbuf, '=' )) == NULL || p < q );
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate start = rbuf;
3020Sstevel@tonic-gate saved_rbuf = strdup( rbuf );
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate if ( !use_ldif && ( q = strchr( rbuf, '\n' )) != NULL ) {
3050Sstevel@tonic-gate for ( p = rbuf; p < q; ++p ) {
3060Sstevel@tonic-gate if ( !isdigit( *p )) {
3070Sstevel@tonic-gate break;
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate if ( p >= q ) {
3110Sstevel@tonic-gate use_ldif = 1;
3120Sstevel@tonic-gate start = q + 1;
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate }
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
3170Sstevel@tonic-gate if ( use_ldif ) {
3180Sstevel@tonic-gate rc = process_ldif_rec( ld, start );
3190Sstevel@tonic-gate } else {
3200Sstevel@tonic-gate rc = process_ldapmod_rec( ld, start );
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate #else
3230Sstevel@tonic-gate if ( use_ldif ) {
3240Sstevel@tonic-gate rc = process_ldif_rec( start );
3250Sstevel@tonic-gate } else {
3260Sstevel@tonic-gate rc = process_ldapmod_rec( start );
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate if ( rc != LDAP_SUCCESS && rejfile != NULL ) {
3310Sstevel@tonic-gate /* Write this record to the reject file */
3320Sstevel@tonic-gate int newfile = 0;
3330Sstevel@tonic-gate struct stat stbuf;
3340Sstevel@tonic-gate if ( stat( rejfile, &stbuf ) < 0 ) {
3350Sstevel@tonic-gate if ( errno == ENOENT ) {
3360Sstevel@tonic-gate newfile = 1;
3370Sstevel@tonic-gate }
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate if (( rfp = ldaptool_open_file( rejfile, "a" )) == NULL ) {
3400Sstevel@tonic-gate fprintf( stderr, gettext("Cannot open error file \"%s\" - "
3410Sstevel@tonic-gate "erroneous entries will not be saved\n"), rejfile );
3420Sstevel@tonic-gate rejfile = NULL;
3430Sstevel@tonic-gate } else {
3440Sstevel@tonic-gate if ( newfile == 0 ) {
3450Sstevel@tonic-gate fputs( "\n", rfp );
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate fprintf( rfp, gettext("# Error: %s\n"), ldap_err2string( rc ));
3480Sstevel@tonic-gate fputs( saved_rbuf, rfp );
3490Sstevel@tonic-gate fclose( rfp );
3500Sstevel@tonic-gate rfp = NULL;
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate free( rbuf );
3550Sstevel@tonic-gate free( saved_rbuf );
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate ldaptool_reset_control_array( ldaptool_request_ctrls );
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate /* turn off bulk import?*/
3600Sstevel@tonic-gate if (bulkimport_suffix) {
3610Sstevel@tonic-gate struct berval bv, *retdata;
3620Sstevel@tonic-gate char *retoid;
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate bv.bv_val = "";
3650Sstevel@tonic-gate bv.bv_len = 0;
3660Sstevel@tonic-gate if ((rc = ldap_extended_operation_s(ld,
3670Sstevel@tonic-gate BULKIMPORT_STOP_OID, &bv, NULL,
3680Sstevel@tonic-gate NULL, &retoid, &retdata)) != 0) {
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate fprintf(stderr, gettext("Error: unable to service "
3710Sstevel@tonic-gate "extended operation request\n\t '%s' for "
3720Sstevel@tonic-gate "bulk import\n\t(rc:%d:'%s')\n"),
3730Sstevel@tonic-gate BULKIMPORT_STOP_OID, rc, ldap_err2string(rc));
3740Sstevel@tonic-gate return (rc);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate if (retoid)
3770Sstevel@tonic-gate ldap_memfree(retoid);
3780Sstevel@tonic-gate if (retdata)
3790Sstevel@tonic-gate ber_bvfree(retdata);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
3830Sstevel@tonic-gate mutex_lock(&read_mutex);
3840Sstevel@tonic-gate #endif
3850Sstevel@tonic-gate ldaptool_cleanup( ld );
3860Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
3870Sstevel@tonic-gate mutex_unlock(&read_mutex);
3880Sstevel@tonic-gate #endif
3890Sstevel@tonic-gate return( rc );
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate static void
options_callback(int option,char * optarg)3940Sstevel@tonic-gate options_callback( int option, char *optarg )
3950Sstevel@tonic-gate {
3960Sstevel@tonic-gate switch( option ) {
3970Sstevel@tonic-gate case 'a': /* add */
3980Sstevel@tonic-gate newval = 1;
3990Sstevel@tonic-gate break;
4000Sstevel@tonic-gate case 'b': /* read values from files (for binary attributes) */
4010Sstevel@tonic-gate valsfromfiles = 1;
4020Sstevel@tonic-gate break;
4030Sstevel@tonic-gate case 'A': /* display non-ASCII values when -v is used */
4040Sstevel@tonic-gate display_binary_values = 1;
4050Sstevel@tonic-gate break;
4060Sstevel@tonic-gate case 'c': /* continuous operation */
4070Sstevel@tonic-gate contoper = 1;
4080Sstevel@tonic-gate break;
4090Sstevel@tonic-gate case 'F': /* force all changes records to be used */
4100Sstevel@tonic-gate force = 1;
4110Sstevel@tonic-gate break;
4120Sstevel@tonic-gate case 'e':
4130Sstevel@tonic-gate rejfile = strdup( optarg );
4140Sstevel@tonic-gate break;
4150Sstevel@tonic-gate case 'B': /* bulk import option */
4160Sstevel@tonic-gate bulkimport_suffix = strdup( optarg );
4170Sstevel@tonic-gate break;
4180Sstevel@tonic-gate case 'q': /* quiet mode on add/modify operations */
4190Sstevel@tonic-gate ldapmodify_quiet = 1;
4200Sstevel@tonic-gate break;
4210Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4220Sstevel@tonic-gate case 'r': /* default is to replace rather than add values */
4230Sstevel@tonic-gate replace = 1;
4240Sstevel@tonic-gate break;
4250Sstevel@tonic-gate case 'l':
4260Sstevel@tonic-gate nbthreads = atoi(optarg);
4270Sstevel@tonic-gate break;
4280Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
4290Sstevel@tonic-gate default:
4300Sstevel@tonic-gate usage();
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate static int
4370Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
process_ldif_rec(LDAP * ld,char * rbuf)4380Sstevel@tonic-gate process_ldif_rec( LDAP *ld, char *rbuf )
4390Sstevel@tonic-gate #else
4400Sstevel@tonic-gate process_ldif_rec( char *rbuf )
4410Sstevel@tonic-gate #endif
4420Sstevel@tonic-gate {
4430Sstevel@tonic-gate char *line, *dn, *type, *value, *newrdn, *newparent, *p;
4440Sstevel@tonic-gate char *ctrl_oid=NULL, *ctrl_value=NULL;
4450Sstevel@tonic-gate int ctrl_criticality=1;
4460Sstevel@tonic-gate LDAPControl *ldctrl;
4470Sstevel@tonic-gate int rc, linenum, vlen, modop, replicaport;
4480Sstevel@tonic-gate int expect_modop, expect_sep, expect_chgtype_or_control, expect_newrdn;
4490Sstevel@tonic-gate int expect_deleteoldrdn, expect_newparent, rename, moddn;
4500Sstevel@tonic-gate int deleteoldrdn, saw_replica, use_record, new_entry, delete_entry;
4510Sstevel@tonic-gate int got_all, got_value;
4520Sstevel@tonic-gate LDAPMod **pmods;
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate new_entry = newval;
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate rc = got_all = saw_replica = delete_entry = expect_modop = 0;
4570Sstevel@tonic-gate expect_deleteoldrdn = expect_newrdn = expect_newparent = expect_sep = 0;
4580Sstevel@tonic-gate expect_chgtype_or_control = linenum = got_value = rename = moddn = 0;
4590Sstevel@tonic-gate deleteoldrdn = 1;
4600Sstevel@tonic-gate use_record = force;
4610Sstevel@tonic-gate pmods = NULL;
4620Sstevel@tonic-gate dn = newrdn = newparent = NULL;
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4650Sstevel@tonic-gate while ( rc == 0 && ( line = str_getline( &rbuf )) != NULL ) {
4660Sstevel@tonic-gate #else
4670Sstevel@tonic-gate while ( rc == 0 && ( line = ldif_getline( &rbuf )) != NULL ) {
4680Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
4690Sstevel@tonic-gate ++linenum;
4700Sstevel@tonic-gate if ( expect_sep && strcasecmp( line, T_MODSEPSTR ) == 0 ) {
4710Sstevel@tonic-gate expect_sep = 0;
4720Sstevel@tonic-gate expect_modop = 1;
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate /*If we see a separator in the input stream,
4750Sstevel@tonic-gate but we didn't get a value from the last modify
4760Sstevel@tonic-gate then we have to fill pmods with an empty value*/
4770Sstevel@tonic-gate if (modop == LDAP_MOD_REPLACE && !got_value){
4780Sstevel@tonic-gate addmodifyop( &pmods, modop, value, NULL, 0);
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate got_value = 0;
4820Sstevel@tonic-gate continue;
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4860Sstevel@tonic-gate if ( str_parse_line( line, &type, &value, &vlen ) < 0 ) {
4870Sstevel@tonic-gate #else
4880Sstevel@tonic-gate if ( ldif_parse_line( line, &type, &value, &vlen ) < 0 ) {
4890Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
4900Sstevel@tonic-gate fprintf( stderr, gettext("%s: invalid format (line %d of entry: %s)\n"),
4910Sstevel@tonic-gate ldaptool_progname, linenum, dn == NULL ? "" : dn );
4920Sstevel@tonic-gate fprintf( stderr, gettext("%s: line contents: (%s)\n"),
4930Sstevel@tonic-gate ldaptool_progname, line );
4940Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
4950Sstevel@tonic-gate break;
4960Sstevel@tonic-gate }
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate evaluate_line:
4990Sstevel@tonic-gate if ( dn == NULL ) {
5000Sstevel@tonic-gate if ( !use_record && strcasecmp( type, T_REPLICA_STR ) == 0 ) {
5010Sstevel@tonic-gate ++saw_replica;
5020Sstevel@tonic-gate if (( p = strchr( value, ':' )) == NULL ) {
5030Sstevel@tonic-gate replicaport = LDAP_PORT;
5040Sstevel@tonic-gate } else {
5050Sstevel@tonic-gate *p++ = '\0';
5060Sstevel@tonic-gate replicaport = atoi( p );
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate if ( strcasecmp( value, ldaptool_host ) == 0 &&
5090Sstevel@tonic-gate replicaport == ldaptool_port ) {
5100Sstevel@tonic-gate use_record = 1;
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate } else if ( strcasecmp( type, T_DN_STR ) == 0 ) {
5140Sstevel@tonic-gate if (( dn = strdup( value )) == NULL ) {
5150Sstevel@tonic-gate perror( "strdup" );
5160Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
5170Sstevel@tonic-gate }
5180Sstevel@tonic-gate expect_chgtype_or_control = 1;
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate } else if ( strcasecmp( type, T_VERSION_STR ) == 0 ) {
5210Sstevel@tonic-gate ldif_version = atoi( value );
5220Sstevel@tonic-gate if ( ldif_version != LDIF_VERSION_ONE ) {
5230Sstevel@tonic-gate fprintf( stderr, gettext("%s: LDIF version %d is not supported;"
5240Sstevel@tonic-gate " use version: %d\n"), ldaptool_progname, ldif_version,
5250Sstevel@tonic-gate LDIF_VERSION_ONE );
5260Sstevel@tonic-gate exit( LDAP_PARAM_ERROR );
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate if ( ldaptool_verbose ) {
5290Sstevel@tonic-gate printf( gettext("Processing a version %d LDIF file...\n"),
5300Sstevel@tonic-gate ldif_version );
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate /* Now check if there's something left to process */
5340Sstevel@tonic-gate /* and if not, go get the new record, else continue */
5350Sstevel@tonic-gate if ( *rbuf == '\0' ) {
5360Sstevel@tonic-gate return( 0 );
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate } else if ( !saw_replica ) {
5400Sstevel@tonic-gate printf( gettext("%s: skipping change record: no dn: line\n"),
5410Sstevel@tonic-gate ldaptool_progname );
5420Sstevel@tonic-gate return( 0 );
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate continue; /* skip all lines until we see "dn:" */
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate if ( expect_chgtype_or_control ) {
5490Sstevel@tonic-gate expect_chgtype_or_control = 0;
5500Sstevel@tonic-gate if ( !use_record && saw_replica ) {
5510Sstevel@tonic-gate printf( gettext("%s: skipping change record for entry: %s\n\t(LDAP host/port does not match replica: lines)\n"),
5520Sstevel@tonic-gate ldaptool_progname, dn );
5530Sstevel@tonic-gate free( dn );
5540Sstevel@tonic-gate return( 0 );
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
5580Sstevel@tonic-gate if ( strcasecmp( type, "control" ) == 0 ) {
5590Sstevel@tonic-gate value = strdup_and_trim( value );
5600Sstevel@tonic-gate if (ldaptool_parse_ctrl_arg(value, ' ', &ctrl_oid,
5610Sstevel@tonic-gate &ctrl_criticality, &ctrl_value, &vlen)) {
5620Sstevel@tonic-gate usage();
5630Sstevel@tonic-gate }
5640Sstevel@tonic-gate ldctrl = calloc(1,sizeof(LDAPControl));
5650Sstevel@tonic-gate if (ctrl_value) {
5660Sstevel@tonic-gate rc = ldaptool_berval_from_ldif_value( ctrl_value, vlen,
5670Sstevel@tonic-gate &(ldctrl->ldctl_value),
5680Sstevel@tonic-gate 1 /* recognize file URLs */, 0 /* always try file */,
5690Sstevel@tonic-gate 1 /* report errors */ );
5700Sstevel@tonic-gate if ((rc = ldaptool_fileurlerr2ldaperr( rc )) != LDAP_SUCCESS) {
5710Sstevel@tonic-gate fprintf( stderr, gettext("Unable to parse %s\n"), ctrl_value);
5720Sstevel@tonic-gate usage();
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate ldctrl->ldctl_oid = ctrl_oid;
5760Sstevel@tonic-gate ldctrl->ldctl_iscritical = ctrl_criticality;
5770Sstevel@tonic-gate ldaptool_add_control_to_array(ldctrl, ldaptool_request_ctrls);
5780Sstevel@tonic-gate expect_chgtype_or_control = 1;
5790Sstevel@tonic-gate continue;
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate if ( strcasecmp( type, T_CHANGETYPESTR ) == 0 ) {
5840Sstevel@tonic-gate value = strdup_and_trim( value );
5850Sstevel@tonic-gate if ( strcasecmp( value, T_MODIFYCTSTR ) == 0 ) {
5860Sstevel@tonic-gate new_entry = 0;
5870Sstevel@tonic-gate expect_modop = 1;
5880Sstevel@tonic-gate } else if ( strcasecmp( value, T_ADDCTSTR ) == 0 ) {
5890Sstevel@tonic-gate new_entry = 1;
5900Sstevel@tonic-gate modop = LDAP_MOD_ADD;
5910Sstevel@tonic-gate } else if ( strcasecmp( value, T_MODRDNCTSTR ) == 0 ) {
5920Sstevel@tonic-gate expect_newrdn = 1;
5930Sstevel@tonic-gate moddn = 1;
5940Sstevel@tonic-gate } else if ( strcasecmp( value, T_MODDNCTSTR ) == 0 ) {
5950Sstevel@tonic-gate expect_newrdn = 1;
5960Sstevel@tonic-gate moddn = 1;
5970Sstevel@tonic-gate } else if ( strcasecmp( value, T_RENAMECTSTR ) == 0 ) {
5980Sstevel@tonic-gate expect_newrdn = 1;
5990Sstevel@tonic-gate rename = 1;
6000Sstevel@tonic-gate } else if ( strcasecmp( value, T_DELETECTSTR ) == 0 ) {
6010Sstevel@tonic-gate got_all = delete_entry = 1;
6020Sstevel@tonic-gate } else {
6030Sstevel@tonic-gate fprintf( stderr,
6040Sstevel@tonic-gate gettext("%s: unknown %s \"%s\" (line %d of entry: %s)\n"),
6050Sstevel@tonic-gate ldaptool_progname, T_CHANGETYPESTR, value,
6060Sstevel@tonic-gate linenum, dn );
6070Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate free( value );
6100Sstevel@tonic-gate continue;
6110Sstevel@tonic-gate } else if ( newval ) { /* missing changetype => add */
6120Sstevel@tonic-gate new_entry = 1;
6130Sstevel@tonic-gate modop = LDAP_MOD_ADD;
6140Sstevel@tonic-gate } else {
6150Sstevel@tonic-gate /*The user MUST put in changetype: blah
6160Sstevel@tonic-gate unless adding a new entry with either -a or ldapadd*/
6170Sstevel@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"),
6180Sstevel@tonic-gate ldaptool_progname, type, linenum, dn);
6190Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
6200Sstevel@tonic-gate /*expect_modop = 1; missing changetype => modify */
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate }
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate if ( expect_modop ) {
6250Sstevel@tonic-gate expect_modop = 0;
6260Sstevel@tonic-gate expect_sep = 1;
6270Sstevel@tonic-gate if ( strcasecmp( type, T_MODOPADDSTR ) == 0 ) {
6280Sstevel@tonic-gate modop = LDAP_MOD_ADD;
6290Sstevel@tonic-gate continue;
6300Sstevel@tonic-gate } else if ( strcasecmp( type, T_MODOPREPLACESTR ) == 0 ) {
6310Sstevel@tonic-gate modop = LDAP_MOD_REPLACE;
6320Sstevel@tonic-gate continue;
6330Sstevel@tonic-gate } else if ( strcasecmp( type, T_MODOPDELETESTR ) == 0 ) {
6340Sstevel@tonic-gate modop = LDAP_MOD_DELETE;
6350Sstevel@tonic-gate addmodifyop( &pmods, modop, value, NULL, 0 );
6360Sstevel@tonic-gate continue;
6370Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
6380Sstevel@tonic-gate } else { /* no modify op: use default */
6390Sstevel@tonic-gate modop = replace ? LDAP_MOD_REPLACE : LDAP_MOD_ADD;
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate #else
6420Sstevel@tonic-gate } else { /*Bug 27479. Remove default add operation*/
6430Sstevel@tonic-gate fprintf(stderr, gettext("%s: Invalid parameter \"%s\" specified for changetype modify (line %d of entry %s)\n"),
6440Sstevel@tonic-gate ldaptool_progname, type, linenum, dn);
6450Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate }
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate if ( expect_newrdn ) {
6520Sstevel@tonic-gate if ( strcasecmp( type, T_NEWRDNSTR ) == 0 ) {
6530Sstevel@tonic-gate if ( *value == '\0' ) {
6540Sstevel@tonic-gate fprintf( stderr,
6550Sstevel@tonic-gate gettext("%s: newrdn value missing (line %d of entry: %s)\n"),
6560Sstevel@tonic-gate ldaptool_progname, linenum, dn == NULL ? "" : dn );
6570Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
6580Sstevel@tonic-gate } else if (( newrdn = strdup( value )) == NULL ) {
6590Sstevel@tonic-gate perror( "strdup" );
6600Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
6610Sstevel@tonic-gate } else {
6620Sstevel@tonic-gate expect_newrdn = 0;
6630Sstevel@tonic-gate if ( rename ) {
6640Sstevel@tonic-gate expect_newparent = 1;
6650Sstevel@tonic-gate } else {
6660Sstevel@tonic-gate expect_deleteoldrdn = 1;
6670Sstevel@tonic-gate }
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate } else {
6700Sstevel@tonic-gate fprintf( stderr, gettext("%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n"),
6710Sstevel@tonic-gate ldaptool_progname, T_NEWRDNSTR, type, linenum, dn );
6720Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
6730Sstevel@tonic-gate }
6740Sstevel@tonic-gate } else if ( expect_newparent ) {
6750Sstevel@tonic-gate expect_newparent = 0;
6760Sstevel@tonic-gate if ( rename ) {
6770Sstevel@tonic-gate expect_deleteoldrdn = 1;
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate if ( strcasecmp( type, T_NEWPARENTSTR ) == 0
6800Sstevel@tonic-gate || strcasecmp( type, T_NEWSUPERIORSTR ) == 0 ) {
6810Sstevel@tonic-gate if (( newparent = strdup( value )) == NULL ) {
6820Sstevel@tonic-gate perror( "strdup" );
6830Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate } else {
6860Sstevel@tonic-gate /* Since this is an optional argument for rename/moddn, cause
6870Sstevel@tonic-gate * the current line to be re-evaluated if newparent doesn't
6880Sstevel@tonic-gate * follow deleteoldrdn.
6890Sstevel@tonic-gate */
6900Sstevel@tonic-gate newparent = NULL;
6910Sstevel@tonic-gate goto evaluate_line;
6920Sstevel@tonic-gate }
6930Sstevel@tonic-gate } else if ( expect_deleteoldrdn ) {
6940Sstevel@tonic-gate if ( strcasecmp( type, T_DELETEOLDRDNSTR ) == 0 ) {
6950Sstevel@tonic-gate if ( *value == '\0' ) {
6960Sstevel@tonic-gate fprintf( stderr,
6970Sstevel@tonic-gate gettext("%s: missing 0 or 1 (line %d of entry: %s)\n"),
6980Sstevel@tonic-gate ldaptool_progname, linenum, dn == NULL ? "" : dn );
6990Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
7000Sstevel@tonic-gate } else {
7010Sstevel@tonic-gate deleteoldrdn = ( *value == '0' ) ? 0 : 1;
7020Sstevel@tonic-gate expect_deleteoldrdn = 0;
7030Sstevel@tonic-gate if ( moddn ) {
7040Sstevel@tonic-gate expect_newparent = 1;
7050Sstevel@tonic-gate }
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate } else {
7080Sstevel@tonic-gate fprintf( stderr, gettext("%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n"),
7090Sstevel@tonic-gate ldaptool_progname, T_DELETEOLDRDNSTR, type, linenum,
7100Sstevel@tonic-gate dn );
7110Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate got_all = 1;
7140Sstevel@tonic-gate } else if ( got_all ) {
7150Sstevel@tonic-gate fprintf( stderr,
7160Sstevel@tonic-gate gettext("%s: extra lines at end (line %d of entry %s)\n"),
7170Sstevel@tonic-gate ldaptool_progname, linenum, dn );
7180Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
7190Sstevel@tonic-gate got_all = 1;
7200Sstevel@tonic-gate } else {
7210Sstevel@tonic-gate addmodifyop( &pmods, modop, type, value, vlen );
7220Sstevel@tonic-gate /*There was a value to replace*/
7230Sstevel@tonic-gate got_value = 1;
7240Sstevel@tonic-gate
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate if ( rc == 0 ) {
7290Sstevel@tonic-gate if ( delete_entry ) {
7300Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7310Sstevel@tonic-gate rc = dodelete( ld, dn );
7320Sstevel@tonic-gate #else
7330Sstevel@tonic-gate rc = dodelete( dn );
7340Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
7350Sstevel@tonic-gate } else if ( newrdn != NULL ) {
7360Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7370Sstevel@tonic-gate rc = dorename( ld, dn, newrdn, newparent, deleteoldrdn );
7380Sstevel@tonic-gate #else
7390Sstevel@tonic-gate rc = dorename( dn, newrdn, newparent, deleteoldrdn );
7400Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
7410Sstevel@tonic-gate rename = 0;
7420Sstevel@tonic-gate } else {
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate /*Patch to fix Bug 22183
7450Sstevel@tonic-gate If pmods is null, then there is no
7460Sstevel@tonic-gate attribute to replace, so we alloc
7470Sstevel@tonic-gate an empty pmods*/
7480Sstevel@tonic-gate if (modop == LDAP_MOD_REPLACE && !got_value && expect_sep){
7490Sstevel@tonic-gate addmodifyop( &pmods, modop, value, NULL, 0);
7500Sstevel@tonic-gate }/*End Patch*/
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7540Sstevel@tonic-gate rc = domodify( ld, dn, pmods, new_entry );
7550Sstevel@tonic-gate #else
7560Sstevel@tonic-gate rc = domodify( dn, pmods, new_entry );
7570Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate if ( rc == LDAP_SUCCESS ) {
7610Sstevel@tonic-gate rc = 0;
7620Sstevel@tonic-gate }
7630Sstevel@tonic-gate }
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate if ( dn != NULL ) {
7660Sstevel@tonic-gate free( dn );
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate if ( newrdn != NULL ) {
7690Sstevel@tonic-gate free( newrdn );
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate if ( newparent != NULL ) {
7720Sstevel@tonic-gate free( newparent );
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate if ( pmods != NULL ) {
7750Sstevel@tonic-gate freepmods( pmods );
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate return( rc );
7790Sstevel@tonic-gate }
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate static int
7830Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7840Sstevel@tonic-gate process_ldapmod_rec( LDAP *ld, char *rbuf )
7850Sstevel@tonic-gate #else
7860Sstevel@tonic-gate process_ldapmod_rec( char *rbuf )
7870Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
7880Sstevel@tonic-gate {
7890Sstevel@tonic-gate char *line, *dn, *p, *q, *attr, *value;
7900Sstevel@tonic-gate int rc, linenum, modop;
7910Sstevel@tonic-gate LDAPMod **pmods;
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate pmods = NULL;
7940Sstevel@tonic-gate dn = NULL;
7950Sstevel@tonic-gate linenum = 0;
7960Sstevel@tonic-gate line = rbuf;
7970Sstevel@tonic-gate rc = 0;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate while ( rc == 0 && rbuf != NULL && *rbuf != '\0' ) {
8000Sstevel@tonic-gate ++linenum;
8010Sstevel@tonic-gate if (( p = strchr( rbuf, '\n' )) == NULL ) {
8020Sstevel@tonic-gate rbuf = NULL;
8030Sstevel@tonic-gate } else {
8040Sstevel@tonic-gate if ( *(p-1) == '\\' ) { /* lines ending in '\' are continued */
8050Sstevel@tonic-gate strcpy( p - 1, p );
8060Sstevel@tonic-gate rbuf = p;
8070Sstevel@tonic-gate continue;
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate *p++ = '\0';
8100Sstevel@tonic-gate rbuf = p;
8110Sstevel@tonic-gate }
8120Sstevel@tonic-gate
8130Sstevel@tonic-gate if ( dn == NULL ) { /* first line contains DN */
8140Sstevel@tonic-gate if (( dn = strdup( line )) == NULL ) {
8150Sstevel@tonic-gate perror( "strdup" );
8160Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate } else {
8190Sstevel@tonic-gate if (( p = strchr( line, '=' )) == NULL ) {
8200Sstevel@tonic-gate value = NULL;
8210Sstevel@tonic-gate p = line + strlen( line );
8220Sstevel@tonic-gate } else {
8230Sstevel@tonic-gate *p++ = '\0';
8240Sstevel@tonic-gate value = p;
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate
8270Sstevel@tonic-gate for ( attr = line; *attr != '\0' && isspace( *attr ); ++attr ) {
8280Sstevel@tonic-gate ; /* skip attribute leading white space */
8290Sstevel@tonic-gate }
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate for ( q = p - 1; q > attr && isspace( *q ); --q ) {
8320Sstevel@tonic-gate *q = '\0'; /* remove attribute trailing white space */
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate if ( value != NULL ) {
8360Sstevel@tonic-gate while ( isspace( *value )) {
8370Sstevel@tonic-gate ++value; /* skip value leading white space */
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate for ( q = value + strlen( value ) - 1; q > value &&
8400Sstevel@tonic-gate isspace( *q ); --q ) {
8410Sstevel@tonic-gate *q = '\0'; /* remove value trailing white space */
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate if ( *value == '\0' ) {
8440Sstevel@tonic-gate value = NULL;
8450Sstevel@tonic-gate }
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate }
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate if ( value == NULL && newval ) {
8500Sstevel@tonic-gate fprintf( stderr, gettext("%s: missing value on line %d (attr is %s)\n"),
8510Sstevel@tonic-gate ldaptool_progname, linenum, attr );
8520Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
8530Sstevel@tonic-gate } else {
8540Sstevel@tonic-gate switch ( *attr ) {
8550Sstevel@tonic-gate case '-':
8560Sstevel@tonic-gate modop = LDAP_MOD_DELETE;
8570Sstevel@tonic-gate ++attr;
8580Sstevel@tonic-gate break;
8590Sstevel@tonic-gate case '+':
8600Sstevel@tonic-gate modop = LDAP_MOD_ADD;
8610Sstevel@tonic-gate ++attr;
8620Sstevel@tonic-gate break;
8630Sstevel@tonic-gate default:
8640Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
8650Sstevel@tonic-gate modop = replace ? LDAP_MOD_REPLACE : LDAP_MOD_ADD;
8660Sstevel@tonic-gate #else
8670Sstevel@tonic-gate /*Bug 27479. Remove the add default*/
8680Sstevel@tonic-gate fprintf(stderr, gettext("%s: Invalid parameter specified for changetype modify (line %d of entry %s)\n"),
8690Sstevel@tonic-gate ldaptool_progname, linenum, dn);
8700Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
8710Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate addmodifyop( &pmods, modop, attr, value,
8750Sstevel@tonic-gate ( value == NULL ) ? 0 : strlen( value ));
8760Sstevel@tonic-gate }
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate line = rbuf;
8800Sstevel@tonic-gate }
8810Sstevel@tonic-gate
8820Sstevel@tonic-gate if ( rc == 0 ) {
8830Sstevel@tonic-gate if ( dn == NULL ) {
8840Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
8850Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
8860Sstevel@tonic-gate } else if (( rc = domodify( ld, dn, pmods, newval )) == LDAP_SUCCESS ){
8870Sstevel@tonic-gate #else
8880Sstevel@tonic-gate } else if (( rc = domodify( dn, pmods, newval )) == LDAP_SUCCESS ){
8890Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
8900Sstevel@tonic-gate rc = 0;
8910Sstevel@tonic-gate }
8920Sstevel@tonic-gate }
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate if ( pmods != NULL ) {
8950Sstevel@tonic-gate freepmods( pmods );
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate if ( dn != NULL ) {
8980Sstevel@tonic-gate free( dn );
8990Sstevel@tonic-gate }
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate return( rc );
9020Sstevel@tonic-gate }
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate
9050Sstevel@tonic-gate static void
9060Sstevel@tonic-gate addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
9070Sstevel@tonic-gate {
9080Sstevel@tonic-gate LDAPMod **pmods;
9090Sstevel@tonic-gate int i, j, rc;
9100Sstevel@tonic-gate struct berval *bvp;
9110Sstevel@tonic-gate
9120Sstevel@tonic-gate pmods = *pmodsp;
9130Sstevel@tonic-gate modop |= LDAP_MOD_BVALUES;
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate i = 0;
9160Sstevel@tonic-gate if ( pmods != NULL ) {
9170Sstevel@tonic-gate for ( ; pmods[ i ] != NULL; ++i ) {
9180Sstevel@tonic-gate if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
9190Sstevel@tonic-gate pmods[ i ]->mod_op == modop ) {
9200Sstevel@tonic-gate break;
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate
9250Sstevel@tonic-gate if ( pmods == NULL || pmods[ i ] == NULL ) {
9260Sstevel@tonic-gate if (( pmods = (LDAPMod **)LDAPTOOL_SAFEREALLOC( pmods, (i + 2) *
9270Sstevel@tonic-gate sizeof( LDAPMod * ))) == NULL ) {
9280Sstevel@tonic-gate perror( "realloc" );
9290Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
9300Sstevel@tonic-gate }
9310Sstevel@tonic-gate *pmodsp = pmods;
9320Sstevel@tonic-gate pmods[ i + 1 ] = NULL;
9330Sstevel@tonic-gate if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
9340Sstevel@tonic-gate == NULL ) {
9350Sstevel@tonic-gate perror( "calloc" );
9360Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
9370Sstevel@tonic-gate }
9380Sstevel@tonic-gate pmods[ i ]->mod_op = modop;
9390Sstevel@tonic-gate if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
9400Sstevel@tonic-gate perror( "strdup" );
9410Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
9420Sstevel@tonic-gate }
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate
9450Sstevel@tonic-gate if ( value != NULL ) {
9460Sstevel@tonic-gate j = 0;
9470Sstevel@tonic-gate if ( pmods[ i ]->mod_bvalues != NULL ) {
9480Sstevel@tonic-gate for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
9490Sstevel@tonic-gate ;
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate }
9520Sstevel@tonic-gate if (( pmods[ i ]->mod_bvalues = (struct berval **)
9530Sstevel@tonic-gate LDAPTOOL_SAFEREALLOC( pmods[ i ]->mod_bvalues,
9540Sstevel@tonic-gate (j + 2) * sizeof( struct berval * ))) == NULL ) {
9550Sstevel@tonic-gate perror( "realloc" );
9560Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
9590Sstevel@tonic-gate if (( bvp = (struct berval *)malloc( sizeof( struct berval )))
9600Sstevel@tonic-gate == NULL ) {
9610Sstevel@tonic-gate perror( "malloc" );
9620Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate pmods[ i ]->mod_bvalues[ j ] = bvp;
9650Sstevel@tonic-gate
9660Sstevel@tonic-gate #ifdef notdef
9670Sstevel@tonic-gate if (ldaptool_verbose) {
9680Sstevel@tonic-gate printf(gettext("%s: value: %s vlen: %d\n"), "ldapmodify", value, vlen);
9690Sstevel@tonic-gate }
9700Sstevel@tonic-gate #endif
9710Sstevel@tonic-gate rc = ldaptool_berval_from_ldif_value( value, vlen, bvp,
9720Sstevel@tonic-gate ( ldif_version >= LDIF_VERSION_ONE ), valsfromfiles,
9730Sstevel@tonic-gate 1 /* report errors */ );
9740Sstevel@tonic-gate if ( rc != LDAPTOOL_FILEURL_SUCCESS ) {
9750Sstevel@tonic-gate exit( ldaptool_fileurlerr2ldaperr( rc ));
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate }
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate static int
9820Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
9830Sstevel@tonic-gate domodify( LDAP *ld, char *dn, LDAPMod **pmods, int newentry )
9840Sstevel@tonic-gate #else
9850Sstevel@tonic-gate domodify( char *dn, LDAPMod **pmods, int newentry )
9860Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
9870Sstevel@tonic-gate {
9880Sstevel@tonic-gate int i, j, notascii, op;
9890Sstevel@tonic-gate struct berval *bvp;
9900Sstevel@tonic-gate
9910Sstevel@tonic-gate if ( pmods == NULL ) {
9920Sstevel@tonic-gate fprintf( stderr, gettext("%s: no attributes to change or add (entry %s)\n"),
9930Sstevel@tonic-gate ldaptool_progname, dn );
9940Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate if ( ldaptool_verbose ) {
9980Sstevel@tonic-gate for ( i = 0; pmods[ i ] != NULL; ++i ) {
9990Sstevel@tonic-gate op = pmods[ i ]->mod_op & ~LDAP_MOD_BVALUES;
10000Sstevel@tonic-gate printf( gettext("%s %s:\n"), op == LDAP_MOD_REPLACE ?
10010Sstevel@tonic-gate gettext("replace") : op == LDAP_MOD_ADD ?
10020Sstevel@tonic-gate gettext("add") : gettext("delete"), pmods[ i ]->mod_type );
10030Sstevel@tonic-gate if ( pmods[ i ]->mod_bvalues != NULL ) {
10040Sstevel@tonic-gate for ( j = 0; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
10050Sstevel@tonic-gate bvp = pmods[ i ]->mod_bvalues[ j ];
10060Sstevel@tonic-gate notascii = 0;
10070Sstevel@tonic-gate if ( !display_binary_values ) {
10080Sstevel@tonic-gate notascii = !ldaptool_berval_is_ascii( bvp );
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate if ( notascii ) {
10110Sstevel@tonic-gate printf( gettext("\tNOT ASCII (%ld bytes)\n"), bvp->bv_len );
10120Sstevel@tonic-gate } else {
10130Sstevel@tonic-gate printf( "\t%s\n", bvp->bv_val );
10140Sstevel@tonic-gate }
10150Sstevel@tonic-gate }
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate }
10190Sstevel@tonic-gate
10200Sstevel@tonic-gate if ( !ldapmodify_quiet) {
10210Sstevel@tonic-gate if ( newentry ) {
10220Sstevel@tonic-gate printf( gettext("%sadding new entry %s\n"),
10230Sstevel@tonic-gate ldaptool_not ? "!" : "", dn );
10240Sstevel@tonic-gate } else {
10250Sstevel@tonic-gate printf( gettext("%smodifying entry %s\n"),
10260Sstevel@tonic-gate ldaptool_not ? "!" : "", dn );
10270Sstevel@tonic-gate }
10280Sstevel@tonic-gate }
10290Sstevel@tonic-gate
10300Sstevel@tonic-gate if ( !ldaptool_not ) {
10310Sstevel@tonic-gate if ( newentry ) {
10320Sstevel@tonic-gate unsigned int sleep_interval = 2; /* seconds */
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
10350Sstevel@tonic-gate /* Backward compatibility with old Solaris command */
10360Sstevel@tonic-gate unsigned int nb = 0;
10370Sstevel@tonic-gate timestruc_t to;
10380Sstevel@tonic-gate while ((i = ldaptool_add_ext_s( ld, dn, pmods,
10390Sstevel@tonic-gate ldaptool_request_ctrls, NULL, "ldap_add" ))
10400Sstevel@tonic-gate != LDAP_SUCCESS) {
10410Sstevel@tonic-gate if (i == LDAP_BUSY) {
10420Sstevel@tonic-gate if ( sleep_interval > 3600 ) {
10430Sstevel@tonic-gate printf(gettext("ldap_add: Unable to complete "
10440Sstevel@tonic-gate "request. Server is too "
10450Sstevel@tonic-gate "busy servicing other "
10460Sstevel@tonic-gate "requests\n"));
10470Sstevel@tonic-gate break;
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate if ( !ldapmodify_quiet ) {
10500Sstevel@tonic-gate printf(gettext("ldap_add: LDAP_BUSY returned "
10510Sstevel@tonic-gate "by server. Will retry "
10520Sstevel@tonic-gate "operation in %d seconds\n"),
10530Sstevel@tonic-gate sleep_interval);
10540Sstevel@tonic-gate }
10550Sstevel@tonic-gate sleep( sleep_interval );
10560Sstevel@tonic-gate sleep_interval *= 2;
10570Sstevel@tonic-gate } else if (i == LDAP_NO_SUCH_OBJECT) {
10580Sstevel@tonic-gate /*
10590Sstevel@tonic-gate * Wait for the parent entry to be created by
10600Sstevel@tonic-gate * another thread. Do not retry more than the
10610Sstevel@tonic-gate * number of threads.
10620Sstevel@tonic-gate */
10630Sstevel@tonic-gate ++nb;
10640Sstevel@tonic-gate if (nb >= nbthreads)
10650Sstevel@tonic-gate break;
10660Sstevel@tonic-gate mutex_lock(&wait_mutex);
10670Sstevel@tonic-gate to.tv_sec = 5;
10680Sstevel@tonic-gate to.tv_nsec = 0;
10690Sstevel@tonic-gate if (cond_reltimedwait(&wait_cond, &wait_mutex, &to)
10700Sstevel@tonic-gate == ETIME) {
10710Sstevel@tonic-gate nb = nbthreads; /* last chance */
10720Sstevel@tonic-gate }
10730Sstevel@tonic-gate mutex_unlock(&wait_mutex);
10740Sstevel@tonic-gate } else {
10750Sstevel@tonic-gate break;
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate }
10780Sstevel@tonic-gate cond_broadcast(&wait_cond);
10790Sstevel@tonic-gate #else
10800Sstevel@tonic-gate while ((i = ldaptool_add_ext_s( ld, dn, pmods,
10810Sstevel@tonic-gate ldaptool_request_ctrls, NULL, "ldap_add" ))
10820Sstevel@tonic-gate == LDAP_BUSY) {
10830Sstevel@tonic-gate if ( sleep_interval > 3600 ) {
10840Sstevel@tonic-gate printf("ldap_add: Unable to complete request. ");
10850Sstevel@tonic-gate printf("Server is too ");
10860Sstevel@tonic-gate printf("busy servicing other requests\n");
10870Sstevel@tonic-gate break;
10880Sstevel@tonic-gate }
10890Sstevel@tonic-gate if ( !ldapmodify_quiet ) {
10900Sstevel@tonic-gate printf("ldap_add: LDAP_BUSY returned by server. ");
10910Sstevel@tonic-gate printf("Will retry operation ");
10920Sstevel@tonic-gate printf("in %d seconds\n", sleep_interval);
10930Sstevel@tonic-gate }
10940Sstevel@tonic-gate sleep( sleep_interval );
10950Sstevel@tonic-gate sleep_interval *= 2;
10960Sstevel@tonic-gate }
10970Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
10980Sstevel@tonic-gate } else {
10990Sstevel@tonic-gate i = ldaptool_modify_ext_s( ld, dn, pmods, ldaptool_request_ctrls,
11000Sstevel@tonic-gate NULL, "ldap_modify" );
11010Sstevel@tonic-gate }
11020Sstevel@tonic-gate if ( i == LDAP_SUCCESS && ldaptool_verbose ) {
11030Sstevel@tonic-gate printf( gettext("modify complete\n") );
11040Sstevel@tonic-gate }
11050Sstevel@tonic-gate } else {
11060Sstevel@tonic-gate i = LDAP_SUCCESS;
11070Sstevel@tonic-gate }
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate if ( !ldapmodify_quiet) {
11100Sstevel@tonic-gate putchar( '\n' );
11110Sstevel@tonic-gate }
11120Sstevel@tonic-gate
11130Sstevel@tonic-gate return( i );
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate static int
11180Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
11190Sstevel@tonic-gate dodelete( LDAP *ld, char *dn )
11200Sstevel@tonic-gate #else
11210Sstevel@tonic-gate dodelete( char *dn )
11220Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
11230Sstevel@tonic-gate {
11240Sstevel@tonic-gate int rc;
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate printf( gettext("%sdeleting entry %s\n"), ldaptool_not ? "!" : "", dn );
11270Sstevel@tonic-gate if ( !ldaptool_not ) {
11280Sstevel@tonic-gate if (( rc = ldaptool_delete_ext_s( ld, dn, ldaptool_request_ctrls,
11290Sstevel@tonic-gate NULL, "ldap_delete" )) == LDAP_SUCCESS && ldaptool_verbose ) {
11300Sstevel@tonic-gate printf( gettext("delete complete") );
11310Sstevel@tonic-gate }
11320Sstevel@tonic-gate } else {
11330Sstevel@tonic-gate rc = LDAP_SUCCESS;
11340Sstevel@tonic-gate }
11350Sstevel@tonic-gate
11360Sstevel@tonic-gate putchar( '\n' );
11370Sstevel@tonic-gate
11380Sstevel@tonic-gate return( rc );
11390Sstevel@tonic-gate }
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate
11420Sstevel@tonic-gate static int
11430Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
11440Sstevel@tonic-gate dorename( LDAP *ld, char *dn, char *newrdn, char *newparent, int deleteoldrdn )
11450Sstevel@tonic-gate #else
11460Sstevel@tonic-gate dorename( char *dn, char *newrdn, char *newparent, int deleteoldrdn )
11470Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
11480Sstevel@tonic-gate {
11490Sstevel@tonic-gate int rc;
11500Sstevel@tonic-gate
11510Sstevel@tonic-gate if ( ldaptool_verbose ) {
11520Sstevel@tonic-gate if ( newparent == NULL ) {
11530Sstevel@tonic-gate printf(deleteoldrdn ?
11540Sstevel@tonic-gate gettext("new RDN: %s (do not keep existing values)\n"):
11550Sstevel@tonic-gate gettext("new RDN: %s (keep existing values)\n"));
11560Sstevel@tonic-gate } else {
11570Sstevel@tonic-gate printf(deleteoldrdn ?
11580Sstevel@tonic-gate gettext("new RDN: %s, new parent %s ( do not keep existing values)\n"):
11590Sstevel@tonic-gate gettext("new RDN: %s, new parent %s ( keep existing values)\n"));
11600Sstevel@tonic-gate }
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate
11630Sstevel@tonic-gate printf( gettext("%smodifying RDN of entry %s%s\n"),
11640Sstevel@tonic-gate ldaptool_not ? "!" : "", dn, ( newparent == NULL ) ? "" :
11650Sstevel@tonic-gate gettext(" and/or moving it beneath a new parent\n") );
11660Sstevel@tonic-gate
11670Sstevel@tonic-gate if ( !ldaptool_not ) {
11680Sstevel@tonic-gate if (( rc = ldaptool_rename_s( ld, dn, newrdn, newparent, deleteoldrdn,
11690Sstevel@tonic-gate ldaptool_request_ctrls, NULL, "ldap_rename" )) == LDAP_SUCCESS
11700Sstevel@tonic-gate && ldaptool_verbose ) {
11710Sstevel@tonic-gate printf( gettext("rename completed\n") );
11720Sstevel@tonic-gate }
11730Sstevel@tonic-gate } else {
11740Sstevel@tonic-gate rc = LDAP_SUCCESS;
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate putchar( '\n' );
11780Sstevel@tonic-gate
11790Sstevel@tonic-gate return( rc );
11800Sstevel@tonic-gate }
11810Sstevel@tonic-gate
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate static void
11840Sstevel@tonic-gate freepmods( LDAPMod **pmods )
11850Sstevel@tonic-gate {
11860Sstevel@tonic-gate int i;
11870Sstevel@tonic-gate
11880Sstevel@tonic-gate for ( i = 0; pmods[ i ] != NULL; ++i ) {
11890Sstevel@tonic-gate if ( pmods[ i ]->mod_bvalues != NULL ) {
11900Sstevel@tonic-gate ber_bvecfree( pmods[ i ]->mod_bvalues );
11910Sstevel@tonic-gate }
11920Sstevel@tonic-gate if ( pmods[ i ]->mod_type != NULL ) {
11930Sstevel@tonic-gate free( pmods[ i ]->mod_type );
11940Sstevel@tonic-gate }
11950Sstevel@tonic-gate free( pmods[ i ] );
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate free( pmods );
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate
12000Sstevel@tonic-gate
12010Sstevel@tonic-gate static char *
12020Sstevel@tonic-gate read_one_record( FILE *fp )
12030Sstevel@tonic-gate {
12040Sstevel@tonic-gate int len, gotnothing;
12050Sstevel@tonic-gate char *buf, line[ LDAPMOD_MAXLINE ];
12060Sstevel@tonic-gate int lcur, lmax;
12070Sstevel@tonic-gate
12080Sstevel@tonic-gate lcur = lmax = 0;
12090Sstevel@tonic-gate buf = NULL;
12100Sstevel@tonic-gate gotnothing = 1;
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
12130Sstevel@tonic-gate mutex_lock(&read_mutex);
12140Sstevel@tonic-gate
12150Sstevel@tonic-gate if (fp == NULL) {
12160Sstevel@tonic-gate mutex_unlock(&read_mutex);
12170Sstevel@tonic-gate return(NULL);
12180Sstevel@tonic-gate }
12190Sstevel@tonic-gate #endif
12200Sstevel@tonic-gate
12210Sstevel@tonic-gate while ( fgets( line, sizeof(line), fp ) != NULL ) {
12220Sstevel@tonic-gate if ( (len = strlen( line )) < 2 ) {
12230Sstevel@tonic-gate if ( gotnothing ) {
12240Sstevel@tonic-gate continue;
12250Sstevel@tonic-gate } else {
12260Sstevel@tonic-gate break;
12270Sstevel@tonic-gate }
12280Sstevel@tonic-gate }
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate /* Check if the blank line starts with '\r' (CR) */
12310Sstevel@tonic-gate if ( ((len = strlen( line )) == 2) && (line[0] == '\r') ) {
12320Sstevel@tonic-gate if ( gotnothing ) {
12330Sstevel@tonic-gate continue;
12340Sstevel@tonic-gate } else {
12350Sstevel@tonic-gate break;
12360Sstevel@tonic-gate }
12370Sstevel@tonic-gate }
12380Sstevel@tonic-gate
12390Sstevel@tonic-gate if ( *line == '#' ) {
12400Sstevel@tonic-gate continue; /* skip comment lines */
12410Sstevel@tonic-gate }
12420Sstevel@tonic-gate
12430Sstevel@tonic-gate gotnothing = 0;
12440Sstevel@tonic-gate if ( lcur + len + 1 > lmax ) {
12450Sstevel@tonic-gate lmax = LDAPMOD_MAXLINE
12460Sstevel@tonic-gate * (( lcur + len + 1 ) / LDAPMOD_MAXLINE + 1 );
12470Sstevel@tonic-gate if (( buf = (char *)LDAPTOOL_SAFEREALLOC( buf, lmax )) == NULL ) {
12480Sstevel@tonic-gate perror( "realloc" );
12490Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
12500Sstevel@tonic-gate mutex_unlock(&read_mutex);
12510Sstevel@tonic-gate #endif
12520Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
12530Sstevel@tonic-gate }
12540Sstevel@tonic-gate }
12550Sstevel@tonic-gate strcpy( buf + lcur, line );
12560Sstevel@tonic-gate lcur += len;
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate
12590Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
12600Sstevel@tonic-gate mutex_unlock(&read_mutex);
12610Sstevel@tonic-gate #endif
12620Sstevel@tonic-gate
12630Sstevel@tonic-gate return( buf );
12640Sstevel@tonic-gate }
12650Sstevel@tonic-gate
12660Sstevel@tonic-gate
12670Sstevel@tonic-gate /*
12680Sstevel@tonic-gate * strdup and trim trailing blanks
12690Sstevel@tonic-gate */
12700Sstevel@tonic-gate static char *
12710Sstevel@tonic-gate strdup_and_trim( char *s )
12720Sstevel@tonic-gate {
12730Sstevel@tonic-gate char *p;
12740Sstevel@tonic-gate
12750Sstevel@tonic-gate if (( s = strdup( s )) == NULL ) {
12760Sstevel@tonic-gate perror( "strdup" );
12770Sstevel@tonic-gate exit( LDAP_NO_MEMORY );
12780Sstevel@tonic-gate }
12790Sstevel@tonic-gate
12800Sstevel@tonic-gate p = s + strlen( s ) - 1;
12810Sstevel@tonic-gate while ( p >= s && isspace( *p )) {
12820Sstevel@tonic-gate --p;
12830Sstevel@tonic-gate }
12840Sstevel@tonic-gate *++p = '\0';
12850Sstevel@tonic-gate
12860Sstevel@tonic-gate return( s );
12870Sstevel@tonic-gate }
1288