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

📄 parseaddr.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
					}
					dprintf("\n");
				}
				pp = m->match_first;
				while (pp <= m->match_last)
				{
					if (avp >= &npvp[MAXATOM])
					{
						syserr("554 5.3.0 rewrite: expansion too long");
						return EX_DATAERR;
					}
					*avp++ = *pp++;
				}
			}
			else
			{
				/* some sort of replacement */
				if (avp >= &npvp[MAXATOM])
				{
	toolong:
					syserr("554 5.3.0 rewrite: expansion too long");
					return EX_DATAERR;
				}
				if ((*rp & 0377) != MACRODEXPAND)
				{
					/* vanilla replacement */
					*avp++ = rp;
				}
				else
				{
					/* $&x replacement */
					char *mval = macvalue(rp[1], e);
					char **xpvp;
					int trsize = 0;
					static size_t pvpb1_size = 0;
					static char **pvpb1 = NULL;
					char pvpbuf[PSBUFSIZE];

					if (tTd(21, 2))
						dprintf("rewrite: RHS $&%s => \"%s\"\n",
							macname(rp[1]),
							mval == NULL ? "(NULL)" : mval);
					if (mval == NULL || *mval == '\0')
						continue;

					/* save the remainder of the input */
					for (xpvp = pvp; *xpvp != NULL; xpvp++)
						trsize += sizeof *xpvp;
					if ((size_t) trsize > pvpb1_size)
					{
						if (pvpb1 != NULL)
							free(pvpb1);
						pvpb1 = (char **)xalloc(trsize);
						pvpb1_size = trsize;
					}

					memmove((char *) pvpb1,
						(char *) pvp,
						trsize);

					/* scan the new replacement */
					xpvp = prescan(mval, '\0', pvpbuf,
						       sizeof pvpbuf, NULL,
						       NULL);
					if (xpvp == NULL)
					{
						/* prescan pre-printed error */
						return EX_DATAERR;
					}

					/* insert it into the output stream */
					while (*xpvp != NULL)
					{
						if (tTd(21, 19))
							dprintf(" ... %s\n",
								*xpvp);
						*avp++ = newstr(*xpvp);
						if (avp >= &npvp[MAXATOM])
							goto toolong;
						xpvp++;
					}
					if (tTd(21, 19))
						dprintf(" ... DONE\n");

					/* restore the old trailing input */
					memmove((char *) pvp,
						(char *) pvpb1,
						trsize);
				}
			}
		}
		*avp++ = NULL;

		/*
		**  Check for any hostname/keyword lookups.
		*/

		for (rvp = npvp; *rvp != NULL; rvp++)
		{
			char **hbrvp;
			char **xpvp;
			int trsize;
			char *replac;
			int endtoken;
			STAB *map;
			char *mapname;
			char **key_rvp;
			char **arg_rvp;
			char **default_rvp;
			char cbuf[MAXNAME + 1];
			char *pvpb1[MAXATOM + 1];
			char *argvect[10];
			char pvpbuf[PSBUFSIZE];
			char *nullpvp[1];

			if ((**rvp & 0377) != HOSTBEGIN &&
			    (**rvp & 0377) != LOOKUPBEGIN)
				continue;

			/*
			**  Got a hostname/keyword lookup.
			**
			**	This could be optimized fairly easily.
			*/

			hbrvp = rvp;
			if ((**rvp & 0377) == HOSTBEGIN)
			{
				endtoken = HOSTEND;
				mapname = "host";
			}
			else
			{
				endtoken = LOOKUPEND;
				mapname = *++rvp;
			}
			map = stab(mapname, ST_MAP, ST_FIND);
			if (map == NULL)
				syserr("554 5.3.0 rewrite: map %s not found", mapname);

			/* extract the match part */
			key_rvp = ++rvp;
			default_rvp = NULL;
			arg_rvp = argvect;
			xpvp = NULL;
			replac = pvpbuf;
			while (*rvp != NULL && (**rvp & 0377) != endtoken)
			{
				int nodetype = **rvp & 0377;

				if (nodetype != CANONHOST && nodetype != CANONUSER)
				{
					rvp++;
					continue;
				}

				*rvp++ = NULL;

				if (xpvp != NULL)
				{
					cataddr(xpvp, NULL, replac,
						&pvpbuf[sizeof pvpbuf] - replac,
						'\0');
					*++arg_rvp = replac;
					replac += strlen(replac) + 1;
					xpvp = NULL;
				}
				switch (nodetype)
				{
				  case CANONHOST:
					xpvp = rvp;
					break;

				  case CANONUSER:
					default_rvp = rvp;
					break;
				}
			}
			if (*rvp != NULL)
				*rvp++ = NULL;
			if (xpvp != NULL)
			{
				cataddr(xpvp, NULL, replac,
					&pvpbuf[sizeof pvpbuf] - replac,
					'\0');
				*++arg_rvp = replac;
			}
			*++arg_rvp = NULL;

			/* save the remainder of the input string */
			trsize = (int) (avp - rvp + 1) * sizeof *rvp;
			memmove((char *) pvpb1, (char *) rvp, trsize);

			/* look it up */
			cataddr(key_rvp, NULL, cbuf, sizeof cbuf,
				map == NULL ? '\0' : map->s_map.map_spacesub);
			argvect[0] = cbuf;
			replac = map_lookup(map, cbuf, argvect, &rstat, e);

			/* if no replacement, use default */
			if (replac == NULL && default_rvp != NULL)
			{
				/* create the default */
				cataddr(default_rvp, NULL, cbuf, sizeof cbuf, '\0');
				replac = cbuf;
			}

			if (replac == NULL)
			{
				xpvp = key_rvp;
			}
			else if (*replac == '\0')
			{
				/* null replacement */
				nullpvp[0] = NULL;
				xpvp = nullpvp;
			}
			else
			{
				/* scan the new replacement */
				xpvp = prescan(replac, '\0', pvpbuf,
					       sizeof pvpbuf, NULL, NULL);
				if (xpvp == NULL)
				{
					/* prescan already printed error */
					return EX_DATAERR;
				}
			}

			/* append it to the token list */
			for (avp = hbrvp; *xpvp != NULL; xpvp++)
			{
				*avp++ = newstr(*xpvp);
				if (avp >= &npvp[MAXATOM])
					goto toolong;
			}

			/* restore the old trailing information */
			rvp = avp - 1;
			for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )
				if (avp >= &npvp[MAXATOM])
					goto toolong;
		}

		/*
		**  Check for subroutine calls.
		*/

		status = callsubr(npvp, reclevel, e);
		if (rstat == EX_OK || status == EX_TEMPFAIL)
			rstat = status;

		/* copy vector back into original space. */
		for (avp = npvp; *avp++ != NULL;)
			continue;
		memmove((char *) pvp, (char *) npvp,
		      (int) (avp - npvp) * sizeof *avp);

		if (tTd(21, 4))
		{
			dprintf("rewritten as:");
			printav(pvp);
		}
	}

	if (OpMode == MD_TEST)
	{
		printf("%s%-16.16s returns:", prefix, rulename);
		printav(pvp);
	}
	else if (tTd(21, 1))
	{
		dprintf("%s%-16.16s returns:", prefix, rulename);
		printav(pvp);
	}
	return rstat;
}
/*
**  CALLSUBR -- call subroutines in rewrite vector
**
**	Parameters:
**		pvp -- pointer to token vector.
**		reclevel -- the current recursion level.
**		e -- the current envelope.
**
**	Returns:
**		The status from the subroutine call.
**
**	Side Effects:
**		pvp is modified.
*/

