summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2015-06-23 10:32:02 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2015-08-07 15:50:43 +0000
commit61ee6939819963b7845c101485e188ca2a8119c6 (patch)
treead6314638c8818c8eff49201eeb74e699f5977a7
parent8ef24e7a4f4b4d464b66fa7d3f0acaa88800d6cb (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.
-rw-r--r--src/basic/util.c34
-rw-r--r--src/basic/util.h1
-rw-r--r--src/test/test-util.c16
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();