diff src/eldap.c @ 371:cc15677e0335 r21-2b1

Import from CVS: tag r21-2b1
author cvs
date Mon, 13 Aug 2007 11:03:08 +0200
parents 7347b34c275b
children bbff43aa5eb7
line wrap: on
line diff
--- a/src/eldap.c	Mon Aug 13 11:01:58 2007 +0200
+++ b/src/eldap.c	Mon Aug 13 11:03:08 2007 +0200
@@ -26,20 +26,26 @@
    conforming to the API defined in RFC 1823.
    It has been tested with:
    - UMich LDAP 3.3 (http://www.umich.edu/~dirsvcs/ldap/)
-   - OpenLDAP 1.2 (http://www.openldap.org/)
-   - Netscape's LDAP SDK (http://developer.netscape.com/) */
+   - Netscape's LDAP SDK 1.0 (http://developer.netscape.com) */
 
 
 #include <config.h>
 #include "lisp.h"
 #include "opaque.h"
 #include "sysdep.h"
-#include "buffer.h"
 
 #include <errno.h>
 
 #include "eldap.h"
 
+#ifdef HAVE_NS_LDAP
+# define HAVE_LDAP_SET_OPTION 1
+# define HAVE_LDAP_GET_ERRNO 1
+#else
+# undef HAVE_LDAP_SET_OPTION
+# undef HAVE_LDAP_GET_ERRNO
+#endif
+
 static int ldap_default_port;
 static Lisp_Object Vldap_default_base;
 
@@ -61,27 +67,16 @@
 /************************************************************************/
 
 static void
-signal_ldap_error (LDAP *ld, LDAPMessage *res, int ldap_err)
+signal_ldap_error (LDAP *ld)
 {
-  if (ldap_err <= 0)
-    {
-#if defined HAVE_LDAP_PARSE_RESULT
-      int err;
-      ldap_err = ldap_parse_result (ld, res,
-                                    &err,
-                                    NULL, NULL, NULL, NULL, 0);
-      if (ldap_err == LDAP_SUCCESS)
-        ldap_err = err;
-#elif defined HAVE_LDAP_GET_LDERRNO
-      ldap_err = ldap_get_lderrno (ld, NULL, NULL);
-#elif defined HAVE_LDAP_RESULT2ERROR
-      ldap_err = ldap_result2error (ld, res, 0);
+#ifdef HAVE_LDAP_GET_ERRNO
+  signal_simple_error
+    ("LDAP error",
+     build_string (ldap_err2string (ldap_get_lderrno (ld, NULL, NULL))));
 #else
-      ldap_err = ld->ld_errno;
+  signal_simple_error ("LDAP error",
+                       build_string (ldap_err2string (ld->ld_errno)));
 #endif
-    }
-  signal_simple_error ("LDAP error",
-                       build_string (ldap_err2string (ldap_err)));
 }
 
 
@@ -116,7 +111,7 @@
 
   write_c_string ("#<ldap ", printcharfun);
   print_internal (ldap->host, printcharfun, 1);
-  if (!ldap->ld)
+  if (!ldap->livep)
     write_c_string ("(dead) ",printcharfun);
   sprintf (buf, " 0x%x>", (unsigned int)ldap);
   write_c_string (buf, printcharfun);
@@ -130,6 +125,7 @@
 
   ldap->ld = NULL;
   ldap->host = Qnil;
+  ldap->livep = 0;
   return ldap;
 }
 
@@ -142,9 +138,8 @@
     signal_simple_error ("Can't dump an emacs containing LDAP objects",
 			 make_ldap (ldap));
 
-  if (ldap->ld)
+  if (ldap->livep)
     ldap_unbind (ldap->ld);
-  ldap->ld = NULL;
 }
 
 DEFINE_LRECORD_IMPLEMENTATION ("ldap", ldap,
@@ -181,7 +176,7 @@
        (ldap))
 {
   CHECK_LDAP (ldap);
-  return (XLDAP (ldap))->ld ? Qt : Qnil;
+  return (XLDAP (ldap))->livep ? Qt : Qnil;
 }
 
 /************************************************************************/
@@ -249,13 +244,15 @@
       else if (EQ (keyword, Qbinddn))
         {
           CHECK_STRING (value);
-          GET_C_STRING_OS_DATA_ALLOCA (value, ldap_binddn);
+          ldap_binddn = alloca (XSTRING_LENGTH (value) + 1);
+          strcpy (ldap_binddn, (char *)XSTRING_DATA (value));
         }
       /* Password */
       else if (EQ (keyword, Qpasswd))
         {
           CHECK_STRING (value);
-          GET_C_STRING_OS_DATA_ALLOCA (value, ldap_passwd);
+          ldap_passwd = alloca (XSTRING_LENGTH (value) + 1);
+          strcpy (ldap_passwd, (char *)XSTRING_DATA (value));
         }
       /* Deref */
       else if (EQ (keyword, Qderef))
