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

📄 parseaddr.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
**		name -- the name to translate.
**		m -- the mailer that we want to do rewriting relative
**			to.
**		flags -- fine tune operations.
**		pstat -- pointer to status word.
**		e -- the current envelope.
**
**	Returns:
**		the text string representing this address relative to
**			the receiving mailer.
**
**	Side Effects:
**		none.
**
**	Warnings:
**		The text string returned is tucked away locally;
**			copy it if you intend to save it.
*/

char *
remotename(name, m, flags, pstat, e)
	char *name;
	struct mailer *m;
	int flags;
	int *pstat;
	register ENVELOPE *e;
{
	register char **pvp;
	char *fancy;
	char *oldg = macvalue('g', e);
	int rwset;
	static char buf[MAXNAME + 1];
	char lbuf[MAXNAME + 1];
	char pvpbuf[PSBUFSIZE];
#if _FFR_ADDR_TYPE
	char addrtype[4];
#endif /* _FFR_ADDR_TYPE */

	if (tTd(12, 1))
		dprintf("remotename(%s)\n", name);

	/* don't do anything if we are tagging it as special */
	if (bitset(RF_SENDERADDR, flags))
	{
		rwset = bitset(RF_HEADERADDR, flags) ? m->m_sh_rwset
						     : m->m_se_rwset;
#if _FFR_ADDR_TYPE
		addrtype[2] = 's';
#endif /* _FFR_ADDR_TYPE */
	}
	else
	{
		rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset
						     : m->m_re_rwset;
#if _FFR_ADDR_TYPE
		addrtype[2] = 'r';
#endif /* _FFR_ADDR_TYPE */
	}
	if (rwset < 0)
		return name;
#if _FFR_ADDR_TYPE
	addrtype[1] = ' ';
	addrtype[3] = '\0';
	addrtype[0] = bitset(RF_HEADERADDR, flags) ? 'h' : 'e';
	define(macid("{addr_type}", NULL), addrtype, e);
#endif /* _FFR_ADDR_TYPE */

	/*
	**  Do a heuristic crack of this name to extract any comment info.
	**	This will leave the name as a comment and a $g macro.
	*/

	if (bitset(RF_CANONICAL, flags) || bitnset(M_NOCOMMENT, m->m_flags))
		fancy = "\201g";
	else
		fancy = crackaddr(name);

	/*
	**  Turn the name into canonical form.
	**	Normally this will be RFC 822 style, i.e., "user@domain".
	**	If this only resolves to "user", and the "C" flag is
	**	specified in the sending mailer, then the sender's
	**	domain will be appended.
	*/

	pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
	if (pvp == NULL)
		return name;
	if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
		*pstat = EX_TEMPFAIL;
	if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL)
	{
		/* append from domain to this address */
		register char **pxp = pvp;
		int l = MAXATOM;	/* size of buffer for pvp */

		/* see if there is an "@domain" in the current name */
		while (*pxp != NULL && strcmp(*pxp, "@") != 0)
		{
			pxp++;
			--l;
		}
		if (*pxp == NULL)
		{
			/* no.... append the "@domain" from the sender */
			register char **qxq = e->e_fromdomain;

			while ((*pxp++ = *qxq++) != NULL)
			{
				if (--l <= 0)
				{
					*--pxp = NULL;
					usrerr("553 5.1.0 remotename: too many tokens");
					*pstat = EX_UNAVAILABLE;
					break;
				}
			}
			if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
				*pstat = EX_TEMPFAIL;
		}
	}

	/*
	**  Do more specific rewriting.
	**	Rewrite using ruleset 1 or 2 depending on whether this is
	**		a sender address or not.
	**	Then run it through any receiving-mailer-specific rulesets.
	*/

	if (bitset(RF_SENDERADDR, flags))
	{
		if (rewrite(pvp, 1, 0, e) == EX_TEMPFAIL)
			*pstat = EX_TEMPFAIL;
	}
	else
	{
		if (rewrite(pvp, 2, 0, e) == EX_TEMPFAIL)
			*pstat = EX_TEMPFAIL;
	}
	if (rwset > 0)
	{
		if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL)
			*pstat = EX_TEMPFAIL;
	}

	/*
	**  Do any final sanitation the address may require.
	**	This will normally be used to turn internal forms
	**	(e.g., user@host.LOCAL) into external form.  This
	**	may be used as a default to the above rules.
	*/

	if (rewrite(pvp, 4, 0, e) == EX_TEMPFAIL)
		*pstat = EX_TEMPFAIL;

	/*
	**  Now restore the comment information we had at the beginning.
	*/

	cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
	define('g', lbuf, e);

	/* need to make sure route-addrs have <angle brackets> */
	if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
		expand("<\201g>", buf, sizeof buf, e);
	else
		expand(fancy, buf, sizeof buf, e);

	define('g', oldg, e);

	if (tTd(12, 1))
		dprintf("remotename => `%s'\n", buf);
	return buf;
}
/*
**  MAPLOCALUSER -- run local username through ruleset 5 for final redirection
**
**	Parameters:
**		a -- the address to map (but just the user name part).
**		sendq -- the sendq in which to install any replacement
**			addresses.
**		aliaslevel -- the alias nesting depth.
**		e -- the envelope.
**
**	Returns:
**		none.
*/

