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 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 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 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 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 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