зеркало из https://github.com/mozilla/pjs.git
2119 строки
81 KiB
Plaintext
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’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–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"
|
|
…
|
|
LDAPMod attribute1;
|
|
char *sn_values[] = { "Jensen", NULL };
|
|
…
|
|
attribute1.mod_op = 0;
|
|
attribute1.mod_type = "sn";
|
|
attribute1.mod_values = sn_values;
|
|
…</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"
|
|
…
|
|
LDAPMod attribute2, attribute3;
|
|
char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL };
|
|
char *objectClass_values[] = { "top", "person",
|
|
"organizationalPerson", "inetOrgPerson", NULL };
|
|
…
|
|
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;
|
|
…</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 <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include "ldap.h"
|
|
…
|
|
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", &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] = &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;
|
|
…
|
|
/* Code for filling the LDAPMod structures with values */
|
|
…
|
|
list_of_mods[0] = &attribute1;
|
|
list_of_mods[1] = &attribute2;
|
|
list_of_mods[2] = &attribute3;
|
|
list_of_mods[3] = &attribute4;
|
|
list_of_mods[4] = NULL;
|
|
…</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 <stdio.h>
|
|
#include "ldap.h"
|
|
…
|
|
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
|
|
…
|
|
LDAP *ld;
|
|
LDAPMod **mods;
|
|
char *matched_msg = NULL, *error_msg = NULL;
|
|
int rc;
|
|
…
|
|
/* 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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 );
|
|
}
|
|
…</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 <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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 < 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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 < 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 <stdio.h>
|
|
#include "ldap.h"
|
|
…
|
|
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
|
|
|
|
…
|
|
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;
|
|
…
|
|
/* Send the LDAP add request. */
|
|
rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, &msgid );
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
|
|
ldap_unbind( ld );
|
|
return( 1 );
|
|
}
|
|
…
|
|
/* Poll the server for the results of the add operation. */
|
|
while ( !finished ) {
|
|
rc = ldap_result( ld, msgid, 0, &zerotime, &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, &rc, &matched_msg,
|
|
&error_msg, &referrals, &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 & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 );
|
|
}
|
|
}
|
|
}
|
|
…</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 <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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 < 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, &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, &zerotime, &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, &rc, &matched_msg,
|
|
&error_msg, &referrals, &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 & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 < 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;
|
|
…</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 <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include "ldap.h"
|
|
…
|
|
char *audio_data;
|
|
FILE *fp;
|
|
struct stat st;
|
|
LDAPMod attribute3;
|
|
struct berval audio_berval;
|
|
struct berval *audio_values[2];
|
|
…
|
|
/* Get information about the audio file, including its size. */
|
|
if ( stat( "my_sounds.au", &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] = &audio_berval;
|
|
audio_values[1] = NULL;
|
|
attribute3.mod_values = audio_values;
|
|
…</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"
|
|
…
|
|
LDAPMod *list_of_mods[4]
|
|
LDAPMod attribute1, attribute2, attribute3;
|
|
…
|
|
/* Code for filling the LDAPMod structures with values */
|
|
…
|
|
list_of_mods[0] = &attribute1;
|
|
list_of_mods[1] = &attribute2;
|
|
list_of_mods[2] = &attribute3;
|
|
list_of_mods[3] = NULL;
|
|
…</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 <stdio.h>
|
|
#include "ldap.h"
|
|
|
|
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
|
|
…
|
|
LDAP *ld;
|
|
LDAPMod *mods[ 3 ];
|
|
char *matched_msg = NULL, *error_msg = NULL;
|
|
int rc;
|
|
…
|
|
/* 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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 );
|
|
…</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 <stdio.h>
|
|
#include <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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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( &now );
|
|
sprintf( buf, "This entry was modified with the modattrs program on %s",
|
|
ctime( &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 ] = &mod0;
|
|
mods[ 1 ] = &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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 <stdio.h>
|
|
#include "ldap.h"
|
|
…
|
|
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
|
|
…
|
|
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;
|
|
…
|
|
/* Send the LDAP modify request. */
|
|
rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, &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, &zerotime, &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, &rc, &matched_msg,
|
|
&error_msg, &referrals, &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 & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 );
|
|
…</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 <stdio.h>
|
|
#include <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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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( &now );
|
|
sprintf( buf,
|
|
"This entry was modified with the modattrs program on %s",
|
|
ctime( &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 ] = &mod0;
|
|
mods[ 1 ] = &mod1;
|
|
mods[ 2 ] = NULL;
|
|
/* Send the LDAP modify request. */
|
|
rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, &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, &zerotime, &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, &rc, &matched_msg,
|
|
&error_msg, &referrals, &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 & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 <stdio.h>
|
|
#include "ldap.h"
|
|
…
|
|
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
|
|
…
|
|
LDAP *ld;
|
|
char *matched_msg = NULL, *error_msg = NULL;
|
|
int rc;
|
|
…
|
|
/* 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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 );
|
|
…</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 <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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 <stdio.h>
|
|
#include "ldap.h"
|
|
…
|
|
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
|
|
…
|
|
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;
|
|
…
|
|
/* Send the LDAP delete request. */
|
|
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, &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, &zerotime, &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, &rc, &matched_msg,
|
|
&error_msg, &referrals, &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 & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 );
|
|
…</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 <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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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, &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, &zerotime, &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, &rc, &matched_msg,
|
|
&error_msg, &referrals, &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 & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 <stdio.h>
|
|
#include "ldap.h"
|
|
…
|
|
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
|
|
#define NEW_RDN "uid=wjensen"
|
|
…
|
|
LDAP *ld;
|
|
char *matched_msg = NULL, *error_msg = NULL;
|
|
int rc;
|
|
…
|
|
/* 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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 );
|
|
…</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 <stdio.h>
|
|
#include "ldap.h"
|
|
…
|
|
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
|
|
#define NEW_RDN "uid=wjensen"
|
|
…
|
|
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;
|
|
…
|
|
/* Send the LDAP modify DN request. */
|
|
rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, &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, &zerotime, &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, &rc, &matched_msg,
|
|
&error_msg, &referrals, &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 & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 );
|
|
…</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 <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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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 <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, &matched_msg, &error_msg );
|
|
if ( error_msg != NULL && *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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, &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, &zerotime, &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, &rc, &matched_msg,
|
|
&error_msg, &referrals, &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 & *error_msg != '\0' ) {
|
|
fprintf( stderr, "%s\n", error_msg );
|
|
}
|
|
if ( matched_msg != NULL && *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>
|