summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-12-13 12:04:56 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2016-12-13 12:04:56 +0200
commit151eb4b9e00a56a1e4c85e8120403385012eb95a (patch)
treef5d4a54192eefbae0401f04a44b650b21949b3a4
parenta923b221dc3a620dd5507ad935774cc70c9c28ec (diff)
downloadmailutils-151eb4b9e00a56a1e4c85e8120403385012eb95a.tar.gz
mailutils-151eb4b9e00a56a1e4c85e8120403385012eb95a.tar.bz2
Fix command expansion in wordsplit
* libmailutils/string/wordsplit.c: Change ordering of expansions so that command expansion occurs first. This fixes nested expansions and command expansions occurring after variable expansions. * libmailutils/tests/wordsplit.at: Add more tests.
-rw-r--r--libmailutils/string/wordsplit.c35
-rw-r--r--libmailutils/tests/wordsplit.at205
2 files changed, 227 insertions, 13 deletions
diff --git a/libmailutils/string/wordsplit.c b/libmailutils/string/wordsplit.c
index b570ccf17..58d23c0a5 100644
--- a/libmailutils/string/wordsplit.c
+++ b/libmailutils/string/wordsplit.c
@@ -1332,7 +1332,6 @@ expcmd (struct mu_wordsplit *wsp, const char *str, size_t len,
struct mu_wordsplit ws;
rc = _wsplt_subsplit (wsp, &ws, str, j,
- MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
MU_WRDSF_WS | MU_WRDSF_QUOTE);
if (rc)
{
@@ -2064,30 +2063,42 @@ mu_wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex)
}
}
}
+
+/* This structure describes a single expansion phase */
struct exptab
{
- char *descr;
- int flag;
- int opt;
- int (*expansion) (struct mu_wordsplit *wsp);
+ char *descr; /* Textual description (for debugging) */
+ int flag; /* MU_WRDSF_ bit that controls this phase */
+ int opt; /* Entry-specific options (see EXPOPT_ flags below */
+ int (*expansion) (struct mu_wordsplit *wsp); /* expansion function */
};
+/* The following options control expansions: */
+/* Normally the exptab entry is run if its flag bit is set in struct
+ wordsplit. The EXPOPT_NEG option negates this test so that expansion
+ is performed if its associated flag bit is not set in struct wordsplit. */
#define EXPOPT_NEG 0x01
+/* Coalesce the input list before running the expansion. */
#define EXPOPT_COALESCE 0x02
static struct exptab exptab[] = {
- { N_("WS trimming"), MU_WRDSF_WS, 0, mu_wordsplit_trimws },
- { N_("tilde expansion"), MU_WRDSF_PATHEXPAND, 0, mu_wordsplit_tildexpand },
+ { N_("WS trimming"), MU_WRDSF_WS, 0,
+ mu_wordsplit_trimws },
+ { N_("command substitution"), MU_WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE,
+ mu_wordsplit_cmdexp },
+ { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
+ NULL },
+ { N_("tilde expansion"), MU_WRDSF_PATHEXPAND, 0,
+ mu_wordsplit_tildexpand },
{ N_("variable expansion"), MU_WRDSF_NOVAR, EXPOPT_NEG,
mu_wordsplit_varexp },
- { N_("quote removal"), 0, EXPOPT_NEG,
+ { N_("quote removal"), 0, EXPOPT_NEG,
wsnode_quoteremoval },
- { N_("command substitution"), MU_WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE,
- mu_wordsplit_cmdexp },
- { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
+ { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
NULL },
- { N_("path expansion"), MU_WRDSF_PATHEXPAND, 0, mu_wordsplit_pathexpand },
+ { N_("path expansion"), MU_WRDSF_PATHEXPAND, 0,
+ mu_wordsplit_pathexpand },
{ NULL }
};
diff --git a/libmailutils/tests/wordsplit.at b/libmailutils/tests/wordsplit.at
index f2d4bf032..96d2b1fe4 100644
--- a/libmailutils/tests/wordsplit.at
+++ b/libmailutils/tests/wordsplit.at
@@ -420,5 +420,208 @@ NF: 1
],
[input exhausted
])
-
+
+dnl Something that doesn't fit into TESTWSP
+
+AT_SETUP([simple command substitution])
+AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-1])
+AT_CHECK([
+mkdir dir
+> dir/file
+
+wsp -nocmd <<'EOT'
+begin $(find dir) end
+EOT
+],
+[0],
+[NF: 4
+0: begin
+1: dir
+2: dir/file
+3: end
+])
+AT_CLEANUP
+
+AT_SETUP([quoted command substitution])
+AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-2])
+AT_CHECK([
+mkdir dir
+> dir/file
+
+wsp -nocmd <<'EOT'
+begin "$(find dir)" end
+EOT
+],
+[0],
+[NF: 3
+0: begin
+1: "dir dir/file"
+2: end
+])
+AT_CLEANUP
+
+AT_SETUP([coalesced command substitution])
+AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-3])
+AT_CHECK([
+mkdir dir
+> dir/file
+
+wsp -nocmd <<'EOT'
+begin($(find dir))end
+EOT
+],
+[0],
+[NF: 2
+0: begin(dir
+1: dir/file)end
+])
+AT_CLEANUP
+
+AT_SETUP([quoted coalesced command substitution])
+AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-4])
+AT_CHECK([
+mkdir dir
+> dir/file
+
+wsp -nocmd <<'EOT'
+"begin($(find dir))end"
+EOT
+],
+[0],
+[NF: 1
+0: "begin(dir dir/file)end"
+])
+AT_CLEANUP
+
+AT_SETUP([variable and command substitution])
+AT_KEYWORDS([wordsplit wsp wsp-var wsp-var24 wsp-cmd wsp-cmd-5])
+AT_CHECK([
+mkdir dir
+> dir/file
+
+DIR=dir wsp -nocmd -novar<<'EOT'
+begin $DIR $(find $DIR) end
+EOT
+],
+[0],
+[NF: 5
+0: begin
+1: dir
+2: dir
+3: dir/file
+4: end
+])
+AT_CLEANUP
+
+AT_SETUP([variable expansion and command substitution in quotes])
+AT_KEYWORDS([wordsplit wsp wsp-var wsp-var25 wsp-cmd wsp-cmd-6])
+AT_CHECK([
+mkdir dir
+> dir/file
+
+DIR=dir BEGIN=begin wsp -nocmd -novar<<'EOT'
+"${BEGIN}($(find $DIR))end"
+EOT
+],
+[0],
+[NF: 1
+0: "begin(dir dir/file)end"
+])
+AT_CLEANUP
+
+AT_SETUP([nested commands])
+AT_KEYWORDS([wordsplit wsp wsp-cmd])
+AT_CHECK([
+AT_DATA([input],[foo
+bar
+baz
+])
+SUFFIX=put wsp -nocmd -novar <<'EOT'
+$(echo output $(cat in$SUFFIX))
+EOT
+],
+[0],
+[NF: 4
+0: output
+1: foo
+2: bar
+3: baz
+])
+AT_CLEANUP
+
+AT_SETUP([pathname expansion])
+AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-1])
+AT_CHECK([
+mkdir dir
+> dir/1.c
+> dir/2.c
+> dir/3.b
+
+wsp pathexpand<<'EOT'
+begin dir/*.c end
+EOT
+],
+[0],
+[NF: 4
+0: begin
+1: dir/1.c
+2: dir/2.c
+3: end
+])
+AT_CLEANUP
+
+AT_SETUP([pathname expansion: no match])
+AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-2])
+AT_CHECK([
+mkdir dir
+> dir/1.c
+> dir/2.b
+
+wsp pathexpand<<'EOT'
+begin dir/*.d end
+EOT
+],
+[0],
+[NF: 3
+0: begin
+1: dir/*.d
+2: end
+])
+AT_CLEANUP
+
+AT_SETUP([pathname expansion: nullglob])
+AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-3])
+AT_CHECK([
+mkdir dir
+> dir/1.c
+> dir/2.b
+
+wsp pathexpand nullglob<<'EOT'
+begin dir/*.d end
+EOT
+],
+[0],
+[NF: 2
+0: begin
+1: end
+])
+AT_CLEANUP
+
+AT_SETUP([pathname expansion: failglob])
+AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-4])
+AT_CHECK([
+mkdir dir
+> dir/1.c
+> dir/2.b
+
+wsp pathexpand failglob<<'EOT'
+begin dir/*.d end
+EOT
+],
+[0],
+[],
+[no files match pattern dir/*.d
+])
+AT_CLEANUP
+
m4_popdef([TESTWSP])

Return to:

Send suggestions and report system problems to the System administrator.