static int
callsubr(pvp, reclevel, e)
	char **pvp;
	int reclevel;
	ENVELOPE *e;
{
	char **avp;
	char **rvp;
	register int i;
	int subr;
	int status;
	int rstat = EX_OK;
	char *tpvp[MAXATOM + 1];

	for (avp = pvp; *avp != NULL; avp++)
	{
		if ((**avp & 0377) == CALLSUBR && avp[1] != NULL)
		{
			stripquotes(avp[1]);
			subr = strtorwset(avp[1], NULL, ST_FIND);
			if (subr < 0)
			{
				syserr("Unknown ruleset %s", avp[1]);
				return EX_CONFIG;
			}

			if (tTd(21, 3))
				dprintf("-----callsubr %s (%d)\n",
					avp[1], subr);

			/*
			**  Take care of possible inner calls first.
			**  use a full size temporary buffer to avoid
			**  overflows in rewrite, but strip off the
			**  subroutine call.
			*/

			for (i = 2; avp[i] != NULL; i++)
				tpvp[i - 2] = avp[i];
			tpvp[i - 2] = NULL;

			status = callsubr(tpvp, reclevel, e);
			if (rstat == EX_OK || status == EX_TEMPFAIL)
				rstat = status;

			/*
			**  Now we need to call the ruleset specified for
			**  the subroutine. we can do this with the
			**  temporary buffer that we set up earlier,
			**  since it has all the data we want to rewrite.
			*/

			status = rewrite(tpvp, subr, reclevel, e);
			if (rstat == EX_OK || status == EX_TEMPFAIL)
				rstat = status;

			/*
			**  Find length of tpvp and current offset into
			**  pvp, if the total is greater than MAXATOM,
			**  then it would overflow the buffer if we copied
			**  it back in to pvp, in which case we throw a
			**  fit.
			*/

			for (rvp = tpvp; *rvp != NULL; rvp++)
				continue;
			if (((rvp - tpvp) + (avp - pvp)) > MAXATOM)
			{
				syserr("554 5.3.0 callsubr: expansion too long");
				return EX_DATAERR;
			}

			/*
			**  Now we can copy the rewritten code over
			**  the initial subroutine call in the buffer.
			*/

			for (i = 0; tpvp[i] != NULL; i++)
				avp[i] = tpvp[i];
			avp[i] = NULL;

			/*
			**  If we got this far, we've processed the left
			**  most subroutine, and recursively called ourselves
			**  to handle any other subroutines.  We're done.
			*/

			break;
		}
	}
	return rstat;
}
/*
**  MAP_LOOKUP -- do lookup in map
**
**	Parameters:
**		map -- the map to use for the lookup.
**		key -- the key to look up.
**		argvect -- arguments to pass to the map lookup.
**		pstat -- a pointer to an integer in which to store the
**			status from the lookup.
**		e -- the current envelope.
**
**	Returns:
**		The result of the lookup.
**		NULL -- if there was no data for the given key.
*/

