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