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