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

📄 headers.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	{
		if (tTd(32, 1))
			dprintf("%s: ", h->h_field);
		if (h->h_value == NULL)
		{
			if (tTd(32, 1))
				dprintf("<NULL>\n");
			continue;
		}

		/* do early binding */
		if (bitset(H_DEFAULT, h->h_flags) &&
		    !bitset(H_BINDLATE, h->h_flags))
		{
			if (tTd(32, 1))
			{
				dprintf("(");
				xputs(h->h_value);
				dprintf(") ");
			}
			expand(h->h_value, buf, sizeof buf, e);
			if (buf[0] != '\0')
			{
				if (bitset(H_FROM, h->h_flags))
					expand(crackaddr(buf), buf, sizeof buf, e);
				h->h_value = newstr(buf);
				h->h_flags &= ~H_DEFAULT;
			}
		}

		if (tTd(32, 1))
		{
			xputs(h->h_value);
			dprintf("\n");
		}

		/* count the number of times it has been processed */
		if (bitset(H_TRACE, h->h_flags))
			hopcnt++;

		/* send to this person if we so desire */
		if (GrabTo && bitset(H_RCPT, h->h_flags) &&
		    !bitset(H_DEFAULT, h->h_flags) &&
		    (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
		{
#if 0
			int saveflags = e->e_flags;
#endif /* 0 */

			(void) sendtolist(h->h_value, NULLADDR,
					  &e->e_sendqueue, 0, e);

#if 0
			/*
			**  Change functionality so a fatal error on an
			**  address doesn't affect the entire envelope.
			*/

			/* delete fatal errors generated by this address */
			if (!bitset(EF_FATALERRS, saveflags))
				e->e_flags &= ~EF_FATALERRS;
#endif /* 0 */
		}

		/* save the message-id for logging */
		p = "resent-message-id";
		if (!bitset(EF_RESENT, e->e_flags))
			p += 7;
		if (strcasecmp(h->h_field, p) == 0)
		{
			msgid = h->h_value;
			while (isascii(*msgid) && isspace(*msgid))
				msgid++;
		}
	}
	if (tTd(32, 1))
		dprintf("----------------------------\n");

	/* if we are just verifying (that is, sendmail -t -bv), drop out now */
	if (OpMode == MD_VERIFY)
		return;

	/* store hop count */
	if (hopcnt > e->e_hopcount)
		e->e_hopcount = hopcnt;

	/* message priority */
	p = hvalue("precedence", e->e_header);
	if (p != NULL)
		e->e_class = priencode(p);
	if (e->e_class < 0)
		e->e_timeoutclass = TOC_NONURGENT;
	else if (e->e_class > 0)
		e->e_timeoutclass = TOC_URGENT;
	if (full)
	{
		e->e_msgpriority = e->e_msgsize
				 - e->e_class * WkClassFact
				 + e->e_nrcpts * WkRecipFact;
	}

	/* message timeout priority */
	p = hvalue("priority", e->e_header);
	if (p != NULL)
	{
		/* (this should be in the configuration file) */
		if (strcasecmp(p, "urgent") == 0)
			e->e_timeoutclass = TOC_URGENT;
		else if (strcasecmp(p, "normal") == 0)
			e->e_timeoutclass = TOC_NORMAL;
		else if (strcasecmp(p, "non-urgent") == 0)
			e->e_timeoutclass = TOC_NONURGENT;
	}

	/* date message originated */
	p = hvalue("posted-date", e->e_header);
	if (p == NULL)
		p = hvalue("date", e->e_header);
	if (p != NULL)
		define('a', p, e);

	/* check to see if this is a MIME message */
	if ((e->e_bodytype != NULL &&
	     strcasecmp(e->e_bodytype, "8BITMIME") == 0) ||
	    hvalue("MIME-Version", e->e_header) != NULL)
	{
		e->e_flags |= EF_IS_MIME;
		if (HasEightBits)
			e->e_bodytype = "8BITMIME";
	}
	else if ((p = hvalue("Content-Type", e->e_header)) != NULL)
	{
		/* this may be an RFC 1049 message */
		p = strpbrk(p, ";/");
		if (p == NULL || *p == ';')
		{
			/* yep, it is */
			e->e_flags |= EF_DONT_MIME;
		}
	}

	/*
	**  From person in antiquated ARPANET mode
	**	required by UK Grey Book e-mail gateways (sigh)
	*/

	if (OpMode == MD_ARPAFTP)
	{
		register struct hdrinfo *hi;

		for (hi = HdrInfo; hi->hi_field != NULL; hi++)
		{
			if (bitset(H_FROM, hi->hi_flags) &&
			    (!bitset(H_RESENT, hi->hi_flags) ||
			     bitset(EF_RESENT, e->e_flags)) &&
			    (p = hvalue(hi->hi_field, e->e_header)) != NULL)
				break;
		}
		if (hi->hi_field != NULL)
		{
			if (tTd(32, 2))
				dprintf("eatheader: setsender(*%s == %s)\n",
					hi->hi_field, p);
			setsender(p, e, NULL, '\0', TRUE);
		}
	}

	/*
	**  Log collection information.
	*/

	if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
		logsender(e, msgid);
	e->e_flags &= ~EF_LOGSENDER;
}
/*
**  LOGSENDER -- log sender information
**
**	Parameters:
**		e -- the envelope to log
**		msgid -- the message id
**
**	Returns:
**		none
*/

void
logsender(e, msgid)
	register ENVELOPE *e;
	char *msgid;
{
	char *name;
	register char *sbp;
	register char *p;
	int l;
	char hbuf[MAXNAME + 1];
	char sbuf[MAXLINE + 1];
	char mbuf[MAXNAME + 1];

	/* don't allow newlines in the message-id */
	if (msgid != NULL)
	{
		l = strlen(msgid);
		if (l > sizeof mbuf - 1)
			l = sizeof mbuf - 1;
		memmove(mbuf, msgid, l);
		mbuf[l] = '\0';
		p = mbuf;
		while ((p = strchr(p, '\n')) != NULL)
			*p++ = ' ';
	}

	if (bitset(EF_RESPONSE, e->e_flags))
		name = "[RESPONSE]";
	else if ((name = macvalue('_', e)) != NULL)
		/* EMPTY */
		;
	else if (RealHostName == NULL)
		name = "localhost";
	else if (RealHostName[0] == '[')
		name = RealHostName;
	else
	{
		name = hbuf;
		(void) snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName);
		if (RealHostAddr.sa.sa_family != 0)
		{
			p = &hbuf[strlen(hbuf)];
			(void) snprintf(p, SPACELEFT(hbuf, p), " (%.100s)",
				anynet_ntoa(&RealHostAddr));
		}
	}

	/* some versions of syslog only take 5 printf args */
#if (SYSLOG_BUFSIZE) >= 256
	sbp = sbuf;
	snprintf(sbp, SPACELEFT(sbuf, sbp),
	    "from=%.200s, size=%ld, class=%d, nrcpts=%d",
	    e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
	    e->e_msgsize, e->e_class, e->e_nrcpts);
	sbp += strlen(sbp);
	if (msgid != NULL)
	{
		snprintf(sbp, SPACELEFT(sbuf, sbp), ", msgid=%.100s", mbuf);
		sbp += strlen(sbp);
	}
	if (e->e_bodytype != NULL)
	{
		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", bodytype=%.20s",
			e->e_bodytype);
		sbp += strlen(sbp);
	}
	p = macvalue('r', e);
	if (p != NULL)
	{
		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", proto=%.20s", p);
		sbp += strlen(sbp);
	}
	p = macvalue(macid("{daemon_name}", NULL), e);
	if (p != NULL)
	{
		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", daemon=%.20s", p);
		sbp += strlen(sbp);
	}
