make default $#error number 553 instead of 501
[unix-history] / usr / src / usr.sbin / sendmail / src / parseaddr.c
index 1bbdbfe..040d075 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)parseaddr.c        8.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)parseaddr.c        8.30 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -84,13 +84,6 @@ parseaddr(addr, a, flags, delim, delimptr, e)
        if (tTd(20, 1))
                printf("\n--parseaddr(%s)\n", addr);
 
        if (tTd(20, 1))
                printf("\n--parseaddr(%s)\n", addr);
 
-       if (invalidaddr(addr))
-       {
-               if (tTd(20, 1))
-                       printf("parseaddr-->bad address\n");
-               return NULL;
-       }
-
        {
                extern char *DelimChar;         /* parseaddr.c */
                char savec;
        {
                extern char *DelimChar;         /* parseaddr.c */
                char savec;
@@ -110,7 +103,7 @@ parseaddr(addr, a, flags, delim, delimptr, e)
        if (delimptr == NULL)
                delimptr = &delimptrbuf;
 
        if (delimptr == NULL)
                delimptr = &delimptrbuf;
 
-       pvp = prescan(addr, delim, pvpbuf, delimptr);
+       pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr);
        if (pvp == NULL)
        {
                if (tTd(20, 1))
        if (pvp == NULL)
        {
                if (tTd(20, 1))
@@ -118,6 +111,13 @@ parseaddr(addr, a, flags, delim, delimptr, e)
                return (NULL);
        }
 
                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.
        **
        /*
        **  Save addr if we are going to have to.
        **
@@ -143,9 +143,9 @@ parseaddr(addr, a, flags, delim, delimptr, e)
        */
 
        queueup = FALSE;
        */
 
        queueup = FALSE;
-       if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+       if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
                queueup = TRUE;
                queueup = TRUE;
-       if (rewrite(pvp, 0, e) == EX_TEMPFAIL)
+       if (rewrite(pvp, 0, 0, e) == EX_TEMPFAIL)
                queueup = TRUE;
 
 
                queueup = TRUE;
 
 
@@ -204,18 +204,43 @@ parseaddr(addr, a, flags, delim, delimptr, e)
 */
 
 bool
 */
 
 bool
-invalidaddr(addr)
+invalidaddr(addr, delimptr)
        register char *addr;
        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++)
        {
        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;
        }
        }
-       return FALSE;
+       if (*addr == '\0')
+       {
+               if (savedelim != '\0' && delimptr != NULL)
+                       *delimptr = savedelim;
+               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.
 }
 \f/*
 **  ALLOCADDR -- do local allocations of address on demand.
@@ -322,6 +347,7 @@ invalidaddr(addr)
 **                     If '\t' then we are reading the .cf file.
 **             pvpbuf -- place to put the saved text -- note that
 **                     the pointers are static.
 **                     If '\t' then we are reading the .cf file.
 **             pvpbuf -- place to put the saved text -- note that
 **                     the pointers are static.
+**             pvpbsize -- size of pvpbuf.
 **             delimptr -- if non-NULL, set to the location of the
 **                     terminating delimiter.
 **
 **             delimptr -- if non-NULL, set to the location of the
 **                     terminating delimiter.
 **
@@ -355,10 +381,34 @@ static short StateTab[NSTATES][NSTATES] =
        /*ONE*/         OPR,    OPR,    OPR,    OPR,    OPR,
 };
 
        /*ONE*/         OPR,    OPR,    OPR,    OPR,    OPR,
 };
 
+/* token type table -- it gets modified with $o characters */
+static TokTypeTab[256] =
+{
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM,ATM,SPC,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
+       OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+       ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+};
+
+#define toktype(c)     ((int) TokTypeTab[(c) & 0xff])
+
+
 # define NOCHAR                -1      /* signal nothing in lookahead token */
 
 char **
 # define NOCHAR                -1      /* signal nothing in lookahead token */
 
 char **
-prescan(addr, delim, pvpbuf, delimptr)
+prescan(addr, delim, pvpbuf, pvpbsize, delimptr)
        char *addr;
        char delim;
        char pvpbuf[];
        char *addr;
        char delim;
        char pvpbuf[];
