diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-12-13 12:04:56 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-12-13 12:04:56 +0200 |
commit | 151eb4b9e00a56a1e4c85e8120403385012eb95a (patch) | |
tree | f5d4a54192eefbae0401f04a44b650b21949b3a4 | |
parent | a923b221dc3a620dd5507ad935774cc70c9c28ec (diff) | |
download | mailutils-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.c | 35 | ||||
-rw-r--r-- | libmailutils/tests/wordsplit.at | 205 |
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]) |