]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
util: Add shell_escape
authorRichard Maw <richard.maw@codethink.co.uk>
Tue, 23 Jun 2015 10:32:02 +0000 (10:32 +0000)
committerRichard Maw <richard.maw@codethink.co.uk>
Fri, 7 Aug 2015 15:50:43 +0000 (15:50 +0000)
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.

src/basic/util.c
src/basic/util.h
src/test/test-util.c

index 0b974b2ab5690a36e75603effe52bf452a9bc7fe..ebfc6c6a7275317eab86f410890b9d1b4294a6a8 100644 (file)
@@ -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;
index 4d6a8abb574ab1029a3683dedbc0b0243dfba131..098f9edcc1637ec032056ec43a7fc83b86d77c6e 100644 (file)
@@ -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);
index fc7a3de106e9608dd4dc876a63d89577123d5ba7..3c1bac4606b1c2076badc8c077340e24c4485521 100644 (file)
@@ -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();