1 # include <stdio.h> 2 # include <ctype.h> 3 # include <pwd.h> 4 # include "dlvrmail.h" 5 6 static char SccsId[] = "@(#)alias.c 2.2 12/06/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 ** 29 ** Called By: 30 ** main 31 ** 32 ** Files: 33 ** ALIASFILE -- the mail aliases. The format is 34 ** a series of lines of the form: 35 ** alias:name1,name2,name3,... 36 ** where 'alias' expands to all of 37 ** 'name[i]'. Continuations begin with 38 ** space or tab. 39 ** ALIASFILE.pag, ALIASFILE.dir: libdbm version 40 ** of alias file. Keys are aliases, datums 41 ** (data?) are name1,name2, ... 42 ** 43 ** Notes: 44 ** If NoAlias (the "-n" flag) is set, no aliasing is 45 ** done. 46 ** 47 ** Deficiencies: 48 ** It should complain about names that are aliased to 49 ** nothing. 50 ** It is unsophisticated about line overflows. 51 */ 52 53 54 # define MAXRCRSN 10 55 56 #ifdef DBM 57 typedef struct {char *dptr; int dsize;} datum; 58 datum lhs, rhs; 59 extern datum fetch(); 60 #endif DBM 61 62 alias() 63 { 64 register addrq *q; 65 addrq *q2; 66 FILE *af; 67 char line[MAXLINE+1]; 68 register char *p; 69 extern int errno; 70 bool didalias; 71 bool gotmatch; 72 auto addrq al; 73 extern bool sameaddr(); 74 extern addrq *parse(); 75 76 if (NoAlias) 77 return; 78 # ifdef DEBUG 79 if (Debug) 80 printf("--- alias ---\n"); 81 # endif 82 83 /* open alias file if not already open */ 84 #ifndef DBM 85 # ifdef DEBUG 86 if (Debug && (af = fopen("mailaliases", "r")) != NULL) 87 printf(" [using local alias file]\n"); 88 else 89 # endif 90 if ((af = fopen(ALIASFILE, "r")) == NULL) 91 { 92 # ifdef DEBUG 93 if (Debug) 94 printf("Can't open %s\n", ALIASFILE); 95 # endif 96 errno = 0; 97 return; 98 } 99 #else DBM 100 dbminit(ALIASFILE); 101 #endif DBM 102 103 #ifndef DBM 104 /* 105 ** Scan alias file. 106 ** If we find any user that any line matches any user, we 107 ** will send to the line rather than to the user. 108 ** 109 ** We pass through the file several times. Didalias tells 110 ** us if we took some alias on this pass through the file; 111 ** when it goes false at the top of the loop we don't have 112 ** to scan any more. Gotmatch tells the same thing, but 113 ** on a line-by-line basis; it is used for processing 114 ** continuation lines. 115 */ 116 117 do 118 { 119 didalias = FALSE; 120 gotmatch = FALSE; 121 rewind(af); 122 while (fgets(line, sizeof line, af) != NULL) 123 { 124 /* comments begin with `#' */ 125 if (line[0] == '#') 126 continue; 127 128 /* check for continuation lines */ 129 if (isspace(line[0])) 130 { 131 if (gotmatch) 132 { 133 sendto(line, 1); 134 } 135 continue; 136 } 137 gotmatch = FALSE; 138 139 /* 140 ** Check to see if this pseudonym exists in SendQ. 141 ** Turn the alias into canonical form. 142 ** Then scan SendQ until you do (or do not) 143 ** find that address. 144 */ 145 146 /* Get a canonical form for the alias. */ 147 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 148 continue; 149 if (*p == '\0' || *p == '\n') 150 { 151 syntaxerr: 152 syserr("Bad alias line `%s'", line); 153 continue; 154 } 155 *p++ = '\0'; 156 if (parse(line, &al, -1) == NULL) 157 { 158 *--p = ':'; 159 goto syntaxerr; 160 } 161 162 /* if already in AliasQ don't realias */ 163 for (q = &AliasQ; (q = nxtinq(q)) != NULL; ) 164 { 165 if (sameaddr(&al, q, TRUE)) 166 break; 167 } 168 if (q != NULL) 169 continue; 170 171 /* Scan SendQ for that canonical form. */ 172 for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 173 { 174 if (sameaddr(&al, q, TRUE)) 175 break; 176 } 177 if (q != NULL) 178 { 179 /* 180 ** Match on Alias. 181 ** Deliver to the target list. 182 ** Remove the alias from the send queue 183 ** and put it on the Alias queue. 184 */ 185 186 # ifdef DEBUG 187 if (Debug) 188 printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 189 q->q_paddr, q->q_host, q->q_user, 190 p, al.q_paddr, al.q_host, al.q_user); 191 # endif 192 tkoffq(q, &SendQ); 193 didalias++; 194 gotmatch++; 195 sendto(p, 1); 196 putonq(q, &AliasQ); 197 } 198 } 199 } while (didalias); 200 fclose(af); 201 #else DBM 202 /* 203 ** Scan SendQ 204 ** We only have to do this once, since anything we alias 205 ** to is being put at the end of the queue we are 206 ** scanning. 207 ** If the alias on SendQ is also (already) on AliasQ, we 208 ** have an alias such as: 209 ** eric:eric,i:eric 210 ** In this case we have already done this alias once, and 211 ** we don't want to do it again (for obvious reasons!). 212 */ 213 214 for (q2 = nxtinq(&SendQ); q2 != NULL; ) 215 { 216 /* if already in AliasQ, don't realias */ 217 for (q = &AliasQ; (q = nxtinq(q)) != NULL; ) 218 { 219 if (sameaddr(q, q2, TRUE)) 220 break; 221 } 222 if (q != NULL) 223 { 224 q2 = nxtinq(q2); 225 continue; 226 } 227 228 /* save ptr to next address */ 229 q = q2; 230 q2 = nxtinq(q); 231 232 /* only alias local users */ 233 if (q->q_mailer != &Mailer[0]) 234 continue; 235 236 /* create a key for fetch */ 237 lhs.dptr = q->q_user; 238 lhs.dsize = strlen(q->q_user) + 1; 239 rhs = fetch(lhs); 240 241 /* find this alias? */ 242 p = rhs.dptr; 243 if (p == NULL) 244 continue; 245 246 /* 247 ** Match on Alias. 248 ** Deliver to the target list. 249 ** Remove the alias from the send queue 250 ** and put it on the Alias queue. 251 */ 252 253 # ifdef DEBUG 254 if (Debug) 255 printf("%s (%s, %s) aliased to %s\n", 256 q->q_paddr, q->q_host, q->q_user, p); 257 # endif 258 tkoffq(q, &SendQ); 259 sendto(p, 1); 260 putonq(q, &AliasQ); 261 262 /* if our last entry had an alias, process them */ 263 if (q2 == NULL) 264 q2 = nxtinq(&SendQ); 265 } 266 #endif DBM 267 } 268 /* 269 ** FORWARD -- Try to forward mail 270 ** 271 ** This is similar but not identical to aliasing. 272 ** 273 ** Currently it is undefined, until the protocol for userinfo 274 ** databases is finalized. 275 ** 276 ** Parameters: 277 ** user -- the name of the user who's mail we 278 ** would like to forward to. 279 ** 280 ** Returns: 281 ** TRUE -- we have forwarded it somewhere. 282 ** FALSE -- not forwarded; go ahead & deliver. 283 ** 284 ** Side Effects: 285 ** New names are added to SendQ. 286 ** 287 ** Called By: 288 ** recipient 289 */ 290 291 bool 292 forward(user) 293 addrq *user; 294 { 295 return (FALSE); 296 } 297