@@ -376,6 +426,22 @@ prescan(addr, delim, pvpbuf, delimptr)
        int newstate;
        char *saveto = CurEnv->e_to;
        static char *av[MAXATOM+1];
        int newstate;
        char *saveto = CurEnv->e_to;
        static char *av[MAXATOM+1];
+       static char firsttime = TRUE;
+
+       if (firsttime)
+       {
+               /* initialize the token type table */
+               char obuf[50];
+
+               firsttime = FALSE;
+               expand("\201o", obuf, &obuf[sizeof obuf - sizeof DELIMCHARS], CurEnv);
+               strcat(obuf, DELIMCHARS);
+               for (p = obuf; *p != '\0'; p++)
+               {
+                       if (TokTypeTab[*p & 0xff] == ATM)
+                               TokTypeTab[*p & 0xff] = OPR;
+               }
+       }
 
        /* make sure error messages don't have garbage on them */
        errno = 0;
 
        /* make sure error messages don't have garbage on them */
        errno = 0;
@@ -406,9 +472,10 @@ prescan(addr, delim, pvpbuf, delimptr)
                        if (c != NOCHAR && !bslashmode)
                        {
                                /* see if there is room */
                        if (c != NOCHAR && !bslashmode)
                        {
                                /* see if there is room */
-                               if (q >= &pvpbuf[PSBUFSIZE - 5])
+                               if (q >= &pvpbuf[pvpbsize - 5])
                                {
                                        usrerr("553 Address too long");
                                {
                                        usrerr("553 Address too long");
+       returnnull:
                                        if (delimptr != NULL)
                                                *delimptr = p;
                                        CurEnv->e_to = saveto;
                                        if (delimptr != NULL)
                                                *delimptr = p;
                                        CurEnv->e_to = saveto;
@@ -426,18 +493,18 @@ prescan(addr, delim, pvpbuf, delimptr)
                                /* diagnose and patch up bad syntax */
                                if (state == QST)
                                {
                                /* diagnose and patch up bad syntax */
                                if (state == QST)
                                {
-                                       usrerr("653 Unbalanced '\"' (fixed)");
+                                       usrerr("653 Unbalanced '\"'");
                                        c = '"';
                                }
                                else if (cmntcnt > 0)
                                {
                                        c = '"';
                                }
                                else if (cmntcnt > 0)
                                {
-                                       usrerr("653 Unbalanced '(' (fixed)");
+                                       usrerr("653 Unbalanced '('");
                                        c = ')';
                                }
                                else if (anglecnt > 0)
                                {
                                        c = '>';
                                        c = ')';
                                }
                                else if (anglecnt > 0)
                                {
                                        c = '>';
-                                       usrerr("653 Unbalanced '<' (fixed)");
+                                       usrerr("653 Unbalanced '<'");
                                }
                                else
                                        break;
                                }
                                else
                                        break;
@@ -487,7 +554,7 @@ prescan(addr, delim, pvpbuf, delimptr)
                        {
                                if (cmntcnt <= 0)
                                {
                        {
                                if (cmntcnt <= 0)
                                {
-                                       usrerr("653 Unbalanced ')' (fixed)");
+                                       usrerr("653 Unbalanced ')'");
                                        c = NOCHAR;
                                }
                                else
                                        c = NOCHAR;
                                }
                                else
@@ -501,7 +568,7 @@ prescan(addr, delim, pvpbuf, delimptr)
                        {
                                if (anglecnt <= 0)
                                {
                        {
                                if (anglecnt <= 0)
                                {
-                                       usrerr("653 Unbalanced '>' (fixed)");
+                                       usrerr("653 Unbalanced '>'");
                                        c = NOCHAR;
                                }
                                else
                                        c = NOCHAR;
                                }
                                else
@@ -554,10 +621,12 @@ prescan(addr, delim, pvpbuf, delimptr)
                        if (avp >= &av[MAXATOM])
                        {
                                syserr("553 prescan: too many tokens");
                        if (avp >= &av[MAXATOM])
                        {
                                syserr("553 prescan: too many tokens");
-                               if (delimptr != NULL)
-                                       *delimptr = p;
-                               CurEnv->e_to = saveto;
-                               return (NULL);
+                               goto returnnull;
+                       }
+                       if (q - tok > MAXNAME)
+                       {
+                               syserr("553 prescan: token too long");
+                               goto returnnull;
                        }
                        *avp++ = tok;
                }
                        }
                        *avp++ = tok;
                }
@@ -573,55 +642,12 @@ prescan(addr, delim, pvpbuf, delimptr)
        }
        CurEnv->e_to = saveto;
        if (av[0] == NULL)
        }
        CurEnv->e_to = saveto;
        if (av[0] == NULL)
-               return (NULL);
-       return (av);
-}
-\f/*
-**  TOKTYPE -- return token type
-**
-**     Parameters:
-**             c -- the character in question.
-**
-**     Returns:
-**             Its type.
-**
-**     Side Effects:
-**             none.
-*/
-
-static int
-toktype(c)
-       register int c;
-{
-       static char buf[50];
-       static bool firstime = TRUE;
-
-       if (firstime)
        {
        {
-               firstime = FALSE;
-               expand("\201o", buf, &buf[sizeof buf - 1], CurEnv);
-               (void) strcat(buf, DELIMCHARS);
+               if (tTd(22, 1))
+                       printf("prescan: null leading token\n");
+               return (NULL);
        }
        }
-       c &= 0377;
-       if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS)
-               return (ONE);
-       if (c == MACRODEXPAND)
-               return (ONE);
-#ifdef MACVALUE
-       if (c == MACVALUE)
-               return (ONE);
-#endif /* MACVALUE */
-       if (c == '"')
-               return (QST);
-       if ((c & 0340) == 0200)
-               return (OPR);
-       if (!isascii(c))
-               return (ATM);
-       if (isspace(c) || c == ')')
-               return (SPC);
-       if (strchr(buf, c) != NULL)
-               return (OPR);
-       return (ATM);
+       return (av);
 }
 \f/*
 **  REWRITE -- apply rewrite rules to token vector.
 }
 \f/*
 **  REWRITE -- apply rewrite rules to token vector.
@@ -648,6 +674,7 @@ toktype(c)
 **     Parameters:
 **             pvp -- pointer to token vector.
 **             ruleset -- the ruleset to use for rewriting.
 **     Parameters:
 **             pvp -- pointer to token vector.
 **             ruleset -- the ruleset to use for rewriting.
+**             reclevel -- recursion level (to catch loops).
 **             e -- the current envelope.
 **
 **     Returns:
 **             e -- the current envelope.
 **
 **     Returns:
@@ -675,8 +702,12 @@ struct match
 # define MAXMATCH      9       /* max params per rewrite */
 # define MAX_CONTROL ' '
 
 # define MAXMATCH      9       /* max params per rewrite */
 # define MAX_CONTROL ' '
 
+# ifndef MAXRULERECURSION
+#  define MAXRULERECURSION     50      /* max recursion depth */
+# endif
 static char control_opts[MAX_CONTROL];
 
 static char control_opts[MAX_CONTROL];
 
+
 int
 static char control_init_data[] = { 
        MATCHZANY,      OP_VARLEN,
 int
 static char control_init_data[] = { 
        MATCHZANY,      OP_VARLEN,
@@ -692,9 +723,10 @@ static char control_init_data[] = {
 static int nrw;
 
 void
 static int nrw;
 
 void
-rewrite(pvp, ruleset, e)
+rewrite(pvp, ruleset, reclevel, e)
        char **pvp;
        int ruleset;
        char **pvp;
        int ruleset;
+       int reclevel;
        register ENVELOPE *e;
 {
        nrw = 0;
        register ENVELOPE *e;
 {
        nrw = 0;
@@ -714,6 +746,7 @@ _rewrite(pvp, ruleset)
        register struct rewrite *rwr;   /* pointer to current rewrite rule */
        int ruleno;                     /* current rule number */
        int rstat = EX_OK;              /* return status */
        register struct rewrite *rwr;   /* pointer to current rewrite rule */
        int ruleno;                     /* current rule number */
        int rstat = EX_OK;              /* return status */
+       int loopcount;
        int subr;                       /* subroutine number if >= 0 */
        bool dolookup;                  /* do host aliasing */
        char *npvp[MAXATOM+1];          /* temporary space for rebuild */
        int subr;                       /* subroutine number if >= 0 */
        bool dolookup;                  /* do host aliasing */
        char *npvp[MAXATOM+1];          /* temporary space for rebuild */
@@ -734,6 +767,11 @@ _rewrite(pvp, ruleset)
                syserr("554 rewrite: illegal ruleset number %d", ruleset);
                return EX_CONFIG;
        }
                syserr("554 rewrite: illegal ruleset number %d", ruleset);
                return EX_CONFIG;
        }
+       if (reclevel++ > MAXRULERECURSION)
+       {
+               syserr("rewrite: infinite recursion, ruleset %d", ruleset);
+               return EX_CONFIG;
+       }
        if (pvp == NULL)
                return EX_USAGE;
 
        if (pvp == NULL)
                return EX_USAGE;
 
@@ -756,10 +794,9 @@ _rewrite(pvp, ruleset)
        */
 
        ruleno = 1;
        */
 
        ruleno = 1;
+       loopcount = 0;
        for (rwr = RewriteRules[ruleset]; rwr != NULL; )
        {
        for (rwr = RewriteRules[ruleset]; rwr != NULL; )
        {
-               int loopcount = 0;
-
                if (tTd(21, 12))
                {
                        printf("-----trying rule:");
                if (tTd(21, 12))
                {
                        printf("-----trying rule:");
@@ -1147,6 +1184,7 @@ backup:
                                printf("----- rule fails\n");
                        rwr = rwr->r_next;
                        ruleno++;
                                printf("----- rule fails\n");
                        rwr = rwr->r_next;
                        ruleno++;
+                       loopcount = 0;
                        nmatches = 0;
                        continue;
                }
                        nmatches = 0;
                        continue;
                }
@@ -1173,6 +1211,7 @@ backup:
                        rvp++;
                        rwr = rwr->r_next;
                        ruleno++;
                        rvp++;
                        rwr = rwr->r_next;
                        ruleno++;
+                       loopcount = 0;
                        nmatches = 0;
                }
                else if ((*rp & 0377) == CANONHOST)
                        nmatches = 0;
                }
                else if ((*rp & 0377) == CANONHOST)
@@ -1541,6 +1580,12 @@ buildaddr(tv, a, flags, e)
        static char *errorargv[] = { "ERROR", NULL };
        static char buf[MAXNAME];
 
        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);
        clear((char *) a, sizeof *a);
        if (a == NULL)
                a = (ADDRESS *) xalloc(sizeof *a);
        clear((char *) a, sizeof *a);
@@ -1581,6 +1626,8 @@ badaddr:
                        }
                        tv++;
                }
                        }
                        tv++;
                }
