/*
 * call-seq:
 * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE)
 *   => self
 * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE)
 *   { |conn| }  => nil
 *
 * Bind an LDAP connection, using the DN, +dn+, the credential, +password+,
 * and the bind method, +method+. If a block is given, +self+ is yielded to
 * the block.
 */
VALUE
rb_ldap_conn_bind_s (int argc, VALUE argv[], VALUE self)
{
  RB_LDAP_DATA *ldapdata;

  VALUE arg1, arg2, arg3;
  char *dn = NULL;
  char *passwd = NULL;
  int method = LDAP_AUTH_SIMPLE;

  Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
  if (!ldapdata->ldap)
    {
      if (rb_iv_get (self, "@args") != Qnil)
        {
          rb_ldap_conn_rebind (self);
          GET_LDAP_DATA (self, ldapdata);
        }
      else
        {
          rb_raise (rb_eLDAP_InvalidDataError,
                    "The LDAP handler has already unbound.");
        }
    }

  if (ldapdata->bind)
    {
      rb_raise (rb_eLDAP_Error, "already bound.");
    };
  switch (rb_scan_args (argc, argv, "03", &arg1, &arg2, &arg3))
    {
    case 0:
      break;
    case 1:
      dn = StringValueCStr (arg1);
      break;
    case 2:
      dn = StringValueCStr (arg1);
      passwd = StringValueCStr (arg2);
      break;
    case 3:
      dn = StringValueCStr (arg1);
      passwd = StringValueCStr (arg2);
      method = NUM2INT (arg3);
      break;
    default:
      rb_bug ("rb_ldap_conn_bind_s");
    }

  ldapdata->err = ldap_bind_s (ldapdata->ldap, dn, passwd, method);
  Check_LDAP_Result (ldapdata->err);
  ldapdata->bind = 1;

  if (rb_block_given_p ())
    {
      rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self);
      return Qnil;
    }
  else
    {
      return self;
    };
}