1N/A * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers. 1N/A * All rights reserved. 1N/A * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 1N/A * Copyright (c) 1988, 1993 1N/A * The Regents of the University of California. All rights reserved. 1N/A * By using this file, you agree to the terms and conditions set 1N/A * forth in the LICENSE file which can be found at the top level of 1N/A * the sendmail distribution. 1N/A/* replacement for illegal characters in addresses */ 1N/A** PARSEADDR -- Parse an address 1N/A** Parses an address and breaks it up into three parts: a 1N/A** net to transmit the message on, the host to transmit it 1N/A** to, and a user on that host. These are loaded into an 1N/A** ADDRESS header with the values squirreled away if necessary. 1N/A** The "user" part may not be a real user; the process may 1N/A** just reoccur on that machine. For example, on a machine 1N/A** with an arpanet connection, the address 1N/A** csvax.bill@berkeley 1N/A** will break up to a "user" of 'csvax.bill' and a host 1N/A** of 'berkeley' -- to be transmitted over the arpanet. 1N/A** addr -- the address to parse. 1N/A** a -- a pointer to the address descriptor buffer. 1N/A** If NULL, an address will be created. 1N/A** flags -- describe detail for parsing. See RF_ definitions 1N/A** delim -- the character to terminate the address, passed 1N/A** delimptr -- if non-NULL, set to the location of the 1N/A** delim character that was found. 1N/A** e -- the envelope that will contain this address. 1N/A** isrcpt -- true if the address denotes a recipient; false 1N/A** indicates a sender. 1N/A** A pointer to the address descriptor header (`a' if 1N/A/* following delimiters are inherent to the internal algorithms */ 1N/A ** Initialize and prescan address. 1N/A ** Save addr if we are going to have to. 1N/A ** We have to do this early because there is a chance that 1N/A ** the map lookups in the rewriting rules could clobber 1N/A ** static memory somewhere. 1N/A ** Apply rewriting rules. 1N/A ** Ruleset 0 does basic parsing. It must resolve. 1N/A ** Build canonical address from pvp. 1N/A ** Just mark the address as bad so DSNs work. 1N/A ** hasctrlchar() has to make sure that the address 1N/A ** has been sanitized, e.g., shortened. 1N/A ** Make local copies of the host & user and then 1N/A ** transport them out. 1N/A /* weed out bad characters in the printable address too */ 1N/A ** Select a queue directory for recipient addresses. 1N/A ** This is done here and in split_across_queue_groups(), 1N/A ** but the latter applies to addresses after aliasing, 1N/A ** and only if splitting is done. 1N/A /* call ruleset which should return a queue group name */ 1N/A "can't find queue group name %s, selection ignored",
1N/A "queue group name %s -> %d",
1N/A ** If there was a parsing failure, mark it for queueing. 1N/A char *
msg =
"Transient parse error -- message queued for future delivery";
1N/A msg =
"Deferring message until queue run";
1N/A ** Compute return value. 1N/A** INVALIDADDR -- check for address containing characters used for macros 1N/A** addr -- the address to check. 1N/A** delimptr -- if non-NULL: end of address to check, i.e., 1N/A** a pointer in the address string. 1N/A** isrcpt -- true iff the address is for a recipient. 1N/A** true -- if the address has characters that are reservered 1N/A** for macros or is too long. 1N/A** false -- otherwise. 1N/A /* delimptr points to the end of the address to test */ 1N/A usrerr(
"553 5.1.0 Address \"%s\" too long (%d bytes max)",
1N/A usrerr(
"501 5.1.3 8-bit character in mailbox address \"%s\"",
1N/A usrerr(
"501 5.1.7 8-bit character in mailbox address \"%s\"",
1N/A** HASCTRLCHAR -- check for address containing meta-characters 1N/A** Checks that the address contains no meta-characters, and contains 1N/A** no "non-printable" characters unless they are quoted or escaped. 1N/A** Quoted or escaped characters are literals. 1N/A** addr -- the address to check. 1N/A** isrcpt -- true if the address is for a recipient; false 1N/A** complain -- true if an error should issued if the address 1N/A** is invalid and should be "repaired". 1N/A** true -- if the address has any "weird" characters or 1N/A** non-printable characters or if a quote is unbalanced. 1N/A** false -- otherwise. 1N/A usrerr(
"553 5.1.0 Address \"%s\" too long (%d bytes max)",
1N/A /* XXX Generic problem: no '\0' in strings. */ 1N/A result =
"unbalanced quote";
/* unbalanced quote */ 1N/A usrerr(
"501 5.1.3 Syntax error in mailbox address \"%s\" (%s)",
1N/A usrerr(
"501 5.1.7 Syntax error in mailbox address \"%s\" (%s)",
1N/A** ALLOCADDR -- do local allocations of address on demand. 1N/A** Also lowercases the host name if requested. 1N/A** a -- the address to reallocate. 1N/A** for a description). 1N/A** paddr -- the printname of the address. 1N/A** Copies portions of a into local buffers as requested. 1N/A** PRESCAN -- Prescan name and make it canonical 1N/A** Scans a name and turns it into a set of tokens. This process 1N/A** deletes blanks and comments (in parentheses) (if the token type 1N/A** for left paren is SPC). 1N/A** This routine knows about quoted strings and angle brackets. 1N/A** There are certain subtleties to this routine. The one that 1N/A** comes to mind now is that backslashes on the ends of names 1N/A** are silently stripped off; this is intentional. The problem 1N/A** is that some versions of sndmsg (like at LBL) set the kill 1N/A** character to something other than @ when reading addresses; 1N/A** so people type "csvax.eric\@berkeley" -- which screws up the 1N/A** addr -- the name to chomp. 1N/A** delim -- the delimiter for the address, normally 1N/A** '\0' or ','; \0 is accepted in any case. 1N/A** If '\t' then we are reading the .cf file. 1N/A** pvpbuf -- place to put the saved text -- note that 1N/A** the pointers are static. 1N/A** pvpbsize -- size of pvpbuf. 1N/A** delimptr -- if non-NULL, set to the location of the 1N/A** terminating delimiter. 1N/A** toktab -- if set, a token table to use for parsing. 1N/A** If NULL, use the default table. 1N/A** ignore -- if true, ignore unbalanced addresses 1N/A** A pointer to a vector of tokens. 1N/A/* states and character types */ 1N/A#
define QST 2 /* in quoted string */ 1N/A#
define SPC 3 /* chewing up spaces */ 1N/A#
define ONE 4 /* pick up one character */ 1N/A#
define ILL 5 /* illegal character */ 1N/A#
define TYPE 0
17 /* mask to select state type */ 1N/A/* meta bits for table */ 1N/A#
define M 0
20 /* meta character; don't pass through */ 1N/A#
define B 0
40 /* cause a break */ 1N/A#
define MB M|B
/* meta-break */ 1N/A /* oldst chtype> OPR ATM QST SPC ONE ILL */ 1N/A/* these all get modified with the OperatorChars */ 1N/A/* token type table for external strings */ 1N/A /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
SPC,
SPC,
SPC,
SPC,
SPC,
ATM,
ATM,
1N/A /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* sp ! " # $ % & ' ( ) * + , - . / */ 1N/A SPC,
ATM,
QST,
ATM,
ATM,
ATM,
ATM,
ATM,
SPC,
SPC,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* @ A B C D E F G H I J K L M N O */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* ` a b c d e f g h i j k l m n o */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* p q r s t u v w x y z { | } ~ del */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* sp ! " # $ % & ' ( ) * + , - . / */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* @ A B C D E F G H I J K L M N O */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* ` a b c d e f g h i j k l m n o */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* p q r s t u v w x y z { | } ~ del */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM 1N/A/* token type table for internal strings */ 1N/A /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
SPC,
SPC,
SPC,
SPC,
SPC,
ATM,
ATM,
1N/A /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* sp ! " # $ % & ' ( ) * + , - . / */ 1N/A SPC,
ATM,
QST,
ATM,
ATM,
ATM,
ATM,
ATM,
SPC,
SPC,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* @ A B C D E F G H I J K L M N O */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* ` a b c d e f g h i j k l m n o */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* p q r s t u v w x y z { | } ~ del */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 1N/A OPR,
OPR,
ONE,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
1N/A /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 1N/A OPR,
OPR,
OPR,
ONE,
ONE,
ONE,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
1N/A /* sp ! " # $ % & ' ( ) * + , - . / */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* @ A B C D E F G H I J K L M N O */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* ` a b c d e f g h i j k l m n o */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* p q r s t u v w x y z { | } ~ del */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ONE 1N/A/* token type table for MIME parsing */ 1N/A /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
SPC,
SPC,
SPC,
SPC,
SPC,
ILL,
ILL,
1N/A /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
1N/A /* sp ! " # $ % & ' ( ) * + , - . / */ 1N/A SPC,
ATM,
QST,
ATM,
ATM,
ATM,
ATM,
ATM,
SPC,
SPC,
ATM,
ATM,
OPR,
ATM,
ATM,
OPR,
1N/A /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
1N/A /* @ A B C D E F G H I J K L M N O */ 1N/A OPR,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
OPR,
OPR,
OPR,
ATM,
ATM,
1N/A /* ` a b c d e f g h i j k l m n o */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* p q r s t u v w x y z { | } ~ del */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
1N/A /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
1N/A /* sp ! " # $ % & ' ( ) * + , - . / */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
1N/A /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
1N/A /* @ A B C D E F G H I J K L M N O */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
1N/A /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
1N/A /* ` a b c d e f g h i j k l m n o */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
1N/A /* p q r s t u v w x y z { | } ~ del */ 1N/A ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ILL,
ONE 1N/A/* token type table: don't strip comments */ 1N/A /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
SPC,
SPC,
SPC,
SPC,
SPC,
ATM,
ATM,
1N/A /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* sp ! " # $ % & ' ( ) * + , - . / */ 1N/A SPC,
ATM,
QST,
ATM,
ATM,
ATM,
ATM,
ATM,
OPR,
OPR,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* @ A B C D E F G H I J K L M N O */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* ` a b c d e f g h i j k l m n o */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* p q r s t u v w x y z { | } ~ del */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ 1N/A OPR,
OPR,
ONE,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
1N/A /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ 1N/A OPR,
OPR,
OPR,
ONE,
ONE,
ONE,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
OPR,
1N/A /* sp ! " # $ % & ' ( ) * + , - . / */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* @ A B C D E F G H I J K L M N O */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* P Q R S T U V W X Y Z [ \ ] ^ _ */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* ` a b c d e f g h i j k l m n o */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
1N/A /* p q r s t u v w x y z { | } ~ del */ 1N/A ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ATM,
ONE 1N/A#
define NOCHAR (-
1)
/* signal nothing in lookahead token */ 1N/A /* initialize the token type table */ 1N/A /* make sure error messages don't have garbage on them */ 1N/A /* store away any old lookahead character */ 1N/A /* see if there is room */ 1N/A /* squirrel it away */ 1N/A if ((
char) c == (
char) -
1 && !
tTd(
82,
101) &&
1N/A#
endif /* !ALLOW_255 */ 1N/A /* read a new input character */ 1N/A c = (*p++) &
0x00ff;
1N/A /* diagnose and patch up bad syntax */ 1N/A /* special case for better error management */ 1N/A /* chew up special characters */ 1N/A /* kludge \! for naive users */ 1N/A /* see if there is room */ 1N/A /* do nothing, just avoid next clauses */ 1N/A /* see if this is end of input */ 1N/A /* see if there is room */ 1N/A usrerr(
"553 5.1.0 prescan: too many tokens");
1N/A** REWRITE -- apply rewrite rules to token vector. 1N/A** This routine is an ordered production system. Each rewrite 1N/A** rule has a LHS (called the pattern) and a RHS (called the 1N/A** rewrite); 'rwr' points the the current rewrite rule. 1N/A** For each rewrite rule, 'avp' points the address vector we 1N/A** are trying to match against, and 'pvp' points to the pattern. 1N/A** If pvp points to a special match value (MATCHZANY, MATCHANY, 1N/A** MATCHONE, MATCHCLASS, MATCHNCLASS) then the address in avp 1N/A** matched is saved away in the match vector (pointed to by 'mvp'). 1N/A** When a match between avp & pvp does not match, we try to 1N/A** back out. If we back up over MATCHONE, MATCHCLASS, or MATCHNCLASS 1N/A** we must also back out the match in mvp. If we reach a 1N/A** MATCHANY or MATCHZANY we just extend the match and start 1N/A** When we finally match, we rewrite the address vector 1N/A** and try over again. 1N/A** pvp -- pointer to token vector. 1N/A** ruleset -- the ruleset to use for rewriting. 1N/A** reclevel -- recursion level (to catch loops). 1N/A** e -- the current envelope. 1N/A** maxatom -- maximum length of buffer (usually MAXATOM) 1N/A** A status code. If EX_TEMPFAIL, higher level code should 1N/A register char *
ap;
/* address pointer */ 1N/A register char *
rp;
/* rewrite pointer */ 1N/A register char **
avp;
/* address vector pointer */ 1N/A register char **
rvp;
/* rewrite vector pointer */ 1N/A register struct rewrite *
rwr;
/* pointer to current rewrite rule */ 1N/A ** mlp will not exceed mlist[] because readcf enforces 1N/A ** the upper limit of entries when reading rulesets. 1N/A syserr(
"rewrite: excessive recursion (max %d), ruleset %s",
1N/A ** Run through the list of rewrite rules, applying 1N/A /* if already canonical, quit now */ 1N/A /* try to match on this rule */ 1N/A syserr(
"554 5.3.5 Infinite loop in ruleset %s, rule %d",
1N/A /* end-of-pattern before end-of-address */ 1N/A /* end-of-input with patterns left */ 1N/A /* match any phrase in a class */ 1N/A /* match any token not in a class */ 1N/A /* match exactly one token */ 1N/A /* match zero or more tokens */ 1N/A /* match zero tokens */ 1N/A ** Match against run-time macro. 1N/A ** This algorithm is broken for the 1N/A ** general case (no recursive macros, 1N/A ** improper tokenization) but should 1N/A ** work for the usual cases. 1N/A /* must have exact match */ 1N/A /* successful match on this token */ 1N/A /* match failed -- back up */ 1N/A /* run off the end -- back up again */ 1N/A /* extend binding and continue */ 1N/A /* extend binding and try again */ 1N/A /* total failure to match */ 1N/A ** See if we successfully matched 1N/A /* substitute from LHS */ 1N/A syserr(
"554 5.3.5 rewrite: ruleset %s: replacement $%c out of bounds",
1N/A /* some sort of replacement */ 1N/A syserr(
"554 5.3.0 rewrite: expansion too long");
1N/A "rewrite: expansion too long, ruleset=%s, ruleno=%d",
1N/A /* vanilla replacement from RHS */ 1N/A /* $&{x} replacement */ 1N/A /* save the remainder of the input */ 1N/A /* scan the new replacement */ 1N/A /* prescan pre-printed error */ 1N/A /* insert it into the output stream */ 1N/A /* restore the old trailing input */ 1N/A syserr(
"554 5.3.0 rewrite: missing mapname");
1N/A ** This could be optimized fairly easily. 1N/A syserr(
"554 5.3.0 rewrite: map %s not found",
1N/A /* extract the match part */ 1N/A syserr(
"554 5.3.0 rewrite: missing key for map %s",
1N/A /* save the remainder of the input string */ 1N/A /* if no replacement, use default */ 1N/A /* create the default */ 1N/A /* null replacement */ 1N/A /* scan the new replacement */ 1N/A /* prescan already printed error */ 1N/A /* append it to the token list */ 1N/A /* restore the old trailing information */ 1N/A ** Check for subroutine calls. 1N/A /* copy vector back into original space. */ 1N/A** CALLSUBR -- call subroutines in rewrite vector 1N/A** pvp -- pointer to token vector. 1N/A** reclevel -- the current recursion level. 1N/A** e -- the current envelope. 1N/A** The status from the subroutine call. 1N/A ** Look for subroutine calls in pvp, collect them into subr*[] 1N/A ** We will perform the calls in the next loop, because we will 1N/A ** call the "last" subroutine first to avoid recursive calls 1N/A ** and too much copying. 1N/A ** XXX instead of doing this we could optimize 1N/A ** the rules after reading them: just remove 1N/A ** calls to empty rulesets 1N/A /* subroutine is an empty ruleset? don't call it */ 1N/A syserr(
"554 5.3.0 Too many subroutine calls (%d max)",
1N/A ** Perform the actual subroutines calls, "last" one first, i.e., 1N/A ** go from the right to the left through all calls, 1N/A ** do the rewriting in place. 1N/A /* remove the subroutine call and name */ 1N/A ** Now we need to call the ruleset specified for 1N/A ** the subroutine. We can do this in place since 1N/A ** we call the "last" subroutine first. 1N/A** MAP_LOOKUP -- do lookup in map 1N/A** smap -- the map to use for the lookup. 1N/A** key -- the key to look up. 1N/A** argvect -- arguments to pass to the map lookup. 1N/A** pstat -- a pointer to an integer in which to store the 1N/A** status from the lookup. 1N/A** e -- the current envelope. 1N/A** The result of the lookup. 1N/A** NULL -- if there was no data for the given key. 1N/A /* don't do any map lookups */ 1N/A /* should recover if status == EX_TEMPFAIL */ 1N/A "%.80s map: lookup (%s): deferred",
1N/A** INITERRMAILERS -- initialize error and discard mailers 1N/A** initializes error and discard mailers. 1N/A /* initialize the discard mailer */ 1N/A /* initialize the bogus mailer */ 1N/A** BUILDADDR -- build address from token vector. 1N/A** tv -- token vector. 1N/A** a -- pointer to address descriptor to fill. 1N/A** If NULL, one will be allocated. 1N/A** flags -- info regarding whether this is a sender or 1N/A** e -- the current envelope. 1N/A** NULL if there was an error. 1N/A /* set up default error return flags */ 1N/A syserr(
"554 5.3.5 buildaddr: no mailer in parsed address");
1N/A ** ExitStat may have been set by an earlier map open 1N/A ** failure (to a permanent error (EX_OSERR) in syserr()) 1N/A ** so we also need to check if this particular $#error 1N/A ** return wanted a 4XX failure. 1N/A ** XXX the real fix is probably to set ExitStat correctly, 1N/A ** i.e., to EX_TEMPFAIL if the map open is just a temporary 1N/A /* extract host and user portions */ 1N/A /* save away the host name */ 1N/A /* Set up triplet for use by -bv */ 1N/A /* XXX wrong place? */ 1N/A /* XXX ubuf[off - 1] = ' '; */ 1N/A /* figure out what host (if any) */ 1N/A /* figure out the user */ 1N/A /* do special mapping for local mailer */ 1N/A /* may be :include: */ 1N/A /* if :include:, don't need further rewriting */ 1N/A /* rewrite according recipient mailer rewriting rules */ 1N/A /* sender addresses done later */ 1N/A /* save the result for the command line/RCPT argument */ 1N/A ** Do mapping to lower case as requested by mailer 1N/A** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs) 1N/A** pvp -- parameter vector to rebuild. 1N/A** evp -- last parameter to include. Can be NULL to 1N/A** buf -- buffer to build the string into. 1N/A** sz -- size of buf. 1N/A** spacesub -- the space separator character; if '\0', 1N/A** external -- convert to external form? 1N/A** (no metacharacters; METAQUOTEs removed, see below) 1N/A** There are two formats for strings: internal and external. 1N/A** The external format is just an eight-bit clean string (no 1N/A** null bytes, everything else OK). The internal format can 1N/A** include sendmail metacharacters. The special character 1N/A** METAQUOTE essentially quotes the character following, stripping 1N/A** it of all special semantics. 1N/A** The cataddr routine needs to be aware of whether it is producing 1N/A** an internal or external form as output (it only takes internal 1N/A** The parseaddr routine has a similar issue on input, but that 1N/A** is flagged on the basis of which token table is passed in. 1N/A ** If the current character (c) is METAQUOTE and we 1N/A ** want the "external" form and the next character 1N/A ** is not NUL, then overwrite METAQUOTE with that 1N/A ** character (i.e., METAQUOTE ch is changed to 1N/A ** ch). p[-1] is used because p is advanced (above). 1N/A ** Silently truncate long strings: even though this doesn't 1N/A ** seem like a good idea it is necessary because header checks 1N/A ** send the whole header value to rscheck() and hence rewrite(). 1N/A ** The latter however sometimes uses a "short" buffer (e.g., 1N/A ** cbuf[MAXNAME + 1]) to call cataddr() which then triggers this 1N/A ** error function. One possible fix to the problem is to pass 1N/A ** flags to rscheck() and rewrite() to distinguish the various 1N/A ** calls and only trigger the error if necessary. For now just 1N/A ** undo the change from 8.13.0. 1N/A** SAMEADDR -- Determine if two addresses are the same 1N/A** This is not just a straight comparison -- if the mailer doesn't 1N/A** care about the host we just ignore it, etc. 1N/A** a, b -- pointers to the internal forms to compare. 1N/A** true -- they represent the same mailbox. 1N/A** false -- they don't. 1N/A /* if they don't have the same mailer, forget it */ 1N/A /* if the user isn't the same, we can drop out */ 1N/A /* if we have good uids for both but they differ, these are different */ 1N/A /* otherwise compare hosts (but be careful for NULL ptrs) */ 1N/A /* probably both null pointers */ 1N/A /* only one is a null pointer */ 1N/A** PRINTADDR -- print address (for debugging) 1N/A** a -- the address to print 1N/A** follow -- follow the q_next chain. 1N/A /* find the mailer -- carefully */ 1N/A "%s:\n\tmailer %d (%s), host `%s'\n",
1N/A "\tuser `%s', ruser `%s'\n",
1N/A ", next=%p, alias %p, uid %d, gid %d\n",
1N/A "\towner=%s, home=\"%s\", fullname=\"%s\"\n",
1N/A "\torcpt=\"%s\", statmta=%s, status=%s\n",
1N/A "\tfinalrcpt=\"%s\"\n",
1N/A "\trstatus=\"%s\"\n",
1N/A** EMPTYADDR -- return true if this address is empty (``<>'') 1N/A** a -- pointer to the address 1N/A** true -- if this address is "empty" (i.e., no one should 1N/A** ever generate replies to it. 1N/A** false -- if it is a "regular" (read: replyable) address. 1N/A** REMOTENAME -- return the name relative to the current mailer 1N/A** name -- the name to translate. 1N/A** m -- the mailer that we want to do rewriting relative to. 1N/A** flags -- fine tune operations. 1N/A** pstat -- pointer to status word. 1N/A** e -- the current envelope. 1N/A** the text string representing this address relative to 1N/A** the receiving mailer. 1N/A** The text string returned is tucked away locally; 1N/A** copy it if you intend to save it. 1N/A /* don't do anything if we are tagging it as special */ 1N/A ** Do a heuristic crack of this name to extract any comment info. 1N/A ** This will leave the name as a comment and a $g macro. 1N/A ** Turn the name into canonical form. 1N/A ** Normally this will be RFC 822 style, i.e., "user@domain". 1N/A ** If this only resolves to "user", and the "C" flag is 1N/A ** specified in the sending mailer, then the sender's 1N/A ** domain will be appended. 1N/A /* append from domain to this address */ 1N/A /* see if there is an "@domain" in the current name */ 1N/A /* no.... append the "@domain" from the sender */ 1N/A usrerr(
"553 5.1.0 remotename: too many tokens");
1N/A ** Do more specific rewriting. 1N/A ** Rewrite using ruleset 1 or 2 depending on whether this is 1N/A ** a sender address or not. 1N/A ** Then run it through any receiving-mailer-specific rulesets. 1N/A ** Do any final sanitation the address may require. 1N/A ** This will normally be used to turn internal forms 1N/A ** (e.g., user@host.LOCAL) into external form. This 1N/A ** may be used as a default to the above rules. 1N/A ** Now restore the comment information we had at the beginning. 1N/A /* need to make sure route-addrs have <angle brackets> */ 1N/A** MAPLOCALUSER -- run local username through ruleset 5 for final redirection 1N/A** a -- the address to map (but just the user name part). 1N/A** sendq -- the sendq in which to install any replacement 1N/A** aliaslevel -- the alias nesting depth. 1N/A** e -- the envelope. 1N/A ** mark address as bad, S5 returned an error 1N/A ** and we gave that back to the SMTP client. 1N/A /* if non-null, mailer destination specified -- has it changed? */ 1N/A /* make new address take on flags and print attributes of old */ 1N/A /* mark old address as dead; insert new address */ 1N/A** DEQUOTE_INIT -- initialize dequote map 1N/A** map -- the internal map structure. 1N/A** args -- arguments. 1N/A /* there is no check whether there is really an argument */ 1N/A** DEQUOTE_MAP -- unquote an address 1N/A** map -- the internal map structure (ignored). 1N/A** name -- the name to dequote. 1N/A** av -- arguments (ignored). 1N/A** statp -- pointer to status out-parameter. 1N/A** NULL -- if there were no quotes, or if the resulting 1N/A** unquoted buffer would not be acceptable to prescan. 1N/A** else -- The dequoted buffer. 1N/A for (p = q =
name; (c = *p++) !=
'\0'; )
1N/A** RSCHECK -- check string(s) for validity using rewriting sets 1N/A** rwset -- the rewriting set to use. 1N/A** p1 -- the first string to check. 1N/A** p2 -- the second string to check -- may be null. 1N/A** e -- the current envelope. 1N/A** logl -- logging level. 1N/A** host -- NULL or relay host. 1N/A** logid -- id for sm_syslog. 1N/A** addr -- if not NULL and ruleset returns $#error: 1N/A** store mailer triple here. 1N/A** EX_OK -- if the rwset doesn't resolve to $#error 1N/A** else -- the failure status (message printed) 1N/A syserr("rscheck: cannot prescan input: \"%s\"", 1N/A shortenstring(buf, MAXSHORTSTR)); 1N/A /* got an error -- process it */ 1N/A "ruleset=%s, arg1=%s%s, discard",
1N/A "ruleset=%s, arg1=%s%s, quarantine=%s",
1N/A "ruleset=%s, arg1=%s%s, reject=%s",
1N/A /* rulesets don't set errno */ 1N/A** RSCAP -- call rewriting set to return capabilities 1N/A** rwset -- the rewriting set to use. 1N/A** p1 -- the first string to check. 1N/A** p2 -- the second string to check -- may be null. 1N/A** e -- the current envelope. 1N/A** pvp -- pointer to token vector. 1N/A** pvpbuf -- buffer space. 1N/A** size -- size of buffer space. 1N/A** EX_UNAVAILABLE -- ruleset doesn't exist. 1N/A** EX_DATAERR -- prescan() failed. 1N/A** EX_OK -- rewrite() was successful. 1N/A** else -- return status from rewrite(). 1N/A /* prevent information leak, this may contain rewrite error */