1 # include <stdio.h> 2 # include <ctype.h> 3 # include <pwd.h> 4 # include "dlvrmail.h" 5 6 static char SccsId[] = "@(#)alias.c 1.4 10/17/80"; 7 8 /* 9 ** ALIAS -- Compute aliases. 10 ** 11 ** Scans the file ALIASFILE for a set of aliases. 12 ** If found, it arranges to deliver to them by inserting the 13 ** new names onto the SendQ queue. Uses libdbm database if -DDBM. 14 ** 15 ** Parameters: 16 ** none 17 ** 18 ** Returns: 19 ** none 20 ** 21 ** Side Effects: 22 ** Aliases found on SendQ are removed and put onto 23 ** AliasQ; replacements are added to SendQ. This is 24 ** done until no such replacement occurs. 25 ** 26 ** Defined Constants: 27 ** MAXRCRSN -- the maximum recursion depth. 28 ** ALIASFILE -- the pathname of the alias file. 29 ** 30 ** Called By: 31 ** main 32 ** 33 ** Files: 34 ** ALIASFILE -- the mail aliases. The format is 35 ** a series of lines of the form: 36 ** alias:name1,name2,name3,... 37 ** where 'alias' expands to all of 38 ** 'name[i]'. Continuations begin with 39 ** space or tab. 40 ** ALIASFILE.pag, ALIASFILE.dir: libdbm version 41 ** of alias file. Keys are aliases, datums 42 ** (data?) are name1,name2, ... 43 ** 44 ** Notes: 45 ** If NoAlias (the "-n" flag) is set, no aliasing is 46 ** done. 47 ** 48 ** Deficiencies: 49 ** It should complain about names that are aliased to 50 ** nothing. 51 ** It is unsophisticated about line overflows. 52 */ 53 54 55 # define ALIASFILE "/usr/lib/mailaliases" 56 # define MAXRCRSN 10 57 58 #ifdef DBM 59 typedef struct {char *dptr; int dsize;} datum; 60 datum lhs, rhs; 61 datum fetch(); 62 #endif DBM 63 64 alias() 65 { 66 register addrq *q; 67 FILE *af; 68 char line[MAXLINE+1]; 69 register char *p; 70 extern int errno; 71 bool didalias; 72 bool gotmatch; 73 auto addrq al; 74 extern bool sameaddr(); 75 extern addrq *parse(); 76 77 if (NoAlias) 78 return; 79 # ifdef DEBUG 80 if (Debug) 81 printf("--- alias ---\n"); 82 # endif 83 84 /* open alias file if not already open */ 85 #ifndef DBM 86 # ifdef DEBUG 87 if (Debug && (af = fopen("mailaliases", "r")) != NULL) 88 printf(" [using local alias file]\n"); 89 else 90 # endif 91 if ((af = fopen(ALIASFILE, "r")) == NULL) 92 { 93 # ifdef DEBUG 94 if (Debug) 95 printf("Can't open %s\n", ALIASFILE); 96 # endif 97 errno = 0; 98 return; 99 } 100 #else DBM 101 dbminit(ALIASFILE); 102 #endif DBM 103 104 #ifndef DBM 105 /* 106 ** Scan alias file. 107 ** If we find any user that any line matches any user, we 108 ** will send to the line rather than to the user. 109 ** 110 ** We pass through the file several times. Didalias tells 111 ** us if we took some alias on this pass through the file; 112 ** when it goes false at the top of the loop we don't have 113 ** to scan any more. Gotmatch tells the same thing, but 114 ** on a line-by-line basis; it is used for processing 115 ** continuation lines. 116 */ 117 118 do 119 { 120 didalias = FALSE; 121 gotmatch = FALSE; 122 rewind(af); 123 while (fgets(line, sizeof line, af) != NULL) 124 { 125 /* comments begin with `#' */ 126 if (line[0] == '#') 127 continue; 128 129 /* check for continuation lines */ 130 if (isspace(line[0])) 131 { 132 if (gotmatch) 133 { 134 sendto(line, 1); 135 } 136 continue; 137 } 138 gotmatch = FALSE; 139 140 /* 141 ** Check to see if this pseudonym exists in SendQ. 142 ** Turn the alias into canonical form. 143 ** Then scan SendQ until you do (or do not) 144 ** find that address. 145 */ 146 147 /* Get a canonical form for the alias. */ 148 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 149 continue; 150 if (*p == '\0' || *p == '\n') 151 { 152 syntaxerr: 153 syserr("Bad alias line `%s'", line); 154 continue; 155 } 156 *p++ = '\0'; 157 if (parse(line, &al, -1) == NULL) 158 { 159 *--p = ':'; 160 goto syntaxerr; 161 } 162 163 /* Scan SendQ for that canonical form. */ 164 for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 165 { 166 if (sameaddr(&al, q, TRUE)) 167 break; 168 } 169 if (q != NULL) 170 { 171 #else DBM 172 /* 173 ** Scan SendQ 174 ** We pass through the queue several times. Didalias tells 175 ** us if we took some alias on this pass through the queue; 176 ** when it goes false at the top of the loop we don't have 177 ** to scan any more. 178 */ 179 180 do 181 { 182 didalias = FALSE; 183 /* Scan SendQ for that canonical form. */ 184 for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 185 { 186 lhs.dptr = q -> q_paddr; 187 lhs.dsize = strlen(lhs.dptr)+1; 188 rhs = fetch(lhs); 189 p = rhs.dptr; 190 if (p != NULL) 191 { 192 #endif 193 /* 194 ** Match on Alias. 195 ** Deliver to the target list. 196 ** Remove the alias from the send queue 197 ** and put it on the Alias queue. 198 */ 199 200 # ifdef DEBUG 201 if (Debug) 202 printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 203 q->q_paddr, q->q_host, q->q_user, 204 p, al.q_paddr, al.q_host, al.q_user); 205 # endif 206 tkoffq(q, &SendQ); 207 putonq(q, &AliasQ); 208 didalias++; 209 gotmatch++; 210 sendto(p, 1); 211 } 212 } 213 } while (didalias); 214 #ifndef DBM 215 fclose(af); 216 #endif 217 } 218 /* 219 ** FORWARD -- Try to forward mail 220 ** 221 ** This is similar but not identical to aliasing. 222 ** 223 ** Currently it is undefined, until the protocol for userinfo 224 ** databases is finalized. 225 ** 226 ** Parameters: 227 ** user -- the name of the user who's mail we 228 ** would like to forward to. 229 ** 230 ** Returns: 231 ** TRUE -- we have forwarded it somewhere. 232 ** FALSE -- not forwarded; go ahead & deliver. 233 ** 234 ** Side Effects: 235 ** New names are added to SendQ. 236 ** 237 ** Called By: 238 ** recipient 239 */ 240 241 bool 242 forward(user) 243 addrq *user; 244 { 245 return (FALSE); 246 } 247