@@ -291,10 +288,7 @@
     }
 
   /* Connect to the server and bind */
-  slow_down_interrupts ();
   ld = ldap_open ((char *)XSTRING_DATA (host), ldap_port);
-  speed_up_interrupts ();
-
   if (ld == NULL )
     signal_simple_error_2 ("Failed connecting to host",
                            host,
@@ -302,21 +296,16 @@
 
 
 #ifdef HAVE_LDAP_SET_OPTION
-  if ((err = ldap_set_option (ld, LDAP_OPT_DEREF,
-                              (void *)&ldap_deref)) != LDAP_SUCCESS)
-    signal_ldap_error (ld, NULL, err);
-  if ((err = ldap_set_option (ld, LDAP_OPT_TIMELIMIT,
-                              (void *)&ldap_timelimit)) != LDAP_SUCCESS)
-    signal_ldap_error (ld, NULL, err);
-  if ((err = ldap_set_option (ld, LDAP_OPT_SIZELIMIT,
-                              (void *)&ldap_sizelimit)) != LDAP_SUCCESS)
-    signal_ldap_error (ld, NULL, err);
-  if ((err = ldap_set_option (ld, LDAP_OPT_REFERRALS,
-                              LDAP_OPT_ON)) != LDAP_SUCCESS)
-    signal_ldap_error (ld, NULL, err);
-  if ((err = ldap_set_option (ld, LDAP_OPT_RESTART,
-                              LDAP_OPT_ON)) != LDAP_SUCCESS)
-    signal_ldap_error (ld, NULL, err);
+  if (ldap_set_option (ld, LDAP_OPT_DEREF, (void *)&ldap_deref) != LDAP_SUCCESS)
+    signal_ldap_error (ld);
+  if (ldap_set_option (ld, LDAP_OPT_TIMELIMIT,
+                       (void *)&ldap_timelimit) != LDAP_SUCCESS)
+    signal_ldap_error (ld);
+  if (ldap_set_option (ld, LDAP_OPT_SIZELIMIT,
+                       (void *)&ldap_sizelimit) != LDAP_SUCCESS)
+    signal_ldap_error (ld);
+  if (ldap_set_option (ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON) != LDAP_SUCCESS)
+    signal_ldap_error (ld);
 #else  /* not HAVE_LDAP_SET_OPTION */
   ld->ld_deref = ldap_deref;
   ld->ld_timelimit = ldap_timelimit;
@@ -326,11 +315,12 @@
 #else /* not LDAP_REFERRALS */
   ld->ld_options = 0;
 #endif /* not LDAP_REFERRALS */
-  /* XEmacs uses interrupts (SIGIO,SIGALRM), LDAP calls need to ignore them */
-  ld->ld_options |= LDAP_OPT_RESTART;
 #endif /* not HAVE_LDAP_SET_OPTION */
 
+  /* ldap_bind_s calls select and may be wedged by SIGIO.  */
+  slow_down_interrupts ();
   err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth);
+  speed_up_interrupts ();
   if (err != LDAP_SUCCESS)
     signal_simple_error ("Failed binding to the server",
                          build_string (ldap_err2string (err)));
@@ -338,6 +328,7 @@
   ldap = allocate_ldap ();
   ldap->ld = ld;
   ldap->host = host;
+  ldap->livep = 1;
 
   return make_ldap (ldap);
 }
@@ -353,7 +344,7 @@
   CHECK_LIVE_LDAP (ldap);
   lldap = XLDAP (ldap);
   ldap_unbind (lldap->ld);
-  lldap->ld = NULL;
+  lldap->livep = 0;
   return Qnil;
 }
 
@@ -365,9 +356,10 @@
 struct ldap_unwind_struct
 {
   LDAPMessage *res;
-  struct berval **vals;
+  char **vals;
 };
 
+
 static Lisp_Object
 ldap_search_unwind (Lisp_Object unwind_obj)
 {
@@ -376,7 +368,7 @@
   if (unwind->res)
     ldap_msgfree (unwind->res);
   if (unwind->vals)
-    ldap_value_free_len (unwind->vals);
+    ldap_value_free (unwind->vals);
   return Qnil;
 }
 
