| #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 int |
| forward_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; |
| } |
| |