xref: /plan9/sys/src/cmd/upas/send/bind.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include "common.h"
23e12c5d1SDavid du Colombier #include "send.h"
33e12c5d1SDavid du Colombier 
43e12c5d1SDavid du Colombier static int forward_loop(char *, char *);
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier /* bind the destinations to the commands to be executed */
73e12c5d1SDavid du Colombier extern dest *
up_bind(dest * destp,message * mp,int checkforward)83e12c5d1SDavid du Colombier up_bind(dest *destp, message *mp, int checkforward)
93e12c5d1SDavid du Colombier {
103e12c5d1SDavid du Colombier 	dest *list[2];		/* lists of unbound destinations */
113e12c5d1SDavid du Colombier 	int li;			/* index into list[2] */
123e12c5d1SDavid du Colombier 	dest *bound=0;	/* bound destinations */
133e12c5d1SDavid du Colombier 	dest *dp;
143e12c5d1SDavid du Colombier 	int i;
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier 	list[0] = destp;
173e12c5d1SDavid du Colombier 	list[1] = 0;
183e12c5d1SDavid du Colombier 
193e12c5d1SDavid du Colombier 	/*
203e12c5d1SDavid du Colombier 	 *  loop once to check for:
213e12c5d1SDavid du Colombier 	 *	- forwarding rights
223e12c5d1SDavid du Colombier 	 *	- addressing loops
233e12c5d1SDavid du Colombier 	 *	- illegal characters
24*7dd7cddfSDavid du Colombier 	 *	- characters that need escaping
253e12c5d1SDavid du Colombier 	 */
263e12c5d1SDavid du Colombier 	for (dp = d_rm(&list[0]); dp != 0; dp = d_rm(&list[0])) {
273e12c5d1SDavid du Colombier 		if (!checkforward)
283e12c5d1SDavid du Colombier 			dp->authorized = 1;
29*7dd7cddfSDavid du Colombier 		dp->addr = escapespecial(dp->addr);
303e12c5d1SDavid du Colombier 		if (forward_loop(s_to_c(dp->addr), thissys)) {
313e12c5d1SDavid du Colombier 			dp->status = d_eloop;
323e12c5d1SDavid du Colombier 			d_same_insert(&bound, dp);
333e12c5d1SDavid du Colombier 		} else if(forward_loop(s_to_c(mp->sender), thissys)) {
343e12c5d1SDavid du Colombier 			dp->status = d_eloop;
353e12c5d1SDavid du Colombier 			d_same_insert(&bound, dp);
363e12c5d1SDavid du Colombier 		} else if(shellchars(s_to_c(dp->addr))) {
373e12c5d1SDavid du Colombier 			dp->status = d_syntax;
383e12c5d1SDavid du Colombier 			d_same_insert(&bound, dp);
393e12c5d1SDavid du Colombier 		} else
403e12c5d1SDavid du Colombier 			d_insert(&list[1], dp);
413e12c5d1SDavid du Colombier 	}
423e12c5d1SDavid du Colombier 	li = 1;
433e12c5d1SDavid du Colombier 
443e12c5d1SDavid du Colombier 	/* Loop until all addresses are bound or address loop detected */
453e12c5d1SDavid du Colombier 	for (i=0; list[li]!=0 && i<32; ++i, li ^= 1) {
463e12c5d1SDavid du Colombier 		/* Traverse the current list.  Bound items are put on the
473e12c5d1SDavid du Colombier 		 * `bound' list.  Unbound items are put on the next list to
483e12c5d1SDavid du Colombier 		 * traverse, `list[li^1]'.
493e12c5d1SDavid du Colombier 		 */
503e12c5d1SDavid du Colombier 		for (dp = d_rm(&list[li]); dp != 0; dp = d_rm(&list[li])){
513e12c5d1SDavid du Colombier 			dest *newlist;
523e12c5d1SDavid du Colombier 
53*7dd7cddfSDavid du Colombier 			rewrite(dp, mp);
543e12c5d1SDavid du Colombier 			if(debug)
553e12c5d1SDavid du Colombier 				fprint(2, "%s -> %s\n", s_to_c(dp->addr),
563e12c5d1SDavid du Colombier 					dp->repl1 ? s_to_c(dp->repl1):"");
573e12c5d1SDavid du Colombier 			switch (dp->status) {
583e12c5d1SDavid du Colombier 			case d_auth:
593e12c5d1SDavid du Colombier 				/* authorize address if not already authorized */
603e12c5d1SDavid du Colombier 				if(!dp->authorized){
613e12c5d1SDavid du Colombier 					authorize(dp);
623e12c5d1SDavid du Colombier 					if(dp->status==d_auth)
633e12c5d1SDavid du Colombier 						d_insert(&list[li^1], dp);
643e12c5d1SDavid du Colombier 					else
653e12c5d1SDavid du Colombier 						d_insert(&bound, dp);
663e12c5d1SDavid du Colombier 				}
673e12c5d1SDavid du Colombier 				break;
683e12c5d1SDavid du Colombier 			case d_cat:
693e12c5d1SDavid du Colombier 				/* address -> local */
703e12c5d1SDavid du Colombier 				newlist = expand_local(dp);
713e12c5d1SDavid du Colombier 				if (newlist == 0) {
723e12c5d1SDavid du Colombier 					/* append to mailbox (or error) */
733e12c5d1SDavid du Colombier 					d_same_insert(&bound, dp);
743e12c5d1SDavid du Colombier 				} else if (newlist->status == d_undefined) {
753e12c5d1SDavid du Colombier 					/* Forward to ... */
763e12c5d1SDavid du Colombier 					d_insert(&list[li^1], newlist);
773e12c5d1SDavid du Colombier 				} else {
783e12c5d1SDavid du Colombier 					/* Pipe to ... */
793e12c5d1SDavid du Colombier 					d_same_insert(&bound, newlist);
803e12c5d1SDavid du Colombier 				}
813e12c5d1SDavid du Colombier 				break;
823e12c5d1SDavid du Colombier 			case d_pipe:
833e12c5d1SDavid du Colombier 				/* address -> command */
843e12c5d1SDavid du Colombier 				d_same_insert(&bound, dp);
853e12c5d1SDavid du Colombier 				break;
863e12c5d1SDavid du Colombier 			case d_alias:
873e12c5d1SDavid du Colombier 				/* address -> rewritten address */
883e12c5d1SDavid du Colombier 				newlist = s_to_dest(dp->repl1, dp);
893e12c5d1SDavid du Colombier 				if(newlist != 0)
903e12c5d1SDavid du Colombier 					d_insert(&list[li^1], newlist);
913e12c5d1SDavid du Colombier 				else
923e12c5d1SDavid du Colombier 					d_same_insert(&bound, dp);
933e12c5d1SDavid du Colombier 				break;
943e12c5d1SDavid du Colombier 			case d_translate:
953e12c5d1SDavid du Colombier 				/* pipe to a translator */
963e12c5d1SDavid du Colombier 				newlist = translate(dp);
973e12c5d1SDavid du Colombier 				if (newlist != 0)
983e12c5d1SDavid du Colombier 					d_insert(&list[li^1], newlist);
993e12c5d1SDavid du Colombier 				else
1003e12c5d1SDavid du Colombier 					d_same_insert(&bound, dp);
1013e12c5d1SDavid du Colombier 				break;
1023e12c5d1SDavid du Colombier 			default:
1033e12c5d1SDavid du Colombier 				/* error */
1043e12c5d1SDavid du Colombier 				d_same_insert(&bound, dp);
1053e12c5d1SDavid du Colombier 				break;
1063e12c5d1SDavid du Colombier 			}
1073e12c5d1SDavid du Colombier 		}
1083e12c5d1SDavid du Colombier 	}
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier 	/* mark remaining comands as "forwarding loops" */
1113e12c5d1SDavid du Colombier 	for (dp = d_rm(&list[li]); dp != 0; dp = d_rm(&list[li])) {
1123e12c5d1SDavid du Colombier 		dp->status = d_loop;
1133e12c5d1SDavid du Colombier 		d_same_insert(&bound, dp);
1143e12c5d1SDavid du Colombier 	}
1153e12c5d1SDavid du Colombier 
1163e12c5d1SDavid du Colombier 	return bound;
1173e12c5d1SDavid du Colombier }
1183e12c5d1SDavid du Colombier 
1193e12c5d1SDavid du Colombier /* Return TRUE if a forwarding loop exists, i.e., the String `system'
1203e12c5d1SDavid du Colombier  * is found more than 4 times in the return address.
1213e12c5d1SDavid du Colombier  */
1223e12c5d1SDavid du Colombier static int
forward_loop(char * addr,char * system)1233e12c5d1SDavid du Colombier forward_loop(char *addr, char *system)
1243e12c5d1SDavid du Colombier {
1253e12c5d1SDavid du Colombier 	int len = strlen(system), found = 0;
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier 	while (addr = strchr(addr, '!'))
1283e12c5d1SDavid du Colombier 		if (!strncmp(++addr, system, len)
1293e12c5d1SDavid du Colombier 		 && addr[len] == '!' && ++found == 4)
1303e12c5d1SDavid du Colombier 			return 1;
1313e12c5d1SDavid du Colombier 	return 0;
1323e12c5d1SDavid du Colombier }
1333e12c5d1SDavid du Colombier 
134