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

##### Functions

    alias             X
    aliaslookup       X
    forward           X
    initaliases       X

##### Macros

    DBMMODE           X

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

#### Defined functions

alias defined in line 70; used 1 times

- in /usr/src/usr.sbin/sendmail.MX/src/recipient.c line 266

aliaslookup defined in line 131; used 5 times

- in line 75, 95, 210
- in /usr/src/usr.sbin/sendmail.MX/src/deliver.c line 1471, 1483

forward defined in line 564; used 1 times

- in /usr/src/usr.sbin/sendmail.MX/src/recipient.c line 328

initaliases defined in line 172; used 4 times

- in /usr/src/usr.sbin/sendmail.MX/src/main.c line 496, 505
- in /usr/src/usr.sbin/sendmail.MX/src/queue.c line 339
- in /usr/src/usr.sbin/sendmail.MX/src/srvrsmtp.c line 685

readaliases defined in line 309; used 2 times

- in line 285-288(2)

#### Defined variables

sccsid defined in line 21; never used

#### Defined macros

DBMMODE defined in line 170; used 2 times

- in line 361, 369

Last modified: 1988-09-14 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1784 |