# if SASL
	p = macvalue(macid("{auth_type}", NULL), e);
	if (p != NULL)
	{
		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", mech=%.12s", p);
		sbp += strlen(sbp);
	}
	p = macvalue(macid("{auth_author}", NULL), e);
	if (p != NULL)
	{
		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", auth=%.30s", p);
		sbp += strlen(sbp);
	}
# endif /* SASL */
	sm_syslog(LOG_INFO, e->e_id,
		  "%.850s, relay=%.100s",
		  sbuf, name);

#else /* (SYSLOG_BUFSIZE) >= 256 */

	sm_syslog(LOG_INFO, e->e_id,
		  "from=%s",
		  e->e_from.q_paddr == NULL ? "<NONE>"
					    : shortenstring(e->e_from.q_paddr, 83));
	sm_syslog(LOG_INFO, e->e_id,
		  "size=%ld, class=%ld, nrcpts=%d",
		  e->e_msgsize, e->e_class, e->e_nrcpts);
	if (msgid != NULL)
		sm_syslog(LOG_INFO, e->e_id,
			  "msgid=%s",
			  shortenstring(mbuf, 83));
	sbp = sbuf;
	*sbp = '\0';
	if (e->e_bodytype != NULL)
	{
		snprintf(sbp, SPACELEFT(sbuf, sbp), "bodytype=%.20s, ", e->e_bodytype);
		sbp += strlen(sbp);
	}
	p = macvalue('r', e);
	if (p != NULL)
	{
		snprintf(sbp, SPACELEFT(sbuf, sbp), "proto=%.20s, ", p);
		sbp += strlen(sbp);
	}
	sm_syslog(LOG_INFO, e->e_id,
		  "%.400srelay=%.100s", sbuf, name);
