in initial hooks for per-mailer rewriting; improve diagnostics in readcf,
including number lines; increase the number of rewriting sets.
SCCS-vsn: usr.sbin/sendmail/src/sendmail.h 3.85
SCCS-vsn: usr.sbin/sendmail/src/parseaddr.c 3.51
SCCS-vsn: usr.sbin/sendmail/src/version.c 3.185
-SCCSID(@(#)parseaddr.c 3.50 %G%);
+SCCSID(@(#)parseaddr.c 3.51 %G%);
/*
** PARSE -- Parse an address
/*
** PARSE -- Parse an address
**
** For each rewrite rule, 'avp' points the address vector we
** are trying to match against, and 'pvp' points to the pattern.
**
** For each rewrite rule, 'avp' points the address vector we
** are trying to match against, and 'pvp' points to the pattern.
-** If pvp points to a special match value (MATCHANY, MATCHONE,
-** MATCHCLASS) then the address in avp matched is saved away
-** in the match vector (pointed to by 'mvp').
+** If pvp points to a special match value (MATCHZANY, MATCHANY,
+** MATCHONE, MATCHCLASS) then the address in avp matched is
+** saved away in the match vector (pointed to by 'mvp').
**
** When a match between avp & pvp does not match, we try to
** back out. If we back up over a MATCHONE or a MATCHCLASS
** we must also back out the match in mvp. If we reach a
**
** When a match between avp & pvp does not match, we try to
** back out. If we back up over a MATCHONE or a MATCHCLASS
** we must also back out the match in mvp. If we reach a
-** MATCHANY we just extend the match and start over again.
+** MATCHANY or MATCHZANY we just extend the match and start
+** over again.
**
** When we finally match, we rewrite the address vector
** and try over again.
**
** When we finally match, we rewrite the address vector
** and try over again.
register char *rp; /* rewrite pointer */
register char **avp; /* address vector pointer */
register char **rvp; /* rewrite vector pointer */
register char *rp; /* rewrite pointer */
register char **avp; /* address vector pointer */
register char **rvp; /* rewrite vector pointer */
- struct rewrite *rwr; /* pointer to current rewrite rule */
+ register struct match *mlp; /* cur ptr into mlist */
+ register struct rewrite *rwr; /* pointer to current rewrite rule */
struct match mlist[MAXMATCH]; /* stores match on LHS */
struct match mlist[MAXMATCH]; /* stores match on LHS */
- struct match *mlp; /* cur ptr into mlist */
char *npvp[MAXATOM+1]; /* temporary space for rebuild */
extern bool sameword();
# ifdef DEBUG
if (tTd(21, 9))
{
char *npvp[MAXATOM+1]; /* temporary space for rebuild */
extern bool sameword();
# ifdef DEBUG
if (tTd(21, 9))
{
- printf("rewrite: original pvp:\n");
+ printf("rewrite: ruleset %d, original pvp:\n", ruleset);
printav(pvp);
}
# endif DEBUG
printav(pvp);
}
# endif DEBUG
/* try to match on this rule */
mlp = mlist;
/* try to match on this rule */
mlp = mlist;
- for (rvp = rwr->r_lhs, avp = pvp; *avp != NULL; )
+ rvp = rwr->r_lhs;
+ avp = pvp;
+ while ((ap = *avp) != NULL || *rvp != NULL)
+# ifdef DEBUG
+ if (tTd(21, 35))
+ {
+ printf("ap=\"");
+ xputs(ap);
+ printf("\", rp=\"");
+ xputs(rp);
+ printf("\"\n");
+ }
+# endif DEBUG
if (rp == NULL)
{
/* end-of-pattern before end-of-address */
if (rp == NULL)
{
/* end-of-pattern before end-of-address */
+ goto backup;
+ }
+ if (ap == NULL && *rp != MATCHZANY)
+ {
+ /* end-of-input */
+ break;
/* match any token in a class */
class = rp[1];
if (!isalpha(class))
/* match any token in a class */
class = rp[1];
if (!isalpha(class))
if (isupper(class))
class -= 'A';
else
class -= 'a';
s = stab(ap, ST_CLASS, ST_FIND);
if (s == NULL || (s->s_class & (1L << class)) == 0)
if (isupper(class))
class -= 'A';
else
class -= 'a';
s = stab(ap, ST_CLASS, ST_FIND);
if (s == NULL || (s->s_class & (1L << class)) == 0)
/* explicit fall-through */
case MATCHONE:
case MATCHANY:
/* match exactly one token */
/* explicit fall-through */
case MATCHONE:
case MATCHANY:
/* match exactly one token */
- mlp->first = mlp->last = avp++;
+ mlp->first = avp;
+ mlp->last = avp++;
+ mlp++;
+ break;
+
+ case MATCHZANY:
+ /* match zero or more tokens */
+ mlp->first = avp;
+ mlp->last = avp - 1;
mlp++;
break;
default:
/* must have exact match */
if (!sameword(rp, ap))
mlp++;
break;
default:
/* must have exact match */
if (!sameword(rp, ap))
/* match failed -- back up */
while (--rvp >= rwr->r_lhs)
{
rp = *rvp;
/* match failed -- back up */
while (--rvp >= rwr->r_lhs)
{
rp = *rvp;
+ if (*rp == MATCHANY || *rp == MATCHZANY)
{
/* extend binding and continue */
{
/* extend binding and continue */
+ avp = ++mlp[-1].last;
+ avp++;
if (rvp >= rwr->r_lhs && *rvp == NULL)
{
if (rvp >= rwr->r_lhs && *rvp == NULL)
{
# ifdef DEBUG
if (tTd(21, 12))
{
printf("-----rule matches:\n");
# ifdef DEBUG
if (tTd(21, 12))
{
printf("-----rule matches:\n");
+ /* see if this is a "subroutine" call */
+ rp = *rvp;
+ if (*rp == CALLSUBR)
+ {
+ rp = *++rvp;
+# ifdef DEBUG
+ if (tTd(21, 2))
+ printf("-----callsubr %s\n", rp);
+# endif DEBUG
+ rewrite(pvp, atoi(rp));
+ rwr = rwr->r_next;
+ continue;
+ }
+
/* substitute */
for (rvp = rwr->r_rhs, avp = npvp; *rvp != NULL; rvp++)
{
/* substitute */
for (rvp = rwr->r_rhs, avp = npvp; *rvp != NULL; rvp++)
{
{
printf("$%c:", rp[1]);
pp = m->first;
{
printf("$%c:", rp[1]);
pp = m->first;
{
printf(" %x=\"", *pp);
(void) fflush(stdout);
{
printf(" %x=\"", *pp);
(void) fflush(stdout);
- printf("%s\"", *pp);
- } while (pp++ != m->last);
+ printf("%s\"", *pp++);
+ }
printf("\n");
}
# endif DEBUG
pp = m->first;
printf("\n");
}
# endif DEBUG
pp = m->first;
{
if (avp >= &npvp[MAXATOM])
{
syserr("rewrite: expansion too long");
return;
}
{
if (avp >= &npvp[MAXATOM])
{
syserr("rewrite: expansion too long");
return;
}
- *avp++ = *pp;
- } while (pp++ != m->last);
** First put this address into canonical form.
** First turn it into a macro.
** Then run it through ruleset 4.
** First put this address into canonical form.
** First turn it into a macro.
** Then run it through ruleset 4.
+ ** If the mailer defines a rewriting set, run it through
+ ** there next.
+ ** The intent is that ruleset 4 puts the name into a
+ ** canonical form; the mailer's ruleset then
+ ** does any customization.
*/
/* save away the extraneous pretty stuff */
*/
/* save away the extraneous pretty stuff */
if (pvp == NULL)
return (name);
rewrite(pvp, 4);
if (pvp == NULL)
return (name);
rewrite(pvp, 4);
+ if (m->m_rwset > 0)
+ rewrite(pvp, m->m_rwset);
/*
** See if this mailer wants the name to be rewritten. There are
/*
** See if this mailer wants the name to be rewritten. There are
# ifdef _DEFINE
# define EXTERN
# ifndef lint
# ifdef _DEFINE
# define EXTERN
# ifndef lint
-static char SmailSccsId[] = "@(#)sendmail.h 3.84 %G%";
+static char SmailSccsId[] = "@(#)sendmail.h 3.85 %G%";
# endif lint
# else _DEFINE
# define EXTERN extern
# endif lint
# else _DEFINE
# define EXTERN extern
# define MAXHOP 30 /* max value of HopCount */
# define MAXATOM 100 /* max atoms per address */
# define MAXMAILERS 25 /* maximum mailers known to system */
# define MAXHOP 30 /* max value of HopCount */
# define MAXATOM 100 /* max atoms per address */
# define MAXMAILERS 25 /* maximum mailers known to system */
+# define MAXRWSETS 30 /* max # of sets of rewriting rules */
# define SPACESUB ('.'|0200) /* substitution for <lwsp> */
\f/*
** Address structure.
# define SPACESUB ('.'|0200) /* substitution for <lwsp> */
\f/*
** Address structure.
short m_mno; /* mailer number internally */
char *m_from; /* pattern for From: header */
char **m_argv; /* template argument vector */
short m_mno; /* mailer number internally */
char *m_from; /* pattern for From: header */
char **m_argv; /* template argument vector */
+ short m_rwset; /* apply this rewriting set to addresses */
};
typedef struct mailer MAILER;
};
typedef struct mailer MAILER;
struct rewrite *r_next;/* next in chain */
};
struct rewrite *r_next;/* next in chain */
};
-extern struct rewrite *RewriteRules[];
+EXTERN struct rewrite *RewriteRules[MAXRWSETS];
-# define MATCHANY '\020' /* match one or more tokens */
-# define MATCHONE '\021' /* match exactly one token */
-# define MATCHCLASS '\022' /* match one token in a class */
-# define MATCHREPL '\023' /* replacement on RHS for above */
+/*
+** Special characters in rewriting rules.
+** These are used internally only.
+** The COND* rules are actually used in macros rather than in
+** rewriting rules, but are given here because they
+** cannot conflict.
+*/
+
+/* left hand side items */
+# define MATCHZANY '\020' /* match zero or more tokens */
+# define MATCHANY '\021' /* match one or more tokens */
+# define MATCHONE '\022' /* match exactly one token */
+# define MATCHCLASS '\023' /* match one token in a class */
+# define MATCHREPL '\024' /* replacement on RHS for above */
+/* right hand side items */
# define CANONNET '\025' /* canonical net, next token */
# define CANONHOST '\026' /* canonical host, next token */
# define CANONUSER '\027' /* canonical user, next N tokens */
# define CANONNET '\025' /* canonical net, next token */
# define CANONHOST '\026' /* canonical host, next token */
# define CANONUSER '\027' /* canonical user, next N tokens */
+# define CALLSUBR '\030' /* call another rewriting set */
-# define CONDIF '\030' /* conditional if-then */
-# define CONDELSE '\031' /* conditional else */
-# define CONDFI '\032' /* conditional fi */
+/* conditionals in macros */
+# define CONDIF '\031' /* conditional if-then */
+# define CONDELSE '\032' /* conditional else */
+# define CONDFI '\033' /* conditional fi */
\f/*
** Symbol table definitions
*/
\f/*
** Symbol table definitions
*/
EXTERN int HopCount; /* hop count */
EXTERN int AliasLevel; /* depth of aliasing */
EXTERN int MotherPid; /* proc id of parent process */
EXTERN int HopCount; /* hop count */
EXTERN int AliasLevel; /* depth of aliasing */
EXTERN int MotherPid; /* proc id of parent process */
+EXTERN int LineNumber; /* line number in current input */
EXTERN time_t QueueIntvl; /* intervals between running the queue */
EXTERN char *HostName; /* name of this host for SMTP messages */
EXTERN char *Transcript; /* the transcript file name */
EXTERN time_t QueueIntvl; /* intervals between running the queue */
EXTERN char *HostName; /* name of this host for SMTP messages */
EXTERN char *Transcript; /* the transcript file name */
-static char SccsId[] = "@(#)SendMail version 3.184 of %G%";
+static char SccsId[] = "@(#)SendMail version 3.185 of %G%";
-char Version[] = "3.184 [%G%]";
+char Version[] = "3.185 [%G%]";