diff options
-rw-r--r-- | stream.c | 24 | ||||
-rw-r--r-- | tests/018/sh-esc.tl | 11 | ||||
-rw-r--r-- | txr.1 | 90 |
3 files changed, 125 insertions, 0 deletions
@@ -4838,6 +4838,26 @@ static val sh(val command) #endif +static val sh_esc(val string) +{ + return str_esc(lit("|&;<>()$`\\\"' \t\n*?[#~"), chr('\\'), string); +} + +static val sh_esc_all(val string) +{ + return str_esc(lit("|&;<>()$`\\\"' \t\n*?[#~=%"), chr('\\'), string); +} + +static val sh_esc_dq(val string) +{ + return str_esc(lit("$`\\\"\n"), chr('\\'), string); +} + +static val sh_esc_sq(val string) +{ + return str_esc(lit("'"), lit("'\\'"), string); +} + val remove_path(val path, val throw_on_error) { val self = lit("remove-path"); @@ -5556,6 +5576,10 @@ void stream_init(void) reg_fun(intern(lit("sh"), user_package), func_n1(sh)); reg_fun(intern(lit("run"), user_package), func_n2o(run, 1)); #endif + reg_fun(intern(lit("sh-esc"), user_package), func_n1(sh_esc)); + reg_fun(intern(lit("sh-esc-all"), user_package), func_n1(sh_esc_all)); + reg_fun(intern(lit("sh-esc-dq"), user_package), func_n1(sh_esc_dq)); + reg_fun(intern(lit("sh-esc-sq"), user_package), func_n1(sh_esc_sq)); reg_fun(intern(lit("remove-path"), user_package), func_n2o(remove_path, 1)); reg_fun(intern(lit("rename-path"), user_package), func_n2(rename_path)); reg_fun(intern(lit("open-files"), user_package), func_n3o(open_files, 1)); diff --git a/tests/018/sh-esc.tl b/tests/018/sh-esc.tl new file mode 100644 index 00000000..3466ee76 --- /dev/null +++ b/tests/018/sh-esc.tl @@ -0,0 +1,11 @@ +(load "../common") + +(mtest + (sh-esc "|&;<>()$`\\\"' \t\n*?[#~=%abc") + "\\|\\&\\;\\<\\>\\(\\)\\$\\`\\\\\\\"\\'\\ \\\t\\\n\\*\\?\\[\\#\\~=%abc" + (sh-esc-all "|&;<>()$`\\\"' \t\n*?[#~=%abc") + "\\|\\&\\;\\<\\>\\(\\)\\$\\`\\\\\\\"\\'\\ \\\t\\\n\\*\\?\\[\\#\\~\\=\\%abc" + (sh-esc-dq "$`\\\"\n'abc()*~") + "\\$\\`\\\\\\\"\\\n'abc()*~" + (sh-esc-sq "$`\\\"\n'abc()*~") + "$`\\\"\n'\\''abc()*~") @@ -72684,6 +72684,96 @@ and expected to support .onom as a way of specifying a command to execute. +.coNP Functions @, sh-esc @, sh-esc-all @ sh-esc-dq and @ sh-esc-sq +.synb +.mets (sh-esc << str ) +.mets (sh-esc-all << str ) +.mets (sh-esc-dq << str ) +.mets (sh-esc-sq << str ) +.syne +.desc +The functions +.codn sh-esc , +.codn sh-esc-all , +.code sh-esc-dq +and +.code sh-esc-sq +transform the argument string +.code str +for safe insertion into commands. These functions are intended +for use on POSIX systems, where the +command interpreter used by the functions +.code sh +and +.code open-command +and related functions is the POSIX Shell Command Language. + +The +.code sh-esc +function escapes its argument in such a way that the resulting +string may be inserted as an argument into a command. + +The +.code sh-esc-all +function performs a stricter escaping, such that the transformed +string may be inserted into any syntactic context where a +textual operand is required for any reason, such as the +.meta pattern +in the +.mono +.meti <2> ${ var % pattern } +.onom +construct, or + +The +.code sh-esc-dq +function escapes its argument for insertion into a double-quoted field in a +shell command line. It does not add the double quotes themselves. + +The +.code sh-esc-dq +function escapes its argument for insertion into a single-quoted field in a +shell command line. It does not add the single quotes themselves. + +The precise set of characters which are escaped by a backslash by the +.code sh-esc +function is the following: + +.verb + | & ; < > ( ) $ ` \e " ' tab newline space * ? [ # ~ +.brev + +The +.code sh-esc-all +function escapes all the above characters, and also these: + +.verb + = % +.brev + +The +.code sh-esc-dq +function escapes the following characters: + +.verb + $ ` \e " newline +.brev + +To escape with a backslash means to precede every occurrence of the +specified characters with the character +.codn \e . + +The +.code sh-esc-sq +function replaces every occurrence of the +.code ' +character (single quote, apostrophe) with the sequence +.code '\e'' +(single quote, backslash, single quotes, single quote). +This sequence has the effect of terminating the enclosing single-quoted +field, then producing a single quote via a backslash escape, +and then opening a single-quoted field. + .SS* Unix Filesystem Manipulation .coNP Structure @ stat |