예제 #1
0
static int
set_strerr_flt ()
{
  mu_stream_t flt, trans[2];
  int rc;
  
  rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_GET, trans);
  if (rc == 0)
    {
      char sessidstr[10];
      char *argv[] = { "inline-comment", NULL, "-S", NULL };

      snprintf (sessidstr, sizeof sessidstr, "%08lx:", mu_session_id);
      argv[1] = sessidstr;
      rc = mu_filter_create_args (&flt, trans[0], "inline-comment", 3,
				  (const char **)argv,
				  MU_FILTER_ENCODE, MU_STREAM_WRITE);
      mu_stream_unref (trans[0]);
      if (rc == 0)
	{
	  mu_stream_set_buffer (flt, mu_buffer_line, 0);
	  trans[0] = flt;
	  trans[1] = NULL;
	  rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM,
				MU_IOCTL_OP_SET, trans);
	  mu_stream_unref (trans[0]);
	  if (rc)
	    mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM",
		      mu_stream_strerror (mu_strerr, rc));
	}
      else
	mu_error (_("cannot create log filter stream: %s"), mu_strerror (rc));
    }
  else
    {
      mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM",
		mu_stream_strerror (mu_strerr, rc));
    }
  return rc;
}
예제 #2
0
static int
msgset_prev (mu_mailbox_t mbox, size_t *pnum)
{
  size_t cur_n = 0;
  msgset_cur (mbox, &cur_n);
  if (cur_n < 1)
    {
      mu_error (_("no prev message"));
      exit (1);
    }
  *pnum = cur_n - 1;
  return 0;
}
예제 #3
0
파일: header.c 프로젝트: ssvlab/esbmc-gpu
int
docmd (int argc, char **argv)
{
  struct cmdtab *cmd = find_cmd (argv[0]);
  if (!cmd)
    {
      mu_error ("%u: unknown command %s", line_num, argv[0]);
      return 1;
    }
  else
    cmd->fun (argc, argv);
  return 0;
}
예제 #4
0
int
mail_unalias (int argc, char **argv)
{
  if (argc == 1)
    {
      /* TRANSLATORS: 'unalias' is a command name. Do not translate it! */
      mu_error (_("unalias requires at least one argument"));
      return 1;
    }
  while (--argc)
    alias_destroy (*++argv);
  return 0;
}
예제 #5
0
/* Display the contents of the given file on the terminal */
static void
display_file (const char *name)
{
  const char *pager = mh_global_profile_get ("moreproc", getenv ("PAGER"));

  if (pager)
    mh_spawnp (pager, name);
  else
    {
      mu_stream_t stream;
      int rc;
      size_t off = 0;
      size_t n;
      char buffer[512];
      
      rc = mu_file_stream_create (&stream, name, MU_STREAM_READ);
      if (rc)
	{
	  mu_error ("mu_file_stream_create: %s", mu_strerror (rc));
	  return;
	}
      rc = mu_stream_open (stream);
      if (rc)
	{
	  mu_error ("mu_stream_open: %s", mu_strerror (rc));
	  return;
	} 
      
      while (mu_stream_read (stream, buffer, sizeof buffer - 1, off, &n) == 0
	     && n != 0)
	{
	  buffer[n] = '\0';
	  printf ("%s", buffer);
	  off += n;
	}
      mu_stream_destroy (&stream, NULL);
    }
}      
예제 #6
0
int
imap4d_init_tls_server ()
{
  mu_stream_t tlsstream, stream[2];
  int rc;

  rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_GET, stream);
  if (rc)
    {
      mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM",
		mu_stream_strerror (iostream, rc));
      return 1;
    }
  
  rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0);
  if (rc)
    {
      mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"),
		      mu_stream_strerror (tlsstream, rc));
      return 1;
    }

  mu_stream_unref (stream[0]);
  mu_stream_unref (stream[1]);
  stream[0] = stream[1] = tlsstream;

  rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, stream);
  if (rc)
    {
      mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM",
		mu_stream_strerror (iostream, rc));
      imap4d_bye (ERR_STREAM_CREATE);
    }
  mu_stream_unref (stream[0]);
  mu_stream_unref (stream[1]);
  
  return 0;
}
예제 #7
0
static int
msgset_next (mu_mailbox_t mbox, size_t *pnum)
{
  size_t cur_n = 0, total = 0;
  msgset_cur (mbox, &cur_n);
  mu_mailbox_messages_count (mbox, &total);
  if (cur_n + 1 > total)
    {
      mu_error (_("no next message"));
      exit (1);
    }
  *pnum = cur_n + 1;
  return 0;
}
예제 #8
0
void
mu_imap_register_callback_function (mu_imap_t imap, int code,
				    mu_imap_callback_t callback,
				    void *data)
{
  if (code < 0 || code >= _MU_IMAP_CB_MAX)
    {
      mu_error ("%s:%d: ignoring unsupported callback code %d",
		__FILE__, __LINE__, code);
      return;
    }
  imap->callback[code].action = callback;
  imap->callback[code].data = data;
}
예제 #9
0
void
_mu_onexit_run (void)
{
  mu_iterator_t itr;
  int rc, status = 0;

  if (!onexit_list)
    return;
  rc = mu_list_get_iterator (onexit_list, &itr);
  if (rc)
    {
      mu_error (_("cannot create iterator, onexit aborted: %s"),
		mu_strerror (rc));
      mu_stream_destroy (&mu_strerr);
      _exit (127);
    }
  
  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      struct onexit_closure *cp;
      int rc = mu_iterator_current (itr, (void**)&cp);
      if (rc)
	{
	  status = 127;
	  mu_error (_("cannot obtain current item while traversing the"
		      " onexit action list: %s"), mu_strerror (rc));
	}
      else
	cp->function (cp->data);
      mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
    }
  mu_iterator_destroy (&itr);
  mu_list_destroy (&onexit_list);
  if (status)
    _exit (status);
}
예제 #10
0
static int
msgset_last (mu_mailbox_t mbox, size_t *pnum)
{
  int rc;
  size_t count = 0;

  rc = mu_mailbox_messages_count (mbox, &count);
  if (rc)
    {
      mu_error (_("cannot get last message: %s"), mu_strerror (rc));
      exit (1);
    }
  *pnum = count;
  return 0;
}
예제 #11
0
static void
send_address_add (mu_address_t *paddr, const char *value)
{
  mu_address_t addr = NULL;
  int rc;

  rc = mu_address_create (&addr, value);
  if (rc)
    {
      mu_error (_("%s: %s"), value, mu_strerror (rc));
      exit (1);
    }
  MU_ASSERT (mu_address_union (paddr, addr));
  mu_address_destroy (&addr);
}
예제 #12
0
파일: header.c 프로젝트: ssvlab/esbmc-gpu
void
cmd_remove (int argc, char **argv)
{
  char *fn;
  int num = 1;
  int status;
  
  if (check_args (argv[0], argc, 2, 3))
    return;
  fn = argv[1];
  if (argc == 3)
    num = atoi (argv[2]);
  status = mu_header_remove (header, fn, num);
  if (status)
    mu_error ("%u: %s: %s", line_num, argv[0], mu_strerror (status));
}
예제 #13
0
파일: sortm.c 프로젝트: ssvlab/esbmc-gpu
static void
addop (char *field, compfun comp)
{
  struct comp_op *op = xmalloc (sizeof (*op));
  
  if (!oplist)
    {
      if (mu_list_create (&oplist))
	{
	  mu_error (_("can't create operation list"));
	  exit (1);
	}
      mu_list_set_destroy_item (oplist, mu_list_free_item);
    }
  op->field = field;
  op->comp = comp;
  mu_list_append (oplist, op);
}
예제 #14
0
static int
_mh_prop_setval (struct _mu_property *prop, const char *key,
		 const char *val, int overwrite)
{
  struct mu_mh_prop *mhprop = prop->_prop_init_data;
  mu_header_t header = prop->_prop_data;
  if (!header)
    {
      int rc;
      if ((rc = mu_header_create (&header, NULL, 0)) != 0)
	{
	  mu_error (_("cannot create context %s: %s"),
		    mhprop->filename, mu_strerror (rc));
	  return 1;
	}
      prop->_prop_data = header;
    }
  return mu_header_set_value (header, key, val, overwrite);
}
예제 #15
0
void
ioloop (char *id, mu_stream_t in, mu_stream_t out)
{
  char *buf = NULL;
  size_t size = 0, n;
  int rc;
  
  while ((rc = mu_stream_getline (in, &buf, &size, &n)) == 0 && n > 0)
    {
      if (rc)
	{
	  mu_error("%s: read error: %s", id, mu_stream_strerror (in, rc));
	  exit (1);
	}
      MU_ASSERT (mu_stream_write (out, buf, n, NULL));
    }
  mu_stream_flush (out);
  if (verbose)
    fprintf (stderr, "%s exited\n", id);
}
예제 #16
0
파일: header.c 프로젝트: ssvlab/esbmc-gpu
void
cmd_print (int argc, char **argv)
{
  char *fn;
  int num = 1;
  int status;
  const char *str;
  
  if (check_args (argv[0], argc, 2, 3))
    return;
  fn = argv[1];
  if (argc == 3)
    num = atoi (argv[2]);

  status = mu_header_sget_value_n (header, fn, num, &str);
  if (status == 0)
    printf ("%s: %s\n", fn, str);
  else
    mu_error ("%u: %s", line_num, mu_strerror (status));
}
예제 #17
0
파일: ldap.c 프로젝트: Distrotech/mailutils
static int
chk_ssha (const char *db_pass, const char *pass)
{
  int rc;
  unsigned char sha1digest[20];
  unsigned char *d1;
  struct mu_sha1_ctx sha1context;
  mu_stream_t str = NULL, flt = NULL;
  size_t size;
  
  size = strlen (db_pass);
  mu_static_memory_stream_create (&str, db_pass, size);
  mu_filter_create (&flt, str, "base64", MU_FILTER_DECODE, MU_STREAM_READ);
  mu_stream_unref (str);

  d1 = malloc (size);
  if (!d1)
    {
      mu_stream_destroy (&flt);
      return ENOMEM;
    }
  
  mu_stream_read (flt, (char*) d1, size, &size);
  mu_stream_destroy (&flt);

  if (size <= 16)
    {
      mu_error ("malformed SSHA1 password: %s", db_pass);
      return MU_ERR_FAILURE;
    }
  
  mu_sha1_init_ctx (&sha1context);
  mu_sha1_process_bytes (pass, strlen (pass), &sha1context);
  mu_sha1_process_bytes (d1 + 20, size - 20, &sha1context);
  mu_sha1_finish_ctx (&sha1context, sha1digest);

  rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0 ?
                  0 : MU_ERR_AUTH_FAILURE;
  free (d1);
  return rc;
}
예제 #18
0
/* Preprocess a part of a complex message designation. Returns
   a pointer to the allocated memory containing expanded part of
   the designation. Pointer to the beginning of the not expanded
   part (in arg) is placed into *rest */
