123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- #include "common.h"
- #include "send.h"
- static String* s_parseq(String*, String*);
- /* exports */
- dest *dlist;
- extern dest*
- d_new(String *addr)
- {
- dest *dp;
- dp = (dest *)mallocz(sizeof(dest), 1);
- if (dp == 0) {
- perror("d_new");
- exit(1);
- }
- dp->same = dp;
- dp->nsame = 1;
- dp->nchar = 0;
- dp->next = dp;
- dp->addr = escapespecial(addr);
- dp->parent = 0;
- dp->repl1 = dp->repl2 = 0;
- dp->status = d_undefined;
- return dp;
- }
- extern void
- d_free(dest *dp)
- {
- if (dp != 0) {
- s_free(dp->addr);
- s_free(dp->repl1);
- s_free(dp->repl2);
- free((char *)dp);
- }
- }
- /* The following routines manipulate an ordered list of items. Insertions
- * are always to the end of the list. Deletions are from the beginning.
- *
- * The list are circular witht the `head' of the list being the last item
- * added.
- */
- /* Get first element from a circular list linked via 'next'. */
- extern dest *
- d_rm(dest **listp)
- {
- dest *dp;
- if (*listp == 0)
- return 0;
- dp = (*listp)->next;
- if (dp == *listp)
- *listp = 0;
- else
- (*listp)->next = dp->next;
- dp->next = dp;
- return dp;
- }
- /* Insert a new entry at the end of the list linked via 'next'. */
- extern void
- d_insert(dest **listp, dest *new)
- {
- dest *head;
- if (*listp == 0) {
- *listp = new;
- return;
- }
- if (new == 0)
- return;
- head = new->next;
- new->next = (*listp)->next;
- (*listp)->next = head;
- *listp = new;
- return;
- }
- /* Get first element from a circular list linked via 'same'. */
- extern dest *
- d_rm_same(dest **listp)
- {
- dest *dp;
- if (*listp == 0)
- return 0;
- dp = (*listp)->same;
- if (dp == *listp)
- *listp = 0;
- else
- (*listp)->same = dp->same;
- dp->same = dp;
- return dp;
- }
- /* Look for a duplicate on the same list */
- int
- d_same_dup(dest *dp, dest *new)
- {
- dest *first = dp;
- if(new->repl2 == 0)
- return 1;
- do {
- if(strcmp(s_to_c(dp->repl2), s_to_c(new->repl2))==0)
- return 1;
- dp = dp->same;
- } while(dp != first);
- return 0;
- }
- /* Insert an entry into the corresponding list linked by 'same'. Note that
- * the basic structure is a list of lists.
- */
- extern void
- d_same_insert(dest **listp, dest *new)
- {
- dest *dp;
- int len;
- if(new->status == d_pipe || new->status == d_cat) {
- len = new->repl2 ? strlen(s_to_c(new->repl2)) : 0;
- if(*listp != 0){
- dp = (*listp)->next;
- do {
- if(dp->status == new->status
- && strcmp(s_to_c(dp->repl1), s_to_c(new->repl1))==0){
- /* remove duplicates */
- if(d_same_dup(dp, new))
- return;
- /* add to chain if chain small enough */
- if(dp->nsame < MAXSAME
- && dp->nchar + len < MAXSAMECHAR){
- new->same = dp->same;
- dp->same = new;
- dp->nchar += len + 1;
- dp->nsame++;
- return;
- }
- }
- dp = dp->next;
- } while (dp != (*listp)->next);
- }
- new->nchar = strlen(s_to_c(new->repl1)) + len + 1;
- }
- new->next = new;
- d_insert(listp, new);
- }
- /*
- * Form a To: if multiple destinations.
- * The local! and !local! checks are artificial intelligence,
- * there should be a better way.
- */
- extern String*
- d_to(dest *list)
- {
- dest *np, *sp;
- String *s;
- int i, n;
- char *cp;
- s = s_new();
- s_append(s, "To: ");
- np = list;
- i = n = 0;
- do {
- np = np->next;
- sp = np;
- do {
- sp = sp->same;
- cp = s_to_c(sp->addr);
- /* hack to get local! out of the names */
- if(strncmp(cp, "local!", 6) == 0)
- cp += 6;
- if(n > 20){ /* 20 to appease mailers complaining about long lines */
- s_append(s, "\n\t");
- n = 0;
- }
- if(i != 0){
- s_append(s, ", ");
- n += 2;
- }
- s_append(s, cp);
- n += strlen(cp);
- i++;
- } while(sp != np);
- } while(np != list);
- return unescapespecial(s);
- }
- /* expand a String of destinations into a linked list of destiniations */
- extern dest *
- s_to_dest(String *sp, dest *parent)
- {
- String *addr;
- dest *list=0;
- dest *new;
- if (sp == 0)
- return 0;
- addr = s_new();
- while (s_parseq(sp, addr)!=0) {
- addr = escapespecial(addr);
- if(shellchars(s_to_c(addr))){
- while(new = d_rm(&list))
- d_free(new);
- break;
- }
- new = d_new(addr);
- new->parent = parent;
- new->authorized = parent->authorized;
- d_insert(&list, new);
- addr = s_new();
- }
- s_free(addr);
- return list;
- }
- #define isspace(c) ((c)==' ' || (c)=='\t' || (c)=='\n')
- /* Get the next field from a String. The field is delimited by white space.
- * Anything delimited by double quotes is included in the string.
- */
- static String*
- s_parseq(String *from, String *to)
- {
- int c;
- if (*from->ptr == '\0')
- return 0;
- if (to == 0)
- to = s_new();
- for (c = *from->ptr;!isspace(c) && c != 0; c = *(++from->ptr)){
- s_putc(to, c);
- if(c == '"'){
- for (c = *(++from->ptr); c && c != '"'; c = *(++from->ptr))
- s_putc(to, *from->ptr);
- s_putc(to, '"');
- if(c == 0)
- break;
- }
- }
- s_terminate(to);
- /* crunch trailing white */
- while(isspace(*from->ptr))
- from->ptr++;
- return to;
- }
|