pjs/directory/docs/ldapcsdk/csdk-write.sgm

2119 строки
81 KiB
Plaintext

<!--
Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
Portions copyright 1999 Netscape Communications Corporation. All
Rights Reserved.
The contents of this document are subject to the terms of the
Creative Commons Attribution-ShareAlike 2.5 license or any later
version (the "License"). You may not use this document except in
compliance with the License.
See the License for the specific language governing
permissions and limitations under the License. You can obtain
a copy of the License at
http://creativecommons.org/licenses/by-sa/2.5/legalcode.
-->
<chapter id="csdk-write"><title>Adding, Updating, and Deleting Entries With &DirectorySDKForC;
</title>
<indexterm>
<primary>C SDK</primary>
<secondary>writing to directory entries</secondary>
</indexterm><highlights>
<para>This chapter explains how to use LDAP C API functions to add, update,
delete, and rename entries.</para>
<itemizedlist>
<para>This chapter covers the following topics:</para>
<listitem><para><olink targetptr="bdafw">Specifying Entry Information With
Directory SDK for C</olink></para></listitem>
<listitem><para><olink targetptr="bdafx">Adding an Entry With Directory SDK
for C</olink></para></listitem>
<listitem><para><olink targetptr="bdagg">Modifying an Entry With Directory
SDK for C</olink></para></listitem>
<listitem><para><olink targetptr="bdagr">Deleting an Entry With Directory
SDK for C</olink></para></listitem>
<listitem><para><olink targetptr="bdagu">Changing the DN of an Entry With
Directory SDK for C</olink></para></listitem>
</itemizedlist>
</highlights>
<sect1 id="bdafw"><title>Specifying Entry Information With &DirectorySDKForC;</title>
<itemizedlist>
<para>To add or modify an entry in the directory, you need to specify information
about the entry&rsquo;s attributes. In most cases, you must specify the following:
</para>
<listitem><para>The type of attribute that you are working with. For example,
the <literal>sn</literal> attribute or the <literal>telephoneNumber</literal> attribute.
</para></listitem>
<listitem><para>The values that you are adding, or replacing in the attribute.</para>
</listitem>
<listitem><para>The operation that you are performing when modifying an existing
entry. In other words, determine whether you are adding, modifying, or deleting
the attribute in the existing entry.</para></listitem>
</itemizedlist>
<para>To specify this information, you use an <structname>LDAPMod</structname> structure
as shown here.</para>
<example id="write-ldapmod-prototype"><title><structname>LDAPMod</structname> Structure
</title>
<programlisting>typedef struct ldapmod {
int mod_op;
char *mod_type;
union {
char **modv_strvals;
struct berval **modv_bvals;
} mod_vals;
#define mod_values mod_vals.modv_strvals
#define mod_bvalues mod_vals.modv_bvals
} LDAPMod;</programlisting>
</example>
<para>The following table details the fields in the <structname>LDAPMod</structname> data
structure.</para>
<table frame="topbot" pgwide="1" id="write-ldapmod-fields"><title><structname>LDAPMod
</structname> Field Descriptions</title>
<tgroup cols="2"><colspec colnum="1" colwidth="10*"><colspec colnum="2"
colwidth="90*">
<thead>
<row rowsep="1">
<entry colsep="0">
<para>Field</para></entry>
<entry colsep="0">
<para>Description</para></entry>
</row>
</thead>
<tbody>
<row rowsep="1">
<?PubTbl row rht="2.27in">
<entry colsep="0">
<para><structfield>mod_op</structfield></para></entry>
<entry colsep="0">
<itemizedlist>
<para>The operation to be performed on the attribute and the type of data
that is specified as the attribute values. This field can have one of the
following values:</para>
<listitem><para><literal>LDAP_MOD_ADD</literal> adds a value to the attribute.</para>
</listitem>
<listitem><para><literal>LDAP_MOD_DELETE</literal> removes a value from the
attribute.</para></listitem>
<listitem><para><literal>LDAP_MOD_REPLACE</literal> replaces all existing
values of the attribute.</para><para>Furthermore, if you specify binary values
in the <structfield>mod_bvalues</structfield> field, use the bitwise or operator, <literal>
|</literal>, to combine <literal>LDAP_MOD_BVALUES</literal> with the operation
type:</para>
<programlisting>mod->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES</programlisting>
<para>If you are using the structure to add a new entry, you can specify <literal>
0</literal> for the <literal>mod_op</literal> field, unless you are adding
binary values and need to specify <literal>LDAP_MOD_BVALUES</literal>. See <olink targetptr="bdafx">Adding an Entry With Directory SDK for C</olink> for details.</para>
</listitem>
</itemizedlist>
</entry>
</row>
<row>
<entry colsep="0">
<para><structfield>mod_type</structfield></para></entry>
<entry colsep="0">
<para>Attribute type that you want to add, delete, or replace, such as <literal>sn
</literal> or <literal>telephoneNumber</literal>.</para></entry>
</row>
<row>
<entry colsep="0">
<para><structfield>mod_values</structfield></para></entry>
<entry colsep="0">
<para>Pointer to a <literal>NULL</literal> terminated array of string values
for the attribute.</para></entry>
</row>
<row>
<entry colsep="0">
<para><structfield>mod_bvalues</structfield></para></entry>
<entry colsep="0">
<para>Pointer to a <literal>NULL</literal> terminated array of <structname>berval
</structname> structures for the attribute.</para></entry>
</row>
</tbody>
</tgroup>
</table>
<caution><para>The following precautions pertain to entry modifications and
the fields detailed in <olink targetptr="write-ldapmod-fields">Table 11&ndash;1</olink>.
</para></caution>
<itemizedlist>
<listitem><para>If you specify <literal>LDAP_MOD_DELETE</literal> in the <literal>
mod_op</literal> field to remove all values in an attribute, the attribute
is removed from the entry.</para></listitem>
<listitem><para>If you specify <literal>LDAP_MOD_DELETE</literal> in the <literal>
mod_op</literal> field and <literal>NULL</literal> in the <literal>mod_values</literal> field,
the attribute is removed from the entry.</para></listitem>
<listitem><para>If you specify <literal>LDAP_MOD_REPLACE</literal> in the <literal>
mod_op</literal> field and <literal>NULL</literal> in the <literal>mod_values</literal> field,
the attribute is removed from the entry.</para></listitem>
<listitem><para>If you specify <literal>LDAP_MOD_REPLACE</literal> in the <literal>
mod_op</literal> field, but the attribute does not exist in the entry, the
attribute is added to the entry.</para></listitem>
<listitem><para>If you specify <literal>LDAP_MOD_ADD</literal> in the <literal>mod_op
</literal> field, but the attribute does not exist in the entry, the attribute
is added to the entry.</para></listitem>
</itemizedlist>
<para>If you allocate memory for the structures yourself, free the structures
when you finish by calling the <function>ldap_mods_free</function> function.</para>
</sect1>
<sect1 id="bdafx"><title>Adding an Entry With &DirectorySDKForC;</title>
<indexterm>
<primary>LDAP entries</primary>
<secondary>adding</secondary>
</indexterm><indexterm>
<primary>entries</primary>
<secondary>adding</secondary>
</indexterm><indexterm>
<primary>adding</primary>
<secondary>LDAP entries</secondary>
</indexterm>
<para>The following procedure provides the general steps for adding a new
entry to the directory.</para>
<task><title>To Add a New Entry</title>
<procedure>
<step><para>Use the <structname>LDAPMod</structname> structure to specify
the name and values of each attribute.</para></step>
<step><para>Create an array of <structname>LDAPMod</structname> structures
to represent the attributes in the entry.</para></step>
<step><para>Call the <function>ldap_add_ext</function> or <function>ldap_add_ext_s
</function> function, passing in the array of <structname>LDAPMod</structname> structures
and a distinguished name (DN) for the entry. </para></step>
<step><para>Call the <function>ldap_mods_free</function> function to free
any <structname>LDAPMod</structname> structures that you allocated.</para>
</step>
</procedure>
</task>
<sect2 id="bdafy"><title>Specifying Values for Attributes</title>
<para>You can specify a value for an attribute in three ways. You can specify
a single value. You can specify multiple values. You can add binary data as
the value of an attribute.</para>
<sect3 id="bdafz"><title>Specifying a Single Value in an Attribute</title>
<para>To specify a value in an attribute, set the <literal>mod_op</literal>, <literal>
mod_type</literal>, and <literal>mod_values</literal> fields in an <structname>LDAPMod
</structname> structure. This example sets up the structure for the <literal>sn</literal> attribute.
</para>
<example id="write-setup-attr-example"><title>Setting Up an Attribute Structure</title>
<programlisting>#include "ldap.h"
&hellip;
LDAPMod attribute1;
char *sn_values[] = { "Jensen", NULL };
&hellip;
attribute1.mod_op = 0;
attribute1.mod_type = "sn";
attribute1.mod_values = sn_values;
&hellip;</programlisting>
</example>
<para>Because you are specifying an attribute for a new entry, rather than
for an existing entry, you can set the <literal>mod_op</literal> field to <literal>
0</literal>. For an existing entry, the <literal>mod_op</literal> field identifies
the type of change you are making to the entry.</para></sect3>
<sect3 id="bdaga"><title>Specifying Multiple Values in an Attribute</title>
<para>If an attribute has more than one value, specify the values in the <literal>
mod_values</literal> array. This example specifies two values for the <literal>cn
</literal> attribute.</para>
<example id="write-multiple-attr-vals-example"><title>Specifying Multiple
Values in an Attribute</title>
<programlisting>#include "ldap.h"
&hellip;
LDAPMod attribute2, attribute3;
char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL };
char *objectClass_values[] = { "top", "person",
"organizationalPerson", "inetOrgPerson", NULL };
&hellip;
attribute2.mod_op = 0;
attribute2.mod_type = "cn";
attribute2.mod_values = cn_values;
attribute3.mod_op = 0;
attribute3.mod_type = "objectClass";
attribute3.mod_values = objectClass_values;
&hellip;</programlisting>
</example>
</sect3>
<sect3 id="bdagb"><title>Specifying Binary Data as the Value of an Attribute</title>
<para>If the attribute contains binary data rather than string values, specify
the data in a <structname>berval</structname> structure similar to this.</para>
<example id="write-berval-prototype"><title><structname>berval</structname> Structure
</title>
<programlisting>struct berval {
unsigned long bv_len;
char *bv_val;
}</programlisting>
</example>
<para>The <structname>berval</structname> structure fields and field descriptions
are as follows:</para>
<variablelist>
<varlistentry><term>bv_len</term>
<listitem><para>The length of the data</para>
</listitem>
</varlistentry>
<varlistentry><term>bv_val</term>
<listitem><para>A pointer to the binary data</para>
</listitem>
</varlistentry>
</variablelist>
<para>After creating the <structname>berval</structname> structures for the
binary data, you may use the structures.</para>
<task><title>To Use <structname>berval</structname> Structures</title>
<procedure>
<step><para>Add the <structname>berval</structname> structures to the <literal>mod_bvalues
</literal> field in the <structname>LDAPMod</structname> structure.</para>
</step>
<step><para>Use the bitwise or operator, <literal>|</literal>, to combine
the value of the <literal>mod_op</literal> field with <literal>LDAP_MOD_BVALUES</literal>.
</para><para>When adding a new entry, you set the <literal>mod_op</literal> field
to <literal>LDAP_MOD_BVALUES</literal> because the <literal>mod_op</literal> field
is <literal>0</literal> in this case.</para><para>For example, suppose the
file <literal>my_photo.jpg</literal> contains a JPEG photograph of Barbara
Jensen. The following example sets the <literal>jpegPhoto</literal> attribute
to the JPEG data of the photograph.</para></step>
</procedure>
<example id="write-add-attr-value-example">
<title>Adding a Value to an Attribute</title>
<programlisting>#include &lt;stdio.h>
#include &lt;sys/stat.h>
#include "ldap.h"
&hellip;
char *photo_data;
FILE *fp;
struct stat st;
LDAPMod attribute4;
struct berval photo_berval;
struct berval *jpegPhoto_values[2];
/* Get information about the JPEG file, including its size. */
if ( stat( "my_photo.jpg", &amp;st ) != 0 ) {
perror( "stat" );
return( 1 );
}
/* Open the JPEG file and read it into memory. */
if ( ( fp = fopen( "my_photo.jpg", "rb" ) ) == NULL ) {
perror( "fopen" );
return( 1 );
}
if ( ( ( photo_data = ( char * )malloc( st.st_size ) ) == NULL ) ||
( fread ( photo_data, st.st_size, 1, fp ) != 1 ) ) {
perror( photo_data ? "fread" : "malloc" );
return( 1 );
}
fclose( fp );
attribute4.mod_op = LDAP_MOD_BVALUES;
attribute4.mod_type = "jpegPhoto";
photo_berval.bv_len = st.st_size;
photo_berval.bv_val = photo_data;
jpegPhoto_values[0] = &amp;photo_berval;
jpegPhoto_values[1] = NULL;
attribute4.mod_values = jpegPhoto_values;</programlisting>
</example>
</task>
</sect3>
</sect2>
<sect2 id="bdagc"><title>Specifying Attributes in the Entry</title>
<para>After specifying values for attributes in <structname>LDAPMod</structname> structures,
as described in <olink targetptr="bdafy">Specifying Values for Attributes</olink>,
you need to construct an array of these structures. You then pass a pointer
to this array as a parameter to the function for creating a new entry.</para>
<para>Make sure you create <structname>LDAPMod</structname> structures for
all required attributes in the new entry.</para>
<para> The following example creates an array of <structname>LDAPMod</structname> structures.
</para>
<example id="write-add-attr-value-array-example"><title>Adding an Array of
Structures to an Attribute</title>
<programlisting>#include "ldap.h"
LDAPMod *list_of_mods[5]
LDAPMod attribute1, attribute2, attribute3, attribute4;
&hellip;
/* Code for filling the LDAPMod structures with values */
&hellip;
list_of_mods[0] = &amp;attribute1;
list_of_mods[1] = &amp;attribute2;
list_of_mods[2] = &amp;attribute3;
list_of_mods[3] = &amp;attribute4;
list_of_mods[4] = NULL;
&hellip;</programlisting>
</example>
</sect2>
<sect2 id="bdagd"><title>Adding the Entry to the Directory</title>
<itemizedlist>
<para>To add the entry to the directory, call one of the following:</para>
<listitem><para>The synchronous <function>ldap_add_ext_s</function> function</para>
</listitem>
<listitem><para>The asynchronous <function>ldap_add_ext</function> function</para>
</listitem>
</itemizedlist>
<para>If you have allocated <structname>LDAPMod</structname> structures yourself,
you should free the structures when you are done. Call the <function>ldap_mods_free
</function> function to free <structname>LDAPMod</structname> structures.</para>
<sect3 id="bdage"><title>Synchronous Add Operation</title>
<indexterm>
<primary>synchronous functions</primary>
<secondary>add operation</secondary>
</indexterm>
<para>If you want to wait for the results of the add operation to complete
before continuing, call the synchronous <function>ldap_add_ext_s</function> function.
This function sends an LDAP add request to the server. The function also blocks
other work until the server sends the results of the operation back to your
client. The <function>ldap_add_ext_s</function> function returns <errorcode>LDAP_SUCCESS
</errorcode> if the operation completed successfully, or an error code if
a problem occurred.</para>
<para>The following example calls the synchronous <function>ldap_add_ext_s</function> function
to add the user <literal>William Jensen</literal> to the directory.</para>
<example id="write-sync-add-example"><title>Performing a Synchronous Add Operation
</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
&hellip;
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
&hellip;
LDAP *ld;
LDAPMod **mods;
char *matched_msg = NULL, *error_msg = NULL;
int rc;
&hellip;
/* Perform the add operation. */
rc = ldap_add_ext_s( ld, NEW_DN, mods, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s added successfully.\n", NEW_DN );
}
&hellip;</programlisting>
</example>
<para>The following sample program calls the synchronous <function>ldap_add_ext_s
</function> function to add a new user to the directory.</para>
<example id="write-sync-add-entry-example"><title>Sample Synchronous Add Program</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NUM_MODS 5
int
main( int argc, char **argv )
{
LDAP *ld;
LDAPMod **mods;
char *matched_msg = NULL, *error_msg = NULL;
int i, rc;
char *object_vals[] = { "top", "person", "organizationalPerson",
"inetOrgPerson", NULL };
char *cn_vals[] = { "William B Jensen", "William Jensen", "Bill Jensen",
NULL };
char *sn_vals[] = { "Jensen", NULL };
char *givenname_vals[] = { "William", "Bill", NULL };
char *telephonenumber_vals[] = { "+1 415 555 1212", NULL };
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind to the server as the Directory Manager. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Construct the array of LDAPMod structures representing the attributes
of the new entry. */
mods = ( LDAPMod ** ) malloc(( NUM_MODS + 1 ) * sizeof( LDAPMod * ));
if ( mods == NULL ) {
fprintf( stderr, "Cannot allocate memory for mods array\n" );
exit( 1 );
}
for ( i = 0; i &lt; NUM_MODS; i++ ) {
if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL ) {
fprintf( stderr, "Cannot allocate memory for mods element\n" );
exit( 1 );
}
}
mods[ 0 ]->mod_op = 0;
mods[ 0 ]->mod_type = "objectclass";
mods[ 0 ]->mod_values = object_vals;
mods[ 1 ]->mod_op = 0;
mods[ 1 ]->mod_type = "cn";
mods[ 1 ]->mod_values = cn_vals;
mods[ 2 ]->mod_op = 0;
mods[ 2 ]->mod_type = "sn";
mods[ 2 ]->mod_values = sn_vals;
mods[ 3 ]->mod_op = 0;
mods[ 3 ]->mod_type = "givenname";
mods[ 3 ]->mod_values = givenname_vals;
mods[ 4 ]->mod_op = 0;
mods[ 4 ]->mod_type = "telephonenumber";
mods[ 4 ]->mod_values = telephonenumber_vals;
mods[ 5 ] = NULL;
/* Perform the add operation. */
rc = ldap_add_ext_s( ld, NEW_DN, mods, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s added successfully.\n", NEW_DN );
}
ldap_unbind_s( ld );
for ( i = 0; i &lt; NUM_MODS; i++ ) {
free( mods[ i ] );
}
free( mods );
return 0;
}</programlisting>
</example>
</sect3>
<sect3 id="bdagf"><title>Asynchronous Add Operation</title>
<indexterm>
<primary>asynchronous functions</primary>
<secondary>add operation</secondary>
</indexterm>
<para>If you want to perform other work while waiting for the entry to be
added, call the asynchronous <function>ldap_add_ext</function> function. This
function sends an LDAP add request to the server and returns an <errorcode>LDAP_SUCCESS
</errorcode> result code if the request was successfully sent, or an LDAP
result code if an error occurred.</para>
<para>The <function>ldap_add_ext</function> function passes back a message
ID identifying the add operation. To determine whether the server sent a response
for this operation to your client, call the <function>ldap_result</function> function
and pass in this message ID. The <function>ldap_result</function> function
uses the message ID to determine if the server sent the results of the add
operation. The <function>ldap_result</function> function passes back the results
in an <structname>LDAPMessage</structname> structure. You can call the <function>
ldap_parse_result</function> function to parse the <structname>LDAPMessage</structname> structure
to determine if the operation was successful.</para>
<para>The following example calls the asynchronous <function>ldap_add_ext</function> function
to add the user <literal>William Jensen</literal> to the directory.</para>
<example id="write-async-add-example"><title>Performing an Asynchronous Add
Operation</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
&hellip;
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
&hellip;
LDAP *ld;
LDAPMessage *res;
LDAPControl **serverctrls;
char *matched_msg = NULL, *error_msg = NULL;
char **referrals;
int i, rc, parse_rc, msgid, finished = 0;
/* Timeout period for the ldap_result() function to wait for results. */
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
&hellip;
/* Send the LDAP add request. */
rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, &amp;msgid );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
}
&hellip;
/* Poll the server for the results of the add operation. */
while ( !finished ) {
rc = ldap_result( ld, msgid, 0, &amp;zerotime, &amp;res );
switch ( rc ) {
case -1:
/* An error occurred. */
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
case 0:
/* The timeout period specified by zerotime was exceeded,
so call ldap_result() again and continue polling. */
break;
default:
/* The function has retrieved the results of the add operation. */
finished = 1;
/* Parse the result to determine the result of
the add operation. */
parse_rc = ldap_parse_result( ld, res, &amp;rc, &amp;matched_msg,
&amp;error_msg, &amp;referrals, &amp;serverctrls, 1 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_parse_result: %s\n",
ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Check the results of the LDAP add operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s added successfully.\n", NEW_DN );
}
}
}
&hellip;</programlisting>
</example>
<para>The following sample program calls the asynchronous <function>ldap_add_ext</function> function
to add a new user to the directory.</para>
<example id="write-async-add-entry-example"><title>Sample Asynchronous Add
Program</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
void free_mods( LDAPMod **mods );
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NUM_MODS 5
int
main( int argc, char **argv )
{
LDAP *ld;
LDAPMessage *res;
LDAPMod **mods;
LDAPControl **serverctrls;
char *matched_msg = NULL, *error_msg = NULL;
char **referrals;
int i, rc, parse_rc, msgid, finished = 0;
struct timeval zerotime;
char *object_vals[] = { "top", "person", "organizationalPerson",
"inetOrgPerson", NULL };
char *cn_vals[] = { "William B Jensen", "William Jensen",
"Bill Jensen", NULL };
char *sn_vals[] = { "Jensen", NULL };
char *givenname_vals[] = { "William", "Bill", NULL };
char *telephonenumber_vals[] = { "+1 415 555 1212", NULL };
zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind to the server as the Directory Manager. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Construct the array of LDAPMod structures representing the attributes
of the new entry. */
mods = ( LDAPMod ** ) malloc(( NUM_MODS + 1 ) * sizeof( LDAPMod * ));
if ( mods == NULL ) {
fprintf( stderr, "Cannot allocate memory for mods array\n" );
exit( 1 );
}
for ( i = 0; i &lt; NUM_MODS; i++ ) {
if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL ) {
fprintf( stderr, "Cannot allocate memory for mods element\n" );
exit( 1 );
}
}
mods[ 0 ]->mod_op = 0;
mods[ 0 ]->mod_type = "objectclass";
mods[ 0 ]->mod_values = object_vals;
mods[ 1 ]->mod_op = 0;
mods[ 1 ]->mod_type = "cn";
mods[ 1 ]->mod_values = cn_vals;
mods[ 2 ]->mod_op = 0;
mods[ 2 ]->mod_type = "sn";
mods[ 2 ]->mod_values = sn_vals;
mods[ 3 ]->mod_op = 0;
mods[ 3 ]->mod_type = "givenname";
mods[ 3 ]->mod_values = givenname_vals;
mods[ 4 ]->mod_op = 0;
mods[ 4 ]->mod_type = "telephonenumber";
mods[ 4 ]->mod_values = telephonenumber_vals;
mods[ 5 ] = NULL;
/* Send the LDAP add request. */
rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, &amp;msgid );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
free_mods( mods );
return( 1 );
}
/* Poll the server for the results of the add operation. */
while ( !finished ) {
rc = ldap_result( ld, msgid, 0, &amp;zerotime, &amp;res );
switch ( rc ) {
case -1:
/* An error occurred. */
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
free_mods( mods );
return( 1 );
case 0:
/* The timeout period specified by zerotime was exceeded.
This means that the server has still not yet sent the
results of the add operation back to your client.
Break out of this switch statement, and continue calling
ldap_result() to poll for results. */
break;
default:
/* The function has retrieved the results of the add operation
from the server. */
finished = 1;
/* Parse the results received from the server. Note the last
argument is a non-zero value, which indicates that the
LDAPMessage structure will be freed when done. (No need
to call ldap_msgfree().) */
parse_rc =
ldap_parse_result( ld, res, &amp;rc, &amp;matched_msg,
&amp;error_msg, &amp;referrals, &amp;serverctrls, 1 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr,
"ldap_parse_result: %s\n",
ldap_err2string( parse_rc ) );
ldap_unbind( ld );
free_mods( mods );
return( 1 );
}
/* Check the results of the LDAP add operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s added successfully.\n"
"Counted to %d while waiting for the add operation.\n",
NEW_DN, global_counter );
}
}
/* Do other work while waiting for the results of the add operation. */
if ( !finished ) {
do_other_work();
}
}
ldap_unbind( ld );
free_mods( mods );
return 0;
}
/*
* Free a mods array.
*/
void
free_mods( LDAPMod **mods )
{
int i;
for ( i = 0; i &lt; NUM_MODS; i++ ) {
free( mods[ i ] );
}
free( mods );
}
/*
* Perform other work while polling for results.
* This doesn't do anything useful, but it could.
*/
void
do_other_work()
{
global_counter++;
}</programlisting>
</example>
</sect3>
</sect2>
</sect1>
<sect1 id="bdagg"><title>Modifying an Entry With &DirectorySDKForC;</title>
<indexterm>
<primary>LDAP entries</primary>
<secondary>modifying</secondary>
</indexterm><indexterm>
<primary>modifying</primary>
<secondary>LDAP entries</secondary>
</indexterm><indexterm>
<primary>entries</primary>
<secondary>modifying</secondary>
</indexterm>
<para>The following procedure provides the general steps for modifying an
entry.</para>
<task><title>To Modify an Entry</title>
<procedure>
<step><para>Use the <structname>LDAPMod</structname> structure to specify
a change to an attribute.</para></step>
<step><para>Create an array of <structname>LDAPMod</structname> structures
that represent the changes that need to be made.</para></step>
<step><para>Call the <function>ldap_modify_ext</function> or <function>ldap_modify_ext_s
</function> function, passing in the array of <structname>LDAPMod</structname> structures
and the DN of the entry that you want modified.</para></step>
<step><para>Call the <function>ldap_mods_free</function> function to free
any <structname>LDAPMod</structname> structures that you allocated.</para>
</step>
</procedure>
</task>
<sect2 id="bdagh"><title>Types of Modifications</title>
<para>You can modify an entry in various ways. The following sections explain
the types of modifications.</para>
<sect3 id="bdagi"><title>Replacing the Values of an Attribute</title>
<itemizedlist>
<para>To replace all existing values of an attribute, create an <structname>LDAPMod
</structname> structure with the following values.</para>
<listitem><para>Set the <literal>mod_type</literal> field to the attribute
type that you want to change, such as <literal>telephoneNumber</literal>.</para>
</listitem>
<listitem><para>Set the <literal>mod_values</literal> field to the new values
of the attribute.</para></listitem>
<listitem><para>Set the value of the <literal>mod_op</literal> field to <literal>
LDAP_MOD_REPLACE</literal>.</para></listitem>
</itemizedlist>
<para>The following code specifies a change that replaces the values of the <literal>
telephoneNumber</literal> attribute.</para>
<programlisting>#include "ldap.h"
LDAPMod attribute1;
char *telephoneNumber_values[] = { "+1 800 555 1212", NULL };
attribute1.mod_type = "telephoneNumber";
attribute1.mod_op = LDAP_MOD_REPLACE;
attribute1.mod_values = telephoneNumber_values;</programlisting>
<itemizedlist>
<para>If you want to specify binary data as <structname>berval</structname> structures
as opposed to string values, you need to do the following:</para>
<listitem><para>Use the <literal>mod_bvalues</literal> field rather than the <literal>
mod_values</literal> field.</para></listitem>
<listitem><para>Use the bitwise or operator, <literal>|</literal>, to combine
the value <literal>LDAP_MOD_BVALUES</literal> with the value of the <literal>mod_op
</literal> field.</para></listitem>
</itemizedlist>
<caution><para>If you specify an attribute that does not exist in the entry,
the attribute is added to the entry.</para><para>You can set a <literal>NULL</literal> value
for the attribute either by setting the <literal>mod_values</literal> field
to <literal>NULL</literal> or by setting the <literal>mod_bvalues</literal> field
to <literal>NULL</literal>. When the <literal>mod_op</literal> field also
contains <literal>LDAP_MOD_BVALUES</literal>, the attribute is removed from
the entry.</para></caution>
</sect3>
<sect3 id="bdagj"><title>Removing Values From an Attribute</title>
<itemizedlist>
<para>To remove values from an attribute, create an <structname>LDAPMod</structname> structure
with the following values:</para>
<listitem><para>Set the <literal>mod_type</literal> field to the attribute
type that contains the values to remove such as <literal>facsimileTelephoneNumber
</literal>.</para></listitem>
<listitem><para>Set the <literal>mod_values</literal> field to the values
that you want removed from the attribute.</para></listitem>
<listitem><para>Set the value of the <literal>mod_op</literal> field to <literal>
LDAP_MOD_DELETE</literal>.</para><para>The following code specifies the removal
of one of the values of the <literal>facsimileTelephoneNumber</literal> attribute
in the entry.</para>
<programlisting>#include "ldap.h"
LDAPMod attribute2;
char *fax_values[] = { "+1 800 555 1212", NULL };
attribute2.mod_type = "facsimileTelephoneNumber";
attribute2.mod_op = LDAP_MOD_DELETE;
attribute2.mod_values = fax_values;
&hellip;</programlisting>
</listitem>
</itemizedlist>
<itemizedlist>
<para>If you want to specify binary data as <structname>berval</structname> structures
as opposed to string values, you need to do the following:</para>
<listitem><para>Use the <literal>mod_bvalues</literal> field rather than the <literal>
mod_values</literal> field.</para></listitem>
<listitem><para>Use the bitwise or operator, <literal>|</literal>, to combine
the value <literal>LDAP_MOD_BVALUES</literal> with the value of the <literal>mod_op
</literal> field.</para></listitem>
</itemizedlist>
<caution><para>If you remove all values from the attribute, the attribute
is removed from the entry.</para><para>You can set a <literal>NULL</literal> value
for the attribute either by setting the <literal>mod_values</literal> field
to <literal>NULL</literal>, or by setting the <literal>mod_bvalues</literal> field
to <literal>NULL</literal>. When the <literal>mod_op</literal> field then
contains <literal>LDAP_MOD_BVALUES</literal>, the attribute is removed from
the entry.</para></caution>
</sect3>
<sect3 id="bdagk"><title>Adding Values to an Attribute</title>
<itemizedlist>
<para>To add values to an attribute in an entry, create an <structname>LDAPMod</structname> structure
with the following:</para>
<listitem><para>Set the <literal>mod_type</literal> field to the attribute
type that you want to add values to, such as <literal>audio</literal>.</para>
</listitem>
<listitem><para>Set the <literal>mod_values</literal> field to the new values
of the attribute.</para></listitem>
<listitem><para>Set the value of the <literal>mod_op</literal> field to <literal>
LDAP_MOD_ADD</literal>.</para></listitem>
</itemizedlist>
<itemizedlist>
<para>If the attribute contains binary data as opposed to string values, you
need to do the following values:</para>
<listitem><para>Use the <literal>mod_bvalues</literal> field rather than the <literal>
mod_values</literal> field, and put the values in <structname>berval</structname> structures.
</para></listitem>
<listitem><para>Use the bitwise or operator, <literal>|</literal>, to combine
the value <literal>LDAP_MOD_BVALUES</literal> with the value of the <literal>mod_op
</literal> field.</para></listitem>
</itemizedlist>
<para>If the attribute does not already exist in the entry, the attribute
is added to the entry.</para>
<para>The following code adds values to the <literal>audio</literal> attribute
of an entry.</para>
<programlisting>#include &lt;stdio.h>
#include &lt;sys/stat.h>
#include "ldap.h"
&hellip;
char *audio_data;
FILE *fp;
struct stat st;
LDAPMod attribute3;
struct berval audio_berval;
struct berval *audio_values[2];
&hellip;
/* Get information about the audio file, including its size. */
if ( stat( "my_sounds.au", &amp;st ) != 0 ) {
perror( "stat" );
return( 1 );
}
/* Open the audio file and read it into memory. */
if ( ( fp = fopen( "my_sounds.au", "rb" ) ) == NULL ) {
perror( "fopen" );
return( 1 );
}
if ( ( ( audio_data = ( char * )malloc( st.st_size ) ) == NULL ) ||
( fread ( audio_data, st.st_size, 1, fp ) != 1 ) ) {
perror( audio_data ? "fread" : "malloc" );
return( 1 );
}
fclose( fp );
attribute3.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
attribute3.mod_type = "audio";
audio_berval.bv_len = st.st_size;
audio_berval.bv_val = audio_data;
audio_values[0] = &amp;audio_berval;
audio_values[1] = NULL;
attribute3.mod_values = audio_values;
&hellip;</programlisting>
</sect3>
<sect3 id="bdagl"><title>Removing an Attribute With &DirectorySDKForC;</title>
<itemizedlist>
<para>You can remove an attribute from an entry in either of the following
ways:</para>
<listitem><para>Remove all values from the attribute.</para></listitem>
<listitem><para>Set the <literal>mod_op</literal> field to <literal>LDAP_MOD_REPLACE
</literal> or <literal>LDAP_MOD_DELETE</literal>, and specify <literal>NULL</literal> for
the <literal>mod_values</literal> field.</para></listitem>
</itemizedlist>
</sect3>
<sect3 id="bdagm"><title>Adding an Attribute With &DirectorySDKForC;</title>
<para>If you add or replace values in an attribute that does not yet exist
in the entry, the attribute is added to the entry.</para></sect3>
</sect2>
<sect2 id="bdagn"><title>Creating an Array of Changes</title>
<para>After specifying the changes to attribute values in <structname>LDAPMod</structname> structures,
you need to construct an array of these structures. You pass a pointer to
this array as a parameter to the function for modifying the entry. The following
example creates an array of <structname>LDAPMod</structname> structures.</para>
<example id="write-array-ldapmod-example"><title>Assembling an Array of <structname>
LDAPMod</structname> Structures</title>
<programlisting>#include "ldap.h"
&hellip;
LDAPMod *list_of_mods[4]
LDAPMod attribute1, attribute2, attribute3;
&hellip;
/* Code for filling the LDAPMod structures with values */
&hellip;
list_of_mods[0] = &amp;attribute1;
list_of_mods[1] = &amp;attribute2;
list_of_mods[2] = &amp;attribute3;
list_of_mods[3] = NULL;
&hellip;</programlisting>
</example>
</sect2>
<sect2 id="bdago"><title>Modifying an Entry in the Directory With &DirectorySDKForC;
</title>
<itemizedlist>
<para>To modify an entry in the directory, call one of the following functions:</para>
<listitem><para>The synchronous <function>ldap_modify_ext_s</function> function</para>
</listitem>
<listitem><para>The asynchronous <function>ldap_modify_ext</function> function</para>
</listitem>
</itemizedlist>
<sect3 id="bdagp"><title>Synchronous Modify Operation</title>
<para>If you want to wait for the results of the modify operation to complete
before continuing, call the synchronous <function>ldap_modify_ext_s</function> function.
The function sends a modify request to the server. Also, the function blocks
all work until the server sends the results of the operation back to your
client. The function returns <errorcode>LDAP_SUCCESS</errorcode> if the operation
completed successfully, or an error code if a problem occurred.</para>
<para>The following example calls the synchronous <function>ldap_modify_ext_s</function> function
to modify the entry for the user <literal>William Jensen</literal> in the
directory.</para>
<example id="write-sync-mod-example"><title>Performing a Synchronous Modify
Operation</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
&hellip;
LDAP *ld;
LDAPMod *mods[ 3 ];
char *matched_msg = NULL, *error_msg = NULL;
int rc;
&hellip;
/* Perform the modify operation. */
rc = ldap_modify_ext_s( ld, MODIFY_DN, mods, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_modify_ext_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s modified successfully.\n", MODIFY_DN );
}
ldap_unbind_s( ld );
&hellip;</programlisting>
</example>
<para>The following sample program calls the synchronous <function>ldap_modify_ext_s
</function> function to modify a user entry in the directory. The program
replaces the values of the <literal>mail</literal> attribute and adds a <literal>
description</literal> attribute to the entry.</para>
<example id="write-sync-mod-entry-example"><title>Sample Synchronous Modify
Program</title>
<programlisting>#include &lt;stdio.h>
#include &lt;time.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
LDAP *ld;
LDAPMod mod0, mod1;
LDAPMod *mods[ 3 ];
char *matched_msg = NULL, *error_msg = NULL;
char *vals0[ 2 ], *vals1[ 2 ];
time_t now;
char buf[ 128 ];
int rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind to the server as the Directory Manager. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Construct the array of LDAPMod structures representing the
changes that you want to make to attributes in the entry. */
/* Specify the first modification, which replaces all values of the
mail attribute with the value "wbj@example.com". */
mod0.mod_op = LDAP_MOD_REPLACE;
mod0.mod_type = "mail";
vals0[0] = "wbj@example.com";
vals0[1] = NULL;
mod0.mod_values = vals0;
/* Specify the second modification, which adds a value to the
description attribute. If this attribute does not yet exist,
the attribute ia added to the entry. */
mod1.mod_op = LDAP_MOD_ADD;
mod1.mod_type = "description";
time( &amp;now );
sprintf( buf, "This entry was modified with the modattrs program on %s",
ctime( &amp;now ));
/* Get rid of \n which ctime put on the end of the time string */
if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
buf[ strlen( buf ) - 1 ] = '\0';
}
vals1[ 0 ] = buf;
vals1[ 1 ] = NULL;
mod1.mod_values = vals1;
mods[ 0 ] = &amp;mod0;
mods[ 1 ] = &amp;mod1;
mods[ 2 ] = NULL;
/* Perform the modify operation. */
rc = ldap_modify_ext_s( ld, MODIFY_DN, mods, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_modify_ext_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s modified successfully.\n", MODIFY_DN );
}
ldap_unbind_s( ld );
return 0;
}</programlisting>
</example>
</sect3>
<sect3 id="bdagq"><title>Asynchronous Modify Operation</title>
<indexterm>
<primary>asynchronous functions</primary>
<secondary>modify operation</secondary>
</indexterm>
<para>If you want to perform other work in parallel while waiting for the
entry to be modified, call the asynchronous <function>ldap_modify_ext</function> function.
This function sends a modify request to the server and returns an <errorcode>LDAP_SUCCESS
</errorcode> result code if the request was successfully sent, or an LDAP
result code if an error occurred.</para>
<para>The <function>ldap_modify_ext</function> function passes back a message
ID identifying the modify operation. To determine whether the server sent
a response for this operation to your client, call the <function>ldap_result</function> function
and pass in this message ID. The <function>ldap_result</function> function
uses the message ID to determine if the server sent the results of the modify
operation. The <function>ldap_result</function> function passes back the results
in an <structname>LDAPMessage</structname> structure. You can call the <function>
ldap_parse_result</function> function to parse the <structname>LDAPMessage</structname> structure
to determine if the operation was successful.</para>
<para>The following example calls the asynchronous <function>ldap_modify_ext</function> function
to modify the entry for the user <literal>William Jensen</literal> in the
directory.</para>
<example id="write-async-mod-example"><title>Performing an Asynchronous Modify
Operation</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
&hellip;
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
&hellip;
LDAP *ld;
LDAPMessage *res;
LDAPMod *mods[ 3 ];
LDAPControl **serverctrls;
char *matched_msg = NULL, *error_msg = NULL;
char **referrals;
int rc, parse_rc, msgid, finished = 0;
/* Timeout period for the ldap_result() function to wait for results. */
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
&hellip;
/* Send the LDAP modify request. */
rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, &amp;msgid );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Poll the server for the results of the modify operation. */
while ( !finished ) {
rc = ldap_result( ld, msgid, 0, &amp;zerotime, &amp;res );
switch ( rc ) {
case -1:
/* An error occurred. */
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
case 0:
/* The timeout period specified by zerotime was exceeded,
so call ldap_result() again and continue polling. */
break;
default:
/* The function has retrieved the results of the
modify operation. */
finished = 1;
/* Parse the results received from the server. */
parse_rc = ldap_parse_result( ld, res, &amp;rc, &amp;matched_msg,
&amp;error_msg, &amp;referrals, &amp;serverctrls, 1 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_parse_result: %s\n",
ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Check the results of the LDAP modify operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_modify_ext: %s\n",
ldap_err2string( rc ) );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s modified successfully.\n", MODIFY_DN );
}
}
}
ldap_unbind( ld );
&hellip;</programlisting>
</example>
<para>The following sample program calls the asynchronous <function>ldap_modify_ext
</function> function to modify a user entry in the directory. The program
replaces the values of the <literal>mail</literal> attribute and adds a <literal>
description</literal> attribute to the entry.</para>
<example id="write-async-mod-entry-example"><title>Sample Asynchronous Modify
Program</title>
<programlisting>#include &lt;stdio.h>
#include &lt;time.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
LDAP *ld;
LDAPMessage *res;
LDAPMod mod0, mod1;
LDAPMod *mods[ 3 ];
LDAPControl **serverctrls;
char *matched_msg = NULL, *error_msg = NULL;
char **referrals;
char *vals0[ 2 ], *vals1[ 2 ];
time_t now;
char buf[ 128 ];
int rc, parse_rc, msgid, finished = 0;
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind to the server as the Directory Manager. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Construct the array of LDAPMod structures representing the changes
that you want to make to attributes in the entry. */
/* Specify the first modification, which replaces all values of the
mail attribute with the value "wbj@example.com". */
mod0.mod_op = LDAP_MOD_REPLACE;
mod0.mod_type = "mail";
vals0[0] = "wbj@example.com";
vals0[1] = NULL;
mod0.mod_values = vals0;
/* Specify the second modification, which adds a value to the description
attribute. If this attribute does not yet exist, the attribute ia added
to the entry. */
mod1.mod_op = LDAP_MOD_ADD;
mod1.mod_type = "description";
time( &amp;now );
sprintf( buf,
"This entry was modified with the modattrs program on %s",
ctime( &amp;now ));
/* Get rid of \n which ctime put on the end of the time string */
if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
buf[ strlen( buf ) - 1 ] = '\0';
}
vals1[ 0 ] = buf;
vals1[ 1 ] = NULL;
mod1.mod_values = vals1;
mods[ 0 ] = &amp;mod0;
mods[ 1 ] = &amp;mod1;
mods[ 2 ] = NULL;
/* Send the LDAP modify request. */
rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, &amp;msgid );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Poll the server for the results of the modify operation. */
while ( !finished ) {
rc = ldap_result( ld, msgid, 0, &amp;zerotime, &amp;res );
switch ( rc ) {
case -1:
/* An error occurred. */
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
case 0:
/* The timeout period specified by zerotime was exceeded.
This means that the server has still not yet sent the
results of the modify operation back to your client.
Break out of this switch statement, and continue calling
ldap_result() to poll for results. */
break;
default:
/* The function has retrieved the results of the modify
operation from the server. */
finished = 1;
/* Parse the results received from the server. Note the last
argument is a non-zero value, which indicates that the
LDAPMessage structure will be freed when done. (No need
to call ldap_msgfree().) */
parse_rc = ldap_parse_result( ld, res, &amp;rc, &amp;matched_msg,
&amp;error_msg, &amp;referrals, &amp;serverctrls, 1 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr,
"ldap_parse_result: %s\n",
ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Check the results of the LDAP add operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s modified successfully.\n"
"Counted to %d while waiting for the modify operation.\n",
MODIFY_DN, global_counter );
}
}
/* Do other work while waiting for the results of the modify operation. */
if ( !finished ) {
do_other_work();
}
}
ldap_unbind( ld );
return 0;
}
/*
* Perform other work while polling for results. This doesn't do anything
* useful, but it could.
*/
void
do_other_work()
{
global_counter++;
}</programlisting>
</example>
</sect3>
</sect2>
</sect1>
<sect1 id="bdagr"><title>Deleting an Entry With &DirectorySDKForC;</title>
<indexterm>
<primary>LDAP entry</primary>
<secondary>delete</secondary>
</indexterm><indexterm>
<primary>deleting</primary>
<secondary>LDAP entry</secondary>
</indexterm><indexterm>
<primary>entries</primary>
<secondary>deleting</secondary>
</indexterm>
<itemizedlist>
<para>To remove an entry from the directory, call one of the following functions:
</para>
<listitem><para>The synchronous <function>ldap_delete_ext_s</function> function</para>
</listitem>
<listitem><para>The asynchronous <function>ldap_delete_ext</function> function</para>
</listitem>
</itemizedlist>
<sect2 id="bdags"><title>Synchronous Delete Operation</title>
<indexterm>
<primary>synchronous functions</primary>
<secondary>delete operation</secondary>
</indexterm>
<para>If you want to wait for the results of the delete operation to complete
before continuing, call the synchronous <function>ldap_delete_ext_s</function> function.
This function sends a delete request to the server. The function also blocks
all other processes until the server sends the results of the operation back
to your client. The <function>ldap_delete_ext_s</function> function returns <errorcode>
LDAP_SUCCESS</errorcode> if the operation completed successfully, or an error
code if a problem occurred.</para>
<para>The following example calls the synchronous <function>ldap_delete_ext_s</function> function
to remove the entry for user <literal>William Jensen</literal> from the directory.
</para>
<example id="write-sync-del-example"><title>Performing a Synchronous Delete
Operation</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
&hellip;
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
&hellip;
LDAP *ld;
char *matched_msg = NULL, *error_msg = NULL;
int rc;
&hellip;
/* Perform the delete operation. */
rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_delete_ext_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s deleted successfully.\n", DELETE_DN );
}
ldap_unbind_s( ld );
&hellip;</programlisting>
</example>
<para>The following sample program calls the synchronous <function>ldap_delete_ext_s
</function> function to delete a user entry from the directory.</para>
<example id="write-sync-del-entry-example"><title>Sample Synchronous Delete
Program</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
LDAP *ld;
char *matched_msg = NULL, *error_msg = NULL;
int rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind to the server as the Directory Manager. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Perform the delete operation. */
rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_delete_ext_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s deleted successfully.\n", DELETE_DN );
}
ldap_unbind_s( ld );
return 0;
}</programlisting>
</example>
</sect2>
<sect2 id="bdagt"><title>Asynchronous Delete Operation</title>
<indexterm>
<primary>asynchronous functions</primary>
<secondary>delete operation</secondary>
</indexterm>
<para>If you want to perform other work in parallel while waiting for the
entry to be deleted, call the asynchronous <function>ldap_delete_ext</function> function.
This function sends a delete request to the server and returns an <errorcode>LDAP_SUCCESS
</errorcode> result code if the request was successfully sent, an LDAP result
code if an error occurred.</para>
<para>The <function>ldap_delete_ext</function> function passes back a message
ID identifying the delete operation. To determine whether the server sent
a response for this operation to your client, call the <function>ldap_result</function> function
and pass in this message ID. The <function>ldap_result</function> function
uses the message ID to determine if the server sent the results of the delete
operation. The <function>ldap_result</function> function passes back the results
in an <structname>LDAPMessage</structname> structure. You can call the <function>
ldap_parse_result</function> function to parse the <structname>LDAPMessage</structname> structure
to determine if the operation was successful.</para>
<para>The following example calls the asynchronous <function>ldap_delete_ext</function> function
to remove the user <literal>William Jensen</literal> from the directory.</para>
<example id="write-async-del-example"><title>Performing an Asynchronous Delete
Operation</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
&hellip;
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
&hellip;
LDAP *ld;
LDAPMessage *res;
LDAPControl **serverctrls;
char *matched_msg = NULL, *error_msg = NULL;
char **referrals;
int rc, parse_rc, msgid, finished = 0;
/* Timeout period for the ldap_result() function to wait for results. */
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
&hellip;
/* Send the LDAP delete request. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, &amp;msgid );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Poll the server for the results of the delete operation. */
while ( !finished ) {
rc = ldap_result( ld, msgid, 0, &amp;zerotime, &amp;res );
switch ( rc ) {
case -1:
/* An error occurred. */
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
case 0:
/* The timeout period specified by zerotime was exceeded,
so call ldap_result() again and continue polling. */
break;
default:
/* The function has retrieved the results of the
delete operation. */
finished = 1;
/* Parse the results received from the server. */
parse_rc = ldap_parse_result( ld, res, &amp;rc, &amp;matched_msg,
&amp;error_msg, &amp;referrals, &amp;serverctrls, 1 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_parse_result: %s\n",
ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Check the results of the LDAP delete operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_delete_ext: %s\n",
ldap_err2string( rc ) );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s deleted successfully.\n", DELETE_DN );
}
}
}
ldap_unbind( ld );
&hellip;</programlisting>
</example>
<para>The following sample program calls the asynchronous <function>ldap_delete_ext
</function> function to delete a user entry from the directory.</para>
<example id="write-async-del-entry-example"><title>Sample Asynchronous Delete
Program</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
LDAP *ld;
LDAPMessage *res;
LDAPControl **serverctrls;
char *matched_msg = NULL, *error_msg = NULL;
char **referrals;
int rc, parse_rc, msgid, finished = 0;
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind to the server as the Directory Manager. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Send the LDAP delete request. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, &amp;msgid );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Poll the server for the results of the delete operation. */
while ( !finished ) {
rc = ldap_result( ld, msgid, 0, &amp;zerotime, &amp;res );
switch ( rc ) {
case -1:
/* An error occurred. */
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
case 0:
/* The timeout period specified by zerotime was exceeded.
This means that the server has still not yet sent the
results of the delete operation back to your client.
Break out of this switch statement, and continue calling
ldap_result() to poll for results. */
break;
default:
/* The function has retrieved the results of the delete operation
from the server. */
finished = 1;
/* Parse the results received from the server. Note the last
argument is a non-zero value, which indicates that the
LDAPMessage structure will be freed when done. (No need
to call ldap_msgfree().) */
parse_rc = ldap_parse_result( ld, res, &amp;rc, &amp;matched_msg,
&amp;error_msg, &amp;referrals, &amp;serverctrls, 1 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr,
"ldap_parse_result: %s\n",
ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Check the results of the LDAP delete operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s deleted successfully.\n"
"Counted to %d while waiting for the delete operation.\n",
DELETE_DN, global_counter );
}
}
/* Do other work while waiting for the results of the
delete operation. */
if ( !finished ) {
do_other_work();
}
}
ldap_unbind( ld );
return 0;
}
/*
* Perform other work while polling for results. This
* doesn't do anything useful, but it could.
*/
void
do_other_work()
{
global_counter++;
}</programlisting>
</example>
</sect2>
</sect1>
<sect1 id="bdagu"><title>Changing the DN of an Entry With &DirectorySDKForC;</title>
<indexterm>
<primary>LDAP entry</primary>
<secondary>change DN</secondary>
</indexterm><indexterm>
<primary>changing</primary>
<secondary>DN of entry</secondary>
</indexterm><indexterm>
<primary>entries</primary>
<secondary>changing DN of<?Pub Caret></secondary>
</indexterm>
<itemizedlist>
<para>To change the distinguished name (DN) of an entry, call one of the following
functions:</para>
<listitem><para>The synchronous <function>ldap_rename_s</function> function</para>
</listitem>
<listitem><para>The asynchronous <function>ldap_rename</function> function</para>
</listitem>
</itemizedlist>
<para>For both functions, you can choose to delete the attribute that represents
the old relative distinguished name (RDN). You can also change the location
of the entry in the directory tree.</para>
<sect2 id="bdagv"><title>Synchronous Renaming Operation</title>
<indexterm>
<primary>synchronous functions</primary>
<secondary>renaming operation</secondary>
</indexterm>
<para>If you want to wait for the results of the modify DN operation to complete
before continuing, call the synchronous <function>ldap_rename_s</function> function.
This function sends a modify DN request to the server. The function also blocks
other work until the server sends the results of the operation back to your
client. The <function>ldap_rename_s</function> function returns <errorcode>LDAP_SUCCESS
</errorcode> if the operation completed successfully, or an error code if
a problem occurred.</para>
<para>The following calls the synchronous <function>ldap_rename_s</function> function
to change the RDN of the entry for the user <literal>William Jensen</literal> in
the directory.</para>
<example id="write-sync-rename-example"><title>Performing a Synchronous Rename
Operation</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
&hellip;
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
&hellip;
LDAP *ld;
char *matched_msg = NULL, *error_msg = NULL;
int rc;
&hellip;
/* Perform the modify DN operation. */
rc = ldap_rename_s( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_rename_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s renamed successfully.\n", OLD_DN );
}
ldap_unbind_s( ld );
&hellip;</programlisting>
</example>
</sect2>
<sect2 id="bdagw"><title>Asynchronous Renaming Operation</title>
<indexterm>
<primary>asynchronous functions</primary>
<secondary>renaming operation</secondary>
</indexterm>
<para>If you want to perform other work in parallel while waiting for the
entry to be renamed, call the asynchronous <function>ldap_rename</function> function.
This function sends a modify DN request to the server and returns an <errorcode>LDAP_SUCCESS
</errorcode> result code if the request was successfully sent, or an LDAP
result code if an error occurred.</para>
<para>The <function>ldap_rename</function> function passes back a message
ID identifying the modify DN operation. To determine whether the server sent
a response for this operation to your client, call the <function>ldap_result</function> function
and pass in this message ID. The <function>ldap_result</function> function
uses the message ID to determine if the server sent the results of the modify
DN operation. The <function>ldap_result</function> function passes back the
results in an <structname>LDAPMessage</structname> structure. You can call
the <function>ldap_parse_result</function> function to parse the <structname>LDAPMessage
</structname> structure to determine if the operation was successful.</para>
<para>The following example calls the asynchronous <function>ldap_rename</function> function
to change the RDN of the user <literal>William Jensen</literal> in the directory.
</para>
<example id="write-async-rename-example"><title>Performing an Asynchronous
Rename Operation</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
&hellip;
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
&hellip;
LDAP *ld;
LDAPMessage *res;
LDAPControl **serverctrls;
char *matched_msg = NULL, *error_msg = NULL;
char **referrals;
int rc, parse_rc, msgid, finished = 0;
/* Timeout period for the ldap_result() function to wait
for results. */
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
&hellip;
/* Send the LDAP modify DN request. */
rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, &amp;msgid );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Poll the server for the results of the modify DN operation. */
while ( !finished ) {
rc = ldap_result( ld, msgid, 0, &amp;zerotime, &amp;res );
switch ( rc ) {
case -1:
/* An error occurred. */
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
case 0:
/* The timeout period specified by zerotime was exceeded,
so call ldap_result() again and continue polling. */
break;
default:
/* The function has retrieved the results of the
modify DN operation. */
finished = 1;
/* Parse the results received from the server. */
parse_rc = ldap_parse_result( ld, res, &amp;rc, &amp;matched_msg,
&amp;error_msg, &amp;referrals, &amp;serverctrls, 1 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_parse_result: %s\n",
ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Check the results of the LDAP modify DN operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s renamed successfully.\n", OLD_DN );
}
}
}
ldap_unbind( ld );
&hellip;</programlisting>
</example>
</sect2>
<sect2 id="bdagx"><title>Deleting the Attribute From the Old RDN</title>
<para>Both <function>ldap_rename</function> and <function>ldap_rename_s</function> have
a <literal>deleteoldrdn</literal> parameter that allows you to remove the
old RDN from the entry. For example, suppose an entry has the following values
for the <literal>cn</literal> attribute:</para>
<programlisting>cn: Barbara Jensen
cn: Babs Jensen</programlisting>
<para>Then the following function adds the second name and removes the first:</para>
<programlisting>ldap_modrdn2( "cn=Barbara Jensen", "cn=Barbie Jensen", 1 );</programlisting>
<para>The function adds <literal>Barbie Jensen</literal> to the list of values.
The function removes the <literal>Barbara Jensen</literal> value. The resulting
entry has the following values:</para>
<programlisting>cn: Barbie Jensen
cn: Babs Jensen</programlisting>
<para>Suppose <literal>0</literal> is passed for the <literal>deleteoldrdn</literal> parameter
instead of <literal>1</literal>:</para>
<programlisting>ldap_modrdn2( "cn=Barbara Jensen", "cn=Barbie Jensen", 0 );</programlisting>
<para>The <literal>Barbara Jensen</literal> value is not removed from the
entry. The resulting entry has the following values:</para>
<programlisting>cn: Barbie Jensen
cn: Babs Jensen
cn: Barbara Jensen</programlisting>
</sect2>
<sect2 id="bdagy"><title>Changing the Location of the Entry</title>
<para>Both <function>ldap_rename</function> and <function>ldap_rename_s</function> have
a <literal>newparent</literal> parameter that allows you to specify a new
location for the entry in the directory tree. For example, if you pass <literal>ou=Contractors,dc=example,dc=com
</literal> as the <literal>newparent</literal> parameter when renaming the
entry <literal>uid=bjensen,ou=People,dc=example,dc=com</literal>, the entry
is moved under <literal>ou=Contractors,dc=example,dc=com</literal>. The new
DN for the entry is <literal>uid=bjensen,ou=Contractors,dc=example,dc=com</literal>.
</para>
<note><para>Some LDAP servers do not support this feature. When you specify
this argument, a server might return the LDAP result code <errorcode>LDAP_UNWILLING_TO_PERFORM
</errorcode>, with the error message <literal>Server does not support moving
of entries</literal>.</para></note>
<sect3 id="bdagz"><title>Synchronous Relocation of an Entry</title>
<para>The following example calls the synchronous <function>ldap_rename_s</function> function
to change the RDN of a user entry in the directory.</para>
<example id="write-sync-moddn-example"><title>Performing a Synchronous Relocation
of an Entry</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
int
main( int argc, char **argv )
{
LDAP *ld;
char *matched_msg = NULL, *error_msg = NULL;
int rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind to the server as the Directory Manager. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Perform the modify DN operation. */
rc = ldap_rename_s( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_rename_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s renamed successfully.\n", OLD_DN );
}
ldap_unbind_s( ld );
return 0;
}</programlisting>
</example>
</sect3>
<sect3 id="bdaha"><title>Asynchronous Relocation of an Entry</title>
<para>The following example calls the asynchronous <function>ldap_rename</function> function
to change the RDN of a user entry in the directory.</para>
<example id="write-async-moddn-example"><title>Performing an Asynchronous
Relocation of an Entry</title>
<programlisting>#include &lt;stdio.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "dougy4444"
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
int
main( int argc, char **argv )
{
LDAP *ld;
LDAPMessage *res;
LDAPControl **serverctrls;
char *matched_msg = NULL, *error_msg = NULL;
char **referrals;
int rc, parse_rc, msgid, finished = 0;
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind to the server as the Directory Manager. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &amp;matched_msg, &amp;error_msg );
if ( error_msg != NULL &amp;&amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Send the LDAP modify DN request. */
rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, &amp;msgid );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Poll the server for the results of the modify DN operation. */
while ( !finished ) {
rc = ldap_result( ld, msgid, 0, &amp;zerotime, &amp;res );
switch ( rc ) {
case -1:
/* An error occurred. */
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
case 0:
/* The timeout period specified by zerotime was exceeded.
This means that the server has still not yet sent the
results of the modify DN operation back to your client.
Break out of this switch statement, and continue calling
ldap_result() to poll for results. */
break;
default:
/* The function has retrieved the results of the modify DN operation
from the server. */
finished = 1;
/* Parse the results received from the server. Note the last
argument is a non-zero value, which indicates that the
LDAPMessage structure will be freed when done. (No need
to call ldap_msgfree().) */
parse_rc = ldap_parse_result( ld, res, &amp;rc, &amp;matched_msg,
&amp;error_msg, &amp;referrals, &amp;serverctrls, 1 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr,
"ldap_parse_result: %s\n",
ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Check the results of the LDAP modify DN operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL &amp; *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL &amp;&amp; *matched_msg != '\0' ) {
fprintf( stderr,
"Part of the DN that matches an existing entry: %s\n",
matched_msg );
}
} else {
printf( "%s renamed successfully.\n"
"Counted to %d while waiting for the modify DN operation.\n",
OLD_DN, global_counter );
}
}
/* Do other work while waiting for the results of the
modify DN operation. */
if ( !finished ) {
do_other_work();
}
}
ldap_unbind( ld );
return 0;
}
/*
* Perform other work while polling for results. This doesn't do
* anything useful, but it could.
*/
void
do_other_work()
{
global_counter++;
}</programlisting>
</example>
</sect3>
</sect2>
</sect1>
</chapter>