1 # include <pwd.h> 2 # include "sendmail.h" 3 4 # ifdef DBM 5 static char SccsId[] = "@(#)alias.c 3.17 08/21/81 (with DBM)"; 6 # else DBM 7 static char SccsId[] = "@(#)alias.c 3.17 08/21/81 (without DBM)"; 8 # endif DBM 9 10 /* 11 ** ALIAS -- Compute aliases. 12 ** 13 ** Scans the file /usr/lib/aliases for a set of aliases. 14 ** If found, it arranges to deliver to them. Uses libdbm 15 ** database if -DDBM. 16 ** 17 ** Parameters: 18 ** a -- address to alias. 19 ** 20 ** Returns: 21 ** none 22 ** 23 ** Side Effects: 24 ** Aliases found are expanded. 25 ** 26 ** Files: 27 ** /usr/lib/aliases -- the mail aliases. The format is 28 ** a series of lines of the form: 29 ** alias:name1,name2,name3,... 30 ** where 'alias' expands to all of 31 ** 'name[i]'. Continuations begin with 32 ** space or tab. 33 ** /usr/lib/aliases.pag, /usr/lib/aliases.dir: libdbm version 34 ** of alias file. Keys are aliases, datums 35 ** (data?) are name1,name2, ... 36 ** 37 ** Notes: 38 ** If NoAlias (the "-n" flag) is set, no aliasing is 39 ** done. 40 ** 41 ** Deficiencies: 42 ** It should complain about names that are aliased to 43 ** nothing. 44 ** It is unsophisticated about line overflows. 45 */ 46 47 48 #ifdef DBM 49 typedef struct 50 { 51 char *dptr; 52 int dsize; 53 } DATUM; 54 DATUM lhs, rhs; 55 extern DATUM fetch(); 56 #endif DBM 57 58 alias(a) 59 register ADDRESS *a; 60 { 61 register char *p; 62 # ifndef DBM 63 register STAB *s; 64 # endif DBM 65 66 if (NoAlias) 67 return; 68 # ifdef DEBUG 69 if (Debug) 70 printf("alias(%s)\n", a->q_paddr); 71 # endif 72 73 /* don't realias already aliased names */ 74 if (bitset(QDONTSEND, a->q_flags)) 75 return; 76 77 To = a->q_paddr; 78 79 # ifdef DBM 80 /* create a key for fetch */ 81 lhs.dptr = a->q_user; 82 lhs.dsize = strlen(a->q_user) + 1; 83 rhs = fetch(lhs); 84 85 /* find this alias? */ 86 p = rhs.dptr; 87 if (p == NULL) 88 return; 89 # else DBM 90 s = stab(a->q_user, ST_ALIAS, ST_FIND); 91 if (s == NULL) 92 return; 93 p = s->s_alias; 94 # endif DBM 95 96 /* 97 ** Match on Alias. 98 ** Deliver to the target list. 99 */ 100 101 # ifdef DEBUG 102 if (Debug) 103 printf("%s (%s, %s) aliased to %s\n", 104 a->q_paddr, a->q_host, a->q_user, p); 105 # endif 106 if (Verbose) 107 message(Arpa_Info, "aliased to %s", p); 108 a->q_flags |= QDONTSEND; 109 AliasLevel++; 110 sendto(p, 1); 111 AliasLevel--; 112 } 113 /* 114 ** INITALIASES -- initialize for aliasing 115 ** 116 ** Very different depending on whether we are running DBM or not. 117 ** 118 ** Parameters: 119 ** aliasfile -- location of aliases. 120 ** init -- if set and if DBM, initialize the DBM files. 121 ** 122 ** Returns: 123 ** none. 124 ** 125 ** Side Effects: 126 ** initializes aliases: 127 ** if DBM: opens the database. 128 ** if ~DBM: reads the aliases into the symbol table. 129 */ 130 131 # define DBMMODE 0666 132 133 initaliases(aliasfile, init) 134 char *aliasfile; 135 bool init; 136 { 137 # ifdef DBM 138 if (init) 139 { 140 char buf[MAXNAME]; 141 142 (void) strcpy(buf, aliasfile); 143 (void) strcat(buf, ".dir"); 144 if (close(creat(buf, DBMMODE)) < 0) 145 { 146 syserr("cannot make %s", buf); 147 return; 148 } 149 (void) strcpy(buf, aliasfile); 150 (void) strcat(buf, ".pag"); 151 if (close(creat(buf, DBMMODE)) < 0) 152 { 153 syserr("cannot make %s", buf); 154 return; 155 } 156 } 157 dbminit(aliasfile); 158 if (init) 159 readaliases(aliasfile, TRUE); 160 # else DBM 161 readaliases(aliasfile, init); 162 # endif DBM 163 } 164 /* 165 ** READALIASES -- read and process the alias file. 166 ** 167 ** This routine implements the part of initaliases that occurs 168 ** when we are not going to use the DBM stuff. 169 ** 170 ** Parameters: 171 ** aliasfile -- the pathname of the alias file master. 172 ** init -- if set, initialize the DBM stuff. 173 ** 174 ** Returns: 175 ** none. 176 ** 177 ** Side Effects: 178 ** Reads aliasfile into the symbol table. 179 ** Optionally, builds the .dir & .pag files. 180 */ 181 182 static 183 readaliases(aliasfile, init) 184 char *aliasfile; 185 bool init; 186 { 187 char line[BUFSIZ]; 188 register char *p; 189 char *p2; 190 char *rhs; 191 bool skipping; 192 ADDRESS al, bl; 193 FILE *af; 194 int lineno; 195 register STAB *s; 196 197 if ((af = fopen(aliasfile, "r")) == NULL) 198 { 199 # ifdef DEBUG 200 if (Debug) 201 printf("Can't open %s\n", aliasfile); 202 # endif 203 errno = 0; 204 NoAlias++; 205 return; 206 } 207 /* read and interpret lines */ 208 lineno = 0; 209 skipping = FALSE; 210 while (fgets(line, sizeof (line), af) != NULL) 211 { 212 lineno++; 213 switch (line[0]) 214 { 215 case '#': 216 case '\n': 217 case '\0': 218 skipping = FALSE; 219 continue; 220 221 case ' ': 222 case '\t': 223 if (!skipping) 224 syserr("aliases: %d: Non-continuation line starts with space", lineno); 225 skipping = TRUE; 226 continue; 227 } 228 skipping = FALSE; 229 230 /* process the LHS */ 231 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 232 continue; 233 if (*p == '\0' || *p == '\n') 234 { 235 syntaxerr: 236 syserr("aliases: %d: missing colon", lineno); 237 continue; 238 } 239 *p++ = '\0'; 240 if (parse(line, &al, 1) == NULL) 241 { 242 *--p = ':'; 243 goto syntaxerr; 244 } 245 rhs = p; 246 for (;;) 247 { 248 register char c; 249 250 if (init) 251 { 252 /* do parsing & compression of addresses */ 253 c = *p; 254 while (c != '\0') 255 { 256 p2 = p; 257 while (*p != '\n' && *p != ',' && *p != '\0') 258 p++; 259 c = *p; 260 *p++ = '\0'; 261 if (*p2 == '\0') 262 { 263 p[-1] = c; 264 continue; 265 } 266 parse(p2, &bl, -1); 267 p[-1] = c; 268 while (isspace(*p)) 269 p++; 270 } 271 } 272 else 273 p = &p[strlen(p)]; 274 275 /* see if there should be a continuation line */ 276 c = fgetc(af); 277 if (!feof(af)) 278 ungetc(c, af); 279 if (c != ' ' && c != '\t') 280 break; 281 282 /* read continuation line */ 283 p--; 284 if (fgets(p, sizeof line - (p - line), af) == NULL) 285 break; 286 lineno++; 287 } 288 if (al.q_mailer != MN_LOCAL) 289 { 290 syserr("aliases: %d: cannot alias non-local names", lineno); 291 continue; 292 } 293 # ifdef DBM 294 if (init) 295 { 296 DATUM key, content; 297 298 key.dsize = strlen(al.q_user) + 1; 299 key.dptr = al.q_user; 300 content.dsize = strlen(rhs) + 1; 301 content.dptr = rhs; 302 store(key, content); 303 } 304 else 305 # endif DBM 306 { 307 s = stab(al.q_user, ST_ALIAS, ST_ENTER); 308 s->s_alias = newstr(rhs); 309 } 310 } 311 (void) fclose(af); 312 } 313 /* 314 ** FORWARD -- Try to forward mail 315 ** 316 ** This is similar but not identical to aliasing. 317 ** 318 ** Parameters: 319 ** user -- the name of the user who's mail we 320 ** would like to forward to. 321 ** 322 ** Returns: 323 ** none. 324 ** 325 ** Side Effects: 326 ** New names are added to send queues. 327 ** Sets the QDONTSEND bit in addresses that are forwarded. 328 */ 329 330 forward(user) 331 ADDRESS *user; 332 { 333 char buf[60]; 334 register FILE *fp; 335 register char *p; 336 337 # ifdef DEBUG 338 if (Debug) 339 printf("forward(%s)\n", user->q_paddr); 340 # endif DEBUG 341 342 if (user->q_mailer != MN_LOCAL || bitset(QBADADDR, user->q_flags)) 343 return; 344 345 /* good address -- look for .forward file in home */ 346 define('z', user->q_home); 347 (void) expand("$z/.forward", buf, &buf[sizeof buf - 1]); 348 if (access(buf, 4) < 0) 349 return; 350 351 /* we do have an address to forward to -- do it */ 352 user->q_flags |= QDONTSEND; 353 include(buf, "forwarding"); 354 } 355