Blame


1 5cdb1798 2005-10-29 devnull #include "common.h"
2 5cdb1798 2005-10-29 devnull #include "send.h"
3 5cdb1798 2005-10-29 devnull
4 5cdb1798 2005-10-29 devnull static String* s_parseq(String*, String*);
5 5cdb1798 2005-10-29 devnull
6 5cdb1798 2005-10-29 devnull /* exports */
7 5cdb1798 2005-10-29 devnull dest *dlist;
8 5cdb1798 2005-10-29 devnull
9 5cdb1798 2005-10-29 devnull extern dest*
10 5cdb1798 2005-10-29 devnull d_new(String *addr)
11 5cdb1798 2005-10-29 devnull {
12 5cdb1798 2005-10-29 devnull dest *dp;
13 5cdb1798 2005-10-29 devnull
14 5cdb1798 2005-10-29 devnull dp = (dest *)mallocz(sizeof(dest), 1);
15 5cdb1798 2005-10-29 devnull if (dp == 0) {
16 5cdb1798 2005-10-29 devnull perror("d_new");
17 5cdb1798 2005-10-29 devnull exit(1);
18 5cdb1798 2005-10-29 devnull }
19 5cdb1798 2005-10-29 devnull dp->same = dp;
20 5cdb1798 2005-10-29 devnull dp->nsame = 1;
21 5cdb1798 2005-10-29 devnull dp->nchar = 0;
22 5cdb1798 2005-10-29 devnull dp->next = dp;
23 5cdb1798 2005-10-29 devnull dp->addr = escapespecial(addr);
24 5cdb1798 2005-10-29 devnull dp->parent = 0;
25 5cdb1798 2005-10-29 devnull dp->repl1 = dp->repl2 = 0;
26 5cdb1798 2005-10-29 devnull dp->status = d_undefined;
27 5cdb1798 2005-10-29 devnull return dp;
28 5cdb1798 2005-10-29 devnull }
29 5cdb1798 2005-10-29 devnull
30 5cdb1798 2005-10-29 devnull extern void
31 5cdb1798 2005-10-29 devnull d_free(dest *dp)
32 5cdb1798 2005-10-29 devnull {
33 5cdb1798 2005-10-29 devnull if (dp != 0) {
34 5cdb1798 2005-10-29 devnull s_free(dp->addr);
35 5cdb1798 2005-10-29 devnull s_free(dp->repl1);
36 5cdb1798 2005-10-29 devnull s_free(dp->repl2);
37 5cdb1798 2005-10-29 devnull free((char *)dp);
38 5cdb1798 2005-10-29 devnull }
39 5cdb1798 2005-10-29 devnull }
40 5cdb1798 2005-10-29 devnull
41 5cdb1798 2005-10-29 devnull /* The following routines manipulate an ordered list of items. Insertions
42 5cdb1798 2005-10-29 devnull * are always to the end of the list. Deletions are from the beginning.
43 5cdb1798 2005-10-29 devnull *
44 5cdb1798 2005-10-29 devnull * The list are circular witht the `head' of the list being the last item
45 5cdb1798 2005-10-29 devnull * added.
46 5cdb1798 2005-10-29 devnull */
47 5cdb1798 2005-10-29 devnull
48 5cdb1798 2005-10-29 devnull /* Get first element from a circular list linked via 'next'. */
49 5cdb1798 2005-10-29 devnull extern dest *
50 5cdb1798 2005-10-29 devnull d_rm(dest **listp)
51 5cdb1798 2005-10-29 devnull {
52 5cdb1798 2005-10-29 devnull dest *dp;
53 5cdb1798 2005-10-29 devnull
54 5cdb1798 2005-10-29 devnull if (*listp == 0)
55 5cdb1798 2005-10-29 devnull return 0;
56 5cdb1798 2005-10-29 devnull dp = (*listp)->next;
57 5cdb1798 2005-10-29 devnull if (dp == *listp)
58 5cdb1798 2005-10-29 devnull *listp = 0;
59 5cdb1798 2005-10-29 devnull else
60 5cdb1798 2005-10-29 devnull (*listp)->next = dp->next;
61 5cdb1798 2005-10-29 devnull dp->next = dp;
62 5cdb1798 2005-10-29 devnull return dp;
63 5cdb1798 2005-10-29 devnull }
64 5cdb1798 2005-10-29 devnull
65 5cdb1798 2005-10-29 devnull /* Insert a new entry at the end of the list linked via 'next'. */
66 5cdb1798 2005-10-29 devnull extern void
67 5cdb1798 2005-10-29 devnull d_insert(dest **listp, dest *new)
68 5cdb1798 2005-10-29 devnull {
69 5cdb1798 2005-10-29 devnull dest *head;
70 5cdb1798 2005-10-29 devnull
71 5cdb1798 2005-10-29 devnull if (*listp == 0) {
72 5cdb1798 2005-10-29 devnull *listp = new;
73 5cdb1798 2005-10-29 devnull return;
74 5cdb1798 2005-10-29 devnull }
75 5cdb1798 2005-10-29 devnull if (new == 0)
76 5cdb1798 2005-10-29 devnull return;
77 5cdb1798 2005-10-29 devnull head = new->next;
78 5cdb1798 2005-10-29 devnull new->next = (*listp)->next;
79 5cdb1798 2005-10-29 devnull (*listp)->next = head;
80 5cdb1798 2005-10-29 devnull *listp = new;
81 5cdb1798 2005-10-29 devnull return;
82 5cdb1798 2005-10-29 devnull }
83 5cdb1798 2005-10-29 devnull
84 5cdb1798 2005-10-29 devnull /* Get first element from a circular list linked via 'same'. */
85 5cdb1798 2005-10-29 devnull extern dest *
86 5cdb1798 2005-10-29 devnull d_rm_same(dest **listp)
87 5cdb1798 2005-10-29 devnull {
88 5cdb1798 2005-10-29 devnull dest *dp;
89 5cdb1798 2005-10-29 devnull
90 5cdb1798 2005-10-29 devnull if (*listp == 0)
91 5cdb1798 2005-10-29 devnull return 0;
92 5cdb1798 2005-10-29 devnull dp = (*listp)->same;
93 5cdb1798 2005-10-29 devnull if (dp == *listp)
94 5cdb1798 2005-10-29 devnull *listp = 0;
95 5cdb1798 2005-10-29 devnull else
96 5cdb1798 2005-10-29 devnull (*listp)->same = dp->same;
97 5cdb1798 2005-10-29 devnull dp->same = dp;
98 5cdb1798 2005-10-29 devnull return dp;
99 5cdb1798 2005-10-29 devnull }
100 5cdb1798 2005-10-29 devnull
101 5cdb1798 2005-10-29 devnull /* Look for a duplicate on the same list */
102 5cdb1798 2005-10-29 devnull int
103 5cdb1798 2005-10-29 devnull d_same_dup(dest *dp, dest *new)
104 5cdb1798 2005-10-29 devnull {
105 5cdb1798 2005-10-29 devnull dest *first = dp;
106 5cdb1798 2005-10-29 devnull
107 5cdb1798 2005-10-29 devnull if(new->repl2 == 0)
108 5cdb1798 2005-10-29 devnull return 1;
109 5cdb1798 2005-10-29 devnull do {
110 5cdb1798 2005-10-29 devnull if(strcmp(s_to_c(dp->repl2), s_to_c(new->repl2))==0)
111 5cdb1798 2005-10-29 devnull return 1;
112 5cdb1798 2005-10-29 devnull dp = dp->same;
113 5cdb1798 2005-10-29 devnull } while(dp != first);
114 5cdb1798 2005-10-29 devnull return 0;
115 5cdb1798 2005-10-29 devnull }
116 5cdb1798 2005-10-29 devnull
117 5cdb1798 2005-10-29 devnull /* Insert an entry into the corresponding list linked by 'same'. Note that
118 5cdb1798 2005-10-29 devnull * the basic structure is a list of lists.
119 5cdb1798 2005-10-29 devnull */
120 5cdb1798 2005-10-29 devnull extern void
121 5cdb1798 2005-10-29 devnull d_same_insert(dest **listp, dest *new)
122 5cdb1798 2005-10-29 devnull {
123 5cdb1798 2005-10-29 devnull dest *dp;
124 5cdb1798 2005-10-29 devnull int len;
125 5cdb1798 2005-10-29 devnull
126 5cdb1798 2005-10-29 devnull if(new->status == d_pipe || new->status == d_cat) {
127 5cdb1798 2005-10-29 devnull len = new->repl2 ? strlen(s_to_c(new->repl2)) : 0;
128 5cdb1798 2005-10-29 devnull if(*listp != 0){
129 5cdb1798 2005-10-29 devnull dp = (*listp)->next;
130 5cdb1798 2005-10-29 devnull do {
131 5cdb1798 2005-10-29 devnull if(dp->status == new->status
132 5cdb1798 2005-10-29 devnull && strcmp(s_to_c(dp->repl1), s_to_c(new->repl1))==0){
133 5cdb1798 2005-10-29 devnull /* remove duplicates */
134 5cdb1798 2005-10-29 devnull if(d_same_dup(dp, new))
135 5cdb1798 2005-10-29 devnull return;
136 5cdb1798 2005-10-29 devnull /* add to chain if chain small enough */
137 5cdb1798 2005-10-29 devnull if(dp->nsame < MAXSAME
138 5cdb1798 2005-10-29 devnull && dp->nchar + len < MAXSAMECHAR){
139 5cdb1798 2005-10-29 devnull new->same = dp->same;
140 5cdb1798 2005-10-29 devnull dp->same = new;
141 5cdb1798 2005-10-29 devnull dp->nchar += len + 1;
142 5cdb1798 2005-10-29 devnull dp->nsame++;
143 5cdb1798 2005-10-29 devnull return;
144 5cdb1798 2005-10-29 devnull }
145 5cdb1798 2005-10-29 devnull }
146 5cdb1798 2005-10-29 devnull dp = dp->next;
147 5cdb1798 2005-10-29 devnull } while (dp != (*listp)->next);
148 5cdb1798 2005-10-29 devnull }
149 5cdb1798 2005-10-29 devnull new->nchar = strlen(s_to_c(new->repl1)) + len + 1;
150 5cdb1798 2005-10-29 devnull }
151 5cdb1798 2005-10-29 devnull new->next = new;
152 5cdb1798 2005-10-29 devnull d_insert(listp, new);
153 5cdb1798 2005-10-29 devnull }
154 5cdb1798 2005-10-29 devnull
155 5cdb1798 2005-10-29 devnull /*
156 5cdb1798 2005-10-29 devnull * Form a To: if multiple destinations.
157 5cdb1798 2005-10-29 devnull * The local! and !local! checks are artificial intelligence,
158 5cdb1798 2005-10-29 devnull * there should be a better way.
159 5cdb1798 2005-10-29 devnull */
160 5cdb1798 2005-10-29 devnull extern String*
161 5cdb1798 2005-10-29 devnull d_to(dest *list)
162 5cdb1798 2005-10-29 devnull {
163 5cdb1798 2005-10-29 devnull dest *np, *sp;
164 5cdb1798 2005-10-29 devnull String *s;
165 5cdb1798 2005-10-29 devnull int i, n;
166 5cdb1798 2005-10-29 devnull char *cp;
167 5cdb1798 2005-10-29 devnull
168 5cdb1798 2005-10-29 devnull s = s_new();
169 5cdb1798 2005-10-29 devnull s_append(s, "To: ");
170 5cdb1798 2005-10-29 devnull np = list;
171 5cdb1798 2005-10-29 devnull i = n = 0;
172 5cdb1798 2005-10-29 devnull do {
173 5cdb1798 2005-10-29 devnull np = np->next;
174 5cdb1798 2005-10-29 devnull sp = np;
175 5cdb1798 2005-10-29 devnull do {
176 5cdb1798 2005-10-29 devnull sp = sp->same;
177 5cdb1798 2005-10-29 devnull cp = s_to_c(sp->addr);
178 5cdb1798 2005-10-29 devnull
179 5cdb1798 2005-10-29 devnull /* hack to get local! out of the names */
180 5cdb1798 2005-10-29 devnull if(strncmp(cp, "local!", 6) == 0)
181 5cdb1798 2005-10-29 devnull cp += 6;
182 5cdb1798 2005-10-29 devnull
183 5cdb1798 2005-10-29 devnull if(n > 20){ /* 20 to appease mailers complaining about long lines */
184 5cdb1798 2005-10-29 devnull s_append(s, "\n\t");
185 5cdb1798 2005-10-29 devnull n = 0;
186 5cdb1798 2005-10-29 devnull }
187 5cdb1798 2005-10-29 devnull if(i != 0){
188 5cdb1798 2005-10-29 devnull s_append(s, ", ");
189 5cdb1798 2005-10-29 devnull n += 2;
190 5cdb1798 2005-10-29 devnull }
191 5cdb1798 2005-10-29 devnull s_append(s, cp);
192 5cdb1798 2005-10-29 devnull n += strlen(cp);
193 5cdb1798 2005-10-29 devnull i++;
194 5cdb1798 2005-10-29 devnull } while(sp != np);
195 5cdb1798 2005-10-29 devnull } while(np != list);
196 5cdb1798 2005-10-29 devnull
197 5cdb1798 2005-10-29 devnull return unescapespecial(s);
198 5cdb1798 2005-10-29 devnull }
199 5cdb1798 2005-10-29 devnull
200 5cdb1798 2005-10-29 devnull /* expand a String of destinations into a linked list of destiniations */
201 5cdb1798 2005-10-29 devnull extern dest *
202 5cdb1798 2005-10-29 devnull s_to_dest(String *sp, dest *parent)
203 5cdb1798 2005-10-29 devnull {
204 5cdb1798 2005-10-29 devnull String *addr;
205 5cdb1798 2005-10-29 devnull dest *list=0;
206 5cdb1798 2005-10-29 devnull dest *new;
207 5cdb1798 2005-10-29 devnull
208 5cdb1798 2005-10-29 devnull if (sp == 0)
209 5cdb1798 2005-10-29 devnull return 0;
210 5cdb1798 2005-10-29 devnull addr = s_new();
211 5cdb1798 2005-10-29 devnull while (s_parseq(sp, addr)!=0) {
212 5cdb1798 2005-10-29 devnull addr = escapespecial(addr);
213 5cdb1798 2005-10-29 devnull if(shellchars(s_to_c(addr))){
214 5cdb1798 2005-10-29 devnull while(new = d_rm(&list))
215 5cdb1798 2005-10-29 devnull d_free(new);
216 5cdb1798 2005-10-29 devnull break;
217 5cdb1798 2005-10-29 devnull }
218 5cdb1798 2005-10-29 devnull new = d_new(addr);
219 5cdb1798 2005-10-29 devnull new->parent = parent;
220 5cdb1798 2005-10-29 devnull new->authorized = parent->authorized;
221 5cdb1798 2005-10-29 devnull d_insert(&list, new);
222 5cdb1798 2005-10-29 devnull addr = s_new();
223 5cdb1798 2005-10-29 devnull }
224 5cdb1798 2005-10-29 devnull s_free(addr);
225 5cdb1798 2005-10-29 devnull return list;
226 5cdb1798 2005-10-29 devnull }
227 5cdb1798 2005-10-29 devnull
228 5cdb1798 2005-10-29 devnull #undef isspace
229 5cdb1798 2005-10-29 devnull #define isspace(c) ((c)==' ' || (c)=='\t' || (c)=='\n')
230 5cdb1798 2005-10-29 devnull
231 5cdb1798 2005-10-29 devnull /* Get the next field from a String. The field is delimited by white space.
232 5cdb1798 2005-10-29 devnull * Anything delimited by double quotes is included in the string.
233 5cdb1798 2005-10-29 devnull */
234 5cdb1798 2005-10-29 devnull static String*
235 5cdb1798 2005-10-29 devnull s_parseq(String *from, String *to)
236 5cdb1798 2005-10-29 devnull {
237 5cdb1798 2005-10-29 devnull int c;
238 5cdb1798 2005-10-29 devnull
239 5cdb1798 2005-10-29 devnull if (*from->ptr == '\0')
240 5cdb1798 2005-10-29 devnull return 0;
241 5cdb1798 2005-10-29 devnull if (to == 0)
242 5cdb1798 2005-10-29 devnull to = s_new();
243 5cdb1798 2005-10-29 devnull for (c = *from->ptr;!isspace(c) && c != 0; c = *(++from->ptr)){
244 5cdb1798 2005-10-29 devnull s_putc(to, c);
245 5cdb1798 2005-10-29 devnull if(c == '"'){
246 5cdb1798 2005-10-29 devnull for (c = *(++from->ptr); c && c != '"'; c = *(++from->ptr))
247 5cdb1798 2005-10-29 devnull s_putc(to, *from->ptr);
248 5cdb1798 2005-10-29 devnull s_putc(to, '"');
249 5cdb1798 2005-10-29 devnull if(c == 0)
250 5cdb1798 2005-10-29 devnull break;
251 5cdb1798 2005-10-29 devnull }
252 5cdb1798 2005-10-29 devnull }
253 5cdb1798 2005-10-29 devnull s_terminate(to);
254 5cdb1798 2005-10-29 devnull
255 5cdb1798 2005-10-29 devnull /* crunch trailing white */
256 5cdb1798 2005-10-29 devnull while(isspace(*from->ptr))
257 5cdb1798 2005-10-29 devnull from->ptr++;
258 5cdb1798 2005-10-29 devnull
259 5cdb1798 2005-10-29 devnull return to;
260 5cdb1798 2005-10-29 devnull }