#define Q_COPYFLAGS	(QPRIMARY|QBOGUSSHELL|QUNSAFEADDR|\
			 Q_PINGFLAGS|QHASNOTIFY|\
			 QRELAYED|QEXPANDED|QDELIVERED|QDELAYED)

void
maplocaluser(a, sendq, aliaslevel, e)
	register ADDRESS *a;
	ADDRESS **sendq;
	int aliaslevel;
	ENVELOPE *e;
{
	register char **pvp;
	register ADDRESS *a1 = NULL;
	auto char *delimptr;
	char pvpbuf[PSBUFSIZE];

	if (tTd(29, 1))
	{
		dprintf("maplocaluser: ");
		printaddr(a, FALSE);
	}
	pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr, NULL);
	if (pvp == NULL)
	{
		if (tTd(29, 9))
			dprintf("maplocaluser: cannot prescan %s\n",
				a->q_user);
		return;
	}

	define('h', a->q_host, e);
	define('u', a->q_user, e);
	define('z', a->q_home, e);

#if _FFR_ADDR_TYPE
	define(macid("{addr_type}", NULL), "e r", e);
#endif /* _FFR_ADDR_TYPE */
	if (rewrite(pvp, 5, 0, e) == EX_TEMPFAIL)
	{
		if (tTd(29, 9))
			dprintf("maplocaluser: rewrite tempfail\n");
		a->q_state = QS_QUEUEUP;
		a->q_status = "4.4.3";
		return;
	}
	if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
	{
		if (tTd(29, 9))
			dprintf("maplocaluser: doesn't resolve\n");
		return;
	}

	/* if non-null, mailer destination specified -- has it changed? */
	a1 = buildaddr(pvp, NULL, 0, e);
	if (a1 == NULL || sameaddr(a, a1))
	{
		if (tTd(29, 9))
			dprintf("maplocaluser: address unchanged\n");
		if (a1 != NULL)
			free(a1);
		return;
	}

	/* make new address take on flags and print attributes of old */
	a1->q_flags &= ~Q_COPYFLAGS;
	a1->q_flags |= a->q_flags & Q_COPYFLAGS;
	a1->q_paddr = newstr(a->q_paddr);
	a1->q_orcpt = a->q_orcpt;

	/* mark old address as dead; insert new address */
	a->q_state = QS_REPLACED;
	if (tTd(29, 5))
	{
		dprintf("maplocaluser: QS_REPLACED ");
		printaddr(a, FALSE);
	}
	a1->q_alias = a;
	allocaddr(a1, RF_COPYALL, newstr(a->q_paddr));
	(void) recipient(a1, sendq, aliaslevel, e);
}
/*
**  DEQUOTE_INIT -- initialize dequote map
**
**	This is a no-op.
**
**	Parameters:
**		map -- the internal map structure.
**		args -- arguments.
**
**	Returns:
**		TRUE.
*/

bool
dequote_init(map, args)
	MAP *map;
	char *args;
{
	register char *p = args;

	/* there is no check whether there is really an argument */
	map->map_mflags |= MF_KEEPQUOTES;
	for (;;)
	{
		while (isascii(*p) && isspace(*p))
			p++;
		if (*p != '-')
			break;
		switch (*++p)
		{
		  case 'a':
			map->map_app = ++p;
			break;

		  case 'D':
			map->map_mflags |= MF_DEFER;
			break;

		  case 'S':
		  case 's':
			map->map_spacesub = *++p;
			break;
		}
		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
			p++;
		if (*p != '\0')
			*p = '\0';
	}
	if (map->map_app != NULL)
		map->map_app = newstr(map->map_app);

	return TRUE;
}
/*
**  DEQUOTE_MAP -- unquote an address
**
**	Parameters:
**		map -- the internal map structure (ignored).
**		name -- the name to dequote.
**		av -- arguments (ignored).
**		statp -- pointer to status out-parameter.
**
**	Returns:
**		NULL -- if there were no quotes, or if the resulting
**			unquoted buffer would not be acceptable to prescan.
**		else -- The dequoted buffer.
*/

