⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macro.c

📁 < linux网络编程工具>>配套源码
💻 C
字号:
/*
 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
 * Copyright (c) 1988, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 */

#ifndef lint
static char id[] = "@(#)$Id: macro.c,v 8.40.16.2 2000/09/17 17:04:26 gshapiro Exp $";
#endif /* ! lint */

#include <sendmail.h>

char	*MacroName[256];	/* macro id to name table */
int	NextMacroId = 0240;	/* codes for long named macros */


/*
**  EXPAND -- macro expand a string using $x escapes.
**
**	Parameters:
**		s -- the string to expand.
**		buf -- the place to put the expansion.
**		bufsize -- the size of the buffer.
**		e -- envelope in which to work.
**
**	Returns:
**		none.
**
**	Side Effects:
**		none.
*/

void
expand(s, buf, bufsize, e)
	register char *s;
	register char *buf;
	size_t bufsize;
	register ENVELOPE *e;
{
	register char *xp;
	register char *q;
	bool skipping;		/* set if conditionally skipping output */
	bool recurse = FALSE;	/* set if recursion required */
	int i;
	int skiplev;		/* skipping nesting level */
	int iflev;		/* if nesting level */
	char xbuf[MACBUFSIZE];
	static int explevel = 0;

	if (tTd(35, 24))
	{
		dprintf("expand(");
		xputs(s);
		dprintf(")\n");
	}

	skipping = FALSE;
	skiplev = 0;
	iflev = 0;
	if (s == NULL)
		s = "";
	for (xp = xbuf; *s != '\0'; s++)
	{
		int c;

		/*
		**  Check for non-ordinary (special?) character.
		**	'q' will be the interpolated quantity.
		*/

		q = NULL;
		c = *s;
		switch (c & 0377)
		{
		  case CONDIF:		/* see if var set */
			iflev++;
			c = *++s;
			if (skipping)
				skiplev++;
			else
			{
				char *mv;

				mv = macvalue(c, e);
				skipping = (mv == NULL || *mv == '\0');
			}
			continue;

		  case CONDELSE:	/* change state of skipping */
			if (iflev == 0)
				break;
			if (skiplev == 0)
				skipping = !skipping;
			continue;

		  case CONDFI:		/* stop skipping */
			if (iflev == 0)
				break;
			iflev--;
			if (skiplev == 0)
				skipping = FALSE;
			if (skipping)
				skiplev--;
			continue;

		  case MACROEXPAND:	/* macro interpolation */
			c = *++s & 0377;
			if (c != '\0')
				q = macvalue(c, e);
			else
			{
				s--;
				q = NULL;
			}
			if (q == NULL)
				continue;
			break;
		}

		/*
		**  Interpolate q or output one character
		*/

		if (skipping || xp >= &xbuf[sizeof xbuf - 1])
			continue;
		if (q == NULL)
			*xp++ = c;
		else
		{
			/* copy to end of q or max space remaining in buf */
			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
			{
				/* check for any sendmail metacharacters */
				if ((c & 0340) == 0200)
					recurse = TRUE;
				*xp++ = c;
			}
		}
	}
	*xp = '\0';

	if (tTd(35, 24))
	{
		dprintf("expand ==> ");
		xputs(xbuf);
		dprintf("\n");
	}

	/* recurse as appropriate */
	if (recurse)
	{
		if (explevel < MaxMacroRecursion)
		{
			explevel++;
			expand(xbuf, buf, bufsize, e);
			explevel--;
			return;
		}
		syserr("expand: recursion too deep (%d max)",
			MaxMacroRecursion);
	}

	/* copy results out */
	i = xp - xbuf;
	if ((size_t)i >= bufsize)
		i = bufsize - 1;
	memmove(buf, xbuf, i);
	buf[i] = '\0';
}
/*
**  DEFINE -- define a macro.
**
**	this would be better done using a #define macro.
**
**	Parameters:
**		n -- the macro name.
**		v -- the macro value.
**		e -- the envelope to store the definition in.
**
**	Returns:
**		none.
**
**	Side Effects:
**		e->e_macro[n] is defined.
**
**	Notes:
**		There is one macro for each ASCII character,
**		although they are not all used.  The currently
**		defined macros are:
**
**		$a   date in ARPANET format (preferring the Date: line
**		     of the message)
**		$b   the current date (as opposed to the date as found
**		     the message) in ARPANET format
**		$c   hop count
**		$d   (current) date in UNIX (ctime) format
**		$e   the SMTP entry message+
**		$f   raw from address
**		$g   translated from address
**		$h   to host
**		$i   queue id
**		$j   official SMTP hostname, used in messages+
**		$k   UUCP node name
**		$l   UNIX-style from line+
**		$m   The domain part of our full name.
**		$n   name of sendmail ("MAILER-DAEMON" on local
**		     net typically)+
**		$o   delimiters ("operators") for address tokens+
**		     (set via OperatorChars option in V6 or later
**		      sendmail.cf files)
**		$p   my process id in decimal
**		$q   the string that becomes an address -- this is
**		     normally used to combine $g & $x.
**		$r   protocol used to talk to sender
**		$s   sender's host name
**		$t   the current time in seconds since 1/1/1970
**		$u   to user
**		$v   version number of sendmail
**		$w   our host name (if it can be determined)
**		$x   signature (full name) of from person
**		$y   the tty id of our terminal
**		$z   home directory of to person
**		$_   RFC1413 authenticated sender address
**
**		Macros marked with + must be defined in the
**		configuration file and are used internally, but
**		are not set.
**
**		There are also some macros that can be used
**		arbitrarily to make the configuration file
**		cleaner.  In general all upper-case letters
**		are available.
*/

