📄 udb.c
字号:
a->q_user,
hp->po_name,
hp->po_host);
break;
}
info.data = pobuf;
snprintf(pobuf, sizeof pobuf, "%s@%s",
hp->po_name, hp->po_host);
info.size = strlen(info.data);
# else /* HES_GETMAILHOST */
break;
# endif /* HES_GETMAILHOST */
}
if (tTd(28, 80))
dprintf("udbexpand: match %.*s: %.*s\n",
(int) key.size, (char *) key.data,
(int) info.size, (char *) info.data);
a->q_flags &= ~QSELFREF;
if (bitset(EF_VRFYONLY, e->e_flags))
{
a->q_state = QS_VERIFIED;
return EX_OK;
}
breakout = TRUE;
if (info.size >= usersize)
user = xalloc(info.size + 1);
memmove(user, info.data, info.size);
user[info.size] = '\0';
message("hesioded to %s", user);
if (LogLevel > 10)
sm_syslog(LOG_INFO, e->e_id,
"hesiod %.100s => %s",
e->e_to,
shortenstring(user, MAXSHORTSTR));
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
if (tTd(28, 5))
{
dprintf("udbexpand: QS_EXPANDED ");
printaddr(a, FALSE);
}
a->q_state = QS_EXPANDED;
}
/*
** If this address has a -request address, reflect
** it into the envelope.
*/
(void) strlcpy(keybuf, a->q_user, sizeof keybuf);
(void) strlcat(keybuf, ":mailsender", sizeof keybuf);
keylen = strlen(keybuf);
key.data = keybuf;
key.size = keylen;
i = hes_udb_get(&key, &info);
if (i != 0 || info.size <= 0)
break;
a->q_owner = xalloc(info.size + 1);
memmove(a->q_owner, info.data, info.size);
a->q_owner[info.size] = '\0';
break;
# endif /* HESIOD */
case UDB_REMOTE:
/* not yet implemented */
break;
case UDB_FORWARD:
if (bitset(EF_VRFYONLY, e->e_flags))
{
a->q_state = QS_VERIFIED;
return EX_OK;
}
i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
if (i >= usersize)
{
usersize = i + 1;
user = xalloc(usersize);
}
(void) snprintf(user, usersize, "%s@%s",
a->q_user, up->udb_fwdhost);
message("expanded to %s", user);
a->q_flags &= ~QSELFREF;
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
if (tTd(28, 5))
{
dprintf("udbexpand: QS_EXPANDED ");
printaddr(a, FALSE);
}
a->q_state = QS_EXPANDED;
}
breakout = TRUE;
break;
case UDB_EOLIST:
breakout = TRUE;
break;
default:
/* unknown entry type */
break;
}
if (user != userbuf)
free(user);
}
return EX_OK;
}
/*
** UDBSENDER -- return canonical external name of sender, given local name
**
** Parameters:
** sender -- the name of the sender on the local machine.
**
** Returns:
** The external name for this sender, if derivable from the
** database.
** NULL -- if nothing is changed from the database.
**
** Side Effects:
** none.
*/
char *
udbsender(sender)
char *sender;
{
return udbmatch(sender, "mailname");
}
/*
** UDBMATCH -- match user in field, return result of lookup.
**
** Parameters:
** user -- the name of the user.
** field -- the field to lookup.
**
** Returns:
** The external name for this sender, if derivable from the
** database.
** NULL -- if nothing is changed from the database.
**
** Side Effects:
** none.
*/
static char *
udbmatch(user, field)
char *user;
char *field;
{
register char *p;
register struct udbent *up;
int i;
int keylen;
DBT key, info;
char keybuf[MAXKEY];
if (tTd(28, 1))
dprintf("udbmatch(%s, %s)\n", user, field);
if (!UdbInitialized)
{
if (_udbx_init(CurEnv) == EX_TEMPFAIL)
return NULL;
}
/* short circuit if no spec */
if (UdbSpec == NULL || UdbSpec[0] == '\0')
return NULL;
/* short circuit name begins with '\\' since it can't possibly match */
if (user[0] == '\\')
return NULL;
/* long names can never match and are a pain to deal with */
i = strlen(field);
if (i < sizeof "maildrop")
i = sizeof "maildrop";
if ((strlen(user) + i) > sizeof keybuf - 4)
return NULL;
/* names beginning with colons indicate metadata */
if (user[0] == ':')
return NULL;
/* build database key */
(void) snprintf(keybuf, sizeof keybuf, "%s:%s", user, field);
keylen = strlen(keybuf);
for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
{
/*
** Select action based on entry type.
*/
switch (up->udb_type)
{
# ifdef NEWDB
case UDB_DBFETCH:
memset(&key, '\0', sizeof key);
memset(&info, '\0', sizeof info);
key.data = keybuf;
key.size = keylen;
# if DB_VERSION_MAJOR < 2
i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
# else /* DB_VERSION_MAJOR < 2 */
i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
&key, &info, 0);
# endif /* DB_VERSION_MAJOR < 2 */
if (i != 0 || info.size <= 0)
{
if (tTd(28, 2))
dprintf("udbmatch: no match on %s (%d) via db\n",
keybuf, keylen);
continue;
}
p = xalloc(info.size + 1);
memmove(p, info.data, info.size);
p[info.size] = '\0';
if (tTd(28, 1))
dprintf("udbmatch ==> %s\n", p);
return p;
# endif /* NEWDB */
# ifdef HESIOD
case UDB_HESIOD:
key.data = keybuf;
key.size = keylen;
i = hes_udb_get(&key, &info);
if (i != 0 || info.size <= 0)
{
if (tTd(28, 2))
dprintf("udbmatch: no match on %s (%d) via hesiod\n",
keybuf, keylen);
continue;
}
p = xalloc(info.size + 1);
memmove(p, info.data, info.size);
p[info.size] = '\0';
if (tTd(28, 1))
dprintf("udbmatch ==> %s\n", p);
return p;
# endif /* HESIOD */
}
}
if (strcmp(field, "mailname") != 0)
return NULL;
/*
** Nothing yet. Search again for a default case. But only
** use it if we also have a forward (:maildrop) pointer already
** in the database.
*/
/* build database key */
(void) strlcpy(keybuf, user, sizeof keybuf);
(void) strlcat(keybuf, ":maildrop", sizeof keybuf);
keylen = strlen(keybuf);
for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
{
switch (up->udb_type)
{
# ifdef NEWDB
case UDB_DBFETCH:
/* get the default case for this database */
if (up->udb_default == NULL)
{
memset(&key, '\0', sizeof key);
memset(&info, '\0', sizeof info);
key.data = ":default:mailname";
key.size = strlen(key.data);
# if DB_VERSION_MAJOR < 2
i = (*up->udb_dbp->get)(up->udb_dbp,
&key, &info, 0);
# else /* DB_VERSION_MAJOR < 2 */
i = errno = (*up->udb_dbp->get)(up->udb_dbp,
NULL, &key,
&info, 0);
# endif /* DB_VERSION_MAJOR < 2 */
if (i != 0 || info.size <= 0)
{
/* no default case */
up->udb_default = "";
continue;
}
/* save the default case */
up->udb_default = xalloc(info.size + 1);
memmove(up->udb_default, info.data, info.size);
up->udb_default[info.size] = '\0';
}
else if (up->udb_default[0] == '\0')
continue;
/* we have a default case -- verify user:maildrop */
memset(&key, '\0', sizeof key);
memset(&info, '\0', sizeof info);
key.data = keybuf;
key.size = keylen;
# if DB_VERSION_MAJOR < 2
i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
# else /* DB_VERSION_MAJOR < 2 */
i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
&key, &info, 0);
# endif /* DB_VERSION_MAJOR < 2 */
if (i != 0 || info.size <= 0)
{
/* nope -- no aliasing for this user */
continue;
}
/* they exist -- build the actual address */
i = strlen(user) + strlen(up->udb_default) + 2;
p = xalloc(i);
(void) snprintf(p, i, "%s@%s", user, up->udb_default);
if (tTd(28, 1))
dprintf("udbmatch ==> %s\n", p);
return p;
# endif /* NEWDB */
# ifdef HESIOD
case UDB_HESIOD:
/* get the default case for this database */
if (up->udb_default == NULL)
{
key.data = ":default:mailname";
key.size = strlen(key.data);
i = hes_udb_get(&key, &info);
if (i != 0 || info.size <= 0)
{
/* no default case */
up->udb_default = "";
continue;
}
/* save the default case */
up->udb_default = xalloc(info.size + 1);
memmove(up->udb_default, info.data, info.size);
up->udb_default[info.size] = '\0';
}
else if (up->udb_default[0] == '\0')
continue;
/* we have a default case -- verify user:maildrop */
key.data = keybuf;
key.size = keylen;
i = hes_udb_get(&key, &info);
if (i != 0 || info.size <= 0)
{
/* nope -- no aliasing for this user */
continue;
}
/* they exist -- build the actual address */
i = strlen(user) + strlen(up->udb_default) + 2;
p = xalloc(i);
(void) snprintf(p, i, "%s@%s", user, up->udb_default);
if (tTd(28, 1))
dprintf("udbmatch ==> %s\n", p);
return p;
break;
# endif /* HESIOD */
}
}
/* still nothing.... too bad */
return NULL;
}
/*
** UDB_MAP_LOOKUP -- look up arbitrary entry in user database map
**
** Parameters:
** map -- the map being queried.
** name -- the name to look up.
** av -- arguments to the map lookup.
** statp -- to get any error status.
**
** Returns:
** NULL if name not found in map.
** The rewritten name otherwise.
*/
/* ARGSUSED3 */
char *
udb_map_lookup(map, name, av, statp)
MAP *map;
char *name;
char **av;
int *statp;
{
char *val;
char *key;
char keybuf[MAXNAME + 1];
if (tTd(28, 20) || tTd(38, 20))
dprintf("udb_map_lookup(%s, %s)\n", map->map_mname, name);
if (bitset(MF_NOFOLDCASE, map->map_mflags))
{
key = name;
}
else
{
int keysize = strlen(name);
if (keysize > sizeof keybuf - 1)
keysize = sizeof keybuf - 1;
memmove(keybuf, name, keysize);
keybuf[keysize] = '\0';
makelower(keybuf);
key = keybuf;
}
val = udbmatch(key, map->map_file);
if (val == NULL)
return NULL;
if (bitset(MF_MATCHONLY, map->map_mflags))
return map_rewrite(map, name, strlen(name), NULL);
else
return map_rewrite(map, val, strlen(val), av);
}
/*
** _UDBX_INIT -- parse the UDB specification, opening any valid entries.
**
** Parameters:
** e -- the current envelope.
**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -