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