aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/upas/send/bind.c
blob: 8a8fc8eacf1d390698cf7666c354847aec0ac7cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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;
}