4 static String* s_parseq(String*, String*);
14 dp = (dest *)mallocz(sizeof(dest), 1);
23 dp->addr = escapespecial(addr);
25 dp->repl1 = dp->repl2 = 0;
26 dp->status = d_undefined;
41 /* The following routines manipulate an ordered list of items. Insertions
42 * are always to the end of the list. Deletions are from the beginning.
44 * The list are circular witht the `head' of the list being the last item
48 /* Get first element from a circular list linked via 'next'. */
60 (*listp)->next = dp->next;
65 /* Insert a new entry at the end of the list linked via 'next'. */
67 d_insert(dest **listp, dest *new)
78 new->next = (*listp)->next;
79 (*listp)->next = head;
84 /* Get first element from a circular list linked via 'same'. */
86 d_rm_same(dest **listp)
96 (*listp)->same = dp->same;
101 /* Look for a duplicate on the same list */
103 d_same_dup(dest *dp, dest *new)
110 if(strcmp(s_to_c(dp->repl2), s_to_c(new->repl2))==0)
113 } while(dp != first);
117 /* Insert an entry into the corresponding list linked by 'same'. Note that
118 * the basic structure is a list of lists.
121 d_same_insert(dest **listp, dest *new)
126 if(new->status == d_pipe || new->status == d_cat) {
127 len = new->repl2 ? strlen(s_to_c(new->repl2)) : 0;
131 if(dp->status == new->status
132 && strcmp(s_to_c(dp->repl1), s_to_c(new->repl1))==0){
133 /* remove duplicates */
134 if(d_same_dup(dp, new))
136 /* add to chain if chain small enough */
137 if(dp->nsame < MAXSAME
138 && dp->nchar + len < MAXSAMECHAR){
139 new->same = dp->same;
141 dp->nchar += len + 1;
147 } while (dp != (*listp)->next);
149 new->nchar = strlen(s_to_c(new->repl1)) + len + 1;
152 d_insert(listp, new);
156 * Form a To: if multiple destinations.
157 * The local! and !local! checks are artificial intelligence,
158 * there should be a better way.
177 cp = s_to_c(sp->addr);
179 /* hack to get local! out of the names */
180 if(strncmp(cp, "local!", 6) == 0)
183 if(n > 20){ /* 20 to appease mailers complaining about long lines */
197 return unescapespecial(s);
200 /* expand a String of destinations into a linked list of destiniations */
202 s_to_dest(String *sp, dest *parent)
211 while (s_parseq(sp, addr)!=0) {
212 addr = escapespecial(addr);
213 if(shellchars(s_to_c(addr))){
214 while(new = d_rm(&list))
219 new->parent = parent;
220 new->authorized = parent->authorized;
221 d_insert(&list, new);
229 #define isspace(c) ((c)==' ' || (c)=='\t' || (c)=='\n')
231 /* Get the next field from a String. The field is delimited by white space.
232 * Anything delimited by double quotes is included in the string.
235 s_parseq(String *from, String *to)
239 if (*from->ptr == '\0')
243 for (c = *from->ptr;!isspace(c) && c != 0; c = *(++from->ptr)){
246 for (c = *(++from->ptr); c && c != '"'; c = *(++from->ptr))
247 s_putc(to, *from->ptr);
255 /* crunch trailing white */
256 while(isspace(*from->ptr))