plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

bind.c (3251B)


      1 #include "common.h"
      2 #include "send.h"
      3 
      4 static int forward_loop(char *, char *);
      5 
      6 /* bind the destinations to the commands to be executed */
      7 extern dest *
      8 up_bind(dest *destp, message *mp, int checkforward)
      9 {
     10 	dest *list[2];		/* lists of unbound destinations */
     11 	int li;			/* index into list[2] */
     12 	dest *bound=0;	/* bound destinations */
     13 	dest *dp;
     14 	int i;
     15 
     16 	list[0] = destp;
     17 	list[1] = 0;
     18 
     19 	/*
     20 	 *  loop once to check for:
     21 	 *	- forwarding rights
     22 	 *	- addressing loops
     23 	 *	- illegal characters
     24 	 *	- characters that need escaping
     25 	 */
     26 	for (dp = d_rm(&list[0]); dp != 0; dp = d_rm(&list[0])) {
     27 		if (!checkforward)
     28 			dp->authorized = 1;
     29 		dp->addr = escapespecial(dp->addr);
     30 		if (forward_loop(s_to_c(dp->addr), thissys)) {
     31 			dp->status = d_eloop;
     32 			d_same_insert(&bound, dp);
     33 		} else if(forward_loop(s_to_c(mp->sender), thissys)) {
     34 			dp->status = d_eloop;
     35 			d_same_insert(&bound, dp);
     36 		} else if(shellchars(s_to_c(dp->addr))) {
     37 			dp->status = d_syntax;
     38 			d_same_insert(&bound, dp);
     39 		} else
     40 			d_insert(&list[1], dp);
     41 	}
     42 	li = 1;
     43 
     44 	/* Loop until all addresses are bound or address loop detected */
     45 	for (i=0; list[li]!=0 && i<32; ++i, li ^= 1) {
     46 		/* Traverse the current list.  Bound items are put on the
     47 		 * `bound' list.  Unbound items are put on the next list to
     48 		 * traverse, `list[li^1]'.
     49 		 */
     50 		for (dp = d_rm(&list[li]); dp != 0; dp = d_rm(&list[li])){
     51 			dest *newlist;
     52 
     53 			rewrite(dp, mp);
     54 			if(debug)
     55 				fprint(2, "%s -> %s\n", s_to_c(dp->addr),
     56 					dp->repl1 ? s_to_c(dp->repl1):"");
     57 			switch (dp->status) {
     58 			case d_auth:
     59 				/* authorize address if not already authorized */
     60 				if(!dp->authorized){
     61 					authorize(dp);
     62 					if(dp->status==d_auth)
     63 						d_insert(&list[li^1], dp);
     64 					else
     65 						d_insert(&bound, dp);
     66 				}
     67 				break;
     68 			case d_cat:
     69 				/* address -> local */
     70 				newlist = expand_local(dp);
     71 				if (newlist == 0) {
     72 					/* append to mailbox (or error) */
     73 					d_same_insert(&bound, dp);
     74 				} else if (newlist->status == d_undefined) {
     75 					/* Forward to ... */
     76 					d_insert(&list[li^1], newlist);
     77 				} else {
     78 					/* Pipe to ... */
     79 					d_same_insert(&bound, newlist);
     80 				}
     81 				break;
     82 			case d_pipe:
     83 				/* address -> command */
     84 				d_same_insert(&bound, dp);
     85 				break;
     86 			case d_alias:
     87 				/* address -> rewritten address */
     88 				newlist = s_to_dest(dp->repl1, dp);
     89 				if(newlist != 0)
     90 					d_insert(&list[li^1], newlist);
     91 				else
     92 					d_same_insert(&bound, dp);
     93 				break;
     94 			case d_translate:
     95 				/* pipe to a translator */
     96 				newlist = translate(dp);
     97 				if (newlist != 0)
     98 					d_insert(&list[li^1], newlist);
     99 				else
    100 					d_same_insert(&bound, dp);
    101 				break;
    102 			default:
    103 				/* error */
    104 				d_same_insert(&bound, dp);
    105 				break;
    106 			}
    107 		}
    108 	}
    109 
    110 	/* mark remaining comands as "forwarding loops" */
    111 	for (dp = d_rm(&list[li]); dp != 0; dp = d_rm(&list[li])) {
    112 		dp->status = d_loop;
    113 		d_same_insert(&bound, dp);
    114 	}
    115 
    116 	return bound;
    117 }
    118 
    119 /* Return TRUE if a forwarding loop exists, i.e., the String `system'
    120  * is found more than 4 times in the return address.
    121  */
    122 static int
    123 forward_loop(char *addr, char *system)
    124 {
    125 	int len = strlen(system), found = 0;
    126 
    127 	while (addr = strchr(addr, '!'))
    128 		if (!strncmp(++addr, system, len)
    129 		 && addr[len] == '!' && ++found == 4)
    130 			return 1;
    131 	return 0;
    132 }