/* ARGSUSED2 */
char *
dequote_map(map, name, av, statp)
	MAP *map;
	char *name;
	char **av;
	int *statp;
{
	register char *p;
	register char *q;
	register char c;
	int anglecnt = 0;
	int cmntcnt = 0;
	int quotecnt = 0;
	int spacecnt = 0;
	bool quotemode = FALSE;
	bool bslashmode = FALSE;
	char spacesub = map->map_spacesub;

	for (p = q = name; (c = *p++) != '\0'; )
	{
		if (bslashmode)
		{
			bslashmode = FALSE;
			*q++ = c;
			continue;
		}

		if (c == ' ' && spacesub != '\0')
			c = spacesub;

		switch (c)
		{
		  case '\\':
			bslashmode = TRUE;
			break;

		  case '(':
			cmntcnt++;
			break;

		  case ')':
			if (cmntcnt-- <= 0)
				return NULL;
			break;

		  case ' ':
		  case '\t':
			spacecnt++;
			break;
		}

		if (cmntcnt > 0)
		{
			*q++ = c;
			continue;
		}

		switch (c)
		{
		  case '"':
			quotemode = !quotemode;
			quotecnt++;
			continue;

		  case '<':
			anglecnt++;
			break;

		  case '>':
			if (anglecnt-- <= 0)
				return NULL;
			break;
		}
		*q++ = c;
	}

	if (anglecnt != 0 || cmntcnt != 0 || bslashmode ||
	    quotemode || quotecnt <= 0 || spacecnt != 0)
		return NULL;
	*q++ = '\0';
	return map_rewrite(map, name, strlen(name), NULL);
}
/*
**  RSCHECK -- check string(s) for validity using rewriting sets
**
**	Parameters:
**		rwset -- the rewriting set to use.
**		p1 -- the first string to check.
**		p2 -- the second string to check -- may be null.
**		e -- the current envelope.
**		rmcomm -- remove comments?
**		cnt -- count rejections (statistics)?
**		logl -- logging level
**
**	Returns:
**		EX_OK -- if the rwset doesn't resolve to $#error
**		else -- the failure status (message printed)
*/

int
rscheck(rwset, p1, p2, e, rmcomm, cnt, logl)
	char *rwset;
	char *p1;
	char *p2;
	ENVELOPE *e;
	bool rmcomm, cnt;
	int logl;
{
	char *buf;
	int bufsize;
	int saveexitstat;
	int rstat = EX_OK;
	char **pvp;
	int rsno;
	bool discard = FALSE;
	auto ADDRESS a1;
	bool saveQuickAbort = QuickAbort;
	bool saveSuprErrs = SuprErrs;
	char buf0[MAXLINE];
	char pvpbuf[PSBUFSIZE];
	extern char MsgBuf[];

	if (tTd(48, 2))
		dprintf("rscheck(%s, %s, %s)\n", rwset, p1,
			p2 == NULL ? "(NULL)" : p2);

	rsno = strtorwset(rwset, NULL, ST_FIND);
	if (rsno < 0)
		return EX_OK;

	if (p2 != NULL)
	{
		bufsize = strlen(p1) + strlen(p2) + 2;
		if (bufsize > sizeof buf0)
			buf = xalloc(bufsize);
		else
		{
			buf = buf0;
			bufsize = sizeof buf0;
		}
		(void) snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2);
	}
	else
	{
		bufsize = strlen(p1) + 1;
		if (bufsize > sizeof buf0)
			buf = xalloc(bufsize);
		else
		{
			buf = buf0;
			bufsize = sizeof buf0;
		}
		(void) snprintf(buf, bufsize, "%s", p1);
	}
	SuprErrs = TRUE;
	QuickAbort = FALSE;
	pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL,
		      rmcomm ? NULL : TokTypeNoC);
	SuprErrs = saveSuprErrs;
	if (pvp == NULL)
	{
		if (tTd(48, 2))
			dprintf("rscheck: cannot prescan input\n");
/*
		syserr("rscheck: cannot prescan input: \"%s\"",
			shortenstring(buf, MAXSHORTSTR));
		rstat = EX_DATAERR;
*/
		goto finis;
	}

	MapOpenErr = FALSE;
	(void) rewrite(pvp, rsno, 0, e);
	if (MapOpenErr)
		usrerrenh("4.3.0", "451 Temporary failure");

	if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET ||
	    pvp[1] == NULL || (strcmp(pvp[1], "error") != 0 &&
			       strcmp(pvp[1], "discard") != 0))
	{
		goto finis;
	}

	if (strcmp(pvp[1], "discard") == 0)
	{
		if (tTd(48, 2))
			dprintf("rscheck: discard mailer selected\n");
		e->e_flags |= EF_DISCARD;
		discard = TRUE;
	}
	else
	{
		int savelogusrerrs = LogUsrErrs;
		static bool logged = FALSE;

		/* got an error -- process it */
		saveexitstat = ExitStat;
		LogUsrErrs = FALSE;
		(void) buildaddr(pvp, &a1, 0, e);
		LogUsrErrs = savelogusrerrs;
		rstat = ExitStat;
		ExitStat = saveexitstat;
		if (!logged)
		{
			if (cnt)
				markstats(e, &a1, TRUE);
			logged = TRUE;
		}
	}

	if (LogLevel >= logl)
	{
		char *relay;
		char *p;
		char lbuf[MAXLINE];

⌨️ 快捷键说明

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