static char *
msgset_preproc_part (mu_mailbox_t mbox, char *arg, char **rest)
{
  struct msgset_keyword *p;
  char *cp;
  
  for (p = keywords; p->name; p++)
    if (strncmp (arg, p->name, strlen (p->name)) == 0)
      {
	int rc;
	size_t uid, num;
	mu_message_t msg;
	
	if (p->handler (mbox, &num))
	  msgset_abort (arg);
	rc = mu_mailbox_get_message (mbox, num, &msg);
	if (rc)
	  {
	    mu_error (_("cannot get message %lu: %s"),
		      (unsigned long) num, mu_strerror (rc));
	    exit (1);
	  }
	*rest = arg + strlen (p->name);
	mu_message_get_uid (msg, &uid);
	return xstrdup (mu_umaxtostr (0, uid));
      }
  cp = strchr (arg, '-');
  if (cp)
    {
      char *ret;

      *rest = cp;
      ret = xmalloc (cp - arg + 1);
      memcpy (ret, arg, cp - arg);
      ret[cp - arg] = 0;
      return ret;
    }

  *rest = arg + strlen (arg);
  return strdup (arg);
}
예제 #19
0
static handler_fp
func (struct action_tab *p, const char *name)
{
  int len;
  
  if (!name)
    return func (p, "help");

  len = strlen (name);
  for (; p->name; p++)
    {
      int min = strlen (p->name);
      if (min > len)
	min = len;
      if (strncmp (p->name, name, min) == 0)
	return p->fp;
    }

  mu_error (_("%s is unknown. Hit <CR> for help"), name);
  return NULL;
}
예제 #20
0
static int
_mh_prop_write_stream (mu_header_t header, struct mu_mh_prop *mhprop,
		       mu_stream_t stream)
{
  int rc;
  mu_stream_t instream;
  mu_off_t size;

  mu_header_get_streamref (header, &instream);
  rc = mu_stream_copy (stream, instream, 0, &size);
  if (rc)
    {
      mu_error (_("error writing to context file %s: %s"),
		mhprop->filename, mu_strerror (rc));
      return rc;
    }
  else
    rc = mu_stream_truncate (stream, size);
  mu_stream_destroy (&instream);
  return rc;
}
예제 #21
0
파일: sql.c 프로젝트: ssvlab/esbmc-gpu
static mu_sql_dispatch_t *
get_sql_entry (int type)
{
  init_disptab ();
  if (type == 0 && sql_disptab[0] == NULL)
    {
      int i;
      for (i = 1; i < sql_disptab_next; i++)
	if (sql_disptab[i])
	  {
	    sql_disptab[type] = sql_disptab[i];
	    break;
	  }
    }
  if (!sql_disptab[type])
    {
      mu_error (_("SQL dispatcher table empty"));
      abort ();
    }
  return sql_disptab[type];
}
예제 #22
0
int
print_envelope (msgset_t *mspec, mu_message_t msg, void *data)
{
  int status;
  mu_envelope_t env = NULL;
  const char *sender = NULL, *date = NULL;

  status = mu_message_get_envelope (msg, &env);
  if (status)
    {
      mu_error (_("%lu: Cannot get envelope"),
		(unsigned long) mspec->msg_part[0]);
    }
  else
    {
      mu_envelope_sget_sender (env, &sender);
      mu_envelope_sget_date (env, &date);
      if (data)
	mu_printf ("%s ", (char*) data);
      mu_printf ("%s %s", sender, date);
    }
  return 0;
}
예제 #23
0
static int
cb_tls_required (void *data, mu_config_value_t *val)
{
  int bv;
  
  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
    return 1;
  if (mu_cfg_parse_boolean (val->v.string, &bv))
    mu_error (_("Not a boolean value"));
  else if (bv)
    {
      tls_mode = tls_required;
      mu_diag_output (MU_DIAG_WARNING,
		      "the \"tls-required\" statement is deprecated, "
		      "use \"tls required\" instead");
    }
  else
    mu_diag_output (MU_DIAG_WARNING,
		    "the \"tls-required\" statement is deprecated, "
		    "use \"tls\" instead");

  return 0;
}
예제 #24
0
int
mail_eq (int argc, char **argv)
{
  msgset_t *list = NULL;
  size_t n;

  switch (argc)
    {
    case 1:
      n = get_cursor ();
      if (n == 0)
        mu_error (_("No applicable message"));
      else
        mu_printf ("%lu\n", (unsigned long) n);
      break;

    case 2:
      if (msgset_parse (argc, argv, MSG_NODELETED, &list) == 0)
	{
	  if (list->msg_part[0] <= total)
	    {
	      set_cursor (list->msg_part[0]);
	      mu_printf ("%lu\n",
				(unsigned long) list->msg_part[0]);
	    }
	  else
	    util_error_range (list->msg_part[0]);
	  msgset_free (list);
	}
      break;

    default:
      return 1;
    }
  
  return 0;
}
예제 #25
0
void
io_getline (char **pbuf, size_t *psize, size_t *pnbytes)
{
  size_t len;
  int rc = mu_stream_getline (iostream, pbuf, psize, &len);
  if (rc == 0)
    {
      char *s = *pbuf;

      if (len == 0)
        {
          imap4d_bye (ERR_NO_IFILE);
          /*FIXME rc = ECONNABORTED;*/
        }
      len = mu_rtrim_class (s, MU_CTYPE_ENDLN);
      if (pnbytes)
	*pnbytes = len;
    }
  else
    {
      mu_error (_("read error: %s"), mu_strerror (rc));
      imap4d_bye (ERR_NO_IFILE);
    }
}
예제 #26
0
파일: ldap.c 프로젝트: Distrotech/mailutils
/* FIXME: Duplicated in other modules */
static void
get_quota (mu_off_t *pquota, const char *str)
{
  char *p;
  mu_off_t quota = strtoul (str, &p, 10);
  switch (*p)
    {
    case 0:
      break;
	      
    case 'k':
    case 'K':
      quota *= 1024;
      break;
      
    case 'm':
    case 'M':
      quota *= 1024*1024;
      break;
	      
    default:
      mu_error (_("invalid value for quota: %s"), str);
    }
}
예제 #27
0
static void
update_list (mu_list_t *plist, const char *arg)
{
  size_t j;
  struct mu_wordsplit ws;
  mu_list_t list = *plist;
  
  if (!list)
    {
      MU_ASSERT (mu_list_create (&list));
      *plist = list;
    }

  ws.ws_delim = ",";
  if (mu_wordsplit (arg, &ws, MU_WRDSF_DEFFLAGS | MU_WRDSF_DELIM))
    {
      mu_error ("mu_wordsplit: %s", mu_wordsplit_strerror (&ws));
      exit (1);
    }
  for (j = 0; j < ws.ws_wordc; j++)
    MU_ASSERT (mu_list_append (list, ws.ws_wordv[j]));
  ws.ws_wordc = 0;
  mu_wordsplit_free (&ws);
}
예제 #28
0
static int
_mh_prop_fill (struct _mu_property *prop)
{
  struct mu_mh_prop *mhprop = prop->_prop_init_data;
  int rc;
  mu_stream_t stream;
  mu_header_t header;
  
  rc = mu_file_stream_create (&stream, mhprop->filename, MU_STREAM_READ);
  if (rc)
    {
      if ((rc = mu_header_create (&header, NULL, 0)) != 0)
	mu_error (_("cannot create context %s: %s"),
		  mhprop->filename, mu_strerror (rc));
    }
  else
    {
      rc = _mh_prop_read_stream (&header, stream);
      mu_stream_unref (stream);
    }
  if (rc == 0)
    prop->_prop_data = header;
  return rc;
}
예제 #29
0
파일: header.c 프로젝트: ssvlab/esbmc-gpu
int
main (int argc, char **argv)
{
  int c;
  char buf[512];
  char **prevv;
  int prevc = 0;
  
  interactive = isatty (0);
  while ((c = getopt (argc, argv, "f:h")) != EOF)
    {
      switch (c)
	{
	case 'f':
	  file = optarg;
	  break;

	case 'h':
	  printf ("usage: header [-f file]\n");
	  exit (0);

	default:
	  exit (1);
	}
    }

  if (file)
    {
      if (load_file (file))
	exit (1);
    }
  else
    {
      int status = mu_header_create (&header, NULL, 0, NULL);
      if (status)
	{
	  mu_error ("cannot create header: %s", mu_strerror (status));
	  exit (1);
	}
    }
  
  while (prompt(0), fgets(buf, sizeof buf, stdin))
    {
      int c;
      char **v;
      int status;

      line_num++;
      status = mu_argcv_get (buf, NULL, "#", &c, &v);
      if (status)
	{
	  mu_error ("%u: cannot parse: %s",
		   line_num, mu_strerror (status));
	  continue;
	}

      if (c == 0)
	{
	  if (prevc)
	    docmd (prevc, prevv);
	  else
	    mu_argcv_free (c, v);
	}
      else
	{
	  docmd (c, v);
	  mu_argcv_free (prevc, prevv);
	  prevc = c;
	  prevv = v;
	}
    }
  exit (0);
}
예제 #30
0
파일: ldap.c 프로젝트: Distrotech/mailutils
static int
_mu_conn_setup (LDAP **pld)
{
  int rc;
  LDAPURLDesc *ludlist, **ludp;
  char **urls = NULL;
  int nurls = 0;
  char *ldapuri = NULL;
  LDAP *ld = NULL;
  int protocol = LDAP_VERSION3; /* FIXME: must be configurable */
  
  if (ldap_param.debug)
    {
      if (ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &ldap_param.debug)
	  != LBER_OPT_SUCCESS )
	mu_error (_("cannot set LBER_OPT_DEBUG_LEVEL %d"), ldap_param.debug);

      if (ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_param.debug)
	  != LDAP_OPT_SUCCESS )
	mu_error (_("could not set LDAP_OPT_DEBUG_LEVEL %d"),
		  ldap_param.debug);
    }

  if (ldap_param.url)
    {
      rc = ldap_url_parse (ldap_param.url, &ludlist);
      if (rc != LDAP_URL_SUCCESS)
	{
	  mu_error (_("cannot parse LDAP URL(s)=%s (%d)"),
		    ldap_param.url, rc);
	  return 1;
	}
      
      for (ludp = &ludlist; *ludp; )
	{
	  LDAPURLDesc *lud = *ludp;
	  char **tmp;
	  
	  if (lud->lud_dn && lud->lud_dn[0]
	      && (lud->lud_host == NULL || lud->lud_host[0] == '\0'))
	    {
	      /* if no host but a DN is provided, try DNS SRV to gather the
		 host list */
	      char *domain = NULL, *hostlist = NULL;
	      size_t i;
	      struct mu_wordsplit ws;
	      
	      if (ldap_dn2domain (lud->lud_dn, &domain) || !domain)
		{
		  mu_error (_("DNS SRV: cannot convert DN=\"%s\" into a domain"),
			    lud->lud_dn );
		  goto dnssrv_free;
		}
	      
	      rc = ldap_domain2hostlist (domain, &hostlist);
	      if (rc)
		{
		  mu_error (_("DNS SRV: cannot convert domain=%s into a hostlist"),
			    domain);
		  goto dnssrv_free;
		}

	      if (mu_wordsplit (hostlist, &ws, MU_WRDSF_DEFFLAGS))
		{
		  mu_error (_("DNS SRV: could not parse hostlist=\"%s\": %s"),
			    hostlist, mu_wordsplit_strerror (&ws));
		  goto dnssrv_free;
		}
	      
	      tmp = realloc (urls, sizeof(char *) * (nurls + ws.ws_wordc + 1));
	      if (!tmp)
		{
		  mu_error ("DNS SRV %s", mu_strerror (errno));
		  goto dnssrv_free;
		}
	      
	      urls = tmp;
	      urls[nurls] = NULL;
	      
	      for (i = 0; i < ws.ws_wordc; i++)
		{
		  urls[nurls + i + 1] = NULL;
		  rc = mu_asprintf (&urls[nurls + i],
				    "%s://%s",
				    lud->lud_scheme, ws.ws_wordv[i]);
		  if (rc)
		    {
		      mu_error ("DNS SRV %s", mu_strerror (rc));
		      goto dnssrv_free;
		    }
		}
	      
	      nurls += i;
	      
	    dnssrv_free:
	      mu_wordsplit_free (&ws);
	      ber_memfree (hostlist);
	      ber_memfree (domain);
	    }
	  else
	    {
	      tmp = realloc (urls, sizeof(char *) * (nurls + 2));
	      if (!tmp)
		{
		  mu_error ("DNS SRV %s", mu_strerror (errno));
		  break;
		}
	      urls = tmp;
	      urls[nurls + 1] = NULL;
	      
	      urls[nurls] = ldap_url_desc2str (lud);
	      if (!urls[nurls])
		{
		  mu_error ("DNS SRV %s", mu_strerror (errno));
		  break;
		}
	      nurls++;
	    }
	  
	  *ludp = lud->lud_next;
	  
	  lud->lud_next = NULL;
	  ldap_free_urldesc (lud);
	}

      if (ludlist)
	{
	  ldap_free_urldesc (ludlist);
	  return 1;
	}
      else if (!urls)
	return 1;
      
      rc = mu_argcv_string (nurls, urls, &ldapuri);
      if (rc)
	{
	  mu_error ("%s", mu_strerror (rc));
	  return 1;
	}
      
      ber_memvfree ((void **)urls);
    }

  mu_diag_output (MU_DIAG_INFO,
		  "constructed LDAP URI: %s", ldapuri ? ldapuri : "<DEFAULT>");

  rc = ldap_initialize (&ld, ldapuri);
  if (rc != LDAP_SUCCESS)
    {
      mu_error (_("cannot create LDAP session handle for URI=%s (%d): %s"),
		ldapuri, rc, ldap_err2string (rc));

      free (ldapuri);
      return 1;
    }
  free (ldapuri);
  
  ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &protocol);

  if (ldap_param.tls)
    {
      rc = ldap_start_tls_s (ld, NULL, NULL);
      if (rc != LDAP_SUCCESS)
	{
	  char *msg = NULL;
	  ldap_get_option (ld,
			   LDAP_OPT_DIAGNOSTIC_MESSAGE,
			   (void*)&msg);
	  
	  mu_error (_("ldap_start_tls failed: %s"), ldap_err2string (rc));
	  mu_error (_("TLS diagnostics: %s"), msg);
	  ldap_memfree (msg);

	  ldap_unbind_ext (ld, NULL, NULL);
	  
	  return 1;
	}
    }

  /* FIXME: Timeouts, SASL, etc. */
  *pld = ld;
  return 0;
}