122707Sdist /* 2*68839Seric * 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*68839Seric static char sccsid[] = "@(#)macro.c 8.11 (Berkeley) 04/21/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 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 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 * 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 * 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 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)) 31667767Seric printf("macid(%s) => ", p); 31767767Seric 31867815Seric if (*p == '\0' || (p[0] == '{' && p[1] == '}')) 31967767Seric { 32067767Seric syserr("Name required for macro/class"); 32167767Seric if (ep != NULL) 32267767Seric *ep = p; 32367767Seric if (tTd(35, 14)) 32467767Seric printf("NULL\n"); 32567767Seric return '\0'; 32667767Seric } 32767767Seric if (*p != '{') 32867767Seric { 32967767Seric /* the macro is its own code */ 33067767Seric if (ep != NULL) 33167767Seric *ep = p + 1; 33267767Seric if (tTd(35, 14)) 33367767Seric printf("%c\n", *p); 33467767Seric return *p; 33567767Seric } 33667767Seric bp = mbuf; 33767767Seric while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf]) 33867815Seric { 33967815Seric if (isascii(*p) && (isalnum(*p) || *p == '_')) 34067815Seric *bp++ = *p; 34167815Seric else 34267815Seric syserr("Invalid macro/class character %c", *p); 34367815Seric } 34467767Seric *bp = '\0'; 34567767Seric mid = -1; 34667767Seric if (*p == '\0') 34767767Seric { 34867767Seric syserr("Unbalanced { on %s", mbuf); /* missing } */ 34967767Seric } 35067767Seric else if (*p != '}') 35167767Seric { 35267767Seric syserr("Macro/class name ({%s}) too long (%d chars max)", 35367767Seric mbuf, sizeof mbuf - 1); 35467767Seric } 35567767Seric else if (mbuf[1] == '\0') 35667767Seric { 35767767Seric /* ${x} == $x */ 35867767Seric mid = mbuf[0]; 35967767Seric p++; 36067767Seric } 36167767Seric else 36267767Seric { 36367767Seric register STAB *s; 36467767Seric 36567767Seric s = stab(mbuf, ST_MACRO, ST_ENTER); 36667767Seric if (s->s_macro != 0) 36767767Seric mid = s->s_macro; 36867767Seric else 36967767Seric { 37067767Seric if (NextMacroId > 0377) 37167767Seric { 37267767Seric syserr("Macro/class {%s}: too many long names", mbuf); 37367767Seric s->s_macro = -1; 37467767Seric } 37567767Seric else 37667767Seric { 37767767Seric MacroName[NextMacroId] = s->s_name; 37867767Seric s->s_macro = mid = NextMacroId++; 37967767Seric } 38067767Seric } 38167767Seric p++; 38267767Seric } 38367767Seric if (ep != NULL) 38467767Seric *ep = p; 38567767Seric if (tTd(35, 14)) 38667767Seric printf("0x%x\n", mid); 38767767Seric return mid; 38867767Seric } 38968199Seric /* 39068199Seric ** WORDINCLASS -- tell if a word is in a specific class 39168199Seric ** 39268199Seric ** Parameters: 39368398Seric ** str -- the name of the word to look up. 39468199Seric ** cl -- the class name. 39568199Seric ** 39668199Seric ** Returns: 39768398Seric ** TRUE if str can be found in cl. 39868199Seric ** FALSE otherwise. 39968199Seric */ 40068199Seric 40168199Seric bool 40268398Seric wordinclass(str, cl) 40368398Seric char *str; 40468483Seric int cl; 40568199Seric { 40668199Seric register STAB *s; 40768199Seric 40868398Seric s = stab(str, ST_CLASS, ST_FIND); 40968483Seric return s != NULL && bitnset(cl & 0xff, s->s_class); 41068199Seric } 411