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 
20 static int	contoper, remove_oldrdn;
21 static LDAP	*ld;
22 
23 static int domodrdn( LDAP *ld, char *dn, char *rdn, char *newsuperior,
24 			int remove_oldrdn);
25 static void options_callback( int option, char *optarg );
26 
27 static 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 
38 int
39 main(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 
207 static void
208 options_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 
222 static int
223 domodrdn( 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