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

Defined functions

alias defined in line 50; used 1 times
aliaslookup defined in line 110; never used
forward defined in line 472; used 1 times
initaliases defined in line 151; used 1 times
readaliases defined in line 280; used 2 times

Defined macros

DBMMODE defined in line 149; used 2 times
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1216
Valid CSS Valid XHTML 1.0 Strict