parseaddr.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:62k
- /*
- * Copyright (c) 1998, 1999 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.
- *
- */
- #ifndef lint
- static char id[] = "@(#)$Id: parseaddr.c,v 8.231 1999/12/06 21:48:51 ca Exp $";
- #endif /* ! lint */
- #include <sendmail.h>
- static void allocaddr __P((ADDRESS *, int, char *));
- static int callsubr __P((char**, int, ENVELOPE *));
- static char *map_lookup __P((STAB *, char *, char **, int *, ENVELOPE *));
- static ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *));
- /*
- ** PARSEADDR -- Parse an address
- **
- ** Parses an address and breaks it up into three parts: a
- ** net to transmit the message on, the host to transmit it
- ** to, and a user on that host. These are loaded into an
- ** ADDRESS header with the values squirreled away if necessary.
- ** The "user" part may not be a real user; the process may
- ** just reoccur on that machine. For example, on a machine
- ** with an arpanet connection, the address
- ** csvax.bill@berkeley
- ** will break up to a "user" of 'csvax.bill' and a host
- ** of 'berkeley' -- to be transmitted over the arpanet.
- **
- ** Parameters:
- ** addr -- the address to parse.
- ** a -- a pointer to the address descriptor buffer.
- ** If NULL, a header will be created.
- ** flags -- describe detail for parsing. See RF_ definitions
- ** in sendmail.h.
- ** delim -- the character to terminate the address, passed
- ** to prescan.
- ** delimptr -- if non-NULL, set to the location of the
- ** delim character that was found.
- ** e -- the envelope that will contain this address.
- **
- ** Returns:
- ** A pointer to the address descriptor header (`a' if
- ** `a' is non-NULL).
- ** NULL on error.
- **
- ** Side Effects:
- ** none
- */
- /* following delimiters are inherent to the internal algorithms */
- #define DELIMCHARS "()<>,;rn" /* default word delimiters */
- ADDRESS *
- parseaddr(addr, a, flags, delim, delimptr, e)
- char *addr;
- register ADDRESS *a;
- int flags;
- int delim;
- char **delimptr;
- register ENVELOPE *e;
- {
- register char **pvp;
- auto char *delimptrbuf;
- bool qup;
- char pvpbuf[PSBUFSIZE];
- /*
- ** Initialize and prescan address.
- */
- e->e_to = addr;
- if (tTd(20, 1))
- dprintf("n--parseaddr(%s)n", addr);
- if (delimptr == NULL)
- delimptr = &delimptrbuf;
- pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL);
- if (pvp == NULL)
- {
- if (tTd(20, 1))
- dprintf("parseaddr-->NULLn");
- return NULL;
- }
- if (invalidaddr(addr, delim == ' ' ? NULL : *delimptr))
- {
- if (tTd(20, 1))
- dprintf("parseaddr-->bad addressn");
- return NULL;
- }
- /*
- ** Save addr if we are going to have to.
- **
- ** We have to do this early because there is a chance that
- ** the map lookups in the rewriting rules could clobber
- ** static memory somewhere.
- */
- if (bitset(RF_COPYPADDR, flags) && addr != NULL)
- {
- char savec = **delimptr;
- if (savec != ' ')
- **delimptr = ' ';
- e->e_to = addr = newstr(addr);
- if (savec != ' ')
- **delimptr = savec;
- }
- /*
- ** Apply rewriting rules.
- ** Ruleset 0 does basic parsing. It must resolve.
- */
- qup = FALSE;
- if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
- qup = TRUE;
- if (rewrite(pvp, 0, 0, e) == EX_TEMPFAIL)
- qup = TRUE;
- /*
- ** Build canonical address from pvp.
- */
- a = buildaddr(pvp, a, flags, e);
- /*
- ** Make local copies of the host & user and then
- ** transport them out.
- */
- allocaddr(a, flags, addr);
- if (QS_IS_BADADDR(a->q_state))
- return a;
- /*
- ** If there was a parsing failure, mark it for queueing.
- */
- if (qup && OpMode != MD_INITALIAS)
- {
- char *msg = "Transient parse error -- message queued for future delivery";
- if (e->e_sendmode == SM_DEFER)
- msg = "Deferring message until queue run";
- if (tTd(20, 1))
- dprintf("parseaddr: queuing messagen");
- message(msg);
- if (e->e_message == NULL && e->e_sendmode != SM_DEFER)
- e->e_message = newstr(msg);
- a->q_state = QS_QUEUEUP;
- a->q_status = "4.4.3";
- }
- /*
- ** Compute return value.
- */
- if (tTd(20, 1))
- {
- dprintf("parseaddr-->");
- printaddr(a, FALSE);
- }
- return a;
- }
- /*
- ** INVALIDADDR -- check for address containing meta-characters
- **
- ** Parameters:
- ** addr -- the address to check.
- **
- ** Returns:
- ** TRUE -- if the address has any "wierd" characters
- ** FALSE -- otherwise.
- */
- bool
- invalidaddr(addr, delimptr)
- register char *addr;
- char *delimptr;
- {
- char savedelim = ' ';
- if (delimptr != NULL)
- {
- savedelim = *delimptr;
- if (savedelim != ' ')
- *delimptr = ' ';
- }
- if (strlen(addr) > MAXNAME - 1)
- {
- usrerr("553 5.1.1 Address too long (%d bytes max)",
- MAXNAME - 1);
- goto failure;
- }
- for (; *addr != ' '; addr++)
- {
- if ((*addr & 0340) == 0200)
- break;
- }
- if (*addr == ' ')
- {
- if (delimptr != NULL && savedelim != ' ')
- *delimptr = savedelim;
- return FALSE;
- }
- setstat(EX_USAGE);
- usrerr("553 5.1.1 Address contained invalid control characters");
- failure:
- if (delimptr != NULL && savedelim != ' ')
- *delimptr = savedelim;
- return TRUE;
- }
- /*
- ** ALLOCADDR -- do local allocations of address on demand.
- **
- ** Also lowercases the host name if requested.
- **
- ** Parameters:
- ** a -- the address to reallocate.
- ** flags -- the copy flag (see RF_ definitions in sendmail.h
- ** for a description).
- ** paddr -- the printname of the address.
- **
- ** Returns:
- ** none.
- **
- ** Side Effects:
- ** Copies portions of a into local buffers as requested.
- */
- static void
- allocaddr(a, flags, paddr)
- register ADDRESS *a;
- int flags;
- char *paddr;
- {
- if (tTd(24, 4))
- dprintf("allocaddr(flags=%x, paddr=%s)n", flags, paddr);
- a->q_paddr = paddr;
- if (a->q_user == NULL)
- a->q_user = newstr("");
- if (a->q_host == NULL)
- a->q_host = newstr("");
- if (bitset(RF_COPYPARSE, flags))
- {
- a->q_host = newstr(a->q_host);
- if (a->q_user != a->q_paddr)
- a->q_user = newstr(a->q_user);
- }
- if (a->q_paddr == NULL)
- a->q_paddr = newstr(a->q_user);
- }
- /*
- ** PRESCAN -- Prescan name and make it canonical
- **
- ** Scans a name and turns it into a set of tokens. This process
- ** deletes blanks and comments (in parentheses) (if the token type
- ** for left paren is SPC).
- **
- ** This routine knows about quoted strings and angle brackets.
- **
- ** There are certain subtleties to this routine. The one that
- ** comes to mind now is that backslashes on the ends of names
- ** are silently stripped off; this is intentional. The problem
- ** is that some versions of sndmsg (like at LBL) set the kill
- ** character to something other than @ when reading addresses;
- ** so people type "csvax.eric@berkeley" -- which screws up the
- ** berknet mailer.
- **
- ** Parameters:
- ** addr -- the name to chomp.
- ** delim -- the delimiter for the address, normally
- ** ' ' or ',';