#endif /* (SYSLOG_BUFSIZE) >= 256 */
}
/*
**  PRIENCODE -- encode external priority names into internal values.
**
**	Parameters:
**		p -- priority in ascii.
**
**	Returns:
**		priority as a numeric level.
**
**	Side Effects:
**		none.
*/

static int
priencode(p)
	char *p;
{
	register int i;

	for (i = 0; i < NumPriorities; i++)
	{
		if (strcasecmp(p, Priorities[i].pri_name) == 0)
			return Priorities[i].pri_val;
	}

	/* unknown priority */
	return 0;
}
/*
**  CRACKADDR -- parse an address and turn it into a macro
**
**	This doesn't actually parse the address -- it just extracts
**	it and replaces it with "$g".  The parse is totally ad hoc
**	and isn't even guaranteed to leave something syntactically
**	identical to what it started with.  However, it does leave
**	something semantically identical.
**
**	This algorithm has been cleaned up to handle a wider range
**	of cases -- notably quoted and backslash escaped strings.
**	This modification makes it substantially better at preserving
**	the original syntax.
**
**	Parameters:
**		addr -- the address to be cracked.
**
**	Returns:
**		a pointer to the new version.
**
**	Side Effects:
**		none.
**
**	Warning:
**		The return value is saved in local storage and should
**		be copied if it is to be reused.
*/

