142 lines · 3.6 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "common.h"#include "send.h" static int forward_loop(char *, char *); /* bind the destinations to the commands to be executed */extern dest *up_bind(dest *destp, message *mp, int checkforward){	dest *list[2];		/* lists of unbound destinations */	int li;			/* index into list[2] */	dest *bound=0;	/* bound destinations */	dest *dp;	int i; 	list[0] = destp;	list[1] = 0; 	/*	 *  loop once to check for:	 *	- forwarding rights	 *	- addressing loops	 *	- illegal characters	 *	- characters that need escaping	 */	for (dp = d_rm(&list[0]); dp != 0; dp = d_rm(&list[0])) {		if (!checkforward)			dp->authorized = 1;		dp->addr = escapespecial(dp->addr);		if (forward_loop(s_to_c(dp->addr), thissys)) {			dp->status = d_eloop;			d_same_insert(&bound, dp);		} else if(forward_loop(s_to_c(mp->sender), thissys)) {			dp->status = d_eloop;			d_same_insert(&bound, dp);		} else if(shellchars(s_to_c(dp->addr))) {			dp->status = d_syntax;			d_same_insert(&bound, dp);		} else			d_insert(&list[1], dp);	}	li = 1; 	/* Loop until all addresses are bound or address loop detected */	for (i=0; list[li]!=0 && i<32; ++i, li ^= 1) {		/* Traverse the current list.  Bound items are put on the		 * `bound' list.  Unbound items are put on the next list to		 * traverse, `list[li^1]'.		 */		for (dp = d_rm(&list[li]); dp != 0; dp = d_rm(&list[li])){			dest *newlist; 			rewrite(dp, mp);			if(debug)				fprint(2, "%s -> %s\n", s_to_c(dp->addr),					dp->repl1 ? s_to_c(dp->repl1):"");			switch (dp->status) {			case d_auth:				/* authorize address if not already authorized */				if(!dp->authorized){					authorize(dp);					if(dp->status==d_auth)						d_insert(&list[li^1], dp);					else						d_insert(&bound, dp);				}				break;			case d_cat:				/* address -> local */				newlist = expand_local(dp);				if (newlist == 0) {					/* append to mailbox (or error) */					d_same_insert(&bound, dp);				} else if (newlist->status == d_undefined) {					/* Forward to ... */					d_insert(&list[li^1], newlist);				} else {					/* Pipe to ... */					d_same_insert(&bound, newlist);				}				break;			case d_pipe:				/* address -> command */				d_same_insert(&bound, dp);				break;			case d_alias:				/* address -> rewritten address */				newlist = s_to_dest(dp->repl1, dp);				if(newlist != 0)					d_insert(&list[li^1], newlist);				else					d_same_insert(&bound, dp);				break;			case d_translate:				/* pipe to a translator */				newlist = translate(dp);				if (newlist != 0)					d_insert(&list[li^1], newlist);				else					d_same_insert(&bound, dp);				break;			default:				/* error */				d_same_insert(&bound, dp);				break;			}		}	} 	/* mark remaining comands as "forwarding loops" */	for (dp = d_rm(&list[li]); dp != 0; dp = d_rm(&list[li])) {		dp->status = d_loop;		d_same_insert(&bound, dp);	} 	return bound;} /* Return TRUE if a forwarding loop exists, i.e., the String `system' * is found more than 4 times in the return address. */static intforward_loop(char *addr, char *system){	int len = strlen(system), found = 0; 	while (addr = strchr(addr, '!'))		if (!strncmp(++addr, system, len)		 && addr[len] == '!' && ++found == 4)			return 1;	return 0;}