diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2015-06-23 10:32:02 +0000 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2015-08-07 15:50:43 +0000 |
commit | 61ee6939819963b7845c101485e188ca2a8119c6 (patch) | |
tree | ad6314638c8818c8eff49201eeb74e699f5977a7 /src | |
parent | 8ef24e7a4f4b4d464b66fa7d3f0acaa88800d6cb (diff) |
util: Add shell_escape
This is for shell-style \ escaping rather than quoting, which while it
has the same effect in produced shell commands, is not exclusively
useful for shell commands.
shell_escape would be useful for producing sed commands, as you would be
able to \ escape the normal special characters, plus whichever argument
separator was chosen; or it could be used to escape arguments passed to
the overlayfs mount command.
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/util.c | 34 | ||||
-rw-r--r-- | src/basic/util.h | 1 | ||||
-rw-r--r-- | src/test/test-util.c | 16 |
3 files changed, 44 insertions, 7 deletions
diff --git a/src/basic/util.c b/src/basic/util.c index 0b974b2ab5..ebfc6c6a72 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -6537,6 +6537,32 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char return 0; } +static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) { + assert(bad); + + for (; *s; s++) { + if (*s == '\\' || strchr(bad, *s)) + *(t++) = '\\'; + + *(t++) = *s; + } + + return t; +} + +char *shell_escape(const char *s, const char *bad) { + char *r, *t; + + r = new(char, strlen(s)*2+1); + if (!r) + return NULL; + + t = strcpy_backslash_escaped(r, s, bad); + *t = 0; + + return r; +} + char *shell_maybe_quote(const char *s) { const char *p; char *r, *t; @@ -6563,13 +6589,7 @@ char *shell_maybe_quote(const char *s) { *(t++) = '"'; t = mempcpy(t, s, p - s); - for (; *p; p++) { - - if (strchr(SHELL_NEED_ESCAPE, *p)) - *(t++) = '\\'; - - *(t++) = *p; - } + t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE); *(t++)= '"'; *t = 0; diff --git a/src/basic/util.h b/src/basic/util.h index 4d6a8abb57..098f9edcc1 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -919,6 +919,7 @@ void cmsg_close_all(struct msghdr *mh); int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); +char *shell_escape(const char *s, const char *bad); char *shell_maybe_quote(const char *s); int parse_mode(const char *s, mode_t *ret); diff --git a/src/test/test-util.c b/src/test/test-util.c index fc7a3de106..3c1bac4606 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -2100,6 +2100,21 @@ static void test_sparse_write(void) { test_sparse_write_one(fd, test_e, sizeof(test_e)); } +static void test_shell_escape_one(const char *s, const char *bad, const char *expected) { + _cleanup_free_ char *r; + + assert_se(r = shell_escape(s, bad)); + assert_se(streq_ptr(r, expected)); +} + +static void test_shell_escape(void) { + test_shell_escape_one("", "", ""); + test_shell_escape_one("\\", "", "\\\\"); + test_shell_escape_one("foobar", "", "foobar"); + test_shell_escape_one("foobar", "o", "f\\o\\obar"); + test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz"); +} + static void test_shell_maybe_quote_one(const char *s, const char *expected) { _cleanup_free_ char *r; @@ -2264,6 +2279,7 @@ int main(int argc, char *argv[]) { test_same_fd(); test_uid_ptr(); test_sparse_write(); + test_shell_escape(); test_shell_maybe_quote(); test_parse_mode(); test_tempfn(); |