char *
crackaddr(addr)
	register char *addr;
{
	register char *p;
	register char c;
	int cmtlev;
	int realcmtlev;
	int anglelev, realanglelev;
	int copylev;
	int bracklev;
	bool qmode;
	bool realqmode;
	bool skipping;
	bool putgmac = FALSE;
	bool quoteit = FALSE;
	bool gotangle = FALSE;
	bool gotcolon = FALSE;
	register char *bp;
	char *buflim;
	char *bufhead;
	char *addrhead;
	static char buf[MAXNAME + 1];

	if (tTd(33, 1))
		dprintf("crackaddr(%s)\n", addr);

	/* strip leading spaces */
	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
		addr++;

	/*
	**  Start by assuming we have no angle brackets.  This will be
	**  adjusted later if we find them.
	*/

	bp = bufhead = buf;
	buflim = &buf[sizeof buf - 7];
	p = addrhead = addr;
	copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
	bracklev = 0;
	qmode = realqmode = FALSE;

	while ((c = *p++) != '\0')
	{
		/*
		**  If the buffer is overful, go into a special "skipping"
		**  mode that tries to keep legal syntax but doesn't actually
		**  output things.
		*/

		skipping = bp >= buflim;

		if (copylev > 0 && !skipping)
			*bp++ = c;

		/* check for backslash escapes */
		if (c == '\\')
		{
			/* arrange to quote the address */
			if (cmtlev <= 0 && !qmode)
				quoteit = TRUE;

			if ((c = *p++) == '\0')
			{
				/* too far */
				p--;
				goto putg;
			}
			if (copylev > 0 && !skipping)
				*bp++ = c;
			goto putg;
		}

		/* check for quoted strings */
		if (c == '"' && cmtlev <= 0)
		{
			qmode = !qmode;
			if (copylev > 0 && !skipping)
				realqmode = !realqmode;
			continue;
		}
		if (qmode)
			goto putg;

		/* check for comments */
		if (c == '(')
		{
			cmtlev++;

			/* allow space for closing paren */
			if (!skipping)
			{
				buflim--;
				realcmtlev++;
				if (copylev++ <= 0)
				{
					if (bp != bufhead)
						*bp++ = ' ';
					*bp++ = c;
				}
			}
		}
		if (cmtlev > 0)
		{
			if (c == ')')
			{
				cmtlev--;
				copylev--;
				if (!skipping)
				{
					realcmtlev--;
					buflim++;
				}
			}
			continue;
		}
		else if (c == ')')
		{
			/* syntax error: unmatched ) */
			if (copylev > 0 && !skipping)
				bp--;
		}

		/* count nesting on [ ... ] (for IPv6 domain literals) */
		if (c == '[')
			bracklev++;
		else if (c == ']')
			bracklev--;

		/* check for group: list; syntax */
		if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
		    !gotcolon && !ColonOkInAddr)
		{
			register char *q;

			/*
			**  Check for DECnet phase IV ``::'' (host::user)
			**  or **  DECnet phase V ``:.'' syntaxes.  The latter
			**  covers ``user@DEC:.tay.myhost'' and
			**  ``DEC:.tay.myhost::user'' syntaxes (bletch).
			*/

			if (*p == ':' || *p == '.')
			{
				if (cmtlev <= 0 && !qmode)
					quoteit = TRUE;
				if (copylev > 0 && !skipping)
				{
					*bp++ = c;
					*bp++ = *p;
				}
				p++;
				goto putg;
			}

			gotcolon = TRUE;

			bp = bufhead;
			if (quoteit)
			{
				*bp++ = '"';

				/* back up over the ':' and any spaces */
				--p;
				while (isascii(*--p) && isspace(*p))
					continue;
				p++;
			}
			for (q = addrhead; q < p; )
			{
				c = *q++;
				if (bp < buflim)
				{
					if (quoteit && c == '"')
						*bp++ = '\\';
					*bp++ = c;
				}
			}
			if (quoteit)
			{
				if (bp == &bufhead[1])
					bp--;
				else
					*bp++ = '"';
				while ((c = *p++) != ':')
				{
					if (bp < buflim)
						*bp++ = c;
				}
				*bp++ = c;
			}

			/* any trailing white space is part of group: */
			while (isascii(*p) && isspace(*p) && bp < buflim)
				*bp++ = *p++;
			copylev = 0;
			putgmac = quoteit = FALSE;
			bufhead = bp;
			addrhead = p;
			continue;
		}

		if (c == ';' && copylev <= 0 && !ColonOkInAddr)
		{
			if (bp < buflim)
				*bp++ = c;
		}

		/* check for characters that may have to be quoted */
		if (strchr(MustQuoteChars, c) != NULL)
		{
			/*
			**  If these occur as the phrase part of a <>
			**  construct, but are not inside of () or already
			**  quoted, they will have to be quoted.  Note that
			**  now (but don't actually do the quoting).
			*/

			if (cmtlev <= 0 && !qmode)
				quoteit = TRUE;
		}

		/* check for angle brackets */
		if (c == '<')
		{
			register char *q;

			/* assume first of two angles is bogus */
			if (gotangle)
				quoteit = TRUE;
			gotangle = TRUE;

			/* oops -- have to change our mind */
			anglelev = 1;
			if (!skipping)
				realanglelev = 1;

			bp = bufhead;
			if (quoteit)
			{
				*bp++ = '"';

				/* back up over the '<' and any spaces */
				--p;
				while (isascii(*--p) && isspace(*p))
					continue;
				p++;
			}
			for (q = addrhead; q < p; )
			{
				c = *q++;
				if (bp < buflim)
				{
					if (quoteit && c == '"')
						*bp++ = '\\';
					*bp++ = c;

⌨️ 快捷键说明

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