macro.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:8k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  3.  * All rights reserved.
  4.  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
  5.  * Copyright (c) 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * By using this file, you agree to the terms and conditions set
  9.  * forth in the LICENSE file which can be found at the top level of
  10.  * the sendmail distribution.
  11.  *
  12.  */
  13. #ifndef lint
  14. static char id[] = "@(#)$Id: macro.c,v 8.40 1999/11/22 19:10:16 gshapiro Exp $";
  15. #endif /* ! lint */
  16. #include <sendmail.h>
  17. char *MacroName[256]; /* macro id to name table */
  18. int NextMacroId = 0240; /* codes for long named macros */
  19. /*
  20. **  EXPAND -- macro expand a string using $x escapes.
  21. **
  22. ** Parameters:
  23. ** s -- the string to expand.
  24. ** buf -- the place to put the expansion.
  25. ** bufsize -- the size of the buffer.
  26. ** e -- envelope in which to work.
  27. **
  28. ** Returns:
  29. ** none.
  30. **
  31. ** Side Effects:
  32. ** none.
  33. */
  34. void
  35. expand(s, buf, bufsize, e)
  36. register char *s;
  37. register char *buf;
  38. size_t bufsize;
  39. register ENVELOPE *e;
  40. {
  41. register char *xp;
  42. register char *q;
  43. bool skipping; /* set if conditionally skipping output */
  44. bool recurse = FALSE; /* set if recursion required */
  45. int i;
  46. int skiplev; /* skipping nesting level */
  47. int iflev; /* if nesting level */
  48. char xbuf[MACBUFSIZE];
  49. static int explevel = 0;
  50. if (tTd(35, 24))
  51. {
  52. dprintf("expand(");
  53. xputs(s);
  54. dprintf(")n");
  55. }
  56. skipping = FALSE;
  57. skiplev = 0;
  58. iflev = 0;
  59. if (s == NULL)
  60. s = "";
  61. for (xp = xbuf; *s != ''; s++)
  62. {
  63. int c;
  64. /*
  65. **  Check for non-ordinary (special?) character.
  66. ** 'q' will be the interpolated quantity.
  67. */
  68. q = NULL;
  69. c = *s;
  70. switch (c & 0377)
  71. {
  72.   case CONDIF: /* see if var set */
  73. iflev++;
  74. c = *++s;
  75. if (skipping)
  76. skiplev++;
  77. else
  78. {
  79. char *mv;
  80. mv = macvalue(c, e);
  81. skipping = (mv == NULL || *mv == '');
  82. }
  83. continue;
  84.   case CONDELSE: /* change state of skipping */
  85. if (iflev == 0)
  86. break;
  87. if (skiplev == 0)
  88. skipping = !skipping;
  89. continue;
  90.   case CONDFI: /* stop skipping */
  91. if (iflev == 0)
  92. break;
  93. iflev--;
  94. if (skiplev == 0)
  95. skipping = FALSE;
  96. if (skipping)
  97. skiplev--;
  98. continue;
  99.   case MACROEXPAND: /* macro interpolation */
  100. c = *++s & 0377;
  101. if (c != '')
  102. q = macvalue(c, e);
  103. else
  104. {
  105. s--;
  106. q = NULL;
  107. }
  108. if (q == NULL)
  109. continue;
  110. break;
  111. }
  112. /*
  113. **  Interpolate q or output one character
  114. */
  115. if (skipping || xp >= &xbuf[sizeof xbuf - 1])
  116. continue;
  117. if (q == NULL)
  118. *xp++ = c;
  119. else
  120. {
  121. /* copy to end of q or max space remaining in buf */
  122. while ((c = *q++) != '' && xp < &xbuf[sizeof xbuf - 1])
  123. {
  124. /* check for any sendmail metacharacters */
  125. if ((c & 0340) == 0200)
  126. recurse = TRUE;
  127. *xp++ = c;
  128. }
  129. }
  130. }
  131. *xp = '';
  132. if (tTd(35, 24))
  133. {
  134. dprintf("expand ==> ");
  135. xputs(xbuf);
  136. dprintf("n");
  137. }
  138. /* recurse as appropriate */
  139. if (recurse)
  140. {
  141. if (explevel < MaxMacroRecursion)
  142. {
  143. explevel++;
  144. expand(xbuf, buf, bufsize, e);
  145. explevel--;
  146. return;
  147. }
  148. syserr("expand: recursion too deep (%d max)",
  149. MaxMacroRecursion);
  150. }
  151. /* copy results out */
  152. i = xp - xbuf;
  153. if (i >= bufsize)
  154. i = bufsize - 1;
  155. memmove(buf, xbuf, i);
  156. buf[i] = '';
  157. }
  158. /*
  159. **  DEFINE -- define a macro.
  160. **
  161. ** this would be better done using a #define macro.
  162. **
  163. ** Parameters:
  164. ** n -- the macro name.
  165. ** v -- the macro value.
  166. ** e -- the envelope to store the definition in.
  167. **
  168. ** Returns:
  169. ** none.
  170. **
  171. ** Side Effects:
  172. ** e->e_macro[n] is defined.
  173. **
  174. ** Notes:
  175. ** There is one macro for each ASCII character,
  176. ** although they are not all used.  The currently
  177. ** defined macros are:
  178. **
  179. ** $a   date in ARPANET format (preferring the Date: line
  180. **      of the message)
  181. ** $b   the current date (as opposed to the date as found
  182. **      the message) in ARPANET format
  183. ** $c   hop count
  184. ** $d   (current) date in UNIX (ctime) format
  185. ** $e   the SMTP entry message+
  186. ** $f   raw from address
  187. ** $g   translated from address
  188. ** $h   to host
  189. ** $i   queue id
  190. ** $j   official SMTP hostname, used in messages+
  191. ** $k   UUCP node name
  192. ** $l   UNIX-style from line+
  193. ** $m   The domain part of our full name.
  194. ** $n   name of sendmail ("MAILER-DAEMON" on local
  195. **      net typically)+
  196. ** $o   delimiters ("operators") for address tokens+
  197. **      (set via OperatorChars option in V6 or later
  198. **       sendmail.cf files)
  199. ** $p   my process id in decimal
  200. ** $q   the string that becomes an address -- this is
  201. **      normally used to combine $g & $x.
  202. ** $r   protocol used to talk to sender
  203. ** $s   sender's host name
  204. ** $t   the current time in seconds since 1/1/1970
  205. ** $u   to user
  206. ** $v   version number of sendmail
  207. ** $w   our host name (if it can be determined)
  208. ** $x   signature (full name) of from person
  209. ** $y   the tty id of our terminal
  210. ** $z   home directory of to person
  211. ** $_   RFC1413 authenticated sender address
  212. **
  213. ** Macros marked with + must be defined in the
  214. ** configuration file and are used internally, but
  215. ** are not set.
  216. **
  217. ** There are also some macros that can be used
  218. ** arbitrarily to make the configuration file
  219. ** cleaner.  In general all upper-case letters
  220. ** are available.
  221. */
  222. void
  223. define(n, v, e)
  224. int n;
  225. char *v;
  226. register ENVELOPE *e;
  227. {
  228. int m;
  229. m = n & 0377;
  230. if (tTd(35, 9))
  231. {
  232. dprintf("%sdefine(%s as ",
  233. (e->e_macro[m] == NULL) ? ""
  234. : "re", macname(n));
  235. xputs(v);
  236. dprintf(")n");
  237. }
  238. e->e_macro[m] = v;
  239. #if _FFR_RESET_MACRO_GLOBALS
  240. switch (m)
  241. {
  242.   case 'j':
  243. MyHostName = v;
  244. break;
  245. }
  246. #endif /* _FFR_RESET_MACRO_GLOBALS */
  247. }
  248. /*
  249. **  MACVALUE -- return uninterpreted value of a macro.
  250. **
  251. ** Parameters:
  252. ** n -- the name of the macro.
  253. **
  254. ** Returns:
  255. ** The value of n.
  256. **
  257. ** Side Effects:
  258. ** none.
  259. */
  260. char *
  261. macvalue(n, e)
  262. int n;
  263. register ENVELOPE *e;
  264. {
  265. n &= 0377;
  266. while (e != NULL)
  267. {
  268. register char *p = e->e_macro[n];
  269. if (p != NULL)
  270. return p;
  271. e = e->e_parent;
  272. }
  273. return NULL;
  274. }
  275. /*
  276. **  MACNAME -- return the name of a macro given its internal id
  277. **
  278. ** Parameter:
  279. ** n -- the id of the macro
  280. **
  281. ** Returns:
  282. ** The name of n.
  283. **
  284. ** Side Effects:
  285. ** none.
  286. */
  287. char *
  288. macname(n)
  289. int n;
  290. {
  291. static char mbuf[2];
  292. n &= 0377;
  293. if (bitset(0200, n))
  294. {
  295. char *p = MacroName[n];
  296. if (p != NULL)
  297. return p;
  298. return "***UNDEFINED MACRO***";
  299. }
  300. mbuf[0] = n;
  301. mbuf[1] = '';
  302. return mbuf;
  303. }
  304. /*
  305. **  MACID -- return id of macro identified by its name
  306. **
  307. ** Parameters:
  308. ** p -- pointer to name string -- either a single
  309. ** character or {name}.
  310. ** ep -- filled in with the pointer to the byte
  311. ** after the name.
  312. **
  313. ** Returns:
  314. ** The internal id code for this macro.  This will
  315. ** fit into a single byte.
  316. **
  317. ** Side Effects:
  318. ** If this is a new macro name, a new id is allocated.
  319. */
  320. int
  321. macid(p, ep)
  322. register char *p;
  323. char **ep;
  324. {
  325. int mid;
  326. register char *bp;
  327. char mbuf[MAXMACNAMELEN + 1];
  328. if (tTd(35, 14))
  329. {
  330. dprintf("macid(");
  331. xputs(p);
  332. dprintf(") => ");
  333. }
  334. if (*p == '' || (p[0] == '{' && p[1] == '}'))
  335. {
  336. syserr("Name required for macro/class");
  337. if (ep != NULL)
  338. *ep = p;
  339. if (tTd(35, 14))
  340. dprintf("NULLn");
  341. return '';
  342. }
  343. if (*p != '{')
  344. {
  345. /* the macro is its own code */
  346. if (ep != NULL)
  347. *ep = p + 1;
  348. if (tTd(35, 14))
  349. dprintf("%cn", *p);
  350. return *p;
  351. }
  352. bp = mbuf;
  353. while (*++p != '' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
  354. {
  355. if (isascii(*p) && (isalnum(*p) || *p == '_'))
  356. *bp++ = *p;
  357. else
  358. syserr("Invalid macro/class character %c", *p);
  359. }
  360. *bp = '';
  361. mid = -1;
  362. if (*p == '')
  363. {
  364. syserr("Unbalanced { on %s", mbuf); /* missing } */
  365. }
  366. else if (*p != '}')
  367. {
  368. syserr("Macro/class name ({%s}) too long (%d chars max)",
  369. mbuf, sizeof mbuf - 1);
  370. }
  371. else if (mbuf[1] == '')
  372. {
  373. /* ${x} == $x */
  374. mid = mbuf[0];
  375. p++;
  376. }
  377. else
  378. {
  379. register STAB *s;
  380. s = stab(mbuf, ST_MACRO, ST_ENTER);
  381. if (s->s_macro != 0)
  382. mid = s->s_macro;
  383. else
  384. {
  385. if (NextMacroId > MAXMACROID)
  386. {
  387. syserr("Macro/class {%s}: too many long names", mbuf);
  388. s->s_macro = -1;
  389. }
  390. else
  391. {
  392. MacroName[NextMacroId] = s->s_name;
  393. s->s_macro = mid = NextMacroId++;
  394. }
  395. }
  396. p++;
  397. }
  398. if (ep != NULL)
  399. *ep = p;
  400. if (tTd(35, 14))
  401. dprintf("0x%xn", mid);
  402. return mid;
  403. }
  404. /*
  405. **  WORDINCLASS -- tell if a word is in a specific class
  406. **
  407. ** Parameters:
  408. ** str -- the name of the word to look up.
  409. ** cl -- the class name.
  410. **
  411. ** Returns:
  412. ** TRUE if str can be found in cl.
  413. ** FALSE otherwise.
  414. */
  415. bool
  416. wordinclass(str, cl)
  417. char *str;
  418. int cl;
  419. {
  420. register STAB *s;
  421. s = stab(str, ST_CLASS, ST_FIND);
  422. return s != NULL && bitnset(cl & 0xff, s->s_class);
  423. }