1 # include <stdio.h> 2 # include <ctype.h> 3 # include <pwd.h> 4 # include "sendmail.h" 5 6 static char SccsId[] = "@(#)alias.c 3.8 08/09/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. Uses libdbm 13 ** database if -DDBM. 14 ** 15 ** Parameters: 16 ** none 17 ** 18 ** Returns: 19 ** none 20 ** 21 ** Side Effects: 22 ** Aliases found are expanded. 23 ** 24 ** Defined Constants: 25 ** MAXRCRSN -- the maximum recursion depth. 26 ** 27 ** Files: 28 ** ALIASFILE -- the mail aliases. The format is 29 ** a series of lines of the form: 30 ** alias:name1,name2,name3,... 31 ** where 'alias' expands to all of 32 ** 'name[i]'. Continuations begin with 33 ** space or tab. 34 ** ALIASFILE.pag, ALIASFILE.dir: libdbm version 35 ** of alias file. Keys are aliases, datums 36 ** (data?) are name1,name2, ... 37 ** 38 ** Notes: 39 ** If NoAlias (the "-n" flag) is set, no aliasing is 40 ** done. 41 ** 42 ** Deficiencies: 43 ** It should complain about names that are aliased to 44 ** nothing. 45 ** It is unsophisticated about line overflows. 46 */ 47 48 49 # define MAXRCRSN 10 50 51 #ifdef DBM 52 typedef struct 53 { 54 char *dptr; 55 int dsize; 56 } datum; 57 datum lhs, rhs; 58 extern datum fetch(); 59 #endif DBM 60 61 alias() 62 { 63 register ADDRESS *q; 64 register char *p; 65 # ifndef DBM 66 FILE *af; 67 char line[MAXLINE+1]; 68 bool didalias; 69 bool gotmatch; 70 auto ADDRESS al; 71 # else 72 int mno; 73 # endif DBM 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. 140 ** Turn the alias into canonical form. 141 ** Then scan the send queue until you 142 ** do (or do not) 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 /* if already queued up, don't realias */ 162 for (q = Mailer[al.q_mailer]->m_sendq; q != NULL; q = q->q_next) 163 { 164 if (sameaddr(&al, q, TRUE)) 165 break; 166 } 167 if (q == NULL || bitset(QDONTSEND, q->q_flags)) 168 continue; 169 170 /* 171 ** Match on Alias. 172 ** Deliver to the target list. 173 ** Remove the alias from the send queue 174 ** and put it on the Alias queue. 175 */ 176 177 # ifdef DEBUG 178 if (Debug) 179 printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 180 q->q_paddr, q->q_host, q->q_user, 181 p, al.q_paddr, al.q_host, al.q_user); 182 # endif 183 if (Verbose) 184 message("050", "aliased to %s", p); 185 q->q_flags |= QDONTSEND; 186 didalias++; 187 gotmatch++; 188 sendto(p, 1); 189 } 190 } while (didalias); 191 (void) fclose(af); 192 #else DBM 193 /* 194 ** Scan send queues 195 ** We only have to do this once, since anything we alias 196 ** to is being put at the end of the queue we are 197 ** scanning. 198 */ 199 200 for (mno = 0; Mailer[mno] != NULL; mno++) 201 { 202 for (q = Mailer[mno]->m_sendq; q != NULL; q = q->q_next) 203 { 204 To = q->q_paddr; 205 206 /* don't realias already aliased names */ 207 if (bitset(QDONTSEND, q->q_flags)) 208 continue; 209 210 /* only alias local users */ 211 if (q->q_mailer != M_LOCAL) 212 continue; 213 214 /* create a key for fetch */ 215 lhs.dptr = q->q_user; 216 lhs.dsize = strlen(q->q_user) + 1; 217 rhs = fetch(lhs); 218 219 /* find this alias? */ 220 p = rhs.dptr; 221 if (p == NULL) 222 continue; 223 224 /* 225 ** Match on Alias. 226 ** Deliver to the target list. 227 ** Remove the alias from the send queue 228 ** and put it on the Alias queue. 229 */ 230 231 # ifdef DEBUG 232 if (Debug) 233 printf("%s (%s, %s) aliased to %s\n", 234 q->q_paddr, q->q_host, q->q_user, p); 235 # endif 236 if (Verbose) 237 message("050", "aliased to %s", p); 238 q->q_flags |= QDONTSEND; 239 sendto(p, 1); 240 } 241 } 242 #endif DBM 243 } 244 /* 245 ** FORWARD -- Try to forward mail 246 ** 247 ** This is similar but not identical to aliasing. 248 ** 249 ** Currently it is undefined, until the protocol for userinfo 250 ** databases is finalized. 251 ** 252 ** Parameters: 253 ** user -- the name of the user who's mail we 254 ** would like to forward to. 255 ** 256 ** Returns: 257 ** TRUE -- we have forwarded it somewhere. 258 ** FALSE -- not forwarded; go ahead & deliver. 259 ** 260 ** Side Effects: 261 ** New names are added to send queues. 262 */ 263 264 bool 265 forward(user) 266 ADDRESS *user; 267 { 268 char buf[60]; 269 register FILE *fp; 270 register char *p; 271 272 if (user->q_mailer != M_LOCAL || bitset(QBADADDR, user->q_flags)) 273 return (FALSE); 274 275 /* good address -- look for .forward file in home */ 276 (void) expand("$z/.forward", buf, &buf[sizeof buf - 1]); 277 fp = fopen(buf, "r"); 278 if (fp == NULL) 279 return (FALSE); 280 281 /* we do have an address to forward to -- do it */ 282 (void) fgets(buf, sizeof buf, fp); 283 if ((p = index(buf, '\n')) != NULL) 284 *p = '\0'; 285 (void) fclose(fp); 286 if (buf[0] == '\0') 287 return (FALSE); 288 if (Verbose) 289 message("050", "forwarded to %s", buf); 290 sendto(buf, 1); 291 return (TRUE); 292 } 293