122707Sdist /*
268839Seric * Copyright (c) 1983, 1995 Eric P. Allman
362525Sbostic * Copyright (c) 1988, 1993
462525Sbostic * The Regents of the University of California. All rights reserved.
533729Sbostic *
642826Sbostic * %sccs.include.redist.c%
733729Sbostic */
822707Sdist
922707Sdist #ifndef lint
10*69917Seric static char sccsid[] = "@(#)macro.c 8.12 (Berkeley) 06/17/95";
1133729Sbostic #endif /* not lint */
1222707Sdist
136056Seric # include "sendmail.h"
143379Seric
1567767Seric char *MacroName[256]; /* macro id to name table */
1667767Seric int NextMacroId = 0240; /* codes for long named macros */
1767767Seric
1867767Seric
193379Seric /*
203379Seric ** EXPAND -- macro expand a string using $x escapes.
213379Seric **
223379Seric ** Parameters:
233379Seric ** s -- the string to expand.
243379Seric ** buf -- the place to put the expansion.
2568529Seric ** bufsize -- the size of the buffer.
266980Seric ** e -- envelope in which to work.
273379Seric **
283379Seric ** Returns:
299382Seric ** none.
303379Seric **
313379Seric ** Side Effects:
323379Seric ** none.
333379Seric */
343379Seric
3560494Seric void
expand(s,buf,bufsize,e)3668529Seric expand(s, buf, bufsize, e)
376980Seric register char *s;
386980Seric register char *buf;
3968529Seric size_t bufsize;
406980Seric register ENVELOPE *e;
416980Seric {
4217349Seric register char *xp;
436056Seric register char *q;
449382Seric bool skipping; /* set if conditionally skipping output */
4517349Seric bool recurse = FALSE; /* set if recursion required */
4617349Seric int i;
4757589Seric int iflev; /* if nesting level */
486056Seric char xbuf[BUFSIZ];
493379Seric
5024941Seric if (tTd(35, 24))
516056Seric {
526056Seric printf("expand(");
536056Seric xputs(s);
546056Seric printf(")\n");
556056Seric }
563379Seric
573387Seric skipping = FALSE;
5857589Seric iflev = 0;
598064Seric if (s == NULL)
608064Seric s = "";
6117349Seric for (xp = xbuf; *s != '\0'; s++)
623379Seric {
6364087Seric int c;
644319Seric
654319Seric /*
666056Seric ** Check for non-ordinary (special?) character.
674319Seric ** 'q' will be the interpolated quantity.
684319Seric */
694319Seric
703379Seric q = NULL;
716056Seric c = *s;
7258050Seric switch (c & 0377)
733387Seric {
746056Seric case CONDIF: /* see if var set */
7557977Seric c = *++s;
7657977Seric if (skipping)
7757977Seric iflev++;
7857977Seric else
7957589Seric skipping = macvalue(c, e) == NULL;
8057977Seric continue;
813387Seric
826056Seric case CONDELSE: /* change state of skipping */
8357977Seric if (iflev == 0)
8457589Seric skipping = !skipping;
856056Seric continue;
863387Seric
876056Seric case CONDFI: /* stop skipping */
8857977Seric if (iflev == 0)
8957589Seric skipping = FALSE;
9057977Seric if (skipping)
9157977Seric iflev--;
9257977Seric continue;
933387Seric
9458050Seric case MACROEXPAND: /* macro interpolation */
9567767Seric c = *++s & 0377;
9666019Seric if (c != '\0')
9766019Seric q = macvalue(c, e);
9866019Seric else
9966019Seric {
10066019Seric s--;
10166019Seric q = NULL;
10266019Seric }
1039382Seric if (q == NULL)
1043387Seric continue;
1056056Seric break;
1063387Seric }
1073387Seric
1083379Seric /*
1093379Seric ** Interpolate q or output one character
1103379Seric */
1113379Seric
11217349Seric if (skipping || xp >= &xbuf[sizeof xbuf])
1133387Seric continue;
11417349Seric if (q == NULL)
11517349Seric *xp++ = c;
11617349Seric else
1176056Seric {
11817349Seric /* copy to end of q or max space remaining in buf */
11917349Seric while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
1206056Seric {
12158050Seric /* check for any sendmail metacharacters */
12258050Seric if ((c & 0340) == 0200)
12317349Seric recurse = TRUE;
1246056Seric *xp++ = c;
1256056Seric }
1266056Seric }
1273379Seric }
1286056Seric *xp = '\0';
1293379Seric
13024941Seric if (tTd(35, 24))
1316056Seric {
1328064Seric printf("expand ==> ");
1336056Seric xputs(xbuf);
1348064Seric printf("\n");
1356056Seric }
1363379Seric
1376056Seric /* recurse as appropriate */
13817349Seric if (recurse)
1399382Seric {
14068529Seric expand(xbuf, buf, bufsize, e);
1419382Seric return;
1429382Seric }
1436056Seric
1446056Seric /* copy results out */
14568529Seric i = xp - xbuf;
14668529Seric if (i >= bufsize)
14768529Seric i = bufsize - 1;
14817349Seric bcopy(xbuf, buf, i);
14917349Seric buf[i] = '\0';
1503379Seric }
1513379Seric /*
1523379Seric ** DEFINE -- define a macro.
1533379Seric **
1543379Seric ** this would be better done using a #define macro.
1553379Seric **
1563379Seric ** Parameters:
1573379Seric ** n -- the macro name.
1583379Seric ** v -- the macro value.
1599382Seric ** e -- the envelope to store the definition in.
1603379Seric **
1613379Seric ** Returns:
1623379Seric ** none.
1633379Seric **
1643379Seric ** Side Effects:
1659382Seric ** e->e_macro[n] is defined.
1664092Seric **
1674092Seric ** Notes:
1684092Seric ** There is one macro for each ASCII character,
1694092Seric ** although they are not all used. The currently
1704092Seric ** defined macros are:
1714092Seric **
1724202Seric ** $a date in ARPANET format (preferring the Date: line
1734202Seric ** of the message)
1744202Seric ** $b the current date (as opposed to the date as found
1754202Seric ** the message) in ARPANET format
1764092Seric ** $c hop count
1774202Seric ** $d (current) date in UNIX (ctime) format
17810710Seric ** $e the SMTP entry message+
1794092Seric ** $f raw from address
1804092Seric ** $g translated from address
1814092Seric ** $h to host
1827851Seric ** $i queue id
1837851Seric ** $j official SMTP hostname, used in messages+
18457630Seric ** $k UUCP node name
1854092Seric ** $l UNIX-style from line+
18658319Seric ** $m The domain part of our full name.
1874092Seric ** $n name of sendmail ("MAILER-DAEMON" on local
1884092Seric ** net typically)+
1894092Seric ** $o delimiters ("operators") for address tokens+
1904092Seric ** $p my process id in decimal
1915919Seric ** $q the string that becomes an address -- this is
1925919Seric ** normally used to combine $g & $x.
1935187Seric ** $r protocol used to talk to sender
1945187Seric ** $s sender's host name
1954092Seric ** $t the current time in seconds since 1/1/1970
1964092Seric ** $u to user
1974092Seric ** $v version number of sendmail
19810407Seric ** $w our host name (if it can be determined)
1994092Seric ** $x signature (full name) of from person
2004202Seric ** $y the tty id of our terminal
2014092Seric ** $z home directory of to person
20258951Seric ** $_ RFC1413 authenticated sender address
2034092Seric **
2044092Seric ** Macros marked with + must be defined in the
2054092Seric ** configuration file and are used internally, but
2064092Seric ** are not set.
2074092Seric **
2084092Seric ** There are also some macros that can be used
2094092Seric ** arbitrarily to make the configuration file
2104092Seric ** cleaner. In general all upper-case letters
2114092Seric ** are available.
2123379Seric */
2133379Seric
21460494Seric void
define(n,v,e)2159382Seric define(n, v, e)
21664087Seric int n;
2173379Seric char *v;
2189382Seric register ENVELOPE *e;
2193379Seric {
22024941Seric if (tTd(35, 9))
2216056Seric {
22267767Seric printf("define(%s as ", macname(n));
2236056Seric xputs(v);
2246056Seric printf(")\n");
2256056Seric }
22667767Seric e->e_macro[n & 0377] = v;
2273379Seric }
2284454Seric /*
2294454Seric ** MACVALUE -- return uninterpreted value of a macro.
2304454Seric **
2314454Seric ** Parameters:
2324454Seric ** n -- the name of the macro.
2334454Seric **
2344454Seric ** Returns:
2354454Seric ** The value of n.
2364454Seric **
2374454Seric ** Side Effects:
2384454Seric ** none.
2394454Seric */
2404454Seric
2414454Seric char *
macvalue(n,e)2428182Seric macvalue(n, e)
24364087Seric int n;
2448182Seric register ENVELOPE *e;
2454454Seric {
24667767Seric n &= 0377;
2478182Seric while (e != NULL)
2488182Seric {
2498182Seric register char *p = e->e_macro[n];
2508182Seric
2518182Seric if (p != NULL)
2528182Seric return (p);
2538182Seric e = e->e_parent;
2548182Seric }
2558182Seric return (NULL);
2564454Seric }
25767767Seric /*
25867767Seric ** MACNAME -- return the name of a macro given its internal id
25967767Seric **
26067767Seric ** Parameter:
26167767Seric ** n -- the id of the macro
26267767Seric **
26367767Seric ** Returns:
26467767Seric ** The name of n.
26567767Seric **
26667767Seric ** Side Effects:
26767767Seric ** none.
26867767Seric */
26967767Seric
27067767Seric char *
macname(n)27167767Seric macname(n)
27267767Seric int n;
27367767Seric {
27467767Seric static char mbuf[2];
27567767Seric
27667767Seric n &= 0377;
27767767Seric if (bitset(0200, n))
27867767Seric {
27967767Seric char *p = MacroName[n];
28067767Seric
28167767Seric if (p != NULL)
28267767Seric return p;
28367767Seric return "***UNDEFINED MACRO***";
28467767Seric }
28567767Seric mbuf[0] = n;
28667767Seric mbuf[1] = '\0';
28767767Seric return mbuf;
28867767Seric }
28967767Seric /*
29067767Seric ** MACID -- return id of macro identified by its name
29167767Seric **
29267767Seric ** Parameters:
29367767Seric ** p -- pointer to name string -- either a single
29467767Seric ** character or {name}.
29567767Seric ** ep -- filled in with the pointer to the byte
29667767Seric ** after the name.
29767767Seric **
29867767Seric ** Returns:
29967767Seric ** The internal id code for this macro. This will
30067767Seric ** fit into a single byte.
30167767Seric **
30267767Seric ** Side Effects:
30367767Seric ** If this is a new macro name, a new id is allocated.
30467767Seric */
30567767Seric
30667767Seric int
macid(p,ep)30767767Seric macid(p, ep)
30867767Seric register char *p;
30967767Seric char **ep;
31067767Seric {
31167767Seric int mid;
31267767Seric register char *bp;
31367767Seric char mbuf[21];
31467767Seric
31567767Seric if (tTd(35, 14))
316*69917Seric {
317*69917Seric printf("macid(");
318*69917Seric xputs(p);
319*69917Seric printf(") => ");
320*69917Seric }
32167767Seric
32267815Seric if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
32367767Seric {
32467767Seric syserr("Name required for macro/class");
32567767Seric if (ep != NULL)
32667767Seric *ep = p;
32767767Seric if (tTd(35, 14))
32867767Seric printf("NULL\n");
32967767Seric return '\0';
33067767Seric }
33167767Seric if (*p != '{')
33267767Seric {
33367767Seric /* the macro is its own code */
33467767Seric if (ep != NULL)
33567767Seric *ep = p + 1;
33667767Seric if (tTd(35, 14))
33767767Seric printf("%c\n", *p);
33867767Seric return *p;
33967767Seric }
34067767Seric bp = mbuf;
34167767Seric while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf])
34267815Seric {
34367815Seric if (isascii(*p) && (isalnum(*p) || *p == '_'))
34467815Seric *bp++ = *p;
34567815Seric else
34667815Seric syserr("Invalid macro/class character %c", *p);
34767815Seric }
34867767Seric *bp = '\0';
34967767Seric mid = -1;
35067767Seric if (*p == '\0')
35167767Seric {
35267767Seric syserr("Unbalanced { on %s", mbuf); /* missing } */
35367767Seric }
35467767Seric else if (*p != '}')
35567767Seric {
35667767Seric syserr("Macro/class name ({%s}) too long (%d chars max)",
35767767Seric mbuf, sizeof mbuf - 1);
35867767Seric }
35967767Seric else if (mbuf[1] == '\0')
36067767Seric {
36167767Seric /* ${x} == $x */
36267767Seric mid = mbuf[0];
36367767Seric p++;
36467767Seric }
36567767Seric else
36667767Seric {
36767767Seric register STAB *s;
36867767Seric
36967767Seric s = stab(mbuf, ST_MACRO, ST_ENTER);
37067767Seric if (s->s_macro != 0)
37167767Seric mid = s->s_macro;
37267767Seric else
37367767Seric {
37467767Seric if (NextMacroId > 0377)
37567767Seric {
37667767Seric syserr("Macro/class {%s}: too many long names", mbuf);
37767767Seric s->s_macro = -1;
37867767Seric }
37967767Seric else
38067767Seric {
38167767Seric MacroName[NextMacroId] = s->s_name;
38267767Seric s->s_macro = mid = NextMacroId++;
38367767Seric }
38467767Seric }
38567767Seric p++;
38667767Seric }
38767767Seric if (ep != NULL)
38867767Seric *ep = p;
38967767Seric if (tTd(35, 14))
39067767Seric printf("0x%x\n", mid);
39167767Seric return mid;
39267767Seric }
39368199Seric /*
39468199Seric ** WORDINCLASS -- tell if a word is in a specific class
39568199Seric **
39668199Seric ** Parameters:
39768398Seric ** str -- the name of the word to look up.
39868199Seric ** cl -- the class name.
39968199Seric **
40068199Seric ** Returns:
40168398Seric ** TRUE if str can be found in cl.
40268199Seric ** FALSE otherwise.
40368199Seric */
40468199Seric
40568199Seric bool
wordinclass(str,cl)40668398Seric wordinclass(str, cl)
40768398Seric char *str;
40868483Seric int cl;
40968199Seric {
41068199Seric register STAB *s;
41168199Seric
41268398Seric s = stab(str, ST_CLASS, ST_FIND);
41368483Seric return s != NULL && bitnset(cl & 0xff, s->s_class);
41468199Seric }
415