Blame SOURCES/0181-util-add-shell_maybe_quote-call-for-preparing-a-stri.patch

17b0f1
From 32b4631e74262e02094c6402d39d1e4264442037 Mon Sep 17 00:00:00 2001
17b0f1
From: Lennart Poettering <lennart@poettering.net>
17b0f1
Date: Thu, 9 Apr 2015 18:32:21 +0200
17b0f1
Subject: [PATCH] util: add shell_maybe_quote() call for preparing a string for
17b0f1
 shell cmdline inclusion
17b0f1
17b0f1
If necessary the passed string is enclosed in "", and all special
17b0f1
characters escapes.
17b0f1
17b0f1
This also ports over usage in bus-util.c and job.c to use this, instead
17b0f1
of a incorrect local implementation that forgets to properly escape.
17b0f1
17b0f1
Conflicts:
17b0f1
	src/shared/util.c
17b0f1
	src/shared/util.h
17b0f1
17b0f1
Cherry-picked from: 019c7fba
17b0f1
Resolves: #1016680
17b0f1
---
17b0f1
 src/core/job.c                   |  8 +++---
17b0f1
 src/libsystemd/sd-bus/bus-util.c | 15 +++++------
17b0f1
 src/shared/util.c                | 45 ++++++++++++++++++++++++++++++--
17b0f1
 src/shared/util.h                |  2 ++
17b0f1
 src/test/test-util.c             | 19 ++++++++++++++
17b0f1
 5 files changed, 74 insertions(+), 15 deletions(-)
17b0f1
17b0f1
diff --git a/src/core/job.c b/src/core/job.c
17b0f1
index 4740ff18cb..7416386a18 100644
17b0f1
--- a/src/core/job.c
17b0f1
+++ b/src/core/job.c
17b0f1
@@ -679,15 +679,13 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
17b0f1
                         break;
17b0f1
 
17b0f1
                 case JOB_FAILED: {
17b0f1
-                        bool quotes;
17b0f1
+                        _cleanup_free_ char *quoted = NULL;
17b0f1
 
17b0f1
-                        quotes = chars_intersect(u->id, SHELL_NEED_QUOTES);
17b0f1
+                        quoted = shell_maybe_quote(u->id);
17b0f1
 
17b0f1
                         manager_flip_auto_status(u->manager, true);
17b0f1
                         unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
17b0f1
-                        manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL,
17b0f1
-                                              "See \"systemctl status %s%s%s\" for details.",
17b0f1
-                                              quotes ? "'" : "", u->id, quotes ? "'" : "");
17b0f1
+                        manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
17b0f1
                         break;
17b0f1
                 }
17b0f1
 
17b0f1
diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
17b0f1
index 52d4ebe611..b0a5a7592a 100644
17b0f1
--- a/src/libsystemd/sd-bus/bus-util.c
17b0f1
+++ b/src/libsystemd/sd-bus/bus-util.c
17b0f1
@@ -1709,16 +1709,15 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) {
17b0f1
                 else if (streq(d->result, "unsupported"))
17b0f1
                         log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
17b0f1
                 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
17b0f1
-                        if (d->name) {
17b0f1
-                                bool quotes;
17b0f1
+                        _cleanup_free_ char *quoted = NULL;
17b0f1
 
17b0f1
-                                quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
17b0f1
+                        if (d->name)
17b0f1
+                                quoted = shell_maybe_quote(d->name);
17b0f1
 
17b0f1
-                                log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
17b0f1
-                                          d->name,
17b0f1
-                                          quotes ? "'" : "", d->name, quotes ? "'" : "");
17b0f1
-                        } else
17b0f1
-                                log_error("Job failed. See \"journalctl -xe\" for details.");
17b0f1
+                        if (quoted)
17b0f1
+                                log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xe' for details.", d->name, quoted);
17b0f1
+                        else
17b0f1
+                                log_error("Job failed. See 'journalctl -xe' for details.");
17b0f1
                 }
17b0f1
         }
17b0f1
 
