/*
 * call-seq:
 * conn.search2(base_dn, scope, filter, attrs=nil, attrsonly=false,
 *              sec=0, usec=0, s_attr=nil, s_proc=nil)  => array
 * conn.search2(base_dn, scope, filter, attrs=nil, attrsonly=false,
 *              sec=0, usec=0, s_attr=nil, s_proc=nil) { |entry_as_hash| }  => self
 *
 * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
 * search filter of +filter+.
 *
 * If +attrs+ is present, it should be an array of the attributes that the
 * search should return. By default, all attributes are returned, which is the
 * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
 * single string, in which case it will be treated as a single element array.
 *
 * If +attrsonly+ is *true*, attributes will be returned, but not their values.
 *
 * If +sec+ and/or +usec+ are given, they define the time-out for the search in
 * seconds and microseconds, respectively.
 *
 * If +s_attr+ is given, it specifies the attribute on which to sort the
 * entries returned by the server. If +s_proc+ is given, it specifies a Proc
 * object that will be used to sort the entries returned by the server.
 *
 * Note that not all results may be returned by this method. If a
 * size limit has been set for the number of results to be returned and this
 * limit is exceeded, the results set will be truncated. You can check for
 * this by calling LDAP::Conn#err immediately after this method and comparing
 * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
 */
VALUE
rb_ldap_conn_search2_s (int argc, VALUE argv[], VALUE self)
{
  RB_LDAP_DATA *ldapdata;
  LDAPMessage *cmsg;
  LDAP *cldap;
  VALUE ary = Qnil;
  VALUE rc_ary = Qnil;

  rb_ldap_conn_search_i (argc, argv, self, &ldapdata, &cmsg);
  cldap = ldapdata->ldap;

  ary = rb_ary_new ();
  if (ldapdata->err == LDAP_SUCCESS
      || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
    {
      void *pass_data[] = { (void *) cldap, (void *) cmsg, (void *) ary };

      rc_ary = rb_ldap_parse_result (cldap, cmsg);
      rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary));
      rb_iv_set (self, "@controls", rb_ary_shift (rc_ary));

      rb_ensure (rb_ldap_conn_search2_b, (VALUE) pass_data,
                 rb_ldap_msgfree, (VALUE) cmsg);
    }

  if (rb_block_given_p ())
    {
      return self;
    }
  else
    {
      return ary;
    }
}