-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stdlib.h>
#include "macro.h"
#include "utf8.h"
-size_t cescape_char(char c, char *buf) {
- char * buf_old = buf;
+int cescape_char(char c, char *buf) {
+ char *buf_old = buf;
+
+ /* Needs space for 4 characters in the buffer */
switch (c) {
/* C++11 style 16bit unicode */
int a[4];
- unsigned i;
+ size_t i;
uint32_t c;
if (length != (size_t) -1 && length < 5)
/* C++11 style 32bit unicode */
int a[8];
- unsigned i;
+ size_t i;
char32_t c;
if (length != (size_t) -1 && length < 9)
/* Undoes C style string escaping, and optionally prefixes it. */
- pl = prefix ? strlen(prefix) : 0;
+ pl = strlen_ptr(prefix);
r = new(char, pl+length+1);
if (!r)
assert(remaining > 0);
if (*f != '\\') {
- /* A literal literal, copy verbatim */
+ /* A literal, copy verbatim */
*(t++) = *f;
continue;
}
for (f = s, t = r; f < s + len; f++) {
- if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
+ if (*f < ' ' || *f >= 127 || IN_SET(*f, '\\', '"')) {
*(t++) = '\\';
*(t++) = '0' + (*f >> 6);
*(t++) = '0' + ((*f >> 3) & 8);
}
-static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
+static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) {
assert(bad);
for (; *s; s++) {
+ if (escape_tab_nl && IN_SET(*s, '\n', '\t')) {
+ *(t++) = '\\';
+ *(t++) = *s == '\n' ? 'n' : 't';
+ continue;
+ }
+
if (*s == '\\' || strchr(bad, *s))
*(t++) = '\\';
if (!r)
return NULL;
- t = strcpy_backslash_escaped(r, s, bad);
+ t = strcpy_backslash_escaped(r, s, bad, false);
*t = 0;
return r;
}
-char *shell_maybe_quote(const char *s) {
+char* shell_maybe_quote(const char *s, EscapeStyle style) {
const char *p;
char *r, *t;
assert(s);
- /* Encloses a string in double quotes if necessary to make it
- * OK as shell string. */
+ /* Encloses a string in quotes if necessary to make it OK as a shell
+ * string. Note that we treat benign UTF-8 characters as needing
+ * escaping too, but that should be OK. */
for (p = s; *p; p++)
if (*p <= ' ' ||
if (!*p)
return strdup(s);
- r = new(char, 1+strlen(s)*2+1+1);
+ r = new(char, (style == ESCAPE_POSIX) + 1 + strlen(s)*2 + 1 + 1);
if (!r)
return NULL;
t = r;
- *(t++) = '"';
+ if (style == ESCAPE_BACKSLASH)
+ *(t++) = '"';
+ else if (style == ESCAPE_POSIX) {
+ *(t++) = '$';
+ *(t++) = '\'';
+ } else
+ assert_not_reached("Bad EscapeStyle");
+
t = mempcpy(t, s, p - s);
- t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
+ if (style == ESCAPE_BACKSLASH)
+ t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE, false);
+ else
+ t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true);
- *(t++)= '"';
+ if (style == ESCAPE_BACKSLASH)
+ *(t++) = '"';
+ else
+ *(t++) = '\'';
*t = 0;
return r;