-/* $Cambridge: exim/src/src/route.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */
+/* $Cambridge: exim/src/src/route.c,v 1.14 2009/11/16 19:50:37 nm4 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions concerned with routing, and the list of generic router options. */
{
int rc;
uschar *check_local_part;
+unsigned int *localpart_cache;
/* Reset variables to hold a home directory and data from lookup of a domain or
local part, and ensure search_find_defer is unset, in case there aren't any
caseful local part, so that +caseful can restore it, even if this router is
handling local parts caselessly. However, we can't just pass cc_local_part,
because that doesn't have the prefix or suffix stripped. A bit of massaging is
-required. */
+required. Also, we only use the match cache for local parts that have not had
+a prefix or suffix stripped. */
if (addr->prefix == NULL && addr->suffix == NULL)
+ {
+ localpart_cache = addr->localpart_cache;
check_local_part = addr->cc_local_part;
+ }
else
{
+ localpart_cache = NULL;
check_local_part = string_copy(addr->cc_local_part);
if (addr->prefix != NULL)
check_local_part += Ustrlen(addr->prefix);
}
if ((rc = route_check_dls(r->name, US"local_parts", r->local_parts,
- &localpartlist_anchor, addr->localpart_cache, MCL_LOCALPART,
+ &localpartlist_anchor, localpart_cache, MCL_LOCALPART,
check_local_part, &deliver_localpart_data, !r->caseful_local_part,
perror)) != OK)
return rc;
BOOL
route_finduser(uschar *s, struct passwd **pw, uid_t *return_uid)
{
-if (Ustrcmp(lastname, s) != 0)
+BOOL cache_set = (Ustrcmp(lastname, s) == 0);
+
+DEBUG(D_uid) debug_printf("seeking password data for user \"%s\": %s\n", s,
+ cache_set? "using cached result" : "cache not available");
+
+if (!cache_set)
{
int i = 0;
else for (;;)
{
+ errno = 0;
if ((lastpw = getpwnam(CS s)) != NULL) break;
if (++i > finduser_retries) break;
sleep(1);
pwcopy.pw_shell = CS lastshell;
lastpw = &pwcopy;
}
+
+ else DEBUG(D_uid)
+ {
+ if (errno != 0) debug_printf("getpwnam(%s) failed: %s\n", s,
+ strerror(errno));
+ }
+ }
+
+if (lastpw == NULL)
+ {
+ DEBUG(D_uid) debug_printf("getpwnam() returned NULL (user not found)\n");
+ return FALSE;
}
else
{
- DEBUG(D_uid) debug_printf("finduser used cached passwd data for %s\n", s);
+ DEBUG(D_uid) debug_printf("getpwnam() succeeded uid=%d gid=%d\n",
+ lastpw->pw_uid, lastpw->pw_gid);
}
-if (lastpw == NULL) return FALSE;
-
if (return_uid != NULL) *return_uid = lastpw->pw_uid;
if (pw != NULL) *pw = lastpw;
HDEBUG(D_route) debug_printf("calling %s router\n", r->name);
- yield = (r->info->code)(r, addr, pw, verify != v_none, paddr_local,
- paddr_remote, addr_new, addr_succeed);
+ yield = (r->info->code)(r, addr, pw, verify, paddr_local, paddr_remote,
+ addr_new, addr_succeed);
if (yield == FAIL)
{
DEBUG(D_route) debug_printf("%s [%s] translated to %s\n",
h->name, h->address, newaddress);
- if (string_is_ip_address(newaddress, NULL))
+ if (string_is_ip_address(newaddress, NULL) != 0)
{
h->address = newaddress;
continue;
h->mx = MX_NONE;
store_pool = POOL_PERM;
- rc = host_find_byname(h, NULL, NULL, TRUE);
+ rc = host_find_byname(h, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, TRUE);
store_pool = old_pool;
if (rc == HOST_FIND_FAILED || rc == HOST_FIND_AGAIN)
&unseen);
if (yield != OK) goto ROUTE_EXIT;
-
-
/* Debugging output recording a successful routing */
HDEBUG(D_route)