From 5cdb17983ae6e6367ad7a940cb219eab247a9304 Mon Sep 17 00:00:00 2001 From: rsc Date: Sat, 29 Oct 2005 16:26:44 +0000 Subject: Thanks to John Cummings. --- src/cmd/upas/send/bind.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/cmd/upas/send/bind.c (limited to 'src/cmd/upas/send/bind.c') diff --git a/src/cmd/upas/send/bind.c b/src/cmd/upas/send/bind.c new file mode 100644 index 00000000..8a8fc8ea --- /dev/null +++ b/src/cmd/upas/send/bind.c @@ -0,0 +1,133 @@ +#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; +} + -- cgit v1.2.3