root/usr/src/cmd/ldap/common/ldapmodrdn.c
/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include <ctype.h>
#include <lber.h>
#include <ldap.h>
#include <locale.h>
#include "ldaptool.h"

static int      contoper, remove_oldrdn;
static LDAP     *ld;

static int domodrdn( LDAP *ld, char *dn, char *rdn, char *newsuperior,
                        int remove_oldrdn);
static void options_callback( int option, char *optarg );

static void usage( void )
{
        fprintf(stderr, gettext("usage: %s [options] [dn newrdn [newsuperior]]\n"), ldaptool_progname);
        fprintf( stderr, gettext("options:\n"));
        ldaptool_common_usage( 0 );
        fprintf( stderr, gettext("    -c\t\tcontinuous mode\n") );
        fprintf( stderr, gettext("    -r\t\tremove old RDN from the entries\n"));
        fprintf( stderr, gettext("    -f file\tread changes from `file'\n") );
        exit(LDAP_PARAM_ERROR );
}

int
main(int argc, char **argv )
{
        char *myname, *entrydn, *rdn, buf[ 4096 ];
        int rc, havedn, deref, optind;
        char * L_newParent = NULL;
        int haverdn = 0;

        int L_protoVersion = LDAP_VERSION3;

        char *locale = setlocale(LC_ALL, "");
        textdomain(TEXT_DOMAIN);
        ldaplogconfigf(NULL);


        contoper =  remove_oldrdn = 0;

        if ((myname = strrchr(argv[0], '/')) == NULL)
                myname = argv[0];
        else
                ++myname;

        optind = ldaptool_process_args( argc, argv, "cr", 0, options_callback);

        if ( optind == -1 ) {
                usage();
        }

        if ( ldaptool_fp == NULL ) {
        ldaptool_fp = stdin;
        }

        havedn = 0;
        if (argc - optind == 3)                 /* accept as arguments: dn rdn newsuperior */
        {
                if (( L_newParent = strdup( argv[argc - 1] )) == NULL )
                {
                        perror( "strdup" );
                        exit( LDAP_NO_MEMORY );
                }

                if (( rdn = strdup( argv[argc - 2] )) == NULL )
                {
                        perror( "strdup" );
                        exit( LDAP_NO_MEMORY );
                }

                if (( entrydn = strdup( argv[argc - 3] )) == NULL )
                {
                        perror( "strdup" );
                        exit( LDAP_NO_MEMORY );
                }
                ++havedn;
        }
        else if (argc - optind == 2)            /* accept as arguments: dn rdn */
        {
                if (( rdn = strdup( argv[argc - 1] )) == NULL )
                {
                        perror( "strdup" );
                        exit( LDAP_NO_MEMORY );
                }

                if (( entrydn = strdup( argv[argc - 2] )) == NULL )
                {
                        perror( "strdup" );
                        exit( 1 );
                }
                ++havedn;
        }
        else if ( argc - optind != 0 )
        {
                fprintf( stderr, gettext("%s: invalid number of arguments, only two or three allowed\n"), myname);
                usage();
                exit( 1 );
        }

        ld = ldaptool_ldap_init (0);

        if ( !ldaptool_not ) {
                deref = LDAP_DEREF_NEVER;       /* this seems prudent */
                ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
        }

        ldaptool_bind( ld );

        rc = 0;
        if (havedn)
        {
                rc = domodrdn(ld, entrydn, rdn, L_newParent, remove_oldrdn);
        }
        else while (    (rc == 0 || contoper) &&
                                        (fgets(buf, sizeof(buf), ldaptool_fp) != NULL) )

        {
                /*
                 * The format of the file is one of the following:
                 *      dn
                 *      rdn
                 *      newsuperior
                 *      <blank lines...>
                 * OR
                 *      dn
                 *      rdn
                 *      <blank lines...>
                 * both types of sequences can be found in the file
                 */

                if ( (strlen(buf) == 1) && (ldaptool_fp == stdin) )
                        break;

                buf[ strlen( buf ) - 1 ] = '\0';        /* remove nl */
                if ( *buf != '\0' )             /* blank lines optional, skip */
                {
                        if ( haverdn )          /* first type of sequence */
                        {
                                if (( L_newParent = strdup( buf )) == NULL )
                                {
                                        perror( "strdup" );
                                        exit( LDAP_NO_MEMORY );
                                }
                                if ( L_newParent && (L_protoVersion == LDAP_VERSION) )
                                {
                                        printf( gettext("LDAP Server is V2: <newsuperior> argument is ignored...\n") );
                                        L_newParent = NULL;
                                }
                                rc = domodrdn(ld, entrydn, rdn, L_newParent, remove_oldrdn);
                                haverdn = 0;
                        }
                        else if ( havedn )              /* have DN, get RDN */
                        {
                                if (( rdn = strdup( buf )) == NULL )
                                {
                                        perror( "strdup" );
                                        exit( LDAP_NO_MEMORY );
                                }
                                havedn = 0;
                                ++haverdn;
                        }
                        else if ( !havedn )             /* don't have DN yet */
                        {
                                if (( entrydn = strdup( buf )) == NULL)
                                {
                                        perror( "strdup" );
                                        exit( LDAP_NO_MEMORY );
                                }
                                ++havedn;
                        }
                }
                else
                {
                        printf(gettext("kex: new line %d\n"), rc);
                        if ( haverdn )          /* second type of sequence */
                        {
                                rc = domodrdn(ld, entrydn, rdn, NULL, remove_oldrdn);
                                haverdn = 0;
                        }
                }
        }
        if ( (rc == 0 || contoper) && haverdn )         /* second type of sequence */
        {
                rc = domodrdn(ld, entrydn, rdn, NULL, remove_oldrdn);
                haverdn = 0;
        }

        ldaptool_cleanup( ld );

        exit( rc );
}

static void
options_callback( int option, char *optarg )
{
        switch( option ) {
                case 'c':       /* continuous operation mode */
                        ++contoper;
                        break;
                case 'r':       /* remove old RDN */
                        ++remove_oldrdn;
                        break;
                default:
                usage();
        }
}

static int
domodrdn( LDAP *ld, char *dn, char *rdn, char *newsuperior, int remove_oldrdn )
{
        int     rc = LDAP_SUCCESS;

        if ( ldaptool_verbose )
                printf( gettext("new RDN: %1$s (%2$skeep existing values)\n"),
                                                rdn, remove_oldrdn ? "do not " : "" );

        printf( gettext("%1$srenaming entry %2$s\n"),
                        ldaptool_not ? "!" : "", dn );

        if ( !ldaptool_not )
        {
                rc = ldap_rename_s( ld, dn, rdn, newsuperior, remove_oldrdn, NULL, NULL );
                if ( rc != LDAP_SUCCESS )
                        fprintf(stderr, gettext("ldap_rename_s: %s\n"), ldap_err2string(rc));
                else if ( ldaptool_verbose )
                        printf( gettext("rename completed\n") );
        }

        putchar('\n');

        return( rc );
}