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

📄 parseaddr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
{	register char *ap;		/* address pointer */	register char *rp;		/* rewrite pointer */	register char **avp;		/* address vector pointer */	register char **rvp;		/* rewrite vector pointer */	register struct match *mlp;	/* cur ptr into mlist */	register struct rewrite *rwr;	/* pointer to current rewrite rule */	int ruleno;			/* current rule number */	int rstat = EX_OK;		/* return status */	int loopcount;	struct match mlist[MAXMATCH];	/* stores match on LHS */	char *npvp[MAXATOM+1];		/* temporary space for rebuild */	if (OpMode == MD_TEST || tTd(21, 2))	{		printf("rewrite: ruleset %2d   input:", ruleset);		printav(pvp);	}	if (ruleset < 0 || ruleset >= MAXRWSETS)	{		syserr("554 rewrite: illegal ruleset number %d", ruleset);		return EX_CONFIG;	}	if (reclevel++ > MAXRULERECURSION)	{		syserr("rewrite: infinite recursion, ruleset %d", ruleset);		return EX_CONFIG;	}	if (pvp == NULL)		return EX_USAGE;	/*	**  Run through the list of rewrite rules, applying	**	any that match.	*/	ruleno = 1;	loopcount = 0;	for (rwr = RewriteRules[ruleset]; rwr != NULL; )	{		if (tTd(21, 12))		{			printf("-----trying rule:");			printav(rwr->r_lhs);		}		/* try to match on this rule */		mlp = mlist;		rvp = rwr->r_lhs;		avp = pvp;		if (++loopcount > 100)		{			syserr("554 Infinite loop in ruleset %d, rule %d",				ruleset, ruleno);			if (tTd(21, 1))			{				printf("workspace: ");				printav(pvp);			}			break;		}		while ((ap = *avp) != NULL || *rvp != NULL)		{			rp = *rvp;			if (tTd(21, 35))			{				printf("ADVANCE rp=");				xputs(rp);				printf(", ap=");				xputs(ap);				printf("\n");			}			if (rp == NULL)			{				/* end-of-pattern before end-of-address */				goto backup;			}			if (ap == NULL && (*rp & 0377) != MATCHZANY &&			    (*rp & 0377) != MATCHZERO)			{				/* end-of-input with patterns left */				goto backup;			}			switch (*rp & 0377)			{				register STAB *s;				char buf[MAXLINE];			  case MATCHCLASS:				/* match any phrase in a class */				mlp->pattern = rvp;				mlp->first = avp;	extendclass:				ap = *avp;				if (ap == NULL)					goto backup;				mlp->last = avp++;				cataddr(mlp->first, mlp->last, buf, sizeof buf, '\0');				s = stab(buf, ST_CLASS, ST_FIND);				if (s == NULL || !bitnset(rp[1], s->s_class))				{					if (tTd(21, 36))					{						printf("EXTEND  rp=");						xputs(rp);						printf(", ap=");						xputs(ap);						printf("\n");					}					goto extendclass;				}				if (tTd(21, 36))					printf("CLMATCH\n");				mlp++;				break;			  case MATCHNCLASS:				/* match any token not in a class */				s = stab(ap, ST_CLASS, ST_FIND);				if (s != NULL && bitnset(rp[1], s->s_class))					goto backup;				/* fall through */			  case MATCHONE:			  case MATCHANY:				/* match exactly one token */				mlp->pattern = rvp;				mlp->first = avp;				mlp->last = avp++;				mlp++;				break;			  case MATCHZANY:				/* match zero or more tokens */				mlp->pattern = rvp;				mlp->first = avp;				mlp->last = avp - 1;				mlp++;				break;			  case MATCHZERO:				/* match zero tokens */				break;			  case MACRODEXPAND:				/*				**  Match against run-time macro.				**  This algorithm is broken for the				**  general case (no recursive macros,				**  improper tokenization) but should				**  work for the usual cases.				*/				ap = macvalue(rp[1], e);				mlp->first = avp;				if (tTd(21, 2))					printf("rewrite: LHS $&%c => \"%s\"\n",						rp[1],						ap == NULL ? "(NULL)" : ap);				if (ap == NULL)					break;				while (*ap != '\0')				{					if (*avp == NULL ||					    strncasecmp(ap, *avp, strlen(*avp)) != 0)					{						/* no match */						avp = mlp->first;						goto backup;					}					ap += strlen(*avp++);				}				/* match */				break;			  default:				/* must have exact match */				if (strcasecmp(rp, ap))					goto backup;				avp++;				break;			}			/* successful match on this token */			rvp++;			continue;	  backup:			/* match failed -- back up */			while (--mlp >= mlist)			{				rvp = mlp->pattern;				rp = *rvp;				avp = mlp->last + 1;				ap = *avp;				if (tTd(21, 36))				{					printf("BACKUP  rp=");					xputs(rp);					printf(", ap=");					xputs(ap);					printf("\n");				}				if (ap == NULL)				{					/* run off the end -- back up again */					continue;				}				if ((*rp & 0377) == MATCHANY ||				    (*rp & 0377) == MATCHZANY)				{					/* extend binding and continue */					mlp->last = avp++;					rvp++;					mlp++;					break;				}				if ((*rp & 0377) == MATCHCLASS)				{					/* extend binding and try again */					mlp->last = avp;					goto extendclass;				}			}			if (mlp < mlist)			{				/* total failure to match */				break;			}		}		/*		**  See if we successfully matched		*/		if (mlp < mlist || *rvp != NULL)		{			if (tTd(21, 10))				printf("----- rule fails\n");			rwr = rwr->r_next;			ruleno++;			loopcount = 0;			continue;		}		rvp = rwr->r_rhs;		if (tTd(21, 12))		{			printf("-----rule matches:");			printav(rvp);		}		rp = *rvp;		if ((*rp & 0377) == CANONUSER)		{			rvp++;			rwr = rwr->r_next;			ruleno++;			loopcount = 0;		}		else if ((*rp & 0377) == CANONHOST)		{			rvp++;			rwr = NULL;		}		else if ((*rp & 0377) == CANONNET)			rwr = NULL;		/* substitute */		for (avp = npvp; *rvp != NULL; rvp++)		{			register struct match *m;			register char **pp;			rp = *rvp;			if ((*rp & 0377) == MATCHREPL)			{				/* substitute from LHS */				m = &mlist[rp[1] - '1'];				if (m < mlist || m >= mlp)				{					syserr("554 rewrite: ruleset %d: replacement $%c out of bounds",						ruleset, rp[1]);					return EX_CONFIG;				}				if (tTd(21, 15))				{					printf("$%c:", rp[1]);					pp = m->first;					while (pp <= m->last)					{						printf(" %x=\"", *pp);						(void) fflush(stdout);						printf("%s\"", *pp++);					}					printf("\n");				}				pp = m->first;				while (pp <= m->last)				{					if (avp >= &npvp[MAXATOM])					{						syserr("554 rewrite: expansion too long");						return EX_DATAERR;					}					*avp++ = *pp++;				}			}			else			{				/* vanilla replacement */				if (avp >= &npvp[MAXATOM])				{	toolong:					syserr("554 rewrite: expansion too long");					return EX_DATAERR;				}				if ((*rp & 0377) != MACRODEXPAND)					*avp++ = rp;				else				{					*avp = macvalue(rp[1], e);					if (tTd(21, 2))						printf("rewrite: RHS $&%c => \"%s\"\n",							rp[1],							*avp == NULL ? "(NULL)" : *avp);					if (*avp != NULL)						avp++;				}			}		}		*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 buf[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 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;			bcopy((char *) rvp, (char *) pvpb1, trsize);			/* look it up */			cataddr(key_rvp, NULL, buf, sizeof buf, '\0');			argvect[0] = buf;			if (map != NULL && bitset(MF_OPEN, map->s_map.map_mflags))			{				auto int stat = EX_OK;				/* XXX should try to auto-open the map here */				if (tTd(60, 1))					printf("map_lookup(%s, %s) => ",						mapname, buf);				replac = (*map->s_map.map_class->map_lookup)(&map->s_map,						buf, argvect, &stat);				if (tTd(60, 1))					printf("%s (%d)\n",						replac ? replac : "NOT FOUND",						stat);				/* should recover if stat == EX_TEMPFAIL */				if (stat == EX_TEMPFAIL)					rstat = stat;			}			else				replac = NULL;			/* if no replacement, use default */			if (replac == NULL && default_rvp != NULL)			{				/* create the default */				cataddr(default_rvp, NULL, buf, sizeof buf, '\0');				replac = buf;			}			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);				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 */			for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )				if (avp >= &npvp[MAXATOM])					goto toolong;			break;		}		/*		**  Check for subroutine calls.		*/		if (*npvp != NULL && (**npvp & 0377) == CALLSUBR)		{			int stat;			if (npvp[1] == NULL)			{				syserr("parseaddr: NULL subroutine call in ruleset %d, rule %d",					ruleset, ruleno);				*pvp = NULL;			}			else			{				bcopy((char *) &npvp[2], (char *) pvp,					(int) (avp - npvp - 2) * sizeof *avp);				if (tTd(21, 3))					printf("-----callsubr %s\n", npvp[1]);				stat = rewrite(pvp, atoi(npvp[1]), reclevel, e);				if (rstat == EX_OK || stat == EX_TEMPFAIL)					rstat = stat;				if (*pvp != NULL && (**pvp & 0377) == CANONNET)				rwr = NULL;			}		}		else		{			bcopy((char *) npvp, (char *) pvp,				(int) (avp - npvp) * sizeof *avp);		}		if (tTd(21, 4))		{			printf("rewritten as:");			printav(pvp);		}	}	if (OpMode == MD_TEST || tTd(21, 2))	{		printf("rewrite: ruleset %2d returns:", ruleset);		printav(pvp);	}	return rstat;}/***  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'*/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,	"software",	EX_SOFTWARE,	"tempfail",	EX_TEMPFAIL,	"protocol",	EX_PROTOCOL,#ifdef EX_CONFIG	"config",	EX_CONFIG,#endif	NULL,		EX_UNAVAILABLE,};ADDRESS *buildaddr(tv, a, flags, e)	register char **tv;	register ADDRESS *a;	int flags;	register ENVELOPE *e;{	struct mailer **mp;	register struct mailer *m;	char *bp;	int spaceleft;	static MAILER errormailer;	static char *errorargv[] = { "ERROR", NULL };	static char buf[MAXNAME];	if (tTd(24, 5))	{		printf("buildaddr, flags=%o, tv=", flags);		printav(tv);	}	if (a == NULL)		a = (ADDRESS *) xalloc(sizeof *a);	bzero((char *) a, sizeof *a);	/* figure out what net/mailer to use */	if (*tv == NULL || (**tv & 0377) != CANONNET)	{		syserr("554 buildaddr: no net");badaddr:		a->q_flags |= QBADADDR;		a->q_mailer = &errormailer;		if (errormailer.m_name == NULL)		{			/* initialize the bogus mailer */			errormailer.m_name = "*error*";			errormailer.m_mailer = "ERROR";			errormailer.m_argv = errorargv;		}		return a;	}	tv++;	if (strcasecmp(*tv, "error") == 0)	{		if ((**++tv & 0377) == CANONHOST)		{			register struct errcodes *ep;			if (isascii(**++tv) && isdigit(**tv))			{				setstat(atoi(*tv));			}			else			{				for (ep = ErrorCodes; ep->ec_name != NULL; ep++)					if (strcasecmp(ep->ec_name, *tv) == 0)						break;

⌨️ 快捷键说明

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