/*
- * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
#ifndef lint
-static char sccsid[] = "@(#)parseaddr.c 8.45 (Berkeley) %G%";
+static char sccsid[] = "@(#)parseaddr.c 8.73 (Berkeley) 6/19/95";
#endif /* not lint */
-#include "sendmail.h"
-
-#ifdef CC_WONT_PROMOTE
-static int toktype __P((char));
-#else /* !CC_WONT_PROMOTE */
-static int toktype __P((int)); /* char -> int */
-#endif /* CC_WONT_PROMOTE */
-static void _rewrite __P((char **, int));
-static void callsubr __P((char **));
-static ADDRESS * buildaddr __P((char **, ADDRESS *));
-static void uurelativize __P((const char *, const char *, char **));
-
-char *DelimChar; /* set to point to the delimiter */
+# include "sendmail.h"
/*
** PARSEADDR -- Parse an address
auto char *delimptrbuf;
bool queueup;
char pvpbuf[PSBUFSIZE];
+ extern ADDRESS *buildaddr();
+ extern bool invalidaddr();
+ extern void allocaddr __P((ADDRESS *, int, char *));
/*
** Initialize and prescan address.
if (tTd(20, 1))
printf("\n--parseaddr(%s)\n", addr);
- {
- extern char *DelimChar; /* parseaddr.c */
- char savec;
- bool invalid;
- extern char *finddelim();
- extern bool invalidaddr();
-
- DelimChar = finddelim(addr, delim);
- savec = *DelimChar;
- *DelimChar = '\0';
- invalid = invalidaddr(addr);
- *DelimChar = savec;
- if (invalid)
- return (NULL);
- }
-
if (delimptr == NULL)
delimptr = &delimptrbuf;
- pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr);
+ pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL);
if (pvp == NULL)
{
if (tTd(20, 1))
if (e->e_message == NULL)
e->e_message = newstr(msg);
a->q_flags |= QQUEUEUP;
+ a->q_status = "4.4.3";
}
/*
register char *addr;
char *delimptr;
{
- char savedelim;
+ char savedelim = '\0';
if (delimptr != NULL)
{
}
if (*addr == '\0')
{
- if (savedelim != '\0' && delimptr != NULL)
+ if (delimptr != NULL && savedelim != '\0')
*delimptr = savedelim;
return FALSE;
}
setstat(EX_USAGE);
usrerr("553 Address contained invalid control characters");
addrfailure:
- if (savedelim != '\0' && delimptr != NULL)
+ if (delimptr != NULL && savedelim != '\0')
*delimptr = savedelim;
return TRUE;
}
** Copies portions of a into local buffers as requested.
*/
+void
allocaddr(a, flags, paddr)
register ADDRESS *a;
int flags;
a->q_paddr = a->q_user;
}
\f/*
-** INVALIDADDR -- check an address string for invalid control characters.
-**
-** Parameters:
-** addr -- address string to be checked.
-**
-** Returns:
-** TRUE if address string could cause problems, FALSE o/w.
-**
-** Side Effects:
-** ExitStat may be changed and an error message generated.
-*/
-
-bool
-invalidaddr(addr)
- const char *addr;
-{
- register const char *cp;
-
- /* make sure error messages don't have garbage on them */
- errno = 0;
-
- /*
- ** Sendmail reserves characters 020 - 036 for rewriting rules
- ** which can cause havoc (e.g. infinite rewriting loops) if
- ** one shows up at the wrong time. If any of these characters
- ** appear in an address, the address is deemed "invalid" and
- ** an error message is generated.
- */
-
- for (cp = addr; *cp; cp++)
- if ((*cp >= MATCHZANY && *cp <= HOSTEND) || *cp == '\001')
- {
- setstat(EX_USAGE);
- usrerr("address contained invalid control char(s)");
- return (TRUE);
- }
- return (FALSE);
-}
-\f/*
** PRESCAN -- Prescan name and make it canonical
**
** Scans a name and turns it into a set of tokens. This process
** pvpbsize -- size of pvpbuf.
** delimptr -- if non-NULL, set to the location of the
** terminating delimiter.
+** toktab -- if set, a token table to use for parsing.
+** If NULL, use the default table.
**
** Returns:
** A pointer to a vector of tokens.
# define QST 2 /* in quoted string */
# define SPC 3 /* chewing up spaces */
# define ONE 4 /* pick up one character */
+# define ILL 5 /* illegal character */
-# define NSTATES 5 /* number of states */
+# define NSTATES 6 /* number of states */
# define TYPE 017 /* mask to select state type */
/* meta bits for table */
static short StateTab[NSTATES][NSTATES] =
{
- /* oldst chtype> OPR ATM QST SPC ONE */
- /*OPR*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B,
- /*ATM*/ OPR|B, ATM, QST|B, SPC|MB, ONE|B,
- /*QST*/ QST, QST, OPR, QST, QST,
- /*SPC*/ OPR, ATM, QST, SPC|M, ONE,
- /*ONE*/ OPR, OPR, OPR, OPR, OPR,
+ /* oldst chtype> OPR ATM QST SPC ONE ILL */
+ /*OPR*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|MB,
+ /*ATM*/ OPR|B, ATM, QST|B, SPC|MB, ONE|B, ILL|MB,
+ /*QST*/ QST, QST, OPR, QST, QST, QST,
+ /*SPC*/ OPR, ATM, QST, SPC|M, ONE, ILL|MB,
+ /*ONE*/ OPR, OPR, OPR, OPR, OPR, ILL|MB,
+ /*ILL*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|M,
};
/* token type table -- it gets modified with $o characters */
-static TokTypeTab[256] =
+static u_char 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,
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, ATM,SPC,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* @ A B C D E F G H I J K L M N O */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* ` a b c d e f g h i j k l m n o */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* p q r s t u v w x y z { | } ~ del */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* @ A B C D E F G H I J K L M N O */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* ` a b c d e f g h i j k l m n o */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* p q r s t u v w x y z { | } ~ del */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
};
-#define toktype(c) ((int) TokTypeTab[(c) & 0xff])
+/* token type table for MIME parsing */
+u_char MimeTokenTab[256] =
+{
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,SPC,SPC,SPC,SPC,SPC,ILL,ILL,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, ATM,SPC,ATM,ATM,OPR,ATM,ATM,OPR,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,OPR,OPR,OPR,OPR,OPR,OPR,
+ /* @ A B C D E F G H I J K L M N O */
+ OPR,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,OPR,OPR,OPR,ATM,ATM,
+ /* ` a b c d e f g h i j k l m n o */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* p q r s t u v w x y z { | } ~ del */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* @ A B C D E F G H I J K L M N O */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* ` a b c d e f g h i j k l m n o */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* p q r s t u v w x y z { | } ~ del */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+};
# define NOCHAR -1 /* signal nothing in lookahead token */
char **
-prescan(addr, delim, pvpbuf, pvpbsize, delimptr)
+prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
char *addr;
- char delim;
+ int delim;
char pvpbuf[];
char **delimptr;
+ u_char *toktab;
{
register char *p;
register char *q;
char *saveto = CurEnv->e_to;
static char *av[MAXATOM+1];
static char firsttime = TRUE;
+ extern int errno;
if (firsttime)
{
char obuf[50];
firsttime = FALSE;
- expand("\201o", obuf, &obuf[sizeof obuf - sizeof DELIMCHARS], CurEnv);
+ expand("\201o", obuf, sizeof obuf - sizeof DELIMCHARS, CurEnv);
strcat(obuf, DELIMCHARS);
for (p = obuf; *p != '\0'; p++)
{
TokTypeTab[*p & 0xff] = OPR;
}
}
+ if (toktab == NULL)
+ toktab = TokTypeTab;
/* make sure error messages don't have garbage on them */
errno = 0;
if (q >= &pvpbuf[pvpbsize - 5])
{
usrerr("553 Address too long");
+ if (strlen(addr) > MAXNAME)
+ addr[MAXNAME] = '\0';
returnnull:
if (delimptr != NULL)
*delimptr = p;
{
bslashmode = TRUE;
}
- if (state == QST)
+ else if (state == QST)
{
/* do nothing, just avoid next clauses */
}
}
else if (delim == ' ' && isascii(c) && isspace(c))
c = ' ';
- else if (c == ':' && !CurEnv->e_oldstyle)
- {
- /* consume characters until a semicolon */
- while (*p != '\0' && *p != ';')
- p++;
- if (*p == '\0')
- usrerr("Unbalanced ':...;' group spec");
- else
- p++;
- c = ' ';
- }
-
- else if (c == ';') /* semicolons are not tokens */
- c = NOCHAR;
if (c == NOCHAR)
continue;
if (c == delim && anglecnt <= 0 && state != QST)
break;
- newstate = StateTab[state][toktype(c)];
+ newstate = StateTab[state][toktab[c & 0xff]];
if (tTd(22, 101))
printf("ns=%02o\n", newstate);
state = newstate & TYPE;
+ if (state == ILL)
+ {
+ if (isascii(c) && isprint(c))
+ usrerr("653 Illegal character %c", c);
+ else
+ usrerr("653 Illegal character 0x%02x", c);
+ }
if (bitset(M, newstate))
c = NOCHAR;
if (bitset(B, newstate))
** pvp is modified.
*/
-# define OP_NONZLEN 00001
-# define OP_VARLEN 00002
-# define OP_CLASS 00004
-# define OP_EXACT 00010
-
struct match
{
char **first; /* first token matched */
char **last; /* last token matched */
char **pattern; /* pointer to pattern */
- char **source; /* left hand source operand */
- char flags; /* attributes of this operator */
};
# 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];
int
-static char control_init_data[] = {
- MATCHZANY, OP_VARLEN,
- MATCHONE, OP_NONZLEN,
- MATCHANY, OP_VARLEN|OP_NONZLEN,
-#ifdef MACVALUE
- MACVALUE, OP_EXACT,
-#endif /* MACVALUE */
- MATCHNCLASS, OP_NONZLEN,
- MATCHCLASS, OP_NONZLEN|OP_VARLEN|OP_CLASS,
-};
-
-static int nrw;
-
-void
rewrite(pvp, ruleset, reclevel, e)
char **pvp;
int ruleset;
int reclevel;
register ENVELOPE *e;
-{
- nrw = 0;
- _rewrite(pvp, ruleset);
-}
-
-static void
-_rewrite(pvp, ruleset)
- char **pvp;
- int ruleset;
{
register char *ap; /* address pointer */
register char *rp; /* rewrite pointer */
int ruleno; /* current rule number */
int rstat = EX_OK; /* return status */
int loopcount;
- int subr; /* subroutine number if >= 0 */
- bool dolookup; /* do host aliasing */
+ struct match mlist[MAXMATCH]; /* stores match on LHS */
char *npvp[MAXATOM+1]; /* temporary space for rebuild */
- char tokbuf[MAXNAME+1]; /* for concatenated class tokens */
- int nloops, nmatches = 0; /* for looping rule checks */
- struct rewrite *prev_rwr; /* pointer to previous rewrite rule */
- struct match mlist[MAXMATCH+1]; /* stores match on LHS */
- struct match *old_mlp; /* to save our place */
- bool extend_match; /* extend existing match during backup */
if (OpMode == MD_TEST || tTd(21, 1))
{
printf("rewrite: ruleset %2d input:", ruleset);
- printcav(pvp);
+ printav(pvp);
}
if (ruleset < 0 || ruleset >= MAXRWSETS)
{
if (pvp == NULL)
return EX_USAGE;
- if (++nrw > 100)
- {
- char buf[MAXLINE];
-
- buf[0] = buf[MAXLINE-1] = 0;
- while (*pvp)
- (void) strncat(buf, *pvp++, sizeof buf);
- syserr("address causes rewrite loop: <%s>", buf);
- return;
- }
-
- /* Be sure to recognize first rule as new */
- prev_rwr = NULL;
-
/*
- ** Run through the list of rewrite rules, applying any that match.
+ ** Run through the list of rewrite rules, applying
+ ** any that match.
*/
ruleno = 1;
if (tTd(21, 12))
{
printf("-----trying rule:");
- printcav(rwr->r_lhs);
- }
-
- /*
- ** Set up the match list. This is done once for each
- ** rule. If a rule is used repeatedly, the list need not
- ** be set up the next time.
- */
-
- if (rwr != prev_rwr)
- {
- prev_rwr = rwr;
- for (rvp = rwr->r_lhs, mlp = mlist;
- *rvp && (mlp < &mlist[MAXMATCH]); rvp++)
- {
- mlp->flags = ((unsigned char) **rvp >= MAX_CONTROL) ?
- 0 : control_opts[**rvp] ;
- if (mlp->flags)
- {
- mlp->source = rvp;
- mlp++;
- }
- }
- if (*rvp)
- {
- syserr("Too many variables on LHS in ruleset %d", ruleset);
- return;
- }
- mlp->source = rvp;
-
- /* Make sure end marker is initialized */
- mlp->flags = 0;
+ printav(rwr->r_lhs);
}
/* try to match on this rule */
mlp = mlist;
-
rvp = rwr->r_lhs;
avp = pvp;
- nloops = 0;
- extend_match = FALSE;
-
if (++loopcount > 100)
{
- if (nloops++ > 400)
- {
- syserr("Looping on ruleset %d, rule %d",
- ruleset, rwr-RewriteRules[ruleset]);
- mlp = mlist - 1; /* force rule failure */
- break;
- }
syserr("554 Infinite loop in ruleset %d, rule %d",
ruleset, ruleno);
if (tTd(21, 1))
while ((ap = *avp) != NULL || *rvp != NULL)
{
rp = *rvp;
-
if (tTd(21, 35))
{
printf("ADVANCE rp=");
xputs(ap);
printf("\n");
}
-
- if (extend_match)
- extend_match = FALSE;
- else
- {
- mlp->first = avp;
- mlp->last = mlp->flags == 0 || (mlp->flags & OP_NONZLEN) ?
- avp + 1 : avp;
- }
-
if (rp == NULL)
+ {
/* end-of-pattern before end-of-address */
goto backup;
-
- /* Premature end of address */
- if (ap == NULL && avp != mlp->last)
- goto backup;
-
- /*
- ** Simplest case - exact token comparison between
- ** pattern and address. Such a match is not saved
- ** in mlp.
- */
-
- if (rvp < mlp->source)
+ }
+ if (ap == NULL && (*rp & 0377) != MATCHZANY &&
+ (*rp & 0377) != MATCHZERO)
{
- if (ap == NULL || strcasecmp(ap, rp))
- goto backup;
- rvp++;
- avp++;
- continue;
+ /* end-of-input with patterns left */
+ goto backup;
}
-#ifdef MACVALUE
- /*
- ** This is special case handled. The match is exact,
- ** but might span zero or more address tokens. The
- ** result is saved in mlp.
- */
-
- if (*rp == MACVALUE)
+ switch (*rp & 0377)
{
- int len;
- rp = macvalue(rp[1], CurEnv);
+ char buf[MAXLINE];
- if (rp)
- while (*rp)
+ case MATCHCLASS:
+ /* match any phrase in a class */
+ mlp->pattern = rvp;
+ mlp->first = avp;
+ extendclass:
+ ap = *avp;
+ if (ap == NULL)
+ goto backup;
+ mlp->last = avp++;
+ cataddr(mlp->first, mlp->last, buf, sizeof buf, '\0');
+ if (!wordinclass(buf, rp[1]))
+ {
+ if (tTd(21, 36))
{
- if (*avp == NULL || strncasecmp(rp,*avp,len = strlen(*avp)))
- goto backup;
- rp += len;
- avp++;
+ printf("EXTEND rp=");
+ xputs(rp);
+ printf(", ap=");
+ xputs(ap);
+ printf("\n");
}
- mlp->last = avp;
- rvp++;
+ goto extendclass;
+ }
+ if (tTd(21, 36))
+ printf("CLMATCH\n");
mlp++;
- continue;
- }
-#endif /* MACVALUE */
+ break;
- /*
- ** All other matches are saved in mlp. Initially
- ** assume they match at the shortest possible length
- ** for this pattern. Variable patterns will be
- ** extended later as needed.
- */
+ case MATCHNCLASS:
+ /* match any token not in a class */
+ if (wordinclass(ap, rp[1]))
+ goto backup;
- /* Fixed length first */
- if (!(mlp->flags & OP_VARLEN))
- {
- switch (*rp)
- {
- break;
- }
+ /* fall through */
+
+ case MATCHONE:
+ case MATCHANY:
+ /* match exactly one token */
+ mlp->pattern = rvp;
+ mlp->first = avp;
+ mlp->last = avp++;
+ mlp++;
+ break;
- avp = mlp->last;
- rvp++;
+ case MATCHZANY:
+ /* match zero or more tokens */
+ mlp->pattern = rvp;
+ mlp->first = avp;
+ mlp->last = avp - 1;
mlp++;
break;
case MATCHZERO:
/* match zero tokens */
- continue;
- }
+ break;
case MACRODEXPAND:
/*
/* match */
break;
- /*
- ** We now have a variable length item. It could
- ** be $+ or $* in which case no special checking
- ** is needed. But a class match such as $=x must
- ** be verified.
- **
- ** As a speedup, if a variable length item is
- ** followed by a plain character token, we initially
- ** extend the match to the first such token we find.
- ** If the required character token cannot be found,
- ** we fail the match at this point.
- */
-
- avp = mlp->last;
-
- /* If next token is char token */
- if (&rvp[1] < mlp[1].source)
- {
- while (*avp && strcasecmp(*avp, rvp[1]))
- avp++;
-
- /*
- ** If we can't find the proper ending token,
- ** leave avp point to NULL. This indicates
- ** we have run out of address tokens. It is
- ** pointless to advance the beginning of this
- ** match and retry.
- */
-
- if (*avp == NULL)
+ default:
+ /* must have exact match */
+ if (strcasecmp(rp, ap))
goto backup;
- mlp->last = avp;
- }
- else if (rvp[1] == NULL)
- /* next token is end of address */
- {
- while (*avp)
- avp++;
- mlp->last = avp;
- }
-
- if (mlp->flags & OP_CLASS)
- {
- register char *cp = tokbuf;
-
- avp = mlp->first;
- strcpy(cp, *avp);
avp++;
- for (;;)
- {
- while (avp < mlp->last)
- {
- while (*cp)
- cp++;
- strcpy(cp, *avp);
- avp++;
- }
- switch (*rp)
- {
- register STAB *s;
-
- case MATCHCLASS:
- s = stab(tokbuf, ST_CLASS, ST_FIND);
- if (s != NULL && bitnset(rp[1], s->s_class))
- goto have_match;
- break;
- }
-
- /*
- ** Class match initially failed.
- ** Extend the tentative match.
- ** Again, if followed by a character
- ** token, extend all the way to that
- ** token before checking.
- */
-
- if (*avp)
- {
- (mlp->last)++;
- if (&rvp[1] < mlp[1].source)
- {
- while (*(mlp->last) && strcasecmp(*(mlp->last), rvp[1]))
- (mlp->last)++;
- if (*(mlp->last) == NULL)
- avp = mlp->last;
- }
- }
- if (*avp == NULL)
- {
- /*
- ** We could not find the
- ** ending token. But we had
- ** found ending tokens before.
- ** A match is still plausible
- ** if the start of the
- ** tentative match is advanced.
- ** Hence we must not leave avp
- ** pointing to NULL.
- */
- avp = mlp->first;
- goto backup;
- }
- }
+ break;
}
- have_match:
+ /* successful match on this token */
rvp++;
- mlp++;
continue;
-backup:
- /* We failed to match. mlp marks point of failure */
-
- /*
- ** There is a special case when we have exhausted
- ** the address, but have not exhausted the pattern.
- ** Under normal circumstances we could consider the
- ** failure permanent, since extending the number of
- ** address tokens matched by a '$+' or a '$*' will
- ** only worsen the situation.
- **
- ** There is an exception, however. It is possible
- ** that we have matched a class token, say '$=x',
- ** with three or more tokens. Extending a '$+' say,
- ** which precedes the '$=x' will move the beginning
- ** of the '$=x' match to the right, but it might match
- ** a smaller number of tokens then, possibly
- ** correcting the mismatch.
- **
- ** Thus in this case we initially back up to the
- ** $=x which matches three or more tokens.
- */
-
- if (*avp == NULL)
+ backup:
+ /* match failed -- back up */
+ while (--mlp >= mlist)
{
rvp = mlp->pattern;
- while (--mlp > mlist)
+ rp = *rvp;
+ avp = mlp->last + 1;
+ ap = *avp;
+
+ if (tTd(21, 36))
{
- if ((mlp->flags & OP_CLASS) &&
- mlp->last > 2 + mlp->first)
- break;
+ printf("BACKUP rp=");
+ xputs(rp);
+ printf(", ap=");
+ xputs(ap);
+ printf("\n");
}
- }
- /*
- ** Now backup till we find a match with a pattern
- ** whose length is extendable, and extend that.
- */
-
- mlp--;
- while (mlp >= mlist && !(mlp->flags & OP_VARLEN))
- mlp--;
+ if (ap == NULL)
+ {
+ /* run off the end -- back up again */
+ continue;
+ }
+ if ((*rp & 0377) == MATCHANY ||
+ (*rp & 0377) == MATCHZANY)
+ {
+ /* extend binding and continue */
+ mlp->last = avp++;
+ rvp++;
+ mlp++;
+ break;
+ }
+ if ((*rp & 0377) == MATCHCLASS)
+ {
+ /* extend binding and try again */
+ mlp->last = avp;
+ goto extendclass;
+ }
+ }
- /* Total failure to match */
if (mlp < mlist)
- break;
-
- avp = ++(mlp->last);
- rvp = mlp->source;
-
- /*
- ** We have found a backup point. Normally we would
- ** increase the matched amount by one token, and
- ** continue from the next item in the pattern. But
- ** there are two special cases. If this is a
- ** class-type match (OP_CLASS), we must test the
- ** validity of the extended match. If this pattern
- ** item is directly followed by a character token, it
- ** is worth going back and locating the next such
- ** character token before we continue on.
- */
- if ((mlp->flags & OP_CLASS) || (&rvp[1] < mlp[1].source))
- {
- avp = mlp->first;
- extend_match = TRUE;
- }
- else
{
- mlp++;
- rvp++;
+ /* total failure to match */
+ break;
}
}
/*
- ** See if we successfully matched.
+ ** See if we successfully matched
*/
- if (mlp < mlist)
+ if (mlp < mlist || *rvp != NULL)
{
if (tTd(21, 10))
printf("----- rule fails\n");
rwr = rwr->r_next;
ruleno++;
loopcount = 0;
- nmatches = 0;
- continue;
- }
-
- if (nmatches++ > 200)
- {
- syserr("Loop in ruleset %d, rule %d (too many matches)",
- ruleset, rwr - RewriteRules[ruleset]);
- rwr = rwr->r_next;
- nmatches = 0;
continue;
}
if (tTd(21, 12))
{
printf("-----rule matches:");
- printcav(rvp);
+ printav(rvp);
}
rp = *rvp;
rwr = rwr->r_next;
ruleno++;
loopcount = 0;
- nmatches = 0;
}
else if ((*rp & 0377) == CANONHOST)
{
rwr = NULL;
/* substitute */
- dolookup = FALSE;
for (avp = npvp; *rvp != NULL; rvp++)
{
register struct match *m;
register char **pp;
rp = *rvp;
-
- /* check to see if we should do a lookup */
- if (*rp == MATCHLOOKUP)
- dolookup = TRUE;
-
- /* see if there is substitution here */
- if (*rp == MATCHREPL && rp[1] >= '1' && rp[1] <= '9')
+ if ((*rp & 0377) == MATCHREPL)
{
/* substitute from LHS */
m = &mlist[rp[1] - '1'];
if (m < mlist || m >= mlp)
{
- toolong:
- syserr("rewrite: ruleset %d: replacement #%c out of bounds",
+ syserr("554 rewrite: ruleset %d: replacement $%c out of bounds",
ruleset, rp[1]);
return EX_CONFIG;
}
{
printf("$%c:", rp[1]);
pp = m->first;
- while (pp < m->last)
+ while (pp <= m->last)
{
printf(" %x=\"", *pp);
(void) fflush(stdout);
printf("\n");
}
pp = m->first;
- while (pp < m->last)
+ while (pp <= m->last)
{
if (avp >= &npvp[MAXATOM])
- goto toolong;
+ {
+ syserr("554 rewrite: expansion too long");
+ return EX_DATAERR;
+ }
*avp++ = *pp++;
}
}
{
/* vanilla replacement */
if (avp >= &npvp[MAXATOM])
- goto toolong;
-#ifdef MACVALUE
- if (*rp == MACVALUE)
{
- char *p = macvalue(rp[1], CurEnv);
-
- if (tTd(21, 2))
- printf("expanding runtime macro '%c' to \"%s\"\n",
- rp[1], p ? p : "(null)");
- if (p)
- *avp++ = p;
+ toolong:
+ syserr("554 rewrite: expansion too long");
+ return EX_DATAERR;
}
- else
-#endif /* MACVALUE */
+ if ((*rp & 0377) != MACRODEXPAND)
*avp++ = rp;
+ else
+ {
+ *avp = macvalue(rp[1], e);
+ if (tTd(21, 2))
+ printf("rewrite: RHS $&%c => \"%s\"\n",
+ rp[1],
+ *avp == NULL ? "(NULL)" : *avp);
+ if (*avp != NULL)
+ avp++;
+ }
}
}
*avp++ = NULL;
for (rvp = npvp; *rvp != NULL; rvp++)
{
- char **hbrvp, **ubrvp;
+ char **hbrvp;
char **xpvp;
int trsize;
char *replac;
char **key_rvp;
char **arg_rvp;
char **default_rvp;
- char hbuf[MAXNAME + 1], ubuf[MAXNAME + 1];
+ char buf[MAXNAME + 1];
char *pvpb1[MAXATOM + 1];
char *argvect[10];
char pvpbuf[PSBUFSIZE];
char *nullpvp[1];
- bool match, defaultpart;
- char begintype;
- char db = '\0';
if ((**rvp & 0377) != HOSTBEGIN &&
(**rvp & 0377) != LOOKUPBEGIN)
** This could be optimized fairly easily.
*/
- begintype = **rvp;
hbrvp = rvp;
- ubrvp = NULL;
if ((**rvp & 0377) == HOSTBEGIN)
{
endtoken = HOSTEND;
trsize = (int) (avp - rvp + 1) * sizeof *rvp;
bcopy((char *) rvp, (char *) pvpb1, trsize);
- /* append it to the token list */
- for (avp = hbrvp; *xpvp != NULL; xpvp++)
+ /* look it up */
+ cataddr(key_rvp, NULL, buf, sizeof buf, '\0');
+ argvect[0] = buf;
+ if (map != NULL && bitset(MF_OPEN, map->s_map.map_mflags))
+ {
+ auto int stat = EX_OK;
+
+ if (!bitset(MF_KEEPQUOTES, map->s_map.map_mflags))
+ stripquotes(buf);
+
+ /* XXX should try to auto-open the map here */
+
+ if (tTd(60, 1))
+ printf("map_lookup(%s, %s) => ",
+ mapname, buf);
+ replac = (*map->s_map.map_class->map_lookup)(&map->s_map,
+ buf, argvect, &stat);
+ if (tTd(60, 1))
+ printf("%s (%d)\n",
+ replac ? replac : "NOT FOUND",
+ stat);
+
+ /* should recover if stat == EX_TEMPFAIL */
+ if (stat == EX_TEMPFAIL)
{
- *avp++ = newstr(*xpvp);
- if (avp >= &npvp[MAXATOM])
- goto toolong;
+ rstat = EX_TEMPFAIL;
+ if (tTd(60, 1))
+ printf("map_lookup(%s, %s) failed (stat = %d)\n",
+ mapname, buf, stat);
+ if (e->e_message == NULL)
+ {
+ char mbuf[300];
+
+ sprintf(mbuf, "map %s: lookup (%s) failed",
+ mapname, buf);
+ e->e_message = newstr(mbuf);
+ }
}
}
else
- avp = hbrvp;
+ replac = NULL;
- /* restore the old trailing information */
- rvp = avp - 1;
- for (xpvp = pvpb1; *xpvp != NULL; xpvp++)
+ /* if no replacement, use default */
+ if (replac == NULL && default_rvp != NULL)
{
- if (defaultpart && **xpvp == HOSTEND)
+ /* create the default */
+ cataddr(default_rvp, NULL, buf, sizeof buf, '\0');
+ replac = buf;
+ }
+
+ 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)
{
- defaultpart = FALSE;
- rvp = avp - 1;
+ /* prescan already printed error */
+ return EX_DATAERR;
}
- else if (!defaultpart || !match)
- *avp++ = *xpvp;
+ }
+
+ /* append it to the token list */
+ for (avp = hbrvp; *xpvp != NULL; xpvp++)
+ {
+ *avp++ = newstr(*xpvp);
if (avp >= &npvp[MAXATOM])
goto toolong;
}
- *avp++ = NULL;
- /*break;*/
+ /* restore the old trailing information */
+ for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )
+ if (avp >= &npvp[MAXATOM])
+ goto toolong;
+
+ break;
}
/*
** Check for subroutine calls.
- ** Then copy vector back into original space.
*/
- callsubr(npvp);
-
- for (avp = npvp; *avp++ != NULL;);
- subr = atoi(*++rvp);
- rvp++;
+ if (*npvp != NULL && (**npvp & 0377) == CALLSUBR)
+ {
+ int stat;
+ if (npvp[1] == NULL)
+ {
+ syserr("parseaddr: NULL subroutine call in ruleset %d, rule %d",
+ ruleset, ruleno);
+ *pvp = NULL;
+ }
+ else
+ {
+ int ruleset;
+ STAB *s;
+
+ bcopy((char *) &npvp[2], (char *) pvp,
+ (int) (avp - npvp - 2) * sizeof *avp);
+ if (tTd(21, 3))
+ printf("-----callsubr %s\n", npvp[1]);
+ ruleset = strtorwset(npvp[1], NULL, ST_FIND);
+ stat = rewrite(pvp, ruleset, reclevel, e);
+ if (rstat == EX_OK || stat == EX_TEMPFAIL)
+ rstat = stat;
+ if (*pvp != NULL && (**pvp & 0377) == CANONNET)
+ rwr = NULL;
+ }
+ }
else
- subr = -1;
-
- /*
- ** Copy result back to original string.
- */
-
- for (avp = pvp; *rvp != NULL; rvp++)
- *avp++ = *rvp;
- *avp = NULL;
-
- /*
- ** If this specified a subroutine, call it.
- */
-
- if (subr >= 0)
{
-# ifdef DEBUG
- if (tTd(21, 3))
- printf("-----callsubr %s\n", subr);
-# endif DEBUG
- rewrite(pvp, subr);
+ bcopy((char *) npvp, (char *) pvp,
+ (int) (avp - npvp) * sizeof *avp);
}
-
- /*
- ** Done with rewriting this pass.
- */
-
if (tTd(21, 4))
{
printf("rewritten as:");
- printcav(pvp);
+ printav(pvp);
}
}
if (OpMode == MD_TEST || tTd(21, 1))
{
printf("rewrite: ruleset %2d returns:", ruleset);
- printcav(pvp);
+ printav(pvp);
}
return rstat;
}
\f/*
-** CALLSUBR -- call subroutines in rewrite vector
-**
-** Parameters:
-** pvp -- pointer to token vector.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** pvp is modified.
-*/
-
-static void
-callsubr(pvp)
- char **pvp;
-{
- char **rvp;
- int subr;
-
- for (; *pvp != NULL; pvp++)
- if (**pvp == CALLSUBR && pvp[1] != NULL && isdigit(pvp[1][0]))
- {
- subr = atoi(pvp[1]);
-
- if (tTd(21, 3))
- printf("-----callsubr %d\n", subr);
-
- /*
- ** Take care of possible inner calls.
- */
- callsubr(pvp+2);
-
- /*
- ** Move vector up over calling opcode.
- */
- for (rvp = pvp+2; *rvp != NULL; rvp++)
- rvp[-2] = rvp[0];
- rvp[-2] = NULL;
-
- /*
- ** Call inferior ruleset.
- */
- _rewrite(pvp, subr);
-
- break;
- }
-}
-\f/*
** BUILDADDR -- build address from token vector.
**
** Parameters:
NULL, EX_UNAVAILABLE,
};
-static ADDRESS *
+ADDRESS *
buildaddr(tv, a, flags, e)
register char **tv;
register ADDRESS *a;
{
struct mailer **mp;
register struct mailer *m;
- char *bp;
- int spaceleft;
+ register char *p;
+ char *mname;
+ char **hostp;
+ char hbuf[MAXNAME + 1];
static MAILER errormailer;
static char *errorargv[] = { "ERROR", NULL };
- static char buf[MAXNAME];
+ static char ubuf[MAXNAME + 1];
if (tTd(24, 5))
{
if (a == NULL)
a = (ADDRESS *) xalloc(sizeof *a);
- clear((char *) a, sizeof *a);
+ bzero((char *) a, sizeof *a);
/* set up default error return flags */
a->q_flags |= QPINGONFAILURE|QPINGONDELAY;
/* figure out what net/mailer to use */
- if (*tv == NULL || **tv != CANONNET)
+ if (*tv == NULL || (**tv & 0377) != CANONNET)
{
syserr("554 buildaddr: no net");
badaddr:
}
return a;
}
- tv++;
- if (strcasecmp(*tv, "error") == 0)
+ mname = *++tv;
+
+ /* extract host and user portions */
+ if ((**++tv & 0377) == CANONHOST)
+ hostp = ++tv;
+ else
+ hostp = NULL;
+ while (*tv != NULL && (**tv & 0377) != CANONUSER)
+ tv++;
+ if (*tv == NULL)
{
- if ((**++tv & 0377) == CANONHOST)
+ syserr("554 buildaddr: no user");
+ goto badaddr;
+ }
+ if (hostp != NULL)
+ cataddr(hostp, tv - 1, hbuf, sizeof hbuf, '\0');
+ cataddr(++tv, NULL, ubuf, sizeof ubuf, '\0');
+
+ /* save away the host name */
+ if (strcasecmp(mname, "error") == 0)
+ {
+ if (hostp != NULL)
{
register struct errcodes *ep;
- if (isascii(**++tv) && isdigit(**tv))
+ if (strchr(hbuf, '.') != NULL)
+ {
+ a->q_status = newstr(hbuf);
+ setstat(dsntoexitstat(hbuf));
+ }
+ else if (isascii(hbuf[0]) && isdigit(hbuf[0]))
{
- setstat(atoi(*tv));
+ setstat(atoi(hbuf));
}
else
{
for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
- if (strcasecmp(ep->ec_name, *tv) == 0)
+ if (strcasecmp(ep->ec_name, hbuf) == 0)
break;
setstat(ep->ec_code);
}
- tv++;
}
else
setstat(EX_UNAVAILABLE);
- buf[0] = '\0';
- for (; (*tv != NULL) && (**tv != CANONUSER); tv++)
- {
- if (buf[0] != '\0')
- (void) strcat(buf, " ");
- (void) strcat(buf, *tv);
- }
- if ((**tv & 0377) != CANONUSER)
- syserr("554 buildaddr: error: no user");
- cataddr(++tv, NULL, buf, sizeof buf, ' ');
- stripquotes(buf);
-#ifdef LOG
- if (LogLevel > 8)
- syslog (LOG_DEBUG, "%s: Trace: $#ERROR $: %s",
- CurEnv->e_id, buf);
-#endif /* LOG */
- if (isascii(buf[0]) && isdigit(buf[0]) &&
- isascii(buf[1]) && isdigit(buf[1]) &&
- isascii(buf[2]) && isdigit(buf[2]) &&
- buf[3] == ' ')
+ stripquotes(ubuf);
+ if (isascii(ubuf[0]) && isdigit(ubuf[0]) &&
+ isascii(ubuf[1]) && isdigit(ubuf[1]) &&
+ isascii(ubuf[2]) && isdigit(ubuf[2]) &&
+ ubuf[3] == ' ')
{
char fmt[10];
- strncpy(fmt, buf, 3);
+ strncpy(fmt, ubuf, 3);
strcpy(&fmt[3], " %s");
- usrerr(fmt, buf + 4);
+ usrerr(fmt, ubuf + 4);
/*
** If this is a 4xx code and we aren't running
}
else
{
- usrerr("553 %s", buf);
+ usrerr("553 %s", ubuf);
}
goto badaddr;
}
for (mp = Mailer; (m = *mp++) != NULL; )
{
- if (strcasecmp(m->m_name, *tv) == 0)
+ if (strcasecmp(m->m_name, mname) == 0)
break;
}
if (m == NULL)
{
- syserr("554 buildaddr: unknown mailer %s", *tv);
+ syserr("554 buildaddr: unknown mailer %s", mname);
goto badaddr;
}
a->q_mailer = m;
/* figure out what host (if any) */
- if (**++tv != CANONHOST)
+ if (hostp == NULL)
{
+ if (!bitnset(M_LOCALMAILER, m->m_flags))
+ {
+ syserr("554 buildaddr: no host");
+ goto badaddr;
+ }
a->q_host = NULL;
}
else
- {
- else
- a->q_host = NULL;
- }
- else
- {
- while (*++tv != NULL && **tv != CANONUSER)
- (void) strcat(buf, *tv);
- a->q_host = newstr(buf);
- }
+ a->q_host = newstr(hbuf);
/* figure out the user */
- if (*tv == NULL || (**tv & 0377) != CANONUSER)
+ p = ubuf;
+ if (bitnset(M_CHECKUDB, m->m_flags) && *p == '@')
{
- syserr("554 buildaddr: no user");
- goto badaddr;
+ p++;
+ tv++;
+ a->q_flags |= QNOTREMOTE;
}
- tv++;
/* do special mapping for local mailer */
- if (*tv != NULL)
+ 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))
{
- register char *p = *tv;
-
- 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)
{
- /* may be :include: */
- cataddr(tv, NULL, buf, sizeof buf, '\0');
- stripquotes(buf);
- if (strncasecmp(buf, ":include:", 9) == 0)
- {
- /* if :include:, don't need further rewriting */
- a->q_mailer = m = InclMailer;
- a->q_user = &buf[9];
- return (a);
- }
+ /* if :include:, don't need further rewriting */
+ a->q_mailer = m = InclMailer;
+ a->q_user = newstr(&ubuf[9]);
+ return a;
}
}
- if (bitnset(M_CHECKUDB, m->m_flags) && *tv != NULL &&
- strcmp(*tv, "@") == 0)
+ /* rewrite according recipient mailer rewriting rules */
+ define('h', a->q_host, e);
+ if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
{
- tv++;
- a->q_flags |= QNOTREMOTE;
+ /* 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);
}
-
- if (m->m_r_rwset > 0)
- rewrite(tv, m->m_r_rwset);
(void) rewrite(tv, 4, 0, e);
/* save the result for the command line/RCPT argument */
- cataddr(tv, NULL, buf, sizeof buf, '\0');
- a->q_user = buf;
+ cataddr(tv, NULL, ubuf, sizeof ubuf, '\0');
+ a->q_user = ubuf;
/*
** Do mapping to lower case as requested by mailer
if (!bitnset(M_USR_UPPER, m->m_flags))
makelower(a->q_user);
- return (a);
+ return a;
}
\f/*
** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
char **evp;
char *buf;
register int sz;
- char spacesub;
+ int spacesub;
{
bool oatomtok = FALSE;
- bool natomtok;
+ bool natomtok = FALSE;
register int i;
register char *p;
sz -= 2;
while (*pvp != NULL && (i = strlen(*pvp)) < sz)
{
- natomtok = (toktype(**pvp) == ATM);
+ natomtok = (TokTypeTab[**pvp & 0xff] == ATM);
if (oatomtok && natomtok)
*p++ = spacesub;
(void) strcpy(p, *pvp);
return (FALSE);
/* if the user isn't the same, we can drop out */
- if (strcasecmp(a->q_user, b->q_user))
+ if (strcmp(a->q_user, b->q_user) != 0)
return (FALSE);
/* if we have good uids for both but they differ, these are different */
/* only one is a null pointer */
return (FALSE);
}
- if (strcasecmp(a->q_host, b->q_host))
+ if (strcmp(a->q_host, b->q_host) != 0)
return (FALSE);
return (TRUE);
"QNOTREMOTE", QNOTREMOTE,
"QSELFREF", QSELFREF,
"QVERIFIED", QVERIFIED,
- "QREPORT", QREPORT,
"QBOGUSSHELL", QBOGUSSHELL,
"QUNSAFEADDR", QUNSAFEADDR,
"QPINGONSUCCESS", QPINGONSUCCESS,
"QPINGONFAILURE", QPINGONFAILURE,
"QPINGONDELAY", QPINGONDELAY,
- "QHAS_RET_PARAM", QHAS_RET_PARAM,
- "QRET_HDRS", QRET_HDRS,
+ "QHASNOTIFY", QHASNOTIFY,
"QRELAYED", QRELAYED,
+ "QEXPANDED", QEXPANDED,
+ "QDELIVERED", QDELIVERED,
+ "QDELAYED", QDELAYED,
+ "QTHISPASS", QTHISPASS,
NULL
};
return;
}
- static int indent;
- register int i;
-
while (a != NULL)
{
- for (i = indent; i > 0; i--)
- printf("\t");
printf("%x=", a);
(void) fflush(stdout);
m->m_name = "NULL";
}
- for (i = indent; i > 0; i--)
- printf("\t");
- printf("\tnext=%x, flags=%o, rmailer %d, alias=%x, sibling=%x, child=%x\n",
- a->q_next, a->q_flags, a->q_rmailer, a->q_alias,
- a->q_sibling, a->q_child);
-
- /* follow the chain if appropriate */
+ printf("%s:\n\tmailer %d (%s), host `%s'\n",
+ 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("\tnext=%x, alias %x, uid %d, gid %d\n",
+ a->q_next, a->q_alias, a->q_uid, 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, rstatus=%s\n",
+ a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
+ a->q_statmta == NULL ? "(none)" : a->q_statmta,
+ a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
+
if (!follow)
return;
-
- indent++;
- printaddr(a->q_child, TRUE);
- indent--;
- a = a->q_sibling;
+ a = a->q_next;
}
}
\f/*
char *
remotename(name, m, flags, pstat, e)
char *name;
- MAILER *m;
+ struct mailer *m;
int flags;
int *pstat;
register ENVELOPE *e;
char *fancy;
char *oldg = macvalue('g', e);
int rwset;
- static char buf[MAXNAME];
- char lbuf[MAXNAME];
+ static char buf[MAXNAME + 1];
+ char lbuf[MAXNAME + 1];
char pvpbuf[PSBUFSIZE];
+ extern char *crackaddr();
if (tTd(12, 1))
printf("remotename(%s)\n", name);
/* don't do anything if we are tagging it as special */
- if ((senderaddress ? m->m_s_rwset : m->m_r_rwset) < 0)
+ if (bitset(RF_SENDERADDR, flags))
+ rwset = bitset(RF_HEADERADDR, flags) ? m->m_sh_rwset
+ : m->m_se_rwset;
+ else
+ rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset
+ : m->m_re_rwset;
+ if (rwset < 0)
return (name);
/*
** domain will be appended.
*/
- pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL);
+ pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
if (pvp == NULL)
return (name);
if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
/*
** Do more specific rewriting.
- ** Rewrite using ruleset 1 or 2 for envelope addresses and
- ** 5 or 6 for header addresses depending on whether this
- ** is a sender address or not.
+ ** Rewrite using ruleset 1 or 2 depending on whether this is
+ ** a sender address or not.
** Then run it through any receiving-mailer-specific rulesets.
*/
+ if (bitset(RF_SENDERADDR, flags))
+ {
+ if (rewrite(pvp, 1, 0, e) == EX_TEMPFAIL)
+ *pstat = EX_TEMPFAIL;
+ }
else
{
+ if (rewrite(pvp, 2, 0, e) == EX_TEMPFAIL)
+ *pstat = EX_TEMPFAIL;
+ }
if (rwset > 0)
{
if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL)
/* need to make sure route-addrs have <angle brackets> */
if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
- expand("<\201g>", buf, &buf[sizeof buf - 1], e);
+ expand("<\201g>", buf, sizeof buf, e);
else
- expand(fancy, buf, &buf[sizeof buf - 1], e);
+ expand(fancy, buf, sizeof buf, e);
define('g', oldg, e);
return (buf);
}
\f/*
-** UURELATIVIZE -- Make an address !-relative to recipient/sender nodes
-**
-** Parameters:
-** from -- the sending node (usually "$k" or "$w")
-** to -- the receiving node (usually "$h")
-** pvp -- address vector
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** The pvp is rewritten to be relative the "to" node
-** wrt the "from" node. In other words, if the pvp
-** is headed by "to!" that part is stripped; otherwise
-** "from!" is prepended. Exception: "to!user" addresses
-** with no '!'s in the user part are sent as is.
-**
-** Bugs:
-** The pvp may overflow, but we don't catch it.
-*/
-
-static void
-uurelativize(from, to, pvp)
- const char *from, *to;
- char **pvp;
-{
- register char **pxp = pvp;
- char expfrom[MAXNAME], expto[MAXNAME];
-
- expand(from, expfrom, &expfrom[sizeof expfrom - 1], CurEnv);
- expand(to, expto, &expto[sizeof expto - 1], CurEnv);
-
- /*
- * supposing that we've got something, should
- * we add "from!" or remove "to!"?
- */
- if (pvp[0] != NULL)
- if (pvp[1] == NULL || strcmp(pvp[1], "!") != 0 ||
- /*strcasecmp?*/ strcmp(pvp[0], expto) != 0)
- {
- /* either local name, no UUCP address, */
- /* or not to "to!" ==> prepend address with "from!" */
-
- /* already there? */
- if (pvp[1] == NULL || strcmp(pvp[1], "!") != 0 ||
- /*strcasecmp?*/ strcmp(pvp[0], expfrom) != 0)
- {
-
- /* no, put it there */
- while (*pxp != NULL)
- pxp++;
- do
- pxp[2] = *pxp;
- while (pxp-- != pvp);
- pvp[0] = newstr(expfrom);
- pvp[1] = "!";
- }
- }
- else
- {
- /* address is to "to!" -- remove if not "to!user" */
- for (pxp = &pvp[2];
- *pxp != NULL && strcmp(*pxp, "!") != 0; pxp++)
- ;
- if (*pxp != NULL)
- for (pxp = pvp; *pxp != NULL; pxp++)
- *pxp = pxp[2];
- }
-}
-\f/*
** MAPLOCALUSER -- run local username through ruleset 5 for final redirection
**
** Parameters:
** none.
*/
+void
maplocaluser(a, sendq, aliaslevel, e)
register ADDRESS *a;
ADDRESS **sendq;
printf("maplocaluser: ");
printaddr(a, FALSE);
}
- pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr);
+ pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr, NULL);
if (pvp == NULL)
return;
{
register char *p = args;
+ map->map_mflags |= MF_KEEPQUOTES;
for (;;)
{
while (isascii(*p) && isspace(*p))