return r;
}
-char* shell_maybe_quote(const char *s, EscapeStyle style) {
+char* shell_maybe_quote(const char *s, ShellEscapeFlags flags) {
const char *p;
char *r, *t;
if (!*p)
return strdup(s);
- r = new(char, (style == ESCAPE_POSIX) + 1 + strlen(s)*2 + 1 + 1);
+ r = new(char, FLAGS_SET(flags, SHELL_ESCAPE_POSIX) + 1 + strlen(s)*2 + 1 + 1);
if (!r)
return NULL;
t = r;
- switch (style) {
- case ESCAPE_BACKSLASH:
- case ESCAPE_BACKSLASH_ONELINE:
- *(t++) = '"';
- break;
- case ESCAPE_POSIX:
+ if (FLAGS_SET(flags, SHELL_ESCAPE_POSIX)) {
*(t++) = '$';
*(t++) = '\'';
- break;
- default:
- assert_not_reached("Bad EscapeStyle");
- }
+ } else
+ *(t++) = '"';
t = mempcpy(t, s, p - s);
- if (IN_SET(style, ESCAPE_BACKSLASH, ESCAPE_BACKSLASH_ONELINE))
- t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE,
- style == ESCAPE_BACKSLASH_ONELINE);
- else
- t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true);
+ t = strcpy_backslash_escaped(t, p,
+ FLAGS_SET(flags, SHELL_ESCAPE_POSIX) ? SHELL_NEED_ESCAPE_POSIX : SHELL_NEED_ESCAPE,
+ true);
- if (IN_SET(style, ESCAPE_BACKSLASH, ESCAPE_BACKSLASH_ONELINE))
- *(t++) = '"';
- else
+ if (FLAGS_SET(flags, SHELL_ESCAPE_POSIX))
*(t++) = '\'';
+ else
+ *(t++) = '"';
*t = 0;
return r;
UNESCAPE_ACCEPT_NUL = 1 << 1,
} UnescapeFlags;
-typedef enum EscapeStyle {
- ESCAPE_BACKSLASH = 1, /* Add shell quotes ("") so the shell will consider this a single
- argument, possibly multiline. Tabs and newlines are not escaped. */
- ESCAPE_BACKSLASH_ONELINE = 2, /* Similar to ESCAPE_BACKSLASH, but always produces a single-line
- string instead. Shell escape sequences are produced for tabs and
- newlines. */
- ESCAPE_POSIX = 3, /* Similar to ESCAPE_BACKSLASH_ONELINE, but uses POSIX shell escape
- * syntax (a string enclosed in $'') instead of plain quotes. */
-} EscapeStyle;
+typedef enum ShellEscapeFlags {
+ /* The default is to add shell quotes ("") so the shell will consider this a single argument.
+ * Tabs and newlines are escaped. */
+
+ SHELL_ESCAPE_POSIX = 1 << 1, /* Use POSIX shell escape syntax (a string enclosed in $'') instead of plain quotes. */
+} ShellEscapeFlags;
char* cescape(const char *s);
char* cescape_length(const char *s, size_t n);
char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit);
char* shell_escape(const char *s, const char *bad);
-char* shell_maybe_quote(const char *s, EscapeStyle style);
+char* shell_maybe_quote(const char *s, ShellEscapeFlags flags);
test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
}
-static void test_shell_maybe_quote_one(const char *s,
- EscapeStyle style,
- const char *expected) {
+static void test_shell_maybe_quote_one(const char *s, ShellEscapeFlags flags, const char *expected) {
_cleanup_free_ char *ret = NULL;
- assert_se(ret = shell_maybe_quote(s, style));
+ assert_se(ret = shell_maybe_quote(s, flags));
log_debug("[%s] → [%s] (%s)", s, ret, expected);
assert_se(streq(ret, expected));
}
static void test_shell_maybe_quote(void) {
- test_shell_maybe_quote_one("", ESCAPE_BACKSLASH, "");
- test_shell_maybe_quote_one("", ESCAPE_BACKSLASH_ONELINE, "");
- test_shell_maybe_quote_one("", ESCAPE_POSIX, "");
- test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH, "\"\\\\\"");
- test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH_ONELINE, "\"\\\\\"");
- test_shell_maybe_quote_one("\\", ESCAPE_POSIX, "$'\\\\'");
- test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH, "\"\\\"\"");
- test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH_ONELINE, "\"\\\"\"");
- test_shell_maybe_quote_one("\"", ESCAPE_POSIX, "$'\"'");
- test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH, "foobar");
- test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH_ONELINE, "foobar");
- test_shell_maybe_quote_one("foobar", ESCAPE_POSIX, "foobar");
- test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH, "\"foo bar\"");
- test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH_ONELINE, "\"foo bar\"");
- test_shell_maybe_quote_one("foo bar", ESCAPE_POSIX, "$'foo bar'");
- test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH, "\"foo\tbar\"");
- test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\tbar\"");
- test_shell_maybe_quote_one("foo\tbar", ESCAPE_POSIX, "$'foo\\tbar'");
- test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH, "\"foo\nbar\"");
- test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\nbar\"");
- test_shell_maybe_quote_one("foo\nbar", ESCAPE_POSIX, "$'foo\\nbar'");
- test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH, "\"foo \\\"bar\\\" waldo\"");
- test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH_ONELINE, "\"foo \\\"bar\\\" waldo\"");
- test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_POSIX, "$'foo \"bar\" waldo'");
- test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH, "\"foo\\$bar\"");
- test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\$bar\"");
- test_shell_maybe_quote_one("foo$bar", ESCAPE_POSIX, "$'foo$bar'");
+ test_shell_maybe_quote_one("", 0, "");
+ test_shell_maybe_quote_one("", SHELL_ESCAPE_POSIX, "");
+ test_shell_maybe_quote_one("\\", 0, "\"\\\\\"");
+ test_shell_maybe_quote_one("\\", SHELL_ESCAPE_POSIX, "$'\\\\'");
+ test_shell_maybe_quote_one("\"", 0, "\"\\\"\"");
+ test_shell_maybe_quote_one("\"", SHELL_ESCAPE_POSIX, "$'\"'");
+ test_shell_maybe_quote_one("foobar", 0, "foobar");
+ test_shell_maybe_quote_one("foobar", SHELL_ESCAPE_POSIX, "foobar");
+ test_shell_maybe_quote_one("foo bar", 0, "\"foo bar\"");
+ test_shell_maybe_quote_one("foo bar", SHELL_ESCAPE_POSIX, "$'foo bar'");
+ test_shell_maybe_quote_one("foo\tbar", 0, "\"foo\\tbar\"");
+ test_shell_maybe_quote_one("foo\tbar", SHELL_ESCAPE_POSIX, "$'foo\\tbar'");
+ test_shell_maybe_quote_one("foo\nbar", 0, "\"foo\\nbar\"");
+ test_shell_maybe_quote_one("foo\nbar", SHELL_ESCAPE_POSIX, "$'foo\\nbar'");
+ test_shell_maybe_quote_one("foo \"bar\" waldo", 0, "\"foo \\\"bar\\\" waldo\"");
+ test_shell_maybe_quote_one("foo \"bar\" waldo", SHELL_ESCAPE_POSIX, "$'foo \"bar\" waldo'");
+ test_shell_maybe_quote_one("foo$bar", 0, "\"foo\\$bar\"");
+ test_shell_maybe_quote_one("foo$bar", SHELL_ESCAPE_POSIX, "$'foo$bar'");
/* Note that current users disallow control characters, so this "test"
* is here merely to establish current behaviour. If control characters
* were allowed, they should be quoted, i.e. \001 should become \\001. */
- test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH, "\"a\nb\001\"");
- test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH_ONELINE, "\"a\\nb\001\"");
- test_shell_maybe_quote_one("a\nb\001", ESCAPE_POSIX, "$'a\\nb\001'");
+ test_shell_maybe_quote_one("a\nb\001", 0, "\"a\\nb\001\"");
+ test_shell_maybe_quote_one("a\nb\001", SHELL_ESCAPE_POSIX, "$'a\\nb\001'");
- test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH, "\"foo!bar\"");
- test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH_ONELINE, "\"foo!bar\"");
- test_shell_maybe_quote_one("foo!bar", ESCAPE_POSIX, "$'foo!bar'");
+ test_shell_maybe_quote_one("foo!bar", 0, "\"foo!bar\"");
+ test_shell_maybe_quote_one("foo!bar", SHELL_ESCAPE_POSIX, "$'foo!bar'");
}
int main(int argc, char *argv[]) {