parseaddr.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,432 行 · 第 1/2 页

C
1,432
字号
		rvp = rwr->r_rhs;# ifdef DEBUG		if (tTd(21, 12))		{			printf("-----rule matches:");			printav(rvp);		}# endif DEBUG		rp = *rvp;		if (*rp == CANONUSER)		{			rvp++;			rwr = rwr->r_next;		}		else if (*rp == CANONHOST)		{			rvp++;			rwr = NULL;		}		else if (*rp == CANONNET)			rwr = NULL;		/* substitute */		for (avp = npvp; *rvp != NULL; rvp++)		{			register struct match *m;			register char **pp;			rp = *rvp;			if (*rp == MATCHREPL)			{				/* substitute from LHS */				m = &mlist[rp[1] - '1'];				if (m >= mlp)				{					syserr("rewrite: ruleset %d: replacement out of bounds", ruleset);					return;				}# ifdef DEBUG				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");				}# endif DEBUG				pp = m->first;				while (pp <= m->last)				{					if (avp >= &npvp[MAXATOM])					{						syserr("rewrite: expansion too long");						return;					}					*avp++ = *pp++;				}			}			else			{				/* vanilla replacement */				if (avp >= &npvp[MAXATOM])				{	toolong:					syserr("rewrite: expansion too long");					return;				}				*avp++ = rp;			}		}		*avp++ = NULL;		/*		**  Check for any hostname lookups.		*/		for (rvp = npvp; *rvp != NULL; rvp++)		{			char **hbrvp;			char **xpvp;			int trsize;			char *olddelimchar;			char buf[MAXNAME + 1];			char *pvpb1[MAXATOM + 1];			char pvpbuf[PSBUFSIZE];			extern char *DelimChar;			if (**rvp != HOSTBEGIN)				continue;			/*			**  Got a hostname lookup.			**			**	This could be optimized fairly easily.			*/			hbrvp = rvp;			/* extract the match part */			while (*++rvp != NULL && **rvp != HOSTEND)				continue;			if (*rvp != NULL)				*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(++hbrvp, buf, sizeof buf);			maphostname(buf, sizeof buf);			/* scan the new host name */			olddelimchar = DelimChar;			xpvp = prescan(buf, '\0', pvpbuf);			DelimChar = olddelimchar;			if (xpvp == NULL)			{				syserr("rewrite: cannot prescan canonical hostname: %s", buf);				return;			}			/* 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 == CALLSUBR)		{			bcopy((char *) &npvp[2], (char *) pvp,				(int) (avp - npvp - 2) * sizeof *avp);# ifdef DEBUG			if (tTd(21, 3))				printf("-----callsubr %s\n", npvp[1]);# endif DEBUG			rewrite(pvp, atoi(npvp[1]));		}		else		{			bcopy((char *) npvp, (char *) pvp,				(int) (avp - npvp) * sizeof *avp);		}# ifdef DEBUG		if (tTd(21, 4))		{			printf("rewritten as:");			printav(pvp);		}# endif DEBUG	}	if (OpMode == MD_TEST || tTd(21, 2))	{		printf("rewrite: ruleset %2d returns:", ruleset);		printav(pvp);	}}/***  BUILDADDR -- build address from token vector.****	Parameters:**		tv -- token vector.**		a -- pointer to address descriptor to fill.**			If NULL, one will be allocated.****	Returns:**		NULL if there was an error.**		'a' otherwise.****	Side Effects:**		fills in 'a'*/ADDRESS *buildaddr(tv, a)	register char **tv;	register ADDRESS *a;{	static char buf[MAXNAME];	struct mailer **mp;	register struct mailer *m;	extern bool sameword();	if (a == NULL)		a = (ADDRESS *) xalloc(sizeof *a);	bzero((char *) a, sizeof *a);	/* figure out what net/mailer to use */	if (**tv != CANONNET)	{		syserr("buildaddr: no net");		return (NULL);	}	tv++;	if (sameword(*tv, "error"))	{		if (**++tv == CANONHOST)		{			setstat(atoi(*++tv));			tv++;		}		if (**tv != CANONUSER)			syserr("buildaddr: error: no user");		buf[0] = '\0';		while (*++tv != NULL)		{			if (buf[0] != '\0')				(void) strcat(buf, " ");			(void) strcat(buf, *tv);		}		usrerr(buf);		return (NULL);	}	for (mp = Mailer; (m = *mp++) != NULL; )	{		if (sameword(m->m_name, *tv))			break;	}	if (m == NULL)	{		syserr("buildaddr: unknown mailer %s", *tv);		return (NULL);	}	a->q_mailer = m;	/* figure out what host (if any) */	tv++;	if (!bitnset(M_LOCAL, m->m_flags))	{		if (**tv++ != CANONHOST)		{			syserr("buildaddr: no host");			return (NULL);		}		buf[0] = '\0';		while (*tv != NULL && **tv != CANONUSER)			(void) strcat(buf, *tv++);		a->q_host = newstr(buf);	}	else		a->q_host = NULL;	/* figure out the user */	if (**tv != CANONUSER)	{		syserr("buildaddr: no user");		return (NULL);	}	/* rewrite according recipient mailer rewriting rules */	rewrite(++tv, 2);	if (m->m_r_rwset > 0)		rewrite(tv, m->m_r_rwset);	rewrite(tv, 4);	/* save the result for the command line/RCPT argument */	cataddr(tv, buf, sizeof buf);	a->q_user = buf;	return (a);}/***  CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)****	Parameters:**		pvp -- parameter vector to rebuild.**		buf -- buffer to build the string into.**		sz -- size of buf.****	Returns:**		none.****	Side Effects:**		Destroys buf.*/cataddr(pvp, buf, sz)	char **pvp;	char *buf;	register int sz;{	bool oatomtok = FALSE;	bool natomtok = FALSE;	register int i;	register char *p;	if (pvp == NULL)	{		(void) strcpy(buf, "");		return;	}	p = buf;	sz -= 2;	while (*pvp != NULL && (i = strlen(*pvp)) < sz)	{		natomtok = (toktype(**pvp) == ATM);		if (oatomtok && natomtok)			*p++ = SpaceSub;		(void) strcpy(p, *pvp);		oatomtok = natomtok;		p += i;		sz -= i + 1;		pvp++;	}	*p = '\0';}/***  SAMEADDR -- Determine if two addresses are the same****	This is not just a straight comparison -- if the mailer doesn't**	care about the host we just ignore it, etc.****	Parameters:**		a, b -- pointers to the internal forms to compare.****	Returns:**		TRUE -- they represent the same mailbox.**		FALSE -- they don't.****	Side Effects:**		none.*/boolsameaddr(a, b)	register ADDRESS *a;	register ADDRESS *b;{	/* if they don't have the same mailer, forget it */	if (a->q_mailer != b->q_mailer)		return (FALSE);	/* if the user isn't the same, we can drop out */	if (strcmp(a->q_user, b->q_user) != 0)		return (FALSE);	/**	 ** For Reading mail+ support..  (mailplus)	 **	 ** If the mailer is 'prog'  AND  the addressess from which we are	 ** aliased are owned by different  UIDs, then return false.	 ** Different programs are picked up later. The paranoia checks	 ** are probably not needed.  Quote: JCH  :Enquote	 **/	if (a->q_mailer == ProgMailer &&		a->q_alias != NULL &&		b->q_alias != NULL &&		a->q_alias->q_flags|QGOODUID &&		b->q_alias->q_flags|QGOODUID &&		a->q_alias->q_uid != b->q_alias->q_uid)			return FALSE;	/* if the mailer ignores hosts, we have succeeded! */	if (bitnset(M_LOCAL, a->q_mailer->m_flags))		return (TRUE);	/* otherwise compare hosts (but be careful for NULL ptrs) */	if (a->q_host == NULL || b->q_host == NULL)		return (FALSE);	if (strcmp(a->q_host, b->q_host) != 0)		return (FALSE);	return (TRUE);}/***  PRINTADDR -- print address (for debugging)****	Parameters:**		a -- the address to print**		follow -- follow the q_next chain.****	Returns:**		none.****	Side Effects:**		none.*/# ifdef DEBUGprintaddr(a, follow)	register ADDRESS *a;	bool follow;{	bool first = TRUE;	while (a != NULL)	{		first = FALSE;		printf("%x=", a);		(void) fflush(stdout);		printf("%s: mailer %d (%s), host `%s', user `%s', ruser `%s'\n",			a->q_paddr, a->q_mailer->m_mno, a->q_mailer->m_name,			a->q_host, a->q_user, a->q_ruser ?						a->q_ruser : "<null>");		printf("\tnext=%x, flags=%o, alias %x\n", a->q_next, a->q_flags,		       a->q_alias);		printf("\thome=\"%s\", fullname=\"%s\"\n", a->q_home,		       a->q_fullname);		if (!follow)			return;		a = a->q_next;	}	if (first)		printf("[NULL]\n");}# endif DEBUG/***  REMOTENAME -- return the name relative to the current mailer****	Parameters:**		name -- the name to translate.**		m -- the mailer that we want to do rewriting relative**			to.**		senderaddress -- if set, uses the sender rewriting rules**			rather than the recipient rewriting rules.**		canonical -- if set, strip out any comment information,**			etc.****	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, senderaddress, canonical)	char *name;	struct mailer *m;	bool senderaddress;	bool canonical;{	register char **pvp;	char *fancy;	extern char *macvalue();	char *oldg = macvalue('g', CurEnv);	static char buf[MAXNAME];	char lbuf[MAXNAME];	char pvpbuf[PSBUFSIZE];	extern char **prescan();	extern char *crackaddr();# ifdef DEBUG	if (tTd(12, 1))		printf("remotename(%s)\n", name);# endif DEBUG	/* don't do anything if we are tagging it as special */	if ((senderaddress ? m->m_s_rwset : m->m_r_rwset) < 0)		return (name);	/*	**  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 (canonical)		fancy = "\001g";	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);	if (pvp == NULL)		return (name);	rewrite(pvp, 3);	if( ! canonical  &&  CurEnv->e_fromdomain != NULL ) /* 001 */	{		/* append from domain to this address */		register char **pxp = pvp;		/* see if there is an "@domain" in the current name */		while (*pxp != NULL && strcmp(*pxp, "@") != 0)			pxp++;		if (*pxp == NULL)		{			/* no.... append the "@domain" from the sender */			register char **qxq = CurEnv->e_fromdomain;			while ((*pxp++ = *qxq++) != NULL)				continue;			rewrite(pvp, 3);		}	}	/*	**  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 (senderaddress)	{		rewrite(pvp, 1);		if (m->m_s_rwset > 0)			rewrite(pvp, m->m_s_rwset);	}	else	{		rewrite(pvp, 2);		if (m->m_r_rwset > 0)			rewrite(pvp, m->m_r_rwset);	}	/*	**  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.	*/	rewrite(pvp, 4);	/*	**  Now restore the comment information we had at the beginning.	*/	cataddr(pvp, lbuf, sizeof lbuf);	define('g', lbuf, CurEnv);	expand(fancy, buf, &buf[sizeof buf - 1], CurEnv);	define('g', oldg, CurEnv);# ifdef DEBUG	if (tTd(12, 1))		printf("remotename => `%s'\n", buf);# endif DEBUG	return (buf);}/*****  IN_PASSWD_MAP -- See if something is in a passwd map****	Parameters:**		rvp	-- rewrite rule vector pointer**		ap	-- argument vector**			rather than the recipient rewriting rules.****	Returns:**		NULL	-- if not found in the map**		    else**		TRUE	-- if found in the map****	Side Effects:**		none.****	Warnings:*/struct svcinfo *svcinfo;struct passwd *nopasswd_local();struct passwd *getpwnam_yp();struct passwd *getpwnam_bind();struct passwd * (*getpasswdnames []) ()={		nopasswd_local,		getpwnam_yp,		getpwnam_bind};struct passwd *getpasswdname(name)	char *name;{	struct passwd *p=NULL;	register i;	struct passwd *call;	if ((svcinfo = getsvc()) != NULL)		for (i=0; (svc_lastlookup = svcinfo->svcpath[SVC_PASSWD][i]) != SVC_LAST; i++)			if (p = ((*(getpasswdnames [svcinfo->svcpath[SVC_PASSWD][i]])) (name) ))				break;	return(p);}struct passwd *nopasswd_local(name){	return(NULL);}in_passwd_map(rvp,ap)	char **rvp;		char **ap;{	int err;	if ((getpasswdname(ap)) == NULL) {		/*		 * Assume not in the map.		 */# ifdef DEBUG		if (tTd(21,1))			printf("Map entry  NOT found for %s\n",ap);# endif DEBUG		rvp--;		return(NULL);	}# ifdef DEBUG	if (tTd(21,1))		printf("Map entry found\n");# endif DEBUG	return(TRUE);}/*****  IN_ALIAS_MAP -- See if something is in an aliases map****	Parameters:**		rvp	-- rewrite rule vector pointer**		ap	-- argument vector**			rather than the recipient rewriting rules.****	Returns:**		NULL	-- if not found in the map**		    else**		TRUE	-- if found in the map****	Side Effects:**		none.****	Warnings:*/char *noalias_local();char *aliaslookup_yp();char *aliaslookup_bind();char * (*getaliasnames []) ()={		noalias_local,		aliaslookup_yp,		aliaslookup_bind};char *noalias_local(name){	return(NULL);}char *getaliasname(name)	char *name;{	char *p=NULL;	register i;	char *call;	if ((svcinfo = getsvc()) != NULL)		for (i=0; (svc_lastlookup = svcinfo->svcpath[SVC_ALIASES][i]) != SVC_LAST; i++)			if (p = ((*(getaliasnames [svcinfo->svcpath[SVC_ALIASES][i]])) (name) ))				break;	return(p);}in_alias_map(rvp,ap)	char **rvp;		char **ap;{	int err;	if ((getaliasname(ap)) == NULL) {		/*		 * Assume not in the map.		 */# ifdef DEBUG		if (tTd(21,1))			printf("Map entry  NOT found for %s\n",ap);# endif DEBUG		rvp--;		return(NULL);	}# ifdef DEBUG	if (tTd(21,1))		printf("Map entry found\n");# endif DEBUG	return(TRUE);}

⌨️ 快捷键说明

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