📄 parseaddr.c
字号:
}
dprintf("\n");
}
pp = m->match_first;
while (pp <= m->match_last)
{
if (avp >= &npvp[MAXATOM])
{
syserr("554 5.3.0 rewrite: expansion too long");
return EX_DATAERR;
}
*avp++ = *pp++;
}
}
else
{
/* some sort of replacement */
if (avp >= &npvp[MAXATOM])
{
toolong:
syserr("554 5.3.0 rewrite: expansion too long");
return EX_DATAERR;
}
if ((*rp & 0377) != MACRODEXPAND)
{
/* vanilla replacement */
*avp++ = rp;
}
else
{
/* $&x replacement */
char *mval = macvalue(rp[1], e);
char **xpvp;
int trsize = 0;
static size_t pvpb1_size = 0;
static char **pvpb1 = NULL;
char pvpbuf[PSBUFSIZE];
if (tTd(21, 2))
dprintf("rewrite: RHS $&%s => \"%s\"\n",
macname(rp[1]),
mval == NULL ? "(NULL)" : mval);
if (mval == NULL || *mval == '\0')
continue;
/* save the remainder of the input */
for (xpvp = pvp; *xpvp != NULL; xpvp++)
trsize += sizeof *xpvp;
if ((size_t) trsize > pvpb1_size)
{
if (pvpb1 != NULL)
free(pvpb1);
pvpb1 = (char **)xalloc(trsize);
pvpb1_size = trsize;
}
memmove((char *) pvpb1,
(char *) pvp,
trsize);
/* scan the new replacement */
xpvp = prescan(mval, '\0', pvpbuf,
sizeof pvpbuf, NULL,
NULL);
if (xpvp == NULL)
{
/* prescan pre-printed error */
return EX_DATAERR;
}
/* insert it into the output stream */
while (*xpvp != NULL)
{
if (tTd(21, 19))
dprintf(" ... %s\n",
*xpvp);
*avp++ = newstr(*xpvp);
if (avp >= &npvp[MAXATOM])
goto toolong;
xpvp++;
}
if (tTd(21, 19))
dprintf(" ... DONE\n");
/* restore the old trailing input */
memmove((char *) pvp,
(char *) pvpb1,
trsize);
}
}
}
*avp++ = NULL;
/*
** Check for any hostname/keyword lookups.
*/
for (rvp = npvp; *rvp != NULL; rvp++)
{
char **hbrvp;
char **xpvp;
int trsize;
char *replac;
int endtoken;
STAB *map;
char *mapname;
char **key_rvp;
char **arg_rvp;
char **default_rvp;
char cbuf[MAXNAME + 1];
char *pvpb1[MAXATOM + 1];
char *argvect[10];
char pvpbuf[PSBUFSIZE];
char *nullpvp[1];
if ((**rvp & 0377) != HOSTBEGIN &&
(**rvp & 0377) != LOOKUPBEGIN)
continue;
/*
** Got a hostname/keyword lookup.
**
** This could be optimized fairly easily.
*/
hbrvp = rvp;
if ((**rvp & 0377) == HOSTBEGIN)
{
endtoken = HOSTEND;
mapname = "host";
}
else
{
endtoken = LOOKUPEND;
mapname = *++rvp;
}
map = stab(mapname, ST_MAP, ST_FIND);
if (map == NULL)
syserr("554 5.3.0 rewrite: map %s not found", mapname);
/* extract the match part */
key_rvp = ++rvp;
default_rvp = NULL;
arg_rvp = argvect;
xpvp = NULL;
replac = pvpbuf;
while (*rvp != NULL && (**rvp & 0377) != endtoken)
{
int nodetype = **rvp & 0377;
if (nodetype != CANONHOST && nodetype != CANONUSER)
{
rvp++;
continue;
}
*rvp++ = NULL;
if (xpvp != NULL)
{
cataddr(xpvp, NULL, replac,
&pvpbuf[sizeof pvpbuf] - replac,
'\0');
*++arg_rvp = replac;
replac += strlen(replac) + 1;
xpvp = NULL;
}
switch (nodetype)
{
case CANONHOST:
xpvp = rvp;
break;
case CANONUSER:
default_rvp = rvp;
break;
}
}
if (*rvp != NULL)
*rvp++ = NULL;
if (xpvp != NULL)
{
cataddr(xpvp, NULL, replac,
&pvpbuf[sizeof pvpbuf] - replac,
'\0');
*++arg_rvp = replac;
}
*++arg_rvp = NULL;
/* save the remainder of the input string */
trsize = (int) (avp - rvp + 1) * sizeof *rvp;
memmove((char *) pvpb1, (char *) rvp, trsize);
/* look it up */
cataddr(key_rvp, NULL, cbuf, sizeof cbuf,
map == NULL ? '\0' : map->s_map.map_spacesub);
argvect[0] = cbuf;
replac = map_lookup(map, cbuf, argvect, &rstat, e);
/* if no replacement, use default */
if (replac == NULL && default_rvp != NULL)
{
/* create the default */
cataddr(default_rvp, NULL, cbuf, sizeof cbuf, '\0');
replac = cbuf;
}
if (replac == NULL)
{
xpvp = key_rvp;
}
else if (*replac == '\0')
{
/* null replacement */
nullpvp[0] = NULL;
xpvp = nullpvp;
}
else
{
/* scan the new replacement */
xpvp = prescan(replac, '\0', pvpbuf,
sizeof pvpbuf, NULL, NULL);
if (xpvp == NULL)
{
/* prescan already printed error */
return EX_DATAERR;
}
}
/* append it to the token list */
for (avp = hbrvp; *xpvp != NULL; xpvp++)
{
*avp++ = newstr(*xpvp);
if (avp >= &npvp[MAXATOM])
goto toolong;
}
/* restore the old trailing information */
rvp = avp - 1;
for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )
if (avp >= &npvp[MAXATOM])
goto toolong;
}
/*
** Check for subroutine calls.
*/
status = callsubr(npvp, reclevel, e);
if (rstat == EX_OK || status == EX_TEMPFAIL)
rstat = status;
/* copy vector back into original space. */
for (avp = npvp; *avp++ != NULL;)
continue;
memmove((char *) pvp, (char *) npvp,
(int) (avp - npvp) * sizeof *avp);
if (tTd(21, 4))
{
dprintf("rewritten as:");
printav(pvp);
}
}
if (OpMode == MD_TEST)
{
printf("%s%-16.16s returns:", prefix, rulename);
printav(pvp);
}
else if (tTd(21, 1))
{
dprintf("%s%-16.16s returns:", prefix, rulename);
printav(pvp);
}
return rstat;
}
/*
** CALLSUBR -- call subroutines in rewrite vector
**
** Parameters:
** pvp -- pointer to token vector.
** reclevel -- the current recursion level.
** e -- the current envelope.
**
** Returns:
** The status from the subroutine call.
**
** Side Effects:
** pvp is modified.
*/
static int
callsubr(pvp, reclevel, e)
char **pvp;
int reclevel;
ENVELOPE *e;
{
char **avp;
char **rvp;
register int i;
int subr;
int status;
int rstat = EX_OK;
char *tpvp[MAXATOM + 1];
for (avp = pvp; *avp != NULL; avp++)
{
if ((**avp & 0377) == CALLSUBR && avp[1] != NULL)
{
stripquotes(avp[1]);
subr = strtorwset(avp[1], NULL, ST_FIND);
if (subr < 0)
{
syserr("Unknown ruleset %s", avp[1]);
return EX_CONFIG;
}
if (tTd(21, 3))
dprintf("-----callsubr %s (%d)\n",
avp[1], subr);
/*
** Take care of possible inner calls first.
** use a full size temporary buffer to avoid
** overflows in rewrite, but strip off the
** subroutine call.
*/
for (i = 2; avp[i] != NULL; i++)
tpvp[i - 2] = avp[i];
tpvp[i - 2] = NULL;
status = callsubr(tpvp, reclevel, e);
if (rstat == EX_OK || status == EX_TEMPFAIL)
rstat = status;
/*
** Now we need to call the ruleset specified for
** the subroutine. we can do this with the
** temporary buffer that we set up earlier,
** since it has all the data we want to rewrite.
*/
status = rewrite(tpvp, subr, reclevel, e);
if (rstat == EX_OK || status == EX_TEMPFAIL)
rstat = status;
/*
** Find length of tpvp and current offset into
** pvp, if the total is greater than MAXATOM,
** then it would overflow the buffer if we copied
** it back in to pvp, in which case we throw a
** fit.
*/
for (rvp = tpvp; *rvp != NULL; rvp++)
continue;
if (((rvp - tpvp) + (avp - pvp)) > MAXATOM)
{
syserr("554 5.3.0 callsubr: expansion too long");
return EX_DATAERR;
}
/*
** Now we can copy the rewritten code over
** the initial subroutine call in the buffer.
*/
for (i = 0; tpvp[i] != NULL; i++)
avp[i] = tpvp[i];
avp[i] = NULL;
/*
** If we got this far, we've processed the left
** most subroutine, and recursively called ourselves
** to handle any other subroutines. We're done.
*/
break;
}
}
return rstat;
}
/*
** MAP_LOOKUP -- do lookup in map
**
** Parameters:
** map -- the map to use for the lookup.
** key -- the key to look up.
** argvect -- arguments to pass to the map lookup.
** pstat -- a pointer to an integer in which to store the
** status from the lookup.
** e -- the current envelope.
**
** Returns:
** The result of the lookup.
** NULL -- if there was no data for the given key.
*/
static char *
map_lookup(smap, key, argvect, pstat, e)
STAB *smap;
char key[];
char **argvect;
int *pstat;
ENVELOPE *e;
{
auto int status = EX_OK;
MAP *map;
char *replac;
if (smap == NULL)
return NULL;
map = &smap->s_map;
DYNOPENMAP(map);
if (e->e_sendmode == SM_DEFER &&
bitset(MF_DEFER, map->map_mflags))
{
/* don't do any map lookups */
if (tTd(60, 1))
dprintf("map_lookup(%s, %s) => DEFERRED\n",
smap->s_name, key);
*pstat = EX_TEMPFAIL;
return NULL;
}
if (!bitset(MF_KEEPQUOTES, map->map_mflags))
stripquotes(key);
if (tTd(60, 1))
{
dprintf("map_lookup(%s, %s", smap->s_name, key);
if (tTd(60, 5))
{
int i;
for (i = 0; argvect[i] != NULL; i++)
dprintf(", %%%d=%s", i, argvect[i]);
}
dprintf(") => ");
}
replac = (*map->map_class->map_lookup)(map, key, argvect, &status);
if (tTd(60, 1))
dprintf("%s (%d)\n",
replac != NULL ? replac : "NOT FOUND",
status);
/* should recover if status == EX_TEMPFAIL */
if (status == EX_TEMPFAIL && !bitset(MF_NODEFER, map->map_mflags))
{
*pstat = EX_TEMPFAIL;
if (tTd(60, 1))
dprintf("map_lookup(%s, %s) tempfail: errno=%d\n",
smap->s_name, key, errno);
if (e->e_message == NULL)
{
char mbuf[320];
snprintf(mbuf, sizeof mbuf,
"%.80s map: lookup (%s): deferred",
smap->s_name,
shortenstring(key, MAXSHORTSTR));
e->e_message = newstr(mbuf);
}
}
if (status == EX_TEMPFAIL && map->map_tapp != NULL)
{
size_t i = strlen(key) + strlen(map->map_tapp) + 1;
static char *rwbuf = NULL;
static size_t rwbuflen = 0;
if (i > rwbuflen)
{
if (rwbuf != NULL)
free(rwbuf);
rwbuflen = i;
rwbuf = (char *) xalloc(rwbuflen);
}
snprintf(rwbuf, rwbuflen, "%s%s", key, map->map_tapp);
if (tTd(60, 4))
dprintf("map_lookup tempfail: returning \"%s\"\n",
rwbuf);
return rwbuf;
}
return replac;
}
/*
** INITERRMAILERS -- initialize error and discard mailers
**
** Parameters:
** none.
**
** Returns:
** none.
**
** Side Effects:
** initializes error and discard mailers.
*/
static MAILER discardmailer;
static MAILER errormailer;
static char *discardargv[] = { "DISCARD", NULL };
static char *errorargv[] = { "ERROR", NULL };
void
initerrmailers()
{
if (discardmailer.m_name == NULL)
{
/* initialize the discard mailer */
discardmailer.m_name = "*discard*";
discardmailer.m_mailer = "DISCARD";
discardmailer.m_argv = discardargv;
}
if (errormailer.m_name == NULL)
{
/* initialize the bogus mailer */
errormailer.m_name = "*error*";
errormailer.m_mailer = "ERROR";
errormailer.m_argv = errorargv;
}
}
/*
** BUILDADDR -- build address from token vector.
**
** Parameters:
** tv -- token vector.
** a -- pointer to address descriptor to fill.
** If NULL, one will be allocated.
** flags -- info regarding whether this is a sender or
** a recipient.
** e -- the current envelope.
**
** Returns:
** NULL if there was an error.
** 'a' otherwise.
**
** Side Effects:
** fills in 'a'
*/
static struct errcodes
{
char *ec_name; /* name of error code */
int ec_code; /* numeric code */
} ErrorCodes[] =
{
{ "usage", EX_USAGE },
{ "nouser", EX_NOUSER },
{ "nohost", EX_NOHOST },
{ "unavailable", EX_UNAVAILABLE },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -