Exemplo n.º 1
0
static void
recursive_alias_expand (const char *name, mu_list_t exlist, mu_list_t origlist)
{ 
  alias_t al;
  mu_iterator_t itr;
  
  if ((al = alias_lookup (name)) == NULL)
    {
      if (mu_list_locate (exlist, (void*)name, NULL) == MU_ERR_NOENT)
	mu_list_append (exlist, (void*)name);
      return;
    }
  
  mu_list_get_iterator (al->list, &itr);
  for (mu_iterator_first (itr);
       !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      char *word;
      
      mu_iterator_current (itr, (void **)&word);
      if (mu_list_locate (origlist, word, NULL) == MU_ERR_NOENT)
	{
	  mu_list_push (origlist, word);
	  recursive_alias_expand (word, exlist, origlist);
	  mu_list_pop (origlist, NULL);
	}
    }
  mu_iterator_destroy (&itr);
}
Exemplo n.º 2
0
int
mu_list_foreach_dir (mu_list_t list, int dir,
		     mu_list_action_t action, void *cbdata)
{
  mu_iterator_t itr;
  int status = 0;
  
  if (list == NULL || action == NULL)
    return EINVAL;
  status = mu_list_get_iterator (list, &itr);
  if (status)
    return status;

  status = mu_iterator_ctl (itr, mu_itrctl_set_direction, &dir);
  if (status == 0)
    for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
	 mu_iterator_next (itr))
      {
	void *item;
	mu_iterator_current (itr, &item);
	if ((status = action (item, cbdata)))
	  break;
      }
  mu_iterator_destroy (&itr);
  return status;
}
Exemplo n.º 3
0
static int
is_known_folder (mu_url_t url, mu_folder_t *pfolder)
{
  int ret = 0;
  mu_folder_t folder = NULL;
  mu_iterator_t iterator;

  if (url == NULL || pfolder == NULL)
    return ret;

  if (mu_list_get_iterator (known_folder_list, &iterator) != 0)
    return ret;

  for (mu_iterator_first (iterator); !mu_iterator_is_done (iterator);
       mu_iterator_next (iterator))
    {
      mu_iterator_current (iterator, (void **)&folder);
      /* Check if the same URL type.  */
      if (folder && folder->url
	  && mu_url_is_same_scheme (url, folder->url)
	  && mu_url_is_same_user (url, folder->url)
	  && mu_url_is_same_host (url, folder->url)
	  && mu_url_is_same_path (url, folder->url) 
	  && mu_url_is_same_port (url, folder->url))
	{
	  ret = 1;
	  break;
	}
    }
  if (ret)
    *pfolder = folder;
  mu_iterator_destroy (&iterator);
  return ret;
}
Exemplo n.º 4
0
void
mu_sieve_require (mu_list_t slist)
{
  int status;
  mu_iterator_t itr;
  
  status = mu_list_get_iterator (slist, &itr);
  if (status)
    {
      mu_sv_compile_error (&mu_sieve_locus,
			   _("cannot create iterator: %s"),
			   mu_strerror (status));
      return;
    }

  for (mu_iterator_first (itr);
       !mu_iterator_is_done (itr); mu_iterator_next (itr))
    {
      char *name;
      int (*reqfn) (mu_sieve_machine_t mach, const char *name) = NULL;
      const char *text = NULL;
      
      mu_iterator_current (itr, (void **)&name);

      if (strncmp (name, "comparator-", 11) == 0)
	{
	  name += 11;
	  reqfn = mu_sieve_require_comparator;
	  text = _("required comparator");
	}
      else if (strncmp (name, "test-", 5)  == 0) /* GNU extension */
	{
	  name += 5;
	  reqfn = mu_sieve_require_test;
	  text = _("required test");
	}
      else if (strcmp (name, "relational") == 0) /* RFC 3431 */
	{
	  reqfn = mu_sieve_require_relational;
	  text = "";
	}
      else
	{
	  reqfn = mu_sieve_require_action;
	  text = _("required action");
	}

      if (reqfn (mu_sieve_machine, name))
	{
	  mu_sv_compile_error (&mu_sieve_locus,
			       _("source for the %s %s is not available"),
			       text,
			       name);
	}
    }
  mu_iterator_destroy (&itr);
}
Exemplo n.º 5
0
/* FIXME: The checker interface should be redone. Until then this function
   is commented out.  Problems:

   1. Checkers are called per group, there's no way to call them per tag.
   2. See FIXMEs in the code.
*/
static int
index_checker (const char *name, mu_list_t tags, mu_list_t args)
{
  mu_iterator_t itr;
  mu_sieve_runtime_tag_t *match = NULL;
  int err;
  
  if (!tags || mu_list_get_iterator (tags, &itr))
    return 0;

  err = 0;
  for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      mu_sieve_runtime_tag_t *t;
      mu_iterator_current (itr, (void **)&t);
      
      if (strcmp (t->tag, "index") == 0)
	{
	  if (match)
	    {
	      /* FIXME: 1. This function must be public.
		        2. locus should be included in t
	      */
	      mu_sv_compile_error (&mu_sieve_locus, 
			      _("index specified twice in call to `%s'"),
				   name);
	      err = 1;
	      break;
	    }    
	}
    }

  mu_iterator_destroy (&itr);

  if (err)
    return 1;

  if (match)
    {
      if (match->arg->v.number < 1)
	{
	// See FIXME above 
	  mu_sv_compile_error (&mu_sieve_locus, 
			       _("invalid index value: %s"),
			       match->arg->v.string);
	  return 1;
	}
    }
  
  return 0;
}
Exemplo n.º 6
0
/* Computes an intersection of two lists and returns it in PDEST.
   The resulting list contains elements from A that are
   also encountered in B (as per comparison function of
   the latter).

   If DUP_ITEM is not NULL, it is used to create copies of
   items to be stored in PDEST.  In this case, the destroy_item
   function of B is also attached to PDEST.  Otherwise, if
   DUP_ITEM is NULL, pointers to elements are stored and
   no destroy_item function is assigned. */