static char *
map_lookup(smap, key, argvect, pstat, e)
	STAB *smap;
	char key[];
	char **argvect;
	int *pstat;
	ENVELOPE *e;
{
	auto int status = EX_OK;
	MAP *map;
	char *replac;

	if (smap == NULL)
		return NULL;

	map = &smap->s_map;
	DYNOPENMAP(map);

	if (e->e_sendmode == SM_DEFER &&
	    bitset(MF_DEFER, map->map_mflags))
	{
		/* don't do any map lookups */
		if (tTd(60, 1))
			dprintf("map_lookup(%s, %s) => DEFERRED\n",
				smap->s_name, key);
		*pstat = EX_TEMPFAIL;
		return NULL;
	}

	if (!bitset(MF_KEEPQUOTES, map->map_mflags))
		stripquotes(key);

	if (tTd(60, 1))
	{
		dprintf("map_lookup(%s, %s", smap->s_name, key);
		if (tTd(60, 5))
		{
			int i;

			for (i = 0; argvect[i] != NULL; i++)
				dprintf(", %%%d=%s", i, argvect[i]);
		}
		dprintf(") => ");
	}
	replac = (*map->map_class->map_lookup)(map, key, argvect, &status);
	if (tTd(60, 1))
		dprintf("%s (%d)\n",
			replac != NULL ? replac : "NOT FOUND",
			status);

	/* should recover if status == EX_TEMPFAIL */
	if (status == EX_TEMPFAIL && !bitset(MF_NODEFER, map->map_mflags))
	{
		*pstat = EX_TEMPFAIL;
		if (tTd(60, 1))
			dprintf("map_lookup(%s, %s) tempfail: errno=%d\n",
				smap->s_name, key, errno);
		if (e->e_message == NULL)
		{
			char mbuf[320];

			snprintf(mbuf, sizeof mbuf,
				"%.80s map: lookup (%s): deferred",
				smap->s_name,
				shortenstring(key, MAXSHORTSTR));
			e->e_message = newstr(mbuf);
		}
	}
	if (status == EX_TEMPFAIL && map->map_tapp != NULL)
	{
		size_t i = strlen(key) + strlen(map->map_tapp) + 1;
		static char *rwbuf = NULL;
		static size_t rwbuflen = 0;

		if (i > rwbuflen)
		{
			if (rwbuf != NULL)
				free(rwbuf);
			rwbuflen = i;
			rwbuf = (char *) xalloc(rwbuflen);
		}
		snprintf(rwbuf, rwbuflen, "%s%s", key, map->map_tapp);
		if (tTd(60, 4))
			dprintf("map_lookup tempfail: returning \"%s\"\n",
				rwbuf);
		return rwbuf;
	}
	return replac;
}
/*
**  INITERRMAILERS -- initialize error and discard mailers
**
**	Parameters:
**		none.
**
**	Returns:
**		none.
**
**	Side Effects:
**		initializes error and discard mailers.
*/

static MAILER discardmailer;
static MAILER errormailer;
static char *discardargv[] = { "DISCARD", NULL };
static char *errorargv[] = { "ERROR", NULL };

void
initerrmailers()
{
	if (discardmailer.m_name == NULL)
	{
		/* initialize the discard mailer */
		discardmailer.m_name = "*discard*";
		discardmailer.m_mailer = "DISCARD";
		discardmailer.m_argv = discardargv;
	}
	if (errormailer.m_name == NULL)
	{
		/* initialize the bogus mailer */
		errormailer.m_name = "*error*";
		errormailer.m_mailer = "ERROR";
		errormailer.m_argv = errorargv;
	}
}
/*
**  BUILDADDR -- build address from token vector.
**
**	Parameters:
**		tv -- token vector.
**		a -- pointer to address descriptor to fill.
**			If NULL, one will be allocated.
**		flags -- info regarding whether this is a sender or
**			a recipient.
**		e -- the current envelope.
**
**	Returns:
**		NULL if there was an error.
**		'a' otherwise.
**
**	Side Effects:
**		fills in 'a'
*/

static struct errcodes
{
	char	*ec_name;		/* name of error code */
	int	ec_code;		/* numeric code */
} ErrorCodes[] =
{
	{ "usage",		EX_USAGE	},
	{ "nouser",		EX_NOUSER	},
	{ "nohost",		EX_NOHOST	},
	{ "unavailable",	EX_UNAVAILABLE	},

⌨️ 快捷键说明

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