+               else
+                       setstat(EX_UNAVAILABLE);
                buf[0] = '\0';
                for (; (*tv != NULL) && (**tv != CANONUSER); tv++)
                {
                buf[0] = '\0';
                for (; (*tv != NULL) && (**tv != CANONUSER); tv++)
                {
@@ -1597,7 +1644,21 @@ badaddr:
                        syslog (LOG_DEBUG, "%s: Trace: $#ERROR $: %s",
                                CurEnv->e_id, buf);
 #endif /* LOG */
                        syslog (LOG_DEBUG, "%s: Trace: $#ERROR $: %s",
                                CurEnv->e_id, buf);
 #endif /* LOG */
-               usrerr("%s", buf);
+               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("553 %s", buf);
+               }
                goto badaddr;
        }
 
                goto badaddr;
        }
 
@@ -1672,7 +1733,7 @@ badaddr:
 
        if (m->m_r_rwset > 0)
                rewrite(tv, m->m_r_rwset);
 
        if (m->m_r_rwset > 0)
                rewrite(tv, m->m_r_rwset);
-       (void) rewrite(tv, 4, e);
+       (void) rewrite(tv, 4, 0, e);
 
        /* save the result for the command line/RCPT argument */
        cataddr(tv, NULL, buf, sizeof buf, '\0');
 
        /* save the result for the command line/RCPT argument */
        cataddr(tv, NULL, buf, sizeof buf, '\0');
@@ -1767,6 +1828,8 @@ sameaddr(a, b)
        register ADDRESS *a;
        register ADDRESS *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 they don't have the same mailer, forget it */
        if (a->q_mailer != b->q_mailer)
                return (FALSE);
@@ -1775,9 +1838,16 @@ sameaddr(a, b)
        if (strcasecmp(a->q_user, b->q_user))
                return (FALSE);
 
        if (strcasecmp(a->q_user, b->q_user))
                return (FALSE);
 
-       /* if we have good uids for both but the differ, these are different */
-       if (bitset(QGOODUID, a->q_flags & b->q_flags) && a->q_uid != b->q_uid)
-               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)
 
        /* otherwise compare hosts (but be careful for NULL ptrs) */
        if (a->q_host == b->q_host)
@@ -1921,10 +1991,10 @@ remotename(name, m, flags, pstat, e)
        **      domain will be appended.
        */
 
        **      domain will be appended.
        */
 
-       pvp = prescan(name, '\0', pvpbuf, NULL);
+       pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL);
        if (pvp == NULL)
                return (name);
        if (pvp == NULL)
                return (name);
-       if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+       if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
                *pstat = EX_TEMPFAIL;
        if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL)
        {
                *pstat = EX_TEMPFAIL;
        if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL)
        {
@@ -1941,7 +2011,7 @@ remotename(name, m, flags, pstat, e)
 
                        while ((*pxp++ = *qxq++) != NULL)
                                continue;
 
                        while ((*pxp++ = *qxq++) != NULL)
                                continue;
-                       if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+                       if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
                                *pstat = EX_TEMPFAIL;
                }
        }
                                *pstat = EX_TEMPFAIL;
                }
        }
