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