home *** CD-ROM | disk | FTP | other *** search
- Subject: v08i053: Ease, a language for writing sendmail.cf files, Part01/04
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: ksb@j.cc.purdue.edu
- Mod.sourbes: Volume 8, Issue 53
- Archive-name: ease/Part01
-
- The Ease language is a high-level specification format for sendmail's
- configuration file. The motivation for its development was to fulfill
- a goal of providing a readable and easily modifiable sendmail
- configuration file format. Ease fulfills this goal by shielding the
- programmer from the cryptic configuration specification required by
- sendmail and providing a high-level language with which the programmer
- may specify all modifications to a configuration file. The development
- of Ease coincided with the development of an Ease translator, et, which
- translates a configuration file written in Ease to an equivalent file
- of the standard format accepted by sendmail.
-
- Please let Kevin Braunsdorf, "ksb@j.cc.purdue.edu" know if you make any
- modifications to Ease; he's taking care of this now (the original
- author has since left Purdue) and we'd really like to keep the released
- version exactly in step with our local version in order to make
- supporting this a lot easier.
-
- Thanks,
- "Wombat" <rsk@j.cc.purdue.edu>
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- #----cut here-----cut here-----cut here-----cut here----#
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # doc
- # src
- mkdir doc
- chdir doc
- cat << \SHAR_EOF > ap1
- .DS C
- \s+5\fBAppendix A\fR
-
-
- \fBPre-Declared Macros\fR\s-5
- .DE
- .sp 5
- .TS
- center box;
- c|c|c
- l|l|l.
- \fBEase\fR Macro Raw Equivalent Meaning*
- =
- \fIm_odate\fR a The origination date in Arpanet format
- \fIm_adate\fR b The current date in Arpanet format
- \fIm_hops\fR c The hop count
- \fIm_udate\fR d The date in UNIX (ctime) format
- \fIm_smtp\fR e The SMTP entry message
- \fIm_saddr\fR f The sender (from) address
- \fIm_sreladdr\fR g The sender address relative to the recipient
- \fIm_rhost\fR h The recipient host
- \fIm_qid\fR i The queue id
- \fIm_oname\fR j The official domain name for this site
- \fIm_ufrom\fR l The format of the UNIX from line
- \fIm_daemon\fR n The name of the daemon (for error messages)
- \fIm_addrops\fR o The set of "operators" in addresses
- \fIm_pid\fR p Sendmail's pid
- \fIm_defaddr\fR q The default format of sender address
- \fIm_protocol\fR r Protocol used
- \fIm_shostname\fR s Sender's host name
- \fIm_ctime\fR t A numeric representation of the current time
- \fIm_ruser\fR u The recipient user
- \fIm_version\fR v The version number of sendmail
- \fIm_sitename\fR w The hostname of this site
- \fIm_sname\fR x The full name of the sender
- \fIm_stty\fR y The id of the sender's tty
- \fIm_rhdir\fR z The home directory of the recipient
- .TE
- .FS
- * Taken from pages 15 and 16 of the Installation and Operation Guide
- for Sendmail (UNIX Programmer's Manual, Volume 2c), by Eric Allman.
- .FE
- SHAR_EOF
- if test 1384 -ne "`wc -c ap1`"
- then
- echo shar: error transmitting ap1 '(should have been 1384 characters)'
- fi
- cat << \SHAR_EOF > ap2
- .DS C
- \s+5\fBAppendix B\fR
-
-
- \fBSendmail Options\fR\s-5
- .DE
- .sp 2
- .PP
- For a complete description of Sendmail's options and their values, refer to
- Appendix B of the Installation and Operation Guide for Sendmail (UNIX
- Programmer's Manual, Volume 2c), by Eric Allman.
- .sp 2
- .TS
- center box;
- c|c
- l|l.
- Sendmail Option (\fBEase\fR) Sendmail Option (Raw) Special Values
- =
- \fIo_alias\fR A
- \fIo_ewait\fR a
- \fIo_bsub\fR B
- \fIo_qwait\fR c
- \fIo_delivery\fR (special values below) d (special values below)
- \fId_interactive\fR i
- \fId_background\fR b
- \fId_queue\fR q
- \fIo_rebuild\fR D
- \fIo_handling\fR (special values below) e (special values below)
- \fIh_print\fR p
- \fIh_exit\fR q
- \fIh_mail\fR m
- \fIh_write\fR w
- \fIh_mailz\fR e
- \fIo_tmode\fR F
- \fIo_usave\fR f
- \fIo_gid\fR g
- \fIo_fsmtp\fR H
- \fIo_skipd\fR i
- \fIo_slog\fR L
- \fIo_rsend\fR m
- \fIo_dnet\fR N
- \fIo_hformat\fR o
- \fIo_qdir\fR Q
- \fIo_tread\fR r
- \fIo_flog\fR S
- \fIo_safe\fR s
- \fIo_qtimeout\fR T
- \fIo_timezone\fR t
- \fIo_dmuid\fR u
- \fIo_verbose\fR v
- \fIo_wizpass\fR W
- \fIo_loadq\fR x
- \fIo_loadnc\fR X
- .TE
- SHAR_EOF
- if test 1153 -ne "`wc -c ap2`"
- then
- echo shar: error transmitting ap2 '(should have been 1153 characters)'
- fi
- cat << \SHAR_EOF > ap3
- .DS C
- \s+5\fBAppendix C\fR
-
-
- \fBMailer Flags\fR\s-5
- .DE
- .sp 5
- .PP
- For a complete description of mailer flags, refer to
- Appendix C of the Installation and Operation Guide for Sendmail (UNIX
- Programmer's Manual, Volume 2c), by Eric Allman.
- .sp 5
- .TS
- center box;
- c|c
- l|l.
- Mailer Flag (\fBEase\fR) Mailer Flag (Raw)
- =
- \fIf_ffrom\fR f
- \fIf_rfrom\fR r
- \fIf_noreset\fR S
- \fIf_noufrom\fR n
- \fIf_locm\fR l
- \fIf_strip\fR s
- \fIf_mult\fR m
- \fIf_from\fR F
- \fIf_date\fR D
- \fIf_mesg\fR M
- \fIf_full\fR x
- \fIf_return\fR P
- \fIf_upperu\fR u
- \fIf_upperh\fR h
- \fIf_arpa\fR A
- \fIf_ufrom\fR U
- \fIf_expensive\fR e
- \fIf_dot\fR X
- \fIf_llimit\fR L
- \fIf_retsmtp\fR p
- \fIf_smtp\fR I
- \fIf_addrw\fR C
- .TE
- SHAR_EOF
- if test 689 -ne "`wc -c ap3`"
- then
- echo shar: error transmitting ap3 '(should have been 689 characters)'
- fi
- cat << \SHAR_EOF > cover
- .DA
- .sp 15
- .nr PS 14
- .ps 14
- .DS C
-
- .DE
- .sp 10
- .nr PS 36
- .ps 36
- .DS C
- \fBEase:\fR
- .DE
- .sp 5
- .nr PS 22
- .ps 22
- .DS C
- A Configuration Language
-
- for Sendmail
- .DE
- .sp 13
- .nr PS 14
- .ps 14
- .DS C
- by
-
- \fIJames S. Schoner\fR
- \fIPurdue University Computing Center\fR
- .DE
- SHAR_EOF
- if test 262 -ne "`wc -c cover`"
- then
- echo shar: error transmitting cover '(should have been 262 characters)'
- fi
- cat << \SHAR_EOF > ease.paper
- .LP
- .TL
- Ease: A Configuration Language
- for Sendmail
- .AU
- James S. Schoner
- .AI
- Purdue University Computing Center
- West Lafayette, Indiana 47907
- .sp 2
- .I
- .ce
- ABSTRACT
- .R
- .PP
- The rapid expansion of computer networks and ensuing variation among mailing
- address formats have made address interpretation an increasingly
- complex task. In the UNIX* 4.2BSD operating system, a program named
- \fIsendmail\fR was introduced which provided a
- general internetwork mail routing facility. This facility has significantly
- diminished the complexity of handling address interpretation.
- .PP
- \fISendmail\fR's address interpretation is based on a rewriting
- system composed of
- a number of rewriting rules (or productions) arranged as part of a
- configuration file. Unfortunately, the syntactical format of a
- configuration file for \fIsendmail\fR is both terse and rigid, making it
- rather difficult to modify. The standard format certainly serves its
- purpose, but, as
- the need to change these configurations increases in frequency, a more
- readable format (i.e., one that is similar to the format
- of modern programming languages) is required to permit reasonably
- quick modifications to the configuration. As a solution to this problem,
- \fBEase\fR
- provides a level of abstraction which eliminates most of the current
- syntactic hindrances
- faced by programmers who must reconfigure \fIsendmail\fR's
- address parsing scheme.
- .PP
- As a high-level specification format, \fBEase\fR is proving to be an
- excellent alternative to \fIsendmail\fR's cryptic
- configuration file syntax. The syntactic structures of \fBEase\fR
- are patterned after modern language constructs, making the language
- easy to learn and easy to remember. The format of the address rewriting
- rule is perhaps the most significant syntactical improvement. It was
- undoubtedly
- the most needed improvement. Nevertheless, every element of a configuration
- file is structurally enhanced through the use of \fBEase\fR.
- .FS
- * UNIX is a trademark of AT&T Bell Laboratories.
- .FE
- .sp 2
- .NH
- Introduction
- .PP
- The \fBEase\fR language is a high-level specification format for \fIsendmail\fR's
- configuration file. The motivation for its development
- was to fulfill a goal of providing a readable and easily modifiable
- \fIsendmail\fR configuration file format. \fBEase\fR fulfills this goal by
- shielding the programmer from the cryptic configuration specification required
- by \fIsendmail\fR and providing a high-level language with which the programmer
- may specify all modifications to a configuration file. The development
- of Ease coincided with
- the development of an \fBEase\fR translator, \fIet\fR,
- which translates a configuration file written
- in \fBEase\fR to an
- equivalent file of the standard format accepted by \fIsendmail\fR.
- .NH
- Ease in Profile
- .PP
- As will be seen in the next section, the syntax of \fBEase\fR is quite
- readable and easy to learn. In order to acquire a relevant perspective
- on this issue,
- the reader is advised to examine a raw configuration file for \fIsendmail\fR (the
- output
- of the \fBEase\fR translator, \fIet\fR, will do nicely). The raw syntax, while
- quite fitting for quick translation, can prove to be a programmer's nightmare.
- .PP
- Undoubtedly, one of the more prominent features of \fBEase\fR is the ability
- to attach
- names to address fields. When address field names are well-chosen, a distinct,
- self-documenting quality becomes a visible part of the address rewriting
- rules. Ostensibly, address field names provide a new level of semantic
- abstraction. A brief comparison of the formats can be accomplished by examining
- the following equivalent representations of an address pattern:
- .DS
- user_path@host_name (\fBEase\fR format)
- $+@$- (raw format)
- .DE
- In the above, \*Quser_path\*U represents a field of one or more address
- tokens, and \*Qhost_name\*U represents one address token exactly. These
- token fields are represented by \*Q$+\*U and \*Q$-\*U in the raw format. Clearly,
- the \fBEase\fR format is preferable, not only for increased readability, but
- structural comprehension as well.
- .PP
- Other features of \fBEase\fR include ruleset naming, long identifiers for
- macros and classes, flow-of-control structures, and free formatting. In
- addition, the C language preprocessor (cpp) can be used for file inclusion
- and conditionally defined code constructs. The next section describes
- the \fBEase\fR language in complete detail.
- .NH
- Ease Syntax*
- .FS
- * \fINo attempt is made to describe the complete semantic meaning
- associated with all of the constructs of a sendmail configuration file. Items
- not covered in this document include the semantic distinction among rulesets,
- the special uses of
- pre-defined macros, and the method of building configuration files. To
- obtain this information, the reader is advised to refer to
- the Installation and Operation Guide for Sendmail (UNIX
- Programmer's Manual, Volume 2c), by Eric Allman.\fR
- .FE
- .PP
- At its highest level, \fBEase\fR can be viewed as a collection of
- block-structures, where each block begins with a keyword and is followed by
- zero or more related definitions and/or declarations. There are ten distinct
- block types. The following is
- a list containing all ten block keywords and the block type it denotes.
- .TS
- center;
- l l .
- \fIbind\fR -ruleset identifier bindings
- \fImacro\fR -macro definitions
- \fIclass\fR -class definitions
- \fIoptions\fR -\fIsendmail\fR option definitions
- \fIprecedence\fR -precedence definitions
- \fItrusted\fR -trusted users
- \fIheader\fR -mail header definitions
- \fImailer\fR -mailer definitions
- \fIfield\fR -address field definitions
- \fIruleset\fR -address rewriting rules
- .TE
- .sp 1
- In general,
- .TS
- center ;
- l .
-
- * Letters are distinguished by case,
-
- T{
- * An \fBEase\fR identifier is defined to be a letter, followed by zero or
- more letters, digits, underscores (_), or dashes (-),
- T}
-
- T{
- * A literal newline or double quotation (") character may be included in
- any quoted string by preceding the character with a backslash (\\\\\), and
- T}
-
- T{
- * \fBEase\fR source is preprocessed by the C language preprocessor (cpp),
- thus source comments (i.e., text enclosed by \*Q/*\*U and \*Q*/\*U) may appear
- anywhere as part of \fBEase\fR whitespace.
- T}
- .TE
- .PP
- For notational convenience, this document specifies all reserved
- words of the \fBEase\fR language in italics. In addition, quantities
- enclosed in angle brackets (<..>) represent arbitrary
- identifiers, strings, or numbers.
- .NH 2
- Ruleset Identifier Bindings
- .PP
- A ruleset (a set of rewriting rules) is identified solely by an integer
- in \fIsendmail\fR's
- configuration file. \fBEase\fR, however, allows each ruleset to be named with
- a meaningful identifier. Since a special numeric association for each
- ruleset is required by the address parsing scheme of \fIsendmail\fR, a \fIbind\fR
- block must be present in any \fBEase\fR file which defines one or more
- rulesets. A
- \fIbind\fR block consists of the keyword \fIbind\fR, followed by zero or more
- statements of the form:
- .TS
- center box;
- l .
- <ruleset-id> = \fIruleset\fR <ruleset-number> ;
- .TE
- The following example,
- .sp 1
- \fIbind\fR
- .PP
- FINAL_RW = \fIruleset\fR 4;
- .sp 1
- specifies that FINAL_RW, the final rewriting ruleset, is \fIsendmail\fR's ruleset
- number 4.
- .NH 2
- Macro Definitions
- .PP
- A macro is an identifier which, when referenced in the text of a program,
- is replaced by its value, a string of zero or more characters. The value
- of a macro may include references to other macros, but not itself! \fISendmail\fR
- allows a maximum of 26 user-declared macros in its configuration file. In
- addition, there are a number of pre-declared macros which have special meaning
- to \fIsendmail\fR (see Appendix A). \fBEase\fR macros are defined in
- \fImacro\fR blocks. \fBEase\fR allows any macro to be declared
- (which is equivalent to simply referencing it) before it is defined. A macro
- identifier is replaced by its value when it is preceded by the character
- \*Q$\*U. In addition, a macro reference inside a quoted string must always
- include braces ({}) around the macro identifier (for delimiting purposes).
- .PP
- A \fImacro\fR block consists of the keyword \fImacro\fR, followed by zero
- or more statements taking either of the following forms:
- .TS
- center box;
- l .
- <macro-identifier> = "<macro-value>" ;
- <macro-identifier> = \fBconditional-expression\fR ;
- .TE
- The \fBconditional-expression\fR format will be discussed
- later.
- .sp 1
- The following example,
- .sp 1
- \fImacro\fR
- .PP
- first_name = "James";
- .PP
- last_name = "Schoner";
- .PP
- whole_name = "${first_name} ${second_name}";
- .sp 1
- defines the macros first_name, last_name, and whole_name, where whole_name
- is the string, "James Schoner".
- .NH 2
- Class definitions
- .PP
- A class is denoted by an identifier representing a logical grouping of zero
- or more names. Classes are used to represent the range of values a token
- may assume in the pattern matching of an address. Further discussion on the
- use of classes will be deferred until address fields are described.
- .PP
- One identifier may be used to distinctly represent both a macro
- and class (i.e., the set of macro identifiers and the set of class identifiers
- may form a non-empty intersection). A name, or class element, may
- be an identifier or any quoted word.
- .PP
- A \fIclass\fR block consists of the keyword \fIclass\fR, followed by zero
- or more statements taking any of the following forms:
- .TS
- center box;
- l .
- <class-identifier> = { <name1>, <name2>, <name3>, ... } ;
- <class-identifier> = \fIreadclass\fR ( "<file-name>" ) ;
- <class-identifier> = \fIreadclass\fR ( "<file-name>", "<read-format>" ) ;
- .TE
- The second and third forms cause \fIsendmail\fR to read the names of the class
- from the named
- file. The third form contains a read format, which should be a \fIscanf(3)\fR
- pattern yielding a single string.
- .sp 1
- The following example,
- .sp 1
- \fIclass\fR
- .PP
- campus_hosts = { statistics, engineering, chemistry, physics, physics-2 } ;
- .PP
- versions = { "1.0", "1.1", "4.0", "4.2", latest-and-greatest } ;
- .PP
- phone_hosts = \fIreadclass\fR ( "/tmp/phonenet.list" ) ;
- .sp 1
- defines the classes campus_hosts, versions, and phone_hosts.
- .NH 2
- Sendmail option definitions
- .PP
- A number of options to the \fIsendmail\fR program may be specified in
- an \fIoptions\fR
- block. For a description of the various \fIsendmail\fR options and their
- values, see Appendix B.
- .PP
- An
- \fIoptions\fR block consists of the keyword \fIoptions\fR, followed by zero
- or more statements taking any of the following forms:
- .TS
- center box;
- l l .
- <option-identifier> = "<option-value>" ;
- \fIo_delivery\fR = \fBspecial-value\fR ;
- \fIo_handling\fR = \fBspecial-value\fR ;
- .TE
- All but two options (\fIo_delivery\fR and \fIo_handling\fR) use the first
- form. To specify an option without a value, simply assign to it the null
- string (""). The \fBspecial-value\fR field of the second and third form
- refers to special values (non-quoted) which are specified in Appendix B.
- .sp 1
- The following example,
- .sp 1
- \fIoptions\fR
- .PP
- \fIo_alias\fR = "/usr/lib/aliases" ;
- .PP
- \fIo_tmode\fR = "0600" ;
- .PP
- \fIo_delivery\fR = d_background ;
- .sp 1
- sets the options \fIo_alias\fR, \fIo_tmode\fR, and \fIo_delivery\fR.
- .NH 2
- Precedence definitions
- .PP
- Message headers may contain a \*QPrecedence:\*U field describing the precedence
- of the message class. Identifiers which may appear in the precedence field of
- a message are given precedence values in a configuration file \fIprecedence\fR
- definition. This association will be illustrated below in an example.
- .PP
- A \fIprecedence\fR block consists of the keyword \fIprecedence\fR, followed
- by zero or more statements of the form:
- .KS
- .TS
- center box;
- l .
- <precedence-identifier> = <precedence-integer> ;
- .TE
- .KE
- The following example,
- .sp 1
- \fIprecedence\fR
- .PP
- special-delivery = 100;
- .PP
- junk = -100;
- .sp 1
- defines the precedence level for the names \*Qspecial-delivery\*U and
- \*Qjunk\*U. Thus, whenever the name \*Qjunk\*U appears in
- a \*QPrecedence:\*U field, the corresponding message class will be set to -100.
- .NH 2
- Trusted users
- .PP
- \fISendmail\fR's \fB-f\fR flag allows trusted users to override the sender's
- machine address. Trusted users are listed in \fItrusted\fR blocks. A
- \fItrusted\fR block consists of the keyword \fItrusted\fR, followed
- by zero or more sets of users taking the form:
- .TS
- center box;
- l .
- { <user1>, <user2>, <user3>, ... } ;
- .TE
- The following example,
- .sp 1
- \fItrusted\fR
- .PP
- { root, uucp, network } ;
- .PP
- { acu, kcs, jss } ;
- .sp 1
- specifies that the users root, uucp, network, acu, kcs, and jss can be trusted
- to use the \fIsendmail\fR flag, \fB-f\fR.
- .NH 2
- Mail header definitions
- .PP
- The format of the message headers inserted by \fIsendmail\fR is defined in one
- or more \fIheader\fR blocks in the configuration file. A \fIheader\fR block
- consists of the keyword \fIheader\fR, followed by zero or more statements
- taking any of the following forms:
- .TS
- center box;
- l
- l
- l
- l
- l
- l
- l
- l
- l
- l
- l .
- \fIfor\fR ( <mailer-flag1>, <mailer-flag2>, ... )
- \fIdefine\fR ( "<header-title>" , \fBheader-value\fR ) ;
-
- \fIfor\fR ( <mailer-flag1>, <mailer-flag2>, ... ) {
- \fIdefine\fR ( "<header-title>" , \fBheader-value\fR ) ;
- \fIdefine\fR ( "<header-title>" , \fBheader-value\fR ) ;
- .
- .
- } ;
-
- \fIdefine\fR ( "<header-title>" , \fBheader-value\fR ) ;
- .TE
- The first form is used to define one header for one or more mailer
- flags. The second form differs from the first in that more than one
- header may be defined for a given set of flags. The third form is used to
- define a header,
- regardless of mailer flags. Refer to Appendix C for a list of \fBEase\fR
- identifiers representing mailer flags. The header title is a simple
- string of characters (no macro references), whereas the \fBheader-value\fR can
- be either a string of characters (possibly containing macro references) or
- a \fBconditional-expression\fR (discussed later).
- .sp 1
- The following example,
- .DS
- \fIheader\fR
-
- \fIdefine\fR ( "Subject:", "") ;
-
- \fIfor\fR ( \fIf_return\fR )
- \fIdefine\fR ( "Return-Path:", "<${\fIm_sreladdr\fR}>" ) ;
-
- \fIfor\fR ( \fIf_date\fR ) {
- \fIdefine\fR ( "Resent-Date:", "${\fIm_odate\fR}" ) ;
- \fIdefine\fR ( "Date:", "${\fIm_odate\fR}" );
- } ;
- .DE
- defines a \*QSubject\*U field for all mailers, regardless of their flags, a
- \*QReturn-Path\*U field for mailers whose definition specifies
- the flag, \fIf_return\fR, and the headers, \*QResent-Date\*U and \*QDate\*U,
- for mailers whose definition specifies the flag, \fIf_date\fR.
- .NH 2
- Mailer Definitions
- .PP
- \fISendmail\fR's definition of a mailer (or an interface to one) occurs in a
- \fImailer\fR block. A \fImailer\fR block consists of the keyword \fImailer\fR,
- followed by zero or more statements of the form:
- .TS
- center box;
- l .
- <mailer-identifier> { \fBmailer-spec\fR } ;
- .TE
- The field, \fBmailer-spec\fR, is a list of zero or more of the
- following attribute assignments (where successive assignment statements are
- separated by commas):
- .TS
- center ;
- l l
- l l
- l l
- l l
- l l
- l l
- l l .
- \fIPath\fR = \fBstring-attribute\fR
- \fIArgv\fR = \fBstring-attribute\fR
- \fIEol\fR = \fBstring-attribute\fR
- \fIMaxsize\fR = \fBstring-attribute\fR
- \fIFlags\fR = { <mailer-flag1>, <mailer-flag2>, ... }
- \fISender\fR = <sender-ruleset-id>
- \fIRecipient\fR = <recipient-ruleset-id>
- .TE
- The \fBstring-attribute\fR value can take the form of a quoted string
- (possibly containing macro references) or a \fBconditional-expression\fR
- (discussed later).
- .sp 1
- The following example,
- .sp 1
- \fImailer\fR
- .DS
- local {
- \fIPath\fR = "/bin/mail",
- \fIFlags\fR = { \fIf_from\fR, \fIf_locm\fR },
- \fISender\fR = Sender_RW,
- \fIRecipient\fR = Recip_RW,
- \fIArgv\fR = "mail -d ${\fIm_ruser\fR}",
- \fIMaxsize\fR = "200000"
- } ;
- .DE
- defines a mailer named \*Qlocal\*U.
- .NH 2
- Address field definitions
- .PP
- \fISendmail\fR's address parsing scheme treats an address as a group of tokens
- (an address token is precisely defined in the Arpanet protocol RFC822). In
- general, \fIsendmail\fR divides an address into tokens based on a list of
- characters assigned as a string to the special macro \fIm_addrops\fR. These
- characters will individually be considered as tokens and will separate tokens
- when parsing is performed.
- .PP
- For
- the \fBEase\fR language, there is a distinct set of address tokens (defined
- below) which are used in combination to represent generic forms of
- addresses. In
- addition to literal address tokens, the pattern to be matched in a rewriting
- rule (often refered to as the LHS) may
- include field identifiers which match one of five possibilities:
- .DS
- - zero or more tokens
- - one or more tokens
- - one token exactly
- - one token which is an element of an aribitrary class \fBX\fR
- - one token which is not an element of an aribitrary class \fBX\fR
- .DE
- A particular field type may be assigned to one or more identifiers. Each
- field identifier is associated with (or defined to be) a field type in
- a \fIfield\fR declarations block. A \fIfield\fR declarations block consists
- of the keyword \fIfield\fR, followed by zero or more field definitions of
- the form:
- .TS
- center box;
- l .
- \fBfield-id-list\fR : \fBfield-type\fR ;
- .TE
- A \fBfield-id-list\fR is a list of one or more identifiers, each separated by
- a comma. A \fBfield-type\fR, on the other hand, is a representation of
- one of the five fields
- described above. The syntax for each of the five forms follows:
- .DS
- \fImatch\fR ( 0* )
- \fImatch\fR ( 1* )
- \fImatch\fR ( 1 )
- \fImatch\fR ( 1 ) in <class-X>
- \fImatch\fR ( 0 ) in <class-X>
- .DE
- The star in the first two forms means: "or more". Thus, the first
- form would read: "match zero or more tokens". The fourth form describes
- a field where one token is matched from an arbitrary class (class-X), whereas
- the fifth form describes a field where one token is matched if it is not of the
- given class (class-X).
- .sp 1
- The following example,
- .sp 1
- .DS
- \fIfield\fR
- anypath : \fImatch\fR ( 0* );
- recipient_host : \fImatch\fR ( 1 );
- local_site : \fImatch\fR ( 1 ) in \fIm_sitename\fR;
- remote_site : \fImatch\fR ( 0 ) in \fIm_sitename\fR;
- .DE
- defines the fields anypath, recipient_host, local_site, and remote_site.
- .NH 2
- Address rewriting rules
- .PP
- Address rewriting rules are grouped according to the function they perform. For
- example, it is desirable to form a distinct group for those rewriting rules
- which perform transformations on recipient addresses.
- .PP
- Sets of rewriting rules are defined in \fIruleset\fR blocks. A \fIruleset\fR
- block consists of the keyword \fIruleset\fR, followed by zero or more
- ruleset definitions of the form:
- .TS
- center box;
- l .
- <ruleset-id> { <rewriting-rule1> <rewriting-rule2> ... }
- .TE
- The ruleset identifier, ruleset-id, must be defined in a \fIbind\fR block, as
- described earlier. The rewriting rules have the form:
- .DS
- \fIif\fR ( <match-pattern> )
- <match-action> ( <rewriting-pattern> ) ;
- .DE
- where match-pattern, rewriting-pattern, and match-action are described below.
- .NH 3
- Match-patterns
- .PP
- A match-pattern is a sequence of Ease address elements representing an
- address format. If the address being rewritten matches the pattern
- \*Qmatch-pattern\*U,
- then the address is reformatted using the pattern \*Qrewriting-pattern\*U, and
- the corresponding
- action (\*Qmatch-action\*U) is performed. The five distinct Ease address
- elements which may constitute a match-pattern are as follows:
- .TS
- center ;
- l .
- 1. Field Identifiers (refer to previous section)
- T{
- 2. Non-alphanumeric characters (the exception is the case for literal
- double quotes, which must be preceded by a backslash (\\\\\)
- T}
- 3. Macro references
- 4. Quoted strings ("...")
- 5. \fBConditional-expressions\fR (discussed later)
- .TE
- Below are two sample match-patterns, each describing the same address format:
- .DS
- user-id @ hostname . $arpa_suffix
- user-id @ hostname ".ARPA"
- .DE
- where user-id and hostname are field identifiers, and arpa_suffix is a
- user-defined macro with the value \*QARPA\*U.
- .NH 3
- Rewriting-patterns
- .PP
- A rewriting-pattern specifies the form in which to rewrite a matched
- address. The seven distinct elements which may be used to form
- a rewriting-pattern are as follows:
- .TS
- center ;
- l .
-
- T{
- 1. Non-alphanumeric characters (the exception is the case for literal
- double quotes, left parentheses, or right parentheses, each of which
- must be preceded by a backslash (\\\\\).
- T}
-
- T{
- 2. A call to another ruleset. This is used to perform rewrites
- on a suffix of the rewriting-pattern. The proper use of this
- feature will be demonstrated by example below.
- T}
-
- 3. Quoted strings ("...").
-
- 4. \fBConditional-expressions\fR (discussed later).
-
- 5. A macro reference.
-
- T{
- 6. A positional reference in the matched address. A positional
- reference takes the form: $<integer-position>. For example,
- $3 references the value of the third \fBEase\fR address
- element in the matched address.
- T}
-
- T{
- 7. Canonicalized host names of the form \fIcanon\fR (<id-token>),
- where id-token is a regular identifier, a quoted identifier (with
- double quotes), a macro reference yielding an identifier, or a
- positional reference in the matched address. The canonicalization of
- a host name is simply a mapping to its canonical (or official) form.
- T}
-
- .TE
- Below are two sample rewriting-patterns:
- .DS
- $1 % $2 < @ $3 ".ARPA" >
- OLDSTYLE_RW ( $1 )
- .DE
- The first form specifies an address such as a%b<@c.ARPA>, where a, b, and c
- represent matched identifiers or paths. The second form specifies a call to
- the ruleset \*QOLDSTYLE_RW\*U, for old-style rewriting on the parameter
- $1, which probably references the entire matched address. This will become
- clear in later examples.
- .NH 3
- Match-actions
- .PP
- When a ruleset is called, the address to be rewritten is compared (or matched)
- sequentially against the match-address of each rewriting rule. When a
- match-address describes the address \fIsendmail\fR is attempting to rewrite, the
- address is rewritten (or reformatted) using the rule's
- rewriting-pattern. Following this rewrite, the corresponding match-action
- is performed. There are four match-actions:
- .TS
- center ;
- l l .
- \fIretry\fR T{
- -a standard action which causes the rewritten address
- to be again compared to the match-address of the current rule.
- T}
-
- \fInext\fR T{
- -an action which causes the rewritten address to be
- compared to the match-address of the next rewriting rule of the current
- ruleset. If the end of the list is reached, the ruleset returns the
- rewritten address.
- T}
-
- \fIreturn\fR T{
- -an action which causes an immediate return of the
- ruleset with the current rewritten address.
- T}
-
- \fIresolve\fR T{
- -an action which specifies that the address has been
- completely resolved (i.e., no further rewriting is necessary). The
- \fIresolve\fR action is described in more detail below.
- T}
- .TE
- .PP
- The match-action, \fIresolve\fR, is special in that it terminates
- the address rewriting altogether. The semantic structure of \fIsendmail\fR's
- rewriting scheme requires that a \fIresolve\fR action appear only in the
- ruleset whose numerical binding is to the number zero. The \fIresolve\fR action
- must specify three parameters: \fImailer\fR, \fIhost\fR, and \fIuser\fR. If
- the \fImailer\fR is local, the \fIhost\fR parameter may be omitted. The
- \fImailer\fR argument must be specified as a single word, macro, or positional
- reference in the matched address. The \fIhost\fR argument may be specified as
- a single word or as an expression which expands to a single word (i.e.,
- \fIhost\fR ($1 ".ARPA")). In addition, the \fIhost\fR argument may be a
- canonicalization (as described above) or a numeric internet specification. The
- keyword \fIhostnum\fR is used for numeric internet specifications, as in
- \fIhostnum\fR ("00.00.00.00") or \fIhostnum\fR ( $2 ). The \fIuser\fR
- specification is a rewriting-pattern, as described above.
- .PP
- In general, the format of a \fIresolve\fR action will be as follows:
- .DS
- \fIresolve\fR ( \fImailer\fR ( <mailer-name> ),
- \fIhost\fR ( <host-name> ),
- \fIuser\fR ( <user-address>) );
- .DE
- Examples of the match-action statement are shown below:
- .DS
- \fIfield\fR
- anypath : \fImatch\fR (0*);
- usr, path : \fImatch\fR (1*);
- hostname : \fImatch\fR (1);
- phone_host : \fImatch\fR (1) in phonehosts;
- .DE
- .DS
- \fIruleset\fR
-
- EXAMPLE_RW {
-
- \fIif\fR ( anypath < path > anypath ) /* basic RFC821/822 parse */
- \fIretry\fR ( $2 );
- \fIif\fR ( usr " at " path ) /* \*Qat\*U -> \*Q@\*U */
- \fInext\fR ( $1 @ $2 );
- \fIif\fR ( @path: usr )
- \fIreturn\fR ( LOCAL_RW ( < @$1 > : $2 ) );
- \fIif\fR ( anypath < @phone_host".ARPA" > anypath )
- \fIresolve\fR ( \fImailer\fR ( tcp ),
- \fIhost\fR ( csnet-relay ),
- \fIuser\fR ( $1 % $2 < @"csnet-relay" > $3 ) );
- }
- .DE
- .PP
- The example above defines the ruleset \*QEXAMPLE_RW\*U, which contains four
- rewriting rules. The first rewriting rule discards all tokens of an address
- which lie on either side of a pair of angle brackets (<>), thereby
- rewriting the address as
- the sequence of tokens contained within the angle brackets ($2). Following the
- address rewrite, the rule is applied again (\fIretry\fR). When the first rule
- fails to match the address being rewritten, the second rule is applied.
- .PP
- The second
- rule simply replaces the word \*Qat\*U by the symbol \*Q@\*U. The \*Q\fInext\fR\*U
- action specifies that if a match is made, a rewrite is performed and
- matching continues at the next (or following) rule.
- .PP
- The third rule illustrates
- the use of the \*Q\fIreturn\fR\*U action, which is executed if the
- pattern \*Q@path: usr\*U
- describes the current format of the address being rewritten. In this example,
- the \fIreturn\fR action returns the result of a call to ruleset \*QLOCAL_RW\*U,
- which rewrites the address \*Q<@$1>:$2\*U, where $1 and $2 are substituted
- with the token(s) matched respectively by \*Qpath\*U and \*Qusr\*U.
- .PP
- The fourth (and final) rule signals a resolution (and termination) of the
- rewriting process if the given pattern is matched. The resolution specifies
- that the mailer \*Qtcp\*U will be used to deliver the message to the host
- \*Qcsnet-relay\*U. The \fIuser\fR parameter specifies the final form of the address
- which \fIsendmail\fR has just resolved.
- .sp 2
- .PP
- The \fBEase\fR construct which remains to be examined is the
- \fBconditional-expression\fR. The \fBconditional-expression\fR provides a
- method for
- constructing strings based on the condition that some test macro is (or is not)
- set. The general form begins with the concatenation of a string and a
- \fBstring-conditional\fR:
- .DS
- \fIconcat\fR ( <quoted-string>, \fBstring-conditional\fR )
- \fIconcat\fR ( \fBstring-conditional\fR, <quoted-string> )
- .DE
- A \fBstring-conditional\fR assumes either of the following forms:
- .DS
- \fIifset\fR ( <macro-name>, <ifset-string> )
- \fIifset\fR ( <macro-name>, <ifset-string>, <notset-string> )
- .DE
- A \fBstring-conditional\fR of the first form evaluates to \*Qifset-string\*U
- if the macro \*Qmacro-name\*U has been assigned a value; otherwise it
- evaluates to the null string. The second form behaves similarly, except
- that the \fBstring-conditional\fR evaluates to \*Qnotset-string\*U, instead
- of the null string, if the macro \*Qmacro-name\*U has no value.
- .sp 1
- The following \fBconditional-expression\fR,
- .DS
- \fIconcat\fR ( "New ", \fIifset\fR ( city, "York", "Jersey" ) )
- .DE
- evaluates to the string "New York", if the macro \*Qcity\*U is set. Otherwise,
- the \fBconditional-expression\fR evaluates to the string "New Jersey".
- .NH
- Ease Translation
- .PP
- It is important to note that \fBEase\fR is translated by a stand-alone
- translator to the raw configuration file format. No modifications were
- made to the \fIsendmail\fR program itself. As a result, syntactical verification
- of a configuration file can be performed without invoking \fIsendmail\fR.
- .PP
- The \fBEase\fR language is translated by invoking
- the C language preprocessor (cpp) with \fBEase\fR source as input, then piping
- the output as input to the \fBEase\fR translator (\fIet\fR). The \fBEase\fR
- translator may be invoked on the command line in one of four ways:
- .TS
- center box ;
- l l .
- \fIet\fR <input-file> <output-file> [read from a file, write to a file]
- \fIet\fR <input-file> [read from a file, write to standard output]
- \fIet\fR - <output-file> [read from standard input, write to a file]
- \fIet\fR [read from standard input, write to standard output]
- .TE
- .NH
- Conclusion
- .PP
- \fBEase\fR is currently in use at the Purdue University Computing
- Center. Source code for the \fBEase\fR translator (\fIet\fR) may be
- obtained on request by writing to:
- .DS
- U.S. Mail:
- James S. Schoner
- c/o Kevin S. Braunsdorf
- Purdue University Computing Center
- Purdue University
- West Lafayette, Indiana 47907
-
- Electronic Mail:
- ksb@j.cc.purdue.edu
- .DE
- .PP
- Much of the success of this project is attributable to the constant support
- and insight offered by Mark Shoemaker. To him, I owe a debt of gratitude. In
- addition, I would like to thank Kevin Smallwood, Paul Albitz, and Rich Kulawiec
- for their many notable suggestions and valuable insight.
- SHAR_EOF
- if test 29063 -ne "`wc -c ease.paper`"
- then
- echo shar: error transmitting ease.paper '(should have been 29063 characters)'
- fi
- cat << \SHAR_EOF > Makefile
- #
- # Makefile for Ease document.
- #
- # James S. Schoner
- # Purdue University Computing Center
- #
- all: cover mainbody apen1 apen2 apen3
-
- cover: FRC
- troff -ms cover
-
- mainbody:
- tbl ease.paper | troff -ms
-
- apen1:
- tbl ap1 | troff -ms
-
- apen2:
- tbl ap2 | troff -ms
-
- apen3:
- tbl ap3 | troff -ms
-
- FRC:
-
- SHAR_EOF
- if test 293 -ne "`wc -c Makefile`"
- then
- echo shar: error transmitting Makefile '(should have been 293 characters)'
- fi
- chdir ..
- mkdir src
- chdir src
- cat << \SHAR_EOF > parser.y
- %{
- /* $Header: /usr/src/local/etc/ease/RCS/parser.y,v 1.3 85/12/10 18:02:11 jss Exp $ */
-
- /*
- * parser.y -- EASE parser.
- *
- * Contains code for yacc(1) which produces a parser (y.tab.c)
- * for Ease, a specification format for sendmail configuration
- * files.
- *
- * author -- James S. Schoner, Purdue University Computing Center,
- * West Lafayette, Indiana 47907
- *
- * date -- July 2, 1985
- *
- * Copyright (c) 1985 by Purdue Research Foundation
- *
- * All rights reserved.
- *
- */
-
- #include <stdio.h>
- #include "symtab.h"
-
- extern void BindID ();
- extern void EmitDef ();
- extern char *ListAppend ();
- extern char *MakeCond ();
- extern char *MakeRStr ();
- extern char *ConvOpt ();
- extern char *ConvFlg ();
- extern char *MacScan ();
- extern char *ConvMat ();
- extern void StartRuleset ();
- extern char *MakePosTok ();
- extern char *GetField ();
- extern char *Bracket ();
- extern char *MakeRSCall ();
- extern char *CheckMailer ();
- extern char *CheckRS ();
- extern char *MakeField ();
- extern char MakeMac ();
- extern void AssignType ();
- extern void RemoveSymbol ();
- extern void yyerror ();
-
- extern short RMatch; /* ruleset match flag */
-
- char *Cbuf = " "; /* character buffer */
- char *Mbuf = "$ "; /* macro buffer */
- char *Tsb; /* pointer to temporary string buffer */
- char *Flaglist; /* pointer to header flag list */
-
- %}
-
- %union { /* value stack element type */
- int ival; /* integer token */
- char *psb; /* string token */
- struct he *phe; /* pointer to hash entry */
- enum opts optval; /* sendmail options */
- enum flgs flgval; /* mailer flags */
- enum mats mpval; /* mailer attribute parameters */
- }
-
- %start config
-
- %token <phe> IDENT
- %token <psb> SCONST
- %token <ival> ICONST SEPCHAR
- %token BIND MACRO CLASS OPTIONS PRECEDENCE TRUSTED HEADER RULESET MAILER
- %token IF RETRY NEXT RETURN RESOLVE CONCAT IFSET FOR CANON READCLASS
- %token MPATH MFLAGS MSENDER MRECIPIENT MARGV MEOL MMAXSIZE
- %token AAOPT AOPT BBOPT COPT DOPT DOPTI DOPTB DOPTQ DDOPT EOPT EOPTP EOPTE
- %token EOPTM EOPTW EOPTZ FFOPT FOPT GOPT HHOPT IOPT LLOPT MOPT NNOPT OOPT QQOPT
- %token ROPT SSOPT SOPT TTOPT TOPT UOPT VOPT WWOPT XOPT XXOPT
- %token FFLAG RFLAG SSFLAG NFLAG LFLAG SFLAG MFLAG FFFLAG DDFLAG MMFLAG XFLAG
- %token PPFLAG UFLAG HFLAG AAFLAG UUFLAG EFLAG XXFLAG LLFLAG PFLAG IIFLAG CCFLAG
- %token ASGN COMMA LBRACE RBRACE LPAREN RPAREN SEMI DOLLAR MATCH IN HOSTNUM
- %token DEFINE FIELD COLON STAR HOST USER
-
- %type <psb> mval strval ifcon conval ifres elseres nameset namelist
- %type <psb> doptid eoptid idlist fcond dlist mflags route mdefs
- %type <psb> matchaddr matchtok action actionstmt mailerspec mtdef
- %type <psb> rwaddr rwtok ftype reftok rword cantok resolution
- %type <psb> userspec hword hostid dheader
- %type <ival> anychar
- %type <phe> cdef
- %type <optval> optid
- %type <flgval> flagid
- %type <mpval> mvar
-
- %left COMMA
- %left LPAREN RPAREN
- %nonassoc SCONST
-
- %%
- config : /* empty */
- | config blockdef
- | error blockdef
- ;
-
- blockdef : BIND bindings
- | MACRO macdefs
- | CLASS classdefs
- | OPTIONS optdefs
- | PRECEDENCE precdefs
- | TRUSTED tlist
- | HEADER hdefs
- | MAILER mlist
- | RULESET rdef
- | FIELD fdefs
- ;
-
- bindings : /* empty */
- | bindings IDENT ASGN RULESET ICONST SEMI {
- BindID ($2, $5, ID_RULESET);
- }
- | error SEMI {
- yyerrok;
- }
- ;
-
- macdefs : /* empty */
- | macdefs IDENT ASGN mval SEMI {
- EmitDef (def_macro, $2, $4, (char *) NULL);
- }
- | error SEMI {
- yyerrok;
- }
- ;
-
- mval : strval %prec COMMA {
- $$ = $1;
- }
- | CONCAT LPAREN conval RPAREN {
- $$ = $3;
- }
- ;
-
- strval : SCONST {
- $$ = $1;
- }
- | strval SCONST {
- $$ = ListAppend ($1, $2, (char *) NULL);
- free ($1);
- }
- ;
-
- conval : strval COMMA ifcon {
- $$ = ListAppend ($1, $3, (char *) NULL);
- free ($1);
- free ($3);
- }
- | ifcon COMMA strval {
- $$ = ListAppend ($1, $3, (char *) NULL);
- free ($1);
- free ($3);
- }
- | error {
- $$ = NULL;
- }
- ;
-
- ifcon : IFSET LPAREN IDENT COMMA ifres RPAREN {
- $$ = MakeCond ($3, $5);
- }
- ;
-
- ifres : mval elseres {
- if ($2 != NULL) {
- $$ = ListAppend ($1, $2, "$|");
- free ($1);
- free ($2);
- } else
- $$ = $1;
- }
- | error {
- $$ = NULL;
- }
- ;
-
- elseres : /* empty */ {
- $$ = NULL;
- }
- | COMMA mval {
- $$ = $2;
- }
- ;
-
- classdefs : /* empty */
- | classdefs IDENT ASGN nameset {
- EmitDef (def_class, $2, $4, (char *) NULL);
- }
- | error
- ;
-
- nameset : LBRACE namelist RBRACE SEMI {
- $$ = $2;
- }
- | LBRACE RBRACE SEMI {
- $$ = NULL;
- }
- | LBRACE error RBRACE SEMI {
- $$ = NULL;
- }
- | READCLASS LPAREN strval RPAREN SEMI {
- $$ = MakeRStr ($3, (char *) NULL);
- }
- | READCLASS LPAREN strval COMMA strval RPAREN SEMI {
- $$ = MakeRStr ($3, $5);
- }
- | READCLASS LPAREN error RPAREN SEMI {
- $$ = NULL;
- }
- | error SEMI {
- $$ = NULL;
- yyerrok;
- }
- ;
-
- namelist : IDENT {
- $$ = ListAppend ($1->psb, (char *) NULL, (char *) NULL);
- RemoveSymbol ($1);
- }
- | strval {
- $$ = $1;
- }
- | namelist COMMA IDENT {
- $$ = ListAppend ($1, $3->psb, " ");
- free ($1);
- RemoveSymbol ($3);
- }
- | namelist COMMA strval {
- $$ = ListAppend ($1, $3, " ");
- free ($1);
- free ($3);
- }
- ;
-
- optdefs : /* empty */
- | optdefs optid ASGN strval SEMI {
- EmitDef (def_option, (struct he *) NULL, ConvOpt ($2), $4);
- }
- | optdefs DOPT ASGN doptid SEMI {
- EmitDef (def_option, (struct he *) NULL, ConvOpt (opt_d), $4);
- }
- | optdefs EOPT ASGN eoptid SEMI {
- EmitDef (def_option, (struct he *) NULL, ConvOpt (opt_e), $4);
- }
- | error SEMI {
- yyerrok;
- }
- ;
-
- optid : AAOPT {
- $$ = opt_A;
- }
- | AOPT {
- $$ = opt_a;
- }
- | BBOPT {
- $$ = opt_B;
- }
- | COPT {
- $$ = opt_c;
- }
- | DDOPT {
- $$ = opt_D;
- }
- | FFOPT {
- $$ = opt_F;
- }
- | FOPT {
- $$ = opt_f;
- }
- | GOPT {
- $$ = opt_g;
- }
- | HHOPT {
- $$ = opt_H;
- }
- | IOPT {
- $$ = opt_i;
- }
- | LLOPT {
- $$ = opt_L;
- }
- | MOPT {
- $$ = opt_m;
- }
- | NNOPT {
- $$ = opt_N;
- }
- | OOPT {
- $$ = opt_o;
- }
- | QQOPT {
- $$ = opt_Q;
- }
- | ROPT {
- $$ = opt_r;
- }
- | SSOPT {
- $$ = opt_S;
- }
- | SOPT {
- $$ = opt_s;
- }
- | TTOPT {
- $$ = opt_T;
- }
- | TOPT {
- $$ = opt_t;
- }
- | UOPT {
- $$ = opt_u;
- }
- | VOPT {
- $$ = opt_v;
- }
- | WWOPT {
- $$ = opt_W;
- }
- | XOPT {
- $$ = opt_x;
- }
- | XXOPT {
- $$ = opt_X;
- }
- ;
-
- doptid : DOPTI {
- $$ = ConvOpt (d_opt_i);
- }
- | DOPTB {
- $$ = ConvOpt (d_opt_b);
- }
- | DOPTQ {
- $$ = ConvOpt (d_opt_q);
- }
- ;
-
- eoptid : EOPTP {
- $$ = ConvOpt (e_opt_p);
- }
- | EOPTE {
- $$ = ConvOpt (e_opt_e);
- }
- | EOPTM {
- $$ = ConvOpt (e_opt_m);
- }
- | EOPTW {
- $$ = ConvOpt (e_opt_w);
- }
- | EOPTZ {
- $$ = ConvOpt (e_opt_z);
- }
- ;
-
- precdefs : /* empty */
- | precdefs IDENT ASGN ICONST SEMI {
- BindID ($2, $4, ID_PREC);
- EmitDef (def_prec, $2, (char *) NULL, (char *) NULL);
- }
- ;
-
- tlist : /* empty */
- | tlist LBRACE IDENT idlist RBRACE SEMI {
- EmitDef (def_trusted, (struct he *) NULL,
- ListAppend ($3->psb, $4, " "), (char *) NULL);
- free ($4);
- RemoveSymbol ($3);
- }
- | tlist LBRACE RBRACE SEMI
- | error SEMI {
- yyerrok;
- }
- ;
-
- hdefs : /* empty */
- | hdefs FOR fcond dheader SEMI {
- EmitDef (def_header, (struct he *) NULL, $3, $4);
- }
- | hdefs FOR fcond LBRACE { Flaglist = $3; }
- dheaders RBRACE SEMI
- | hdefs DEFINE dlist SEMI {
- EmitDef (def_header, (struct he *) NULL, (char *) NULL, $3);
- }
- | error SEMI {
- yyerrok;
- }
- ;
-
- fcond : LPAREN RPAREN {
- $$ = NULL;
- }
- | LPAREN mflags RPAREN {
- $$ = $2;
- }
- | LPAREN error RPAREN {
- $$ = NULL;
- }
- ;
-
- mflags : flagid {
- $$ = ListAppend (ConvFlg ($1), (char *) NULL, (char *) NULL);
- }
- | mflags COMMA flagid {
- $$ = ListAppend ($1, ConvFlg($3), (char *) NULL);
- free ($1);
- }
- ;
-
- flagid : FFLAG {
- $$ = flg_f;
- }
- | RFLAG {
- $$ = flg_r;
- }
- | SSFLAG {
- $$ = flg_S;
- }
- | NFLAG {
- $$ = flg_n;
- }
- | LFLAG {
- $$ = flg_l;
- }
- | SFLAG {
- $$ = flg_s;
- }
- | MFLAG {
- $$ = flg_m;
- }
- | FFFLAG {
- $$ = flg_F;
- }
- | DDFLAG {
- $$ = flg_D;
- }
- | MMFLAG {
- $$ = flg_M;
- }
- | XFLAG {
- $$ = flg_x;
- }
- | PPFLAG {
- $$ = flg_P;
- }
- | UFLAG {
- $$ = flg_u;
- }
- | HFLAG {
- $$ = flg_h;
- }
- | AAFLAG {
- $$ = flg_A;
- }
- | UUFLAG {
- $$ = flg_U;
- }
- | EFLAG {
- $$ = flg_e;
- }
- | XXFLAG {
- $$ = flg_X;
- }
- | LLFLAG {
- $$ = flg_L;
- }
- | PFLAG {
- $$ = flg_p;
- }
- | IIFLAG {
- $$ = flg_I;
- }
- | CCFLAG {
- $$ = flg_C;
- }
- ;
-
- dheader : /* empty */ {
- $$ = NULL;
- }
- | DEFINE dlist {
- $$ = $2;
- }
- | error {
- $$ = NULL;
- }
- ;
-
- dheaders : /* empty */
- | dheaders DEFINE dlist SEMI {
- EmitDef (def_header, (struct he *) NULL, Flaglist, $3);
- }
- | error
- ;
-
- dlist : LPAREN strval COMMA mval RPAREN {
- $$ = ListAppend ($2, MacScan ($4), " ");
- free ($2);
- free ($4);
- }
- | LPAREN error RPAREN {
- $$ = NULL;
- }
- ;
-
- mlist : /* empty */
- | mlist IDENT LBRACE mdefs RBRACE SEMI {
- EmitDef (def_mailer, $2, $4, (char *) NULL);
- }
- | mlist IDENT LBRACE RBRACE SEMI {
- EmitDef (def_mailer, $2, (char *) NULL, (char *) NULL);
- }
- | error SEMI {
- yyerrok;
- }
- ;
-
- mdefs : mtdef {
- $$ = $1;
- }
- | mdefs COMMA mtdef {
- $$ = ListAppend ($1, $3, ", ");
- free ($1);
- free ($3);
- }
- ;
-
- mtdef : mvar ASGN mval {
- $$ = ListAppend (ConvMat ($1), MacScan ($3), "=");
- free ($3);
- }
- | MFLAGS ASGN LBRACE mflags RBRACE {
- $$ = ListAppend (ConvMat (mat_flags), $4, "=");
- }
- | MSENDER ASGN IDENT {
- $$ = ListAppend (ConvMat (mat_sender), CheckRS ($3), "=");
- }
- | MRECIPIENT ASGN IDENT {
- $$ = ListAppend (ConvMat (mat_recipient), CheckRS ($3), "=");
- }
- | error {
- $$ = NULL;
- }
- ;
-
- mvar : MPATH {
- $$ = mat_path;
- }
- | MARGV {
- $$ = mat_argv;
- }
- | MEOL {
- $$ = mat_eol;
- }
- | MMAXSIZE {
- $$ = mat_maxsize;
- }
- ;
-
- rdef : /* empty */
- | rdef IDENT { StartRuleset ($2); } rulelist
- ;
-
- rulelist : LBRACE ruledefs RBRACE {
- RMatch = FALSE;
- }
- | error {
- RMatch = FALSE;
- }
- ;
-
- ruledefs : /* empty */ {
- RMatch = TRUE;
- }
- | ruledefs IF LPAREN matchaddr RPAREN actionstmt {
- EmitDef (def_ruleset, (struct he *) NULL,
- ListAppend ($4, $6, "\t"), (char *) NULL);
- free ($4);
- free ($6);
- }
- | error SEMI {
- yyerrok;
- }
- ;
-
- matchaddr : /* empty */ {
- $$ = NULL;
- }
- | matchaddr matchtok {
- $$ = ListAppend ($1, $2, (char *) NULL);
- free ($1);
- }
- | error {
- $$ = NULL;
- }
- ;
-
- matchtok : IDENT {
- $$ = GetField ($1);
- }
- | anychar {
- *Cbuf = $1;
- $$ = ListAppend (Cbuf, (char *) NULL, (char *) NULL);
- }
- | mval {
- $$ = MacScan ($1);
- }
- | DOLLAR IDENT {
- Mbuf[1] = MakeMac ($2, ID_MACRO);
- $$ = ListAppend (Mbuf, (char *) NULL, (char *) NULL);
- }
- ;
-
- actionstmt : action LPAREN rwaddr RPAREN SEMI {
- $$ = ListAppend ($1, $3, (char *) NULL);
- free ($3);
- }
- | RESOLVE LPAREN resolution RPAREN SEMI {
- $$ = $3;
- }
- | error SEMI {
- $$ = NULL;
- yyerrok;
- }
- ;
-
- action : RETRY {
- $$ = NULL;
- }
- | NEXT {
- $$ = "$:";
- }
- | RETURN {
- $$ = "$@";
- }
- ;
-
- rwaddr : /* empty */ {
- $$ = NULL;
- }
- | rwaddr rwtok {
- $$ = ListAppend ($1, $2, (char *) NULL);
- free ($1);
- }
- | rwaddr IDENT LPAREN rwaddr RPAREN {
- $$ = ListAppend ($1, (Tsb = MakeRSCall ($2, $4)), (char *) NULL);
- free ($1);
- free ($4);
- free (Tsb);
- }
- | error {
- $$ = NULL;
- }
- ;
-
- rwtok : anychar {
- *Cbuf = $1;
- $$ = ListAppend (Cbuf, (char *) NULL, (char *) NULL);
- }
- | mval {
- $$ = MacScan ($1);
- }
- | cantok {
- $$ = $1;
- }
- | reftok {
- $$ = $1;
- }
- ;
-
- cantok : CANON LPAREN IDENT RPAREN {
- $$ = Bracket ($3->psb, TRUE);
- RemoveSymbol ($3);
- }
- | CANON LPAREN SCONST RPAREN {
- $$ = Bracket (MacScan ($3), TRUE);
- free ($3);
- }
- | CANON LPAREN reftok RPAREN {
- $$ = Bracket ($3, TRUE);
- free ($3);
- }
- ;
-
- reftok : DOLLAR IDENT {
- Mbuf[1] = MakeMac ($2, ID_MACRO);
- $$ = ListAppend (Mbuf, (char *) NULL, (char *) NULL);
- }
- | DOLLAR ICONST {
- $$ = ListAppend (MakePosTok ($2), (char *) NULL, (char *) NULL);
- }
- ;
-
- anychar : SEPCHAR {
- $$ = $1;
- }
- | COLON {
- $$ = ':';
- }
- | STAR {
- $$ = '*';
- }
- | SEMI {
- $$ = ';';
- }
- | LBRACE {
- $$ = '{';
- }
- | RBRACE {
- $$ = '}';
- }
- | COMMA {
- $$ = ',';
- }
- | ASGN {
- $$ = '=';
- }
- ;
-
- resolution : mailerspec COMMA route {
- $$ = ListAppend ($1, $3, (char *) NULL);
- free ($1);
- free ($3);
- }
- | error {
- $$ = NULL;
- }
- ;
-
- mailerspec : MAILER LPAREN rword RPAREN {
- $$ = ListAppend ("$#", $3, (char *) NULL);
- }
- ;
-
- route : HOST LPAREN hword RPAREN COMMA userspec {
- $$ = ListAppend (Tsb = ListAppend ("$@", $3, (char *) NULL),
- $6, (char *) NULL);
- free (Tsb);
- free ($6);
- }
- | userspec {
- $$ = $1;
- }
- ;
-
- hword : hostid {
- $$ = $1;
- }
- | HOSTNUM LPAREN reftok RPAREN {
- $$ = Bracket ($3, FALSE);
- free ($3);
- }
- ;
-
- hostid : /* empty */ {
- $$ = NULL;
- }
- | hostid IDENT {
- $$ = ListAppend ($1, $2->psb, (char *) NULL);
- RemoveSymbol ($2);
- free ($1);
- }
- | hostid rwtok {
- $$ = ListAppend ($1, $2, (char *) NULL);
- free ($1);
- }
- ;
-
- userspec : USER LPAREN rwaddr RPAREN {
- $$ = ListAppend ("$:", $3, (char *) NULL);
- free ($3);
- }
- ;
-
- rword : IDENT {
- $$ = CheckMailer ($1);
- }
- | reftok {
- $$ = $1;
- }
- ;
-
- fdefs : /* empty */
- | fdefs IDENT idlist COLON ftype SEMI {
- AssignType (ListAppend ($2->psb, $3, " "), $5);
- free ($3);
- }
- | error SEMI {
- yyerrok;
- }
- ;
-
- idlist : /* empty */ {
- $$ = NULL;
- }
- | idlist COMMA IDENT {
- $$ = ListAppend ($1, $3->psb, " ");
- free ($1);
- }
- ;
-
- ftype : MATCH LPAREN ICONST RPAREN cdef {
- $$ = ListAppend (MakeField ($3, $5, FALSE),
- (char *) NULL, (char *) NULL);
- }
- | MATCH LPAREN ICONST STAR RPAREN {
- $$ = ListAppend (MakeField ($3, (struct he *) NULL, TRUE),
- (char *) NULL, (char *) NULL);
- }
- | error {
- $$ = NULL;
- }
- ;
-
- cdef : /* empty */ {
- $$ = NULL;
- }
- | IN IDENT {
- $$ = $2;
- }
- ;
- SHAR_EOF
- if test 14482 -ne "`wc -c parser.y`"
- then
- echo shar: error transmitting parser.y '(should have been 14482 characters)'
- fi
- chdir ..
- # End of shell archive
- exit 0
-
-