17b0f1
diff --git a/src/shared/util.c b/src/shared/util.c
17b0f1
index 649344d88f..778c2b0e04 100644
17b0f1
--- a/src/shared/util.c
17b0f1
+++ b/src/shared/util.c
17b0f1
@@ -1329,7 +1329,8 @@ char *cescape(const char *s) {
17b0f1
 
17b0f1
         assert(s);
17b0f1
 
17b0f1
-        /* Does C style string escaping. */
17b0f1
+        /* Does C style string escaping. May be be reversed with
17b0f1
+         * cunescape(). */
17b0f1
 
17b0f1
         r = new(char, strlen(s)*4 + 1);
17b0f1
         if (!r)
17b0f1
@@ -1493,7 +1494,7 @@ char *xescape(const char *s, const char *bad) {
17b0f1
 
17b0f1
         /* Escapes all chars in bad, in addition to \ and all special
17b0f1
          * chars, in \xFF style escaping. May be reversed with
17b0f1
-         * cunescape. */
17b0f1
+         * cunescape(). */
17b0f1
 
17b0f1
         r = new(char, strlen(s) * 4 + 1);
17b0f1
         if (!r)
17b0f1
@@ -8101,3 +8102,43 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
17b0f1
 
17b0f1
         return -1;
17b0f1
 }
17b0f1
+
17b0f1
+char *shell_maybe_quote(const char *s) {
17b0f1
+        const char *p;
17b0f1
+        char *r, *t;
17b0f1
+
17b0f1
+        assert(s);
17b0f1
+
17b0f1
+        /* Encloses a string in double quotes if necessary to make it
17b0f1
+         * OK as shell string. */
17b0f1
+
17b0f1
+        for (p = s; *p; p++)
17b0f1
+                if (*p <= ' ' ||
17b0f1
+                    *p >= 127 ||
17b0f1
+                    strchr(SHELL_NEED_QUOTES, *p))
17b0f1
+                        break;
17b0f1
+
17b0f1
+        if (!*p)
17b0f1
+                return strdup(s);
17b0f1
+
17b0f1
+        r = new(char, 1+strlen(s)*2+1+1);
17b0f1
+        if (!r)
17b0f1
+                return NULL;
17b0f1
+
17b0f1
+        t = r;
17b0f1
+        *(t++) = '"';
17b0f1
+        t = mempcpy(t, s, p - s);
17b0f1
+
17b0f1
+        for (; *p; p++) {
17b0f1
+
17b0f1
+                if (strchr(SHELL_NEED_ESCAPE, *p))
17b0f1
+                        *(t++) = '\\';
17b0f1
+
17b0f1
+                *(t++) = *p;
17b0f1
+        }
17b0f1
+
17b0f1
+        *(t++)= '"';
17b0f1
+        *t = 0;
17b0f1
+
17b0f1
+        return r;
17b0f1
+}
17b0f1
diff --git a/src/shared/util.h b/src/shared/util.h
17b0f1
index a83b588221..7ecfd8571d 100644
17b0f1
--- a/src/shared/util.h
17b0f1
+++ b/src/shared/util.h
17b0f1
@@ -1078,3 +1078,5 @@ void sigkill_wait(pid_t *pid);
17b0f1
 #define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait)
17b0f1
 
17b0f1
 int syslog_parse_priority(const char **p, int *priority, bool with_facility);
17b0f1
+
17b0f1
+char *shell_maybe_quote(const char *s);
17b0f1
diff --git a/src/test/test-util.c b/src/test/test-util.c
17b0f1
index 9515a8cbf1..9ae347b434 100644
17b0f1
--- a/src/test/test-util.c
17b0f1
+++ b/src/test/test-util.c
17b0f1
@@ -1512,6 +1512,24 @@ static void test_sparse_write(void) {
17b0f1
         test_sparse_write_one(fd, test_e, sizeof(test_e));
17b0f1
 }
17b0f1
 
17b0f1
+static void test_shell_maybe_quote_one(const char *s, const char *expected) {
17b0f1
+        _cleanup_free_ char *r;
17b0f1
+
17b0f1
+        assert_se(r = shell_maybe_quote(s));
17b0f1
+        assert_se(streq(r, expected));
17b0f1
+}
17b0f1
+
17b0f1
+static void test_shell_maybe_quote(void) {
17b0f1
+
17b0f1
+        test_shell_maybe_quote_one("", "");
17b0f1
+        test_shell_maybe_quote_one("\\", "\"\\\\\"");
17b0f1
+        test_shell_maybe_quote_one("\"", "\"\\\"\"");
17b0f1
+        test_shell_maybe_quote_one("foobar", "foobar");
17b0f1
+        test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
17b0f1
+        test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
17b0f1
+        test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
17b0f1
+}
17b0f1
+
17b0f1
 int main(int argc, char *argv[]) {
17b0f1
         log_parse_environment();
17b0f1
         log_open();
17b0f1
@@ -1589,6 +1607,7 @@ int main(int argc, char *argv[]) {
17b0f1
         test_same_fd();
17b0f1
         test_uid_ptr();
17b0f1
         test_sparse_write();
17b0f1
+        test_shell_maybe_quote();
17b0f1
 
17b0f1
         return 0;
17b0f1
 }