Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 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
}
133