1c2aa98e2SPeter Wemm /* 2602a2b1bSGregory Neil Shapiro * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. 306f25ae9SGregory Neil Shapiro * All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 7c2aa98e2SPeter Wemm * 8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 10c2aa98e2SPeter Wemm * the sendmail distribution. 11c2aa98e2SPeter Wemm * 12c2aa98e2SPeter Wemm */ 13c2aa98e2SPeter Wemm 1406f25ae9SGregory Neil Shapiro #include <sendmail.h> 1506f25ae9SGregory Neil Shapiro 1640266059SGregory Neil Shapiro SM_RCSID("@(#)$Id: parseaddr.c,v 8.349 2001/12/12 02:50:22 gshapiro Exp $") 1740266059SGregory Neil Shapiro 1840266059SGregory Neil Shapiro static void allocaddr __P((ADDRESS *, int, char *, ENVELOPE *)); 1906f25ae9SGregory Neil Shapiro static int callsubr __P((char**, int, ENVELOPE *)); 2006f25ae9SGregory Neil Shapiro static char *map_lookup __P((STAB *, char *, char **, int *, ENVELOPE *)); 2106f25ae9SGregory Neil Shapiro static ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *)); 2240266059SGregory Neil Shapiro static bool hasctrlchar __P((register char *, bool)); 23c2aa98e2SPeter Wemm 24c2aa98e2SPeter Wemm /* 25c2aa98e2SPeter Wemm ** PARSEADDR -- Parse an address 26c2aa98e2SPeter Wemm ** 27c2aa98e2SPeter Wemm ** Parses an address and breaks it up into three parts: a 28c2aa98e2SPeter Wemm ** net to transmit the message on, the host to transmit it 29c2aa98e2SPeter Wemm ** to, and a user on that host. These are loaded into an 30c2aa98e2SPeter Wemm ** ADDRESS header with the values squirreled away if necessary. 31c2aa98e2SPeter Wemm ** The "user" part may not be a real user; the process may 32c2aa98e2SPeter Wemm ** just reoccur on that machine. For example, on a machine 33c2aa98e2SPeter Wemm ** with an arpanet connection, the address 34c2aa98e2SPeter Wemm ** csvax.bill@berkeley 35c2aa98e2SPeter Wemm ** will break up to a "user" of 'csvax.bill' and a host 36c2aa98e2SPeter Wemm ** of 'berkeley' -- to be transmitted over the arpanet. 37c2aa98e2SPeter Wemm ** 38c2aa98e2SPeter Wemm ** Parameters: 39c2aa98e2SPeter Wemm ** addr -- the address to parse. 40c2aa98e2SPeter Wemm ** a -- a pointer to the address descriptor buffer. 4140266059SGregory Neil Shapiro ** If NULL, an address will be created. 42c2aa98e2SPeter Wemm ** flags -- describe detail for parsing. See RF_ definitions 43c2aa98e2SPeter Wemm ** in sendmail.h. 44c2aa98e2SPeter Wemm ** delim -- the character to terminate the address, passed 45c2aa98e2SPeter Wemm ** to prescan. 46c2aa98e2SPeter Wemm ** delimptr -- if non-NULL, set to the location of the 47c2aa98e2SPeter Wemm ** delim character that was found. 48c2aa98e2SPeter Wemm ** e -- the envelope that will contain this address. 4940266059SGregory Neil Shapiro ** isrcpt -- true if the address denotes a recipient; false 5040266059SGregory Neil Shapiro ** indicates a sender. 51c2aa98e2SPeter Wemm ** 52c2aa98e2SPeter Wemm ** Returns: 53c2aa98e2SPeter Wemm ** A pointer to the address descriptor header (`a' if 54c2aa98e2SPeter Wemm ** `a' is non-NULL). 55c2aa98e2SPeter Wemm ** NULL on error. 56c2aa98e2SPeter Wemm ** 57c2aa98e2SPeter Wemm ** Side Effects: 5840266059SGregory Neil Shapiro ** e->e_to = addr 59c2aa98e2SPeter Wemm */ 60c2aa98e2SPeter Wemm 61c2aa98e2SPeter Wemm /* following delimiters are inherent to the internal algorithms */ 62c2aa98e2SPeter Wemm #define DELIMCHARS "()<>,;\r\n" /* default word delimiters */ 63c2aa98e2SPeter Wemm 64c2aa98e2SPeter Wemm ADDRESS * 6540266059SGregory Neil Shapiro parseaddr(addr, a, flags, delim, delimptr, e, isrcpt) 66c2aa98e2SPeter Wemm char *addr; 67c2aa98e2SPeter Wemm register ADDRESS *a; 68c2aa98e2SPeter Wemm int flags; 69c2aa98e2SPeter Wemm int delim; 70c2aa98e2SPeter Wemm char **delimptr; 71c2aa98e2SPeter Wemm register ENVELOPE *e; 7240266059SGregory Neil Shapiro bool isrcpt; 73c2aa98e2SPeter Wemm { 7440266059SGregory Neil Shapiro char **pvp; 75c2aa98e2SPeter Wemm auto char *delimptrbuf; 7606f25ae9SGregory Neil Shapiro bool qup; 77c2aa98e2SPeter Wemm char pvpbuf[PSBUFSIZE]; 78c2aa98e2SPeter Wemm 79c2aa98e2SPeter Wemm /* 80c2aa98e2SPeter Wemm ** Initialize and prescan address. 81c2aa98e2SPeter Wemm */ 82c2aa98e2SPeter Wemm 83c2aa98e2SPeter Wemm e->e_to = addr; 84c2aa98e2SPeter Wemm if (tTd(20, 1)) 8540266059SGregory Neil Shapiro sm_dprintf("\n--parseaddr(%s)\n", addr); 86c2aa98e2SPeter Wemm 87c2aa98e2SPeter Wemm if (delimptr == NULL) 88c2aa98e2SPeter Wemm delimptr = &delimptrbuf; 89c2aa98e2SPeter Wemm 90c2aa98e2SPeter Wemm pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL); 91c2aa98e2SPeter Wemm if (pvp == NULL) 92c2aa98e2SPeter Wemm { 93c2aa98e2SPeter Wemm if (tTd(20, 1)) 9440266059SGregory Neil Shapiro sm_dprintf("parseaddr-->NULL\n"); 9506f25ae9SGregory Neil Shapiro return NULL; 96c2aa98e2SPeter Wemm } 97c2aa98e2SPeter Wemm 9840266059SGregory Neil Shapiro if (invalidaddr(addr, delim == '\0' ? NULL : *delimptr, isrcpt)) 99c2aa98e2SPeter Wemm { 100c2aa98e2SPeter Wemm if (tTd(20, 1)) 10140266059SGregory Neil Shapiro sm_dprintf("parseaddr-->bad address\n"); 102c2aa98e2SPeter Wemm return NULL; 103c2aa98e2SPeter Wemm } 104c2aa98e2SPeter Wemm 105c2aa98e2SPeter Wemm /* 106c2aa98e2SPeter Wemm ** Save addr if we are going to have to. 107c2aa98e2SPeter Wemm ** 108c2aa98e2SPeter Wemm ** We have to do this early because there is a chance that 109c2aa98e2SPeter Wemm ** the map lookups in the rewriting rules could clobber 110c2aa98e2SPeter Wemm ** static memory somewhere. 111c2aa98e2SPeter Wemm */ 112c2aa98e2SPeter Wemm 113c2aa98e2SPeter Wemm if (bitset(RF_COPYPADDR, flags) && addr != NULL) 114c2aa98e2SPeter Wemm { 115c2aa98e2SPeter Wemm char savec = **delimptr; 116c2aa98e2SPeter Wemm 117c2aa98e2SPeter Wemm if (savec != '\0') 118c2aa98e2SPeter Wemm **delimptr = '\0'; 11940266059SGregory Neil Shapiro e->e_to = addr = sm_rpool_strdup_x(e->e_rpool, addr); 120c2aa98e2SPeter Wemm if (savec != '\0') 121c2aa98e2SPeter Wemm **delimptr = savec; 122c2aa98e2SPeter Wemm } 123c2aa98e2SPeter Wemm 124c2aa98e2SPeter Wemm /* 125c2aa98e2SPeter Wemm ** Apply rewriting rules. 126c2aa98e2SPeter Wemm ** Ruleset 0 does basic parsing. It must resolve. 127c2aa98e2SPeter Wemm */ 128c2aa98e2SPeter Wemm 12940266059SGregory Neil Shapiro qup = false; 13040266059SGregory Neil Shapiro if (REWRITE(pvp, 3, e) == EX_TEMPFAIL) 13140266059SGregory Neil Shapiro qup = true; 13240266059SGregory Neil Shapiro if (REWRITE(pvp, 0, e) == EX_TEMPFAIL) 13340266059SGregory Neil Shapiro qup = true; 134c2aa98e2SPeter Wemm 135c2aa98e2SPeter Wemm /* 136c2aa98e2SPeter Wemm ** Build canonical address from pvp. 137c2aa98e2SPeter Wemm */ 138c2aa98e2SPeter Wemm 139c2aa98e2SPeter Wemm a = buildaddr(pvp, a, flags, e); 140c2aa98e2SPeter Wemm 14140266059SGregory Neil Shapiro if (hasctrlchar(a->q_user, isrcpt)) 14240266059SGregory Neil Shapiro { 14340266059SGregory Neil Shapiro if (tTd(20, 1)) 14440266059SGregory Neil Shapiro sm_dprintf("parseaddr-->bad q_user\n"); 14540266059SGregory Neil Shapiro return NULL; 14640266059SGregory Neil Shapiro } 14740266059SGregory Neil Shapiro 148c2aa98e2SPeter Wemm /* 149c2aa98e2SPeter Wemm ** Make local copies of the host & user and then 150c2aa98e2SPeter Wemm ** transport them out. 151c2aa98e2SPeter Wemm */ 152c2aa98e2SPeter Wemm 15340266059SGregory Neil Shapiro allocaddr(a, flags, addr, e); 15406f25ae9SGregory Neil Shapiro if (QS_IS_BADADDR(a->q_state)) 155c2aa98e2SPeter Wemm return a; 156c2aa98e2SPeter Wemm 157c2aa98e2SPeter Wemm /* 15840266059SGregory Neil Shapiro ** Select a queue directory for recipient addresses. 15940266059SGregory Neil Shapiro ** This is done here and in split_across_queue_groups(), 16040266059SGregory Neil Shapiro ** but the latter applies to addresses after aliasing, 16140266059SGregory Neil Shapiro ** and only if splitting is done. 16240266059SGregory Neil Shapiro */ 16340266059SGregory Neil Shapiro 16440266059SGregory Neil Shapiro if ((a->q_qgrp == NOAQGRP || a->q_qgrp == ENVQGRP) && 16540266059SGregory Neil Shapiro !bitset(RF_SENDERADDR|RF_HEADERADDR, flags) && 16640266059SGregory Neil Shapiro OpMode != MD_INITALIAS) 16740266059SGregory Neil Shapiro { 16840266059SGregory Neil Shapiro int r; 16940266059SGregory Neil Shapiro 17040266059SGregory Neil Shapiro /* call ruleset which should return a queue group name */ 17140266059SGregory Neil Shapiro r = rscap(RS_QUEUEGROUP, a->q_user, NULL, e, &pvp, pvpbuf, 17240266059SGregory Neil Shapiro sizeof(pvpbuf)); 17340266059SGregory Neil Shapiro if (r == EX_OK && 17440266059SGregory Neil Shapiro pvp != NULL && pvp[0] != NULL && 17540266059SGregory Neil Shapiro (pvp[0][0] & 0377) == CANONNET && 17640266059SGregory Neil Shapiro pvp[1] != NULL && pvp[1][0] != '\0') 17740266059SGregory Neil Shapiro { 17840266059SGregory Neil Shapiro r = name2qid(pvp[1]); 17940266059SGregory Neil Shapiro if (r == NOQGRP && LogLevel > 10) 18040266059SGregory Neil Shapiro sm_syslog(LOG_INFO, NOQID, 18140266059SGregory Neil Shapiro "can't find queue group name %s, selection ignored", 18240266059SGregory Neil Shapiro pvp[1]); 18340266059SGregory Neil Shapiro if (tTd(20, 4) && r != NOQGRP) 18440266059SGregory Neil Shapiro sm_syslog(LOG_INFO, NOQID, 18540266059SGregory Neil Shapiro "queue group name %s -> %d", 18640266059SGregory Neil Shapiro pvp[1], r); 18740266059SGregory Neil Shapiro a->q_qgrp = r == NOQGRP ? ENVQGRP : r; 18840266059SGregory Neil Shapiro } 18940266059SGregory Neil Shapiro } 19040266059SGregory Neil Shapiro 19140266059SGregory Neil Shapiro /* 192c2aa98e2SPeter Wemm ** If there was a parsing failure, mark it for queueing. 193c2aa98e2SPeter Wemm */ 194c2aa98e2SPeter Wemm 19506f25ae9SGregory Neil Shapiro if (qup && OpMode != MD_INITALIAS) 196c2aa98e2SPeter Wemm { 197c2aa98e2SPeter Wemm char *msg = "Transient parse error -- message queued for future delivery"; 198c2aa98e2SPeter Wemm 199c2aa98e2SPeter Wemm if (e->e_sendmode == SM_DEFER) 200c2aa98e2SPeter Wemm msg = "Deferring message until queue run"; 201c2aa98e2SPeter Wemm if (tTd(20, 1)) 20240266059SGregory Neil Shapiro sm_dprintf("parseaddr: queuing message\n"); 203c2aa98e2SPeter Wemm message(msg); 204c2aa98e2SPeter Wemm if (e->e_message == NULL && e->e_sendmode != SM_DEFER) 20540266059SGregory Neil Shapiro e->e_message = sm_rpool_strdup_x(e->e_rpool, msg); 20606f25ae9SGregory Neil Shapiro a->q_state = QS_QUEUEUP; 207c2aa98e2SPeter Wemm a->q_status = "4.4.3"; 208c2aa98e2SPeter Wemm } 209c2aa98e2SPeter Wemm 210c2aa98e2SPeter Wemm /* 211c2aa98e2SPeter Wemm ** Compute return value. 212c2aa98e2SPeter Wemm */ 213c2aa98e2SPeter Wemm 214c2aa98e2SPeter Wemm if (tTd(20, 1)) 215c2aa98e2SPeter Wemm { 21640266059SGregory Neil Shapiro sm_dprintf("parseaddr-->"); 21740266059SGregory Neil Shapiro printaddr(a, false); 218c2aa98e2SPeter Wemm } 219c2aa98e2SPeter Wemm 22006f25ae9SGregory Neil Shapiro return a; 221c2aa98e2SPeter Wemm } 22240266059SGregory Neil Shapiro /* 22340266059SGregory Neil Shapiro ** INVALIDADDR -- check for address containing characters used for macros 224c2aa98e2SPeter Wemm ** 225c2aa98e2SPeter Wemm ** Parameters: 226c2aa98e2SPeter Wemm ** addr -- the address to check. 22740266059SGregory Neil Shapiro ** delimptr -- if non-NULL: end of address to check, i.e., 22840266059SGregory Neil Shapiro ** a pointer in the address string. 22940266059SGregory Neil Shapiro ** isrcpt -- true iff the address is for a recipient. 230c2aa98e2SPeter Wemm ** 231c2aa98e2SPeter Wemm ** Returns: 23240266059SGregory Neil Shapiro ** true -- if the address has characters that are reservered 23340266059SGregory Neil Shapiro ** for macros or is too long. 23440266059SGregory Neil Shapiro ** false -- otherwise. 235c2aa98e2SPeter Wemm */ 236c2aa98e2SPeter Wemm 237c2aa98e2SPeter Wemm bool 23840266059SGregory Neil Shapiro invalidaddr(addr, delimptr, isrcpt) 239c2aa98e2SPeter Wemm register char *addr; 240c2aa98e2SPeter Wemm char *delimptr; 24140266059SGregory Neil Shapiro bool isrcpt; 242c2aa98e2SPeter Wemm { 24340266059SGregory Neil Shapiro bool result = false; 244c2aa98e2SPeter Wemm char savedelim = '\0'; 24540266059SGregory Neil Shapiro int len = 0; 246c2aa98e2SPeter Wemm 247c2aa98e2SPeter Wemm if (delimptr != NULL) 248c2aa98e2SPeter Wemm { 24940266059SGregory Neil Shapiro /* delimptr points to the end of the address to test */ 250c2aa98e2SPeter Wemm savedelim = *delimptr; 25140266059SGregory Neil Shapiro if (savedelim != '\0') /* if that isn't '\0' already: */ 25240266059SGregory Neil Shapiro *delimptr = '\0'; /* set it */ 253c2aa98e2SPeter Wemm } 254c2aa98e2SPeter Wemm for (; *addr != '\0'; addr++) 255c2aa98e2SPeter Wemm { 256c2aa98e2SPeter Wemm if ((*addr & 0340) == 0200) 25740266059SGregory Neil Shapiro { 25840266059SGregory Neil Shapiro setstat(EX_USAGE); 25940266059SGregory Neil Shapiro result = true; 260c2aa98e2SPeter Wemm break; 261c2aa98e2SPeter Wemm } 26240266059SGregory Neil Shapiro if (++len > MAXNAME - 1) 263c2aa98e2SPeter Wemm { 26440266059SGregory Neil Shapiro usrerr("553 5.1.0 Address too long (%d bytes max)", 26540266059SGregory Neil Shapiro MAXNAME - 1); 26640266059SGregory Neil Shapiro result = true; 26740266059SGregory Neil Shapiro goto delim; 268c2aa98e2SPeter Wemm } 26940266059SGregory Neil Shapiro } 27040266059SGregory Neil Shapiro if (result) 27140266059SGregory Neil Shapiro { 27240266059SGregory Neil Shapiro if (isrcpt) 27340266059SGregory Neil Shapiro usrerr("501 5.1.3 Syntax error in mailbox address"); 27440266059SGregory Neil Shapiro else 27540266059SGregory Neil Shapiro usrerr("501 5.1.7 Syntax error in mailbox address"); 27640266059SGregory Neil Shapiro } 27740266059SGregory Neil Shapiro delim: 27840266059SGregory Neil Shapiro if (delimptr != NULL && savedelim != '\0') 27940266059SGregory Neil Shapiro *delimptr = savedelim; /* restore old character at delimptr */ 28040266059SGregory Neil Shapiro return result; 28140266059SGregory Neil Shapiro } 28240266059SGregory Neil Shapiro /* 28340266059SGregory Neil Shapiro ** HASCTRLCHAR -- check for address containing meta-characters 28440266059SGregory Neil Shapiro ** 28540266059SGregory Neil Shapiro ** Checks that the address contains no meta-characters, and contains 28640266059SGregory Neil Shapiro ** no "non-printable" characters unless they are quoted or escaped. 28740266059SGregory Neil Shapiro ** Quoted or escaped characters are literals. 28840266059SGregory Neil Shapiro ** 28940266059SGregory Neil Shapiro ** Parameters: 29040266059SGregory Neil Shapiro ** addr -- the address to check. 29140266059SGregory Neil Shapiro ** isrcpt -- true if the address is for a recipient; false 29240266059SGregory Neil Shapiro ** indicates a from. 29340266059SGregory Neil Shapiro ** 29440266059SGregory Neil Shapiro ** Returns: 29540266059SGregory Neil Shapiro ** true -- if the address has any "wierd" characters or 29640266059SGregory Neil Shapiro ** non-printable characters or if a quote is unbalanced. 29740266059SGregory Neil Shapiro ** false -- otherwise. 29840266059SGregory Neil Shapiro */ 29940266059SGregory Neil Shapiro 30040266059SGregory Neil Shapiro static bool 30140266059SGregory Neil Shapiro hasctrlchar(addr, isrcpt) 30240266059SGregory Neil Shapiro register char *addr; 30340266059SGregory Neil Shapiro bool isrcpt; 30440266059SGregory Neil Shapiro { 30540266059SGregory Neil Shapiro bool result = false; 30640266059SGregory Neil Shapiro int len = 0; 30740266059SGregory Neil Shapiro bool quoted = false; 30840266059SGregory Neil Shapiro 30940266059SGregory Neil Shapiro if (addr == NULL) 31040266059SGregory Neil Shapiro return false; 31140266059SGregory Neil Shapiro for (; *addr != '\0'; addr++) 31240266059SGregory Neil Shapiro { 31340266059SGregory Neil Shapiro if (!quoted && (*addr < 32 || *addr == 127)) 31440266059SGregory Neil Shapiro { 31540266059SGregory Neil Shapiro result = true; /* a non-printable */ 31640266059SGregory Neil Shapiro break; 31740266059SGregory Neil Shapiro } 31840266059SGregory Neil Shapiro if (*addr == '"') 31940266059SGregory Neil Shapiro quoted = !quoted; 32040266059SGregory Neil Shapiro else if (*addr == '\\') 32140266059SGregory Neil Shapiro { 32240266059SGregory Neil Shapiro /* XXX Generic problem: no '\0' in strings. */ 32340266059SGregory Neil Shapiro if (*++addr == '\0') 32440266059SGregory Neil Shapiro { 32540266059SGregory Neil Shapiro result = true; 32640266059SGregory Neil Shapiro break; 32740266059SGregory Neil Shapiro } 32840266059SGregory Neil Shapiro } 32940266059SGregory Neil Shapiro if ((*addr & 0340) == 0200) 33040266059SGregory Neil Shapiro { 331c2aa98e2SPeter Wemm setstat(EX_USAGE); 33240266059SGregory Neil Shapiro result = true; 33340266059SGregory Neil Shapiro break; 334c2aa98e2SPeter Wemm } 33540266059SGregory Neil Shapiro if (++len > MAXNAME - 1) 33640266059SGregory Neil Shapiro { 33740266059SGregory Neil Shapiro usrerr("553 5.1.0 Address too long (%d bytes max)", 33840266059SGregory Neil Shapiro MAXNAME - 1); 33940266059SGregory Neil Shapiro return true; 34040266059SGregory Neil Shapiro } 34140266059SGregory Neil Shapiro } 34240266059SGregory Neil Shapiro if (quoted) 34340266059SGregory Neil Shapiro result = true; /* unbalanced quote */ 34440266059SGregory Neil Shapiro if (result) 34540266059SGregory Neil Shapiro { 34640266059SGregory Neil Shapiro if (isrcpt) 34740266059SGregory Neil Shapiro usrerr("501 5.1.3 Syntax error in mailbox address"); 34840266059SGregory Neil Shapiro else 34940266059SGregory Neil Shapiro usrerr("501 5.1.7 Syntax error in mailbox address"); 35040266059SGregory Neil Shapiro } 35140266059SGregory Neil Shapiro return result; 35240266059SGregory Neil Shapiro } 35340266059SGregory Neil Shapiro /* 354c2aa98e2SPeter Wemm ** ALLOCADDR -- do local allocations of address on demand. 355c2aa98e2SPeter Wemm ** 356c2aa98e2SPeter Wemm ** Also lowercases the host name if requested. 357c2aa98e2SPeter Wemm ** 358c2aa98e2SPeter Wemm ** Parameters: 359c2aa98e2SPeter Wemm ** a -- the address to reallocate. 360c2aa98e2SPeter Wemm ** flags -- the copy flag (see RF_ definitions in sendmail.h 361c2aa98e2SPeter Wemm ** for a description). 362c2aa98e2SPeter Wemm ** paddr -- the printname of the address. 36340266059SGregory Neil Shapiro ** e -- envelope 364c2aa98e2SPeter Wemm ** 365c2aa98e2SPeter Wemm ** Returns: 366c2aa98e2SPeter Wemm ** none. 367c2aa98e2SPeter Wemm ** 368c2aa98e2SPeter Wemm ** Side Effects: 369c2aa98e2SPeter Wemm ** Copies portions of a into local buffers as requested. 370c2aa98e2SPeter Wemm */ 371c2aa98e2SPeter Wemm 37206f25ae9SGregory Neil Shapiro static void 37340266059SGregory Neil Shapiro allocaddr(a, flags, paddr, e) 374c2aa98e2SPeter Wemm register ADDRESS *a; 375c2aa98e2SPeter Wemm int flags; 376c2aa98e2SPeter Wemm char *paddr; 37740266059SGregory Neil Shapiro ENVELOPE *e; 378c2aa98e2SPeter Wemm { 379c2aa98e2SPeter Wemm if (tTd(24, 4)) 38040266059SGregory Neil Shapiro sm_dprintf("allocaddr(flags=%x, paddr=%s)\n", flags, paddr); 381c2aa98e2SPeter Wemm 382c2aa98e2SPeter Wemm a->q_paddr = paddr; 383c2aa98e2SPeter Wemm 384c2aa98e2SPeter Wemm if (a->q_user == NULL) 38540266059SGregory Neil Shapiro a->q_user = ""; 386c2aa98e2SPeter Wemm if (a->q_host == NULL) 38740266059SGregory Neil Shapiro a->q_host = ""; 388c2aa98e2SPeter Wemm 389c2aa98e2SPeter Wemm if (bitset(RF_COPYPARSE, flags)) 390c2aa98e2SPeter Wemm { 39140266059SGregory Neil Shapiro a->q_host = sm_rpool_strdup_x(e->e_rpool, a->q_host); 392c2aa98e2SPeter Wemm if (a->q_user != a->q_paddr) 39340266059SGregory Neil Shapiro a->q_user = sm_rpool_strdup_x(e->e_rpool, a->q_user); 394c2aa98e2SPeter Wemm } 395c2aa98e2SPeter Wemm 396c2aa98e2SPeter Wemm if (a->q_paddr == NULL) 39740266059SGregory Neil Shapiro a->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_user); 39840266059SGregory Neil Shapiro a->q_qgrp = NOAQGRP; 399c2aa98e2SPeter Wemm } 40040266059SGregory Neil Shapiro /* 401c2aa98e2SPeter Wemm ** PRESCAN -- Prescan name and make it canonical 402c2aa98e2SPeter Wemm ** 403c2aa98e2SPeter Wemm ** Scans a name and turns it into a set of tokens. This process 40406f25ae9SGregory Neil Shapiro ** deletes blanks and comments (in parentheses) (if the token type 40506f25ae9SGregory Neil Shapiro ** for left paren is SPC). 406c2aa98e2SPeter Wemm ** 407c2aa98e2SPeter Wemm ** This routine knows about quoted strings and angle brackets. 408c2aa98e2SPeter Wemm ** 409c2aa98e2SPeter Wemm ** There are certain subtleties to this routine. The one that 410c2aa98e2SPeter Wemm ** comes to mind now is that backslashes on the ends of names 411c2aa98e2SPeter Wemm ** are silently stripped off; this is intentional. The problem 412c2aa98e2SPeter Wemm ** is that some versions of sndmsg (like at LBL) set the kill 413c2aa98e2SPeter Wemm ** character to something other than @ when reading addresses; 414c2aa98e2SPeter Wemm ** so people type "csvax.eric\@berkeley" -- which screws up the 415c2aa98e2SPeter Wemm ** berknet mailer. 416c2aa98e2SPeter Wemm ** 417c2aa98e2SPeter Wemm ** Parameters: 418c2aa98e2SPeter Wemm ** addr -- the name to chomp. 419c2aa98e2SPeter Wemm ** delim -- the delimiter for the address, normally 420c2aa98e2SPeter Wemm ** '\0' or ','; \0 is accepted in any case. 421c2aa98e2SPeter Wemm ** If '\t' then we are reading the .cf file. 422c2aa98e2SPeter Wemm ** pvpbuf -- place to put the saved text -- note that 423c2aa98e2SPeter Wemm ** the pointers are static. 424c2aa98e2SPeter Wemm ** pvpbsize -- size of pvpbuf. 425c2aa98e2SPeter Wemm ** delimptr -- if non-NULL, set to the location of the 426c2aa98e2SPeter Wemm ** terminating delimiter. 427c2aa98e2SPeter Wemm ** toktab -- if set, a token table to use for parsing. 428c2aa98e2SPeter Wemm ** If NULL, use the default table. 429c2aa98e2SPeter Wemm ** 430c2aa98e2SPeter Wemm ** Returns: 431c2aa98e2SPeter Wemm ** A pointer to a vector of tokens. 432c2aa98e2SPeter Wemm ** NULL on error. 433c2aa98e2SPeter Wemm */ 434c2aa98e2SPeter Wemm 435c2aa98e2SPeter Wemm /* states and character types */ 436c2aa98e2SPeter Wemm #define OPR 0 /* operator */ 437c2aa98e2SPeter Wemm #define ATM 1 /* atom */ 438c2aa98e2SPeter Wemm #define QST 2 /* in quoted string */ 439c2aa98e2SPeter Wemm #define SPC 3 /* chewing up spaces */ 440c2aa98e2SPeter Wemm #define ONE 4 /* pick up one character */ 441c2aa98e2SPeter Wemm #define ILL 5 /* illegal character */ 442c2aa98e2SPeter Wemm 443c2aa98e2SPeter Wemm #define NSTATES 6 /* number of states */ 444c2aa98e2SPeter Wemm #define TYPE 017 /* mask to select state type */ 445c2aa98e2SPeter Wemm 446c2aa98e2SPeter Wemm /* meta bits for table */ 447c2aa98e2SPeter Wemm #define M 020 /* meta character; don't pass through */ 448c2aa98e2SPeter Wemm #define B 040 /* cause a break */ 449c2aa98e2SPeter Wemm #define MB M|B /* meta-break */ 450c2aa98e2SPeter Wemm 451c2aa98e2SPeter Wemm static short StateTab[NSTATES][NSTATES] = 452c2aa98e2SPeter Wemm { 453c2aa98e2SPeter Wemm /* oldst chtype> OPR ATM QST SPC ONE ILL */ 454c2aa98e2SPeter Wemm /*OPR*/ { OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|MB }, 455c2aa98e2SPeter Wemm /*ATM*/ { OPR|B, ATM, QST|B, SPC|MB, ONE|B, ILL|MB }, 456c2aa98e2SPeter Wemm /*QST*/ { QST, QST, OPR, QST, QST, QST }, 457c2aa98e2SPeter Wemm /*SPC*/ { OPR, ATM, QST, SPC|M, ONE, ILL|MB }, 458c2aa98e2SPeter Wemm /*ONE*/ { OPR, OPR, OPR, OPR, OPR, ILL|MB }, 459c2aa98e2SPeter Wemm /*ILL*/ { OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|M }, 460c2aa98e2SPeter Wemm }; 461c2aa98e2SPeter Wemm 462c2aa98e2SPeter Wemm /* token type table -- it gets modified with $o characters */ 46340266059SGregory Neil Shapiro static unsigned char TokTypeTab[256] = 464c2aa98e2SPeter Wemm { 465c2aa98e2SPeter Wemm /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 466c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM, 467c2aa98e2SPeter Wemm /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 468c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 469c2aa98e2SPeter Wemm /* sp ! " # $ % & ' ( ) * + , - . / */ 47006f25ae9SGregory Neil Shapiro SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, SPC,SPC,ATM,ATM,ATM,ATM,ATM,ATM, 471c2aa98e2SPeter Wemm /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 472c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 473c2aa98e2SPeter Wemm /* @ A B C D E F G H I J K L M N O */ 474c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 475c2aa98e2SPeter Wemm /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 476c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 477c2aa98e2SPeter Wemm /* ` a b c d e f g h i j k l m n o */ 478c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 479c2aa98e2SPeter Wemm /* p q r s t u v w x y z { | } ~ del */ 480c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 481c2aa98e2SPeter Wemm 482c2aa98e2SPeter Wemm /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 483c2aa98e2SPeter Wemm OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR, 484c2aa98e2SPeter Wemm /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 485c2aa98e2SPeter Wemm OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR, 486c2aa98e2SPeter Wemm /* sp ! " # $ % & ' ( ) * + , - . / */ 487c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 488c2aa98e2SPeter Wemm /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 489c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 490c2aa98e2SPeter Wemm /* @ A B C D E F G H I J K L M N O */ 491c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 492c2aa98e2SPeter Wemm /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 493c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 494c2aa98e2SPeter Wemm /* ` a b c d e f g h i j k l m n o */ 495c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 496c2aa98e2SPeter Wemm /* p q r s t u v w x y z { | } ~ del */ 497c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 498c2aa98e2SPeter Wemm }; 499c2aa98e2SPeter Wemm 500c2aa98e2SPeter Wemm /* token type table for MIME parsing */ 50140266059SGregory Neil Shapiro unsigned char MimeTokenTab[256] = 502c2aa98e2SPeter Wemm { 503c2aa98e2SPeter Wemm /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 504c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,SPC,SPC,SPC,SPC,SPC,ILL,ILL, 505c2aa98e2SPeter Wemm /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 506c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 507c2aa98e2SPeter Wemm /* sp ! " # $ % & ' ( ) * + , - . / */ 50806f25ae9SGregory Neil Shapiro SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, SPC,SPC,ATM,ATM,OPR,ATM,ATM,OPR, 509c2aa98e2SPeter Wemm /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 510c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,OPR,OPR,OPR,OPR,OPR,OPR, 511c2aa98e2SPeter Wemm /* @ A B C D E F G H I J K L M N O */ 512c2aa98e2SPeter Wemm OPR,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 513c2aa98e2SPeter Wemm /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 514c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,OPR,OPR,OPR,ATM,ATM, 515c2aa98e2SPeter Wemm /* ` a b c d e f g h i j k l m n o */ 516c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 517c2aa98e2SPeter Wemm /* p q r s t u v w x y z { | } ~ del */ 518c2aa98e2SPeter Wemm ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 519c2aa98e2SPeter Wemm 520c2aa98e2SPeter Wemm /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 521c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 522c2aa98e2SPeter Wemm /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 523c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 524c2aa98e2SPeter Wemm /* sp ! " # $ % & ' ( ) * + , - . / */ 525c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 526c2aa98e2SPeter Wemm /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 527c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 528c2aa98e2SPeter Wemm /* @ A B C D E F G H I J K L M N O */ 529c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 530c2aa98e2SPeter Wemm /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 531c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 532c2aa98e2SPeter Wemm /* ` a b c d e f g h i j k l m n o */ 533c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 534c2aa98e2SPeter Wemm /* p q r s t u v w x y z { | } ~ del */ 535c2aa98e2SPeter Wemm ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, 536c2aa98e2SPeter Wemm }; 537c2aa98e2SPeter Wemm 53806f25ae9SGregory Neil Shapiro /* token type table: don't strip comments */ 53940266059SGregory Neil Shapiro unsigned char TokTypeNoC[256] = 54006f25ae9SGregory Neil Shapiro { 54106f25ae9SGregory Neil Shapiro /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 54206f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM, 54306f25ae9SGregory Neil Shapiro /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 54406f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 54506f25ae9SGregory Neil Shapiro /* sp ! " # $ % & ' ( ) * + , - . / */ 54606f25ae9SGregory Neil Shapiro SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, OPR,OPR,ATM,ATM,ATM,ATM,ATM,ATM, 54706f25ae9SGregory Neil Shapiro /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 54806f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 54906f25ae9SGregory Neil Shapiro /* @ A B C D E F G H I J K L M N O */ 55006f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 55106f25ae9SGregory Neil Shapiro /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 55206f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 55306f25ae9SGregory Neil Shapiro /* ` a b c d e f g h i j k l m n o */ 55406f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 55506f25ae9SGregory Neil Shapiro /* p q r s t u v w x y z { | } ~ del */ 55606f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 55706f25ae9SGregory Neil Shapiro 55806f25ae9SGregory Neil Shapiro /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 55906f25ae9SGregory Neil Shapiro OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR, 56006f25ae9SGregory Neil Shapiro /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 56106f25ae9SGregory Neil Shapiro OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR, 56206f25ae9SGregory Neil Shapiro /* sp ! " # $ % & ' ( ) * + , - . / */ 56306f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 56406f25ae9SGregory Neil Shapiro /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 56506f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 56606f25ae9SGregory Neil Shapiro /* @ A B C D E F G H I J K L M N O */ 56706f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 56806f25ae9SGregory Neil Shapiro /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 56906f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 57006f25ae9SGregory Neil Shapiro /* ` a b c d e f g h i j k l m n o */ 57106f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 57206f25ae9SGregory Neil Shapiro /* p q r s t u v w x y z { | } ~ del */ 57306f25ae9SGregory Neil Shapiro ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, 57406f25ae9SGregory Neil Shapiro }; 57506f25ae9SGregory Neil Shapiro 576c2aa98e2SPeter Wemm 577c2aa98e2SPeter Wemm #define NOCHAR -1 /* signal nothing in lookahead token */ 578c2aa98e2SPeter Wemm 579c2aa98e2SPeter Wemm char ** 580c2aa98e2SPeter Wemm prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab) 581c2aa98e2SPeter Wemm char *addr; 582c2aa98e2SPeter Wemm int delim; 583c2aa98e2SPeter Wemm char pvpbuf[]; 584c2aa98e2SPeter Wemm int pvpbsize; 585c2aa98e2SPeter Wemm char **delimptr; 58640266059SGregory Neil Shapiro unsigned char *toktab; 587c2aa98e2SPeter Wemm { 588c2aa98e2SPeter Wemm register char *p; 589c2aa98e2SPeter Wemm register char *q; 590c2aa98e2SPeter Wemm register int c; 591c2aa98e2SPeter Wemm char **avp; 592c2aa98e2SPeter Wemm bool bslashmode; 593c2aa98e2SPeter Wemm bool route_syntax; 594c2aa98e2SPeter Wemm int cmntcnt; 595c2aa98e2SPeter Wemm int anglecnt; 596c2aa98e2SPeter Wemm char *tok; 597c2aa98e2SPeter Wemm int state; 598c2aa98e2SPeter Wemm int newstate; 599c2aa98e2SPeter Wemm char *saveto = CurEnv->e_to; 600c2aa98e2SPeter Wemm static char *av[MAXATOM + 1]; 60140266059SGregory Neil Shapiro static bool firsttime = true; 602c2aa98e2SPeter Wemm extern int errno; 603c2aa98e2SPeter Wemm 604c2aa98e2SPeter Wemm if (firsttime) 605c2aa98e2SPeter Wemm { 606c2aa98e2SPeter Wemm /* initialize the token type table */ 607c2aa98e2SPeter Wemm char obuf[50]; 608c2aa98e2SPeter Wemm 60940266059SGregory Neil Shapiro firsttime = false; 610c2aa98e2SPeter Wemm if (OperatorChars == NULL) 611c2aa98e2SPeter Wemm { 612c2aa98e2SPeter Wemm if (ConfigLevel < 7) 613c2aa98e2SPeter Wemm OperatorChars = macvalue('o', CurEnv); 614c2aa98e2SPeter Wemm if (OperatorChars == NULL) 615c2aa98e2SPeter Wemm OperatorChars = ".:@[]"; 616c2aa98e2SPeter Wemm } 61706f25ae9SGregory Neil Shapiro expand(OperatorChars, obuf, sizeof obuf - sizeof DELIMCHARS, 61806f25ae9SGregory Neil Shapiro CurEnv); 61940266059SGregory Neil Shapiro (void) sm_strlcat(obuf, DELIMCHARS, sizeof obuf); 620c2aa98e2SPeter Wemm for (p = obuf; *p != '\0'; p++) 621c2aa98e2SPeter Wemm { 622c2aa98e2SPeter Wemm if (TokTypeTab[*p & 0xff] == ATM) 623c2aa98e2SPeter Wemm TokTypeTab[*p & 0xff] = OPR; 62406f25ae9SGregory Neil Shapiro if (TokTypeNoC[*p & 0xff] == ATM) 62506f25ae9SGregory Neil Shapiro TokTypeNoC[*p & 0xff] = OPR; 626c2aa98e2SPeter Wemm } 627c2aa98e2SPeter Wemm } 628c2aa98e2SPeter Wemm if (toktab == NULL) 629c2aa98e2SPeter Wemm toktab = TokTypeTab; 630c2aa98e2SPeter Wemm 631c2aa98e2SPeter Wemm /* make sure error messages don't have garbage on them */ 632c2aa98e2SPeter Wemm errno = 0; 633c2aa98e2SPeter Wemm 634c2aa98e2SPeter Wemm q = pvpbuf; 63540266059SGregory Neil Shapiro bslashmode = false; 63640266059SGregory Neil Shapiro route_syntax = false; 637c2aa98e2SPeter Wemm cmntcnt = 0; 638c2aa98e2SPeter Wemm anglecnt = 0; 639c2aa98e2SPeter Wemm avp = av; 640c2aa98e2SPeter Wemm state = ATM; 641c2aa98e2SPeter Wemm c = NOCHAR; 642c2aa98e2SPeter Wemm p = addr; 643c2aa98e2SPeter Wemm CurEnv->e_to = p; 644c2aa98e2SPeter Wemm if (tTd(22, 11)) 645c2aa98e2SPeter Wemm { 64640266059SGregory Neil Shapiro sm_dprintf("prescan: "); 647c2aa98e2SPeter Wemm xputs(p); 64840266059SGregory Neil Shapiro sm_dprintf("\n"); 649c2aa98e2SPeter Wemm } 650c2aa98e2SPeter Wemm 651c2aa98e2SPeter Wemm do 652c2aa98e2SPeter Wemm { 653c2aa98e2SPeter Wemm /* read a token */ 654c2aa98e2SPeter Wemm tok = q; 655c2aa98e2SPeter Wemm for (;;) 656c2aa98e2SPeter Wemm { 657c2aa98e2SPeter Wemm /* store away any old lookahead character */ 658c2aa98e2SPeter Wemm if (c != NOCHAR && !bslashmode) 659c2aa98e2SPeter Wemm { 660c2aa98e2SPeter Wemm /* see if there is room */ 661c2aa98e2SPeter Wemm if (q >= &pvpbuf[pvpbsize - 5]) 662c2aa98e2SPeter Wemm { 66306f25ae9SGregory Neil Shapiro usrerr("553 5.1.1 Address too long"); 66440266059SGregory Neil Shapiro if (strlen(addr) > MAXNAME) 665c2aa98e2SPeter Wemm addr[MAXNAME] = '\0'; 666c2aa98e2SPeter Wemm returnnull: 667c2aa98e2SPeter Wemm if (delimptr != NULL) 668c2aa98e2SPeter Wemm *delimptr = p; 669c2aa98e2SPeter Wemm CurEnv->e_to = saveto; 67006f25ae9SGregory Neil Shapiro return NULL; 671c2aa98e2SPeter Wemm } 672c2aa98e2SPeter Wemm 673c2aa98e2SPeter Wemm /* squirrel it away */ 674c2aa98e2SPeter Wemm *q++ = c; 675c2aa98e2SPeter Wemm } 676c2aa98e2SPeter Wemm 677c2aa98e2SPeter Wemm /* read a new input character */ 678c2aa98e2SPeter Wemm c = *p++; 679c2aa98e2SPeter Wemm if (c == '\0') 680c2aa98e2SPeter Wemm { 681c2aa98e2SPeter Wemm /* diagnose and patch up bad syntax */ 682c2aa98e2SPeter Wemm if (state == QST) 683c2aa98e2SPeter Wemm { 68440266059SGregory Neil Shapiro usrerr("553 Unbalanced '\"'"); 685c2aa98e2SPeter Wemm c = '"'; 686c2aa98e2SPeter Wemm } 687c2aa98e2SPeter Wemm else if (cmntcnt > 0) 688c2aa98e2SPeter Wemm { 68940266059SGregory Neil Shapiro usrerr("553 Unbalanced '('"); 690c2aa98e2SPeter Wemm c = ')'; 691c2aa98e2SPeter Wemm } 692c2aa98e2SPeter Wemm else if (anglecnt > 0) 693c2aa98e2SPeter Wemm { 694c2aa98e2SPeter Wemm c = '>'; 69540266059SGregory Neil Shapiro usrerr("553 Unbalanced '<'"); 696c2aa98e2SPeter Wemm } 697c2aa98e2SPeter Wemm else 698c2aa98e2SPeter Wemm break; 699c2aa98e2SPeter Wemm 700c2aa98e2SPeter Wemm p--; 701c2aa98e2SPeter Wemm } 702c2aa98e2SPeter Wemm else if (c == delim && cmntcnt <= 0 && state != QST) 703c2aa98e2SPeter Wemm { 704c2aa98e2SPeter Wemm if (anglecnt <= 0) 705c2aa98e2SPeter Wemm break; 706c2aa98e2SPeter Wemm 707c2aa98e2SPeter Wemm /* special case for better error management */ 708c2aa98e2SPeter Wemm if (delim == ',' && !route_syntax) 709c2aa98e2SPeter Wemm { 71040266059SGregory Neil Shapiro usrerr("553 Unbalanced '<'"); 711c2aa98e2SPeter Wemm c = '>'; 712c2aa98e2SPeter Wemm p--; 713c2aa98e2SPeter Wemm } 714c2aa98e2SPeter Wemm } 715c2aa98e2SPeter Wemm 716c2aa98e2SPeter Wemm if (tTd(22, 101)) 71740266059SGregory Neil Shapiro sm_dprintf("c=%c, s=%d; ", c, state); 718c2aa98e2SPeter Wemm 719c2aa98e2SPeter Wemm /* chew up special characters */ 720c2aa98e2SPeter Wemm *q = '\0'; 721c2aa98e2SPeter Wemm if (bslashmode) 722c2aa98e2SPeter Wemm { 72340266059SGregory Neil Shapiro bslashmode = false; 724c2aa98e2SPeter Wemm 725c2aa98e2SPeter Wemm /* kludge \! for naive users */ 726c2aa98e2SPeter Wemm if (cmntcnt > 0) 727c2aa98e2SPeter Wemm { 728c2aa98e2SPeter Wemm c = NOCHAR; 729c2aa98e2SPeter Wemm continue; 730c2aa98e2SPeter Wemm } 731c2aa98e2SPeter Wemm else if (c != '!' || state == QST) 732c2aa98e2SPeter Wemm { 733c2aa98e2SPeter Wemm *q++ = '\\'; 734c2aa98e2SPeter Wemm continue; 735c2aa98e2SPeter Wemm } 736c2aa98e2SPeter Wemm } 737c2aa98e2SPeter Wemm 738c2aa98e2SPeter Wemm if (c == '\\') 739c2aa98e2SPeter Wemm { 74040266059SGregory Neil Shapiro bslashmode = true; 741c2aa98e2SPeter Wemm } 742c2aa98e2SPeter Wemm else if (state == QST) 743c2aa98e2SPeter Wemm { 74406f25ae9SGregory Neil Shapiro /* EMPTY */ 745c2aa98e2SPeter Wemm /* do nothing, just avoid next clauses */ 746c2aa98e2SPeter Wemm } 74706f25ae9SGregory Neil Shapiro else if (c == '(' && toktab['('] == SPC) 748c2aa98e2SPeter Wemm { 749c2aa98e2SPeter Wemm cmntcnt++; 750c2aa98e2SPeter Wemm c = NOCHAR; 751c2aa98e2SPeter Wemm } 75206f25ae9SGregory Neil Shapiro else if (c == ')' && toktab['('] == SPC) 753c2aa98e2SPeter Wemm { 754c2aa98e2SPeter Wemm if (cmntcnt <= 0) 755c2aa98e2SPeter Wemm { 75640266059SGregory Neil Shapiro usrerr("553 Unbalanced ')'"); 757c2aa98e2SPeter Wemm c = NOCHAR; 758c2aa98e2SPeter Wemm } 759c2aa98e2SPeter Wemm else 760c2aa98e2SPeter Wemm cmntcnt--; 761c2aa98e2SPeter Wemm } 762c2aa98e2SPeter Wemm else if (cmntcnt > 0) 76306f25ae9SGregory Neil Shapiro { 764c2aa98e2SPeter Wemm c = NOCHAR; 76506f25ae9SGregory Neil Shapiro } 766c2aa98e2SPeter Wemm else if (c == '<') 767c2aa98e2SPeter Wemm { 76806f25ae9SGregory Neil Shapiro char *ptr = p; 769c2aa98e2SPeter Wemm 770c2aa98e2SPeter Wemm anglecnt++; 77106f25ae9SGregory Neil Shapiro while (isascii(*ptr) && isspace(*ptr)) 77206f25ae9SGregory Neil Shapiro ptr++; 77306f25ae9SGregory Neil Shapiro if (*ptr == '@') 77440266059SGregory Neil Shapiro route_syntax = true; 775c2aa98e2SPeter Wemm } 776c2aa98e2SPeter Wemm else if (c == '>') 777c2aa98e2SPeter Wemm { 778c2aa98e2SPeter Wemm if (anglecnt <= 0) 779c2aa98e2SPeter Wemm { 78040266059SGregory Neil Shapiro usrerr("553 Unbalanced '>'"); 781c2aa98e2SPeter Wemm c = NOCHAR; 782c2aa98e2SPeter Wemm } 783c2aa98e2SPeter Wemm else 784c2aa98e2SPeter Wemm anglecnt--; 78540266059SGregory Neil Shapiro route_syntax = false; 786c2aa98e2SPeter Wemm } 787c2aa98e2SPeter Wemm else if (delim == ' ' && isascii(c) && isspace(c)) 788c2aa98e2SPeter Wemm c = ' '; 789c2aa98e2SPeter Wemm 790c2aa98e2SPeter Wemm if (c == NOCHAR) 791c2aa98e2SPeter Wemm continue; 792c2aa98e2SPeter Wemm 793c2aa98e2SPeter Wemm /* see if this is end of input */ 794c2aa98e2SPeter Wemm if (c == delim && anglecnt <= 0 && state != QST) 795c2aa98e2SPeter Wemm break; 796c2aa98e2SPeter Wemm 797c2aa98e2SPeter Wemm newstate = StateTab[state][toktab[c & 0xff]]; 798c2aa98e2SPeter Wemm if (tTd(22, 101)) 79940266059SGregory Neil Shapiro sm_dprintf("ns=%02o\n", newstate); 800c2aa98e2SPeter Wemm state = newstate & TYPE; 801c2aa98e2SPeter Wemm if (state == ILL) 802c2aa98e2SPeter Wemm { 803c2aa98e2SPeter Wemm if (isascii(c) && isprint(c)) 80440266059SGregory Neil Shapiro usrerr("553 Illegal character %c", c); 805c2aa98e2SPeter Wemm else 80640266059SGregory Neil Shapiro usrerr("553 Illegal character 0x%02x", 80740266059SGregory Neil Shapiro c & 0x0ff); 808c2aa98e2SPeter Wemm } 809c2aa98e2SPeter Wemm if (bitset(M, newstate)) 810c2aa98e2SPeter Wemm c = NOCHAR; 811c2aa98e2SPeter Wemm if (bitset(B, newstate)) 812c2aa98e2SPeter Wemm break; 813c2aa98e2SPeter Wemm } 814c2aa98e2SPeter Wemm 815c2aa98e2SPeter Wemm /* new token */ 816c2aa98e2SPeter Wemm if (tok != q) 817c2aa98e2SPeter Wemm { 818c2aa98e2SPeter Wemm *q++ = '\0'; 819c2aa98e2SPeter Wemm if (tTd(22, 36)) 820c2aa98e2SPeter Wemm { 82140266059SGregory Neil Shapiro sm_dprintf("tok="); 822c2aa98e2SPeter Wemm xputs(tok); 82340266059SGregory Neil Shapiro sm_dprintf("\n"); 824c2aa98e2SPeter Wemm } 825c2aa98e2SPeter Wemm if (avp >= &av[MAXATOM]) 826c2aa98e2SPeter Wemm { 82706f25ae9SGregory Neil Shapiro usrerr("553 5.1.0 prescan: too many tokens"); 828c2aa98e2SPeter Wemm goto returnnull; 829c2aa98e2SPeter Wemm } 830c2aa98e2SPeter Wemm if (q - tok > MAXNAME) 831c2aa98e2SPeter Wemm { 83206f25ae9SGregory Neil Shapiro usrerr("553 5.1.0 prescan: token too long"); 833c2aa98e2SPeter Wemm goto returnnull; 834c2aa98e2SPeter Wemm } 835c2aa98e2SPeter Wemm *avp++ = tok; 836c2aa98e2SPeter Wemm } 837c2aa98e2SPeter Wemm } while (c != '\0' && (c != delim || anglecnt > 0)); 838c2aa98e2SPeter Wemm *avp = NULL; 839c2aa98e2SPeter Wemm p--; 840c2aa98e2SPeter Wemm if (delimptr != NULL) 841c2aa98e2SPeter Wemm *delimptr = p; 842c2aa98e2SPeter Wemm if (tTd(22, 12)) 843c2aa98e2SPeter Wemm { 84440266059SGregory Neil Shapiro sm_dprintf("prescan==>"); 845c2aa98e2SPeter Wemm printav(av); 846c2aa98e2SPeter Wemm } 847c2aa98e2SPeter Wemm CurEnv->e_to = saveto; 848c2aa98e2SPeter Wemm if (av[0] == NULL) 849c2aa98e2SPeter Wemm { 850c2aa98e2SPeter Wemm if (tTd(22, 1)) 85140266059SGregory Neil Shapiro sm_dprintf("prescan: null leading token\n"); 85206f25ae9SGregory Neil Shapiro return NULL; 853c2aa98e2SPeter Wemm } 85406f25ae9SGregory Neil Shapiro return av; 855c2aa98e2SPeter Wemm } 85640266059SGregory Neil Shapiro /* 857c2aa98e2SPeter Wemm ** REWRITE -- apply rewrite rules to token vector. 858c2aa98e2SPeter Wemm ** 859c2aa98e2SPeter Wemm ** This routine is an ordered production system. Each rewrite 860c2aa98e2SPeter Wemm ** rule has a LHS (called the pattern) and a RHS (called the 861c2aa98e2SPeter Wemm ** rewrite); 'rwr' points the the current rewrite rule. 862c2aa98e2SPeter Wemm ** 863c2aa98e2SPeter Wemm ** For each rewrite rule, 'avp' points the address vector we 864c2aa98e2SPeter Wemm ** are trying to match against, and 'pvp' points to the pattern. 865c2aa98e2SPeter Wemm ** If pvp points to a special match value (MATCHZANY, MATCHANY, 866c2aa98e2SPeter Wemm ** MATCHONE, MATCHCLASS, MATCHNCLASS) then the address in avp 867c2aa98e2SPeter Wemm ** matched is saved away in the match vector (pointed to by 'mvp'). 868c2aa98e2SPeter Wemm ** 869c2aa98e2SPeter Wemm ** When a match between avp & pvp does not match, we try to 870c2aa98e2SPeter Wemm ** back out. If we back up over MATCHONE, MATCHCLASS, or MATCHNCLASS 871c2aa98e2SPeter Wemm ** we must also back out the match in mvp. If we reach a 872c2aa98e2SPeter Wemm ** MATCHANY or MATCHZANY we just extend the match and start 873c2aa98e2SPeter Wemm ** over again. 874c2aa98e2SPeter Wemm ** 875c2aa98e2SPeter Wemm ** When we finally match, we rewrite the address vector 876c2aa98e2SPeter Wemm ** and try over again. 877c2aa98e2SPeter Wemm ** 878c2aa98e2SPeter Wemm ** Parameters: 879c2aa98e2SPeter Wemm ** pvp -- pointer to token vector. 880c2aa98e2SPeter Wemm ** ruleset -- the ruleset to use for rewriting. 881c2aa98e2SPeter Wemm ** reclevel -- recursion level (to catch loops). 882c2aa98e2SPeter Wemm ** e -- the current envelope. 88340266059SGregory Neil Shapiro ** maxatom -- maximum length of buffer (usually MAXATOM) 884c2aa98e2SPeter Wemm ** 885c2aa98e2SPeter Wemm ** Returns: 886c2aa98e2SPeter Wemm ** A status code. If EX_TEMPFAIL, higher level code should 887c2aa98e2SPeter Wemm ** attempt recovery. 888c2aa98e2SPeter Wemm ** 889c2aa98e2SPeter Wemm ** Side Effects: 890c2aa98e2SPeter Wemm ** pvp is modified. 891c2aa98e2SPeter Wemm */ 892c2aa98e2SPeter Wemm 893c2aa98e2SPeter Wemm struct match 894c2aa98e2SPeter Wemm { 89506f25ae9SGregory Neil Shapiro char **match_first; /* first token matched */ 89606f25ae9SGregory Neil Shapiro char **match_last; /* last token matched */ 89706f25ae9SGregory Neil Shapiro char **match_pattern; /* pointer to pattern */ 898c2aa98e2SPeter Wemm }; 899c2aa98e2SPeter Wemm 900c2aa98e2SPeter Wemm int 90140266059SGregory Neil Shapiro rewrite(pvp, ruleset, reclevel, e, maxatom) 902c2aa98e2SPeter Wemm char **pvp; 903c2aa98e2SPeter Wemm int ruleset; 904c2aa98e2SPeter Wemm int reclevel; 905c2aa98e2SPeter Wemm register ENVELOPE *e; 90640266059SGregory Neil Shapiro int maxatom; 907c2aa98e2SPeter Wemm { 908c2aa98e2SPeter Wemm register char *ap; /* address pointer */ 909c2aa98e2SPeter Wemm register char *rp; /* rewrite pointer */ 91006f25ae9SGregory Neil Shapiro register char *rulename; /* ruleset name */ 91106f25ae9SGregory Neil Shapiro register char *prefix; 912c2aa98e2SPeter Wemm register char **avp; /* address vector pointer */ 913c2aa98e2SPeter Wemm register char **rvp; /* rewrite vector pointer */ 914c2aa98e2SPeter Wemm register struct match *mlp; /* cur ptr into mlist */ 915c2aa98e2SPeter Wemm register struct rewrite *rwr; /* pointer to current rewrite rule */ 916c2aa98e2SPeter Wemm int ruleno; /* current rule number */ 917c2aa98e2SPeter Wemm int rstat = EX_OK; /* return status */ 918c2aa98e2SPeter Wemm int loopcount; 919c2aa98e2SPeter Wemm struct match mlist[MAXMATCH]; /* stores match on LHS */ 920c2aa98e2SPeter Wemm char *npvp[MAXATOM + 1]; /* temporary space for rebuild */ 921c2aa98e2SPeter Wemm char buf[MAXLINE]; 92206f25ae9SGregory Neil Shapiro char name[6]; 923c2aa98e2SPeter Wemm 924c2aa98e2SPeter Wemm if (ruleset < 0 || ruleset >= MAXRWSETS) 925c2aa98e2SPeter Wemm { 92606f25ae9SGregory Neil Shapiro syserr("554 5.3.5 rewrite: illegal ruleset number %d", ruleset); 927c2aa98e2SPeter Wemm return EX_CONFIG; 928c2aa98e2SPeter Wemm } 92906f25ae9SGregory Neil Shapiro rulename = RuleSetNames[ruleset]; 93006f25ae9SGregory Neil Shapiro if (rulename == NULL) 93106f25ae9SGregory Neil Shapiro { 93240266059SGregory Neil Shapiro (void) sm_snprintf(name, sizeof name, "%d", ruleset); 93306f25ae9SGregory Neil Shapiro rulename = name; 93406f25ae9SGregory Neil Shapiro } 93506f25ae9SGregory Neil Shapiro if (OpMode == MD_TEST) 93606f25ae9SGregory Neil Shapiro prefix = ""; 93706f25ae9SGregory Neil Shapiro else 93806f25ae9SGregory Neil Shapiro prefix = "rewrite: ruleset "; 93906f25ae9SGregory Neil Shapiro if (OpMode == MD_TEST) 94006f25ae9SGregory Neil Shapiro { 94140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 94240266059SGregory Neil Shapiro "%s%-16.16s input:", prefix, rulename); 94306f25ae9SGregory Neil Shapiro printav(pvp); 94406f25ae9SGregory Neil Shapiro } 94506f25ae9SGregory Neil Shapiro else if (tTd(21, 1)) 94606f25ae9SGregory Neil Shapiro { 94740266059SGregory Neil Shapiro sm_dprintf("%s%-16.16s input:", prefix, rulename); 94806f25ae9SGregory Neil Shapiro printav(pvp); 94906f25ae9SGregory Neil Shapiro } 950c2aa98e2SPeter Wemm if (reclevel++ > MaxRuleRecursion) 951c2aa98e2SPeter Wemm { 95206f25ae9SGregory Neil Shapiro syserr("rewrite: excessive recursion (max %d), ruleset %s", 95306f25ae9SGregory Neil Shapiro MaxRuleRecursion, rulename); 954c2aa98e2SPeter Wemm return EX_CONFIG; 955c2aa98e2SPeter Wemm } 956c2aa98e2SPeter Wemm if (pvp == NULL) 957c2aa98e2SPeter Wemm return EX_USAGE; 958c2aa98e2SPeter Wemm 959c2aa98e2SPeter Wemm /* 960c2aa98e2SPeter Wemm ** Run through the list of rewrite rules, applying 961c2aa98e2SPeter Wemm ** any that match. 962c2aa98e2SPeter Wemm */ 963c2aa98e2SPeter Wemm 964c2aa98e2SPeter Wemm ruleno = 1; 965c2aa98e2SPeter Wemm loopcount = 0; 966c2aa98e2SPeter Wemm for (rwr = RewriteRules[ruleset]; rwr != NULL; ) 967c2aa98e2SPeter Wemm { 96806f25ae9SGregory Neil Shapiro int status; 969c2aa98e2SPeter Wemm 970c2aa98e2SPeter Wemm /* if already canonical, quit now */ 971c2aa98e2SPeter Wemm if (pvp[0] != NULL && (pvp[0][0] & 0377) == CANONNET) 972c2aa98e2SPeter Wemm break; 973c2aa98e2SPeter Wemm 974c2aa98e2SPeter Wemm if (tTd(21, 12)) 975c2aa98e2SPeter Wemm { 97606f25ae9SGregory Neil Shapiro if (tTd(21, 15)) 97740266059SGregory Neil Shapiro sm_dprintf("-----trying rule (line %d):", 97806f25ae9SGregory Neil Shapiro rwr->r_line); 97906f25ae9SGregory Neil Shapiro else 98040266059SGregory Neil Shapiro sm_dprintf("-----trying rule:"); 981c2aa98e2SPeter Wemm printav(rwr->r_lhs); 982c2aa98e2SPeter Wemm } 983c2aa98e2SPeter Wemm 984c2aa98e2SPeter Wemm /* try to match on this rule */ 985c2aa98e2SPeter Wemm mlp = mlist; 986c2aa98e2SPeter Wemm rvp = rwr->r_lhs; 987c2aa98e2SPeter Wemm avp = pvp; 988c2aa98e2SPeter Wemm if (++loopcount > 100) 989c2aa98e2SPeter Wemm { 99006f25ae9SGregory Neil Shapiro syserr("554 5.3.5 Infinite loop in ruleset %s, rule %d", 99106f25ae9SGregory Neil Shapiro rulename, ruleno); 992c2aa98e2SPeter Wemm if (tTd(21, 1)) 993c2aa98e2SPeter Wemm { 99440266059SGregory Neil Shapiro sm_dprintf("workspace: "); 995c2aa98e2SPeter Wemm printav(pvp); 996c2aa98e2SPeter Wemm } 997c2aa98e2SPeter Wemm break; 998c2aa98e2SPeter Wemm } 999c2aa98e2SPeter Wemm 1000c2aa98e2SPeter Wemm while ((ap = *avp) != NULL || *rvp != NULL) 1001c2aa98e2SPeter Wemm { 1002c2aa98e2SPeter Wemm rp = *rvp; 1003c2aa98e2SPeter Wemm if (tTd(21, 35)) 1004c2aa98e2SPeter Wemm { 100540266059SGregory Neil Shapiro sm_dprintf("ADVANCE rp="); 1006c2aa98e2SPeter Wemm xputs(rp); 100740266059SGregory Neil Shapiro sm_dprintf(", ap="); 1008c2aa98e2SPeter Wemm xputs(ap); 100940266059SGregory Neil Shapiro sm_dprintf("\n"); 1010c2aa98e2SPeter Wemm } 1011c2aa98e2SPeter Wemm if (rp == NULL) 1012c2aa98e2SPeter Wemm { 1013c2aa98e2SPeter Wemm /* end-of-pattern before end-of-address */ 1014c2aa98e2SPeter Wemm goto backup; 1015c2aa98e2SPeter Wemm } 1016c2aa98e2SPeter Wemm if (ap == NULL && (*rp & 0377) != MATCHZANY && 1017c2aa98e2SPeter Wemm (*rp & 0377) != MATCHZERO) 1018c2aa98e2SPeter Wemm { 1019c2aa98e2SPeter Wemm /* end-of-input with patterns left */ 1020c2aa98e2SPeter Wemm goto backup; 1021c2aa98e2SPeter Wemm } 1022c2aa98e2SPeter Wemm 1023c2aa98e2SPeter Wemm switch (*rp & 0377) 1024c2aa98e2SPeter Wemm { 1025c2aa98e2SPeter Wemm case MATCHCLASS: 1026c2aa98e2SPeter Wemm /* match any phrase in a class */ 102706f25ae9SGregory Neil Shapiro mlp->match_pattern = rvp; 102806f25ae9SGregory Neil Shapiro mlp->match_first = avp; 1029c2aa98e2SPeter Wemm extendclass: 1030c2aa98e2SPeter Wemm ap = *avp; 1031c2aa98e2SPeter Wemm if (ap == NULL) 1032c2aa98e2SPeter Wemm goto backup; 103306f25ae9SGregory Neil Shapiro mlp->match_last = avp++; 103406f25ae9SGregory Neil Shapiro cataddr(mlp->match_first, mlp->match_last, 103506f25ae9SGregory Neil Shapiro buf, sizeof buf, '\0'); 1036c2aa98e2SPeter Wemm if (!wordinclass(buf, rp[1])) 1037c2aa98e2SPeter Wemm { 1038c2aa98e2SPeter Wemm if (tTd(21, 36)) 1039c2aa98e2SPeter Wemm { 104040266059SGregory Neil Shapiro sm_dprintf("EXTEND rp="); 1041c2aa98e2SPeter Wemm xputs(rp); 104240266059SGregory Neil Shapiro sm_dprintf(", ap="); 1043c2aa98e2SPeter Wemm xputs(ap); 104440266059SGregory Neil Shapiro sm_dprintf("\n"); 1045c2aa98e2SPeter Wemm } 1046c2aa98e2SPeter Wemm goto extendclass; 1047c2aa98e2SPeter Wemm } 1048c2aa98e2SPeter Wemm if (tTd(21, 36)) 104940266059SGregory Neil Shapiro sm_dprintf("CLMATCH\n"); 1050c2aa98e2SPeter Wemm mlp++; 1051c2aa98e2SPeter Wemm break; 1052c2aa98e2SPeter Wemm 1053c2aa98e2SPeter Wemm case MATCHNCLASS: 1054c2aa98e2SPeter Wemm /* match any token not in a class */ 1055c2aa98e2SPeter Wemm if (wordinclass(ap, rp[1])) 1056c2aa98e2SPeter Wemm goto backup; 1057c2aa98e2SPeter Wemm 105806f25ae9SGregory Neil Shapiro /* FALLTHROUGH */ 1059c2aa98e2SPeter Wemm 1060c2aa98e2SPeter Wemm case MATCHONE: 1061c2aa98e2SPeter Wemm case MATCHANY: 1062c2aa98e2SPeter Wemm /* match exactly one token */ 106306f25ae9SGregory Neil Shapiro mlp->match_pattern = rvp; 106406f25ae9SGregory Neil Shapiro mlp->match_first = avp; 106506f25ae9SGregory Neil Shapiro mlp->match_last = avp++; 1066c2aa98e2SPeter Wemm mlp++; 1067c2aa98e2SPeter Wemm break; 1068c2aa98e2SPeter Wemm 1069c2aa98e2SPeter Wemm case MATCHZANY: 1070c2aa98e2SPeter Wemm /* match zero or more tokens */ 107106f25ae9SGregory Neil Shapiro mlp->match_pattern = rvp; 107206f25ae9SGregory Neil Shapiro mlp->match_first = avp; 107306f25ae9SGregory Neil Shapiro mlp->match_last = avp - 1; 1074c2aa98e2SPeter Wemm mlp++; 1075c2aa98e2SPeter Wemm break; 1076c2aa98e2SPeter Wemm 1077c2aa98e2SPeter Wemm case MATCHZERO: 1078c2aa98e2SPeter Wemm /* match zero tokens */ 1079c2aa98e2SPeter Wemm break; 1080c2aa98e2SPeter Wemm 1081c2aa98e2SPeter Wemm case MACRODEXPAND: 1082c2aa98e2SPeter Wemm /* 1083c2aa98e2SPeter Wemm ** Match against run-time macro. 1084c2aa98e2SPeter Wemm ** This algorithm is broken for the 1085c2aa98e2SPeter Wemm ** general case (no recursive macros, 1086c2aa98e2SPeter Wemm ** improper tokenization) but should 1087c2aa98e2SPeter Wemm ** work for the usual cases. 1088c2aa98e2SPeter Wemm */ 1089c2aa98e2SPeter Wemm 1090c2aa98e2SPeter Wemm ap = macvalue(rp[1], e); 109106f25ae9SGregory Neil Shapiro mlp->match_first = avp; 1092c2aa98e2SPeter Wemm if (tTd(21, 2)) 109340266059SGregory Neil Shapiro sm_dprintf("rewrite: LHS $&%s => \"%s\"\n", 1094c2aa98e2SPeter Wemm macname(rp[1]), 1095c2aa98e2SPeter Wemm ap == NULL ? "(NULL)" : ap); 1096c2aa98e2SPeter Wemm 1097c2aa98e2SPeter Wemm if (ap == NULL) 1098c2aa98e2SPeter Wemm break; 1099c2aa98e2SPeter Wemm while (*ap != '\0') 1100c2aa98e2SPeter Wemm { 1101c2aa98e2SPeter Wemm if (*avp == NULL || 110240266059SGregory Neil Shapiro sm_strncasecmp(ap, *avp, 110340266059SGregory Neil Shapiro strlen(*avp)) != 0) 1104c2aa98e2SPeter Wemm { 1105c2aa98e2SPeter Wemm /* no match */ 110606f25ae9SGregory Neil Shapiro avp = mlp->match_first; 1107c2aa98e2SPeter Wemm goto backup; 1108c2aa98e2SPeter Wemm } 1109c2aa98e2SPeter Wemm ap += strlen(*avp++); 1110c2aa98e2SPeter Wemm } 1111c2aa98e2SPeter Wemm 1112c2aa98e2SPeter Wemm /* match */ 1113c2aa98e2SPeter Wemm break; 1114c2aa98e2SPeter Wemm 1115c2aa98e2SPeter Wemm default: 1116c2aa98e2SPeter Wemm /* must have exact match */ 1117c2aa98e2SPeter Wemm if (sm_strcasecmp(rp, ap)) 1118c2aa98e2SPeter Wemm goto backup; 1119c2aa98e2SPeter Wemm avp++; 1120c2aa98e2SPeter Wemm break; 1121c2aa98e2SPeter Wemm } 1122c2aa98e2SPeter Wemm 1123c2aa98e2SPeter Wemm /* successful match on this token */ 1124c2aa98e2SPeter Wemm rvp++; 1125c2aa98e2SPeter Wemm continue; 1126c2aa98e2SPeter Wemm 1127c2aa98e2SPeter Wemm backup: 1128c2aa98e2SPeter Wemm /* match failed -- back up */ 1129c2aa98e2SPeter Wemm while (--mlp >= mlist) 1130c2aa98e2SPeter Wemm { 113106f25ae9SGregory Neil Shapiro rvp = mlp->match_pattern; 1132c2aa98e2SPeter Wemm rp = *rvp; 113306f25ae9SGregory Neil Shapiro avp = mlp->match_last + 1; 1134c2aa98e2SPeter Wemm ap = *avp; 1135c2aa98e2SPeter Wemm 1136c2aa98e2SPeter Wemm if (tTd(21, 36)) 1137c2aa98e2SPeter Wemm { 113840266059SGregory Neil Shapiro sm_dprintf("BACKUP rp="); 1139c2aa98e2SPeter Wemm xputs(rp); 114040266059SGregory Neil Shapiro sm_dprintf(", ap="); 1141c2aa98e2SPeter Wemm xputs(ap); 114240266059SGregory Neil Shapiro sm_dprintf("\n"); 1143c2aa98e2SPeter Wemm } 1144c2aa98e2SPeter Wemm 1145c2aa98e2SPeter Wemm if (ap == NULL) 1146c2aa98e2SPeter Wemm { 1147c2aa98e2SPeter Wemm /* run off the end -- back up again */ 1148c2aa98e2SPeter Wemm continue; 1149c2aa98e2SPeter Wemm } 1150c2aa98e2SPeter Wemm if ((*rp & 0377) == MATCHANY || 1151c2aa98e2SPeter Wemm (*rp & 0377) == MATCHZANY) 1152c2aa98e2SPeter Wemm { 1153c2aa98e2SPeter Wemm /* extend binding and continue */ 115406f25ae9SGregory Neil Shapiro mlp->match_last = avp++; 1155c2aa98e2SPeter Wemm rvp++; 1156c2aa98e2SPeter Wemm mlp++; 1157c2aa98e2SPeter Wemm break; 1158c2aa98e2SPeter Wemm } 1159c2aa98e2SPeter Wemm if ((*rp & 0377) == MATCHCLASS) 1160c2aa98e2SPeter Wemm { 1161c2aa98e2SPeter Wemm /* extend binding and try again */ 116206f25ae9SGregory Neil Shapiro mlp->match_last = avp; 1163c2aa98e2SPeter Wemm goto extendclass; 1164c2aa98e2SPeter Wemm } 1165c2aa98e2SPeter Wemm } 1166c2aa98e2SPeter Wemm 1167c2aa98e2SPeter Wemm if (mlp < mlist) 1168c2aa98e2SPeter Wemm { 1169c2aa98e2SPeter Wemm /* total failure to match */ 1170c2aa98e2SPeter Wemm break; 1171c2aa98e2SPeter Wemm } 1172c2aa98e2SPeter Wemm } 1173c2aa98e2SPeter Wemm 1174c2aa98e2SPeter Wemm /* 1175c2aa98e2SPeter Wemm ** See if we successfully matched 1176c2aa98e2SPeter Wemm */ 1177c2aa98e2SPeter Wemm 1178c2aa98e2SPeter Wemm if (mlp < mlist || *rvp != NULL) 1179c2aa98e2SPeter Wemm { 1180c2aa98e2SPeter Wemm if (tTd(21, 10)) 118140266059SGregory Neil Shapiro sm_dprintf("----- rule fails\n"); 1182c2aa98e2SPeter Wemm rwr = rwr->r_next; 1183c2aa98e2SPeter Wemm ruleno++; 1184c2aa98e2SPeter Wemm loopcount = 0; 1185c2aa98e2SPeter Wemm continue; 1186c2aa98e2SPeter Wemm } 1187c2aa98e2SPeter Wemm 1188c2aa98e2SPeter Wemm rvp = rwr->r_rhs; 1189c2aa98e2SPeter Wemm if (tTd(21, 12)) 1190c2aa98e2SPeter Wemm { 119140266059SGregory Neil Shapiro sm_dprintf("-----rule matches:"); 1192c2aa98e2SPeter Wemm printav(rvp); 1193c2aa98e2SPeter Wemm } 1194c2aa98e2SPeter Wemm 1195c2aa98e2SPeter Wemm rp = *rvp; 119606f25ae9SGregory Neil Shapiro if (rp != NULL) 119706f25ae9SGregory Neil Shapiro { 1198c2aa98e2SPeter Wemm if ((*rp & 0377) == CANONUSER) 1199c2aa98e2SPeter Wemm { 1200c2aa98e2SPeter Wemm rvp++; 1201c2aa98e2SPeter Wemm rwr = rwr->r_next; 1202c2aa98e2SPeter Wemm ruleno++; 1203c2aa98e2SPeter Wemm loopcount = 0; 1204c2aa98e2SPeter Wemm } 1205c2aa98e2SPeter Wemm else if ((*rp & 0377) == CANONHOST) 1206c2aa98e2SPeter Wemm { 1207c2aa98e2SPeter Wemm rvp++; 1208c2aa98e2SPeter Wemm rwr = NULL; 1209c2aa98e2SPeter Wemm } 121006f25ae9SGregory Neil Shapiro } 1211c2aa98e2SPeter Wemm 1212c2aa98e2SPeter Wemm /* substitute */ 1213c2aa98e2SPeter Wemm for (avp = npvp; *rvp != NULL; rvp++) 1214c2aa98e2SPeter Wemm { 1215c2aa98e2SPeter Wemm register struct match *m; 1216c2aa98e2SPeter Wemm register char **pp; 1217c2aa98e2SPeter Wemm 1218c2aa98e2SPeter Wemm rp = *rvp; 1219c2aa98e2SPeter Wemm if ((*rp & 0377) == MATCHREPL) 1220c2aa98e2SPeter Wemm { 1221c2aa98e2SPeter Wemm /* substitute from LHS */ 1222c2aa98e2SPeter Wemm m = &mlist[rp[1] - '1']; 1223c2aa98e2SPeter Wemm if (m < mlist || m >= mlp) 1224c2aa98e2SPeter Wemm { 122506f25ae9SGregory Neil Shapiro syserr("554 5.3.5 rewrite: ruleset %s: replacement $%c out of bounds", 122606f25ae9SGregory Neil Shapiro rulename, rp[1]); 1227c2aa98e2SPeter Wemm return EX_CONFIG; 1228c2aa98e2SPeter Wemm } 1229c2aa98e2SPeter Wemm if (tTd(21, 15)) 1230c2aa98e2SPeter Wemm { 123140266059SGregory Neil Shapiro sm_dprintf("$%c:", rp[1]); 123206f25ae9SGregory Neil Shapiro pp = m->match_first; 123306f25ae9SGregory Neil Shapiro while (pp <= m->match_last) 1234c2aa98e2SPeter Wemm { 123540266059SGregory Neil Shapiro sm_dprintf(" %p=\"", *pp); 123640266059SGregory Neil Shapiro sm_dflush(); 123740266059SGregory Neil Shapiro sm_dprintf("%s\"", *pp++); 1238c2aa98e2SPeter Wemm } 123940266059SGregory Neil Shapiro sm_dprintf("\n"); 1240c2aa98e2SPeter Wemm } 124106f25ae9SGregory Neil Shapiro pp = m->match_first; 124206f25ae9SGregory Neil Shapiro while (pp <= m->match_last) 1243c2aa98e2SPeter Wemm { 124440266059SGregory Neil Shapiro if (avp >= &npvp[maxatom]) 1245c2aa98e2SPeter Wemm { 124606f25ae9SGregory Neil Shapiro syserr("554 5.3.0 rewrite: expansion too long"); 124740266059SGregory Neil Shapiro if (LogLevel > 9) 124840266059SGregory Neil Shapiro sm_syslog(LOG_ERR, 124940266059SGregory Neil Shapiro e->e_id, 125040266059SGregory Neil Shapiro "rewrite: expansion too long, ruleset=%s, ruleno=%d", 125140266059SGregory Neil Shapiro rulename, 125240266059SGregory Neil Shapiro ruleno); 1253c2aa98e2SPeter Wemm return EX_DATAERR; 1254c2aa98e2SPeter Wemm } 1255c2aa98e2SPeter Wemm *avp++ = *pp++; 1256c2aa98e2SPeter Wemm } 1257c2aa98e2SPeter Wemm } 1258c2aa98e2SPeter Wemm else 1259c2aa98e2SPeter Wemm { 1260c2aa98e2SPeter Wemm /* some sort of replacement */ 126140266059SGregory Neil Shapiro if (avp >= &npvp[maxatom]) 1262c2aa98e2SPeter Wemm { 1263c2aa98e2SPeter Wemm toolong: 126406f25ae9SGregory Neil Shapiro syserr("554 5.3.0 rewrite: expansion too long"); 126540266059SGregory Neil Shapiro if (LogLevel > 9) 126640266059SGregory Neil Shapiro sm_syslog(LOG_ERR, e->e_id, 126740266059SGregory Neil Shapiro "rewrite: expansion too long, ruleset=%s, ruleno=%d", 126840266059SGregory Neil Shapiro rulename, ruleno); 1269c2aa98e2SPeter Wemm return EX_DATAERR; 1270c2aa98e2SPeter Wemm } 1271c2aa98e2SPeter Wemm if ((*rp & 0377) != MACRODEXPAND) 1272c2aa98e2SPeter Wemm { 1273c2aa98e2SPeter Wemm /* vanilla replacement */ 1274c2aa98e2SPeter Wemm *avp++ = rp; 1275c2aa98e2SPeter Wemm } 1276c2aa98e2SPeter Wemm else 1277c2aa98e2SPeter Wemm { 1278c2aa98e2SPeter Wemm /* $&x replacement */ 1279c2aa98e2SPeter Wemm char *mval = macvalue(rp[1], e); 1280c2aa98e2SPeter Wemm char **xpvp; 1281c2aa98e2SPeter Wemm int trsize = 0; 1282c2aa98e2SPeter Wemm static size_t pvpb1_size = 0; 1283c2aa98e2SPeter Wemm static char **pvpb1 = NULL; 1284c2aa98e2SPeter Wemm char pvpbuf[PSBUFSIZE]; 1285c2aa98e2SPeter Wemm 1286c2aa98e2SPeter Wemm if (tTd(21, 2)) 128740266059SGregory Neil Shapiro sm_dprintf("rewrite: RHS $&%s => \"%s\"\n", 1288c2aa98e2SPeter Wemm macname(rp[1]), 1289c2aa98e2SPeter Wemm mval == NULL ? "(NULL)" : mval); 1290c2aa98e2SPeter Wemm if (mval == NULL || *mval == '\0') 1291c2aa98e2SPeter Wemm continue; 1292c2aa98e2SPeter Wemm 1293c2aa98e2SPeter Wemm /* save the remainder of the input */ 1294c2aa98e2SPeter Wemm for (xpvp = pvp; *xpvp != NULL; xpvp++) 1295c2aa98e2SPeter Wemm trsize += sizeof *xpvp; 129606f25ae9SGregory Neil Shapiro if ((size_t) trsize > pvpb1_size) 1297c2aa98e2SPeter Wemm { 1298c2aa98e2SPeter Wemm if (pvpb1 != NULL) 12998774250cSGregory Neil Shapiro sm_free(pvpb1); 130040266059SGregory Neil Shapiro pvpb1 = (char **) 130140266059SGregory Neil Shapiro sm_pmalloc_x(trsize); 1302c2aa98e2SPeter Wemm pvpb1_size = trsize; 1303c2aa98e2SPeter Wemm } 1304c2aa98e2SPeter Wemm 130506f25ae9SGregory Neil Shapiro memmove((char *) pvpb1, 130606f25ae9SGregory Neil Shapiro (char *) pvp, 130706f25ae9SGregory Neil Shapiro trsize); 1308c2aa98e2SPeter Wemm 1309c2aa98e2SPeter Wemm /* scan the new replacement */ 1310c2aa98e2SPeter Wemm xpvp = prescan(mval, '\0', pvpbuf, 131106f25ae9SGregory Neil Shapiro sizeof pvpbuf, NULL, 131206f25ae9SGregory Neil Shapiro NULL); 1313c2aa98e2SPeter Wemm if (xpvp == NULL) 1314c2aa98e2SPeter Wemm { 1315c2aa98e2SPeter Wemm /* prescan pre-printed error */ 1316c2aa98e2SPeter Wemm return EX_DATAERR; 1317c2aa98e2SPeter Wemm } 1318c2aa98e2SPeter Wemm 1319c2aa98e2SPeter Wemm /* insert it into the output stream */ 1320c2aa98e2SPeter Wemm while (*xpvp != NULL) 1321c2aa98e2SPeter Wemm { 1322c2aa98e2SPeter Wemm if (tTd(21, 19)) 132340266059SGregory Neil Shapiro sm_dprintf(" ... %s\n", 132406f25ae9SGregory Neil Shapiro *xpvp); 132540266059SGregory Neil Shapiro *avp++ = sm_rpool_strdup_x( 132640266059SGregory Neil Shapiro e->e_rpool, *xpvp); 132740266059SGregory Neil Shapiro if (avp >= &npvp[maxatom]) 1328c2aa98e2SPeter Wemm goto toolong; 1329c2aa98e2SPeter Wemm xpvp++; 1330c2aa98e2SPeter Wemm } 1331c2aa98e2SPeter Wemm if (tTd(21, 19)) 133240266059SGregory Neil Shapiro sm_dprintf(" ... DONE\n"); 1333c2aa98e2SPeter Wemm 1334c2aa98e2SPeter Wemm /* restore the old trailing input */ 133506f25ae9SGregory Neil Shapiro memmove((char *) pvp, 133606f25ae9SGregory Neil Shapiro (char *) pvpb1, 133706f25ae9SGregory Neil Shapiro trsize); 1338c2aa98e2SPeter Wemm } 1339c2aa98e2SPeter Wemm } 1340c2aa98e2SPeter Wemm } 1341c2aa98e2SPeter Wemm *avp++ = NULL; 1342c2aa98e2SPeter Wemm 1343c2aa98e2SPeter Wemm /* 1344c2aa98e2SPeter Wemm ** Check for any hostname/keyword lookups. 1345c2aa98e2SPeter Wemm */ 1346c2aa98e2SPeter Wemm 1347c2aa98e2SPeter Wemm for (rvp = npvp; *rvp != NULL; rvp++) 1348c2aa98e2SPeter Wemm { 1349c2aa98e2SPeter Wemm char **hbrvp; 1350c2aa98e2SPeter Wemm char **xpvp; 1351c2aa98e2SPeter Wemm int trsize; 1352c2aa98e2SPeter Wemm char *replac; 1353c2aa98e2SPeter Wemm int endtoken; 1354c2aa98e2SPeter Wemm STAB *map; 1355c2aa98e2SPeter Wemm char *mapname; 1356c2aa98e2SPeter Wemm char **key_rvp; 1357c2aa98e2SPeter Wemm char **arg_rvp; 1358c2aa98e2SPeter Wemm char **default_rvp; 135906f25ae9SGregory Neil Shapiro char cbuf[MAXNAME + 1]; 1360c2aa98e2SPeter Wemm char *pvpb1[MAXATOM + 1]; 1361c2aa98e2SPeter Wemm char *argvect[10]; 1362c2aa98e2SPeter Wemm char pvpbuf[PSBUFSIZE]; 1363c2aa98e2SPeter Wemm char *nullpvp[1]; 1364c2aa98e2SPeter Wemm 1365c2aa98e2SPeter Wemm if ((**rvp & 0377) != HOSTBEGIN && 1366c2aa98e2SPeter Wemm (**rvp & 0377) != LOOKUPBEGIN) 1367c2aa98e2SPeter Wemm continue; 1368c2aa98e2SPeter Wemm 1369c2aa98e2SPeter Wemm /* 1370c2aa98e2SPeter Wemm ** Got a hostname/keyword lookup. 1371c2aa98e2SPeter Wemm ** 1372c2aa98e2SPeter Wemm ** This could be optimized fairly easily. 1373c2aa98e2SPeter Wemm */ 1374c2aa98e2SPeter Wemm 1375c2aa98e2SPeter Wemm hbrvp = rvp; 1376c2aa98e2SPeter Wemm if ((**rvp & 0377) == HOSTBEGIN) 1377c2aa98e2SPeter Wemm { 1378c2aa98e2SPeter Wemm endtoken = HOSTEND; 1379c2aa98e2SPeter Wemm mapname = "host"; 1380c2aa98e2SPeter Wemm } 1381c2aa98e2SPeter Wemm else 1382c2aa98e2SPeter Wemm { 1383c2aa98e2SPeter Wemm endtoken = LOOKUPEND; 1384c2aa98e2SPeter Wemm mapname = *++rvp; 1385c2aa98e2SPeter Wemm } 1386c2aa98e2SPeter Wemm map = stab(mapname, ST_MAP, ST_FIND); 1387c2aa98e2SPeter Wemm if (map == NULL) 138806f25ae9SGregory Neil Shapiro syserr("554 5.3.0 rewrite: map %s not found", mapname); 1389c2aa98e2SPeter Wemm 1390c2aa98e2SPeter Wemm /* extract the match part */ 1391c2aa98e2SPeter Wemm key_rvp = ++rvp; 1392c2aa98e2SPeter Wemm default_rvp = NULL; 1393c2aa98e2SPeter Wemm arg_rvp = argvect; 1394c2aa98e2SPeter Wemm xpvp = NULL; 1395c2aa98e2SPeter Wemm replac = pvpbuf; 1396c2aa98e2SPeter Wemm while (*rvp != NULL && (**rvp & 0377) != endtoken) 1397c2aa98e2SPeter Wemm { 1398c2aa98e2SPeter Wemm int nodetype = **rvp & 0377; 1399c2aa98e2SPeter Wemm 1400c2aa98e2SPeter Wemm if (nodetype != CANONHOST && nodetype != CANONUSER) 1401c2aa98e2SPeter Wemm { 1402c2aa98e2SPeter Wemm rvp++; 1403c2aa98e2SPeter Wemm continue; 1404c2aa98e2SPeter Wemm } 1405c2aa98e2SPeter Wemm 1406c2aa98e2SPeter Wemm *rvp++ = NULL; 1407c2aa98e2SPeter Wemm 1408c2aa98e2SPeter Wemm if (xpvp != NULL) 1409c2aa98e2SPeter Wemm { 1410c2aa98e2SPeter Wemm cataddr(xpvp, NULL, replac, 1411c2aa98e2SPeter Wemm &pvpbuf[sizeof pvpbuf] - replac, 1412c2aa98e2SPeter Wemm '\0'); 1413c2aa98e2SPeter Wemm *++arg_rvp = replac; 1414c2aa98e2SPeter Wemm replac += strlen(replac) + 1; 1415c2aa98e2SPeter Wemm xpvp = NULL; 1416c2aa98e2SPeter Wemm } 1417c2aa98e2SPeter Wemm switch (nodetype) 1418c2aa98e2SPeter Wemm { 1419c2aa98e2SPeter Wemm case CANONHOST: 1420c2aa98e2SPeter Wemm xpvp = rvp; 1421c2aa98e2SPeter Wemm break; 1422c2aa98e2SPeter Wemm 1423c2aa98e2SPeter Wemm case CANONUSER: 1424c2aa98e2SPeter Wemm default_rvp = rvp; 1425c2aa98e2SPeter Wemm break; 1426c2aa98e2SPeter Wemm } 1427c2aa98e2SPeter Wemm } 1428c2aa98e2SPeter Wemm if (*rvp != NULL) 1429c2aa98e2SPeter Wemm *rvp++ = NULL; 1430c2aa98e2SPeter Wemm if (xpvp != NULL) 1431c2aa98e2SPeter Wemm { 1432c2aa98e2SPeter Wemm cataddr(xpvp, NULL, replac, 1433c2aa98e2SPeter Wemm &pvpbuf[sizeof pvpbuf] - replac, 1434c2aa98e2SPeter Wemm '\0'); 1435c2aa98e2SPeter Wemm *++arg_rvp = replac; 1436c2aa98e2SPeter Wemm } 1437c2aa98e2SPeter Wemm *++arg_rvp = NULL; 1438c2aa98e2SPeter Wemm 1439c2aa98e2SPeter Wemm /* save the remainder of the input string */ 1440c2aa98e2SPeter Wemm trsize = (int) (avp - rvp + 1) * sizeof *rvp; 144106f25ae9SGregory Neil Shapiro memmove((char *) pvpb1, (char *) rvp, trsize); 1442c2aa98e2SPeter Wemm 1443c2aa98e2SPeter Wemm /* look it up */ 144406f25ae9SGregory Neil Shapiro cataddr(key_rvp, NULL, cbuf, sizeof cbuf, 144506f25ae9SGregory Neil Shapiro map == NULL ? '\0' : map->s_map.map_spacesub); 144606f25ae9SGregory Neil Shapiro argvect[0] = cbuf; 144706f25ae9SGregory Neil Shapiro replac = map_lookup(map, cbuf, argvect, &rstat, e); 1448c2aa98e2SPeter Wemm 1449c2aa98e2SPeter Wemm /* if no replacement, use default */ 1450c2aa98e2SPeter Wemm if (replac == NULL && default_rvp != NULL) 1451c2aa98e2SPeter Wemm { 1452c2aa98e2SPeter Wemm /* create the default */ 145306f25ae9SGregory Neil Shapiro cataddr(default_rvp, NULL, cbuf, sizeof cbuf, '\0'); 145406f25ae9SGregory Neil Shapiro replac = cbuf; 1455c2aa98e2SPeter Wemm } 1456c2aa98e2SPeter Wemm 1457c2aa98e2SPeter Wemm if (replac == NULL) 1458c2aa98e2SPeter Wemm { 1459c2aa98e2SPeter Wemm xpvp = key_rvp; 1460c2aa98e2SPeter Wemm } 1461c2aa98e2SPeter Wemm else if (*replac == '\0') 1462c2aa98e2SPeter Wemm { 1463c2aa98e2SPeter Wemm /* null replacement */ 1464c2aa98e2SPeter Wemm nullpvp[0] = NULL; 1465c2aa98e2SPeter Wemm xpvp = nullpvp; 1466c2aa98e2SPeter Wemm } 1467c2aa98e2SPeter Wemm else 1468c2aa98e2SPeter Wemm { 1469c2aa98e2SPeter Wemm /* scan the new replacement */ 1470c2aa98e2SPeter Wemm xpvp = prescan(replac, '\0', pvpbuf, 1471c2aa98e2SPeter Wemm sizeof pvpbuf, NULL, NULL); 1472c2aa98e2SPeter Wemm if (xpvp == NULL) 1473c2aa98e2SPeter Wemm { 1474c2aa98e2SPeter Wemm /* prescan already printed error */ 1475c2aa98e2SPeter Wemm return EX_DATAERR; 1476c2aa98e2SPeter Wemm } 1477c2aa98e2SPeter Wemm } 1478c2aa98e2SPeter Wemm 1479c2aa98e2SPeter Wemm /* append it to the token list */ 1480c2aa98e2SPeter Wemm for (avp = hbrvp; *xpvp != NULL; xpvp++) 1481c2aa98e2SPeter Wemm { 148240266059SGregory Neil Shapiro *avp++ = sm_rpool_strdup_x(e->e_rpool, *xpvp); 148340266059SGregory Neil Shapiro if (avp >= &npvp[maxatom]) 1484c2aa98e2SPeter Wemm goto toolong; 1485c2aa98e2SPeter Wemm } 1486c2aa98e2SPeter Wemm 1487c2aa98e2SPeter Wemm /* restore the old trailing information */ 1488c2aa98e2SPeter Wemm rvp = avp - 1; 1489c2aa98e2SPeter Wemm for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; ) 149040266059SGregory Neil Shapiro if (avp >= &npvp[maxatom]) 1491c2aa98e2SPeter Wemm goto toolong; 1492c2aa98e2SPeter Wemm } 1493c2aa98e2SPeter Wemm 1494c2aa98e2SPeter Wemm /* 1495c2aa98e2SPeter Wemm ** Check for subroutine calls. 1496c2aa98e2SPeter Wemm */ 1497c2aa98e2SPeter Wemm 149806f25ae9SGregory Neil Shapiro status = callsubr(npvp, reclevel, e); 149906f25ae9SGregory Neil Shapiro if (rstat == EX_OK || status == EX_TEMPFAIL) 150006f25ae9SGregory Neil Shapiro rstat = status; 1501c2aa98e2SPeter Wemm 1502c2aa98e2SPeter Wemm /* copy vector back into original space. */ 1503c2aa98e2SPeter Wemm for (avp = npvp; *avp++ != NULL;) 1504c2aa98e2SPeter Wemm continue; 150506f25ae9SGregory Neil Shapiro memmove((char *) pvp, (char *) npvp, 1506c2aa98e2SPeter Wemm (int) (avp - npvp) * sizeof *avp); 1507c2aa98e2SPeter Wemm 1508c2aa98e2SPeter Wemm if (tTd(21, 4)) 1509c2aa98e2SPeter Wemm { 151040266059SGregory Neil Shapiro sm_dprintf("rewritten as:"); 1511c2aa98e2SPeter Wemm printav(pvp); 1512c2aa98e2SPeter Wemm } 1513c2aa98e2SPeter Wemm } 1514c2aa98e2SPeter Wemm 151506f25ae9SGregory Neil Shapiro if (OpMode == MD_TEST) 1516c2aa98e2SPeter Wemm { 151740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 151840266059SGregory Neil Shapiro "%s%-16.16s returns:", prefix, rulename); 1519c2aa98e2SPeter Wemm printav(pvp); 1520c2aa98e2SPeter Wemm } 152106f25ae9SGregory Neil Shapiro else if (tTd(21, 1)) 152206f25ae9SGregory Neil Shapiro { 152340266059SGregory Neil Shapiro sm_dprintf("%s%-16.16s returns:", prefix, rulename); 152406f25ae9SGregory Neil Shapiro printav(pvp); 152506f25ae9SGregory Neil Shapiro } 1526c2aa98e2SPeter Wemm return rstat; 1527c2aa98e2SPeter Wemm } 152840266059SGregory Neil Shapiro /* 1529c2aa98e2SPeter Wemm ** CALLSUBR -- call subroutines in rewrite vector 1530c2aa98e2SPeter Wemm ** 1531c2aa98e2SPeter Wemm ** Parameters: 1532c2aa98e2SPeter Wemm ** pvp -- pointer to token vector. 1533c2aa98e2SPeter Wemm ** reclevel -- the current recursion level. 1534c2aa98e2SPeter Wemm ** e -- the current envelope. 1535c2aa98e2SPeter Wemm ** 1536c2aa98e2SPeter Wemm ** Returns: 1537c2aa98e2SPeter Wemm ** The status from the subroutine call. 1538c2aa98e2SPeter Wemm ** 1539c2aa98e2SPeter Wemm ** Side Effects: 1540c2aa98e2SPeter Wemm ** pvp is modified. 1541c2aa98e2SPeter Wemm */ 1542c2aa98e2SPeter Wemm 154306f25ae9SGregory Neil Shapiro static int 1544c2aa98e2SPeter Wemm callsubr(pvp, reclevel, e) 1545c2aa98e2SPeter Wemm char **pvp; 1546c2aa98e2SPeter Wemm int reclevel; 1547c2aa98e2SPeter Wemm ENVELOPE *e; 1548c2aa98e2SPeter Wemm { 1549c2aa98e2SPeter Wemm char **avp; 1550c2aa98e2SPeter Wemm register int i; 155140266059SGregory Neil Shapiro int subr, j; 155240266059SGregory Neil Shapiro int nsubr; 155306f25ae9SGregory Neil Shapiro int status; 1554c2aa98e2SPeter Wemm int rstat = EX_OK; 155540266059SGregory Neil Shapiro #define MAX_SUBR 16 155640266059SGregory Neil Shapiro int subrnumber[MAX_SUBR]; 155740266059SGregory Neil Shapiro int subrindex[MAX_SUBR]; 1558c2aa98e2SPeter Wemm 155940266059SGregory Neil Shapiro nsubr = 0; 156040266059SGregory Neil Shapiro 156140266059SGregory Neil Shapiro /* 156240266059SGregory Neil Shapiro ** Look for subroutine calls in pvp, collect them into subr*[] 156340266059SGregory Neil Shapiro ** We will perform the calls in the next loop, because we will 156440266059SGregory Neil Shapiro ** call the "last" subroutine first to avoid recursive calls 156540266059SGregory Neil Shapiro ** and too much copying. 156640266059SGregory Neil Shapiro */ 156740266059SGregory Neil Shapiro 156840266059SGregory Neil Shapiro for (avp = pvp, j = 0; *avp != NULL; avp++, j++) 1569c2aa98e2SPeter Wemm { 1570c2aa98e2SPeter Wemm if ((**avp & 0377) == CALLSUBR && avp[1] != NULL) 1571c2aa98e2SPeter Wemm { 1572c2aa98e2SPeter Wemm stripquotes(avp[1]); 1573c2aa98e2SPeter Wemm subr = strtorwset(avp[1], NULL, ST_FIND); 1574c2aa98e2SPeter Wemm if (subr < 0) 1575c2aa98e2SPeter Wemm { 157640266059SGregory Neil Shapiro syserr("554 5.3.5 Unknown ruleset %s", avp[1]); 1577c2aa98e2SPeter Wemm return EX_CONFIG; 1578c2aa98e2SPeter Wemm } 1579c2aa98e2SPeter Wemm 1580c2aa98e2SPeter Wemm /* 158140266059SGregory Neil Shapiro ** XXX instead of doing this we could optimize 158240266059SGregory Neil Shapiro ** the rules after reading them: just remove 158340266059SGregory Neil Shapiro ** calls to empty rulesets 1584c2aa98e2SPeter Wemm */ 1585c2aa98e2SPeter Wemm 158640266059SGregory Neil Shapiro /* subroutine is an empty ruleset? don't call it */ 158740266059SGregory Neil Shapiro if (RewriteRules[subr] == NULL) 158840266059SGregory Neil Shapiro { 158940266059SGregory Neil Shapiro if (tTd(21, 3)) 159040266059SGregory Neil Shapiro sm_dprintf("-----skip subr %s (%d)\n", 159140266059SGregory Neil Shapiro avp[1], subr); 1592c2aa98e2SPeter Wemm for (i = 2; avp[i] != NULL; i++) 159340266059SGregory Neil Shapiro avp[i - 2] = avp[i]; 159440266059SGregory Neil Shapiro avp[i - 2] = NULL; 159540266059SGregory Neil Shapiro continue; 159640266059SGregory Neil Shapiro } 159740266059SGregory Neil Shapiro if (++nsubr >= MAX_SUBR) 159840266059SGregory Neil Shapiro { 159940266059SGregory Neil Shapiro syserr("554 5.3.0 Too many subroutine calls (%d max)", 160040266059SGregory Neil Shapiro MAX_SUBR); 160140266059SGregory Neil Shapiro return EX_CONFIG; 160240266059SGregory Neil Shapiro } 160340266059SGregory Neil Shapiro subrnumber[nsubr] = subr; 160440266059SGregory Neil Shapiro subrindex[nsubr] = j; 160540266059SGregory Neil Shapiro } 160640266059SGregory Neil Shapiro } 1607c2aa98e2SPeter Wemm 160840266059SGregory Neil Shapiro /* 160940266059SGregory Neil Shapiro ** Perform the actual subroutines calls, "last" one first, i.e., 161040266059SGregory Neil Shapiro ** go from the right to the left through all calls, 161140266059SGregory Neil Shapiro ** do the rewriting in place. 161240266059SGregory Neil Shapiro */ 161340266059SGregory Neil Shapiro 161440266059SGregory Neil Shapiro for (; nsubr > 0; nsubr--) 161540266059SGregory Neil Shapiro { 161640266059SGregory Neil Shapiro subr = subrnumber[nsubr]; 161740266059SGregory Neil Shapiro avp = pvp + subrindex[nsubr]; 161840266059SGregory Neil Shapiro 161940266059SGregory Neil Shapiro /* remove the subroutine call and name */ 162040266059SGregory Neil Shapiro for (i = 2; avp[i] != NULL; i++) 162140266059SGregory Neil Shapiro avp[i - 2] = avp[i]; 162240266059SGregory Neil Shapiro avp[i - 2] = NULL; 1623c2aa98e2SPeter Wemm 1624c2aa98e2SPeter Wemm /* 1625c2aa98e2SPeter Wemm ** Now we need to call the ruleset specified for 162640266059SGregory Neil Shapiro ** the subroutine. we can do this inplace since 162740266059SGregory Neil Shapiro ** we call the "last" subroutine first. 1628c2aa98e2SPeter Wemm */ 1629c2aa98e2SPeter Wemm 163040266059SGregory Neil Shapiro status = rewrite(avp, subr, reclevel, e, 163140266059SGregory Neil Shapiro MAXATOM - subrindex[nsubr]); 163240266059SGregory Neil Shapiro if (status != EX_OK && status != EX_TEMPFAIL) 163340266059SGregory Neil Shapiro return status; 163406f25ae9SGregory Neil Shapiro if (rstat == EX_OK || status == EX_TEMPFAIL) 163506f25ae9SGregory Neil Shapiro rstat = status; 1636c2aa98e2SPeter Wemm } 1637c2aa98e2SPeter Wemm return rstat; 1638c2aa98e2SPeter Wemm } 163940266059SGregory Neil Shapiro /* 1640c2aa98e2SPeter Wemm ** MAP_LOOKUP -- do lookup in map 1641c2aa98e2SPeter Wemm ** 1642c2aa98e2SPeter Wemm ** Parameters: 164340266059SGregory Neil Shapiro ** smap -- the map to use for the lookup. 1644c2aa98e2SPeter Wemm ** key -- the key to look up. 1645c2aa98e2SPeter Wemm ** argvect -- arguments to pass to the map lookup. 1646c2aa98e2SPeter Wemm ** pstat -- a pointer to an integer in which to store the 1647c2aa98e2SPeter Wemm ** status from the lookup. 1648c2aa98e2SPeter Wemm ** e -- the current envelope. 1649c2aa98e2SPeter Wemm ** 1650c2aa98e2SPeter Wemm ** Returns: 1651c2aa98e2SPeter Wemm ** The result of the lookup. 1652c2aa98e2SPeter Wemm ** NULL -- if there was no data for the given key. 1653c2aa98e2SPeter Wemm */ 1654c2aa98e2SPeter Wemm 165506f25ae9SGregory Neil Shapiro static char * 165606f25ae9SGregory Neil Shapiro map_lookup(smap, key, argvect, pstat, e) 165706f25ae9SGregory Neil Shapiro STAB *smap; 1658c2aa98e2SPeter Wemm char key[]; 1659c2aa98e2SPeter Wemm char **argvect; 1660c2aa98e2SPeter Wemm int *pstat; 1661c2aa98e2SPeter Wemm ENVELOPE *e; 1662c2aa98e2SPeter Wemm { 166306f25ae9SGregory Neil Shapiro auto int status = EX_OK; 166406f25ae9SGregory Neil Shapiro MAP *map; 1665c2aa98e2SPeter Wemm char *replac; 1666c2aa98e2SPeter Wemm 166706f25ae9SGregory Neil Shapiro if (smap == NULL) 166806f25ae9SGregory Neil Shapiro return NULL; 166906f25ae9SGregory Neil Shapiro 167006f25ae9SGregory Neil Shapiro map = &smap->s_map; 167106f25ae9SGregory Neil Shapiro DYNOPENMAP(map); 167206f25ae9SGregory Neil Shapiro 167306f25ae9SGregory Neil Shapiro if (e->e_sendmode == SM_DEFER && 167406f25ae9SGregory Neil Shapiro bitset(MF_DEFER, map->map_mflags)) 1675c2aa98e2SPeter Wemm { 1676c2aa98e2SPeter Wemm /* don't do any map lookups */ 1677c2aa98e2SPeter Wemm if (tTd(60, 1)) 167840266059SGregory Neil Shapiro sm_dprintf("map_lookup(%s, %s) => DEFERRED\n", 167906f25ae9SGregory Neil Shapiro smap->s_name, key); 1680c2aa98e2SPeter Wemm *pstat = EX_TEMPFAIL; 1681c2aa98e2SPeter Wemm return NULL; 1682c2aa98e2SPeter Wemm } 1683c2aa98e2SPeter Wemm 168406f25ae9SGregory Neil Shapiro if (!bitset(MF_KEEPQUOTES, map->map_mflags)) 1685c2aa98e2SPeter Wemm stripquotes(key); 1686c2aa98e2SPeter Wemm 1687c2aa98e2SPeter Wemm if (tTd(60, 1)) 1688065a643dSPeter Wemm { 168940266059SGregory Neil Shapiro sm_dprintf("map_lookup(%s, %s", smap->s_name, key); 1690065a643dSPeter Wemm if (tTd(60, 5)) 1691065a643dSPeter Wemm { 1692065a643dSPeter Wemm int i; 1693065a643dSPeter Wemm 1694065a643dSPeter Wemm for (i = 0; argvect[i] != NULL; i++) 169540266059SGregory Neil Shapiro sm_dprintf(", %%%d=%s", i, argvect[i]); 1696065a643dSPeter Wemm } 169740266059SGregory Neil Shapiro sm_dprintf(") => "); 1698065a643dSPeter Wemm } 169906f25ae9SGregory Neil Shapiro replac = (*map->map_class->map_lookup)(map, key, argvect, &status); 1700c2aa98e2SPeter Wemm if (tTd(60, 1)) 170140266059SGregory Neil Shapiro sm_dprintf("%s (%d)\n", 1702c2aa98e2SPeter Wemm replac != NULL ? replac : "NOT FOUND", 170306f25ae9SGregory Neil Shapiro status); 1704c2aa98e2SPeter Wemm 170506f25ae9SGregory Neil Shapiro /* should recover if status == EX_TEMPFAIL */ 170606f25ae9SGregory Neil Shapiro if (status == EX_TEMPFAIL && !bitset(MF_NODEFER, map->map_mflags)) 1707c2aa98e2SPeter Wemm { 1708c2aa98e2SPeter Wemm *pstat = EX_TEMPFAIL; 1709c2aa98e2SPeter Wemm if (tTd(60, 1)) 171040266059SGregory Neil Shapiro sm_dprintf("map_lookup(%s, %s) tempfail: errno=%d\n", 171106f25ae9SGregory Neil Shapiro smap->s_name, key, errno); 1712c2aa98e2SPeter Wemm if (e->e_message == NULL) 1713c2aa98e2SPeter Wemm { 1714c2aa98e2SPeter Wemm char mbuf[320]; 1715c2aa98e2SPeter Wemm 171640266059SGregory Neil Shapiro (void) sm_snprintf(mbuf, sizeof mbuf, 1717c2aa98e2SPeter Wemm "%.80s map: lookup (%s): deferred", 171806f25ae9SGregory Neil Shapiro smap->s_name, 1719c2aa98e2SPeter Wemm shortenstring(key, MAXSHORTSTR)); 172040266059SGregory Neil Shapiro e->e_message = sm_rpool_strdup_x(e->e_rpool, mbuf); 1721c2aa98e2SPeter Wemm } 1722c2aa98e2SPeter Wemm } 172306f25ae9SGregory Neil Shapiro if (status == EX_TEMPFAIL && map->map_tapp != NULL) 1724c2aa98e2SPeter Wemm { 172506f25ae9SGregory Neil Shapiro size_t i = strlen(key) + strlen(map->map_tapp) + 1; 1726c2aa98e2SPeter Wemm static char *rwbuf = NULL; 1727c2aa98e2SPeter Wemm static size_t rwbuflen = 0; 1728c2aa98e2SPeter Wemm 1729c2aa98e2SPeter Wemm if (i > rwbuflen) 1730c2aa98e2SPeter Wemm { 1731c2aa98e2SPeter Wemm if (rwbuf != NULL) 17328774250cSGregory Neil Shapiro sm_free(rwbuf); 1733c2aa98e2SPeter Wemm rwbuflen = i; 173440266059SGregory Neil Shapiro rwbuf = (char *) sm_pmalloc_x(rwbuflen); 1735c2aa98e2SPeter Wemm } 173640266059SGregory Neil Shapiro (void) sm_strlcpyn(rwbuf, rwbuflen, 2, key, map->map_tapp); 1737c2aa98e2SPeter Wemm if (tTd(60, 4)) 173840266059SGregory Neil Shapiro sm_dprintf("map_lookup tempfail: returning \"%s\"\n", 1739c2aa98e2SPeter Wemm rwbuf); 1740c2aa98e2SPeter Wemm return rwbuf; 1741c2aa98e2SPeter Wemm } 1742c2aa98e2SPeter Wemm return replac; 1743c2aa98e2SPeter Wemm } 174440266059SGregory Neil Shapiro /* 174506f25ae9SGregory Neil Shapiro ** INITERRMAILERS -- initialize error and discard mailers 174606f25ae9SGregory Neil Shapiro ** 174706f25ae9SGregory Neil Shapiro ** Parameters: 174806f25ae9SGregory Neil Shapiro ** none. 174906f25ae9SGregory Neil Shapiro ** 175006f25ae9SGregory Neil Shapiro ** Returns: 175106f25ae9SGregory Neil Shapiro ** none. 175206f25ae9SGregory Neil Shapiro ** 175306f25ae9SGregory Neil Shapiro ** Side Effects: 175406f25ae9SGregory Neil Shapiro ** initializes error and discard mailers. 175506f25ae9SGregory Neil Shapiro */ 175606f25ae9SGregory Neil Shapiro 175706f25ae9SGregory Neil Shapiro static MAILER discardmailer; 175806f25ae9SGregory Neil Shapiro static MAILER errormailer; 175906f25ae9SGregory Neil Shapiro static char *discardargv[] = { "DISCARD", NULL }; 176006f25ae9SGregory Neil Shapiro static char *errorargv[] = { "ERROR", NULL }; 176106f25ae9SGregory Neil Shapiro 176206f25ae9SGregory Neil Shapiro void 176306f25ae9SGregory Neil Shapiro initerrmailers() 176406f25ae9SGregory Neil Shapiro { 176506f25ae9SGregory Neil Shapiro if (discardmailer.m_name == NULL) 176606f25ae9SGregory Neil Shapiro { 176706f25ae9SGregory Neil Shapiro /* initialize the discard mailer */ 176806f25ae9SGregory Neil Shapiro discardmailer.m_name = "*discard*"; 176906f25ae9SGregory Neil Shapiro discardmailer.m_mailer = "DISCARD"; 177006f25ae9SGregory Neil Shapiro discardmailer.m_argv = discardargv; 177106f25ae9SGregory Neil Shapiro } 177206f25ae9SGregory Neil Shapiro if (errormailer.m_name == NULL) 177306f25ae9SGregory Neil Shapiro { 177406f25ae9SGregory Neil Shapiro /* initialize the bogus mailer */ 177506f25ae9SGregory Neil Shapiro errormailer.m_name = "*error*"; 177606f25ae9SGregory Neil Shapiro errormailer.m_mailer = "ERROR"; 177706f25ae9SGregory Neil Shapiro errormailer.m_argv = errorargv; 177806f25ae9SGregory Neil Shapiro } 177906f25ae9SGregory Neil Shapiro } 178040266059SGregory Neil Shapiro /* 1781c2aa98e2SPeter Wemm ** BUILDADDR -- build address from token vector. 1782c2aa98e2SPeter Wemm ** 1783c2aa98e2SPeter Wemm ** Parameters: 1784c2aa98e2SPeter Wemm ** tv -- token vector. 1785c2aa98e2SPeter Wemm ** a -- pointer to address descriptor to fill. 1786c2aa98e2SPeter Wemm ** If NULL, one will be allocated. 1787c2aa98e2SPeter Wemm ** flags -- info regarding whether this is a sender or 1788c2aa98e2SPeter Wemm ** a recipient. 1789c2aa98e2SPeter Wemm ** e -- the current envelope. 1790c2aa98e2SPeter Wemm ** 1791c2aa98e2SPeter Wemm ** Returns: 1792c2aa98e2SPeter Wemm ** NULL if there was an error. 1793c2aa98e2SPeter Wemm ** 'a' otherwise. 1794c2aa98e2SPeter Wemm ** 1795c2aa98e2SPeter Wemm ** Side Effects: 1796c2aa98e2SPeter Wemm ** fills in 'a' 1797c2aa98e2SPeter Wemm */ 1798c2aa98e2SPeter Wemm 179906f25ae9SGregory Neil Shapiro static struct errcodes 1800c2aa98e2SPeter Wemm { 1801c2aa98e2SPeter Wemm char *ec_name; /* name of error code */ 1802c2aa98e2SPeter Wemm int ec_code; /* numeric code */ 1803c2aa98e2SPeter Wemm } ErrorCodes[] = 1804c2aa98e2SPeter Wemm { 1805c2aa98e2SPeter Wemm { "usage", EX_USAGE }, 1806c2aa98e2SPeter Wemm { "nouser", EX_NOUSER }, 1807c2aa98e2SPeter Wemm { "nohost", EX_NOHOST }, 1808c2aa98e2SPeter Wemm { "unavailable", EX_UNAVAILABLE }, 1809c2aa98e2SPeter Wemm { "software", EX_SOFTWARE }, 1810c2aa98e2SPeter Wemm { "tempfail", EX_TEMPFAIL }, 1811c2aa98e2SPeter Wemm { "protocol", EX_PROTOCOL }, 1812c2aa98e2SPeter Wemm { "config", EX_CONFIG }, 1813c2aa98e2SPeter Wemm { NULL, EX_UNAVAILABLE } 1814c2aa98e2SPeter Wemm }; 1815c2aa98e2SPeter Wemm 181606f25ae9SGregory Neil Shapiro static ADDRESS * 1817c2aa98e2SPeter Wemm buildaddr(tv, a, flags, e) 1818c2aa98e2SPeter Wemm register char **tv; 1819c2aa98e2SPeter Wemm register ADDRESS *a; 1820c2aa98e2SPeter Wemm int flags; 1821c2aa98e2SPeter Wemm register ENVELOPE *e; 1822c2aa98e2SPeter Wemm { 1823c2aa98e2SPeter Wemm struct mailer **mp; 1824c2aa98e2SPeter Wemm register struct mailer *m; 1825c2aa98e2SPeter Wemm register char *p; 1826c2aa98e2SPeter Wemm char *mname; 1827c2aa98e2SPeter Wemm char **hostp; 1828c2aa98e2SPeter Wemm char hbuf[MAXNAME + 1]; 1829065a643dSPeter Wemm static char ubuf[MAXNAME + 2]; 1830c2aa98e2SPeter Wemm 1831c2aa98e2SPeter Wemm if (tTd(24, 5)) 1832c2aa98e2SPeter Wemm { 183340266059SGregory Neil Shapiro sm_dprintf("buildaddr, flags=%x, tv=", flags); 1834c2aa98e2SPeter Wemm printav(tv); 1835c2aa98e2SPeter Wemm } 1836c2aa98e2SPeter Wemm 1837c2aa98e2SPeter Wemm if (a == NULL) 183840266059SGregory Neil Shapiro a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof *a); 183906f25ae9SGregory Neil Shapiro memset((char *) a, '\0', sizeof *a); 184006f25ae9SGregory Neil Shapiro hbuf[0] = '\0'; 1841c2aa98e2SPeter Wemm 1842c2aa98e2SPeter Wemm /* set up default error return flags */ 1843c2aa98e2SPeter Wemm a->q_flags |= DefaultNotify; 1844c2aa98e2SPeter Wemm 1845c2aa98e2SPeter Wemm /* figure out what net/mailer to use */ 1846c2aa98e2SPeter Wemm if (*tv == NULL || (**tv & 0377) != CANONNET) 1847c2aa98e2SPeter Wemm { 184806f25ae9SGregory Neil Shapiro syserr("554 5.3.5 buildaddr: no mailer in parsed address"); 1849c2aa98e2SPeter Wemm badaddr: 185006f25ae9SGregory Neil Shapiro if (ExitStat == EX_TEMPFAIL) 185106f25ae9SGregory Neil Shapiro a->q_state = QS_QUEUEUP; 185206f25ae9SGregory Neil Shapiro else 1853c2aa98e2SPeter Wemm { 185406f25ae9SGregory Neil Shapiro a->q_state = QS_BADADDR; 185506f25ae9SGregory Neil Shapiro a->q_mailer = &errormailer; 1856c2aa98e2SPeter Wemm } 1857c2aa98e2SPeter Wemm return a; 1858c2aa98e2SPeter Wemm } 1859c2aa98e2SPeter Wemm mname = *++tv; 1860c2aa98e2SPeter Wemm 1861c2aa98e2SPeter Wemm /* extract host and user portions */ 1862c2aa98e2SPeter Wemm if (*++tv != NULL && (**tv & 0377) == CANONHOST) 1863c2aa98e2SPeter Wemm hostp = ++tv; 1864c2aa98e2SPeter Wemm else 1865c2aa98e2SPeter Wemm hostp = NULL; 1866c2aa98e2SPeter Wemm while (*tv != NULL && (**tv & 0377) != CANONUSER) 1867c2aa98e2SPeter Wemm tv++; 1868c2aa98e2SPeter Wemm if (*tv == NULL) 1869c2aa98e2SPeter Wemm { 187006f25ae9SGregory Neil Shapiro syserr("554 5.3.5 buildaddr: no user"); 1871c2aa98e2SPeter Wemm goto badaddr; 1872c2aa98e2SPeter Wemm } 1873c2aa98e2SPeter Wemm if (tv == hostp) 1874c2aa98e2SPeter Wemm hostp = NULL; 1875c2aa98e2SPeter Wemm else if (hostp != NULL) 1876c2aa98e2SPeter Wemm cataddr(hostp, tv - 1, hbuf, sizeof hbuf, '\0'); 1877c2aa98e2SPeter Wemm cataddr(++tv, NULL, ubuf, sizeof ubuf, ' '); 1878c2aa98e2SPeter Wemm 1879c2aa98e2SPeter Wemm /* save away the host name */ 188040266059SGregory Neil Shapiro if (sm_strcasecmp(mname, "error") == 0) 1881c2aa98e2SPeter Wemm { 188206f25ae9SGregory Neil Shapiro /* Set up triplet for use by -bv */ 188306f25ae9SGregory Neil Shapiro a->q_mailer = &errormailer; 188440266059SGregory Neil Shapiro a->q_user = sm_rpool_strdup_x(e->e_rpool, ubuf); 188540266059SGregory Neil Shapiro /* XXX wrong place? */ 188606f25ae9SGregory Neil Shapiro 1887c2aa98e2SPeter Wemm if (hostp != NULL) 1888c2aa98e2SPeter Wemm { 1889c2aa98e2SPeter Wemm register struct errcodes *ep; 1890c2aa98e2SPeter Wemm 189140266059SGregory Neil Shapiro a->q_host = sm_rpool_strdup_x(e->e_rpool, hbuf); 1892c2aa98e2SPeter Wemm if (strchr(hbuf, '.') != NULL) 1893c2aa98e2SPeter Wemm { 189440266059SGregory Neil Shapiro a->q_status = sm_rpool_strdup_x(e->e_rpool, 189540266059SGregory Neil Shapiro hbuf); 1896c2aa98e2SPeter Wemm setstat(dsntoexitstat(hbuf)); 1897c2aa98e2SPeter Wemm } 1898c2aa98e2SPeter Wemm else if (isascii(hbuf[0]) && isdigit(hbuf[0])) 1899c2aa98e2SPeter Wemm { 1900c2aa98e2SPeter Wemm setstat(atoi(hbuf)); 1901c2aa98e2SPeter Wemm } 1902c2aa98e2SPeter Wemm else 1903c2aa98e2SPeter Wemm { 1904c2aa98e2SPeter Wemm for (ep = ErrorCodes; ep->ec_name != NULL; ep++) 190540266059SGregory Neil Shapiro if (sm_strcasecmp(ep->ec_name, hbuf) == 0) 1906c2aa98e2SPeter Wemm break; 1907c2aa98e2SPeter Wemm setstat(ep->ec_code); 1908c2aa98e2SPeter Wemm } 1909c2aa98e2SPeter Wemm } 1910c2aa98e2SPeter Wemm else 191106f25ae9SGregory Neil Shapiro { 191206f25ae9SGregory Neil Shapiro a->q_host = NULL; 1913c2aa98e2SPeter Wemm setstat(EX_UNAVAILABLE); 1914c2aa98e2SPeter Wemm } 191506f25ae9SGregory Neil Shapiro stripquotes(ubuf); 191606f25ae9SGregory Neil Shapiro if (ISSMTPCODE(ubuf) && ubuf[3] == ' ') 191706f25ae9SGregory Neil Shapiro { 191806f25ae9SGregory Neil Shapiro char fmt[16]; 191906f25ae9SGregory Neil Shapiro int off; 192006f25ae9SGregory Neil Shapiro 192106f25ae9SGregory Neil Shapiro if ((off = isenhsc(ubuf + 4, ' ')) > 0) 192206f25ae9SGregory Neil Shapiro { 192306f25ae9SGregory Neil Shapiro ubuf[off + 4] = '\0'; 192406f25ae9SGregory Neil Shapiro off += 5; 1925c2aa98e2SPeter Wemm } 1926c2aa98e2SPeter Wemm else 1927c2aa98e2SPeter Wemm { 192806f25ae9SGregory Neil Shapiro off = 4; 192906f25ae9SGregory Neil Shapiro ubuf[3] = '\0'; 193006f25ae9SGregory Neil Shapiro } 193140266059SGregory Neil Shapiro (void) sm_strlcpyn(fmt, sizeof fmt, 2, ubuf, " %s"); 193206f25ae9SGregory Neil Shapiro if (off > 4) 193306f25ae9SGregory Neil Shapiro usrerr(fmt, ubuf + off); 193406f25ae9SGregory Neil Shapiro else if (isenhsc(hbuf, '\0') > 0) 193506f25ae9SGregory Neil Shapiro usrerrenh(hbuf, fmt, ubuf + off); 193606f25ae9SGregory Neil Shapiro else 193706f25ae9SGregory Neil Shapiro usrerr(fmt, ubuf + off); 193806f25ae9SGregory Neil Shapiro /* XXX ubuf[off - 1] = ' '; */ 193906f25ae9SGregory Neil Shapiro } 194006f25ae9SGregory Neil Shapiro else 194106f25ae9SGregory Neil Shapiro { 194206f25ae9SGregory Neil Shapiro usrerr("553 5.3.0 %s", ubuf); 1943c2aa98e2SPeter Wemm } 1944c2aa98e2SPeter Wemm goto badaddr; 1945c2aa98e2SPeter Wemm } 1946c2aa98e2SPeter Wemm 1947c2aa98e2SPeter Wemm for (mp = Mailer; (m = *mp++) != NULL; ) 1948c2aa98e2SPeter Wemm { 194940266059SGregory Neil Shapiro if (sm_strcasecmp(m->m_name, mname) == 0) 1950c2aa98e2SPeter Wemm break; 1951c2aa98e2SPeter Wemm } 1952c2aa98e2SPeter Wemm if (m == NULL) 1953c2aa98e2SPeter Wemm { 195406f25ae9SGregory Neil Shapiro syserr("554 5.3.5 buildaddr: unknown mailer %s", mname); 1955c2aa98e2SPeter Wemm goto badaddr; 1956c2aa98e2SPeter Wemm } 1957c2aa98e2SPeter Wemm a->q_mailer = m; 1958c2aa98e2SPeter Wemm 1959c2aa98e2SPeter Wemm /* figure out what host (if any) */ 1960c2aa98e2SPeter Wemm if (hostp == NULL) 1961c2aa98e2SPeter Wemm { 1962c2aa98e2SPeter Wemm if (!bitnset(M_LOCALMAILER, m->m_flags)) 1963c2aa98e2SPeter Wemm { 196406f25ae9SGregory Neil Shapiro syserr("554 5.3.5 buildaddr: no host"); 1965c2aa98e2SPeter Wemm goto badaddr; 1966c2aa98e2SPeter Wemm } 1967c2aa98e2SPeter Wemm a->q_host = NULL; 1968c2aa98e2SPeter Wemm } 1969c2aa98e2SPeter Wemm else 197040266059SGregory Neil Shapiro a->q_host = sm_rpool_strdup_x(e->e_rpool, hbuf); 1971c2aa98e2SPeter Wemm 1972c2aa98e2SPeter Wemm /* figure out the user */ 1973c2aa98e2SPeter Wemm p = ubuf; 1974c2aa98e2SPeter Wemm if (bitnset(M_CHECKUDB, m->m_flags) && *p == '@') 1975c2aa98e2SPeter Wemm { 1976c2aa98e2SPeter Wemm p++; 1977c2aa98e2SPeter Wemm tv++; 1978c2aa98e2SPeter Wemm a->q_flags |= QNOTREMOTE; 1979c2aa98e2SPeter Wemm } 1980c2aa98e2SPeter Wemm 1981c2aa98e2SPeter Wemm /* do special mapping for local mailer */ 1982c2aa98e2SPeter Wemm if (*p == '"') 1983c2aa98e2SPeter Wemm p++; 1984c2aa98e2SPeter Wemm if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags)) 1985c2aa98e2SPeter Wemm a->q_mailer = m = ProgMailer; 1986c2aa98e2SPeter Wemm else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags)) 1987c2aa98e2SPeter Wemm a->q_mailer = m = FileMailer; 1988c2aa98e2SPeter Wemm else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags)) 1989c2aa98e2SPeter Wemm { 1990c2aa98e2SPeter Wemm /* may be :include: */ 1991c2aa98e2SPeter Wemm stripquotes(ubuf); 199240266059SGregory Neil Shapiro if (sm_strncasecmp(ubuf, ":include:", 9) == 0) 1993c2aa98e2SPeter Wemm { 1994c2aa98e2SPeter Wemm /* if :include:, don't need further rewriting */ 1995c2aa98e2SPeter Wemm a->q_mailer = m = InclMailer; 199640266059SGregory Neil Shapiro a->q_user = sm_rpool_strdup_x(e->e_rpool, &ubuf[9]); 1997c2aa98e2SPeter Wemm return a; 1998c2aa98e2SPeter Wemm } 1999c2aa98e2SPeter Wemm } 2000c2aa98e2SPeter Wemm 2001c2aa98e2SPeter Wemm /* rewrite according recipient mailer rewriting rules */ 200240266059SGregory Neil Shapiro macdefine(&e->e_macro, A_PERM, 'h', a->q_host); 200306f25ae9SGregory Neil Shapiro 200440266059SGregory Neil Shapiro if (ConfigLevel >= 10 || 200506f25ae9SGregory Neil Shapiro !bitset(RF_SENDERADDR|RF_HEADERADDR, flags)) 2006c2aa98e2SPeter Wemm { 2007c2aa98e2SPeter Wemm /* sender addresses done later */ 200840266059SGregory Neil Shapiro (void) REWRITE(tv, 2, e); 2009c2aa98e2SPeter Wemm if (m->m_re_rwset > 0) 201040266059SGregory Neil Shapiro (void) REWRITE(tv, m->m_re_rwset, e); 2011c2aa98e2SPeter Wemm } 201240266059SGregory Neil Shapiro (void) REWRITE(tv, 4, e); 2013c2aa98e2SPeter Wemm 2014c2aa98e2SPeter Wemm /* save the result for the command line/RCPT argument */ 2015c2aa98e2SPeter Wemm cataddr(tv, NULL, ubuf, sizeof ubuf, '\0'); 201640266059SGregory Neil Shapiro a->q_user = sm_rpool_strdup_x(e->e_rpool, ubuf); 2017c2aa98e2SPeter Wemm 2018c2aa98e2SPeter Wemm /* 2019c2aa98e2SPeter Wemm ** Do mapping to lower case as requested by mailer 2020c2aa98e2SPeter Wemm */ 2021c2aa98e2SPeter Wemm 2022c2aa98e2SPeter Wemm if (a->q_host != NULL && !bitnset(M_HST_UPPER, m->m_flags)) 2023c2aa98e2SPeter Wemm makelower(a->q_host); 2024c2aa98e2SPeter Wemm if (!bitnset(M_USR_UPPER, m->m_flags)) 2025c2aa98e2SPeter Wemm makelower(a->q_user); 2026c2aa98e2SPeter Wemm 2027c2aa98e2SPeter Wemm if (tTd(24, 6)) 2028c2aa98e2SPeter Wemm { 202940266059SGregory Neil Shapiro sm_dprintf("buildaddr => "); 203040266059SGregory Neil Shapiro printaddr(a, false); 2031c2aa98e2SPeter Wemm } 2032c2aa98e2SPeter Wemm return a; 2033c2aa98e2SPeter Wemm } 203440266059SGregory Neil Shapiro /* 2035c2aa98e2SPeter Wemm ** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs) 2036c2aa98e2SPeter Wemm ** 2037c2aa98e2SPeter Wemm ** Parameters: 2038c2aa98e2SPeter Wemm ** pvp -- parameter vector to rebuild. 2039c2aa98e2SPeter Wemm ** evp -- last parameter to include. Can be NULL to 2040c2aa98e2SPeter Wemm ** use entire pvp. 2041c2aa98e2SPeter Wemm ** buf -- buffer to build the string into. 2042c2aa98e2SPeter Wemm ** sz -- size of buf. 204340266059SGregory Neil Shapiro ** spacesub -- the space separator character; if '\0', 2044c2aa98e2SPeter Wemm ** use SpaceSub. 2045c2aa98e2SPeter Wemm ** 2046c2aa98e2SPeter Wemm ** Returns: 2047c2aa98e2SPeter Wemm ** none. 2048c2aa98e2SPeter Wemm ** 2049c2aa98e2SPeter Wemm ** Side Effects: 2050c2aa98e2SPeter Wemm ** Destroys buf. 2051c2aa98e2SPeter Wemm */ 2052c2aa98e2SPeter Wemm 2053c2aa98e2SPeter Wemm void 2054c2aa98e2SPeter Wemm cataddr(pvp, evp, buf, sz, spacesub) 2055c2aa98e2SPeter Wemm char **pvp; 2056c2aa98e2SPeter Wemm char **evp; 2057c2aa98e2SPeter Wemm char *buf; 2058c2aa98e2SPeter Wemm register int sz; 2059c2aa98e2SPeter Wemm int spacesub; 2060c2aa98e2SPeter Wemm { 206140266059SGregory Neil Shapiro bool oatomtok = false; 206240266059SGregory Neil Shapiro bool natomtok = false; 2063c2aa98e2SPeter Wemm register int i; 2064c2aa98e2SPeter Wemm register char *p; 2065c2aa98e2SPeter Wemm 206606f25ae9SGregory Neil Shapiro if (sz <= 0) 206706f25ae9SGregory Neil Shapiro return; 206806f25ae9SGregory Neil Shapiro 2069c2aa98e2SPeter Wemm if (spacesub == '\0') 2070c2aa98e2SPeter Wemm spacesub = SpaceSub; 2071c2aa98e2SPeter Wemm 2072c2aa98e2SPeter Wemm if (pvp == NULL) 2073c2aa98e2SPeter Wemm { 207406f25ae9SGregory Neil Shapiro *buf = '\0'; 2075c2aa98e2SPeter Wemm return; 2076c2aa98e2SPeter Wemm } 2077c2aa98e2SPeter Wemm p = buf; 2078c2aa98e2SPeter Wemm sz -= 2; 207940266059SGregory Neil Shapiro while (*pvp != NULL && sz > 0) 2080c2aa98e2SPeter Wemm { 2081c2aa98e2SPeter Wemm natomtok = (TokTypeTab[**pvp & 0xff] == ATM); 2082c2aa98e2SPeter Wemm if (oatomtok && natomtok) 208306f25ae9SGregory Neil Shapiro { 2084c2aa98e2SPeter Wemm *p++ = spacesub; 208540266059SGregory Neil Shapiro if (--sz <= 0) 208640266059SGregory Neil Shapiro break; 208706f25ae9SGregory Neil Shapiro } 208840266059SGregory Neil Shapiro if ((i = sm_strlcpy(p, *pvp, sz)) >= sz) 208940266059SGregory Neil Shapiro break; 2090c2aa98e2SPeter Wemm oatomtok = natomtok; 2091c2aa98e2SPeter Wemm p += i; 209206f25ae9SGregory Neil Shapiro sz -= i; 2093c2aa98e2SPeter Wemm if (pvp++ == evp) 2094c2aa98e2SPeter Wemm break; 2095c2aa98e2SPeter Wemm } 2096c2aa98e2SPeter Wemm *p = '\0'; 2097c2aa98e2SPeter Wemm } 209840266059SGregory Neil Shapiro /* 2099c2aa98e2SPeter Wemm ** SAMEADDR -- Determine if two addresses are the same 2100c2aa98e2SPeter Wemm ** 2101c2aa98e2SPeter Wemm ** This is not just a straight comparison -- if the mailer doesn't 2102c2aa98e2SPeter Wemm ** care about the host we just ignore it, etc. 2103c2aa98e2SPeter Wemm ** 2104c2aa98e2SPeter Wemm ** Parameters: 2105c2aa98e2SPeter Wemm ** a, b -- pointers to the internal forms to compare. 2106c2aa98e2SPeter Wemm ** 2107c2aa98e2SPeter Wemm ** Returns: 210840266059SGregory Neil Shapiro ** true -- they represent the same mailbox. 210940266059SGregory Neil Shapiro ** false -- they don't. 2110c2aa98e2SPeter Wemm ** 2111c2aa98e2SPeter Wemm ** Side Effects: 2112c2aa98e2SPeter Wemm ** none. 2113c2aa98e2SPeter Wemm */ 2114c2aa98e2SPeter Wemm 2115c2aa98e2SPeter Wemm bool 2116c2aa98e2SPeter Wemm sameaddr(a, b) 2117c2aa98e2SPeter Wemm register ADDRESS *a; 2118c2aa98e2SPeter Wemm register ADDRESS *b; 2119c2aa98e2SPeter Wemm { 2120c2aa98e2SPeter Wemm register ADDRESS *ca, *cb; 2121c2aa98e2SPeter Wemm 2122c2aa98e2SPeter Wemm /* if they don't have the same mailer, forget it */ 2123c2aa98e2SPeter Wemm if (a->q_mailer != b->q_mailer) 212440266059SGregory Neil Shapiro return false; 2125c2aa98e2SPeter Wemm 2126c2aa98e2SPeter Wemm /* if the user isn't the same, we can drop out */ 2127c2aa98e2SPeter Wemm if (strcmp(a->q_user, b->q_user) != 0) 212840266059SGregory Neil Shapiro return false; 2129c2aa98e2SPeter Wemm 2130c2aa98e2SPeter Wemm /* if we have good uids for both but they differ, these are different */ 2131c2aa98e2SPeter Wemm if (a->q_mailer == ProgMailer) 2132c2aa98e2SPeter Wemm { 2133c2aa98e2SPeter Wemm ca = getctladdr(a); 2134c2aa98e2SPeter Wemm cb = getctladdr(b); 2135c2aa98e2SPeter Wemm if (ca != NULL && cb != NULL && 2136c2aa98e2SPeter Wemm bitset(QGOODUID, ca->q_flags & cb->q_flags) && 2137c2aa98e2SPeter Wemm ca->q_uid != cb->q_uid) 213840266059SGregory Neil Shapiro return false; 2139c2aa98e2SPeter Wemm } 2140c2aa98e2SPeter Wemm 2141c2aa98e2SPeter Wemm /* otherwise compare hosts (but be careful for NULL ptrs) */ 2142c2aa98e2SPeter Wemm if (a->q_host == b->q_host) 2143c2aa98e2SPeter Wemm { 2144c2aa98e2SPeter Wemm /* probably both null pointers */ 214540266059SGregory Neil Shapiro return true; 2146c2aa98e2SPeter Wemm } 2147c2aa98e2SPeter Wemm if (a->q_host == NULL || b->q_host == NULL) 2148c2aa98e2SPeter Wemm { 2149c2aa98e2SPeter Wemm /* only one is a null pointer */ 215040266059SGregory Neil Shapiro return false; 2151c2aa98e2SPeter Wemm } 2152c2aa98e2SPeter Wemm if (strcmp(a->q_host, b->q_host) != 0) 215340266059SGregory Neil Shapiro return false; 2154c2aa98e2SPeter Wemm 215540266059SGregory Neil Shapiro return true; 2156c2aa98e2SPeter Wemm } 215740266059SGregory Neil Shapiro /* 2158c2aa98e2SPeter Wemm ** PRINTADDR -- print address (for debugging) 2159c2aa98e2SPeter Wemm ** 2160c2aa98e2SPeter Wemm ** Parameters: 2161c2aa98e2SPeter Wemm ** a -- the address to print 2162c2aa98e2SPeter Wemm ** follow -- follow the q_next chain. 2163c2aa98e2SPeter Wemm ** 2164c2aa98e2SPeter Wemm ** Returns: 2165c2aa98e2SPeter Wemm ** none. 2166c2aa98e2SPeter Wemm ** 2167c2aa98e2SPeter Wemm ** Side Effects: 2168c2aa98e2SPeter Wemm ** none. 2169c2aa98e2SPeter Wemm */ 2170c2aa98e2SPeter Wemm 2171c2aa98e2SPeter Wemm struct qflags 2172c2aa98e2SPeter Wemm { 2173c2aa98e2SPeter Wemm char *qf_name; 217440266059SGregory Neil Shapiro unsigned long qf_bit; 2175c2aa98e2SPeter Wemm }; 2176c2aa98e2SPeter Wemm 217706f25ae9SGregory Neil Shapiro static struct qflags AddressFlags[] = 2178c2aa98e2SPeter Wemm { 2179c2aa98e2SPeter Wemm { "QGOODUID", QGOODUID }, 2180c2aa98e2SPeter Wemm { "QPRIMARY", QPRIMARY }, 2181c2aa98e2SPeter Wemm { "QNOTREMOTE", QNOTREMOTE }, 2182c2aa98e2SPeter Wemm { "QSELFREF", QSELFREF }, 2183c2aa98e2SPeter Wemm { "QBOGUSSHELL", QBOGUSSHELL }, 2184c2aa98e2SPeter Wemm { "QUNSAFEADDR", QUNSAFEADDR }, 2185c2aa98e2SPeter Wemm { "QPINGONSUCCESS", QPINGONSUCCESS }, 2186c2aa98e2SPeter Wemm { "QPINGONFAILURE", QPINGONFAILURE }, 2187c2aa98e2SPeter Wemm { "QPINGONDELAY", QPINGONDELAY }, 2188c2aa98e2SPeter Wemm { "QHASNOTIFY", QHASNOTIFY }, 2189c2aa98e2SPeter Wemm { "QRELAYED", QRELAYED }, 2190c2aa98e2SPeter Wemm { "QEXPANDED", QEXPANDED }, 2191c2aa98e2SPeter Wemm { "QDELIVERED", QDELIVERED }, 2192c2aa98e2SPeter Wemm { "QDELAYED", QDELAYED }, 2193c2aa98e2SPeter Wemm { "QTHISPASS", QTHISPASS }, 2194c2aa98e2SPeter Wemm { "QRCPTOK", QRCPTOK }, 2195193538b7SGregory Neil Shapiro { NULL, 0 } 2196c2aa98e2SPeter Wemm }; 2197c2aa98e2SPeter Wemm 2198c2aa98e2SPeter Wemm void 2199c2aa98e2SPeter Wemm printaddr(a, follow) 2200c2aa98e2SPeter Wemm register ADDRESS *a; 2201c2aa98e2SPeter Wemm bool follow; 2202c2aa98e2SPeter Wemm { 2203c2aa98e2SPeter Wemm register MAILER *m; 2204c2aa98e2SPeter Wemm MAILER pseudomailer; 2205c2aa98e2SPeter Wemm register struct qflags *qfp; 2206c2aa98e2SPeter Wemm bool firstone; 2207c2aa98e2SPeter Wemm 2208c2aa98e2SPeter Wemm if (a == NULL) 2209c2aa98e2SPeter Wemm { 221040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "[NULL]\n"); 2211c2aa98e2SPeter Wemm return; 2212c2aa98e2SPeter Wemm } 2213c2aa98e2SPeter Wemm 2214c2aa98e2SPeter Wemm while (a != NULL) 2215c2aa98e2SPeter Wemm { 221640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%p=", a); 221740266059SGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 2218c2aa98e2SPeter Wemm 2219c2aa98e2SPeter Wemm /* find the mailer -- carefully */ 2220c2aa98e2SPeter Wemm m = a->q_mailer; 2221c2aa98e2SPeter Wemm if (m == NULL) 2222c2aa98e2SPeter Wemm { 2223c2aa98e2SPeter Wemm m = &pseudomailer; 2224c2aa98e2SPeter Wemm m->m_mno = -1; 2225c2aa98e2SPeter Wemm m->m_name = "NULL"; 2226c2aa98e2SPeter Wemm } 2227c2aa98e2SPeter Wemm 222840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 222940266059SGregory Neil Shapiro "%s:\n\tmailer %d (%s), host `%s'\n", 2230c2aa98e2SPeter Wemm a->q_paddr == NULL ? "<null>" : a->q_paddr, 2231c2aa98e2SPeter Wemm m->m_mno, m->m_name, 2232c2aa98e2SPeter Wemm a->q_host == NULL ? "<null>" : a->q_host); 223340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 223440266059SGregory Neil Shapiro "\tuser `%s', ruser `%s'\n", 2235c2aa98e2SPeter Wemm a->q_user, 2236c2aa98e2SPeter Wemm a->q_ruser == NULL ? "<null>" : a->q_ruser); 223740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\tstate="); 223806f25ae9SGregory Neil Shapiro switch (a->q_state) 223906f25ae9SGregory Neil Shapiro { 224006f25ae9SGregory Neil Shapiro case QS_OK: 224140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "OK"); 224206f25ae9SGregory Neil Shapiro break; 224306f25ae9SGregory Neil Shapiro 224406f25ae9SGregory Neil Shapiro case QS_DONTSEND: 224540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 224640266059SGregory Neil Shapiro "DONTSEND"); 224706f25ae9SGregory Neil Shapiro break; 224806f25ae9SGregory Neil Shapiro 224906f25ae9SGregory Neil Shapiro case QS_BADADDR: 225040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 225140266059SGregory Neil Shapiro "BADADDR"); 225206f25ae9SGregory Neil Shapiro break; 225306f25ae9SGregory Neil Shapiro 225406f25ae9SGregory Neil Shapiro case QS_QUEUEUP: 225540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 225640266059SGregory Neil Shapiro "QUEUEUP"); 225740266059SGregory Neil Shapiro break; 225840266059SGregory Neil Shapiro 225940266059SGregory Neil Shapiro case QS_RETRY: 226040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "RETRY"); 226106f25ae9SGregory Neil Shapiro break; 226206f25ae9SGregory Neil Shapiro 226306f25ae9SGregory Neil Shapiro case QS_SENT: 226440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "SENT"); 226506f25ae9SGregory Neil Shapiro break; 226606f25ae9SGregory Neil Shapiro 226706f25ae9SGregory Neil Shapiro case QS_VERIFIED: 226840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 226940266059SGregory Neil Shapiro "VERIFIED"); 227006f25ae9SGregory Neil Shapiro break; 227106f25ae9SGregory Neil Shapiro 227206f25ae9SGregory Neil Shapiro case QS_EXPANDED: 227340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 227440266059SGregory Neil Shapiro "EXPANDED"); 227506f25ae9SGregory Neil Shapiro break; 227606f25ae9SGregory Neil Shapiro 227706f25ae9SGregory Neil Shapiro case QS_SENDER: 227840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 227940266059SGregory Neil Shapiro "SENDER"); 228006f25ae9SGregory Neil Shapiro break; 228106f25ae9SGregory Neil Shapiro 228206f25ae9SGregory Neil Shapiro case QS_CLONED: 228340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 228440266059SGregory Neil Shapiro "CLONED"); 228506f25ae9SGregory Neil Shapiro break; 228606f25ae9SGregory Neil Shapiro 228706f25ae9SGregory Neil Shapiro case QS_DISCARDED: 228840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 228940266059SGregory Neil Shapiro "DISCARDED"); 229006f25ae9SGregory Neil Shapiro break; 229106f25ae9SGregory Neil Shapiro 229206f25ae9SGregory Neil Shapiro case QS_REPLACED: 229340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 229440266059SGregory Neil Shapiro "REPLACED"); 229506f25ae9SGregory Neil Shapiro break; 229606f25ae9SGregory Neil Shapiro 229706f25ae9SGregory Neil Shapiro case QS_REMOVED: 229840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 229940266059SGregory Neil Shapiro "REMOVED"); 230006f25ae9SGregory Neil Shapiro break; 230106f25ae9SGregory Neil Shapiro 230206f25ae9SGregory Neil Shapiro case QS_DUPLICATE: 230340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 230440266059SGregory Neil Shapiro "DUPLICATE"); 230506f25ae9SGregory Neil Shapiro break; 230606f25ae9SGregory Neil Shapiro 230706f25ae9SGregory Neil Shapiro case QS_INCLUDED: 230840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 230940266059SGregory Neil Shapiro "INCLUDED"); 231006f25ae9SGregory Neil Shapiro break; 231106f25ae9SGregory Neil Shapiro 231206f25ae9SGregory Neil Shapiro default: 231340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 231440266059SGregory Neil Shapiro "%d", a->q_state); 231506f25ae9SGregory Neil Shapiro break; 231606f25ae9SGregory Neil Shapiro } 231740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 231840266059SGregory Neil Shapiro ", next=%p, alias %p, uid %d, gid %d\n", 231940266059SGregory Neil Shapiro a->q_next, a->q_alias, 2320c2aa98e2SPeter Wemm (int) a->q_uid, (int) a->q_gid); 232140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\tflags=%lx<", 232240266059SGregory Neil Shapiro a->q_flags); 232340266059SGregory Neil Shapiro firstone = true; 2324c2aa98e2SPeter Wemm for (qfp = AddressFlags; qfp->qf_name != NULL; qfp++) 2325c2aa98e2SPeter Wemm { 2326c2aa98e2SPeter Wemm if (!bitset(qfp->qf_bit, a->q_flags)) 2327c2aa98e2SPeter Wemm continue; 2328c2aa98e2SPeter Wemm if (!firstone) 232940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 233040266059SGregory Neil Shapiro ","); 233140266059SGregory Neil Shapiro firstone = false; 233240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s", 233340266059SGregory Neil Shapiro qfp->qf_name); 2334c2aa98e2SPeter Wemm } 233540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ">\n"); 233640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 233740266059SGregory Neil Shapiro "\towner=%s, home=\"%s\", fullname=\"%s\"\n", 2338c2aa98e2SPeter Wemm a->q_owner == NULL ? "(none)" : a->q_owner, 2339c2aa98e2SPeter Wemm a->q_home == NULL ? "(none)" : a->q_home, 2340c2aa98e2SPeter Wemm a->q_fullname == NULL ? "(none)" : a->q_fullname); 234140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 234240266059SGregory Neil Shapiro "\torcpt=\"%s\", statmta=%s, status=%s\n", 2343c2aa98e2SPeter Wemm a->q_orcpt == NULL ? "(none)" : a->q_orcpt, 2344c2aa98e2SPeter Wemm a->q_statmta == NULL ? "(none)" : a->q_statmta, 2345c2aa98e2SPeter Wemm a->q_status == NULL ? "(none)" : a->q_status); 234640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 234740266059SGregory Neil Shapiro "\tfinalrcpt=\"%s\"\n", 234840266059SGregory Neil Shapiro a->q_finalrcpt == NULL ? "(none)" : a->q_finalrcpt); 234940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 235040266059SGregory Neil Shapiro "\trstatus=\"%s\"\n", 2351c2aa98e2SPeter Wemm a->q_rstatus == NULL ? "(none)" : a->q_rstatus); 235240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 235340266059SGregory Neil Shapiro "\tstatdate=%s\n", 235406f25ae9SGregory Neil Shapiro a->q_statdate == 0 ? "(none)" : ctime(&a->q_statdate)); 2355c2aa98e2SPeter Wemm 2356c2aa98e2SPeter Wemm if (!follow) 2357c2aa98e2SPeter Wemm return; 2358c2aa98e2SPeter Wemm a = a->q_next; 2359c2aa98e2SPeter Wemm } 2360c2aa98e2SPeter Wemm } 236140266059SGregory Neil Shapiro /* 236240266059SGregory Neil Shapiro ** EMPTYADDR -- return true if this address is empty (``<>'') 2363c2aa98e2SPeter Wemm ** 2364c2aa98e2SPeter Wemm ** Parameters: 2365c2aa98e2SPeter Wemm ** a -- pointer to the address 2366c2aa98e2SPeter Wemm ** 2367c2aa98e2SPeter Wemm ** Returns: 236840266059SGregory Neil Shapiro ** true -- if this address is "empty" (i.e., no one should 2369c2aa98e2SPeter Wemm ** ever generate replies to it. 237040266059SGregory Neil Shapiro ** false -- if it is a "regular" (read: replyable) address. 2371c2aa98e2SPeter Wemm */ 2372c2aa98e2SPeter Wemm 2373c2aa98e2SPeter Wemm bool 2374c2aa98e2SPeter Wemm emptyaddr(a) 2375c2aa98e2SPeter Wemm register ADDRESS *a; 2376c2aa98e2SPeter Wemm { 2377c2aa98e2SPeter Wemm return a->q_paddr == NULL || strcmp(a->q_paddr, "<>") == 0 || 2378c2aa98e2SPeter Wemm a->q_user == NULL || strcmp(a->q_user, "<>") == 0; 2379c2aa98e2SPeter Wemm } 238040266059SGregory Neil Shapiro /* 2381c2aa98e2SPeter Wemm ** REMOTENAME -- return the name relative to the current mailer 2382c2aa98e2SPeter Wemm ** 2383c2aa98e2SPeter Wemm ** Parameters: 2384c2aa98e2SPeter Wemm ** name -- the name to translate. 2385c2aa98e2SPeter Wemm ** m -- the mailer that we want to do rewriting relative 2386c2aa98e2SPeter Wemm ** to. 2387c2aa98e2SPeter Wemm ** flags -- fine tune operations. 2388c2aa98e2SPeter Wemm ** pstat -- pointer to status word. 2389c2aa98e2SPeter Wemm ** e -- the current envelope. 2390c2aa98e2SPeter Wemm ** 2391c2aa98e2SPeter Wemm ** Returns: 2392c2aa98e2SPeter Wemm ** the text string representing this address relative to 2393c2aa98e2SPeter Wemm ** the receiving mailer. 2394c2aa98e2SPeter Wemm ** 2395c2aa98e2SPeter Wemm ** Side Effects: 2396c2aa98e2SPeter Wemm ** none. 2397c2aa98e2SPeter Wemm ** 2398c2aa98e2SPeter Wemm ** Warnings: 2399c2aa98e2SPeter Wemm ** The text string returned is tucked away locally; 2400c2aa98e2SPeter Wemm ** copy it if you intend to save it. 2401c2aa98e2SPeter Wemm */ 2402c2aa98e2SPeter Wemm 2403c2aa98e2SPeter Wemm char * 2404c2aa98e2SPeter Wemm remotename(name, m, flags, pstat, e) 2405c2aa98e2SPeter Wemm char *name; 2406c2aa98e2SPeter Wemm struct mailer *m; 2407c2aa98e2SPeter Wemm int flags; 2408c2aa98e2SPeter Wemm int *pstat; 2409c2aa98e2SPeter Wemm register ENVELOPE *e; 2410c2aa98e2SPeter Wemm { 2411c2aa98e2SPeter Wemm register char **pvp; 241240266059SGregory Neil Shapiro char *SM_NONVOLATILE fancy; 241340266059SGregory Neil Shapiro char *oldg; 2414c2aa98e2SPeter Wemm int rwset; 2415c2aa98e2SPeter Wemm static char buf[MAXNAME + 1]; 2416c2aa98e2SPeter Wemm char lbuf[MAXNAME + 1]; 2417c2aa98e2SPeter Wemm char pvpbuf[PSBUFSIZE]; 241806f25ae9SGregory Neil Shapiro char addrtype[4]; 2419c2aa98e2SPeter Wemm 2420c2aa98e2SPeter Wemm if (tTd(12, 1)) 242140266059SGregory Neil Shapiro sm_dprintf("remotename(%s)\n", name); 2422c2aa98e2SPeter Wemm 2423c2aa98e2SPeter Wemm /* don't do anything if we are tagging it as special */ 2424c2aa98e2SPeter Wemm if (bitset(RF_SENDERADDR, flags)) 242506f25ae9SGregory Neil Shapiro { 2426c2aa98e2SPeter Wemm rwset = bitset(RF_HEADERADDR, flags) ? m->m_sh_rwset 2427c2aa98e2SPeter Wemm : m->m_se_rwset; 242806f25ae9SGregory Neil Shapiro addrtype[2] = 's'; 242906f25ae9SGregory Neil Shapiro } 2430c2aa98e2SPeter Wemm else 243106f25ae9SGregory Neil Shapiro { 2432c2aa98e2SPeter Wemm rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset 2433c2aa98e2SPeter Wemm : m->m_re_rwset; 243406f25ae9SGregory Neil Shapiro addrtype[2] = 'r'; 243506f25ae9SGregory Neil Shapiro } 2436c2aa98e2SPeter Wemm if (rwset < 0) 243706f25ae9SGregory Neil Shapiro return name; 243806f25ae9SGregory Neil Shapiro addrtype[1] = ' '; 243906f25ae9SGregory Neil Shapiro addrtype[3] = '\0'; 244006f25ae9SGregory Neil Shapiro addrtype[0] = bitset(RF_HEADERADDR, flags) ? 'h' : 'e'; 244140266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, macid("{addr_type}"), addrtype); 2442c2aa98e2SPeter Wemm 2443c2aa98e2SPeter Wemm /* 2444c2aa98e2SPeter Wemm ** Do a heuristic crack of this name to extract any comment info. 2445c2aa98e2SPeter Wemm ** This will leave the name as a comment and a $g macro. 2446c2aa98e2SPeter Wemm */ 2447c2aa98e2SPeter Wemm 2448c2aa98e2SPeter Wemm if (bitset(RF_CANONICAL, flags) || bitnset(M_NOCOMMENT, m->m_flags)) 2449c2aa98e2SPeter Wemm fancy = "\201g"; 2450c2aa98e2SPeter Wemm else 2451c2aa98e2SPeter Wemm fancy = crackaddr(name); 2452c2aa98e2SPeter Wemm 2453c2aa98e2SPeter Wemm /* 2454c2aa98e2SPeter Wemm ** Turn the name into canonical form. 2455c2aa98e2SPeter Wemm ** Normally this will be RFC 822 style, i.e., "user@domain". 2456c2aa98e2SPeter Wemm ** If this only resolves to "user", and the "C" flag is 2457c2aa98e2SPeter Wemm ** specified in the sending mailer, then the sender's 2458c2aa98e2SPeter Wemm ** domain will be appended. 2459c2aa98e2SPeter Wemm */ 2460c2aa98e2SPeter Wemm 2461c2aa98e2SPeter Wemm pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL); 2462c2aa98e2SPeter Wemm if (pvp == NULL) 246306f25ae9SGregory Neil Shapiro return name; 246440266059SGregory Neil Shapiro if (REWRITE(pvp, 3, e) == EX_TEMPFAIL) 2465c2aa98e2SPeter Wemm *pstat = EX_TEMPFAIL; 2466c2aa98e2SPeter Wemm if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL) 2467c2aa98e2SPeter Wemm { 2468c2aa98e2SPeter Wemm /* append from domain to this address */ 2469c2aa98e2SPeter Wemm register char **pxp = pvp; 247006f25ae9SGregory Neil Shapiro int l = MAXATOM; /* size of buffer for pvp */ 2471c2aa98e2SPeter Wemm 2472c2aa98e2SPeter Wemm /* see if there is an "@domain" in the current name */ 2473c2aa98e2SPeter Wemm while (*pxp != NULL && strcmp(*pxp, "@") != 0) 247406f25ae9SGregory Neil Shapiro { 2475c2aa98e2SPeter Wemm pxp++; 247606f25ae9SGregory Neil Shapiro --l; 247706f25ae9SGregory Neil Shapiro } 2478c2aa98e2SPeter Wemm if (*pxp == NULL) 2479c2aa98e2SPeter Wemm { 2480c2aa98e2SPeter Wemm /* no.... append the "@domain" from the sender */ 2481c2aa98e2SPeter Wemm register char **qxq = e->e_fromdomain; 2482c2aa98e2SPeter Wemm 2483c2aa98e2SPeter Wemm while ((*pxp++ = *qxq++) != NULL) 248406f25ae9SGregory Neil Shapiro { 248506f25ae9SGregory Neil Shapiro if (--l <= 0) 248606f25ae9SGregory Neil Shapiro { 248706f25ae9SGregory Neil Shapiro *--pxp = NULL; 248806f25ae9SGregory Neil Shapiro usrerr("553 5.1.0 remotename: too many tokens"); 248906f25ae9SGregory Neil Shapiro *pstat = EX_UNAVAILABLE; 249006f25ae9SGregory Neil Shapiro break; 249106f25ae9SGregory Neil Shapiro } 249206f25ae9SGregory Neil Shapiro } 249340266059SGregory Neil Shapiro if (REWRITE(pvp, 3, e) == EX_TEMPFAIL) 2494c2aa98e2SPeter Wemm *pstat = EX_TEMPFAIL; 2495c2aa98e2SPeter Wemm } 2496c2aa98e2SPeter Wemm } 2497c2aa98e2SPeter Wemm 2498c2aa98e2SPeter Wemm /* 2499c2aa98e2SPeter Wemm ** Do more specific rewriting. 2500c2aa98e2SPeter Wemm ** Rewrite using ruleset 1 or 2 depending on whether this is 2501c2aa98e2SPeter Wemm ** a sender address or not. 2502c2aa98e2SPeter Wemm ** Then run it through any receiving-mailer-specific rulesets. 2503c2aa98e2SPeter Wemm */ 2504c2aa98e2SPeter Wemm 2505c2aa98e2SPeter Wemm if (bitset(RF_SENDERADDR, flags)) 2506c2aa98e2SPeter Wemm { 250740266059SGregory Neil Shapiro if (REWRITE(pvp, 1, e) == EX_TEMPFAIL) 2508c2aa98e2SPeter Wemm *pstat = EX_TEMPFAIL; 2509c2aa98e2SPeter Wemm } 2510c2aa98e2SPeter Wemm else 2511c2aa98e2SPeter Wemm { 251240266059SGregory Neil Shapiro if (REWRITE(pvp, 2, e) == EX_TEMPFAIL) 2513c2aa98e2SPeter Wemm *pstat = EX_TEMPFAIL; 2514c2aa98e2SPeter Wemm } 2515c2aa98e2SPeter Wemm if (rwset > 0) 2516c2aa98e2SPeter Wemm { 251740266059SGregory Neil Shapiro if (REWRITE(pvp, rwset, e) == EX_TEMPFAIL) 2518c2aa98e2SPeter Wemm *pstat = EX_TEMPFAIL; 2519c2aa98e2SPeter Wemm } 2520c2aa98e2SPeter Wemm 2521c2aa98e2SPeter Wemm /* 2522c2aa98e2SPeter Wemm ** Do any final sanitation the address may require. 2523c2aa98e2SPeter Wemm ** This will normally be used to turn internal forms 2524c2aa98e2SPeter Wemm ** (e.g., user@host.LOCAL) into external form. This 2525c2aa98e2SPeter Wemm ** may be used as a default to the above rules. 2526c2aa98e2SPeter Wemm */ 2527c2aa98e2SPeter Wemm 252840266059SGregory Neil Shapiro if (REWRITE(pvp, 4, e) == EX_TEMPFAIL) 2529c2aa98e2SPeter Wemm *pstat = EX_TEMPFAIL; 2530c2aa98e2SPeter Wemm 2531c2aa98e2SPeter Wemm /* 2532c2aa98e2SPeter Wemm ** Now restore the comment information we had at the beginning. 2533c2aa98e2SPeter Wemm */ 2534c2aa98e2SPeter Wemm 2535c2aa98e2SPeter Wemm cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0'); 253640266059SGregory Neil Shapiro oldg = macget(&e->e_macro, 'g'); 253740266059SGregory Neil Shapiro macset(&e->e_macro, 'g', lbuf); 2538c2aa98e2SPeter Wemm 253940266059SGregory Neil Shapiro SM_TRY 2540c2aa98e2SPeter Wemm /* need to make sure route-addrs have <angle brackets> */ 2541c2aa98e2SPeter Wemm if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@') 2542c2aa98e2SPeter Wemm expand("<\201g>", buf, sizeof buf, e); 2543c2aa98e2SPeter Wemm else 2544c2aa98e2SPeter Wemm expand(fancy, buf, sizeof buf, e); 254540266059SGregory Neil Shapiro SM_FINALLY 254640266059SGregory Neil Shapiro macset(&e->e_macro, 'g', oldg); 254740266059SGregory Neil Shapiro SM_END_TRY 2548c2aa98e2SPeter Wemm 2549c2aa98e2SPeter Wemm if (tTd(12, 1)) 255040266059SGregory Neil Shapiro sm_dprintf("remotename => `%s'\n", buf); 255106f25ae9SGregory Neil Shapiro return buf; 2552c2aa98e2SPeter Wemm } 255340266059SGregory Neil Shapiro /* 2554c2aa98e2SPeter Wemm ** MAPLOCALUSER -- run local username through ruleset 5 for final redirection 2555c2aa98e2SPeter Wemm ** 2556c2aa98e2SPeter Wemm ** Parameters: 2557c2aa98e2SPeter Wemm ** a -- the address to map (but just the user name part). 2558c2aa98e2SPeter Wemm ** sendq -- the sendq in which to install any replacement 2559c2aa98e2SPeter Wemm ** addresses. 2560c2aa98e2SPeter Wemm ** aliaslevel -- the alias nesting depth. 2561c2aa98e2SPeter Wemm ** e -- the envelope. 2562c2aa98e2SPeter Wemm ** 2563c2aa98e2SPeter Wemm ** Returns: 2564c2aa98e2SPeter Wemm ** none. 2565c2aa98e2SPeter Wemm */ 2566c2aa98e2SPeter Wemm 2567c2aa98e2SPeter Wemm #define Q_COPYFLAGS (QPRIMARY|QBOGUSSHELL|QUNSAFEADDR|\ 2568c2aa98e2SPeter Wemm Q_PINGFLAGS|QHASNOTIFY|\ 256940266059SGregory Neil Shapiro QRELAYED|QEXPANDED|QDELIVERED|QDELAYED|\ 257040266059SGregory Neil Shapiro QBYTRACE|QBYNDELAY|QBYNRELAY) 2571c2aa98e2SPeter Wemm 2572c2aa98e2SPeter Wemm void 2573c2aa98e2SPeter Wemm maplocaluser(a, sendq, aliaslevel, e) 2574c2aa98e2SPeter Wemm register ADDRESS *a; 2575c2aa98e2SPeter Wemm ADDRESS **sendq; 2576c2aa98e2SPeter Wemm int aliaslevel; 2577c2aa98e2SPeter Wemm ENVELOPE *e; 2578c2aa98e2SPeter Wemm { 2579c2aa98e2SPeter Wemm register char **pvp; 258040266059SGregory Neil Shapiro register ADDRESS *SM_NONVOLATILE a1 = NULL; 2581c2aa98e2SPeter Wemm auto char *delimptr; 2582c2aa98e2SPeter Wemm char pvpbuf[PSBUFSIZE]; 2583c2aa98e2SPeter Wemm 2584c2aa98e2SPeter Wemm if (tTd(29, 1)) 2585c2aa98e2SPeter Wemm { 258640266059SGregory Neil Shapiro sm_dprintf("maplocaluser: "); 258740266059SGregory Neil Shapiro printaddr(a, false); 2588c2aa98e2SPeter Wemm } 2589c2aa98e2SPeter Wemm pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr, NULL); 2590c2aa98e2SPeter Wemm if (pvp == NULL) 2591c2aa98e2SPeter Wemm { 2592c2aa98e2SPeter Wemm if (tTd(29, 9)) 259340266059SGregory Neil Shapiro sm_dprintf("maplocaluser: cannot prescan %s\n", 259406f25ae9SGregory Neil Shapiro a->q_user); 2595c2aa98e2SPeter Wemm return; 2596c2aa98e2SPeter Wemm } 2597c2aa98e2SPeter Wemm 259840266059SGregory Neil Shapiro macdefine(&e->e_macro, A_PERM, 'h', a->q_host); 259940266059SGregory Neil Shapiro macdefine(&e->e_macro, A_PERM, 'u', a->q_user); 260040266059SGregory Neil Shapiro macdefine(&e->e_macro, A_PERM, 'z', a->q_home); 2601c2aa98e2SPeter Wemm 260240266059SGregory Neil Shapiro macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e r"); 260340266059SGregory Neil Shapiro if (REWRITE(pvp, 5, e) == EX_TEMPFAIL) 2604c2aa98e2SPeter Wemm { 2605c2aa98e2SPeter Wemm if (tTd(29, 9)) 260640266059SGregory Neil Shapiro sm_dprintf("maplocaluser: rewrite tempfail\n"); 260706f25ae9SGregory Neil Shapiro a->q_state = QS_QUEUEUP; 2608c2aa98e2SPeter Wemm a->q_status = "4.4.3"; 2609c2aa98e2SPeter Wemm return; 2610c2aa98e2SPeter Wemm } 2611c2aa98e2SPeter Wemm if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET) 2612c2aa98e2SPeter Wemm { 2613c2aa98e2SPeter Wemm if (tTd(29, 9)) 261440266059SGregory Neil Shapiro sm_dprintf("maplocaluser: doesn't resolve\n"); 2615c2aa98e2SPeter Wemm return; 2616c2aa98e2SPeter Wemm } 2617c2aa98e2SPeter Wemm 261840266059SGregory Neil Shapiro SM_TRY 2619c2aa98e2SPeter Wemm a1 = buildaddr(pvp, NULL, 0, e); 262040266059SGregory Neil Shapiro SM_EXCEPT(exc, "E:mta.quickabort") 262140266059SGregory Neil Shapiro 262240266059SGregory Neil Shapiro /* 262340266059SGregory Neil Shapiro ** mark address as bad, S5 returned an error 262440266059SGregory Neil Shapiro ** and we gave that back to the SMTP client. 262540266059SGregory Neil Shapiro */ 262640266059SGregory Neil Shapiro 262740266059SGregory Neil Shapiro a->q_state = QS_DONTSEND; 262840266059SGregory Neil Shapiro sm_exc_raisenew_x(&EtypeQuickAbort, 2); 262940266059SGregory Neil Shapiro SM_END_TRY 263040266059SGregory Neil Shapiro 263140266059SGregory Neil Shapiro /* if non-null, mailer destination specified -- has it changed? */ 2632c2aa98e2SPeter Wemm if (a1 == NULL || sameaddr(a, a1)) 2633c2aa98e2SPeter Wemm { 2634c2aa98e2SPeter Wemm if (tTd(29, 9)) 263540266059SGregory Neil Shapiro sm_dprintf("maplocaluser: address unchanged\n"); 2636c2aa98e2SPeter Wemm return; 2637c2aa98e2SPeter Wemm } 2638c2aa98e2SPeter Wemm 2639c2aa98e2SPeter Wemm /* make new address take on flags and print attributes of old */ 2640c2aa98e2SPeter Wemm a1->q_flags &= ~Q_COPYFLAGS; 2641c2aa98e2SPeter Wemm a1->q_flags |= a->q_flags & Q_COPYFLAGS; 264240266059SGregory Neil Shapiro a1->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_paddr); 264340266059SGregory Neil Shapiro a1->q_finalrcpt = a->q_finalrcpt; 264406f25ae9SGregory Neil Shapiro a1->q_orcpt = a->q_orcpt; 2645c2aa98e2SPeter Wemm 2646c2aa98e2SPeter Wemm /* mark old address as dead; insert new address */ 264706f25ae9SGregory Neil Shapiro a->q_state = QS_REPLACED; 2648c2aa98e2SPeter Wemm if (tTd(29, 5)) 2649c2aa98e2SPeter Wemm { 265040266059SGregory Neil Shapiro sm_dprintf("maplocaluser: QS_REPLACED "); 265140266059SGregory Neil Shapiro printaddr(a, false); 2652c2aa98e2SPeter Wemm } 2653c2aa98e2SPeter Wemm a1->q_alias = a; 265440266059SGregory Neil Shapiro allocaddr(a1, RF_COPYALL, sm_rpool_strdup_x(e->e_rpool, a->q_paddr), e); 2655c2aa98e2SPeter Wemm (void) recipient(a1, sendq, aliaslevel, e); 2656c2aa98e2SPeter Wemm } 265740266059SGregory Neil Shapiro /* 2658c2aa98e2SPeter Wemm ** DEQUOTE_INIT -- initialize dequote map 2659c2aa98e2SPeter Wemm ** 2660c2aa98e2SPeter Wemm ** Parameters: 2661c2aa98e2SPeter Wemm ** map -- the internal map structure. 2662c2aa98e2SPeter Wemm ** args -- arguments. 2663c2aa98e2SPeter Wemm ** 2664c2aa98e2SPeter Wemm ** Returns: 266540266059SGregory Neil Shapiro ** true. 2666c2aa98e2SPeter Wemm */ 2667c2aa98e2SPeter Wemm 2668c2aa98e2SPeter Wemm bool 2669c2aa98e2SPeter Wemm dequote_init(map, args) 2670c2aa98e2SPeter Wemm MAP *map; 2671c2aa98e2SPeter Wemm char *args; 2672c2aa98e2SPeter Wemm { 2673c2aa98e2SPeter Wemm register char *p = args; 2674c2aa98e2SPeter Wemm 267506f25ae9SGregory Neil Shapiro /* there is no check whether there is really an argument */ 2676c2aa98e2SPeter Wemm map->map_mflags |= MF_KEEPQUOTES; 2677c2aa98e2SPeter Wemm for (;;) 2678c2aa98e2SPeter Wemm { 2679c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 2680c2aa98e2SPeter Wemm p++; 2681c2aa98e2SPeter Wemm if (*p != '-') 2682c2aa98e2SPeter Wemm break; 2683c2aa98e2SPeter Wemm switch (*++p) 2684c2aa98e2SPeter Wemm { 2685c2aa98e2SPeter Wemm case 'a': 2686c2aa98e2SPeter Wemm map->map_app = ++p; 2687c2aa98e2SPeter Wemm break; 2688c2aa98e2SPeter Wemm 268906f25ae9SGregory Neil Shapiro case 'D': 269006f25ae9SGregory Neil Shapiro map->map_mflags |= MF_DEFER; 269106f25ae9SGregory Neil Shapiro break; 269206f25ae9SGregory Neil Shapiro 269306f25ae9SGregory Neil Shapiro case 'S': 2694c2aa98e2SPeter Wemm case 's': 269506f25ae9SGregory Neil Shapiro map->map_spacesub = *++p; 2696c2aa98e2SPeter Wemm break; 2697c2aa98e2SPeter Wemm } 2698c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 2699c2aa98e2SPeter Wemm p++; 2700c2aa98e2SPeter Wemm if (*p != '\0') 2701c2aa98e2SPeter Wemm *p = '\0'; 2702c2aa98e2SPeter Wemm } 2703c2aa98e2SPeter Wemm if (map->map_app != NULL) 2704c2aa98e2SPeter Wemm map->map_app = newstr(map->map_app); 2705c2aa98e2SPeter Wemm 270640266059SGregory Neil Shapiro return true; 2707c2aa98e2SPeter Wemm } 270840266059SGregory Neil Shapiro /* 2709c2aa98e2SPeter Wemm ** DEQUOTE_MAP -- unquote an address 2710c2aa98e2SPeter Wemm ** 2711c2aa98e2SPeter Wemm ** Parameters: 2712c2aa98e2SPeter Wemm ** map -- the internal map structure (ignored). 2713c2aa98e2SPeter Wemm ** name -- the name to dequote. 2714c2aa98e2SPeter Wemm ** av -- arguments (ignored). 2715c2aa98e2SPeter Wemm ** statp -- pointer to status out-parameter. 2716c2aa98e2SPeter Wemm ** 2717c2aa98e2SPeter Wemm ** Returns: 2718c2aa98e2SPeter Wemm ** NULL -- if there were no quotes, or if the resulting 2719c2aa98e2SPeter Wemm ** unquoted buffer would not be acceptable to prescan. 2720c2aa98e2SPeter Wemm ** else -- The dequoted buffer. 2721c2aa98e2SPeter Wemm */ 2722c2aa98e2SPeter Wemm 2723c2aa98e2SPeter Wemm /* ARGSUSED2 */ 2724c2aa98e2SPeter Wemm char * 2725c2aa98e2SPeter Wemm dequote_map(map, name, av, statp) 2726c2aa98e2SPeter Wemm MAP *map; 2727c2aa98e2SPeter Wemm char *name; 2728c2aa98e2SPeter Wemm char **av; 2729c2aa98e2SPeter Wemm int *statp; 2730c2aa98e2SPeter Wemm { 2731c2aa98e2SPeter Wemm register char *p; 2732c2aa98e2SPeter Wemm register char *q; 2733c2aa98e2SPeter Wemm register char c; 2734c2aa98e2SPeter Wemm int anglecnt = 0; 2735c2aa98e2SPeter Wemm int cmntcnt = 0; 2736c2aa98e2SPeter Wemm int quotecnt = 0; 2737c2aa98e2SPeter Wemm int spacecnt = 0; 273840266059SGregory Neil Shapiro bool quotemode = false; 273940266059SGregory Neil Shapiro bool bslashmode = false; 274006f25ae9SGregory Neil Shapiro char spacesub = map->map_spacesub; 2741c2aa98e2SPeter Wemm 2742c2aa98e2SPeter Wemm for (p = q = name; (c = *p++) != '\0'; ) 2743c2aa98e2SPeter Wemm { 2744c2aa98e2SPeter Wemm if (bslashmode) 2745c2aa98e2SPeter Wemm { 274640266059SGregory Neil Shapiro bslashmode = false; 2747c2aa98e2SPeter Wemm *q++ = c; 2748c2aa98e2SPeter Wemm continue; 2749c2aa98e2SPeter Wemm } 2750c2aa98e2SPeter Wemm 2751c2aa98e2SPeter Wemm if (c == ' ' && spacesub != '\0') 2752c2aa98e2SPeter Wemm c = spacesub; 2753c2aa98e2SPeter Wemm 2754c2aa98e2SPeter Wemm switch (c) 2755c2aa98e2SPeter Wemm { 2756c2aa98e2SPeter Wemm case '\\': 275740266059SGregory Neil Shapiro bslashmode = true; 2758c2aa98e2SPeter Wemm break; 2759c2aa98e2SPeter Wemm 2760c2aa98e2SPeter Wemm case '(': 2761c2aa98e2SPeter Wemm cmntcnt++; 2762c2aa98e2SPeter Wemm break; 2763c2aa98e2SPeter Wemm 2764c2aa98e2SPeter Wemm case ')': 2765c2aa98e2SPeter Wemm if (cmntcnt-- <= 0) 2766c2aa98e2SPeter Wemm return NULL; 2767c2aa98e2SPeter Wemm break; 2768c2aa98e2SPeter Wemm 2769c2aa98e2SPeter Wemm case ' ': 277006f25ae9SGregory Neil Shapiro case '\t': 2771c2aa98e2SPeter Wemm spacecnt++; 2772c2aa98e2SPeter Wemm break; 2773c2aa98e2SPeter Wemm } 2774c2aa98e2SPeter Wemm 2775c2aa98e2SPeter Wemm if (cmntcnt > 0) 2776c2aa98e2SPeter Wemm { 2777c2aa98e2SPeter Wemm *q++ = c; 2778c2aa98e2SPeter Wemm continue; 2779c2aa98e2SPeter Wemm } 2780c2aa98e2SPeter Wemm 2781c2aa98e2SPeter Wemm switch (c) 2782c2aa98e2SPeter Wemm { 2783c2aa98e2SPeter Wemm case '"': 2784c2aa98e2SPeter Wemm quotemode = !quotemode; 2785c2aa98e2SPeter Wemm quotecnt++; 2786c2aa98e2SPeter Wemm continue; 2787c2aa98e2SPeter Wemm 2788c2aa98e2SPeter Wemm case '<': 2789c2aa98e2SPeter Wemm anglecnt++; 2790c2aa98e2SPeter Wemm break; 2791c2aa98e2SPeter Wemm 2792c2aa98e2SPeter Wemm case '>': 2793c2aa98e2SPeter Wemm if (anglecnt-- <= 0) 2794c2aa98e2SPeter Wemm return NULL; 2795c2aa98e2SPeter Wemm break; 2796c2aa98e2SPeter Wemm } 2797c2aa98e2SPeter Wemm *q++ = c; 2798c2aa98e2SPeter Wemm } 2799c2aa98e2SPeter Wemm 2800c2aa98e2SPeter Wemm if (anglecnt != 0 || cmntcnt != 0 || bslashmode || 2801c2aa98e2SPeter Wemm quotemode || quotecnt <= 0 || spacecnt != 0) 2802c2aa98e2SPeter Wemm return NULL; 2803c2aa98e2SPeter Wemm *q++ = '\0'; 2804c2aa98e2SPeter Wemm return map_rewrite(map, name, strlen(name), NULL); 2805c2aa98e2SPeter Wemm } 280640266059SGregory Neil Shapiro /* 2807c2aa98e2SPeter Wemm ** RSCHECK -- check string(s) for validity using rewriting sets 2808c2aa98e2SPeter Wemm ** 2809c2aa98e2SPeter Wemm ** Parameters: 2810c2aa98e2SPeter Wemm ** rwset -- the rewriting set to use. 2811c2aa98e2SPeter Wemm ** p1 -- the first string to check. 2812c2aa98e2SPeter Wemm ** p2 -- the second string to check -- may be null. 2813c2aa98e2SPeter Wemm ** e -- the current envelope. 281406f25ae9SGregory Neil Shapiro ** rmcomm -- remove comments? 281506f25ae9SGregory Neil Shapiro ** cnt -- count rejections (statistics)? 281640266059SGregory Neil Shapiro ** logl -- logging level. 2817193538b7SGregory Neil Shapiro ** host -- NULL or relay host. 281840266059SGregory Neil Shapiro ** logid -- id for sm_syslog. 2819c2aa98e2SPeter Wemm ** 2820c2aa98e2SPeter Wemm ** Returns: 2821c2aa98e2SPeter Wemm ** EX_OK -- if the rwset doesn't resolve to $#error 2822c2aa98e2SPeter Wemm ** else -- the failure status (message printed) 2823c2aa98e2SPeter Wemm */ 2824c2aa98e2SPeter Wemm 2825c2aa98e2SPeter Wemm int 282640266059SGregory Neil Shapiro rscheck(rwset, p1, p2, e, rmcomm, cnt, logl, host, logid) 2827c2aa98e2SPeter Wemm char *rwset; 2828c2aa98e2SPeter Wemm char *p1; 2829c2aa98e2SPeter Wemm char *p2; 2830c2aa98e2SPeter Wemm ENVELOPE *e; 283106f25ae9SGregory Neil Shapiro bool rmcomm, cnt; 283206f25ae9SGregory Neil Shapiro int logl; 2833193538b7SGregory Neil Shapiro char *host; 283440266059SGregory Neil Shapiro char *logid; 2835c2aa98e2SPeter Wemm { 283640266059SGregory Neil Shapiro char *volatile buf; 2837c2aa98e2SPeter Wemm int bufsize; 2838c2aa98e2SPeter Wemm int saveexitstat; 283940266059SGregory Neil Shapiro int volatile rstat = EX_OK; 2840c2aa98e2SPeter Wemm char **pvp; 2841c2aa98e2SPeter Wemm int rsno; 284240266059SGregory Neil Shapiro bool volatile discard = false; 2843c2aa98e2SPeter Wemm auto ADDRESS a1; 2844c2aa98e2SPeter Wemm bool saveQuickAbort = QuickAbort; 2845c2aa98e2SPeter Wemm bool saveSuprErrs = SuprErrs; 284640266059SGregory Neil Shapiro #if _FFR_QUARANTINE 284740266059SGregory Neil Shapiro bool quarantine = false; 284840266059SGregory Neil Shapiro char ubuf[BUFSIZ * 2]; 284940266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 2850c2aa98e2SPeter Wemm char buf0[MAXLINE]; 2851c2aa98e2SPeter Wemm char pvpbuf[PSBUFSIZE]; 2852c2aa98e2SPeter Wemm extern char MsgBuf[]; 2853c2aa98e2SPeter Wemm 2854c2aa98e2SPeter Wemm if (tTd(48, 2)) 285540266059SGregory Neil Shapiro sm_dprintf("rscheck(%s, %s, %s)\n", rwset, p1, 2856c2aa98e2SPeter Wemm p2 == NULL ? "(NULL)" : p2); 2857c2aa98e2SPeter Wemm 2858c2aa98e2SPeter Wemm rsno = strtorwset(rwset, NULL, ST_FIND); 2859c2aa98e2SPeter Wemm if (rsno < 0) 2860c2aa98e2SPeter Wemm return EX_OK; 2861c2aa98e2SPeter Wemm 2862c2aa98e2SPeter Wemm if (p2 != NULL) 2863c2aa98e2SPeter Wemm { 2864c2aa98e2SPeter Wemm bufsize = strlen(p1) + strlen(p2) + 2; 2865c2aa98e2SPeter Wemm if (bufsize > sizeof buf0) 286640266059SGregory Neil Shapiro buf = sm_malloc_x(bufsize); 2867c2aa98e2SPeter Wemm else 2868c2aa98e2SPeter Wemm { 2869c2aa98e2SPeter Wemm buf = buf0; 2870c2aa98e2SPeter Wemm bufsize = sizeof buf0; 2871c2aa98e2SPeter Wemm } 287240266059SGregory Neil Shapiro (void) sm_snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2); 2873c2aa98e2SPeter Wemm } 2874c2aa98e2SPeter Wemm else 2875c2aa98e2SPeter Wemm { 2876c2aa98e2SPeter Wemm bufsize = strlen(p1) + 1; 2877c2aa98e2SPeter Wemm if (bufsize > sizeof buf0) 287840266059SGregory Neil Shapiro buf = sm_malloc_x(bufsize); 2879c2aa98e2SPeter Wemm else 2880c2aa98e2SPeter Wemm { 2881c2aa98e2SPeter Wemm buf = buf0; 2882c2aa98e2SPeter Wemm bufsize = sizeof buf0; 2883c2aa98e2SPeter Wemm } 288440266059SGregory Neil Shapiro (void) sm_strlcpy(buf, p1, bufsize); 2885c2aa98e2SPeter Wemm } 288640266059SGregory Neil Shapiro SM_TRY 288740266059SGregory Neil Shapiro { 288840266059SGregory Neil Shapiro SuprErrs = true; 288940266059SGregory Neil Shapiro QuickAbort = false; 289006f25ae9SGregory Neil Shapiro pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL, 289106f25ae9SGregory Neil Shapiro rmcomm ? NULL : TokTypeNoC); 2892c2aa98e2SPeter Wemm SuprErrs = saveSuprErrs; 2893c2aa98e2SPeter Wemm if (pvp == NULL) 2894c2aa98e2SPeter Wemm { 2895c2aa98e2SPeter Wemm if (tTd(48, 2)) 289640266059SGregory Neil Shapiro sm_dprintf("rscheck: cannot prescan input\n"); 2897c2aa98e2SPeter Wemm /* 2898c2aa98e2SPeter Wemm syserr("rscheck: cannot prescan input: \"%s\"", 2899c2aa98e2SPeter Wemm shortenstring(buf, MAXSHORTSTR)); 2900c2aa98e2SPeter Wemm rstat = EX_DATAERR; 2901c2aa98e2SPeter Wemm */ 2902c2aa98e2SPeter Wemm goto finis; 2903c2aa98e2SPeter Wemm } 290440266059SGregory Neil Shapiro (void) REWRITE(pvp, rsno, e); 2905c2aa98e2SPeter Wemm if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET || 2906c2aa98e2SPeter Wemm pvp[1] == NULL || (strcmp(pvp[1], "error") != 0 && 2907c2aa98e2SPeter Wemm strcmp(pvp[1], "discard") != 0)) 2908c2aa98e2SPeter Wemm { 2909c2aa98e2SPeter Wemm goto finis; 2910c2aa98e2SPeter Wemm } 2911c2aa98e2SPeter Wemm 2912c2aa98e2SPeter Wemm if (strcmp(pvp[1], "discard") == 0) 2913c2aa98e2SPeter Wemm { 2914c2aa98e2SPeter Wemm if (tTd(48, 2)) 291540266059SGregory Neil Shapiro sm_dprintf("rscheck: discard mailer selected\n"); 2916c2aa98e2SPeter Wemm e->e_flags |= EF_DISCARD; 291740266059SGregory Neil Shapiro discard = true; 2918c2aa98e2SPeter Wemm } 291940266059SGregory Neil Shapiro #if _FFR_QUARANTINE 292040266059SGregory Neil Shapiro else if (strcmp(pvp[1], "error") == 0 && 292140266059SGregory Neil Shapiro pvp[2] != NULL && (pvp[2][0] & 0377) == CANONHOST && 292240266059SGregory Neil Shapiro pvp[3] != NULL && strcmp(pvp[3], "quarantine") == 0) 292340266059SGregory Neil Shapiro { 292440266059SGregory Neil Shapiro if (pvp[4] == NULL || 292540266059SGregory Neil Shapiro (pvp[4][0] & 0377) != CANONUSER || 292640266059SGregory Neil Shapiro pvp[5] == NULL) 292740266059SGregory Neil Shapiro e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, 292840266059SGregory Neil Shapiro rwset); 292940266059SGregory Neil Shapiro else 293040266059SGregory Neil Shapiro { 293140266059SGregory Neil Shapiro cataddr(&(pvp[5]), NULL, ubuf, 293240266059SGregory Neil Shapiro sizeof ubuf, ' '); 293340266059SGregory Neil Shapiro e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, 293440266059SGregory Neil Shapiro ubuf); 293540266059SGregory Neil Shapiro } 293640266059SGregory Neil Shapiro macdefine(&e->e_macro, A_PERM, 293740266059SGregory Neil Shapiro macid("{quarantine}"), e->e_quarmsg); 293840266059SGregory Neil Shapiro quarantine = true; 293940266059SGregory Neil Shapiro } 294040266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 2941c2aa98e2SPeter Wemm else 2942c2aa98e2SPeter Wemm { 2943c2aa98e2SPeter Wemm int savelogusrerrs = LogUsrErrs; 294440266059SGregory Neil Shapiro static bool logged = false; 2945c2aa98e2SPeter Wemm 2946c2aa98e2SPeter Wemm /* got an error -- process it */ 2947c2aa98e2SPeter Wemm saveexitstat = ExitStat; 294840266059SGregory Neil Shapiro LogUsrErrs = false; 2949c2aa98e2SPeter Wemm (void) buildaddr(pvp, &a1, 0, e); 2950c2aa98e2SPeter Wemm LogUsrErrs = savelogusrerrs; 2951c2aa98e2SPeter Wemm rstat = ExitStat; 2952c2aa98e2SPeter Wemm ExitStat = saveexitstat; 2953c2aa98e2SPeter Wemm if (!logged) 2954c2aa98e2SPeter Wemm { 295506f25ae9SGregory Neil Shapiro if (cnt) 295640266059SGregory Neil Shapiro markstats(e, &a1, STATS_REJECT); 295740266059SGregory Neil Shapiro logged = true; 2958c2aa98e2SPeter Wemm } 2959c2aa98e2SPeter Wemm } 2960c2aa98e2SPeter Wemm 296140266059SGregory Neil Shapiro if (LogLevel > logl) 2962c2aa98e2SPeter Wemm { 2963c2aa98e2SPeter Wemm char *relay; 2964c2aa98e2SPeter Wemm char *p; 2965c2aa98e2SPeter Wemm char lbuf[MAXLINE]; 2966c2aa98e2SPeter Wemm 2967c2aa98e2SPeter Wemm p = lbuf; 2968c2aa98e2SPeter Wemm if (p2 != NULL) 2969c2aa98e2SPeter Wemm { 297040266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(lbuf, p), 2971c2aa98e2SPeter Wemm ", arg2=%s", 2972c2aa98e2SPeter Wemm p2); 2973c2aa98e2SPeter Wemm p += strlen(p); 2974c2aa98e2SPeter Wemm } 2975193538b7SGregory Neil Shapiro 2976193538b7SGregory Neil Shapiro if (host != NULL) 2977193538b7SGregory Neil Shapiro relay = host; 2978193538b7SGregory Neil Shapiro else 2979193538b7SGregory Neil Shapiro relay = macvalue('_', e); 2980193538b7SGregory Neil Shapiro if (relay != NULL) 2981c2aa98e2SPeter Wemm { 298240266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(lbuf, p), 2983c2aa98e2SPeter Wemm ", relay=%s", relay); 2984c2aa98e2SPeter Wemm p += strlen(p); 2985c2aa98e2SPeter Wemm } 2986c2aa98e2SPeter Wemm *p = '\0'; 2987c2aa98e2SPeter Wemm if (discard) 298840266059SGregory Neil Shapiro sm_syslog(LOG_NOTICE, logid, 2989c2aa98e2SPeter Wemm "ruleset=%s, arg1=%s%s, discard", 2990c2aa98e2SPeter Wemm rwset, p1, lbuf); 299140266059SGregory Neil Shapiro #if _FFR_QUARANTINE 299240266059SGregory Neil Shapiro else if (quarantine) 299340266059SGregory Neil Shapiro sm_syslog(LOG_NOTICE, logid, 299440266059SGregory Neil Shapiro "ruleset=%s, arg1=%s%s, quarantine=%s", 299540266059SGregory Neil Shapiro rwset, p1, lbuf, ubuf); 299640266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 2997c2aa98e2SPeter Wemm else 299840266059SGregory Neil Shapiro sm_syslog(LOG_NOTICE, logid, 2999c2aa98e2SPeter Wemm "ruleset=%s, arg1=%s%s, reject=%s", 3000c2aa98e2SPeter Wemm rwset, p1, lbuf, MsgBuf); 3001c2aa98e2SPeter Wemm } 3002c2aa98e2SPeter Wemm 300340266059SGregory Neil Shapiro finis: ; 300440266059SGregory Neil Shapiro } 300540266059SGregory Neil Shapiro SM_FINALLY 300640266059SGregory Neil Shapiro { 3007c2aa98e2SPeter Wemm /* clean up */ 3008c2aa98e2SPeter Wemm if (buf != buf0) 30098774250cSGregory Neil Shapiro sm_free(buf); 301040266059SGregory Neil Shapiro QuickAbort = saveQuickAbort; 301140266059SGregory Neil Shapiro } 301240266059SGregory Neil Shapiro SM_END_TRY 3013c2aa98e2SPeter Wemm 301440266059SGregory Neil Shapiro setstat(rstat); 301540266059SGregory Neil Shapiro 301640266059SGregory Neil Shapiro /* rulesets don't set errno */ 301740266059SGregory Neil Shapiro errno = 0; 3018c2aa98e2SPeter Wemm if (rstat != EX_OK && QuickAbort) 301940266059SGregory Neil Shapiro sm_exc_raisenew_x(&EtypeQuickAbort, 2); 302040266059SGregory Neil Shapiro return rstat; 302140266059SGregory Neil Shapiro } 302240266059SGregory Neil Shapiro /* 302340266059SGregory Neil Shapiro ** RSCAP -- call rewriting set to return capabilities 302440266059SGregory Neil Shapiro ** 302540266059SGregory Neil Shapiro ** Parameters: 302640266059SGregory Neil Shapiro ** rwset -- the rewriting set to use. 302740266059SGregory Neil Shapiro ** p1 -- the first string to check. 302840266059SGregory Neil Shapiro ** p2 -- the second string to check -- may be null. 302940266059SGregory Neil Shapiro ** e -- the current envelope. 303040266059SGregory Neil Shapiro ** pvp -- pointer to token vector. 303140266059SGregory Neil Shapiro ** pvpbuf -- buffer space. 303240266059SGregory Neil Shapiro ** 303340266059SGregory Neil Shapiro ** Returns: 303440266059SGregory Neil Shapiro ** EX_UNAVAILABLE -- ruleset doesn't exist. 303540266059SGregory Neil Shapiro ** EX_DATAERR -- prescan() failed. 303640266059SGregory Neil Shapiro ** EX_OK -- rewrite() was successful. 303740266059SGregory Neil Shapiro ** else -- return status from rewrite(). 303840266059SGregory Neil Shapiro */ 303940266059SGregory Neil Shapiro 304040266059SGregory Neil Shapiro int 304140266059SGregory Neil Shapiro rscap(rwset, p1, p2, e, pvp, pvpbuf, size) 304240266059SGregory Neil Shapiro char *rwset; 304340266059SGregory Neil Shapiro char *p1; 304440266059SGregory Neil Shapiro char *p2; 304540266059SGregory Neil Shapiro ENVELOPE *e; 304640266059SGregory Neil Shapiro char ***pvp; 304740266059SGregory Neil Shapiro char *pvpbuf; 304840266059SGregory Neil Shapiro int size; 304940266059SGregory Neil Shapiro { 305040266059SGregory Neil Shapiro char *volatile buf; 305140266059SGregory Neil Shapiro int bufsize; 305240266059SGregory Neil Shapiro int volatile rstat = EX_OK; 305340266059SGregory Neil Shapiro int rsno; 305440266059SGregory Neil Shapiro bool saveQuickAbort = QuickAbort; 305540266059SGregory Neil Shapiro bool saveSuprErrs = SuprErrs; 305640266059SGregory Neil Shapiro char buf0[MAXLINE]; 305740266059SGregory Neil Shapiro extern char MsgBuf[]; 305840266059SGregory Neil Shapiro 305940266059SGregory Neil Shapiro if (tTd(48, 2)) 306040266059SGregory Neil Shapiro sm_dprintf("rscap(%s, %s, %s)\n", rwset, p1, 306140266059SGregory Neil Shapiro p2 == NULL ? "(NULL)" : p2); 306240266059SGregory Neil Shapiro 306340266059SGregory Neil Shapiro if (pvp != NULL) 306440266059SGregory Neil Shapiro *pvp = NULL; 306540266059SGregory Neil Shapiro rsno = strtorwset(rwset, NULL, ST_FIND); 306640266059SGregory Neil Shapiro if (rsno < 0) 306740266059SGregory Neil Shapiro return EX_UNAVAILABLE; 306840266059SGregory Neil Shapiro 306940266059SGregory Neil Shapiro if (p2 != NULL) 307040266059SGregory Neil Shapiro { 307140266059SGregory Neil Shapiro bufsize = strlen(p1) + strlen(p2) + 2; 307240266059SGregory Neil Shapiro if (bufsize > sizeof buf0) 307340266059SGregory Neil Shapiro buf = sm_malloc_x(bufsize); 307440266059SGregory Neil Shapiro else 307540266059SGregory Neil Shapiro { 307640266059SGregory Neil Shapiro buf = buf0; 307740266059SGregory Neil Shapiro bufsize = sizeof buf0; 307840266059SGregory Neil Shapiro } 307940266059SGregory Neil Shapiro (void) sm_snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2); 308040266059SGregory Neil Shapiro } 308140266059SGregory Neil Shapiro else 308240266059SGregory Neil Shapiro { 308340266059SGregory Neil Shapiro bufsize = strlen(p1) + 1; 308440266059SGregory Neil Shapiro if (bufsize > sizeof buf0) 308540266059SGregory Neil Shapiro buf = sm_malloc_x(bufsize); 308640266059SGregory Neil Shapiro else 308740266059SGregory Neil Shapiro { 308840266059SGregory Neil Shapiro buf = buf0; 308940266059SGregory Neil Shapiro bufsize = sizeof buf0; 309040266059SGregory Neil Shapiro } 309140266059SGregory Neil Shapiro (void) sm_strlcpy(buf, p1, bufsize); 309240266059SGregory Neil Shapiro } 309340266059SGregory Neil Shapiro SM_TRY 309440266059SGregory Neil Shapiro { 309540266059SGregory Neil Shapiro SuprErrs = true; 309640266059SGregory Neil Shapiro QuickAbort = false; 309740266059SGregory Neil Shapiro *pvp = prescan(buf, '\0', pvpbuf, size, NULL, NULL); 309840266059SGregory Neil Shapiro if (*pvp != NULL) 309940266059SGregory Neil Shapiro rstat = REWRITE(*pvp, rsno, e); 310040266059SGregory Neil Shapiro else 310140266059SGregory Neil Shapiro { 310240266059SGregory Neil Shapiro if (tTd(48, 2)) 310340266059SGregory Neil Shapiro sm_dprintf("rscap: cannot prescan input\n"); 310440266059SGregory Neil Shapiro rstat = EX_DATAERR; 310540266059SGregory Neil Shapiro } 310640266059SGregory Neil Shapiro } 310740266059SGregory Neil Shapiro SM_FINALLY 310840266059SGregory Neil Shapiro { 310940266059SGregory Neil Shapiro /* clean up */ 311040266059SGregory Neil Shapiro if (buf != buf0) 311140266059SGregory Neil Shapiro sm_free(buf); 311240266059SGregory Neil Shapiro SuprErrs = saveSuprErrs; 311340266059SGregory Neil Shapiro QuickAbort = saveQuickAbort; 311440266059SGregory Neil Shapiro 311540266059SGregory Neil Shapiro /* prevent information leak, this may contain rewrite error */ 311640266059SGregory Neil Shapiro MsgBuf[0] = '\0'; 311740266059SGregory Neil Shapiro } 311840266059SGregory Neil Shapiro SM_END_TRY 3119c2aa98e2SPeter Wemm return rstat; 3120c2aa98e2SPeter Wemm } 3121