@@ -1958,7 +2028,7 @@ remotename(name, m, flags, pstat, e)
        {
        if (rwset > 0)
        {
        {
        if (rwset > 0)
        {
-               if (rewrite(pvp, rwset, e) == EX_TEMPFAIL)
+               if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL)
                        *pstat = EX_TEMPFAIL;
        }
 
                        *pstat = EX_TEMPFAIL;
        }
 
@@ -1969,7 +2039,7 @@ remotename(name, m, flags, pstat, e)
        **      may be used as a default to the above rules.
        */
 
        **      may be used as a default to the above rules.
        */
 
-       if (rewrite(pvp, 4, e) == EX_TEMPFAIL)
+       if (rewrite(pvp, 4, 0, e) == EX_TEMPFAIL)
                *pstat = EX_TEMPFAIL;
 
        /*
                *pstat = EX_TEMPFAIL;
 
        /*
@@ -1978,7 +2048,13 @@ remotename(name, m, flags, pstat, e)
 
        cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
        define('g', lbuf, e);
 
        cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
        define('g', lbuf, e);
-       expand(fancy, buf, &buf[sizeof buf - 1], e);
+
+       /* need to make sure route-addrs have <angle brackets> */
+       if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
+               expand("<\201g>", buf, &buf[sizeof buf - 1], e);
+       else
+               expand(fancy, buf, &buf[sizeof buf - 1], e);
+
        define('g', oldg, e);
 
        if (tTd(12, 1))
        define('g', oldg, e);
 
        if (tTd(12, 1))
@@ -2082,11 +2158,11 @@ maplocaluser(a, sendq, e)
                printf("maplocaluser: ");
                printaddr(a, FALSE);
        }
                printf("maplocaluser: ");
                printaddr(a, FALSE);
        }
-       pvp = prescan(a->q_user, '\0', pvpbuf, &delimptr);
+       pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr);
        if (pvp == NULL)
                return;
 
        if (pvp == NULL)
                return;
 
-       (void) rewrite(pvp, 5, e);
+       (void) rewrite(pvp, 5, 0, e);
        if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
                return;
 
        if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
                return;