parseaddr.c
来自「< linux网络编程工具>>配套源码」· C语言 代码 · 共 2,770 行 · 第 1/5 页
C
2,770 行
{ "software", EX_SOFTWARE },
{ "tempfail", EX_TEMPFAIL },
{ "protocol", EX_PROTOCOL },
#ifdef EX_CONFIG
{ "config", EX_CONFIG },
#endif /* EX_CONFIG */
{ NULL, EX_UNAVAILABLE }
};
static ADDRESS *
buildaddr(tv, a, flags, e)
register char **tv;
register ADDRESS *a;
int flags;
register ENVELOPE *e;
{
struct mailer **mp;
register struct mailer *m;
register char *p;
char *mname;
char **hostp;
char hbuf[MAXNAME + 1];
static char ubuf[MAXNAME + 2];
if (tTd(24, 5))
{
dprintf("buildaddr, flags=%x, tv=", flags);
printav(tv);
}
if (a == NULL)
a = (ADDRESS *) xalloc(sizeof *a);
memset((char *) a, '\0', sizeof *a);
hbuf[0] = '\0';
/* set up default error return flags */
a->q_flags |= DefaultNotify;
/* figure out what net/mailer to use */
if (*tv == NULL || (**tv & 0377) != CANONNET)
{
syserr("554 5.3.5 buildaddr: no mailer in parsed address");
badaddr:
if (ExitStat == EX_TEMPFAIL)
a->q_state = QS_QUEUEUP;
else
{
a->q_state = QS_BADADDR;
a->q_mailer = &errormailer;
}
return a;
}
mname = *++tv;
/* extract host and user portions */
if (*++tv != NULL && (**tv & 0377) == CANONHOST)
hostp = ++tv;
else
hostp = NULL;
while (*tv != NULL && (**tv & 0377) != CANONUSER)
tv++;
if (*tv == NULL)
{
syserr("554 5.3.5 buildaddr: no user");
goto badaddr;
}
if (tv == hostp)
hostp = NULL;
else if (hostp != NULL)
cataddr(hostp, tv - 1, hbuf, sizeof hbuf, '\0');
cataddr(++tv, NULL, ubuf, sizeof ubuf, ' ');
/* save away the host name */
if (strcasecmp(mname, "error") == 0)
{
/* Set up triplet for use by -bv */
a->q_mailer = &errormailer;
a->q_user = newstr(ubuf);
if (hostp != NULL)
{
register struct errcodes *ep;
a->q_host = newstr(hbuf);
if (strchr(hbuf, '.') != NULL)
{
a->q_status = newstr(hbuf);
setstat(dsntoexitstat(hbuf));
}
else if (isascii(hbuf[0]) && isdigit(hbuf[0]))
{
setstat(atoi(hbuf));
}
else
{
for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
if (strcasecmp(ep->ec_name, hbuf) == 0)
break;
setstat(ep->ec_code);
}
}
else
{
a->q_host = NULL;
setstat(EX_UNAVAILABLE);
}
stripquotes(ubuf);
if (ISSMTPCODE(ubuf) && ubuf[3] == ' ')
{
char fmt[16];
int off;
if ((off = isenhsc(ubuf + 4, ' ')) > 0)
{
ubuf[off + 4] = '\0';
off += 5;
}
else
{
off = 4;
ubuf[3] = '\0';
}
(void) snprintf(fmt, sizeof fmt, "%s %%s", ubuf);
if (off > 4)
usrerr(fmt, ubuf + off);
else if (isenhsc(hbuf, '\0') > 0)
usrerrenh(hbuf, fmt, ubuf + off);
else
usrerr(fmt, ubuf + off);
/* XXX ubuf[off - 1] = ' '; */
}
else
{
usrerr("553 5.3.0 %s", ubuf);
}
goto badaddr;
}
for (mp = Mailer; (m = *mp++) != NULL; )
{
if (strcasecmp(m->m_name, mname) == 0)
break;
}
if (m == NULL)
{
syserr("554 5.3.5 buildaddr: unknown mailer %s", mname);
goto badaddr;
}
a->q_mailer = m;
/* figure out what host (if any) */
if (hostp == NULL)
{
if (!bitnset(M_LOCALMAILER, m->m_flags))
{
syserr("554 5.3.5 buildaddr: no host");
goto badaddr;
}
a->q_host = NULL;
}
else
a->q_host = newstr(hbuf);
/* figure out the user */
p = ubuf;
if (bitnset(M_CHECKUDB, m->m_flags) && *p == '@')
{
p++;
tv++;
a->q_flags |= QNOTREMOTE;
}
/* do special mapping for local mailer */
if (*p == '"')
p++;
if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags))
a->q_mailer = m = ProgMailer;
else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags))
a->q_mailer = m = FileMailer;
else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags))
{
/* may be :include: */
stripquotes(ubuf);
if (strncasecmp(ubuf, ":include:", 9) == 0)
{
/* if :include:, don't need further rewriting */
a->q_mailer = m = InclMailer;
a->q_user = newstr(&ubuf[9]);
return a;
}
}
/* rewrite according recipient mailer rewriting rules */
define('h', a->q_host, e);
#if _FFR_ADDR_TYPE
/*
** Note, change the 9 to a 10 before removing #if FFR check
** in a future version.
*/
if (ConfigLevel >= 9 ||
!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
#else /* _FFR_ADDR_TYPE */
if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
#endif /* _FFR_ADDR_TYPE */
{
/* sender addresses done later */
(void) rewrite(tv, 2, 0, e);
if (m->m_re_rwset > 0)
(void) rewrite(tv, m->m_re_rwset, 0, e);
}
(void) rewrite(tv, 4, 0, e);
/* save the result for the command line/RCPT argument */
cataddr(tv, NULL, ubuf, sizeof ubuf, '\0');
a->q_user = newstr(ubuf);
/*
** Do mapping to lower case as requested by mailer
*/
if (a->q_host != NULL && !bitnset(M_HST_UPPER, m->m_flags))
makelower(a->q_host);
if (!bitnset(M_USR_UPPER, m->m_flags))
makelower(a->q_user);
if (tTd(24, 6))
{
dprintf("buildaddr => ");
printaddr(a, FALSE);
}
return a;
}
/*
** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
**
** Parameters:
** pvp -- parameter vector to rebuild.
** evp -- last parameter to include. Can be NULL to
** use entire pvp.
** buf -- buffer to build the string into.
** sz -- size of buf.
** spacesub -- the space separator character; if null,
** use SpaceSub.
**
** Returns:
** none.
**
** Side Effects:
** Destroys buf.
*/
void
cataddr(pvp, evp, buf, sz, spacesub)
char **pvp;
char **evp;
char *buf;
register int sz;
int spacesub;
{
bool oatomtok = FALSE;
bool natomtok = FALSE;
register int i;
register char *p;
if (sz <= 0)
return;
if (spacesub == '\0')
spacesub = SpaceSub;
if (pvp == NULL)
{
*buf = '\0';
return;
}
p = buf;
sz -= 2;
while (*pvp != NULL && (i = strlen(*pvp)) < sz - 1)
{
natomtok = (TokTypeTab[**pvp & 0xff] == ATM);
if (oatomtok && natomtok)
{
*p++ = spacesub;
--sz;
}
(void) strlcpy(p, *pvp, sz);
oatomtok = natomtok;
p += i;
sz -= i;
if (pvp++ == evp)
break;
}
*p = '\0';
}
/*
** SAMEADDR -- Determine if two addresses are the same
**
** This is not just a straight comparison -- if the mailer doesn't
** care about the host we just ignore it, etc.
**
** Parameters:
** a, b -- pointers to the internal forms to compare.
**
** Returns:
** TRUE -- they represent the same mailbox.
** FALSE -- they don't.
**
** Side Effects:
** none.
*/
bool
sameaddr(a, b)
register ADDRESS *a;
register ADDRESS *b;
{
register ADDRESS *ca, *cb;
/* if they don't have the same mailer, forget it */
if (a->q_mailer != b->q_mailer)
return FALSE;
/* if the user isn't the same, we can drop out */
if (strcmp(a->q_user, b->q_user) != 0)
return FALSE;
/* if we have good uids for both but they differ, these are different */
if (a->q_mailer == ProgMailer)
{
ca = getctladdr(a);
cb = getctladdr(b);
if (ca != NULL && cb != NULL &&
bitset(QGOODUID, ca->q_flags & cb->q_flags) &&
ca->q_uid != cb->q_uid)
return FALSE;
}
/* otherwise compare hosts (but be careful for NULL ptrs) */
if (a->q_host == b->q_host)
{
/* probably both null pointers */
return TRUE;
}
if (a->q_host == NULL || b->q_host == NULL)
{
/* only one is a null pointer */
return FALSE;
}
if (strcmp(a->q_host, b->q_host) != 0)
return FALSE;
return TRUE;
}
/*
** PRINTADDR -- print address (for debugging)
**
** Parameters:
** a -- the address to print
** follow -- follow the q_next chain.
**
** Returns:
** none.
**
** Side Effects:
** none.
*/
struct qflags
{
char *qf_name;
u_long qf_bit;
};
static struct qflags AddressFlags[] =
{
{ "QGOODUID", QGOODUID },
{ "QPRIMARY", QPRIMARY },
{ "QNOTREMOTE", QNOTREMOTE },
{ "QSELFREF", QSELFREF },
{ "QBOGUSSHELL", QBOGUSSHELL },
{ "QUNSAFEADDR", QUNSAFEADDR },
{ "QPINGONSUCCESS", QPINGONSUCCESS },
{ "QPINGONFAILURE", QPINGONFAILURE },
{ "QPINGONDELAY", QPINGONDELAY },
{ "QHASNOTIFY", QHASNOTIFY },
{ "QRELAYED", QRELAYED },
{ "QEXPANDED", QEXPANDED },
{ "QDELIVERED", QDELIVERED },
{ "QDELAYED", QDELAYED },
{ "QTHISPASS", QTHISPASS },
{ "QRCPTOK", QRCPTOK },
{ NULL }
};
void
printaddr(a, follow)
register ADDRESS *a;
bool follow;
{
register MAILER *m;
MAILER pseudomailer;
register struct qflags *qfp;
bool firstone;
if (a == NULL)
{
printf("[NULL]\n");
return;
}
while (a != NULL)
{
printf("%lx=", (u_long) a);
(void) fflush(stdout);
/* find the mailer -- carefully */
m = a->q_mailer;
if (m == NULL)
{
m = &pseudomailer;
m->m_mno = -1;
m->m_name = "NULL";
}
printf("%s:\n\tmailer %d (%s), host `%s'\n",
a->q_paddr == NULL ? "<null>" : a->q_paddr,
m->m_mno, m->m_name,
a->q_host == NULL ? "<null>" : a->q_host);
printf("\tuser `%s', ruser `%s'\n",
a->q_user,
a->q_ruser == NULL ? "<null>" : a->q_ruser);
printf("\tstate=");
switch (a->q_state)
{
case QS_OK:
printf("OK");
break;
case QS_DONTSEND:
printf("DONTSEND");
break;
case QS_BADADDR:
printf("BADADDR");
break;
case QS_QUEUEUP:
printf("QUEUEUP");
break;
case QS_SENT:
printf("SENT");
break;
case QS_VERIFIED:
printf("VERIFIED");
break;
case QS_EXPANDED:
printf("EXPANDED");
break;
case QS_SENDER:
printf("SENDER");
break;
case QS_CLONED:
printf("CLONED");
break;
case QS_DISCARDED:
printf("DISCARDED");
break;
case QS_REPLACED:
printf("REPLACED");
break;
case QS_REMOVED:
printf("REMOVED");
break;
case QS_DUPLICATE:
printf("DUPLICATE");
break;
case QS_INCLUDED:
printf("INCLUDED");
break;
default:
printf("%d", a->q_state);
break;
}
printf(", next=%lx, alias %lx, uid %d, gid %d\n",
(u_long) a->q_next, (u_long) a->q_alias,
(int) a->q_uid, (int) a->q_gid);
printf("\tflags=%lx<", a->q_flags);
firstone = TRUE;
for (qfp = AddressFlags; qfp->qf_name != NULL; qfp++)
{
if (!bitset(qfp->qf_bit, a->q_flags))
continue;
if (!firstone)
printf(",");
firstone = FALSE;
printf("%s", qfp->qf_name);
}
printf(">\n");
printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n",
a->q_owner == NULL ? "(none)" : a->q_owner,
a->q_home == NULL ? "(none)" : a->q_home,
a->q_fullname == NULL ? "(none)" : a->q_fullname);
printf("\torcpt=\"%s\", statmta=%s, status=%s\n",
a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
a->q_statmta == NULL ? "(none)" : a->q_statmta,
a->q_status == NULL ? "(none)" : a->q_status);
printf("\trstatus=\"%s\"\n",
a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
printf("\tspecificity=%d, statdate=%s\n",
a->q_specificity,
a->q_statdate == 0 ? "(none)" : ctime(&a->q_statdate));
if (!follow)
return;
a = a->q_next;
}
}
/*
** EMPTYADDR -- return TRUE if this address is empty (``<>'')
**
** Parameters:
** a -- pointer to the address
**
** Returns:
** TRUE -- if this address is "empty" (i.e., no one should
** ever generate replies to it.
** FALSE -- if it is a "regular" (read: replyable) address.
*/
bool
emptyaddr(a)
register ADDRESS *a;
{
return a->q_paddr == NULL || strcmp(a->q_paddr, "<>") == 0 ||
a->q_user == NULL || strcmp(a->q_user, "<>") == 0;
}
/*
** REMOTENAME -- return the name relative to the current mailer
**
** Parameters:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?