Commit | Line | Data |
---|---|---|
d185cb11 | 1 | /* |
1f7bda54 | 2 | * Copyright (c) 1983 Eric P. Allman |
bee79b64 KB |
3 | * Copyright (c) 1988 Regents of the University of California. |
4 | * All rights reserved. | |
5 | * | |
417f7a11 | 6 | * %sccs.include.redist.c% |
bee79b64 KB |
7 | */ |
8 | ||
72041f93 | 9 | # include "sendmail.h" |
ce8f0b62 | 10 | # include <sys/stat.h> |
2e2e5270 | 11 | # include <sys/file.h> |
ce8f0b62 | 12 | # include <signal.h> |
76b607b2 | 13 | # include <fcntl.h> |
f9344236 | 14 | # include <pwd.h> |
ce8f0b62 | 15 | |
4099e6e8 | 16 | # ifdef DBM |
33fc5854 | 17 | ERROR: DBM is no longer supported -- use NDBM instead. |
4099e6e8 EA |
18 | # endif |
19 | ||
ce8f0b62 EA |
20 | # ifdef NEWDB |
21 | # include <db.h> | |
22 | # endif | |
23 | ||
6a2bb17b | 24 | # ifdef NDBM |
4099e6e8 | 25 | # include <ndbm.h> |
6a2bb17b EA |
26 | # endif |
27 | ||
bee79b64 | 28 | #ifndef lint |
b9357db9 | 29 | #ifdef NEWDB |
6feb509e | 30 | #ifdef NDBM |
dd3ec3f5 | 31 | static char sccsid[] = "@(#)alias.c 6.24 (Berkeley) %G% (with NEWDB and NDBM)"; |
6feb509e | 32 | #else |
dd3ec3f5 | 33 | static char sccsid[] = "@(#)alias.c 6.24 (Berkeley) %G% (with NEWDB)"; |
6feb509e | 34 | #endif |
07c0651f | 35 | #else |
4099e6e8 | 36 | #ifdef NDBM |
dd3ec3f5 | 37 | static char sccsid[] = "@(#)alias.c 6.24 (Berkeley) %G% (with NDBM)"; |
b9357db9 | 38 | #else |
dd3ec3f5 | 39 | static char sccsid[] = "@(#)alias.c 6.24 (Berkeley) %G% (without NEWDB or NDBM)"; |
b9357db9 | 40 | #endif |
bee79b64 KB |
41 | #endif |
42 | #endif /* not lint */ | |
07c0651f | 43 | \f/* |
b3cbe40f EA |
44 | ** ALIAS -- Compute aliases. |
45 | ** | |
7338e3d4 EA |
46 | ** Scans the alias file for an alias for the given address. |
47 | ** If found, it arranges to deliver to the alias list instead. | |
48 | ** Uses libdbm database if -DDBM. | |
b3cbe40f EA |
49 | ** |
50 | ** Parameters: | |
bdfaa762 | 51 | ** a -- address to alias. |
d4f42161 EA |
52 | ** sendq -- a pointer to the head of the send queue |
53 | ** to put the aliases in. | |
8f48def8 | 54 | ** e -- the current envelope. |
b3cbe40f EA |
55 | ** |
56 | ** Returns: | |
57 | ** none | |
58 | ** | |
59 | ** Side Effects: | |
9e3c0a28 | 60 | ** Aliases found are expanded. |
b3cbe40f | 61 | ** |
b3cbe40f EA |
62 | ** Notes: |
63 | ** If NoAlias (the "-n" flag) is set, no aliasing is | |
64 | ** done. | |
65 | ** | |
66 | ** Deficiencies: | |
67 | ** It should complain about names that are aliased to | |
68 | ** nothing. | |
b3cbe40f EA |
69 | */ |
70 | ||
71 | ||
6c6e2d3a EA |
72 | /* |
73 | ** Sun YP servers read the dbm files directly, so we have to build them | |
74 | ** even if NEWDB | |
75 | */ | |
76 | ||
4099e6e8 | 77 | #ifdef NDBM |
6c6e2d3a EA |
78 | # ifndef NEWDB |
79 | # define IF_MAKEDBMFILES | |
80 | # else | |
81 | # ifdef YPCOMPAT | |
82 | # define IF_MAKEDBMFILES if (makedbmfiles) | |
83 | # endif | |
84 | # endif | |
85 | #endif | |
86 | ||
4099e6e8 | 87 | typedef union |
a530c75f | 88 | { |
4099e6e8 EA |
89 | #ifdef NDBM |
90 | datum dbm; | |
07c0651f | 91 | #endif |
4099e6e8 EA |
92 | #ifdef NEWDB |
93 | DBT dbt; | |
94 | #endif | |
95 | struct | |
96 | { | |
97 | char *data; | |
98 | int size; | |
99 | } xx; | |
100 | } DBdatum; | |
b9357db9 EA |
101 | |
102 | #ifdef NEWDB | |
103 | static DB *AliasDBptr; | |
104 | #endif | |
4099e6e8 EA |
105 | #ifdef NDBM |
106 | static DBM *AliasDBMptr; | |
107 | #endif | |
b3cbe40f | 108 | |
a4076aed | 109 | alias(a, sendq, e) |
bdfaa762 | 110 | register ADDRESS *a; |
d4f42161 | 111 | ADDRESS **sendq; |
a4076aed | 112 | register ENVELOPE *e; |
b3cbe40f | 113 | { |
29871fef | 114 | register char *p; |
1c7897ef | 115 | int naliases; |
84daea29 EA |
116 | char *owner; |
117 | char obuf[MAXNAME + 6]; | |
abae7b2d | 118 | extern ADDRESS *sendto(); |
35cc3fad | 119 | extern char *aliaslookup(); |
b3cbe40f | 120 | |
9678c96d | 121 | if (tTd(27, 1)) |
cdb17311 | 122 | printf("alias(%s)\n", a->q_paddr); |
b3cbe40f | 123 | |
cdb17311 | 124 | /* don't realias already aliased names */ |
8bcce465 | 125 | if (bitset(QDONTSEND|QVERIFIED, a->q_flags)) |
cdb17311 EA |
126 | return; |
127 | ||
a4076aed | 128 | e->e_to = a->q_paddr; |
cdb17311 | 129 | |
74c5fe7c EA |
130 | /* |
131 | ** Look up this name | |
132 | */ | |
133 | ||
2e3062fe EA |
134 | if (NoAlias) |
135 | p = NULL; | |
136 | else | |
137 | p = aliaslookup(a->q_user); | |
cdb17311 EA |
138 | if (p == NULL) |
139 | return; | |
b3cbe40f | 140 | |
d916f0ca | 141 | /* |
cdb17311 EA |
142 | ** Match on Alias. |
143 | ** Deliver to the target list. | |
d916f0ca EA |
144 | */ |
145 | ||
9678c96d | 146 | if (tTd(27, 1)) |
cdb17311 EA |
147 | printf("%s (%s, %s) aliased to %s\n", |
148 | a->q_paddr, a->q_host, a->q_user, p); | |
8f48def8 | 149 | if (bitset(EF_VRFYONLY, e->e_flags)) |
8bcce465 EA |
150 | { |
151 | a->q_flags |= QVERIFIED; | |
8f48def8 | 152 | return; |
8bcce465 EA |
153 | } |
154 | message("aliased to %s", p); | |
aa102c71 | 155 | #ifdef LOG |
68f7099c | 156 | if (LogLevel > 9) |
aa102c71 EA |
157 | syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); |
158 | #endif | |
1c7897ef | 159 | a->q_flags &= ~QSELFREF; |
cdb17311 | 160 | AliasLevel++; |
abae7b2d | 161 | a->q_child = sendto(p, 1, a, 0); |
cdb17311 | 162 | AliasLevel--; |
1c7897ef | 163 | if (naliases > 0 && !bitset(QSELFREF, a->q_flags)) |
f7eca811 EA |
164 | { |
165 | if (tTd(27, 5)) | |
166 | { | |
167 | printf("alias: QDONTSEND "); | |
168 | printaddr(a, FALSE); | |
169 | } | |
170 | a->q_flags |= QDONTSEND; | |
171 | } | |
84daea29 EA |
172 | |
173 | /* | |
174 | ** Look for owner of alias | |
175 | */ | |
176 | ||
177 | (void) strcpy(obuf, "owner-"); | |
178 | if (strncmp(a->q_user, "owner-", 6) == 0) | |
179 | (void) strcat(obuf, "owner"); | |
180 | else | |
181 | (void) strcat(obuf, a->q_user); | |
182 | if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags)) | |
183 | makelower(obuf); | |
184 | owner = aliaslookup(obuf); | |
185 | if (owner != NULL) | |
186 | { | |
187 | if (strchr(owner, ',') != NULL) | |
188 | owner = obuf; | |
189 | a->q_owner = newstr(owner); | |
190 | } | |
cdb17311 EA |
191 | } |
192 | \f/* | |
35cc3fad EA |
193 | ** ALIASLOOKUP -- look up a name in the alias file. |
194 | ** | |
195 | ** Parameters: | |
196 | ** name -- the name to look up. | |
197 | ** | |
198 | ** Returns: | |
199 | ** the value of name. | |
200 | ** NULL if unknown. | |
201 | ** | |
202 | ** Side Effects: | |
203 | ** none. | |
204 | ** | |
205 | ** Warnings: | |
206 | ** The return value will be trashed across calls. | |
207 | */ | |
208 | ||
209 | char * | |
210 | aliaslookup(name) | |
211 | char *name; | |
212 | { | |
698a71d9 EA |
213 | int i; |
214 | char keybuf[MAXNAME + 1]; | |
4099e6e8 EA |
215 | # if defined(NEWDB) || defined(NDBM) |
216 | DBdatum rhs, lhs; | |
b9357db9 | 217 | int s; |
698a71d9 EA |
218 | # else /* neither NEWDB nor NDBM */ |
219 | register STAB *s; | |
220 | # endif | |
35cc3fad EA |
221 | |
222 | /* create a key for fetch */ | |
698a71d9 EA |
223 | i = strlen(name) + 1; |
224 | if (i > sizeof keybuf) | |
225 | i = sizeof keybuf; | |
226 | bcopy(name, keybuf, i); | |
227 | if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) | |
228 | makelower(keybuf); | |
229 | ||
230 | # if defined(NEWDB) || defined(NDBM) | |
231 | lhs.xx.size = i; | |
232 | lhs.xx.data = keybuf; | |
b9357db9 | 233 | # ifdef NEWDB |
07c0651f EA |
234 | if (AliasDBptr != NULL) |
235 | { | |
698a71d9 EA |
236 | i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); |
237 | if (i == 0) | |
4099e6e8 | 238 | return (rhs.dbt.data); |
07c0651f | 239 | } |
4099e6e8 | 240 | # ifdef NDBM |
c796f255 | 241 | else if (AliasDBMptr != NULL) |
07c0651f | 242 | { |
4099e6e8 EA |
243 | rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); |
244 | return (rhs.dbm.dptr); | |
07c0651f | 245 | } |
4099e6e8 | 246 | # endif /* NDBM */ |
5039bcf5 | 247 | return (NULL); |
4099e6e8 EA |
248 | # else /* not NEWDB */ |
249 | rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); | |
250 | return (rhs.dbm.dptr); | |
251 | # endif /* NEWDB */ | |
252 | # else /* neither NEWDB nor NDBM */ | |
698a71d9 | 253 | s = stab(keybuf, ST_ALIAS, ST_FIND); |
07c0651f EA |
254 | if (s != NULL) |
255 | return (s->s_alias); | |
07c0651f | 256 | return (NULL); |
5039bcf5 | 257 | # endif |
35cc3fad EA |
258 | } |
259 | \f/* | |
cdb17311 EA |
260 | ** INITALIASES -- initialize for aliasing |
261 | ** | |
4099e6e8 | 262 | ** Very different depending on whether we are running NDBM or not. |
cdb17311 EA |
263 | ** |
264 | ** Parameters: | |
265 | ** aliasfile -- location of aliases. | |
4099e6e8 | 266 | ** init -- if set and if NDBM, initialize the NDBM files. |
cdb17311 EA |
267 | ** |
268 | ** Returns: | |
269 | ** none. | |
270 | ** | |
271 | ** Side Effects: | |
272 | ** initializes aliases: | |
4099e6e8 EA |
273 | ** if NDBM: opens the database. |
274 | ** if ~NDBM: reads the aliases into the symbol table. | |
cdb17311 EA |
275 | */ |
276 | ||
915f268d | 277 | # define DBMMODE 0644 |
f4dbf345 | 278 | |
a4076aed | 279 | initaliases(aliasfile, init, e) |
cdb17311 | 280 | char *aliasfile; |
f4dbf345 | 281 | bool init; |
a4076aed | 282 | register ENVELOPE *e; |
cdb17311 | 283 | { |
4099e6e8 | 284 | #if defined(NDBM) || defined(NEWDB) |
7bdc419c | 285 | int atcnt; |
d6b27179 | 286 | time_t modtime; |
9327783c EA |
287 | bool automatic = FALSE; |
288 | char buf[MAXNAME]; | |
b9357db9 | 289 | #endif |
7338e3d4 | 290 | struct stat stb; |
a78155b0 | 291 | static bool initialized = FALSE; |
0df908a9 | 292 | static int readaliases(); |
a78155b0 EA |
293 | |
294 | if (initialized) | |
295 | return; | |
296 | initialized = TRUE; | |
d6b27179 | 297 | |
bb09c502 | 298 | if (aliasfile == NULL || stat(aliasfile, &stb) < 0) |
7bdc419c | 299 | { |
9327783c | 300 | if (aliasfile != NULL && init) |
b6edea3d | 301 | syserr("554 Cannot open %s", aliasfile); |
7bdc419c | 302 | NoAlias = TRUE; |
70faa7c8 | 303 | errno = 0; |
7bdc419c EA |
304 | return; |
305 | } | |
306 | ||
4099e6e8 | 307 | # if defined(NDBM) || defined(NEWDB) |
7bdc419c EA |
308 | /* |
309 | ** Check to see that the alias file is complete. | |
310 | ** If not, we will assume that someone died, and it is up | |
311 | ** to us to rebuild it. | |
312 | */ | |
313 | ||
a1a07282 | 314 | if (!init) |
b9357db9 EA |
315 | { |
316 | # ifdef NEWDB | |
317 | (void) strcpy(buf, aliasfile); | |
318 | (void) strcat(buf, ".db"); | |
15af6d40 | 319 | AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); |
aace356e EA |
320 | if (AliasDBptr == NULL) |
321 | { | |
4099e6e8 EA |
322 | # ifdef NDBM |
323 | AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); | |
c796f255 EA |
324 | if (AliasDBMptr == NULL) |
325 | { | |
326 | syserr("initaliases: cannot open %s", buf); | |
327 | NoAlias = TRUE; | |
328 | return; | |
329 | } | |
07c0651f | 330 | # else |
aace356e EA |
331 | syserr("initaliases: cannot open %s", buf); |
332 | NoAlias = TRUE; | |
333 | return; | |
07c0651f | 334 | # endif |
aace356e | 335 | } |
b9357db9 | 336 | # else |
4099e6e8 | 337 | AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); |
c796f255 EA |
338 | if (AliasDBMptr == NULL) |
339 | { | |
aa102c71 EA |
340 | syserr("initaliases: cannot open DBM database %s.{pag,dir}", |
341 | aliasfile); | |
c796f255 EA |
342 | NoAlias = TRUE; |
343 | return; | |
344 | } | |
b9357db9 EA |
345 | # endif |
346 | } | |
560a80d9 EA |
347 | atcnt = SafeAlias * 2; |
348 | if (atcnt > 0) | |
349 | { | |
350 | while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) | |
a1a07282 EA |
351 | { |
352 | /* | |
353 | ** Reinitialize alias file in case the new | |
354 | ** one is mv'ed in instead of cp'ed in. | |
355 | ** | |
356 | ** Only works with new DBM -- old one will | |
357 | ** just consume file descriptors forever. | |
358 | ** If you have a dbmclose() it can be | |
359 | ** added before the sleep(30). | |
360 | */ | |
361 | ||
b9357db9 | 362 | # ifdef NEWDB |
07c0651f EA |
363 | if (AliasDBptr != NULL) |
364 | AliasDBptr->close(AliasDBptr); | |
b9357db9 | 365 | # endif |
4099e6e8 EA |
366 | # ifdef NDBM |
367 | if (AliasDBMptr != NULL) | |
368 | dbm_close(AliasDBMptr); | |
369 | # endif | |
b9357db9 | 370 | |
560a80d9 | 371 | sleep(30); |
b9357db9 EA |
372 | # ifdef NEWDB |
373 | (void) strcpy(buf, aliasfile); | |
374 | (void) strcat(buf, ".db"); | |
15af6d40 KB |
375 | AliasDBptr = |
376 | dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); | |
aace356e EA |
377 | if (AliasDBptr == NULL) |
378 | { | |
07c0651f | 379 | # ifdef NDBM |
4099e6e8 | 380 | AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); |
07c0651f | 381 | # else |
aace356e EA |
382 | syserr("initaliases: cannot open %s", buf); |
383 | NoAlias = TRUE; | |
384 | return; | |
07c0651f | 385 | # endif |
aace356e | 386 | } |
b9357db9 | 387 | # else |
a1a07282 | 388 | # ifdef NDBM |
4099e6e8 | 389 | AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); |
c796f255 EA |
390 | if (AliasDBMptr == NULL) |
391 | { | |
51d9cc47 EA |
392 | syserr("initaliases: cannot open DBM database %s.{pag,dir}", |
393 | aliasfile); | |
c796f255 EA |
394 | NoAlias = TRUE; |
395 | return; | |
396 | } | |
b9357db9 EA |
397 | # endif |
398 | # endif | |
a1a07282 | 399 | } |
560a80d9 EA |
400 | } |
401 | else | |
402 | atcnt = 1; | |
7bdc419c | 403 | |
d6b27179 | 404 | /* |
4099e6e8 | 405 | ** See if the NDBM version of the file is out of date with |
d6b27179 | 406 | ** the text version. If so, go into 'init' mode automatically. |
915f268d KB |
407 | ** This only happens if our effective userid owns the DBM. |
408 | ** Note the unpalatable hack to see if the stat succeeded. | |
d6b27179 EA |
409 | */ |
410 | ||
d6b27179 EA |
411 | modtime = stb.st_mtime; |
412 | (void) strcpy(buf, aliasfile); | |
b9357db9 EA |
413 | # ifdef NEWDB |
414 | (void) strcat(buf, ".db"); | |
415 | # else | |
d6b27179 | 416 | (void) strcat(buf, ".pag"); |
b9357db9 | 417 | # endif |
d6b27179 | 418 | stb.st_ino = 0; |
f12e5a74 | 419 | if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) |
f4dbf345 | 420 | { |
70faa7c8 | 421 | errno = 0; |
915f268d | 422 | if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) |
d6b27179 EA |
423 | { |
424 | init = TRUE; | |
9327783c | 425 | automatic = TRUE; |
b6edea3d | 426 | message("rebuilding alias database"); |
2e3062fe | 427 | #ifdef LOG |
68f7099c | 428 | if (LogLevel > 14) |
2e3062fe | 429 | syslog(LOG_INFO, "rebuilding alias database"); |
f3d8f6d6 | 430 | #endif /* LOG */ |
d6b27179 EA |
431 | } |
432 | else | |
433 | { | |
f12e5a74 | 434 | #ifdef LOG |
68f7099c | 435 | if (LogLevel > 3) |
2e3062fe | 436 | syslog(LOG_INFO, "alias database out of date"); |
f3d8f6d6 | 437 | #endif /* LOG */ |
b6edea3d | 438 | message("Warning: alias database out of date"); |
d6b27179 EA |
439 | } |
440 | } | |
f4dbf345 | 441 | |
d6b27179 EA |
442 | |
443 | /* | |
4099e6e8 EA |
444 | ** If necessary, load the NDBM file. |
445 | ** If running without NDBM, load the symbol table. | |
d6b27179 EA |
446 | */ |
447 | ||
f4dbf345 | 448 | if (init) |
7bdc419c | 449 | { |
9327783c | 450 | #ifdef LOG |
68f7099c | 451 | if (LogLevel > 7) |
9327783c EA |
452 | { |
453 | extern char *username(); | |
454 | ||
455 | syslog(LOG_NOTICE, "alias database %srebuilt by %s", | |
456 | automatic ? "auto" : "", username()); | |
457 | } | |
f3d8f6d6 | 458 | #endif /* LOG */ |
a4076aed | 459 | readaliases(aliasfile, TRUE, e); |
7bdc419c | 460 | } |
4099e6e8 | 461 | # else /* NDBM */ |
a4076aed | 462 | readaliases(aliasfile, init, e); |
4099e6e8 | 463 | # endif /* NDBM */ |
f4dbf345 EA |
464 | } |
465 | \f/* | |
466 | ** READALIASES -- read and process the alias file. | |
467 | ** | |
468 | ** This routine implements the part of initaliases that occurs | |
469 | ** when we are not going to use the DBM stuff. | |
470 | ** | |
471 | ** Parameters: | |
472 | ** aliasfile -- the pathname of the alias file master. | |
4099e6e8 | 473 | ** init -- if set, initialize the NDBM stuff. |
f4dbf345 EA |
474 | ** |
475 | ** Returns: | |
476 | ** none. | |
477 | ** | |
478 | ** Side Effects: | |
479 | ** Reads aliasfile into the symbol table. | |
480 | ** Optionally, builds the .dir & .pag files. | |
481 | */ | |
482 | ||
483 | static | |
a4076aed | 484 | readaliases(aliasfile, init, e) |
f4dbf345 EA |
485 | char *aliasfile; |
486 | bool init; | |
a4076aed | 487 | register ENVELOPE *e; |
f4dbf345 | 488 | { |
cdb17311 | 489 | register char *p; |
41173b8f | 490 | char *lhs; |
cdb17311 EA |
491 | char *rhs; |
492 | bool skipping; | |
7338e3d4 | 493 | int naliases, bytes, longest; |
9e25d1f0 | 494 | FILE *af; |
6c6e2d3a | 495 | bool makedbmfiles; |
21c8ba49 | 496 | void (*oldsigint)(); |
7338e3d4 | 497 | ADDRESS al, bl; |
9e25d1f0 | 498 | register STAB *s; |
b9357db9 EA |
499 | # ifdef NEWDB |
500 | DB *dbp; | |
76b607b2 | 501 | # endif |
4099e6e8 EA |
502 | # ifdef NDBM |
503 | DBM *dbmp; | |
504 | # endif | |
76b607b2 EA |
505 | # ifdef LOCKF |
506 | struct flock fld; | |
b9357db9 | 507 | # endif |
7338e3d4 | 508 | char line[BUFSIZ]; |
cdb17311 | 509 | |
76b607b2 | 510 | if ((af = fopen(aliasfile, "r+")) == NULL) |
d916f0ca | 511 | { |
c796f255 | 512 | if (init) |
b6edea3d | 513 | syserr("554 Can't open %s", aliasfile); |
c796f255 | 514 | else if (tTd(27, 1)) |
9e25d1f0 | 515 | printf("Can't open %s\n", aliasfile); |
cdb17311 EA |
516 | errno = 0; |
517 | NoAlias++; | |
518 | return; | |
519 | } | |
74c5fe7c | 520 | |
4099e6e8 | 521 | # if defined(NDBM) || defined(NEWDB) |
e6e345fa | 522 | /* see if someone else is rebuilding the alias file already */ |
4287d84d | 523 | # ifdef LOCKF |
76b607b2 EA |
524 | fld.l_type = F_WRLCK; |
525 | fld.l_whence = fld.l_start = fld.l_len = 0; | |
526 | if (fcntl(fileno(af), F_SETLK, &fld) < 0) | |
4287d84d | 527 | # else |
e6e345fa | 528 | if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) |
4287d84d | 529 | # endif |
e6e345fa EA |
530 | { |
531 | /* yes, they are -- wait until done and then return */ | |
b6edea3d | 532 | message("Alias file is already being rebuilt"); |
e6e345fa EA |
533 | if (OpMode != MD_INITALIAS) |
534 | { | |
535 | /* wait for other rebuild to complete */ | |
4287d84d | 536 | # ifdef LOCKF |
76b607b2 | 537 | (void) fcntl(fileno(af), F_SETLKW, &fld); |
4287d84d | 538 | # else |
e6e345fa | 539 | (void) flock(fileno(af), LOCK_EX); |
4287d84d | 540 | # endif |
e6e345fa | 541 | } |
03388044 | 542 | (void) fclose(af); |
e6e345fa EA |
543 | errno = 0; |
544 | return; | |
545 | } | |
4099e6e8 | 546 | # endif /* NDBM */ |
e6e345fa EA |
547 | |
548 | /* | |
549 | ** If initializing, create the new DBM files. | |
550 | */ | |
551 | ||
552 | if (init) | |
553 | { | |
554 | oldsigint = signal(SIGINT, SIG_IGN); | |
07c0651f EA |
555 | # ifdef NEWDB |
556 | (void) strcpy(line, aliasfile); | |
557 | (void) strcat(line, ".db"); | |
558 | dbp = dbopen(line, | |
559 | O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); | |
560 | if (dbp == NULL) | |
561 | { | |
562 | syserr("readaliases: cannot create %s", line); | |
563 | (void) signal(SIGINT, oldsigint); | |
564 | return; | |
565 | } | |
6c6e2d3a EA |
566 | # endif |
567 | # ifdef IF_MAKEDBMFILES | |
568 | # ifdef NEWDB | |
569 | makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; | |
570 | # endif | |
571 | IF_MAKEDBMFILES | |
e6e345fa | 572 | { |
4099e6e8 EA |
573 | dbmp = dbm_open(aliasfile, |
574 | O_RDWR|O_CREAT|O_TRUNC, DBMMODE); | |
575 | if (dbmp == NULL) | |
6c6e2d3a | 576 | { |
4099e6e8 EA |
577 | syserr("readaliases: cannot create %s.{dir,pag}", |
578 | aliasfile); | |
6c6e2d3a EA |
579 | (void) signal(SIGINT, oldsigint); |
580 | return; | |
581 | } | |
e6e345fa | 582 | } |
b9357db9 | 583 | # endif |
e6e345fa EA |
584 | } |
585 | ||
74c5fe7c EA |
586 | /* |
587 | ** Read and interpret lines | |
588 | */ | |
589 | ||
7338e3d4 EA |
590 | FileName = aliasfile; |
591 | LineNumber = 0; | |
d6b27179 | 592 | naliases = bytes = longest = 0; |
cdb17311 EA |
593 | skipping = FALSE; |
594 | while (fgets(line, sizeof (line), af) != NULL) | |
595 | { | |
d6b27179 EA |
596 | int lhssize, rhssize; |
597 | ||
7338e3d4 | 598 | LineNumber++; |
f3d8f6d6 | 599 | p = strchr(line, '\n'); |
3312f93c EA |
600 | if (p != NULL) |
601 | *p = '\0'; | |
cdb17311 EA |
602 | switch (line[0]) |
603 | { | |
604 | case '#': | |
cdb17311 EA |
605 | case '\0': |
606 | skipping = FALSE; | |
607 | continue; | |
bdfaa762 | 608 | |
cdb17311 EA |
609 | case ' ': |
610 | case '\t': | |
611 | if (!skipping) | |
b6edea3d | 612 | syserr("554 Non-continuation line starts with space"); |
cdb17311 | 613 | skipping = TRUE; |
bdfaa762 | 614 | continue; |
cdb17311 EA |
615 | } |
616 | skipping = FALSE; | |
bdfaa762 | 617 | |
74c5fe7c EA |
618 | /* |
619 | ** Process the LHS | |
41173b8f | 620 | ** |
6feb509e | 621 | ** Find the colon separator, and parse the address. |
41173b8f EA |
622 | ** It should resolve to a local name. |
623 | ** | |
624 | ** Alternatively, it can be "@hostname" for host | |
625 | ** aliases -- all we do here is map case. Hostname | |
626 | ** need not be a single token. | |
74c5fe7c EA |
627 | */ |
628 | ||
cdb17311 | 629 | for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) |
bdfaa762 | 630 | continue; |
41173b8f | 631 | if (*p != ':') |
cdb17311 | 632 | { |
1bcdf0a2 | 633 | syserr("%s, line %d: syntax error", aliasfile, lineno); |
bdfaa762 | 634 | continue; |
cdb17311 | 635 | } |
41173b8f EA |
636 | *p++ = '\0'; |
637 | if (line[0] == '@') | |
cdb17311 | 638 | { |
41173b8f EA |
639 | /* a host alias */ |
640 | makelower(line); | |
641 | lhs = line; | |
642 | } | |
643 | else | |
644 | { | |
645 | /* a user alias */ | |
646 | if (parseaddr(line, &al, 1, ':') == NULL) | |
647 | { | |
648 | syserr("illegal alias name"); | |
649 | continue; | |
650 | } | |
651 | loweraddr(&al); | |
652 | if (al.q_mailer != LocalMailer) | |
653 | { | |
654 | syserr("cannot alias non-local names"); | |
655 | continue; | |
656 | } | |
657 | lhs = al.q_user; | |
cdb17311 | 658 | } |
74c5fe7c EA |
659 | |
660 | /* | |
661 | ** Process the RHS. | |
662 | ** 'al' is the internal form of the LHS address. | |
663 | ** 'p' points to the text of the RHS. | |
1bcdf0a2 EA |
664 | ** 'p' may begin with a colon (i.e., the |
665 | ** separator was "::") which will use the | |
666 | ** first address as the person to send | |
667 | ** errors to -- i.e., designates the | |
668 | ** list maintainer. | |
74c5fe7c EA |
669 | */ |
670 | ||
1bcdf0a2 EA |
671 | if (*p == ':') |
672 | { | |
673 | ADDRESS *maint; | |
674 | ||
675 | while (isspace(*++p)) | |
676 | continue; | |
677 | rhs = p; | |
678 | while (*p != '\0' && *p != ',') | |
679 | p++; | |
680 | if (*p != ',') | |
681 | goto syntaxerr; | |
682 | *p++ = '\0'; | |
683 | maint = parse(p, (ADDRESS *) NULL, 1); | |
684 | if (maint == NULL) | |
685 | syserr("Illegal list maintainer for list %s", al.q_user); | |
686 | else if (CurEnv->e_returnto == &CurEnv->e_from) | |
687 | { | |
688 | CurEnv->e_returnto = maint; | |
689 | MailBack++; | |
690 | } | |
691 | } | |
692 | ||
cdb17311 | 693 | rhs = p; |
cdb17311 EA |
694 | for (;;) |
695 | { | |
696 | register char c; | |
0957ee6f EA |
697 | register char *nlp; |
698 | ||
699 | nlp = &p[strlen(p)]; | |
700 | if (nlp[-1] == '\n') | |
701 | *--nlp = '\0'; | |
d916f0ca | 702 | |
1e963db5 | 703 | if (init && CheckAliases) |
cdb17311 | 704 | { |
f4dbf345 | 705 | /* do parsing & compression of addresses */ |
3312f93c | 706 | while (*p != '\0') |
cdb17311 | 707 | { |
9e2cf26f | 708 | auto char *delimptr; |
3312f93c | 709 | |
2bee003d EA |
710 | while ((isascii(*p) && isspace(*p)) || |
711 | *p == ',') | |
c49d661c | 712 | p++; |
3312f93c EA |
713 | if (*p == '\0') |
714 | break; | |
9e2cf26f | 715 | if (parseaddr(p, &bl, -1, ',', &delimptr, e) == NULL) |
b6edea3d | 716 | usrerr("553 %s... bad address", p); |
9e2cf26f | 717 | p = delimptr; |
cdb17311 | 718 | } |
cdb17311 | 719 | } |
f4dbf345 | 720 | else |
634c8ff3 | 721 | { |
0957ee6f | 722 | p = nlp; |
634c8ff3 | 723 | } |
d916f0ca | 724 | |
cdb17311 | 725 | /* see if there should be a continuation line */ |
9e25d1f0 EA |
726 | c = fgetc(af); |
727 | if (!feof(af)) | |
74c5fe7c | 728 | (void) ungetc(c, af); |
9e25d1f0 | 729 | if (c != ' ' && c != '\t') |
cdb17311 EA |
730 | break; |
731 | ||
732 | /* read continuation line */ | |
cdb17311 EA |
733 | if (fgets(p, sizeof line - (p - line), af) == NULL) |
734 | break; | |
7338e3d4 | 735 | LineNumber++; |
07b49560 EA |
736 | |
737 | /* check for line overflow */ | |
738 | if (strchr(p, '\n') == NULL) | |
739 | { | |
b6edea3d | 740 | usrerr("554 alias too long"); |
07b49560 EA |
741 | break; |
742 | } | |
cdb17311 | 743 | } |
74c5fe7c EA |
744 | |
745 | /* | |
746 | ** Insert alias into symbol table or DBM file | |
747 | */ | |
748 | ||
41173b8f | 749 | lhssize = strlen(lhs) + 1; |
d6b27179 EA |
750 | rhssize = strlen(rhs) + 1; |
751 | ||
4099e6e8 | 752 | # if defined(NDBM) || defined(NEWDB) |
f4dbf345 EA |
753 | if (init) |
754 | { | |
4099e6e8 | 755 | DBdatum key, content; |
698a71d9 | 756 | int putstat; |
f4dbf345 | 757 | |
4099e6e8 EA |
758 | key.xx.size = lhssize; |
759 | key.xx.data = al.q_user; | |
760 | content.xx.size = rhssize; | |
761 | content.xx.data = rhs; | |
07c0651f | 762 | # ifdef NEWDB |
698a71d9 EA |
763 | putstat = dbp->put(dbp, &key.dbt, &content.dbt, |
764 | R_NOOVERWRITE); | |
765 | if (putstat > 0) | |
766 | { | |
aa102c71 | 767 | usrerr("050 Warning: duplicate alias name %s", |
698a71d9 EA |
768 | al.q_user); |
769 | putstat = dbp->put(dbp, &key.dbt, | |
770 | &content.dbt, 0); | |
771 | } | |
772 | if (putstat != 0) | |
aace356e | 773 | syserr("readaliases: db put (%s)", al.q_user); |
6c6e2d3a EA |
774 | # endif |
775 | # ifdef IF_MAKEDBMFILES | |
776 | IF_MAKEDBMFILES | |
698a71d9 EA |
777 | { |
778 | putstat = dbm_store(dbmp, key.dbm, content.dbm, | |
779 | DBM_INSERT); | |
780 | if (putstat > 0) | |
781 | { | |
aa102c71 | 782 | usrerr("050 Warning: duplicate alias name %s", |
698a71d9 EA |
783 | al.q_user); |
784 | putstat = dbm_store(dbmp, key.dbm, | |
785 | content.dbm, DBM_REPLACE); | |
786 | } | |
787 | if (putstat != 0) | |
4099e6e8 EA |
788 | syserr("readaliases: dbm store (%s)", |
789 | al.q_user); | |
698a71d9 | 790 | } |
b9357db9 | 791 | # endif |
698a71d9 EA |
792 | if (al.q_paddr != NULL) |
793 | free(al.q_paddr); | |
794 | if (al.q_host != NULL) | |
795 | free(al.q_host); | |
796 | if (al.q_user != NULL) | |
797 | free(al.q_user); | |
f4dbf345 EA |
798 | } |
799 | else | |
4099e6e8 | 800 | # endif /* NDBM */ |
f4dbf345 EA |
801 | { |
802 | s = stab(al.q_user, ST_ALIAS, ST_ENTER); | |
803 | s->s_alias = newstr(rhs); | |
804 | } | |
d6b27179 EA |
805 | |
806 | /* statistics */ | |
807 | naliases++; | |
808 | bytes += lhssize + rhssize; | |
809 | if (rhssize > longest) | |
810 | longest = rhssize; | |
d916f0ca | 811 | } |
e6e345fa | 812 | |
4099e6e8 | 813 | # if defined(NDBM) || defined(NEWDB) |
e6e345fa EA |
814 | if (init) |
815 | { | |
816 | /* add the distinquished alias "@" */ | |
4099e6e8 | 817 | DBdatum key; |
b9357db9 | 818 | |
4099e6e8 EA |
819 | key.xx.size = 2; |
820 | key.xx.data = "@"; | |
b9357db9 | 821 | # ifdef NEWDB |
aace356e | 822 | if (dbp->sync(dbp) != 0 || |
4099e6e8 | 823 | dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || |
aace356e EA |
824 | dbp->close(dbp) != 0) |
825 | syserr("readaliases: db close failure"); | |
6c6e2d3a | 826 | # endif |
a47061b6 | 827 | # ifdef IF_MAKEDBMFILES |
09098a56 | 828 | IF_MAKEDBMFILES |
4099e6e8 | 829 | { |
c25096f0 EA |
830 | #ifdef YPCOMPAT |
831 | nis_magic(dbmp); | |
832 | #endif | |
4099e6e8 EA |
833 | if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || |
834 | dbm_error(dbmp)) | |
835 | syserr("readaliases: dbm close failure"); | |
836 | dbm_close(dbmp); | |
837 | } | |
b9357db9 | 838 | # endif |
e6e345fa EA |
839 | |
840 | /* restore the old signal */ | |
841 | (void) signal(SIGINT, oldsigint); | |
842 | } | |
4099e6e8 | 843 | # endif /* NDBM */ |
e6e345fa EA |
844 | |
845 | /* closing the alias file drops the lock */ | |
cdb17311 | 846 | (void) fclose(af); |
a4076aed | 847 | e->e_to = NULL; |
7338e3d4 | 848 | FileName = NULL; |
b6edea3d | 849 | message("%d aliases, longest %d bytes, %d bytes total", |
d6b27179 | 850 | naliases, longest, bytes); |
2e3062fe | 851 | # ifdef LOG |
68f7099c | 852 | if (LogLevel > 7) |
2e3062fe EA |
853 | syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", |
854 | naliases, longest, bytes); | |
f3d8f6d6 | 855 | # endif /* LOG */ |
b3cbe40f EA |
856 | } |
857 | \f/* | |
c25096f0 EA |
858 | ** NIS_MAGIC -- Add NIS magic dbm data |
859 | ** | |
860 | ** This adds the magic entries needed by SunOS to make this a valid | |
861 | ** NIS map. | |
862 | ** | |
863 | ** Parameters: | |
864 | ** dbmp -- a pointer to the DBM structure. | |
865 | ** | |
866 | ** Returns: | |
867 | ** none. | |
868 | */ | |
869 | ||
870 | # ifdef YPCOMPAT | |
871 | ||
872 | static void | |
873 | nis_magic(dbmp) | |
874 | DBM *dbmp; | |
875 | { | |
876 | int i; | |
877 | static datum key[2] = | |
878 | { | |
879 | { "YP_LAST_MODIFIED", sizeof "YP_LAST_MODIFIED" - 1 }, | |
880 | { "YP_MASTER_NAME", sizeof "YP_MASTER_NAME" - 1 }, | |
881 | }; | |
882 | datum contents[2]; | |
883 | char tbuf[12]; | |
884 | char hbuf[MAXHOSTNAMELEN]; | |
885 | ||
886 | (void) sprintf(tbuf, "%010ld", curtime()); | |
887 | contents[0].dptr = tbuf; | |
888 | contents[0].dsize = strlen(tbuf); | |
889 | ||
890 | (void) myhostname(hbuf, sizeof hbuf); | |
891 | contents[1].dptr = hbuf; | |
892 | contents[1].dptr = strlen(hbuf); | |
893 | ||
894 | for (i = 0; i < sizeof key / sizeof *key; i++) | |
895 | { | |
896 | if (dbm_store(dbmp, key[i], contents[i], DBM_REPLACE) != 0 || | |
897 | dbm_error(dbmp)) | |
898 | syserr("nis_magic: dbm_store failure"); | |
899 | } | |
900 | } | |
901 | ||
902 | # endif | |
903 | \f/* | |
b3cbe40f EA |
904 | ** FORWARD -- Try to forward mail |
905 | ** | |
906 | ** This is similar but not identical to aliasing. | |
907 | ** | |
b3cbe40f | 908 | ** Parameters: |
74c5fe7c EA |
909 | ** user -- the name of the user who's mail we would like |
910 | ** to forward to. It must have been verified -- | |
911 | ** i.e., the q_home field must have been filled | |
912 | ** in. | |
d4f42161 EA |
913 | ** sendq -- a pointer to the head of the send queue to |
914 | ** put this user's aliases in. | |
b3cbe40f EA |
915 | ** |
916 | ** Returns: | |
cdb17311 | 917 | ** none. |
b3cbe40f EA |
918 | ** |
919 | ** Side Effects: | |
9e3c0a28 | 920 | ** New names are added to send queues. |
b3cbe40f EA |
921 | */ |
922 | ||
a4076aed | 923 | forward(user, sendq, e) |
a530c75f | 924 | ADDRESS *user; |
d4f42161 | 925 | ADDRESS **sendq; |
a4076aed | 926 | register ENVELOPE *e; |
b3cbe40f | 927 | { |
e0136832 EA |
928 | char *pp; |
929 | char *ep; | |
56678245 | 930 | |
9678c96d | 931 | if (tTd(27, 1)) |
cdb17311 | 932 | printf("forward(%s)\n", user->q_paddr); |
cdb17311 | 933 | |
179c1218 | 934 | if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) |
cdb17311 | 935 | return; |
74c5fe7c | 936 | if (user->q_home == NULL) |
c25096f0 | 937 | { |
b6edea3d | 938 | syserr("554 forward: no home"); |
c25096f0 EA |
939 | user->q_home = "/nosuchdirectory"; |
940 | } | |
56678245 | 941 | |
56678245 | 942 | /* good address -- look for .forward file in home */ |
a4076aed | 943 | define('z', user->q_home, e); |
e0136832 EA |
944 | define('u', user->q_user, e); |
945 | define('h', user->q_host, e); | |
946 | if (ForwardPath == NULL) | |
2bee003d | 947 | ForwardPath = newstr("\201z/.forward"); |
e0136832 EA |
948 | |
949 | for (pp = ForwardPath; pp != NULL; pp = ep) | |
950 | { | |
118e6693 | 951 | int err; |
f43b04ce | 952 | char buf[MAXPATHLEN+1]; |
e0136832 EA |
953 | |
954 | ep = strchr(pp, ':'); | |
955 | if (ep != NULL) | |
956 | *ep = '\0'; | |
957 | expand(pp, buf, &buf[sizeof buf - 1], e); | |
958 | if (ep != NULL) | |
959 | *ep++ = ':'; | |
960 | if (tTd(27, 3)) | |
961 | printf("forward: trying %s\n", buf); | |
118e6693 EA |
962 | err = include(buf, TRUE, user, sendq, e); |
963 | if (err == 0) | |
e0136832 | 964 | break; |
118e6693 EA |
965 | if (transienterror(err)) |
966 | { | |
967 | /* we have to suspend this message */ | |
968 | user->q_flags |= QQUEUEUP|QDONTSEND; | |
969 | return; | |
970 | } | |
e0136832 | 971 | } |
b3cbe40f | 972 | } |
41173b8f EA |
973 | \f/* |
974 | ** MAPHOST -- given a host description, produce a mapping. | |
975 | ** | |
976 | ** This is done by looking up the name in the alias file, | |
977 | ** preceeded by an "@". This can be used for UUCP mapping. | |
978 | ** For example, a call with {blia, ., UUCP} as arguments | |
979 | ** might return {ucsfcgl, !, blia, ., UUCP} as the result. | |
980 | ** | |
981 | ** We first break the input into three parts -- before the | |
982 | ** lookup, the lookup itself, and after the lookup. We | |
983 | ** then do the lookup, concatenate them together, and rescan | |
984 | ** the result. | |
985 | ** | |
986 | ** Parameters: | |
987 | ** pvp -- the parameter vector to map. | |
988 | ** | |
989 | ** Returns: | |
990 | ** The result of the mapping. If nothing found, it | |
991 | ** should just concatenate the three parts together and | |
992 | ** return that. | |
993 | ** | |
994 | ** Side Effects: | |
995 | ** none. | |
996 | */ | |
997 | ||
998 | char ** | |
999 | maphost(pvp) | |
1000 | char **pvp; | |
1001 | { | |
1002 | register char **avp; | |
1003 | register char **bvp; | |
1004 | char *p; | |
1005 | char buf1[MAXNAME]; | |
1006 | char buf2[MAXNAME]; | |
1007 | char buf3[MAXNAME]; | |
1008 | extern char **prescan(); | |
1009 | ||
1010 | /* | |
1011 | ** Extract the three parts of the input as strings. | |
1012 | */ | |
1013 | ||
1014 | /* find the part before the lookup */ | |
1015 | for (bvp = pvp; *bvp != NULL && **bvp != MATCHLOOKUP; bvp++) | |
1016 | continue; | |
1017 | if (*bvp == NULL) | |
1018 | return (pvp); | |
1019 | p = *bvp; | |
1020 | *bvp = NULL; | |
1021 | cataddr(pvp, buf1, sizeof buf1); | |
1022 | *bvp++ = p; | |
1023 | ||
1024 | /* find the rest of the lookup */ | |
1025 | for (avp = bvp; *pvp != NULL && **bvp != MATCHELOOKUP; bvp++) | |
1026 | continue; | |
1027 | if (*bvp == NULL) | |
1028 | return (pvp); | |
1029 | p = *bvp; | |
1030 | *bvp = NULL; | |
1031 | cataddr(avp, buf2, sizeof buf2); | |
1032 | *bvp++ = p; | |
1033 | ||
1034 | /* save the part after the lookup */ | |
1035 | cataddr(bvp, buf3, sizeof buf3); | |
1036 | ||
1037 | /* | |
1038 | ** Now look up the middle part. | |
1039 | */ | |
1040 | ||
1041 | p = aliaslookup(buf2); | |
1042 | if (p != NULL) | |
1043 | strcpy(buf2, p); | |
1044 | ||
1045 | /* | |
1046 | ** Put the three parts back together and break into tokens. | |
1047 | */ | |
1048 | ||
1049 | strcat(buf1, buf2); | |
1050 | strcat(buf1, buf3); | |
1051 | avp = prescan(buf1, '\0'); | |
1052 | ||
1053 | /* return this mapping */ | |
1054 | return (avp); | |
1055 | } |