void
define(n, v, e)
	int n;
	char *v;
	register ENVELOPE *e;
{
	int m;

	m = n & 0377;
	if (tTd(35, 9))
	{
		dprintf("%sdefine(%s as ",
			(e->e_macro[m] == NULL) ? ""
						: "re", macname(n));
		xputs(v);
		dprintf(")\n");
	}
	e->e_macro[m] = v;

#if _FFR_RESET_MACRO_GLOBALS
	switch (m)
	{
	  case 'j':
		MyHostName = v;
		break;
	}
#endif /* _FFR_RESET_MACRO_GLOBALS */
}
/*
**  MACVALUE -- return uninterpreted value of a macro.
**
**	Parameters:
**		n -- the name of the macro.
**
**	Returns:
**		The value of n.
**
**	Side Effects:
**		none.
*/

char *
macvalue(n, e)
	int n;
	register ENVELOPE *e;
{
	n &= 0377;
	while (e != NULL)
	{
		register char *p = e->e_macro[n];

		if (p != NULL)
			return p;
		e = e->e_parent;
	}
	return NULL;
}
/*
**  MACNAME -- return the name of a macro given its internal id
**
**	Parameter:
**		n -- the id of the macro
**
**	Returns:
**		The name of n.
**
**	Side Effects:
**		none.
*/

char *
macname(n)
	int n;
{
	static char mbuf[2];

	n &= 0377;
	if (bitset(0200, n))
	{
		char *p = MacroName[n];

		if (p != NULL)
			return p;
		return "***UNDEFINED MACRO***";
	}
	mbuf[0] = n;
	mbuf[1] = '\0';
	return mbuf;
}
/*
**  MACID -- return id of macro identified by its name
**
**	Parameters:
**		p -- pointer to name string -- either a single
**			character or {name}.
**		ep -- filled in with the pointer to the byte
**			after the name.
**
**	Returns:
**		The internal id code for this macro.  This will
**		fit into a single byte.
**
**	Side Effects:
**		If this is a new macro name, a new id is allocated.
*/

int
macid(p, ep)
	register char *p;
	char **ep;
{
	int mid;
	register char *bp;
	char mbuf[MAXMACNAMELEN + 1];

	if (tTd(35, 14))
	{
		dprintf("macid(");
		xputs(p);
		dprintf(") => ");
	}

	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
	{
		syserr("Name required for macro/class");
		if (ep != NULL)
			*ep = p;
		if (tTd(35, 14))
			dprintf("NULL\n");
		return '\0';
	}
	if (*p != '{')
	{
		/* the macro is its own code */
		if (ep != NULL)
			*ep = p + 1;
		if (tTd(35, 14))
			dprintf("%c\n", *p);
		return *p;
	}
	bp = mbuf;
	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
	{
		if (isascii(*p) && (isalnum(*p) || *p == '_'))
			*bp++ = *p;
		else
			syserr("Invalid macro/class character %c", *p);
	}
	*bp = '\0';
	mid = -1;
	if (*p == '\0')
	{
		syserr("Unbalanced { on %s", mbuf);	/* missing } */
	}
	else if (*p != '}')
	{
		syserr("Macro/class name ({%s}) too long (%d chars max)",
			mbuf, sizeof mbuf - 1);
	}
	else if (mbuf[1] == '\0')
	{
		/* ${x} == $x */
		mid = mbuf[0];
		p++;
	}
	else
	{
		register STAB *s;

		s = stab(mbuf, ST_MACRO, ST_ENTER);
		if (s->s_macro != 0)
			mid = s->s_macro;
		else
		{
			if (NextMacroId > MAXMACROID)
			{
				syserr("Macro/class {%s}: too many long names", mbuf);
				s->s_macro = -1;
			}
			else
			{
				MacroName[NextMacroId] = s->s_name;
				s->s_macro = mid = NextMacroId++;
			}
		}
		p++;
	}
	if (ep != NULL)
		*ep = p;
	if (tTd(35, 14))
		dprintf("0x%x\n", mid);
	return mid;
}
/*
**  WORDINCLASS -- tell if a word is in a specific class
**
**	Parameters:
**		str -- the name of the word to look up.
**		cl -- the class name.
**
**	Returns:
**		TRUE if str can be found in cl.
**		FALSE otherwise.
*/

bool
wordinclass(str, cl)
	char *str;
	int cl;
{
	register STAB *s;

	s = stab(str, ST_CLASS, ST_FIND);
	return s != NULL && bitnset(cl & 0xff, s->s_class);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -