summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/alias.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/alias.c')
-rw-r--r--contrib/sendmail/src/alias.c1015
1 files changed, 0 insertions, 1015 deletions
diff --git a/contrib/sendmail/src/alias.c b/contrib/sendmail/src/alias.c
deleted file mode 100644
index 3eae4ba..0000000
--- a/contrib/sendmail/src/alias.c
+++ /dev/null
@@ -1,1015 +0,0 @@
-/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
- * All rights reserved.
- * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * By using this file, you agree to the terms and conditions set
- * forth in the LICENSE file which can be found at the top level of
- * the sendmail distribution.
- *
- */
-
-#include <sendmail.h>
-
-SM_RCSID("@(#)$Id: alias.c,v 8.219 2006/10/24 18:04:09 ca Exp $")
-
-#define SEPARATOR ':'
-# define ALIAS_SPEC_SEPARATORS " ,/:"
-
-static MAP *AliasFileMap = NULL; /* the actual aliases.files map */
-static int NAliasFileMaps; /* the number of entries in AliasFileMap */
-
-static char *aliaslookup __P((char *, int *, char *));
-
-/*
-** ALIAS -- Compute aliases.
-**
-** Scans the alias file for an alias for the given address.
-** If found, it arranges to deliver to the alias list instead.
-** Uses libdbm database if -DDBM.
-**
-** Parameters:
-** a -- address to alias.
-** sendq -- a pointer to the head of the send queue
-** to put the aliases in.
-** aliaslevel -- the current alias nesting depth.
-** e -- the current envelope.
-**
-** Returns:
-** none
-**
-** Side Effects:
-** Aliases found are expanded.
-**
-** Deficiencies:
-** It should complain about names that are aliased to
-** nothing.
-*/
-
-void
-alias(a, sendq, aliaslevel, e)
- register ADDRESS *a;
- ADDRESS **sendq;
- int aliaslevel;
- register ENVELOPE *e;
-{
- register char *p;
- char *owner;
- auto int status = EX_OK;
- char obuf[MAXNAME + 7];
-
- if (tTd(27, 1))
- sm_dprintf("alias(%s)\n", a->q_user);
-
- /* don't realias already aliased names */
- if (!QS_IS_OK(a->q_state))
- return;
-
- if (NoAlias)
- return;
-
- e->e_to = a->q_paddr;
-
- /*
- ** Look up this name.
- **
- ** If the map was unavailable, we will queue this message
- ** until the map becomes available; otherwise, we could
- ** bounce messages inappropriately.
- */
-
-#if _FFR_REDIRECTEMPTY
- /*
- ** envelope <> can't be sent to mailing lists, only owner-
- ** send spam of this type to owner- of the list
- ** ---- to stop spam from going to mailing lists!
- */
-
- if (e->e_sender != NULL && *e->e_sender == '\0')
- {
- /* Look for owner of alias */
- (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user);
- if (aliaslookup(obuf, &status, a->q_host) != NULL)
- {
- if (LogLevel > 8)
- sm_syslog(LOG_WARNING, e->e_id,
- "possible spam from <> to list: %s, redirected to %s\n",
- a->q_user, obuf);
- a->q_user = sm_rpool_strdup_x(e->e_rpool, obuf);
- }
- }
-#endif /* _FFR_REDIRECTEMPTY */
-
- p = aliaslookup(a->q_user, &status, a->q_host);
- if (status == EX_TEMPFAIL || status == EX_UNAVAILABLE)
- {
- a->q_state = QS_QUEUEUP;
- if (e->e_message == NULL)
- e->e_message = sm_rpool_strdup_x(e->e_rpool,
- "alias database unavailable");
-
- /* XXX msg only per recipient? */
- if (a->q_message == NULL)
- a->q_message = "alias database unavailable";
- return;
- }
- if (p == NULL)
- return;
-
- /*
- ** Match on Alias.
- ** Deliver to the target list.
- */
-
- if (tTd(27, 1))
- sm_dprintf("%s (%s, %s) aliased to %s\n",
- a->q_paddr, a->q_host, a->q_user, p);
- if (bitset(EF_VRFYONLY, e->e_flags))
- {
- a->q_state = QS_VERIFIED;
- return;
- }
- message("aliased to %s", shortenstring(p, MAXSHORTSTR));
- if (LogLevel > 10)
- sm_syslog(LOG_INFO, e->e_id,
- "alias %.100s => %s",
- a->q_paddr, shortenstring(p, MAXSHORTSTR));
- a->q_flags &= ~QSELFREF;
- if (tTd(27, 5))
- {
- sm_dprintf("alias: QS_EXPANDED ");
- printaddr(sm_debug_file(), a, false);
- }
- a->q_state = QS_EXPANDED;
-
- /*
- ** Always deliver aliased items as the default user.
- ** Setting q_gid to 0 forces deliver() to use DefUser
- ** instead of the alias name for the call to initgroups().
- */
-
- a->q_uid = DefUid;
- a->q_gid = 0;
- a->q_fullname = NULL;
- a->q_flags |= QGOODUID|QALIAS;
-
- (void) sendtolist(p, a, sendq, aliaslevel + 1, e);
-
- if (bitset(QSELFREF, a->q_flags) && QS_IS_EXPANDED(a->q_state))
- a->q_state = QS_OK;
-
- /*
- ** Look for owner of alias
- */
-
- if (strncmp(a->q_user, "owner-", 6) == 0 ||
- strlen(a->q_user) > sizeof(obuf) - 7)
- (void) sm_strlcpy(obuf, "owner-owner", sizeof(obuf));
- else
- (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user);
- owner = aliaslookup(obuf, &status, a->q_host);
- if (owner == NULL)
- return;
-
- /* reflect owner into envelope sender */
- if (strpbrk(owner, ",:/|\"") != NULL)
- owner = obuf;
- a->q_owner = sm_rpool_strdup_x(e->e_rpool, owner);
-
- /* announce delivery to this alias; NORECEIPT bit set later */
- if (e->e_xfp != NULL)
- (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
- "Message delivered to mailing list %s\n",
- a->q_paddr);
- e->e_flags |= EF_SENDRECEIPT;
- a->q_flags |= QDELIVERED|QEXPANDED;
-}
-/*
-** ALIASLOOKUP -- look up a name in the alias file.
-**
-** Parameters:
-** name -- the name to look up.
-** pstat -- a pointer to a place to put the status.
-** av -- argument for %1 expansion.
-**
-** Returns:
-** the value of name.
-** NULL if unknown.
-**
-** Side Effects:
-** none.
-**
-** Warnings:
-** The return value will be trashed across calls.
-*/
-
-static char *
-aliaslookup(name, pstat, av)
- char *name;
- int *pstat;
- char *av;
-{
- static MAP *map = NULL;
-#if _FFR_ALIAS_DETAIL
- int i;
- char *argv[4];
-#endif /* _FFR_ALIAS_DETAIL */
-
- if (map == NULL)
- {
- STAB *s = stab("aliases", ST_MAP, ST_FIND);
-
- if (s == NULL)
- return NULL;
- map = &s->s_map;
- }
- DYNOPENMAP(map);
-
- /* special case POstMastER -- always use lower case */
- if (sm_strcasecmp(name, "postmaster") == 0)
- name = "postmaster";
-
-#if _FFR_ALIAS_DETAIL
- i = 0;
- argv[i++] = name;
- argv[i++] = av;
-
- /* XXX '+' is hardwired here as delimiter! */
- if (av != NULL && *av == '+')
- argv[i++] = av + 1;
- argv[i++] = NULL;
- return (*map->map_class->map_lookup)(map, name, argv, pstat);
-#else /* _FFR_ALIAS_DETAIL */
- return (*map->map_class->map_lookup)(map, name, NULL, pstat);
-#endif /* _FFR_ALIAS_DETAIL */
-}
-/*
-** SETALIAS -- set up an alias map
-**
-** Called when reading configuration file.
-**
-** Parameters:
-** spec -- the alias specification
-**
-** Returns:
-** none.
-*/
-
-void
-setalias(spec)
- char *spec;
-{
- register char *p;
- register MAP *map;
- char *class;
- STAB *s;
-
- if (tTd(27, 8))
- sm_dprintf("setalias(%s)\n", spec);
-
- for (p = spec; p != NULL; )
- {
- char buf[50];
-
- while (isascii(*p) && isspace(*p))
- p++;
- if (*p == '\0')
- break;
- spec = p;
-
- if (NAliasFileMaps >= MAXMAPSTACK)
- {
- syserr("Too many alias databases defined, %d max",
- MAXMAPSTACK);
- return;
- }
- if (AliasFileMap == NULL)
- {
- (void) sm_strlcpy(buf, "aliases.files sequence",
- sizeof(buf));
- AliasFileMap = makemapentry(buf);
- if (AliasFileMap == NULL)
- {
- syserr("setalias: cannot create aliases.files map");
- return;
- }
- }
- (void) sm_snprintf(buf, sizeof(buf), "Alias%d", NAliasFileMaps);
- s = stab(buf, ST_MAP, ST_ENTER);
- map = &s->s_map;
- memset(map, '\0', sizeof(*map));
- map->map_mname = s->s_name;
- p = strpbrk(p, ALIAS_SPEC_SEPARATORS);
- if (p != NULL && *p == SEPARATOR)
- {
- /* map name */
- *p++ = '\0';
- class = spec;
- spec = p;
- }
- else
- {
- class = "implicit";
- map->map_mflags = MF_INCLNULL;
- }
-
- /* find end of spec */
- if (p != NULL)
- {
- bool quoted = false;
-
- for (; *p != '\0'; p++)
- {
- /*
- ** Don't break into a quoted string.
- ** Needed for ldap maps which use
- ** commas in their specifications.
- */
-
- if (*p == '"')
- quoted = !quoted;
- else if (*p == ',' && !quoted)
- break;
- }
-
- /* No more alias specifications follow */
- if (*p == '\0')
- p = NULL;
- }
- if (p != NULL)
- *p++ = '\0';
-
- if (tTd(27, 20))
- sm_dprintf(" map %s:%s %s\n", class, s->s_name, spec);
-
- /* look up class */
- s = stab(class, ST_MAPCLASS, ST_FIND);
- if (s == NULL)
- {
- syserr("setalias: unknown alias class %s", class);
- }
- else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags))
- {
- syserr("setalias: map class %s can't handle aliases",
- class);
- }
- else
- {
- map->map_class = &s->s_mapclass;
- map->map_mflags |= MF_ALIAS;
- if (map->map_class->map_parse(map, spec))
- {
- map->map_mflags |= MF_VALID;
- AliasFileMap->map_stack[NAliasFileMaps++] = map;
- }
- }
- }
-}
-/*
-** ALIASWAIT -- wait for distinguished @:@ token to appear.
-**
-** This can decide to reopen or rebuild the alias file
-**
-** Parameters:
-** map -- a pointer to the map descriptor for this alias file.
-** ext -- the filename extension (e.g., ".db") for the
-** database file.
-** isopen -- if set, the database is already open, and we
-** should check for validity; otherwise, we are
-** just checking to see if it should be created.
-**
-** Returns:
-** true -- if the database is open when we return.
-** false -- if the database is closed when we return.
-*/
-
-bool
-aliaswait(map, ext, isopen)
- MAP *map;
- char *ext;
- bool isopen;
-{
- bool attimeout = false;
- time_t mtime;
- struct stat stb;
- char buf[MAXPATHLEN];
-
- if (tTd(27, 3))
- sm_dprintf("aliaswait(%s:%s)\n",
- map->map_class->map_cname, map->map_file);
- if (bitset(MF_ALIASWAIT, map->map_mflags))
- return isopen;
- map->map_mflags |= MF_ALIASWAIT;
-
- if (SafeAlias > 0)
- {
- auto int st;
- unsigned int sleeptime = 2;
- unsigned int loopcount = 0; /* only used for debugging */
- time_t toolong = curtime() + SafeAlias;
-
- while (isopen &&
- map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
- {
- if (curtime() > toolong)
- {
- /* we timed out */
- attimeout = true;
- break;
- }
-
- /*
- ** Close and re-open the alias database in case
- ** the one is mv'ed instead of cp'ed in.
- */
-
- if (tTd(27, 2))
- {
- loopcount++;
- sm_dprintf("aliaswait: sleeping for %u seconds (loopcount = %u)\n",
- sleeptime, loopcount);
- }
-
- map->map_mflags |= MF_CLOSING;
- map->map_class->map_close(map);
- map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
- (void) sleep(sleeptime);
- sleeptime *= 2;
- if (sleeptime > 60)
- sleeptime = 60;
- isopen = map->map_class->map_open(map, O_RDONLY);
- }
- }
-
- /* see if we need to go into auto-rebuild mode */
- if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
- {
- if (tTd(27, 3))
- sm_dprintf("aliaswait: not rebuildable\n");
- map->map_mflags &= ~MF_ALIASWAIT;
- return isopen;
- }
- if (stat(map->map_file, &stb) < 0)
- {
- if (tTd(27, 3))
- sm_dprintf("aliaswait: no source file\n");
- map->map_mflags &= ~MF_ALIASWAIT;
- return isopen;
- }
- mtime = stb.st_mtime;
- if (sm_strlcpyn(buf, sizeof(buf), 2,
- map->map_file, ext == NULL ? "" : ext) >= sizeof(buf))
- {
- if (LogLevel > 3)
- sm_syslog(LOG_INFO, NOQID,
- "alias database %s%s name too long",
- map->map_file, ext == NULL ? "" : ext);
- message("alias database %s%s name too long",
- map->map_file, ext == NULL ? "" : ext);
- }
-
- if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout)
- {
- if (LogLevel > 3)
- sm_syslog(LOG_INFO, NOQID,
- "alias database %s out of date", buf);
- message("Warning: alias database %s out of date", buf);
- }
- map->map_mflags &= ~MF_ALIASWAIT;
- return isopen;
-}
-/*
-** REBUILDALIASES -- rebuild the alias database.
-**
-** Parameters:
-** map -- the database to rebuild.
-** automatic -- set if this was automatically generated.
-**
-** Returns:
-** true if successful; false otherwise.
-**
-** Side Effects:
-** Reads the text version of the database, builds the
-** DBM or DB version.
-*/
-
-bool
-rebuildaliases(map, automatic)
- register MAP *map;
- bool automatic;
-{
- SM_FILE_T *af;
- bool nolock = false;
- bool success = false;
- long sff = SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK;
- sigfunc_t oldsigint, oldsigquit;
-#ifdef SIGTSTP
- sigfunc_t oldsigtstp;
-#endif /* SIGTSTP */
-
- if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
- return false;
-
- if (!bitnset(DBS_LINKEDALIASFILEINWRITABLEDIR, DontBlameSendmail))
- sff |= SFF_NOWLINK;
- if (!bitnset(DBS_GROUPWRITABLEALIASFILE, DontBlameSendmail))
- sff |= SFF_NOGWFILES;
- if (!bitnset(DBS_WORLDWRITABLEALIASFILE, DontBlameSendmail))
- sff |= SFF_NOWWFILES;
-
- /* try to lock the source file */
- if ((af = safefopen(map->map_file, O_RDWR, 0, sff)) == NULL)
- {
- struct stat stb;
-
- if ((errno != EACCES && errno != EROFS) || automatic ||
- (af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL)
- {
- int saveerr = errno;
-
- if (tTd(27, 1))
- sm_dprintf("Can't open %s: %s\n",
- map->map_file, sm_errstring(saveerr));
- if (!automatic && !bitset(MF_OPTIONAL, map->map_mflags))
- message("newaliases: cannot open %s: %s",
- map->map_file, sm_errstring(saveerr));
- errno = 0;
- return false;
- }
- nolock = true;
- if (tTd(27, 1) ||
- fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &stb) < 0 ||
- bitset(S_IWUSR|S_IWGRP|S_IWOTH, stb.st_mode))
- message("warning: cannot lock %s: %s",
- map->map_file, sm_errstring(errno));
- }
-
- /* see if someone else is rebuilding the alias file */
- if (!nolock &&
- !lockfile(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), map->map_file,
- NULL, LOCK_EX|LOCK_NB))
- {
- /* yes, they are -- wait until done */
- message("Alias file %s is locked (maybe being rebuilt)",
- map->map_file);
- if (OpMode != MD_INITALIAS)
- {
- /* wait for other rebuild to complete */
- (void) lockfile(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL),
- map->map_file, NULL, LOCK_EX);
- }
- (void) sm_io_close(af, SM_TIME_DEFAULT);
- errno = 0;
- return false;
- }
-
- oldsigint = sm_signal(SIGINT, SIG_IGN);
- oldsigquit = sm_signal(SIGQUIT, SIG_IGN);
-#ifdef SIGTSTP
- oldsigtstp = sm_signal(SIGTSTP, SIG_IGN);
-#endif /* SIGTSTP */
-
- if (map->map_class->map_open(map, O_RDWR))
- {
- if (LogLevel > 7)
- {
- sm_syslog(LOG_NOTICE, NOQID,
- "alias database %s %srebuilt by %s",
- map->map_file, automatic ? "auto" : "",
- username());
- }
- map->map_mflags |= MF_OPEN|MF_WRITABLE;
- map->map_pid = CurrentPid;
- readaliases(map, af, !automatic, true);
- success = true;
- }
- else
- {
- if (tTd(27, 1))
- sm_dprintf("Can't create database for %s: %s\n",
- map->map_file, sm_errstring(errno));
- if (!automatic)
- syserr("Cannot create database for alias file %s",
- map->map_file);
- }
-
- /* close the file, thus releasing locks */
- (void) sm_io_close(af, SM_TIME_DEFAULT);
-
- /* add distinguished entries and close the database */
- if (bitset(MF_OPEN, map->map_mflags))
- {
- map->map_mflags |= MF_CLOSING;
- map->map_class->map_close(map);
- map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
- }
-
- /* restore the old signals */
- (void) sm_signal(SIGINT, oldsigint);
- (void) sm_signal(SIGQUIT, oldsigquit);
-#ifdef SIGTSTP
- (void) sm_signal(SIGTSTP, oldsigtstp);
-#endif /* SIGTSTP */
- return success;
-}
-/*
-** READALIASES -- read and process the alias file.
-**
-** This routine implements the part of initaliases that occurs
-** when we are not going to use the DBM stuff.
-**
-** Parameters:
-** map -- the alias database descriptor.
-** af -- file to read the aliases from.
-** announcestats -- announce statistics regarding number of
-** aliases, longest alias, etc.
-** logstats -- lot the same info.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Reads aliasfile into the symbol table.
-** Optionally, builds the .dir & .pag files.
-*/
-
-void
-readaliases(map, af, announcestats, logstats)
- register MAP *map;
- SM_FILE_T *af;
- bool announcestats;
- bool logstats;
-{
- register char *p;
- char *rhs;
- bool skipping;
- long naliases, bytes, longest;
- ADDRESS al, bl;
- char line[BUFSIZ];
-
- /*
- ** Read and interpret lines
- */
-
- FileName = map->map_file;
- LineNumber = 0;
- naliases = bytes = longest = 0;
- skipping = false;
- while (sm_io_fgets(af, SM_TIME_DEFAULT, line, sizeof(line)) != NULL)
- {
- int lhssize, rhssize;
- int c;
-
- LineNumber++;
- p = strchr(line, '\n');
-
- /* XXX what if line="a\\" ? */
- while (p != NULL && p > line && p[-1] == '\\')
- {
- p--;
- if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
- SPACELEFT(line, p)) == NULL)
- break;
- LineNumber++;
- p = strchr(p, '\n');
- }
- if (p != NULL)
- *p = '\0';
- else if (!sm_io_eof(af))
- {
- errno = 0;
- syserr("554 5.3.0 alias line too long");
-
- /* flush to end of line */
- while ((c = sm_io_getc(af, SM_TIME_DEFAULT)) !=
- SM_IO_EOF && c != '\n')
- continue;
-
- /* skip any continuation lines */
- skipping = true;
- continue;
- }
- switch (line[0])
- {
- case '#':
- case '\0':
- skipping = false;
- continue;
-
- case ' ':
- case '\t':
- if (!skipping)
- syserr("554 5.3.5 Non-continuation line starts with space");
- skipping = true;
- continue;
- }
- skipping = false;
-
- /*
- ** Process the LHS
- ** Find the colon separator, and parse the address.
- ** It should resolve to a local name -- this will
- ** be checked later (we want to optionally do
- ** parsing of the RHS first to maximize error
- ** detection).
- */
-
- for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
- continue;
- if (*p++ != ':')
- {
- syserr("554 5.3.5 missing colon");
- continue;
- }
- if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv, true)
- == NULL)
- {
- syserr("554 5.3.5 %.40s... illegal alias name", line);
- continue;
- }
-
- /*
- ** Process the RHS.
- ** 'al' is the internal form of the LHS address.
- ** 'p' points to the text of the RHS.
- */
-
- while (isascii(*p) && isspace(*p))
- p++;
- rhs = p;
- for (;;)
- {
- register char *nlp;
-
- nlp = &p[strlen(p)];
- if (nlp > p && nlp[-1] == '\n')
- *--nlp = '\0';
-
- if (CheckAliases)
- {
- /* do parsing & compression of addresses */
- while (*p != '\0')
- {
- auto char *delimptr;
-
- while ((isascii(*p) && isspace(*p)) ||
- *p == ',')
- p++;
- if (*p == '\0')
- break;
- if (parseaddr(p, &bl, RF_COPYNONE, ',',
- &delimptr, CurEnv, true)
- == NULL)
- usrerr("553 5.3.5 %s... bad address", p);
- p = delimptr;
- }
- }
- else
- {
- p = nlp;
- }
-
- /* see if there should be a continuation line */
- c = sm_io_getc(af, SM_TIME_DEFAULT);
- if (!sm_io_eof(af))
- (void) sm_io_ungetc(af, SM_TIME_DEFAULT, c);
- if (c != ' ' && c != '\t')
- break;
-
- /* read continuation line */
- if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
- sizeof(line) - (p-line)) == NULL)
- break;
- LineNumber++;
-
- /* check for line overflow */
- if (strchr(p, '\n') == NULL && !sm_io_eof(af))
- {
- usrerr("554 5.3.5 alias too long");
- while ((c = sm_io_getc(af, SM_TIME_DEFAULT))
- != SM_IO_EOF && c != '\n')
- continue;
- skipping = true;
- break;
- }
- }
-
- if (skipping)
- continue;
-
- if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags))
- {
- syserr("554 5.3.5 %s... cannot alias non-local names",
- al.q_paddr);
- continue;
- }
-
- /*
- ** Insert alias into symbol table or database file.
- **
- ** Special case pOStmaStER -- always make it lower case.
- */
-
- if (sm_strcasecmp(al.q_user, "postmaster") == 0)
- makelower(al.q_user);
-
- lhssize = strlen(al.q_user);
- rhssize = strlen(rhs);
- if (rhssize > 0)
- {
- /* is RHS empty (just spaces)? */
- p = rhs;
- while (isascii(*p) && isspace(*p))
- p++;
- }
- if (rhssize == 0 || *p == '\0')
- {
- syserr("554 5.3.5 %.40s... missing value for alias",
- line);
-
- }
- else
- {
- map->map_class->map_store(map, al.q_user, rhs);
-
- /* statistics */
- naliases++;
- bytes += lhssize + rhssize;
- if (rhssize > longest)
- longest = rhssize;
- }
-
-#if 0
- /*
- ** address strings are now stored in the envelope rpool,
- ** and therefore cannot be freed.
- */
- if (al.q_paddr != NULL)
- sm_free(al.q_paddr); /* disabled */
- if (al.q_host != NULL)
- sm_free(al.q_host); /* disabled */
- if (al.q_user != NULL)
- sm_free(al.q_user); /* disabled */
-#endif /* 0 */
- }
-
- CurEnv->e_to = NULL;
- FileName = NULL;
- if (Verbose || announcestats)
- message("%s: %ld aliases, longest %ld bytes, %ld bytes total",
- map->map_file, naliases, longest, bytes);
- if (LogLevel > 7 && logstats)
- sm_syslog(LOG_INFO, NOQID,
- "%s: %ld aliases, longest %ld bytes, %ld bytes total",
- map->map_file, naliases, longest, bytes);
-}
-/*
-** FORWARD -- Try to forward mail
-**
-** This is similar but not identical to aliasing.
-**
-** Parameters:
-** user -- the name of the user who's mail we would like
-** to forward to. It must have been verified --
-** i.e., the q_home field must have been filled
-** in.
-** sendq -- a pointer to the head of the send queue to
-** put this user's aliases in.
-** aliaslevel -- the current alias nesting depth.
-** e -- the current envelope.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** New names are added to send queues.
-*/
-
-void
-forward(user, sendq, aliaslevel, e)
- ADDRESS *user;
- ADDRESS **sendq;
- int aliaslevel;
- register ENVELOPE *e;
-{
- char *pp;
- char *ep;
- bool got_transient;
-
- if (tTd(27, 1))
- sm_dprintf("forward(%s)\n", user->q_paddr);
-
- if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) ||
- !QS_IS_OK(user->q_state))
- return;
- if (ForwardPath != NULL && *ForwardPath == '\0')
- return;
- if (user->q_home == NULL)
- {
- syserr("554 5.3.0 forward: no home");
- user->q_home = "/no/such/directory";
- }
-
- /* good address -- look for .forward file in home */
- macdefine(&e->e_macro, A_PERM, 'z', user->q_home);
- macdefine(&e->e_macro, A_PERM, 'u', user->q_user);
- macdefine(&e->e_macro, A_PERM, 'h', user->q_host);
- if (ForwardPath == NULL)
- ForwardPath = newstr("\201z/.forward");
-
- got_transient = false;
- for (pp = ForwardPath; pp != NULL; pp = ep)
- {
- int err;
- char buf[MAXPATHLEN];
- struct stat st;
-
- ep = strchr(pp, SEPARATOR);
- if (ep != NULL)
- *ep = '\0';
- expand(pp, buf, sizeof(buf), e);
- if (ep != NULL)
- *ep++ = SEPARATOR;
- if (buf[0] == '\0')
- continue;
- if (tTd(27, 3))
- sm_dprintf("forward: trying %s\n", buf);
-
- err = include(buf, true, user, sendq, aliaslevel, e);
- if (err == 0)
- break;
- else if (transienterror(err))
- {
- /* we may have to suspend this message */
- got_transient = true;
- if (tTd(27, 2))
- sm_dprintf("forward: transient error on %s\n",
- buf);
- if (LogLevel > 2)
- {
- char *curhost = CurHostName;
-
- CurHostName = NULL;
- sm_syslog(LOG_ERR, e->e_id,
- "forward %s: transient error: %s",
- buf, sm_errstring(err));
- CurHostName = curhost;
- }
-
- }
- else
- {
- switch (err)
- {
- case ENOENT:
- break;
-
- case E_SM_WWDIR:
- case E_SM_GWDIR:
- /* check if it even exists */
- if (stat(buf, &st) < 0 && errno == ENOENT)
- {
- if (bitnset(DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH,
- DontBlameSendmail))
- break;
- }
- /* FALLTHROUGH */
-
-#if _FFR_FORWARD_SYSERR
- case E_SM_NOSLINK:
- case E_SM_NOHLINK:
- case E_SM_REGONLY:
- case E_SM_ISEXEC:
- case E_SM_WWFILE:
- case E_SM_GWFILE:
- syserr("forward: %s: %s", buf, sm_errstring(err));
- break;
-#endif /* _FFR_FORWARD_SYSERR */
-
- default:
- if (LogLevel > (RunAsUid == 0 ? 2 : 10))
- sm_syslog(LOG_WARNING, e->e_id,
- "forward %s: %s", buf,
- sm_errstring(err));
- if (Verbose)
- message("forward: %s: %s",
- buf, sm_errstring(err));
- break;
- }
- }
- }
- if (pp == NULL && got_transient)
- {
- /*
- ** There was no successful .forward open and at least one
- ** transient open. We have to defer this address for
- ** further delivery.
- */
-
- message("transient .forward open error: message queued");
- user->q_state = QS_QUEUEUP;
- return;
- }
-}
OpenPOWER on IntegriCloud