int
mu_list_intersect_dup (mu_list_t *pdest, mu_list_t a, mu_list_t b,
		       int (*dup_item) (void **, void *, void *),
		       void *dup_closure)
{
  mu_list_t dest;
  int rc;
  mu_iterator_t itr;
  
  rc = mu_list_create (&dest);
  if (rc)
    return rc;

  mu_list_set_comparator (dest, b->comp);
  if (dup_item)
    mu_list_set_destroy_item (dest, b->destroy_item);
  
  rc = mu_list_get_iterator (a, &itr);
  if (rc)
    {
      mu_list_destroy (&dest);
      return rc;
    }

  rc = 0;
  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      void *data;
      mu_iterator_current (itr, &data);
      if (mu_list_locate (b, data, NULL) == 0)
	{
	  void *new_data;
	  if (dup_item && data)
	    {
	      rc = dup_item (&new_data, data, dup_closure);
	      if (rc)
		break;
	    }
	  else
	    new_data = data;
	
	  mu_list_append (dest, new_data); /* FIXME: Check return, and? */
	}
    }
  mu_iterator_destroy (&itr);
  *pdest = dest;
  return rc;
}
Exemplo n.º 7
0
static void
ali_print_name_list (mu_list_t list, int off)
{
  mu_iterator_t itr;
  char *item;
  
  mu_list_get_iterator (list, &itr);
  
  if (list_mode)
    {
      mu_iterator_first (itr);
      mu_iterator_current (itr, (void **)&item);
      printf ("%s\n", item);
      for (mu_iterator_next (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
	{
	  int len;
	  mu_iterator_current (itr, (void **)&item);
	  len = off + strlen (item);
	  printf ("%*.*s\n", len, len, item);
	}
    }
  else
    {
      int ncol = getcols ();
      int n = off;
      
      mu_iterator_first (itr);

      for (;;)
	{
	  int len;

	  mu_iterator_current (itr, (void **)&item);
	  len = strlen (item) + 2;
	  if (n + len > ncol)
	    n = printf ("\n ");

	  len = printf ("%s", item);
	  mu_iterator_next (itr);
	  if (!mu_iterator_is_done (itr))
	    len += printf (", ");
	  else
	    break;
	  n += len;
	}
      printf ("\n");
    }
  mu_iterator_destroy (&itr);
}
Exemplo n.º 8
0
int
mu_smtp_capa_iterator (mu_smtp_t smtp, mu_iterator_t *itr)
{
  if (!smtp || !itr)
    return EINVAL;
  if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
    return MU_ERR_FAILURE;
  if (!smtp->capa)
    {
      int rc = mu_smtp_ehlo (smtp);
      if (rc)
	return rc;
    }
  if (!MU_SMTP_FISSET (smtp, _MU_SMTP_ESMTP))
    return MU_ERR_FAILURE;
  return mu_list_get_iterator (smtp->capa, itr);
}
Exemplo n.º 9
0
int
mu_registrar_get_iterator (mu_iterator_t *pitr)
{
  int status = 0;
  if (pitr == NULL)
    return MU_ERR_OUT_PTR_NULL;
  mu_monitor_wrlock (&registrar_monitor);
  if (registrar_list == NULL)
    {
      status = mu_list_create (&registrar_list);
      if (status)
	return status;
    }
  status = mu_list_get_iterator (registrar_list, pitr);
  mu_monitor_unlock (&registrar_monitor);
  return status;
}
Exemplo n.º 10
0
sieve_comparator_record_t *
_lookup (mu_list_t list, const char *name)
{
  mu_iterator_t itr;
  sieve_comparator_record_t *reg;

  if (!list || mu_list_get_iterator (list, &itr))
    return NULL;

  for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
    {
      mu_iterator_current (itr, (void **)&reg);
      if (strcmp (reg->name, name) == 0)
	break;
      else
	reg = NULL;
    }
  mu_iterator_destroy (&itr);
  return reg;
}
Exemplo n.º 11
0
static int
sub_msgno_last (mu_msgset_t mset, size_t beg)
{
  int rc;
  struct mu_msgrange *range;

  if (beg == 1)
    mu_list_clear (mset->list);
  else
    {
      mu_iterator_t itr;
      
      rc = mu_list_get_iterator (mset->list, &itr);
      if (rc)
	return rc;
      rc = 1;
      rc = mu_iterator_ctl (itr, mu_itrctl_set_direction, &rc);
      if (rc)
	{
	  mu_iterator_destroy (&itr);
	  return rc;
	}
	  
      for (mu_iterator_first (itr); rc == 0 && !mu_iterator_is_done (itr);
	   mu_iterator_next (itr))
	{
	  mu_iterator_current (itr, (void **)&range);
	  if (range->msg_beg > beg)
	    rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	  else if (range->msg_beg == beg)
	    {
	      rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	      break;
	    }
	  else
	    break;
	}
      mu_iterator_destroy (&itr);
    }
  return 0;
}
Exemplo n.º 12
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);
}
Exemplo n.º 13
0
int
mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args)
{
  mu_iterator_t itr;
  mu_sieve_runtime_tag_t *match = NULL;
  mu_sieve_runtime_tag_t *comp = NULL;
  mu_sieve_runtime_tag_t *tmp;
  mu_sieve_comparator_t compfun = NULL;
  char *compname = "false";
  
  int matchtype;
  int err = 0;
  
  if (!tags || mu_list_get_iterator (tags, &itr))
    return 0;

  for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      mu_sieve_runtime_tag_t *t;
      mu_iterator_current (itr, (void **)&t);
      
      if (strcmp (t->tag, "is") == 0
	  || strcmp (t->tag, "contains") == 0
	  || strcmp (t->tag, "matches") == 0
	  || strcmp (t->tag, "regex") == 0
	  || strcmp (t->tag, "count") == 0
	  || strcmp (t->tag, "value") == 0)
	{
	  if (match)
	    {
	      mu_sv_compile_error (&mu_sieve_locus, 
			     _("match type specified twice in call to `%s'"),
				   name);
	      err = 1;
	    }
	  else
	    match = t;
	}
      else if (strcmp (t->tag, "comparator") == 0) 
	comp = t;
    }

  mu_iterator_destroy (&itr);

  if (err)
    return 1;

  if (!match || strcmp (match->tag, "is") == 0)
    matchtype = MU_SIEVE_MATCH_IS;
  else if (strcmp (match->tag, "contains") == 0)
    matchtype = MU_SIEVE_MATCH_CONTAINS;
  else if (strcmp (match->tag, "matches") == 0)
    matchtype = MU_SIEVE_MATCH_MATCHES;
  else if (strcmp (match->tag, "regex") == 0)
    matchtype = MU_SIEVE_MATCH_REGEX;
  else
    {
      char *str = match->arg->v.string;
      if (strcmp (match->tag, "count") == 0)
	{
	  mu_sieve_value_t *val;
	  char *str;
	  size_t count;
	  
	  if (comp && strcmp (comp->arg->v.string, "i;ascii-numeric"))
	    {
	      mu_sv_compile_error (&mu_sieve_locus, 
				   /* TRANSLATORS: Do not translate ':count'.
				      It is the name of a Sieve tag */
				   _("comparator %s is incompatible with "
				     ":count in call to `%s'"),
				   comp->arg->v.string,
				   name);
	      return 1;
	    }

          matchtype = MU_SIEVE_MATCH_LAST; /* to not leave it undefined */
	  compfun = comp_false;
	  val = mu_sieve_value_get (args, 1);
	  if (!val)
	    return 1; /* shouldn't happen */
	  /* NOTE: Type of v is always SVT_STRING_LIST */
	  mu_list_count (val->v.list, &count);
	  if (count > 1)
	    {
	      mu_sv_compile_error (&mu_sieve_locus, 
			_("second argument must be a list of one element"));
	      return 1;
	    }
	  mu_list_get (val->v.list, 0, (void **) &str);
	  count = strtoul (str, &str, 10);
	  if (*str)
	    {
	      mu_sv_compile_error (&mu_sieve_locus, 
			   _("second argument cannot be converted to number"));
	      return 1;
	    }
	}
      else
	matchtype = MU_SIEVE_MATCH_EQ;

      if (mu_sieve_str_to_relcmp (str, NULL, NULL))
	{
	  mu_sv_compile_error (&mu_sieve_locus, 
			       _("invalid relational match `%s' in call to `%s'"),
			       str, name);
	  return 1;
	}
    }

  if (!compfun)
    {
      compname = comp ? comp->arg->v.string : "i;ascii-casemap";
      compfun = mu_sieve_comparator_lookup (mu_sieve_machine, compname, 
                                            matchtype);
      if (!compfun)
	{
	  mu_sv_compile_error (&mu_sieve_locus, 
			   _("comparator `%s' is incompatible with match type `%s' in call to `%s'"),
			       compname, match ? match->tag : "is", name);
	  return 1;
	}
    }

  tmp = mu_sieve_malloc (mu_sieve_machine, sizeof (*tmp));
  tmp->tag = TAG_COMPFUN;
  tmp->arg = mu_sieve_value_create (SVT_POINTER, compfun);
  mu_list_append (tags, tmp);
  
  if (matchtype == MU_SIEVE_MATCH_REGEX)
    {
      /* To speed up things, compile all patterns at once.
	 Notice that it is supposed that patterns are in arg 2 */
      mu_sieve_value_t *val, *newval;
      struct regex_data rd;
      int rc;
      
      if (mu_list_get (args, 1, (void**)&val))
	return 0;

      rd.flags = REG_EXTENDED;
      if (strcmp (compname, "i;ascii-casemap") == 0)
	rd.flags |= REG_ICASE;

      mu_list_create (&rd.list);
      
      rc = mu_sieve_vlist_do (val, _regex_compile, &rd);

      mu_sieve_machine_add_destructor (mu_sieve_machine, _free_reglist, 
                                       rd.list);

      if (rc)
	return rc;
      newval = mu_sieve_value_create (SVT_STRING_LIST, rd.list);
      mu_list_replace (args, val, newval);
    }
