# 2.11BSD#431 - /usr/src/usr.sbin/sendmail/src/alias.c

##### Functions

    alias             X
    aliaslookup       X
    forward           X
    initaliases       X

##### Macros

    DBMMODE           X

       1: /*
       2: **  Sendmail
       3: **  Copyright (c) 1983  Eric P. Allman
       4: **  Berkeley, California
       5: **
       6: **  Copyright (c) 1983 Regents of the University of California.
       7: **  All rights reserved.  The Berkeley software License Agreement
       8: **  specifies the terms and conditions for redistribution.
       9: */
      10:
      11: # include <pwd.h>
      12: # include <sys/types.h>
      13: # include <sys/stat.h>
      14: # include <signal.h>
      15: # include <errno.h>
      16: # include "sendmail.h"
      17: # ifdef FLOCK
      18: # include <sys/file.h>
      19: # endif FLOCK
      20:
      21: #if !defined(lint) && !defined(NOSCCS)
      22: # ifdef DBM
      23: static char SccsId[] = "@(#)alias.c	5.13 (Berkeley) 4/17/86	(with DBM)";
      24: # else DBM
      25: static char SccsId[] = "@(#)alias.c	5.13 (Berkeley) 4/17/86	(without DBM)";
      26: # endif DBM
      27: #endif
      28:
      29:
      30: /*
      31: **  ALIAS -- Compute aliases.
      32: **
      33: **	Scans the alias file for an alias for the given address.
      34: **	If found, it arranges to deliver to the alias list instead.
      35: **	Uses libdbm database if -DDBM.
      36: **
      37: **	Parameters:
      38: **		a -- address to alias.
      39: **		sendq -- a pointer to the head of the send queue
      40: **			to put the aliases in.
      41: **
      42: **	Returns:
      43: **		none
      44: **
      45: **	Side Effects:
      46: **		Aliases found are expanded.
      47: **
      48: **	Notes:
      49: **		If NoAlias (the "-n" flag) is set, no aliasing is
      50: **			done.
      51: **
      52: **	Deficiencies:
      53: **		It should complain about names that are aliased to
      54: **			nothing.
      55: */
      56:
      57:
      58: #ifdef DBM
      59: typedef struct
      60: {
      61:     char    *dptr;
      62:     int dsize;
      63: } DATUM;
      64: extern DATUM fetch();
      65: #endif DBM
      66:
      67: alias(a, sendq)
      68:     register ADDRESS *a;
      69:     ADDRESS **sendq;
      70: {
      71:     register char *p;
      72:     extern char *aliaslookup();
      73:
      74: # ifdef DEBUG
      75:     if (tTd(27, 1))
      76:         printf("alias(%s)\n", a->q_paddr);
      77: # endif
      78:
      79:     /* don't realias already aliased names */
      80:     if (bitset(QDONTSEND, a->q_flags))
      81:         return;
      82:
      83:     CurEnv->e_to = a->q_paddr;
      84:
      85:     /*
      86: 	**  Look up this name
      87: 	*/
      88:
      89:     if (NoAlias)
      90:         p = NULL;
      91:     else
      92:         p = aliaslookup(a->q_user);
      93:     if (p == NULL)
      94:         return;
      95:
      96:     /*
      97: 	**  Match on Alias.
      98: 	**	Deliver to the target list.
      99: 	*/
     100:
     101: # ifdef DEBUG
     102:     if (tTd(27, 1))
     103:         printf("%s (%s, %s) aliased to %s\n",
     104:             a->q_paddr, a->q_host, a->q_user, p);
     105: # endif
     106:     message(Arpa_Info, "aliased to %s", p);
     107:     AliasLevel++;
     108:     sendtolist(p, a, sendq);
     109:     AliasLevel--;
     110: }
     111: /*
     112: **  ALIASLOOKUP -- look up a name in the alias file.
     113: **
     114: **	Parameters:
     115: **		name -- the name to look up.
     116: **
     117: **	Returns:
     118: **		the value of name.
     119: **		NULL if unknown.
     120: **
     121: **	Side Effects:
     122: **		none.
     123: **
     124: **	Warnings:
     125: **		The return value will be trashed across calls.
     126: */
     127:
     128: char *
     129: aliaslookup(name)
     130:     char *name;
     131: {
     132: # ifdef DBM
     133:     DATUM rhs, lhs;
     134:
     135:     /* create a key for fetch */
     136:     lhs.dptr = name;
     137:     lhs.dsize = strlen(name) + 1;
     138:     rhs = fetch(lhs);
     139:     return (rhs.dptr);
     140: # else DBM
     141:     register STAB *s;
     142:
     143:     s = stab(name, ST_ALIAS, ST_FIND);
     144:     if (s == NULL)
     145:         return (NULL);
     146:     return (s->s_alias);
     147: # endif DBM
     148: }
     149: /*
     150: **  INITALIASES -- initialize for aliasing
     151: **
     152: **	Very different depending on whether we are running DBM or not.
     153: **
     154: **	Parameters:
     155: **		aliasfile -- location of aliases.
     156: **		init -- if set and if DBM, initialize the DBM files.
     157: **
     158: **	Returns:
     159: **		none.
     160: **
     161: **	Side Effects:
     162: **		initializes aliases:
     163: **		if DBM:  opens the database.
     164: **		if ~DBM: reads the aliases into the symbol table.
     165: */
     166:
     167: # define DBMMODE    0644
     168:
     169: initaliases(aliasfile, init)
     170:     char *aliasfile;
     171:     bool init;
     172: {
     173: #ifdef DBM
     174:     int atcnt;
     175:     time_t modtime;
     176:     bool automatic = FALSE;
     177:     char buf[MAXNAME];
     178: #endif DBM
     179:     struct stat stb;
     180:     static bool initialized = FALSE;
     181:
     182:     if (initialized)
     183:         return;
     184:     initialized = TRUE;
     185:
     186:     if (aliasfile == NULL || stat(aliasfile, &stb) < 0)
     187:     {
     188:         if (aliasfile != NULL && init)
     189:             syserr("Cannot open %s", aliasfile);
     190:         NoAlias = TRUE;
     191:         errno = 0;
     192:         return;
     193:     }
     194:
     195: # ifdef DBM
     196:     /*
     197: 	**  Check to see that the alias file is complete.
     198: 	**	If not, we will assume that someone died, and it is up
     199: 	**	to us to rebuild it.
     200: 	*/
     201:
     202:     if (!init)
     203:         dbminit(aliasfile);
     204:     atcnt = SafeAlias * 2;
     205:     if (atcnt > 0)
     206:     {
     207:         while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL)
     208:         {
     209:             /*
     210: 			**  Reinitialize alias file in case the new
     211: 			**  one is mv'ed in instead of cp'ed in.
     212: 			**
     213: 			**	Only works with new DBM -- old one will
     214: 			**	just consume file descriptors forever.
     215: 			**	If you have a dbmclose() it can be
     216: 			**	added before the sleep(30).
     217: 			*/
     218:
     219:             sleep(30);
     220: # ifdef NDBM
     221:             dbminit(aliasfile);
     222: # endif NDBM
     223:         }
     224:     }
     225:     else
     226:         atcnt = 1;
     227:
     228:     /*
     229: 	**  See if the DBM version of the file is out of date with
     230: 	**  the text version.  If so, go into 'init' mode automatically.
     231: 	**	This only happens if our effective userid owns the DBM
     232: 	**	version or if the mode of the database is 666 -- this
     233: 	**	is an attempt to avoid protection problems.  Note the
     234: 	**	unpalatable hack to see if the stat succeeded.
     235: 	*/
     236:
     237:     modtime = stb.st_mtime;
     238:     (void) strcpy(buf, aliasfile);
     239:     (void) strcat(buf, ".pag");
     240:     stb.st_ino = 0;
     241:     if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0))
     242:     {
     243:         errno = 0;
     244:         if (AutoRebuild && stb.st_ino != 0 &&
     245:             ((stb.st_mode & 0777) == 0666 || stb.st_uid == geteuid()))
     246:         {
     247:             init = TRUE;
     248:             automatic = TRUE;
     249:             message(Arpa_Info, "rebuilding alias database");
     250: #ifdef LOG
     251:             if (LogLevel >= 7)
     252:                 syslog(LOG_INFO, "rebuilding alias database");
     253: #endif LOG
     254:         }
     255:         else
     256:         {
     257: #ifdef LOG
     258:             if (LogLevel >= 7)
     259:                 syslog(LOG_INFO, "alias database out of date");
     260: #endif LOG
     261:             message(Arpa_Info, "Warning: alias database out of date");
     262:         }
     263:     }
     264:
     265:
     266:     /*
     267: 	**  If necessary, load the DBM file.
     268: 	**	If running without DBM, load the symbol table.
     269: 	*/
     270:
     271:     if (init)
     272:     {
     273: #ifdef LOG
     274:         if (LogLevel >= 6)
     275:         {
     276:             extern char *username();
     277:
     278:             syslog(LOG_NOTICE, "alias database %srebuilt by %s",
     279:                 automatic ? "auto" : "", username());
     280:         }
     281: #endif LOG
     282:         readaliases(aliasfile, TRUE);
     283:     }
     284: # else DBM
     285:     readaliases(aliasfile, init);
     286: # endif DBM
     287: }
     288: /*
     289: **  READALIASES -- read and process the alias file.
     290: **
     291: **	This routine implements the part of initaliases that occurs
     292: **	when we are not going to use the DBM stuff.
     293: **
     294: **	Parameters:
     295: **		aliasfile -- the pathname of the alias file master.
     296: **		init -- if set, initialize the DBM stuff.
     297: **
     298: **	Returns:
     299: **		none.
     300: **
     301: **	Side Effects:
     302: **		Reads aliasfile into the symbol table.
     303: **		Optionally, builds the .dir & .pag files.
     304: */
     305:
     306: static
     307: readaliases(aliasfile, init)
     308:     char *aliasfile;
     309:     bool init;
     310: {
     311:     register char *p;
     312:     char *rhs;
     313:     bool skipping;
     314:     int naliases, longest;
     315:     long bytes;
     316:     FILE *af;
     317:     int (*oldsigint)();
     318:     ADDRESS al, bl;
     319:     register STAB *s;
     320:     char line[BUFSIZ];
     321:
     322:     if ((af = fopen(aliasfile, "r")) == NULL)
     323:     {
     324: # ifdef DEBUG
     325:         if (tTd(27, 1))
     326:             printf("Can't open %s\n", aliasfile);
     327: # endif
     328:         errno = 0;
     329:         NoAlias++;
     330:         return;
     331:     }
     332:
     333: # ifdef DBM
     334: # ifdef FLOCK
     335:     /* see if someone else is rebuilding the alias file already */
     336:     if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK)
     337:     {
     338:         /* yes, they are -- wait until done and then return */
     339:         message(Arpa_Info, "Alias file is already being rebuilt");
     340:         if (OpMode != MD_INITALIAS)
     341:         {
     342:             /* wait for other rebuild to complete */
     343:             (void) flock(fileno(af), LOCK_EX);
     344:         }
     345:         (void) fclose(af);
     346:         errno = 0;
     347:         return;
     348:     }
     349: # endif FLOCK
     350: # endif DBM
     351:
     352:     /*
     353: 	**  If initializing, create the new DBM files.
     354: 	*/
     355:
     356:     if (init)
     357:     {
     358:         oldsigint = signal(SIGINT, SIG_IGN);
     359:         (void) strcpy(line, aliasfile);
     360:         (void) strcat(line, ".dir");
     361:         if (close(creat(line, DBMMODE)) < 0)
     362:         {
     363:             syserr("cannot make %s", line);
     364:             (void) signal(SIGINT, oldsigint);
     365:             return;
     366:         }
     367:         (void) strcpy(line, aliasfile);
     368:         (void) strcat(line, ".pag");
     369:         if (close(creat(line, DBMMODE)) < 0)
     370:         {
     371:             syserr("cannot make %s", line);
     372:             (void) signal(SIGINT, oldsigint);
     373:             return;
     374:         }
     375:         dbminit(aliasfile);
     376:     }
     377:
     378:     /*
     379: 	**  Read and interpret lines
     380: 	*/
     381:
     382:     FileName = aliasfile;
     383:     LineNumber = 0;
     384:     naliases = bytes = longest = 0;
     385:     skipping = FALSE;
     386:     while (fgets(line, sizeof (line), af) != NULL)
     387:     {
     388:         int lhssize, rhssize;
     389:
     390:         LineNumber++;
     391:         p = index(line, '\n');
     392:         if (p != NULL)
     393:             *p = '\0';
     394:         switch (line[0])
     395:         {
     396:           case '#':
     397:           case '\0':
     398:             skipping = FALSE;
     399:             continue;
     400:
     401:           case ' ':
     402:           case '\t':
     403:             if (!skipping)
     404:                 syserr("Non-continuation line starts with space");
     405:             skipping = TRUE;
     406:             continue;
     407:         }
     408:         skipping = FALSE;
     409:
     410:         /*
     411: 		**  Process the LHS
     412: 		**	Find the final colon, and parse the address.
     413: 		**	It should resolve to a local name -- this will
     414: 		**	be checked later (we want to optionally do
     415: 		**	parsing of the RHS first to maximize error
     416: 		**	detection).
     417: 		*/
     418:
     419:         for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
     420:             continue;
     421:         if (*p++ != ':')
     422:         {
     423:             syserr("missing colon");
     424:             continue;
     425:         }
     426:         if (parseaddr(line, &al, 1, ':') == NULL)
     427:         {
     428:             syserr("illegal alias name");
     429:             continue;
     430:         }
     431:         loweraddr(&al);
     432:
     433:         /*
     434: 		**  Process the RHS.
     435: 		**	'al' is the internal form of the LHS address.
     436: 		**	'p' points to the text of the RHS.
     437: 		*/
     438:
     439:         rhs = p;
     440:         for (;;)
     441:         {
     442:             register char c;
     443:
     444:             if (init && CheckAliases)
     445:             {
     446:                 /* do parsing & compression of addresses */
     447:                 while (*p != '\0')
     448:                 {
     449:                     extern char *DelimChar;
     450:
     451:                     while (isspace(*p) || *p == ',')
     452:                         p++;
     453:                     if (*p == '\0')
     454:                         break;
     455:                     if (parseaddr(p, &bl, -1, ',') == NULL)
     456:                         usrerr("%s... bad address", p);
     457:                     if (bl.q_host && bl.q_host[0])
     458:                         free(bl.q_host);
     459:                     p = DelimChar;
     460:                 }
     461:             }
     462:             else
     463:             {
     464:                 p = &p[strlen(p)];
     465:                 if (p[-1] == '\n')
     466:                     *--p = '\0';
     467:             }
     468:
     469:             /* see if there should be a continuation line */
     470:             c = fgetc(af);
     471:             if (!feof(af))
     472:                 (void) ungetc(c, af);
     473:             if (c != ' ' && c != '\t')
     474:                 break;
     475:
     476:             /* read continuation line */
     477:             if (fgets(p, sizeof line - (p - line), af) == NULL)
     478:                 break;
     479:             LineNumber++;
     480:         }
     481:         if (al.q_mailer != LocalMailer)
     482:         {
     483:             syserr("cannot alias non-local names");
     484:             continue;
     485:         }
     486:
     487:         /*
     488: 		**  Insert alias into symbol table or DBM file
     489: 		*/
     490:
     491:         lhssize = strlen(al.q_user) + 1;
     492:         rhssize = strlen(rhs) + 1;
     493:
     494: # ifdef DBM
     495:         if (init)
     496:         {
     497:             DATUM key, content;
     498:
     499:             key.dsize = lhssize;
     500:             key.dptr = al.q_user;
     501:             content.dsize = rhssize;
     502:             content.dptr = rhs;
     503:             store(key, content);
     504:             if (al.q_paddr)
     505:                 free(al.q_paddr);
     506:             if (al.q_host)
     507:                 free(al.q_host);
     508:             if (al.q_user)
     509:                 free(al.q_user);
     510:         }
     511:         else
     512: # endif DBM
     513:         {
     514:             s = stab(al.q_user, ST_ALIAS, ST_ENTER);
     515:             s->s_alias = newstr(rhs);
     516:         }
     517:
     518:         /* statistics */
     519:         naliases++;
     520:         bytes += lhssize + rhssize;
     521:         if (rhssize > longest)
     522:             longest = rhssize;
     523:     }
     524:
     525: # ifdef DBM
     526:     if (init)
     527:     {
     528:         /* add the distinquished alias "@" */
     529:         DATUM key;
     530:
     531:         key.dsize = 2;
     532:         key.dptr = "@";
     533:         store(key, key);
     534:
     535:         /* restore the old signal */
     536:         (void) signal(SIGINT, oldsigint);
     537:     }
     538: # endif DBM
     539:
     540:     /* closing the alias file drops the lock */
     541:     (void) fclose(af);
     542:     CurEnv->e_to = NULL;
     543:     FileName = NULL;
     544:     message(Arpa_Info, "%d aliases, longest %d bytes, %ld bytes total",
     545:             naliases, longest, bytes);
     546: # ifdef LOG
     547:     if (LogLevel >= 8)
     548:         syslog(LOG_INFO, "%d aliases, longest %d bytes, %ld bytes total",
     549:             naliases, longest, bytes);
     550: # endif LOG
     551: }
     552: /*
     553: **  FORWARD -- Try to forward mail
     554: **
     555: **	This is similar but not identical to aliasing.
     556: **
     557: **	Parameters:
     558: **		user -- the name of the user who's mail we would like
     559: **			to forward to.  It must have been verified --
     560: **			i.e., the q_home field must have been filled
     561: **			in.
     562: **		sendq -- a pointer to the head of the send queue to
     563: **			put this user's aliases in.
     564: **
     565: **	Returns:
     566: **		none.
     567: **
     568: **	Side Effects:
     569: **		New names are added to send queues.
     570: */
     571:
     572: forward(user, sendq)
     573:     ADDRESS *user;
     574:     ADDRESS **sendq;
     575: {
     576:     char buf[60];
     577:     extern bool safefile();
     578:
     579: # ifdef DEBUG
     580:     if (tTd(27, 1))
     581:         printf("forward(%s)\n", user->q_paddr);
     582: # endif DEBUG
     583:
     584:     if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags))
     585:         return;
     586: # ifdef DEBUG
     587:     if (user->q_home == NULL)
     588:         syserr("forward: no home");
     589: # endif DEBUG
     590:
     591:     /* good address -- look for .forward file in home */
     592:     define('z', user->q_home, CurEnv);
     593:     expand("\001z/.forward", buf, &buf[sizeof buf - 1], CurEnv);
     594:     if (!safefile(buf, user->q_uid, S_IREAD))
     595:         return;
     596:
     597:     /* we do have an address to forward to -- do it */
     598:     include(buf, "forwarding", user, sendq);
     599: }

#### Defined functions

alias defined in line 67; used 1 times

- in /usr/src/usr.sbin/sendmail/src/recipient.c line 273

aliaslookup defined in line 128; used 5 times

- in line 72, 92, 207
- in /usr/src/usr.sbin/sendmail/src/deliver.c line 1422, 1434

forward defined in line 572; used 1 times

- in /usr/src/usr.sbin/sendmail/src/recipient.c line 335

initaliases defined in line 169; used 4 times

- in /usr/src/usr.sbin/sendmail/src/main.c line 500, 509
- in /usr/src/usr.sbin/sendmail/src/queue.c line 328
- in /usr/src/usr.sbin/sendmail/src/srvrsmtp.c line 676

readaliases defined in line 306; used 2 times

- in line 282-285(2)

#### Defined variables

SccsId defined in line 25; never used

#### Defined macros

DBMMODE defined in line 167; used 2 times

- in line 361, 369

Last modified: 1991-08-22 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2151 |