122707Sdist /* 234921Sbostic * Copyright (c) 1983 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*68199Seric static char sccsid[] = "@(#)macro.c 8.6 (Berkeley) 01/24/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. 253379Seric ** buflim -- the buffer limit, i.e., the address 263379Seric ** of the last usable position in buf. 276980Seric ** e -- envelope in which to work. 283379Seric ** 293379Seric ** Returns: 309382Seric ** none. 313379Seric ** 323379Seric ** Side Effects: 333379Seric ** none. 343379Seric */ 353379Seric 3660494Seric void 376980Seric expand(s, buf, buflim, e) 386980Seric register char *s; 396980Seric register char *buf; 406980Seric char *buflim; 416980Seric register ENVELOPE *e; 426980Seric { 4317349Seric register char *xp; 446056Seric register char *q; 459382Seric bool skipping; /* set if conditionally skipping output */ 4617349Seric bool recurse = FALSE; /* set if recursion required */ 4717349Seric int i; 4857589Seric int iflev; /* if nesting level */ 496056Seric char xbuf[BUFSIZ]; 503379Seric 5124941Seric if (tTd(35, 24)) 526056Seric { 536056Seric printf("expand("); 546056Seric xputs(s); 556056Seric printf(")\n"); 566056Seric } 573379Seric 583387Seric skipping = FALSE; 5957589Seric iflev = 0; 608064Seric if (s == NULL) 618064Seric s = ""; 6217349Seric for (xp = xbuf; *s != '\0'; s++) 633379Seric { 6464087Seric int c; 654319Seric 664319Seric /* 676056Seric ** Check for non-ordinary (special?) character. 684319Seric ** 'q' will be the interpolated quantity. 694319Seric */ 704319Seric 713379Seric q = NULL; 726056Seric c = *s; 7358050Seric switch (c & 0377) 743387Seric { 756056Seric case CONDIF: /* see if var set */ 7657977Seric c = *++s; 7757977Seric if (skipping) 7857977Seric iflev++; 7957977Seric else 8057589Seric skipping = macvalue(c, e) == NULL; 8157977Seric continue; 823387Seric 836056Seric case CONDELSE: /* change state of skipping */ 8457977Seric if (iflev == 0) 8557589Seric skipping = !skipping; 866056Seric continue; 873387Seric 886056Seric case CONDFI: /* stop skipping */ 8957977Seric if (iflev == 0) 9057589Seric skipping = FALSE; 9157977Seric if (skipping) 9257977Seric iflev--; 9357977Seric continue; 943387Seric 9558050Seric case MACROEXPAND: /* macro interpolation */ 9667767Seric c = *++s & 0377; 9766019Seric if (c != '\0') 9866019Seric q = macvalue(c, e); 9966019Seric else 10066019Seric { 10166019Seric s--; 10266019Seric q = NULL; 10366019Seric } 1049382Seric if (q == NULL) 1053387Seric continue; 1066056Seric break; 1073387Seric } 1083387Seric 1093379Seric /* 1103379Seric ** Interpolate q or output one character 1113379Seric */ 1123379Seric 11317349Seric if (skipping || xp >= &xbuf[sizeof xbuf]) 1143387Seric continue; 11517349Seric if (q == NULL) 11617349Seric *xp++ = c; 11717349Seric else 1186056Seric { 11917349Seric /* copy to end of q or max space remaining in buf */ 12017349Seric while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 1216056Seric { 12258050Seric /* check for any sendmail metacharacters */ 12358050Seric if ((c & 0340) == 0200) 12417349Seric recurse = TRUE; 1256056Seric *xp++ = c; 1266056Seric } 1276056Seric } 1283379Seric } 1296056Seric *xp = '\0'; 1303379Seric 13124941Seric if (tTd(35, 24)) 1326056Seric { 1338064Seric printf("expand ==> "); 1346056Seric xputs(xbuf); 1358064Seric printf("\n"); 1366056Seric } 1373379Seric 1386056Seric /* recurse as appropriate */ 13917349Seric if (recurse) 1409382Seric { 1419382Seric expand(xbuf, buf, buflim, e); 1429382Seric return; 1439382Seric } 1446056Seric 1456056Seric /* copy results out */ 14617349Seric i = buflim - buf - 1; 14717349Seric if (i > xp - xbuf) 14817349Seric i = xp - xbuf; 14917349Seric bcopy(xbuf, buf, i); 15017349Seric buf[i] = '\0'; 1513379Seric } 1523379Seric /* 1533379Seric ** DEFINE -- define a macro. 1543379Seric ** 1553379Seric ** this would be better done using a #define macro. 1563379Seric ** 1573379Seric ** Parameters: 1583379Seric ** n -- the macro name. 1593379Seric ** v -- the macro value. 1609382Seric ** e -- the envelope to store the definition in. 1613379Seric ** 1623379Seric ** Returns: 1633379Seric ** none. 1643379Seric ** 1653379Seric ** Side Effects: 1669382Seric ** e->e_macro[n] is defined. 1674092Seric ** 1684092Seric ** Notes: 1694092Seric ** There is one macro for each ASCII character, 1704092Seric ** although they are not all used. The currently 1714092Seric ** defined macros are: 1724092Seric ** 1734202Seric ** $a date in ARPANET format (preferring the Date: line 1744202Seric ** of the message) 1754202Seric ** $b the current date (as opposed to the date as found 1764202Seric ** the message) in ARPANET format 1774092Seric ** $c hop count 1784202Seric ** $d (current) date in UNIX (ctime) format 17910710Seric ** $e the SMTP entry message+ 1804092Seric ** $f raw from address 1814092Seric ** $g translated from address 1824092Seric ** $h to host 1837851Seric ** $i queue id 1847851Seric ** $j official SMTP hostname, used in messages+ 18557630Seric ** $k UUCP node name 1864092Seric ** $l UNIX-style from line+ 18758319Seric ** $m The domain part of our full name. 1884092Seric ** $n name of sendmail ("MAILER-DAEMON" on local 1894092Seric ** net typically)+ 1904092Seric ** $o delimiters ("operators") for address tokens+ 1914092Seric ** $p my process id in decimal 1925919Seric ** $q the string that becomes an address -- this is 1935919Seric ** normally used to combine $g & $x. 1945187Seric ** $r protocol used to talk to sender 1955187Seric ** $s sender's host name 1964092Seric ** $t the current time in seconds since 1/1/1970 1974092Seric ** $u to user 1984092Seric ** $v version number of sendmail 19910407Seric ** $w our host name (if it can be determined) 2004092Seric ** $x signature (full name) of from person 2014202Seric ** $y the tty id of our terminal 2024092Seric ** $z home directory of to person 20358951Seric ** $_ RFC1413 authenticated sender address 2044092Seric ** 2054092Seric ** Macros marked with + must be defined in the 2064092Seric ** configuration file and are used internally, but 2074092Seric ** are not set. 2084092Seric ** 2094092Seric ** There are also some macros that can be used 2104092Seric ** arbitrarily to make the configuration file 2114092Seric ** cleaner. In general all upper-case letters 2124092Seric ** are available. 2133379Seric */ 2143379Seric 21560494Seric void 2169382Seric define(n, v, e) 21764087Seric int n; 2183379Seric char *v; 2199382Seric register ENVELOPE *e; 2203379Seric { 22124941Seric if (tTd(35, 9)) 2226056Seric { 22367767Seric printf("define(%s as ", macname(n)); 2246056Seric xputs(v); 2256056Seric printf(")\n"); 2266056Seric } 22767767Seric e->e_macro[n & 0377] = v; 2283379Seric } 2294454Seric /* 2304454Seric ** MACVALUE -- return uninterpreted value of a macro. 2314454Seric ** 2324454Seric ** Parameters: 2334454Seric ** n -- the name of the macro. 2344454Seric ** 2354454Seric ** Returns: 2364454Seric ** The value of n. 2374454Seric ** 2384454Seric ** Side Effects: 2394454Seric ** none. 2404454Seric */ 2414454Seric 2424454Seric char * 2438182Seric macvalue(n, e) 24464087Seric int n; 2458182Seric register ENVELOPE *e; 2464454Seric { 24767767Seric n &= 0377; 2488182Seric while (e != NULL) 2498182Seric { 2508182Seric register char *p = e->e_macro[n]; 2518182Seric 2528182Seric if (p != NULL) 2538182Seric return (p); 2548182Seric e = e->e_parent; 2558182Seric } 2568182Seric return (NULL); 2574454Seric } 25867767Seric /* 25967767Seric ** MACNAME -- return the name of a macro given its internal id 26067767Seric ** 26167767Seric ** Parameter: 26267767Seric ** n -- the id of the macro 26367767Seric ** 26467767Seric ** Returns: 26567767Seric ** The name of n. 26667767Seric ** 26767767Seric ** Side Effects: 26867767Seric ** none. 26967767Seric */ 27067767Seric 27167767Seric char * 27267767Seric macname(n) 27367767Seric int n; 27467767Seric { 27567767Seric static char mbuf[2]; 27667767Seric 27767767Seric n &= 0377; 27867767Seric if (bitset(0200, n)) 27967767Seric { 28067767Seric char *p = MacroName[n]; 28167767Seric 28267767Seric if (p != NULL) 28367767Seric return p; 28467767Seric return "***UNDEFINED MACRO***"; 28567767Seric } 28667767Seric mbuf[0] = n; 28767767Seric mbuf[1] = '\0'; 28867767Seric return mbuf; 28967767Seric } 29067767Seric /* 29167767Seric ** MACID -- return id of macro identified by its name 29267767Seric ** 29367767Seric ** Parameters: 29467767Seric ** p -- pointer to name string -- either a single 29567767Seric ** character or {name}. 29667767Seric ** ep -- filled in with the pointer to the byte 29767767Seric ** after the name. 29867767Seric ** 29967767Seric ** Returns: 30067767Seric ** The internal id code for this macro. This will 30167767Seric ** fit into a single byte. 30267767Seric ** 30367767Seric ** Side Effects: 30467767Seric ** If this is a new macro name, a new id is allocated. 30567767Seric */ 30667767Seric 30767767Seric int 30867767Seric macid(p, ep) 30967767Seric register char *p; 31067767Seric char **ep; 31167767Seric { 31267767Seric int mid; 31367767Seric register char *bp; 31467767Seric char mbuf[21]; 31567767Seric 31667767Seric if (tTd(35, 14)) 31767767Seric printf("macid(%s) => ", p); 31867767Seric 31967815Seric if (*p == '\0' || (p[0] == '{' && p[1] == '}')) 32067767Seric { 32167767Seric syserr("Name required for macro/class"); 32267767Seric if (ep != NULL) 32367767Seric *ep = p; 32467767Seric if (tTd(35, 14)) 32567767Seric printf("NULL\n"); 32667767Seric return '\0'; 32767767Seric } 32867767Seric if (*p != '{') 32967767Seric { 33067767Seric /* the macro is its own code */ 33167767Seric if (ep != NULL) 33267767Seric *ep = p + 1; 33367767Seric if (tTd(35, 14)) 33467767Seric printf("%c\n", *p); 33567767Seric return *p; 33667767Seric } 33767767Seric bp = mbuf; 33867767Seric while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf]) 33967815Seric { 34067815Seric if (isascii(*p) && (isalnum(*p) || *p == '_')) 34167815Seric *bp++ = *p; 34267815Seric else 34367815Seric syserr("Invalid macro/class character %c", *p); 34467815Seric } 34567767Seric *bp = '\0'; 34667767Seric mid = -1; 34767767Seric if (*p == '\0') 34867767Seric { 34967767Seric syserr("Unbalanced { on %s", mbuf); /* missing } */ 35067767Seric } 35167767Seric else if (*p != '}') 35267767Seric { 35367767Seric syserr("Macro/class name ({%s}) too long (%d chars max)", 35467767Seric mbuf, sizeof mbuf - 1); 35567767Seric } 35667767Seric else if (mbuf[1] == '\0') 35767767Seric { 35867767Seric /* ${x} == $x */ 35967767Seric mid = mbuf[0]; 36067767Seric p++; 36167767Seric } 36267767Seric else 36367767Seric { 36467767Seric register STAB *s; 36567767Seric 36667767Seric s = stab(mbuf, ST_MACRO, ST_ENTER); 36767767Seric if (s->s_macro != 0) 36867767Seric mid = s->s_macro; 36967767Seric else 37067767Seric { 37167767Seric if (NextMacroId > 0377) 37267767Seric { 37367767Seric syserr("Macro/class {%s}: too many long names", mbuf); 37467767Seric s->s_macro = -1; 37567767Seric } 37667767Seric else 37767767Seric { 37867767Seric MacroName[NextMacroId] = s->s_name; 37967767Seric s->s_macro = mid = NextMacroId++; 38067767Seric } 38167767Seric } 38267767Seric p++; 38367767Seric } 38467767Seric if (ep != NULL) 38567767Seric *ep = p; 38667767Seric if (tTd(35, 14)) 38767767Seric printf("0x%x\n", mid); 38867767Seric return mid; 38967767Seric } 390*68199Seric /* 391*68199Seric ** WORDINCLASS -- tell if a word is in a specific class 392*68199Seric ** 393*68199Seric ** Parameters: 394*68199Seric ** word -- the name of the word to look up. 395*68199Seric ** cl -- the class name. 396*68199Seric ** 397*68199Seric ** Returns: 398*68199Seric ** TRUE if word can be found in cl. 399*68199Seric ** FALSE otherwise. 400*68199Seric */ 401*68199Seric 402*68199Seric bool 403*68199Seric wordinclass(word, cl) 404*68199Seric char *word; 405*68199Seric char cl; 406*68199Seric { 407*68199Seric register STAB *s; 408*68199Seric 409*68199Seric s = stab(word, ST_CLASS, ST_FIND); 410*68199Seric return s != NULL && bitnset(cl, s->s_class); 411*68199Seric } 412