#ifndef FNM_CASEFOLD
  else if (matchtype == MU_SIEVE_MATCH_MATCHES
	   && strcmp (compname, "i;ascii-casemap") == 0)
    {
      int rc;
      mu_sieve_value_t *val;

      if (mu_list_get (args, 1, (void**)&val))
	return 0;
      rc = mu_sieve_vlist_do (val, _pattern_upcase, NULL);
      if (rc)
	return rc;
    }
#endif
  return 0;
}
Exemplo n.º 14
0
int
mu_msgset_sub_range (mu_msgset_t mset, size_t beg, size_t end, int mode)
{
  int rc;
  mu_iterator_t itr;
  struct mu_msgrange *mr;

  if (!mset)
    return EINVAL;
  if (mu_list_is_empty (mset->list))
    return MU_ERR_NOENT;
  if (end && beg > end)
    {
      size_t t = end;
      end = beg;
      beg = t;
    }

  rc = _mu_msgset_translate_pair (mset, mode, &beg, &end);
  if (rc == MU_ERR_NOENT)
    return 0;
  else if (rc)
    return rc;
  
  rc = mu_msgset_aggregate (mset);
  if (rc)
    return rc;

  if (end == MU_MSGNO_LAST)
    return sub_msgno_last (mset, beg);
  
  /* Test border cases */
  rc = mu_list_head (mset->list, (void**)&mr);
  if (rc)
    return rc;
  if (end < mr->msg_beg)
    return 0;
  if (beg < mr->msg_beg)
    beg = mr->msg_beg;
  
  rc = mu_list_tail (mset->list, (void**) &mr);
  if (mr->msg_end != MU_MSGNO_LAST)
    {
      if (beg > mr->msg_end)
	return 0;
      if (end > mr->msg_end)
	end = mr->msg_end;
    }

  rc = mu_list_get_iterator (mset->list, &itr);
  if (rc)
    return rc;
  for (mu_iterator_first (itr); rc == 0 && !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      mu_iterator_current (itr, (void **)&mr);

      if (mr->msg_end == MU_MSGNO_LAST)
	{
	  /* This is the last element in list. */
	  if (mr->msg_beg == beg)
	    rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	  else if (mr->msg_beg > beg)
	    mr->msg_beg = end + 1;
	  break;
	}
      
      if (mr->msg_beg == beg && mr->msg_end == end) /* See case 2 above */
	{
	  rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	  break;
	}
      else if (mr->msg_beg <= beg && beg <= mr->msg_end) 
	{ 
	  if (mr->msg_beg <= end && end <= mr->msg_end) /* Case 3 */
	    {
	      /* Split the range */
	      if (end != mr->msg_end)
		{
		  struct mu_msgrange *newrange = calloc (1,
							 sizeof (*newrange));
		  if (!newrange)
		    {
		      rc = ENOMEM;
		      break;
		    }
		  newrange->msg_beg = end + 1;
		  newrange->msg_end = mr->msg_end;
		  rc = mu_iterator_ctl (itr, mu_itrctl_insert, newrange);
		  if (rc)
		    {
		      free (newrange);
		      break;
		    }
		}
	      
	      if (mr->msg_beg == beg)
		rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	      else
		mr->msg_end = beg - 1;
	      break;
	    }
	  else if (mr->msg_beg == beg)      /* Case 4 */
	    {
	      beg = mr->msg_end;
	      rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	    }
	  else
	    {
	      size_t n = mr->msg_end;
	      mr->msg_end = beg - 1;
	      beg = n;
	    }
	}
      else if (mr->msg_beg <= end && end <= mr->msg_end) /* Case 5 */
	{
	  mr->msg_beg = end + 1;
	  if (mr->msg_beg >= mr->msg_end)
	    rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	  break;
	}
      else if (beg <= mr->msg_beg && mr->msg_beg <= end)
	{
	  rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	}
    }
  mu_iterator_destroy (&itr);
  
  return rc;
}
Exemplo n.º 15
0
/* Switch to the given UID/GID */
int
mu_switch_to_privs (uid_t uid, gid_t gid, mu_list_t retain_groups)
{
  int rc = 0;
  gid_t *emptygidset;
  size_t size = 1, j = 1;
  mu_iterator_t itr;

  if (uid == 0)
    return 0;

  /* Create a list of supplementary groups */
  mu_list_count (retain_groups, &size);
  size++;
  emptygidset = xmalloc (size * sizeof emptygidset[0]);
  emptygidset[0] = gid ? gid : getegid ();

  if (mu_list_get_iterator (retain_groups, &itr) == 0)
    {
      for (mu_iterator_first (itr);
	   !mu_iterator_is_done (itr); mu_iterator_next (itr)) 
	mu_iterator_current (itr,
			     (void **)(emptygidset + j++));
      mu_iterator_destroy (&itr);
    }

  /* Reset group permissions */
  if (geteuid () == 0 && setgroups (j, emptygidset))
    {
      mu_error(_("setgroups(1, %lu) failed: %s"),
	       (unsigned long) emptygidset[0], mu_strerror (errno));
      rc = 1;
    }
  free (emptygidset);
	
  /* Switch to the user's gid. On some OSes the effective gid must
     be reset first */

#if defined(HAVE_SETEGID)
  if ((rc = setegid (gid)) < 0)
    mu_error (_("setegid(%lu) failed: %s"),
	      (unsigned long) gid, mu_strerror (errno));
#elif defined(HAVE_SETREGID)
  if ((rc = setregid (gid, gid)) < 0)
    mu_error (_("setregid(%lu,%lu) failed: %s"),
	      (unsigned long) gid, (unsigned long) gid,
	      mu_strerror (errno));
#elif defined(HAVE_SETRESGID)
  if ((rc = setresgid (gid, gid, gid)) < 0)
    mu_error (_("setresgid(%lu,%lu,%lu) failed: %s"),
	      (unsigned long) gid,
	      (unsigned long) gid,
	      (unsigned long) gid,
	      mu_strerror (errno));
#endif

  if (rc == 0 && gid != 0)
    {
      if ((rc = setgid (gid)) < 0 && getegid () != gid) 
	mu_error (_("setgid(%lu) failed: %s"),
		  (unsigned long) gid, mu_strerror (errno));
      if (rc == 0 && getegid () != gid)
	{
	  mu_error (_("Cannot set effective gid to %lu"),
		    (unsigned long) gid);
	  rc = 1;
	}
    }

  /* Now reset uid */
  if (rc == 0 && uid != 0)
    {
      uid_t euid;

      if (setuid (uid) || geteuid () != uid
	  || (getuid () != uid && (geteuid () == 0 || getuid () == 0)))
	{
#if defined(HAVE_SETREUID)
	  if (geteuid () != uid)
	    {
	      if (setreuid (uid, -1) < 0)
		{
		  mu_error (_("setreuid(%lu,-1) failed: %s"),
			    (unsigned long) uid,
			    mu_strerror (errno));
		  rc = 1;
		}
	      if (setuid (uid) < 0)
		{
		  mu_error (_("second setuid(%lu) failed: %s"),
			    (unsigned long) uid, mu_strerror (errno));
		  rc = 1;
		}
	    } else
#endif
	        {
		  mu_error (_("setuid(%lu) failed: %s"),
			    (unsigned long) uid,
			    mu_strerror (errno));
		  rc = 1;
		}
	}
	
      euid = geteuid ();
      if (uid != 0 && setuid (0) == 0)
	{
	  mu_error (_("seteuid(0) succeeded when it should not"));
	  rc = 1;
	}
      else if (uid != euid && setuid (euid) == 0)
	{
	  mu_error (_("Cannot drop non-root setuid privileges"));
	  rc = 1;
	}
    }
  return rc;
}