Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

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