aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-06-27 17:29:29 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-06-27 17:41:12 +0300
commit34e1da35d027cbeb81bd2cd5ade3bc83b1641534 (patch)
treecb3da507e54755cbdc1f97299ef9c4074f60bdab
parent88622645e52c656cbfadee7a4e91ca42a0860159 (diff)
downloadrush-34e1da35d027cbeb81bd2cd5ade3bc83b1641534.tar.gz
rush-34e1da35d027cbeb81bd2cd5ade3bc83b1641534.tar.bz2
New transformation statements: insert and remopt
* doc/rush.rc.5: Update (unfinished). * doc/rush.texi: Document the changes. * etc/rush.rc (svn): Rewrite the rule using insert and remopt. * src/cfgram.y: New statements: insert and remopt. * src/cflex.l: New keywords. * src/config.c (_parse_transform_ar,_parse_map_ar) (_parse_delete_ar,_parse_delete): Initialize node->target.v.arg.ins to 0. * src/rush.c (get_arg_no): Strict boundary checking. (rush_transform): Special handling for transform_remopt. Support argument insertions. * src/rush.h (transform_target.arg): Change type. (transform_remopt): New constant. (option_defn): New struct. (transform_node.v.remopt): New member. * tests/insert.at: New file. * tests/remopt.at: New file. * tests/Makefile.am: Add new tests. * tests/testsuite.at: Include new tests.
-rw-r--r--doc/rush.rc.5478
-rw-r--r--doc/rush.texi245
-rw-r--r--etc/rush.rc5
-rw-r--r--src/cfgram.y94
-rw-r--r--src/cflex.l2
-rw-r--r--src/config.c15
-rw-r--r--src/rush.c143
-rw-r--r--src/rush.h12
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/insert.at69
-rw-r--r--tests/remopt.at120
-rw-r--r--tests/testsuite.at2
12 files changed, 1074 insertions, 113 deletions
diff --git a/doc/rush.rc.5 b/doc/rush.rc.5
index 97d70d4..1632f18 100644
--- a/doc/rush.rc.5
+++ b/doc/rush.rc.5
@@ -13,14 +13,46 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with GNU Rush. If not, see <http://www.gnu.org/licenses/>.
-.TH RUSH.RC 5 "May 16, 2019" "RUSH.RC" "Rush User Reference"
+.\"
+.\" Additional macros used in this document:
+.\"
+.\" Begins example text
+.de ex
+. nr rush-saved-indent \\n[.i]
+. nr rush-level-indent (\\n[rush-saved-indent] +2m)
+. nr mE \\n(.f
+. nf
+. nh
+. ft CW
+. in \\n[rush-level-indent]u
+. sp
+..
+.\" End example.
+.de ee
+. in \\n[rush-saved-indent]u
+. ft \\n(mE
+. fi
+. hy \\n(HY
+. sp
+..
+.de table
+. sp
+. nf
+. ta \\$1 \\$2
+..
+.de tabend
+. fi
+. sp
+..
+.\" Document begins
+.TH RUSH.RC 5 "June 26, 2019" "RUSH.RC" "Rush User Reference"
.SH NAME
-rush.rc \- configuration rules for rush.
+rush.rc \- configuration rules for remote user shell
.SH DESCRIPTION
The file
.B /etc/rush.rc
contains a set of rules that the
-.B rush (8)
+.BR rush (8)
shell uses in order to determine whether the user is allowed to
execute the requested command and to set up the environment for
its execution.
@@ -28,6 +60,212 @@ its execution.
Empty lines are ignored. Lines beginning with a pound sign are
comments and are ignored as well.
.PP
+Except for comments and empty lines, each line of the configuration
+file consists of the keyword and optional value, and constitutes a
+\fIstatement\fR. Exceedingly long lines may be split across multiple
+physical lines, by ending each line with a backslash immediately
+followed by a newline. Statements fall into two major classes:
+\fIsection\fR and \fIregular\fR statements. A \fIsection\fR statement
+serves as a container for one or more regular statements that pursue the
+same goal, thus playing the role of a chapter in a book.
+A \fIregular\fR statement modifies a certain aspect of the program's
+behavior.
+.PP
+The overall file structure is as follows:
+.ex
+.B rush 2.0
+
+.B global
+ \fIkeyword\fR \fIvalue\fR
+ ...
+
+.B rule \fIA\fB
+ \fIkeyword\fR \fIvalue\fR
+ ...
+
+.B rule \fIB\fB
+ \fIkeyword\fR \fIvalue\fR
+ ...
+.ee
+.PP
+A configuration file must begin with a \fBrush\fR statement indicating
+the version of the syntax this file uses. Current versions of
+\fBrush\fR implement syntax version 2.0. In the absence of the initial
+\fBrush\fR statement, the program will treat the configuration file as
+written in legacy configuration syntax (see
+.B http://www.gnu.org.ua/software/rush/manual/1.x
+for details).
+.PP
+There are two section statements:
+.B global
+and
+.BR rule .
+The
+.B global
+section contains statements configuring the behavior of the program
+in general. There can be as many \fBglobal\fR statements in the
+configuration as you consider necessary, each of them affecting the
+material up to the next \fBglobal\fR statement, or end of the file,
+whichever occurs first.
+.PP
+Examples of statements that can be used in a \fBglobal\fR section are:
+.BR debug ,
+which sets the debug verbosity level,
+.BR message ,
+which configures error messages, etc. See the
+.B FIXME REF
+for the full list.
+.PP
+One or more
+.B rule
+statements constitute the core of the configuration. Each
+.B rule
+statement provides a recipe for serving a specific class of input
+commands. When
+.B rush
+is invoked with a specific command, it will scan the
+configuration file looking for a rule that matches the requested
+command line. If such a rule is found, it will be applied. Commands
+that don't match any rule will be rejected.
+.PP
+A \fBrule\fR statement may be followed by a \fItag\fR, an aribtrary
+sequence of non-whitespace characters serving as a label for this
+rule. This sequence will be used in diagnostic messages to identify
+this rule. In the absense of user-supplied tag, the default one will be
+generated, consisting of the \fB#\fR symbol followed by the ordinal
+number of the rule in the configuration file (started with 1).
+.PP
+To match a particular command, each rule should contain the
+.B match
+statement. Its argument is a conditional expression that can contain
+comparison and boolean operators. The operands can refer to the
+command line using shell-like variables:
+.B $command
+to refer to the entire command line,
+.BR $# ,
+referring to the number of arguments in the command line (the command
+itself being counted as one of the arguments),
+.BR $0
+meaning the command name, and
+.BR $1 ,
+.BR $2 ,
+etc., referring to the particular command line arguments (arguments
+past the ninth one can be accessed as, e.g.
+.BR ${10} ).
+Thus, the following rule:
+.ex
+rule
+ match $command == "ls"
+.ee
+will match only the
+.B ls
+command without arguments.
+.PP
+The
+.B ~
+(tilde) operator denotes regular expression matching. For example,
+the following rule matches \fBls\fR command, optionally preceded with
+any path prefix:
+.ex
+rule
+ match $0 ~ "^(.*/)?ls$"
+.ee
+\fBMatch\fR expressions can contain terms of arbitrary complexity.
+Consider the following example:
+.ex
+rule
+ match $0 ~ "^(.*/)?ls$" && $# == 2 \\
+ && $1 !~ "^(/|/etc)$"
+.ee
+This rule will match any \fBls\fR command having exactly one argument,
+unless that argument is \fB/\fR or \fB/etc\fR. Notice the use of the
+.B !~
+operator to denote the negated regular expression matching, and the use
+of backslash to split a single expression across two physical lines.
+.PP
+Variables are referenced using the same syntax as in shell. For
+example,
+.B ${1:-/bin}
+expands to the value of the first parameter, if it is supplied, or
+to the string "/bin" otherwise. See \fIFIXME REF\fR for details.
+.PP
+Although important, the \fBmatch\fR statement is not mandatory in a
+\fBrule\fR statement. If it is absent, the rule will match any
+command line. This is normally used in \fIfall-through\fR rules.
+A \fIfall-through\fR rule applies modifications to the command
+environment. After applying such rule, the scanning resumes at
+the rule that follows it. Fall-through rules are marked with
+the
+.BR fall\-through
+statement.
+.PP
+A rule can modify the command line and environment in which it will be
+executed. The \fBset\fR statement is provided for altering the
+command line or its parts. It takes three arguments: the variable
+name or index, the operator and the value. For example, the
+statement:
+.ex
+set command = "/bin/sftp-server -u 002"
+.ee
+replaces the entire command line. To replace particular arguments,
+use the \fB[\fIN\fR]\fR syntax, where \fIN\fR is the index of the
+argument in the command line. For example, to set the first argument:
+.ex
+set [1] = "/tmp"
+.ee
+The part to the right of the equals sign can contain a transformation,
+i.e. a string followed by the \fB~\fR operand and a
+\fIs-expression\fR of the form
+\fBs/\fIregexp\fB/\fIreplacement\fB/\fR[\fIflags\fR].
+Parenthesized groups in \fIregexp\fR can be referred to in
+\fIreplacement\fR using the backreference construct in the form
+\fB\\\fIN\fR, where \fIN\fR is the 1-based ordinal number of the
+group. For example, the following statement sets the second argument
+to the directory part of the first one:
+.ex
+set [2] = "$1" ~ "s/(.*)\\//\\1/"
+.ee
+Two points are worth noticing. First, the left operand of \fB~\fR
+undergoes variable expansion. Secondly, the right-hand side operand
+is quoted and therefore each backslash in it has to be escaped.
+.PP
+The special operator \fB=~\fR is used if the resulted value is
+assigned to the same variable that served as its argument. For
+example, the two statements below are equivalent:
+.ex
+set [1] =~ "s/(.*)\\//\\1/"
+set [1] = "$1" ~ "s/(.*)\\//\\1/"
+.ee
+Parenthesized groups matched by the most recent \fBset\fR statement
+remain available for use in the statements that follow it in the rule.
+To refer to the group from the recent matching, use the following
+construct: \fB%\fIN\fR. For example, the following two statements set
+the first argument to the directory part, and second argument to the
+basename of the original \fB$1\fR value:
+.ex
+set [1] =~ "s/(.*)\\/(.*)/\\1/"
+set [2] = %2
+.ee
+The
+.B set
+statement operates not only on positional arguments and built-in
+variables, but also on arbitrary user-defined variables. A
+user-defined variable springs into existence when it first appears as
+a left-hand side argument to the \fBset\fR statement. The name of the
+variable must follow the usual rules for variable names: it must begin
+with an alphabetical character or underscore and contain only letters,
+digits and underscores. References to user-defined variables follow
+the same syntax as for built-in ones.
+.PP
+The following example uses temporary variable \fBtemp\fR to swap two
+arguments:
+.ex
+set temp = $1
+set [1] = $2
+set [2] = $temp
+.ee
+
+.SH REFERENCE: LEXICAL STRUCTURE
A
.I statement
consists of a keyword and arguments, separated by any amount
@@ -71,8 +309,7 @@ expansion.
.sp
During \fIbackslash interpretation\fR, the \fIescape sequences\fR
are recognized and replaced as per table below:
-.nf
-.ta 8n 20n
+.table 8n 20n
.ul
Sequence Replaced with
\\a Audible bell character (ASCII 7)
@@ -85,8 +322,7 @@ are recognized and replaced as per table below:
\\\\ A single backslash
\\\(dq A double-quote.
\\% Percent sign
-.fi
-.sp
+.tabend
In addition, the sequence \fB\\\fInewline\fR is removed from
the string. This allows to split long strings over several
physical lines.
@@ -117,26 +353,20 @@ identifiers: it must begin with a letter and consist of letters,
digits and underscores. Variable name in curly braces can be followed
by \fB\-\fR, \fB=\fR, \fB?\fR, or \fB+\fR, optionally preceded by
\fB:\fR as summarized in the table below:
-.sp
-.nf
-.ta 8n 30n
+.table 8n 30n
.ul
Reference Meaning
${\fIVAR\fR:-\fIWORD\fR} Use Default Values
${\fIVAR\fR:=\fIWORD\fR} Assign Default Values
${\fIVAR\fR:?\fIWORD\fR} Display Error if Null or Unset
${\fIVAR\fR:+\fIWORD\fR} Use Alternate Value
-.fi
-.sp
+.tabend
where \fIWORD\fR stands for any valid token as described in this
section. See the section \fBVARIABLE EXPANSION\fR, for a detailed
discussion of these forms and their meaning.
.TP
.I Comparison and boolean operators
-These are:
-.sp
-.nf
-.ta 8n 30n
+.table 8n 30n
&& Boolean AND
|| Boolean OR
! Boolean negation
@@ -152,35 +382,215 @@ These are:
group Membership in UNIX group
= Assignment
=~ Regular expression substitution
-.fi
-.sp
-.SH STATEMENTS
+.tabend
+.SH REFERENCE: STATEMENTS
There are three global statements, two of which can contain multiple
-substatements.
-.SS rush
-Each configuration file must begin with the \fBrush\fR statement. It
-must be exactly as follows:
+substatements:
.TP
.B rush 2.0
-Declare version of the configuration file syntax.
-.PP
+Declares the version of the syntax this configuration file is written
+in. This must be the first statement in the configuration file.
If this statement is missing, the configuration file will be treated
as
.I legacy configuration file
from previous versions of
.BR "GNU rush" .
-
-Currently two versions are supported. Version 2.0 is the current
-syntax version. Configuration file of the previous \fBrush\fR versions
+For the discussion of the legacy configuration file, please refer to
+.BR http://www.gnu.org.ua/software/rush/manual/1.x .
.TP
.B global
-Introduces global settings. The settings changed within this section
-remain in effect until changed by the next \fBglobal\fR statement.
+Defines global settings.
.TP
-.B rule
-Defines a rule.
+\fBrule\fR [\fITAG\fR]
+Contains a set of rules for a certain class of input command lines.
.SS global
-The \fBglobal\fR statement
+Introduces global settings. This statement is followed by one or
+more substatements. Global settings end at the nearest \fBrule\fR
+statement that follows. They remain in effect until the next
+\fBglobal\fR statement is encountered which alters them.
+.PP
+The following statements may appear in this section.
+.TP
+\fBexpand\-undefined\fR \fIBOOL\fR
+Controls how undefined variables are expanded.
+If \fIBOOL\fR is \fBtrue\fR, references to undefined variables are
+replaced with empty values. If it is \fBfalse\fR (the default), an
+error message is issued and program terminates.
+
+Any of the following values can be used as a synonym for \fBtrue\fR:
+.BR yes ,
+.BR on ,
+.BR t ,
+.BR 1 .
+
+The following values can be used as synonyms for \fBfalse\fR:
+.BR no ,
+.BR off ,
+.BR nil ,
+.BR 0 .
+.TP
+\fBdebug\fR \fINUM\fR
+Set debugging level. The bigger \fINUM\fR is, the more verbose is the
+logging. The debugging information is reported via \fBsyslog\fR at facility
+\fBauthpriv\fR, priority \fBdebug\fR.
+.TP
+\fBsleep\-time\fR \fINUM\fR
+Set the time in seconds to sleep before exiting on error.
+This statement is intended as a measure against brute-force attacks.
+Default sleep time is 5 seconds.
+.TP
+\fBmessage\fR \fICLASS\fR \fITEXT\fR
+Define a textual message which is returned to the remote party if an
+error of the given \fICLASS\fR occurs. Valid classes are:
+.RS 4
+.TP
+.B usage\-error
+This error is reported when \fBrush\fR has been invoked improperly.
+The default text is:
+.sp
+\fB"You are not permitted to execute this command."\fR
+.TP
+.B nologin\-error
+A message which is returned if there is no such user name in the
+password database. Defaults to:
+.sp
+\fB"You are not permitted to execute this command."\fR
+.TP
+.B config\-error
+Define a textual message which is returned if the configuration file
+contained errors. Default is:
+.sp
+\fB"Local configuration error occurred."\fR
+.TP
+.B system\-error
+Define a textual message which is returned if a system error occurs.
+Default is:
+.sp
+\fB"A system error occurred while attempting to execute command."\fR
+.RE
+.TP
+\fBregexp\fR \fIFLAG\fR [\fIFLAG\fR...]
+Configure the type of regular expressions to be used by subsequent
+\fBmatch\fR and \fBset\fR statements. Each \fIFLAG\fR is a word
+specifying a regular expression feature. It can be preceded by a plus
+sing to enable this feature (this is the default), or by the minus
+sign to disable it. Valid flags are:
+.RS 4
+.TP
+.B extended
+Use POSIX Extended Regular Expression syntax when
+interpreting regex. This is the default.
+.TP
+.B basic
+Use basic regular expressions. Equivalent to \fB\-extended\fR.
+.TP
+\fBicase\fR or \fBignore\-case\fR
+Do not differentiate case. Subsequent regex matches will be case
+insensitive.
+.RE
+.TP
+\fBinclude\-security\fR \fIFLAG\fR [\fIFLAG\fR...]
+Configure the security checks for include files. Valid flags are:
+.RS 4
+.TP
+.B all
+Enable all checks.
+.TP
+.B owner
+The file must be owned by root.
+.TP
+\fBiwgrp\fR or \fBgroupwritablefile\fR
+Forbid group writable files.
+.TP
+\fBiwoth\fR or \fBworldwritablefile\fR
+Forbid world writable files.
+.TP
+\fBdir_iwgrp\fR or \fBgroupwritabledir\fR
+Forbid files that reside in group writable directories.
+.TP
+\fBdir_iwoth\fR or \fBworldwritabledir\fR
+Forbid files that reside in world writable directories.
+.TP
+\fBlink\fR
+Forbid symbolic links to files residing in group or world
+writable directories.
+.RE
+.sp
+Each of the above keywords can be prefixed by \fBno\fR, which
+reverses its meaning. The special keyword \fBnone\fR disables all
+checks.
+.TP
+\fBacct\-umask\fR \fIMASK\fR
+Set umask used when accessing accounting database files. Default
+value is 022.
+.TP
+\fBacct\-dir\-mode\fR \fIMODE\fR
+Set mode bits for the accounting directory. The argument
+is the mode in octal.
+.TP
+\fBacct\-file\-mode\fR \fIMODE\fR
+Set mode bits for the \fBwtmp\fR and \fButmp\fR files.
+.SS rule
+Defines a rule. This is a block statement, which means that all statements
+located between it and the next \fBrule\fR statement (or end of file,
+whichever occurs first) modify the definition of that rule.
+.PP
+The syntax is:
+.ex
+rule \fBTAG\fR
+.ee
+Optional \fBTAG\fR argument supplies the identifier for that rule. It
+is used in diagnostic messages. If tag is missing, \fBrush\fR will
+supply a default one, which is constructed by concatenating the
+\fB#\fR character and the ordinal number of rule in the configuration
+file, in decimal notation. Rule numbering starts from 1.
+.PP
+A rule can contain the following statements:
+.TP
+\fBmatch\fR \fIEXPR\fR
+Defines conditions that decide whether the rule matches the particular
+request. The \fIEXPR\fR argument is a comparison expression. It can
+be a simple comparison expression or a boolean expression involving
+several other expressions.
+.sp
+A simple expression is either a comparison or a membership test. A
+comparison has the general syntax
+.ex
+.I lhs op rhs
+.ee
+where \fIlhs\fR and \fIrhs\fR are operands and \fIop\fR is the
+operation. The \fIlhs\fR is either a string (quoted or unquoted), or
+a variable reference. The \fIrhs\fR is a string or number. Prior to
+evaluating a simple expression, its \fILHS\fR undergoes variable
+expansion. In contrast, the \fIRHS\fR operand is always treated
+verbatim.
+.sp
+The comparison operator \fIOP\fR is one of the following:
+.table 8n 30n
+ == Equality (string or numeric)
+ != Inequality (string or numeric)
+ < Less than
+ <= Less than or equal to
+ > Greater than
+ >= Greater than or equal to
+ ~ Regexp matching
+ !~ Negated regexp matching
+.tabend
+Two membership tests are available:
+.RS +4
+.TP
+\fILHS\fR \fBin\fR ( \fISTRING\fR ... )
+.TP
+\fBgroup\fR \fIGRP\fR
+.RE -4
+Compound boolean expression combine one or more expressions using
+logical operators
+.table 8n 30n
+ && Boolean AND
+ || Boolean OR
+ ! Boolean negation
+.tabend
+
.SH SEE ALSO
.BR rush (8),
.BR rushlast (1),
@@ -203,5 +613,5 @@ There is NO WARRANTY, to the extent permitted by law.
.\" time-stamp-start: ".TH [A-Z_][A-Z0-9_.\\-]* [0-9] \""
.\" time-stamp-format: "%:B %:d, %:y"
.\" time-stamp-end: "\""
-.\" time-stamp-line-limit: 20
+.\" time-stamp-line-limit: 60
.\" end:
diff --git a/doc/rush.texi b/doc/rush.texi
index a895443..cbc84aa 100644
--- a/doc/rush.texi
+++ b/doc/rush.texi
@@ -146,9 +146,12 @@ Matching Conditions
Modifying variables
-* set:: Set variable
-* unset:: Unset variable
-* map:: Use file lookup to modify variable
+* set:: Set variable.
+* insert:: Insert positional arguments.
+* unset:: Unset variable.
+* remopt:: Remove options.
+* delete:: Delete arguments.
+* map:: Use file lookup to modify variable.
Localization
@@ -418,7 +421,7 @@ are recognized and replaced as per table below:
A backslash immediately followed by newline character is removed.
A backslash followed by any other character except as listed above
-is retained along with the character.
+is retained along with the character.
@cindex backreference interpretation
@anchor{backreference}
@@ -561,10 +564,10 @@ an undefined variable is expanded (@pxref{Variable expansion}).
If @var{bool} is @samp{true}, expand undefined variables to empty
value. If it is @samp{false} (the default), issue an error and abort.
-The following values can be used as a synonym for @samp{true}:
+The following values can be used as synonyms for @samp{true}:
@samp{yes}, @samp{on}, @samp{t}, @samp{1}.
-The following values can be used as a synonym for @samp{false}:
+The following values can be used as synonyms for @samp{false}:
@samp{no}, @samp{off}, @samp{nil}, @samp{0}.
@end deffn
@@ -686,7 +689,7 @@ expressions for use by subsequent @code{match} and
Configure the type of regular expressions.
@end deffn
-Each @var{flag} is word specifying some regular expression
+Each @var{flag} is a word specifying some regular expression
feature. It can be preceded by @samp{+} to enable this feature (this
is the default), or by @samp{-} to disable it. Valid flags are:
@@ -804,7 +807,7 @@ is the mode in octal.
@end deffn
@deffn {global} acct-file-mode @var{mode}
-Set mode bits for @file{wtmp} and @file{utmp} files.
+Set mode bits for the @file{wtmp} and @file{utmp} files.
@end deffn
@node Rule
@@ -975,7 +978,7 @@ result of processing.
@subsubsection Variable Expansion
Most statements in the configuration file undergo variable expansion prior
-to their use. During variable expansion, any references to variables
+to their use. During variable expansion, references to variables
in the string are replaced with their actual values. A variable
reference has two basic forms:
@@ -1020,10 +1023,15 @@ substituted, otherwise the expansion of @var{word} is substituted.
These constructs test for a variable that is unset or null. Omitting
the colon results in a test only for a variable that is unset.
+When expanding a variable reference, the variable name is first looked
+among the request variables. If it is not found, it is looked up in
+the user-defined variable list. If it is not there, the look up in
+the environment is attempted.
+
@anchor{handling of undefined variables}
@cindex expansion of undefined variables
@cindex undefined variable, expansion
-If an undefined variable is encountered during variable expansion, the
+If the variable name is not found in any of these lists, the
default @command{rush} behavior is to report the error of
@samp{config-error} class (@pxref{Error Messages}) and exit. To
gracefully handle such cases, use the @dfn{default value construct},
@@ -1092,7 +1100,7 @@ A @dfn{comparison expression} is:
@noindent
here, @var{lhs} (@dfn{left-hand side}) is a string (quoted or
-unquoted), or variable reference (@pxref{Lexical Structure}),
+unquoted), or a variable reference (@pxref{Lexical Structure}),
@var{rhs} (@dfn{right-hand side}) is a string or number, and @var{op}
is one of the following binary operators:
@@ -1111,8 +1119,8 @@ is one of the following binary operators:
@end float
Prior to evaluating a simple expression, its left-hand side
-undergoes variable expansion. In contrast, the right-hand side is
-always treated verbatim.
+undergoes variable expansion and backreference interpretation. In
+contrast, the right-hand side is always treated verbatim.
For example the following rule will match any request with 2 or more
arguments (recall, that the command name itself is counted as one of
@@ -1150,7 +1158,7 @@ regular expression in the @var{rhs}.
If the regular expression contains parenthesized groups, subsequent
commands can refer to the strings that matched the groups using the
@dfn{backreference notation} @samp{%@var{n}}, where @var{n} is 1-based
-index ordinal number of the group in the regular expression
+index ordinal number of the group in the regular expression
(@pxref{backreference}). The reference @samp{%0} expands to the
entire matched string. For example:
@@ -1233,7 +1241,7 @@ either the UID is 100 or the user is a member of the group @samp{git}:
rule
match $0 ~ "git-(receive|upload)-pack" && \
($uid == 100 || group "git")
-@end group
+@end group
@end example
@noindent
@@ -1279,9 +1287,12 @@ equivalent to removing the corresponding argument from the command
line.
@menu
-* set:: Set variable
-* unset:: Unset variable
-* map:: Use file lookup to modify variable
+* set:: Set variable.
+* insert:: Insert positional arguments.
+* unset:: Unset variable.
+* remopt:: Remove options.
+* delete:: Delete arguments.
+* map:: Use file lookup to modify variable.
@end menu
@node set
@@ -1306,7 +1317,7 @@ It is discussed in more detail in @ref{Transformations}.
Applies the @command{sed} search-and-replace expression @var{s-expr}
to @var{value} and assigns the result to the variable @var{name} or
argument @var{n}. Both @var{value} and @var{s-expr} are subject to
-variable expansion.
+variable expansion and backreference interpretation.
@end deffn
@deffn {rule} set @var{name} =~ @var{s-expr}
@@ -1398,6 +1409,52 @@ into a regular expression is
s/(.*)\//\1/
@end example
+@node insert
+@subsubsection The @code{insert} statement
+The @code{insert} statement inserts new positional argument at a given
+position. Its syntax is similar to @code{set}:
+
+@deffn {rule} insert [@var{n}] = @var{value}
+@deffnx {rule} insert [@var{n}] = @var{value} ~ @var{s-expr}
+Shift arguments starting from @var{n} one position to the right (so
+that @var{n} becomes @var{n+1} etc.) and insert @var{value} at
+@code{argv[@var{n}]}.
+
+In the second form, the value to be inserted is computed by applying
+sed-expression @var{s-expr} to @var{value}.
+
+Both @var{value} and @var{s-expr} are subject to variable expansion
+and backreference interpretation.
+@end deffn
+
+Example using this statement to insert the @code{--root=/tmp} argument
+at position 1:
+
+@example
+insert [1] = "--root=/tmp"
+@end example
+
+@noindent
+Note that when inserting multiple arguments (e.g. an option with a
+value), you have two possibilities. First, you can insert each
+argument at its corresponding position. For example, to insert two
+arguments @samp{--root} and @samp{/tmp} starting at position 1, one
+can use:
+
+@example
+insert [1] = "--root"
+insert [2] = "/tmp"
+@end example
+
+@noindent
+Otherwise, you can revert the arguments and insert them at the same
+position, as shown in the example below:
+
+@example
+insert [1] = "/tmp"
+insert [1] = "--root"
+@end example
+
@node unset
@subsubsection The @code{unset} statement
@@ -1405,6 +1462,67 @@ s/(.*)\//\1/
Unsets the variable @var{name}.
@end deffn
+@deffn {rule} unset @var{n}
+Unset the positional argument @var{n} (an integer number greater than
+0), shifting the remaining arguments one position left. The effect is
+the same as from @code{delete} (@pxref{delete}).
+@end deffn
+
+@node remopt
+@subsubsection The @code{remopt} statement
+The @code{remopt} statement removes from the command line all
+occurrences of the supplied option.
+
+@deffn {rule} remopt @var{sopt}
+@deffnx {rule} remopt @var{sopt} @var{lopt}
+Remove from the command line all occurrences of the short option
+described by @var{sopt}. The @var{sopt} argument is the short option
+letter, optionally followed by a colon if that option takes a
+mandatory argument, or by two colons if it takes an optional argument.
+
+Optional @var{lopt} supplies a long option equivalent to @var{sopt}.
+If no short option equivalent exists, use @samp{_} as @var{sopt},
+eventually followed by @samp{:} or @samp{::}.
+@end deffn
+
+For example, to remove all occurrences of the @code{-r}
+(@code{--root}) option that takes a mandatory argument, use:
+
+@example
+remopt r: root
+@end example
+
+@node delete
+@subsubsection The @code{delete} statement
+
+Another statement modifying the command line is @code{delete}:
+
+@deffn {rule} delete @var{n}
+Delete @var{n}th argument.
+@end deffn
+
+@deffn {rule} delete @var{i} @var{j}
+Delete positional parameters between @samp{$@var{i}} and @samp{$@var{j}},
+inclusive.
+@end deffn
+
+Neither form can be used to delete the program name (@samp{$0}).
+
+For example, the following statement deletes all arguments from
+the command line, except for the program name:
+
+@example
+delete 1 -1
+@end example
+
+To delete a single argument, @code{unset} can also be used. The
+following statements have the same effect:
+
+@example
+delete 2
+unset 2
+@end example
+
@node map
@subsubsection The @code{map} statement
@@ -1557,9 +1675,14 @@ evalenv $@{DEPTH:=10@}
Transformations are special actions that modify entire command line
or particular arguments from it (positional variables).
- Statements that modify entire command line have been described in
-the previous section: these are @code{set} and @code{map} commands
-with @samp{command} given as first argument.
+ Statements that modify variable have been described in the previous
+section: these are @code{set}, @code{insert}, @code{unset},
+@code{remopt}, @code{delete} and @code{map} statements. When
+@code{set} or @code{map} is applied to the @samp{command} variable, it
+modifies entire command line. When these setatements are applied to an
+index (@samp{[@var{n}]}), they modify the corresponding positional
+variable (argument). This subsection discusses the implications of
+modifying these variable and illustrates them with some examples.
Positional variables and the @code{$command} request variable are
mutually dependent. If the @code{$command} is modified, the word
@@ -1573,21 +1696,45 @@ modified arguments. @xref{Modifying variables}, for more detail on it.
@enumerate 1
@item Echo the command line
@example
+@group
rule
set command = "/bin/echo $command"
+@end group
@end example
-@item This rule first removes all occurrences of @option{-r}
-option and its arguments from the command line, and then adds its own
+@item Remove all occurrences of @option{-r} option and its arguments
+from the command line, and then adds its own
@option{-r} option and replaces @samp{svnserve} with the full program
file name.
+There are at least three different ways to do so.
+
+@enumerate a
+@item The recommended approach is to use the @code{remopt} and
+@code{insert} statements, as shown below:
+
+@example
+@group
+rule svn
+ match $command ~ "^svnserve -t"
+ set program = "/usr/bin/svnserve"
+ remopt r:
+ insert [1] = "-r"
+ insert [2] = "/svnroot"
+@end group
+@end example
+
+@item The same can be achieved using regular expressions. This was
+the default in versions of @command{rush} prior to 2.0:
+
@example
+@group
rule svn
match $command ~ "^svnserve -t"
set command =~ "s/-r *[^ ]*//"
set command =~ \
"s|^svnserve |/usr/bin/svnserve -r /svnroot |"
+@end group
@end example
@noindent
@@ -1602,11 +1749,14 @@ expression in the second @code{set} command will be
@item The same rule, rewritten using the single @command{set} statement:
@example
+@group
rule svn
match $command ~ "^svnserve -t"
set command =~ "s|-r *[^ ]*||;\
s|^svnserve |/usr/bin/svnserve -r /svnroot |"
+@end group
@end example
+@end enumerate
@item Override the executable program name.
@@ -1619,29 +1769,6 @@ rule cvs
@end example
@end enumerate
-@need 800
-@subsubheading Delete
-
-Another statement modifying the command line is @code{delete}:
-
-@deffn {rule} delete @var{n}
-Delete @var{n}th argument.
-@end deffn
-
-@deffn {rule} delete @var{i} @var{j}
-Delete positional parameters between @samp{$@var{i}} and @samp{$@var{j}},
-inclusive.
-@end deffn
-
-Neither form can be used to delete the program name (@samp{$0}).
-
-For example, the following statement deletes all arguments from
-the command line, except for the program name:
-
-@example
-delete 1 -1
-@end example
-
@node System Actions
@subsection System Actions
@cindex system actions
@@ -1753,7 +1880,7 @@ configuration for the next matching rule. Any modifications to the
request found in the fall-through rule take effect immediately, which
means that subsequent rules will see modified command line and
environment. Execution of any other actions found in the fall-through
-rule is delayed until a usual rule is found.
+rule is delayed until a usual rule is found.
A fall-through rule is declared using the following statement:
@@ -2396,7 +2523,7 @@ line option. In this case, the @samp{scp-to} rule will become:
rule scp-to
match $command ~ "^scp (-v )?-t"
...
-@end group
+@end group
@end example
Now, we want users to be able to upload files to
@@ -2413,7 +2540,7 @@ rule scp-to-incoming
$@{-1@} !~ "\\.\\./"
set command "/bin/scp"
set [-1] =~ "s|^|/home/ftp/|"
-@end group
+@end group
@end example
The @code{match} statement ensures that no relative components are
@@ -2442,7 +2569,7 @@ rule scp-home
set [0] = "/bin/scp"
set [-1] =~ "s|^|public_html/|"
chdir "~"
-@end group
+@end group
@end example
Finally, we provide two trap rules for diagnostic purposes:
@@ -2456,7 +2583,7 @@ rule scp-to-trap
rule scp-from
match $command ~ "^scp (-v )?-f"
exit Error: Downloads from this directory prohibited
-@end group
+@end group
@end example
@node rsync
@@ -2486,7 +2613,7 @@ rule rsync-home
set [0] = "s|^|/usr/bin/|"
set [-1] =~ "s|^|public_html/|"
chdir "~"
-@end group
+@end group
@end exam