Back to index

openldap  2.4.31
ldapmodrdn.c
Go to the documentation of this file.
00001 /* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
00007  * Portions Copyright 1998-2001 Net Boolean Incorporated.
00008  * Portions Copyright 2001-2003 IBM Corporation.
00009  * All rights reserved.
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted only as authorized by the OpenLDAP
00013  * Public License.
00014  *
00015  * A copy of this license is available in the file LICENSE in the
00016  * top-level directory of the distribution or, alternatively, at
00017  * <http://www.OpenLDAP.org/license.html>.
00018  */
00019 /* Portions Copyright 1999, Juan C. Gomez, All rights reserved.
00020  * This software is not subject to any license of Silicon Graphics 
00021  * Inc. or Purdue University.
00022  *
00023  * Redistribution and use in source and binary forms are permitted
00024  * without restriction or fee of any kind as long as this notice
00025  * is preserved.
00026  */
00027 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
00028  * All rights reserved.
00029  *
00030  * Redistribution and use in source and binary forms are permitted
00031  * provided that this notice is preserved and that due credit is given
00032  * to the University of Michigan at Ann Arbor.  The name of the
00033  * University may not be used to endorse or promote products derived
00034  * from this software without specific prior written permission.  This
00035  * software is provided ``as is'' without express or implied warranty.
00036  */
00037 /* ACKNOWLEDGEMENTS:
00038  * This work was originally developed by the University of Michigan
00039  * (as part of U-MICH LDAP).  Additional significant contributors
00040  * include:
00041  *     Kurt D. Zeilenga
00042  *     Juan C Gomez
00043  */
00044 
00045 
00046 #include "portable.h"
00047 
00048 #include <stdio.h>
00049 
00050 #include <ac/stdlib.h>
00051 
00052 #include <ac/ctype.h>
00053 #include <ac/string.h>
00054 #include <ac/unistd.h>
00055 #include <ac/socket.h>
00056 #include <ac/time.h>
00057 
00058 #include <ldap.h>
00059 #include "lutil.h"
00060 #include "lutil_ldap.h"
00061 #include "ldap_defaults.h"
00062 
00063 #include "common.h"
00064 
00065 
00066 static char   *newSuperior = NULL;
00067 static int   remove_old_RDN = 0;
00068 
00069 
00070 static int domodrdn(
00071        LDAP   *ld,
00072        char   *dn,
00073        char   *rdn,
00074        char   *newSuperior,
00075        int           remove );     /* flag: remove old RDN */
00076 
00077 void
00078 usage( void )
00079 {
00080        fprintf( stderr, _("Rename LDAP entries\n\n"));
00081        fprintf( stderr, _("usage: %s [options] [dn rdn]\n"), prog);
00082        fprintf( stderr, _(" dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n"));
00083        fprintf( stderr, _("        If not given, the list of modifications is read from stdin or\n"));
00084        fprintf( stderr, _("        from the file specified by \"-f file\" (see man page).\n"));
00085        fprintf( stderr, _("Rename options:\n"));
00086        fprintf( stderr, _("  -c         continuous operation mode (do not stop on errors)\n"));
00087        fprintf( stderr, _("  -f file    read operations from `file'\n"));
00088        fprintf( stderr, _("  -M         enable Manage DSA IT control (-MM to make critical)\n"));
00089        fprintf( stderr, _("  -P version protocol version (default: 3)\n"));
00090        fprintf( stderr, _("  -r            remove old RDN\n"));
00091        fprintf( stderr, _("  -s newsup  new superior entry\n"));
00092        tool_common_usage();
00093        exit( EXIT_FAILURE );
00094 }
00095 
00096 
00097 const char options[] = "rs:"
00098        "cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
00099 
00100 int
00101 handle_private_option( int i )
00102 {
00103        switch ( i ) {
00104 #if 0
00105               int crit;
00106               char *control, *cvalue;
00107        case 'E': /* modrdn extensions */
00108               if( protocol == LDAP_VERSION2 ) {
00109                      fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
00110                             prog, version );
00111                      exit( EXIT_FAILURE );
00112               }
00113 
00114               /* should be extended to support comma separated list of
00115                *     [!]key[=value] parameters, e.g.  -E !foo,bar=567
00116                */
00117 
00118               crit = 0;
00119               cvalue = NULL;
00120               if( optarg[0] == '!' ) {
00121                      crit = 1;
00122                      optarg++;
00123               }
00124 
00125               control = strdup( optarg );
00126               if ( (cvalue = strchr( control, '=' )) != NULL ) {
00127                      *cvalue++ = '\0';
00128               }
00129               fprintf( stderr, _("Invalid modrdn extension name: %s\n"), control );
00130               usage();
00131 #endif
00132 
00133        case 'r':     /* remove old RDN */
00134               remove_old_RDN++;
00135               break;
00136 
00137        case 's':     /* newSuperior */
00138               if( protocol == LDAP_VERSION2 ) {
00139                      fprintf( stderr, _("%s: -X incompatible with LDAPv%d\n"),
00140                             prog, protocol );
00141                      exit( EXIT_FAILURE );
00142               }
00143               newSuperior = strdup( optarg );
00144               protocol = LDAP_VERSION3;
00145               break;
00146 
00147        default:
00148               return 0;
00149        }
00150        return 1;
00151 }
00152 
00153 
00154 int
00155 main(int argc, char **argv)
00156 {
00157        char          *entrydn = NULL, *rdn = NULL, buf[ 4096 ];
00158        FILE          *fp = NULL;
00159        LDAP          *ld = NULL;
00160        int           rc, retval, havedn;
00161 
00162        tool_init( TOOL_MODRDN );
00163        prog = lutil_progname( "ldapmodrdn", argc, argv );
00164 
00165        tool_args( argc, argv );
00166 
00167        havedn = 0;
00168        if (argc - optind == 2) {
00169               if (( rdn = strdup( argv[argc - 1] )) == NULL ) {
00170                      perror( "strdup" );
00171                      retval = EXIT_FAILURE;
00172                      goto fail;
00173               }
00174               if (( entrydn = strdup( argv[argc - 2] )) == NULL ) {
00175                      perror( "strdup" );
00176                      retval = EXIT_FAILURE;
00177                      goto fail;
00178               }
00179               ++havedn;
00180        } else if ( argc - optind != 0 ) {
00181               fprintf( stderr, _("%s: invalid number of arguments (%d), only two allowed\n"), prog, argc-optind );
00182               usage();
00183        }
00184 
00185        if ( infile != NULL ) {
00186               if (( fp = fopen( infile, "r" )) == NULL ) {
00187                      perror( infile );
00188                      retval = EXIT_FAILURE;
00189                      goto fail;
00190               }
00191        } else {
00192               fp = stdin;
00193        }
00194 
00195        ld = tool_conn_setup( 0, 0 );
00196 
00197        tool_bind( ld );
00198 
00199        tool_server_controls( ld, NULL, 0 );
00200 
00201        retval = rc = 0;
00202        if (havedn)
00203               retval = domodrdn( ld, entrydn, rdn, newSuperior, remove_old_RDN );
00204        else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) {
00205               if ( *buf != '\n' ) {       /* blank lines optional, skip */
00206                      buf[ strlen( buf ) - 1 ] = '\0';   /* remove nl */
00207 
00208                      if ( havedn ) {      /* have DN, get RDN */
00209                             if (( rdn = strdup( buf )) == NULL ) {
00210                                    perror( "strdup" );
00211                                    retval = EXIT_FAILURE;
00212                                    goto fail;
00213                             }
00214                             rc = domodrdn(ld, entrydn, rdn, newSuperior, remove_old_RDN );
00215                             if ( rc != 0 )
00216                                    retval = rc;
00217                             havedn = 0;
00218                             free( rdn ); rdn = NULL;
00219                             free( entrydn ); entrydn = NULL;
00220                      } else if ( !havedn ) {     /* don't have DN yet */
00221                             if (( entrydn = strdup( buf )) == NULL ) {
00222                                    retval = EXIT_FAILURE;
00223                                    goto fail;
00224                             }
00225                             ++havedn;
00226                      }
00227               }
00228        }
00229 
00230 fail:
00231        if ( fp && fp != stdin ) fclose( fp );
00232        if ( entrydn ) free( entrydn );
00233        if ( rdn ) free( rdn );
00234        tool_exit( ld, retval );
00235 }
00236 
00237 static int domodrdn(
00238        LDAP   *ld,
00239        char   *dn,
00240        char   *rdn,
00241        char   *newSuperior,
00242        int           remove ) /* flag: remove old RDN */
00243 {
00244        int rc, code, id;
00245        char *matcheddn=NULL, *text=NULL, **refs=NULL;
00246        LDAPControl **ctrls = NULL;
00247        LDAPMessage *res;
00248 
00249        if ( verbose ) {
00250               printf( _("Renaming \"%s\"\n"), dn );
00251               printf( _("\tnew rdn=\"%s\" (%s old rdn)\n"),
00252                      rdn, remove ? _("delete") : _("keep") );
00253               if( newSuperior != NULL ) {
00254                      printf(_("\tnew parent=\"%s\"\n"), newSuperior);
00255               }
00256        }
00257 
00258        if( dont ) return LDAP_SUCCESS;
00259 
00260        rc = ldap_rename( ld, dn, rdn, newSuperior, remove,
00261               NULL, NULL, &id );
00262 
00263        if ( rc != LDAP_SUCCESS ) {
00264               fprintf( stderr, "%s: ldap_rename: %s (%d)\n",
00265                      prog, ldap_err2string( rc ), rc );
00266               return rc;
00267        }
00268 
00269        for ( ; ; ) {
00270               struct timeval       tv = { 0, 0 };
00271 
00272               if ( tool_check_abandon( ld, id ) ) {
00273                      return LDAP_CANCELLED;
00274               }
00275 
00276               tv.tv_sec = 0;
00277               tv.tv_usec = 100000;
00278 
00279               rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res );
00280               if ( rc < 0 ) {
00281                      tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL );
00282                      return rc;
00283               }
00284 
00285               if ( rc != 0 ) {
00286                      break;
00287               }
00288        }
00289 
00290        rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
00291 
00292        if( rc != LDAP_SUCCESS ) {
00293               fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
00294                      prog, ldap_err2string( rc ), rc );
00295               return rc;
00296        }
00297 
00298        if( verbose || code != LDAP_SUCCESS ||
00299               (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) )
00300        {
00301               printf( _("Rename Result: %s (%d)\n"),
00302                      ldap_err2string( code ), code );
00303 
00304               if( text && *text ) {
00305                      printf( _("Additional info: %s\n"), text );
00306               }
00307 
00308               if( matcheddn && *matcheddn ) {
00309                      printf( _("Matched DN: %s\n"), matcheddn );
00310               }
00311 
00312               if( refs ) {
00313                      int i;
00314                      for( i=0; refs[i]; i++ ) {
00315                             printf(_("Referral: %s\n"), refs[i] );
00316                      }
00317               }
00318        }
00319 
00320        if (ctrls) {
00321               tool_print_ctrls( ld, ctrls );
00322               ldap_controls_free( ctrls );
00323        }
00324 
00325        ber_memfree( text );
00326        ber_memfree( matcheddn );
00327        ber_memvfree( (void **) refs );
00328 
00329        return code;
00330 }