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