@@ -403,7 +395,7 @@
   LDAPMessage *e;
   BerElement *ptr;
   char *a;
-  int i, rc, rc2;
+  int i, rc;
   int  matches;
   struct ldap_unwind_struct unwind;
 
@@ -462,7 +454,11 @@
 	{
 	  Lisp_Object current = XCAR (attrs);
 	  CHECK_STRING (current);
-          GET_C_STRING_OS_DATA_ALLOCA (current, ldap_attributes[i]);
+	  ldap_attributes[i] =
+	    alloca_array (char, 1 + XSTRING_LENGTH (current));
+          /* XSTRING_LENGTH is increased by one in order to copy the final 0 */
+	  memcpy (ldap_attributes[i],
+		  XSTRING_DATA (current), 1 + XSTRING_LENGTH (current));
 	  ++i;
 	}
       ldap_attributes[i] = NULL;
@@ -478,9 +474,9 @@
                    NILP (filter) ? "" : (char *) XSTRING_DATA (filter),
                    ldap_attributes,
                    NILP (attrsonly) ? 0 : 1)
-      == -1)
+       == -1)
     {
-      signal_ldap_error (ld, NULL, 0);
+      signal_ldap_error (ld);
     }
 
   /* Ensure we don't exit without cleaning up */
@@ -490,8 +486,10 @@
   /* Build the results list */
   matches = 0;
 
+  /* ldap_result calls select() and can get wedged by EINTR signals */
+  slow_down_interrupts ();
   rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res);
-
+  speed_up_interrupts ();
   while (rc == LDAP_RES_SEARCH_ENTRY)
     {
       QUIT;
@@ -505,23 +503,21 @@
       entry = Qnil;
       for (a= ldap_first_attribute (ld, e, &ptr);
            a != NULL;
-           a = ldap_next_attribute (ld, e, ptr) )
+           a= ldap_next_attribute (ld, e, ptr) )
         {
           list = Fcons (build_ext_string (a, FORMAT_OS), Qnil);
-          unwind.vals = ldap_get_values_len (ld, e, a);
+          unwind.vals = ldap_get_values (ld, e, a);
           if (unwind.vals != NULL)
             {
               for (i = 0; unwind.vals[i] != NULL; i++)
                 {
-                  list = Fcons (make_ext_string (unwind.vals[i]->bv_val,
-                                                 unwind.vals[i]->bv_len,
-                                                 FORMAT_OS),
+                  list = Fcons (build_ext_string (unwind.vals[i], FORMAT_OS),
                                 list);
                 }
             }
           entry = Fcons (Fnreverse (list),
                          entry);
-          ldap_value_free_len (unwind.vals);
+          ldap_value_free (unwind.vals);
           unwind.vals = NULL;
         }
       result = Fcons (Fnreverse (entry),
@@ -529,33 +525,24 @@
       ldap_msgfree (unwind.res);
       unwind.res = NULL;
 
+      slow_down_interrupts ();
       rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res));
+      speed_up_interrupts ();
     }
 
-#if defined HAVE_LDAP_PARSE_RESULT
-  rc2 = ldap_parse_result (ld, unwind.res,
-                           &rc,
-                           NULL, NULL, NULL, NULL, 0);
-  if (rc2 != LDAP_SUCCESS)
-    rc = rc2;
-#else
-  if (rc == 0)
-    signal_ldap_error (ld, NULL, LDAP_TIMELIMIT_EXCEEDED);
-
   if (rc == -1)
-    signal_ldap_error (ld, unwind.res, (unwind.res==NULL) ? ld->ld_errno : 0);
-
-#if defined HAVE_LDAP_RESULT2ERROR
+    {
+      signal_ldap_error (ld);
+    }
   rc = ldap_result2error (ld, unwind.res, 0);
-#endif
-#endif
-
-  if (rc != LDAP_SUCCESS)
-    signal_ldap_error (ld, NULL, rc);
+  if ((rc != LDAP_SUCCESS) &&
+      (rc != LDAP_SIZELIMIT_EXCEEDED))
+    {
+      signal_ldap_error (ld);
+    }
 
   ldap_msgfree (unwind.res);
   unwind.res = (LDAPMessage *)NULL;
-
   /* #### See above for calling message().  */
   message ("Parsing ldap results... done");
 
@@ -580,6 +567,7 @@
 void
 vars_of_eldap (void)
 {
+  Fprovide (intern ("ldap"));
 
   ldap_default_port = LDAP_PORT;
   Vldap_default_base =  Qnil;