*/
#ifndef lint
-static char sccsid[] = "@(#)parseaddr.c 8.1 (Berkeley) 6/27/93";
+static char sccsid[] = "@(#)parseaddr.c 8.17 (Berkeley) 10/31/93";
#endif /* not lint */
# include "sendmail.h"
** addr -- the address to parse.
** a -- a pointer to the address descriptor buffer.
** If NULL, a header will be created.
-** copyf -- determines what shall be copied:
-** -1 -- don't copy anything. The printname
-** (q_paddr) is just addr, and the
-** user & host are allocated internally
-** to parse.
-** 0 -- copy out the parsed user & host, but
-** don't copy the printname.
-** +1 -- copy everything.
+** flags -- describe detail for parsing. See RF_ definitions
+** in sendmail.h.
** delim -- the character to terminate the address, passed
** to prescan.
** delimptr -- if non-NULL, set to the location of the
# define DELIMCHARS "()<>,;\r\n" /* default word delimiters */
ADDRESS *
-parseaddr(addr, a, copyf, delim, delimptr, e)
+parseaddr(addr, a, flags, delim, delimptr, e)
char *addr;
register ADDRESS *a;
- int copyf;
+ int flags;
int delim;
char **delimptr;
register ENVELOPE *e;
if (tTd(20, 1))
printf("\n--parseaddr(%s)\n", addr);
- if (invalidaddr(addr))
- {
- if (tTd(20, 1))
- printf("parseaddr-->bad address\n");
- return NULL;
- }
-
if (delimptr == NULL)
delimptr = &delimptrbuf;
return (NULL);
}
+ if (invalidaddr(addr, delim == '\0' ? NULL : *delimptr))
+ {
+ if (tTd(20, 1))
+ printf("parseaddr-->bad address\n");
+ return NULL;
+ }
+
+ /*
+ ** Save addr if we are going to have to.
+ **
+ ** We have to do this early because there is a chance that
+ ** the map lookups in the rewriting rules could clobber
+ ** static memory somewhere.
+ */
+
+ if (bitset(RF_COPYPADDR, flags) && addr != NULL)
+ {
+ char savec = **delimptr;
+
+ if (savec != '\0')
+ **delimptr = '\0';
+ addr = newstr(addr);
+ if (savec != '\0')
+ **delimptr = savec;
+ }
+
/*
** Apply rewriting rules.
** Ruleset 0 does basic parsing. It must resolve.
if (rewrite(pvp, 0, e) == EX_TEMPFAIL)
queueup = TRUE;
- /*
- ** See if we resolved to a real mailer.
- */
-
- if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
- {
- setstat(EX_USAGE);
- syserr("554 cannot resolve name");
- return (NULL);
- }
/*
** Build canonical address from pvp.
*/
- a = buildaddr(pvp, a, e);
- if (a == NULL)
- return (NULL);
+ a = buildaddr(pvp, a, flags, e);
/*
** Make local copies of the host & user and then
** transport them out.
*/
- allocaddr(a, copyf, addr, *delimptr);
+ allocaddr(a, flags, addr);
+ if (bitset(QBADADDR, a->q_flags))
+ return a;
/*
** If there was a parsing failure, mark it for queueing.
*/
bool
-invalidaddr(addr)
+invalidaddr(addr, delimptr)
register char *addr;
+ char *delimptr;
{
+ char savedelim;
+
+ if (delimptr != NULL)
+ {
+ savedelim = *delimptr;
+ if (savedelim != '\0')
+ *delimptr = '\0';
+ }
+#if 0
+ /* for testing.... */
+ if (strcmp(addr, "INvalidADDR") == 0)
+ {
+ usrerr("553 INvalid ADDRess");
+ goto addrfailure;
+ }
+#endif
for (; *addr != '\0'; addr++)
{
- if ((*addr & 0340) != 0200)
- continue;
- setstat(EX_USAGE);
- usrerr("553 Address contained invalid control characters");
- return TRUE;
+ if ((*addr & 0340) == 0200)
+ break;
+ }
+ if (*addr == '\0')
+ {
+ if (savedelim != '\0' && delimptr != NULL)
+ *delimptr = savedelim;
+ return FALSE;
}
- return FALSE;
+ setstat(EX_USAGE);
+ usrerr("553 Address contained invalid control characters");
+ addrfailure:
+ if (savedelim != '\0' && delimptr != NULL)
+ *delimptr = savedelim;
+ return TRUE;
}
\f/*
** ALLOCADDR -- do local allocations of address on demand.
**
** Parameters:
** a -- the address to reallocate.
-** copyf -- the copy flag (see parseaddr for description).
+** flags -- the copy flag (see RF_ definitions in sendmail.h
+** for a description).
** paddr -- the printname of the address.
-** delimptr -- a pointer to the address delimiter. Must be set.
**
** Returns:
** none.
** Copies portions of a into local buffers as requested.
*/
-allocaddr(a, copyf, paddr, delimptr)
+allocaddr(a, flags, paddr)
register ADDRESS *a;
- int copyf;
+ int flags;
char *paddr;
- char *delimptr;
{
if (tTd(24, 4))
- printf("allocaddr(copyf=%d, paddr=%s)\n", copyf, paddr);
-
- if (copyf > 0 && paddr != NULL)
- {
- char savec = *delimptr;
+ printf("allocaddr(flags=%o, paddr=%s)\n", flags, paddr);
- if (savec != '\0')
- *delimptr = '\0';
- a->q_paddr = newstr(paddr);
- if (savec != '\0')
- *delimptr = savec;
- }
- else
- a->q_paddr = paddr;
+ a->q_paddr = paddr;
if (a->q_user == NULL)
a->q_user = "";
if (a->q_host == NULL)
a->q_host = "";
- if (copyf >= 0)
+ if (bitset(RF_COPYPARSE, flags))
{
a->q_host = newstr(a->q_host);
if (a->q_user != a->q_paddr)
/* diagnose and patch up bad syntax */
if (state == QST)
{
- usrerr("553 Unbalanced '\"'");
+ usrerr("653 Unbalanced '\"'");
c = '"';
}
else if (cmntcnt > 0)
{
- usrerr("553 Unbalanced '('");
+ usrerr("653 Unbalanced '('");
c = ')';
}
else if (anglecnt > 0)
{
c = '>';
- usrerr("553 Unbalanced '<'");
+ usrerr("653 Unbalanced '<'");
}
else
break;
{
if (cmntcnt <= 0)
{
- usrerr("553 Unbalanced ')'");
- if (delimptr != NULL)
- *delimptr = p;
- CurEnv->e_to = saveto;
- return (NULL);
+ usrerr("653 Unbalanced ')'");
+ c = NOCHAR;
}
else
cmntcnt--;
{
if (anglecnt <= 0)
{
- usrerr("553 Unbalanced '>'");
- if (delimptr != NULL)
- *delimptr = p;
- CurEnv->e_to = saveto;
- return (NULL);
+ usrerr("653 Unbalanced '>'");
+ c = NOCHAR;
}
- anglecnt--;
+ else
+ anglecnt--;
}
else if (delim == ' ' && isascii(c) && isspace(c))
c = ' ';
register struct rewrite *rwr; /* pointer to current rewrite rule */
int ruleno; /* current rule number */
int rstat = EX_OK; /* return status */
+ int loopcount;
struct match mlist[MAXMATCH]; /* stores match on LHS */
char *npvp[MAXATOM+1]; /* temporary space for rebuild */
*/
ruleno = 1;
+ loopcount = 0;
for (rwr = RewriteRules[ruleset]; rwr != NULL; )
{
- int loopcount = 0;
-
if (tTd(21, 12))
{
printf("-----trying rule:");
printf("----- rule fails\n");
rwr = rwr->r_next;
ruleno++;
+ loopcount = 0;
continue;
}
rvp++;
rwr = rwr->r_next;
ruleno++;
+ loopcount = 0;
}
else if ((*rp & 0377) == CANONHOST)
{
char *pvpb1[MAXATOM + 1];
char *argvect[10];
char pvpbuf[PSBUFSIZE];
+ char *nullpvp[1];
if ((**rvp & 0377) != HOSTBEGIN &&
(**rvp & 0377) != LOOKUPBEGIN)
{
xpvp = key_rvp;
}
+ else if (*replac == '\0')
+ {
+ /* null replacement */
+ nullpvp[0] = NULL;
+ xpvp = nullpvp;
+ }
else
{
/* scan the new replacement */
** 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:
};
ADDRESS *
-buildaddr(tv, a, e)
+buildaddr(tv, a, flags, e)
register char **tv;
register ADDRESS *a;
+ int flags;
register ENVELOPE *e;
{
struct mailer **mp;
register struct mailer *m;
char *bp;
int spaceleft;
+ static MAILER errormailer;
+ static char *errorargv[] = { "ERROR", NULL };
static char buf[MAXNAME];
+ if (tTd(24, 5))
+ {
+ printf("buildaddr, flags=%o, tv=", flags);
+ printav(tv);
+ }
+
if (a == NULL)
a = (ADDRESS *) xalloc(sizeof *a);
bzero((char *) a, sizeof *a);
/* figure out what net/mailer to use */
- if ((**tv & 0377) != CANONNET)
+ if (*tv == NULL || (**tv & 0377) != CANONNET)
{
syserr("554 buildaddr: no net");
- return (NULL);
+badaddr:
+ a->q_flags |= QBADADDR;
+ a->q_mailer = &errormailer;
+ if (errormailer.m_name == NULL)
+ {
+ /* initialize the bogus mailer */
+ errormailer.m_name = "*error*";
+ errormailer.m_mailer = "ERROR";
+ errormailer.m_argv = errorargv;
+ }
+ return a;
}
tv++;
if (strcasecmp(*tv, "error") == 0)
syserr("554 buildaddr: error: no user");
cataddr(++tv, NULL, buf, sizeof buf, ' ');
stripquotes(buf);
- usrerr(buf);
- return (NULL);
+ if (isascii(buf[0]) && isdigit(buf[0]) &&
+ isascii(buf[1]) && isdigit(buf[1]) &&
+ isascii(buf[2]) && isdigit(buf[2]) &&
+ buf[3] == ' ')
+ {
+ char fmt[10];
+
+ strncpy(fmt, buf, 3);
+ strcpy(&fmt[3], " %s");
+ usrerr(fmt, buf + 4);
+ }
+ else
+ {
+ usrerr("%s", buf);
+ }
+ goto badaddr;
}
for (mp = Mailer; (m = *mp++) != NULL; )
if (m == NULL)
{
syserr("554 buildaddr: unknown mailer %s", *tv);
- return (NULL);
+ goto badaddr;
}
a->q_mailer = m;
if (!bitnset(M_LOCALMAILER, m->m_flags))
{
syserr("554 buildaddr: no host");
- return (NULL);
+ goto badaddr;
}
a->q_host = NULL;
}
if (*tv == NULL || (**tv & 0377) != CANONUSER)
{
syserr("554 buildaddr: no user");
- return (NULL);
+ goto badaddr;
}
tv++;
a->q_flags |= QNOTREMOTE;
}
- /* do cleanup of final address */
+ /* rewrite according recipient mailer rewriting rules */
+ define('h', a->q_host, e);
+ if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
+ {
+ /* sender addresses done later */
+ (void) rewrite(tv, 2, e);
+ if (m->m_re_rwset > 0)
+ (void) rewrite(tv, m->m_re_rwset, e);
+ }
(void) rewrite(tv, 4, e);
/* save the result for the command line/RCPT argument */
printf("%s:\n\tmailer %d (%s), host `%s', user `%s', ruser `%s'\n",
a->q_paddr, m->m_mno, m->m_name,
- a->q_host, a->q_user, a->q_ruser? a->q_ruser: "<null>");
+ a->q_host, a->q_user,
+ a->q_ruser ? a->q_ruser : "<null>");
printf("\tnext=%x, flags=%o, alias %x, uid %d, gid %d\n",
a->q_next, a->q_flags, a->q_alias, a->q_uid, a->q_gid);
printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n",
a->q_owner == NULL ? "(none)" : a->q_owner,
- a->q_home, a->q_fullname);
+ a->q_home == NULL ? "(none)" : a->q_home,
+ a->q_fullname == NULL ? "(none)" : a->q_fullname);
if (!follow)
return;
return;
/* if non-null, mailer destination specified -- has it changed? */
- a1 = buildaddr(pvp, NULL, e);
+ a1 = buildaddr(pvp, NULL, 0, e);
if (a1 == NULL || sameaddr(a, a1))
return;
printaddr(a, FALSE);
}
a1->q_alias = a;
- allocaddr(a1, 1, NULL, delimptr);
+ allocaddr(a1, RF_COPYALL, NULL);
(void) recipient(a1, sendq, e);
}
\f/*