|
On Tue, 9 Jul 2002, Haas, Matt wrote: > I'm trying to make updates to LDAP entries using the ldap_modify_s() API > and I'm not having any success doing this. [SNIP] > According to the documentation, the "mods" parameter is "a pointer to a > null-terminated array of pointers to LDAPmod structures" and both > mod_type and mod_values are pointers to null terminated arrays > attributes and values to add, delete, or replace. The way this is phrased is a bit misleading. mod_type is a pointer to a null-terminated array of characters (i.e. it ends with a byte with the value x'00') and mod_values is a pointer to a null-terminated array of pointers. (i.e. it ends when one of the pointers in the array contains *NULL). > > I've never done anything like this in RPG before (we're on V4R5 still so > I can't take advantage of the enhancements to dealing with data > structures in V5R1 that I'm sure would make this easier) and I'm > completely lost. Can anyone either send me some sample code that shows > how to use this or something like it or (better yet) point me to some > documentation that could help me figure this out on my own? I'm not sure that the V5R1 enhancements would really help with this particular issue. What you really need is a PHd in pointer logic. I don't know of any good documentation on this subject, so I'll try to explain what's going on in this message, and that'll be your documentation... :) As you say, mods is a pointer to a null-terminated array of pointers. That means that we need a pointer that contains an address. At that address will be another pointer, containing another address. Right after that, in the same area of memory, is another pointer containing another address, followed by another pointer, etc until one of those pointers is *NULL. Each of those pointers points to an LDAPMod structure. Which means that those pointers actually point to memory that contains an integer, followed by 3 more pointers. The integer is the "mod_op". It can be a 0, 1, or 2 to mean "add", "delete" or "replace" respectively. In addition, if you set on the 8th bit of the integer, it indicates that the operation should be done with binary values. The first of those three pointers (mod_type) points to memory that contains a character followed by another character, etc, until one of those characters is a x'00'. These characters make up the name of the attribyute that you modify. The next pointer (which can be referred to as mod_values, modv_strvals, mod_bvalues, or modv_bvals) points to YET ANOTHER array of pointers... so it points to a pointer, followed by another pointer, followed by another pointer, etc until one of those pointers is *NULL. Now, if mod_op contains the "LDAP_MOD_BVALUES" bit, these pointers will point to berval structures. If it does not, these pointers point to a character, followed by another character, etc, until one of them is x'00'. And, of course, the berval structure will contain an integer, which indicates a length, followed by YET ANOTHER POINTER, which contains the starting address of the memory containing the value. (and this one is not null-terminated, but rather you use the integer to determine how many characters to read). Whew! Finally, the mod_next pointer... I don't think this is needed for ldap_modify_s, so I just set the blasted thing to *NULL. Are you lost yet? I know I was. It took me a good day or so to get all of these pointers sorted out in my RPG code. I ended up taking sample C code for my PC (the structure is the same), hex-dumping the various areas of memory, and allowing for the differences in the way the PC and the AS/400 store pointers & integers, to finally figure all of this out. I'm tempted to write a whole diatribe on what an awful design this is, but I'll spare you. In the end, I created 3 subprocedures to populate this array. One to create it, one to populate it, and one to free the memory at the end. I couldn't think of a better way to break it down and make it readable. Here's some sample code, I think it'll save you time. I'm not going to repost the LDAP_H /copy member, it's the same as the one I posted in my previous message. Hope it helps... H DFTACTGRP(*NO) ACTGRP(*NEW) BNDDIR('QC2LE') H OPTION(*SRCSTMT: *NOSHOWCPY) D/copy mylib/qrpglesrc,ldap_h D LDAPMod_New PR * D peMaxElems 10I 0 value D LDAPMod_Add PR 10I 0 D peArray * value D peOper 10I 0 value D peAttrib 100A varying const D peValue 800A varying dim(10) D LDAPMod_Free PR D peArray * value D LOGIN_ACCT C 'cn=Administrator' D LOGIN_PASSWD C 'keepwishing' D ld S * D Mods s * D values s 800A varying dim(10) D DN s 100A varying D RC s 10I 0 D Msg s 52A c eval *inlr = *on c eval ld = ldap_init(*NULL: LDAP_PORT) c if ld = *NULL c eval rc = ldap_get_errno(ld) c eval Msg = %str(ldap_err2string(rc)) c dsply Msg c return c endif c eval rc = ldap_simple_bind_s(ld: c LOGIN_ACCT: LOGIN_PASSWD) c if rc <> LDAP_SUCCESS c eval Msg = %str(ldap_err2string(rc)) c dsply Msg c return c endif c exsr KillEntry c exsr AddEntry c exsr ChangeEntry c callp ldap_unbind(ld) c return C*=============================================================== C* This deletes the entry to avoid an "already exists" error C* on the ldap_add_s call. C*=============================================================== CSR KillEntry begsr C*------------------------ c eval DN = 'cn=Scott C Klement,' + c 'ou=Information Systems,' + c 'o=klements' c eval rc = ldap_delete_s(ld: DN) c eval msg = 'entry deleted' c dsply msg C*------------------------ CSR endsr C*=============================================================== C* This adds a new entry to the LDAP Server C*=============================================================== CSR AddEntry begsr C*------------------------ c eval Mods = LDAPMod_New(6) c if mods = *NULL c** handle error c endif c eval values(1) = 'top' c eval values(2) = 'person' c eval values(3) = 'organizationalPerson' c eval values(4) = 'inetOrgPerson' c eval %len(values(5)) = 0 c if ldapmod_add(Mods: c LDAP_MOD_REPLACE: c 'objectClass': c values) < 0 c** Handle error c endif c eval values(1) = 'Scott C Klement' c eval %len(values(2)) = 0 c if ldapmod_add(Mods: c LDAP_MOD_REPLACE: c 'cn': c values) < 0 c** Handle error c endif c eval values(1) = 'Orangutan' c eval %len(values(2)) = 0 c if ldapmod_add(Mods: c LDAP_MOD_REPLACE: c 'givenname': c values) < 0 c** Handle error c endif c eval values(1) = 'Klement' c eval %len(values(2)) = 0 c if ldapmod_add(Mods: c LDAP_MOD_REPLACE: c 'sn': c values) < 0 c** Handle error c endif c eval values(1) = 'Information Systems' c eval %len(values(2)) = 0 c if ldapmod_add(Mods: c LDAP_MOD_REPLACE: c 'ou': c values) < 0 c** Handle error c endif c eval values(1) = 'mistake@nospam.com' c eval %len(values(2)) = 0 c if ldapmod_add(Mods: c LDAP_MOD_REPLACE: c 'mail': c values) < 0 c** Handle error c endif c eval rc = ldap_add_s(ld: DN: Mods) c callp LDAPMod_Free(Mods) c if rc<> LDAP_SUCCESS c eval Msg = %str(ldap_err2string(rc)) c dsply msg c endif c eval msg = 'entry added' c dsply msg C*------------------------ csr endsr C*=============================================================== C* This modifies an entry on the LDAP Server C*=============================================================== CSR ChangeEntry begsr C*------------------------ c eval Mods = LDAPMod_New(2) c if mods = *NULL c** handle error c endif c eval values(1) = 'Scott' c eval %len(values(2)) = 0 c if ldapmod_add(Mods: c LDAP_MOD_REPLACE: c 'givenname': c values) < 0 c** Handle error c endif c eval values(1) = 'klemscot@nospam.com' c eval %len(values(2)) = 0 c if ldapmod_add(Mods: c LDAP_MOD_REPLACE: c 'mail': c values) < 0 c** Handle error c endif c eval DN = 'cn=Scott C Klement,' + c 'ou=Information Systems,' + c 'o=klements' c eval rc = ldap_modify_s(ld: DN: Mods) c callp LDAPMod_Free(Mods) c if rc<> LDAP_SUCCESS c eval Msg = %str(ldap_err2string(rc)) c dsply msg c endif C*------------------------ csr endsr *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * LDAPMod_New: Create a new LDAPMOD array * * peMaxElems = maximum number of modifications to * allow in the array. * * Returns a pointer to the array, or *NULL upon error *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ P LDAPMod_New B export D LDAPMod_New PI * D peMaxElems 10I 0 value D wwSize S 10I 0 D p_Return S * D wwIdx S 10I 0 D p_Elem S * D p_Data S * based(p_Elem) c if peMaxElems < 1 c return *NULL c endif C* Allocate space for an array of pointers: c eval wwSize = (peMaxElems+1) * c %size(p_data) c alloc(e) wwSize p_return c if %error c return *NULL c endif C* initialize all of the pointers in the array to null: c eval p_elem = p_return c for wwIdx = 1 to (peMaxElems+1) c eval p_data = *NULL c eval p_elem = p_elem + %size(p_data) c endfor C* return the array c return p_return P E *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * Add a new modification entry to an LDAPMod array * * peArray = pointer to LDAPMod array returned by the * LDAPMod_New subprocedure. * peOper = operationg to perform (mod_op) * peAttrib = attribute name (mod_type) * peValue = array of values (mod_values) to put into * structure. An empty value signals the * end of the array. * * returns 0 if successful, -1 otherwise *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ P LDAPMod_Add B export D LDAPMod_Add PI 10I 0 D peArray * value D peOper 10I 0 value D peAttrib 100A varying const D peValue 800A varying dim(10) D memset PR ExtProc('memset') D destptr * value D value 10I 0 value D length 10I 0 value D memcpy PR ExtProc('memcpy') D destptr * value D srcptr * value D length 10I 0 value D wwSize S 10I 0 D p_ArrayElem S * D wwArrayElem S * based(p_ArrayElem) D wwAttrib S 100A D p_StrElem S * D wwStrElem S * based(p_StrElem) D wwString S 800A D y S 10I 0 C************************************************* C* Find first *NULL element in the array: C************************************************* C* FIXME: We should be saving the number of allocated C* elements from LDAPMod_New and making sure we C* don't exceed that, here! c eval p_ArrayElem = peArray c dow wwArrayElem <> *NULL c eval p_ArrayElem = p_ArrayElem + c %size(wwArrayElem) c enddo C************************************************* c* Make space for a new LDAPMod structure C* in the array: C************************************************* c eval wwSize = %size(LDAPMod) c alloc wwSize wwArrayElem c eval p_LDAPMod = wwArrayElem c eval mod_op = peOper c eval mod_type = *NULL c eval mod_values = *NULL c eval mod_next = *NULL C************************************************* C* Add the attribute "type" (attribute name) to C* the structure: C************************************************* c eval wwAttrib = peAttrib c eval wwSize = %len(peAttrib) + 1 c alloc wwSize mod_type c callp memset(mod_type: 0: wwSize) c callp memcpy(mod_type: c %addr(wwAttrib): c wwSize - 1) C************************************************* C* Allocate another array of pointers to store C* attribute values: C************************************************* c eval wwSize=%size(wwStrElem) * (10+1) c alloc wwSize mod_values c eval p_strelem = mod_values c eval wwStrElem = *NULL C************************************************* C* Add each string's value to the array C************************************************* c eval y = 1 c dow y<=10 and %len(peValue(y))>0 c eval wwString = peValue(Y) c eval wwSize = %len(peValue(Y)) + 1 c alloc wwSize wwStrElem c callp memset(wwStrElem: 0: wwSize) c callp memcpy(wwStrElem: c %addr(wwString): c wwSize - 1) c eval y = y + 1 c eval p_strelem=p_strelem + %size(wwStrElem) c eval wwStrElem = *NULL c enddo c return 0 P E *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * LDAPMod_Free: Frees memory allocated by LDAPMod_New * and LDAPMod_Add * * peArray = pointer to array of LDAPMod structures * *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ P LDAPMod_Free B export D LDAPMod_Free PI D peArray * value D p_array S * D p_ArrayElem S * based(p_array) D p_value S * D p_valueelem S * based(p_value) c eval p_array = peArray c dow p_ArrayElem <> *NULL c eval p_ldapmod = p_arrayelem c eval p_value = mod_values c c dow p_ValueElem <> *NULL c dealloc p_valueelem c eval p_value = p_value + %size(p_valueelem) c enddo c dealloc mod_values c dealloc mod_type c dealloc p_arrayelem c eval p_array = p_array + %size(p_arrayelem) c enddo c dealloc peArray P E
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.