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