1/*
2 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6#pragma ident	"%Z%%M%	%I%	%E% SMI"
7
8/* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP */
9
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <locale.h>
14#include <ctype.h>
15#include <lber.h>
16#include <ldap.h>
17#include <locale.h>
18#include "ldaptool.h"
19
20static int	contoper, remove_oldrdn;
21static LDAP	*ld;
22
23static int domodrdn( LDAP *ld, char *dn, char *rdn, char *newsuperior,
24			int remove_oldrdn);
25static void options_callback( int option, char *optarg );
26
27static void usage( void )
28{
29	fprintf(stderr, gettext("usage: %s [options] [dn newrdn [newsuperior]]\n"), ldaptool_progname);
30	fprintf( stderr, gettext("options:\n"));
31	ldaptool_common_usage( 0 );
32	fprintf( stderr, gettext("    -c\t\tcontinuous mode\n") );
33	fprintf( stderr, gettext("    -r\t\tremove old RDN from the entries\n"));
34	fprintf( stderr, gettext("    -f file\tread changes from `file'\n") );
35	exit(LDAP_PARAM_ERROR );
36}
37
38int
39main(int argc, char **argv )
40{
41	char *myname, *entrydn, *rdn, buf[ 4096 ];
42	int rc, havedn, deref, optind;
43	char * L_newParent = NULL;
44	int haverdn = 0;
45
46	int L_protoVersion = LDAP_VERSION3;
47
48	char *locale = setlocale(LC_ALL, "");
49	textdomain(TEXT_DOMAIN);
50	ldaplogconfigf(NULL);
51
52
53	contoper =  remove_oldrdn = 0;
54
55	if ((myname = strrchr(argv[0], '/')) == NULL)
56		myname = argv[0];
57	else
58		++myname;
59
60	optind = ldaptool_process_args( argc, argv, "cr", 0, options_callback);
61
62	if ( optind == -1 ) {
63		usage();
64	}
65
66	if ( ldaptool_fp == NULL ) {
67	ldaptool_fp = stdin;
68	}
69
70	havedn = 0;
71	if (argc - optind == 3) 		/* accept as arguments: dn rdn newsuperior */
72	{
73		if (( L_newParent = strdup( argv[argc - 1] )) == NULL )
74		{
75			perror( "strdup" );
76			exit( LDAP_NO_MEMORY );
77		}
78
79		if (( rdn = strdup( argv[argc - 2] )) == NULL )
80		{
81			perror( "strdup" );
82			exit( LDAP_NO_MEMORY );
83		}
84
85		if (( entrydn = strdup( argv[argc - 3] )) == NULL )
86		{
87			perror( "strdup" );
88			exit( LDAP_NO_MEMORY );
89		}
90		++havedn;
91	}
92	else if (argc - optind == 2) 		/* accept as arguments: dn rdn */
93	{
94		if (( rdn = strdup( argv[argc - 1] )) == NULL )
95		{
96			perror( "strdup" );
97			exit( LDAP_NO_MEMORY );
98		}
99
100		if (( entrydn = strdup( argv[argc - 2] )) == NULL )
101		{
102			perror( "strdup" );
103			exit( 1 );
104		}
105		++havedn;
106	}
107	else if ( argc - optind != 0 )
108	{
109		fprintf( stderr, gettext("%s: invalid number of arguments, only two or three allowed\n"), myname);
110		usage();
111		exit( 1 );
112	}
113
114	ld = ldaptool_ldap_init (0);
115
116	if ( !ldaptool_not ) {
117		deref = LDAP_DEREF_NEVER;	/* this seems prudent */
118		ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
119	}
120
121	ldaptool_bind( ld );
122
123	rc = 0;
124	if (havedn)
125	{
126		rc = domodrdn(ld, entrydn, rdn, L_newParent, remove_oldrdn);
127	}
128	else while (	(rc == 0 || contoper) &&
129					(fgets(buf, sizeof(buf), ldaptool_fp) != NULL) )
130
131	{
132		/*
133		 * The format of the file is one of the following:
134		 * 	dn
135		 * 	rdn
136		 * 	newsuperior
137		 * 	<blank lines...>
138		 * OR
139		 * 	dn
140		 * 	rdn
141		 * 	<blank lines...>
142		 * both types of sequences can be found in the file
143		 */
144
145		if ( (strlen(buf) == 1) && (ldaptool_fp == stdin) )
146			break;
147
148		buf[ strlen( buf ) - 1 ] = '\0';	/* remove nl */
149		if ( *buf != '\0' ) 		/* blank lines optional, skip */
150		{
151			if ( haverdn )		/* first type of sequence */
152			{
153				if (( L_newParent = strdup( buf )) == NULL )
154				{
155					perror( "strdup" );
156					exit( LDAP_NO_MEMORY );
157				}
158				if ( L_newParent && (L_protoVersion == LDAP_VERSION) )
159				{
160					printf( gettext("LDAP Server is V2: <newsuperior> argument is ignored...\n") );
161					L_newParent = NULL;
162				}
163				rc = domodrdn(ld, entrydn, rdn, L_newParent, remove_oldrdn);
164				haverdn = 0;
165			}
166			else if ( havedn ) 		/* have DN, get RDN */
167			{
168				if (( rdn = strdup( buf )) == NULL )
169				{
170					perror( "strdup" );
171					exit( LDAP_NO_MEMORY );
172				}
173				havedn = 0;
174				++haverdn;
175			}
176			else if ( !havedn ) 		/* don't have DN yet */
177			{
178				if (( entrydn = strdup( buf )) == NULL)
179				{
180					perror( "strdup" );
181					exit( LDAP_NO_MEMORY );
182				}
183				++havedn;
184			}
185		}
186		else
187		{
188			printf(gettext("kex: new line %d\n"), rc);
189			if ( haverdn )		/* second type of sequence */
190			{
191				rc = domodrdn(ld, entrydn, rdn, NULL, remove_oldrdn);
192				haverdn = 0;
193			}
194		}
195	}
196	if ( (rc == 0 || contoper) && haverdn )		/* second type of sequence */
197	{
198		rc = domodrdn(ld, entrydn, rdn, NULL, remove_oldrdn);
199		haverdn = 0;
200	}
201
202	ldaptool_cleanup( ld );
203
204	exit( rc );
205}
206
207static void
208options_callback( int option, char *optarg )
209{
210	switch( option ) {
211		case 'c':	/* continuous operation mode */
212			++contoper;
213			break;
214		case 'r':	/* remove old RDN */
215			++remove_oldrdn;
216			break;
217		default:
218		usage();
219	}
220}
221
222static int
223domodrdn( LDAP *ld, char *dn, char *rdn, char *newsuperior, int remove_oldrdn )
224{
225	int	rc = LDAP_SUCCESS;
226
227	if ( ldaptool_verbose )
228		printf( gettext("new RDN: %1$s (%2$skeep existing values)\n"),
229						rdn, remove_oldrdn ? "do not " : "" );
230
231	printf( gettext("%1$srenaming entry %2$s\n"),
232			ldaptool_not ? "!" : "", dn );
233
234	if ( !ldaptool_not )
235	{
236		rc = ldap_rename_s( ld, dn, rdn, newsuperior, remove_oldrdn, NULL, NULL );
237		if ( rc != LDAP_SUCCESS )
238			fprintf(stderr, gettext("ldap_rename_s: %s\n"), ldap_err2string(rc));
239		else if ( ldaptool_verbose )
240			printf( gettext("rename completed\n") );
241	}
242
243	putchar('\n');
244
245	return( rc );
246}
247