× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



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 thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

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.