4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering/***
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering This file is part of systemd.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering Copyright 2010 Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering systemd is free software; you can redistribute it and/or modify it
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering under the terms of the GNU Lesser General Public License as published by
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering (at your option) any later version.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering systemd is distributed in the hope that it will be useful, but
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering Lesser General Public License for more details.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering You should have received a copy of the GNU Lesser General Public License
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering***/
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <errno.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stdlib.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <string.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
e4e73a632524c382139034d4271f53b6089ab4cbLennart Poettering#include "escape.h"
e4e73a632524c382139034d4271f53b6089ab4cbLennart Poettering#include "hexdecoct.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "macro.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "utf8.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringsize_t cescape_char(char c, char *buf) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering char * buf_old = buf;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering switch (c) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\a':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = 'a';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\b':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = 'b';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\f':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = 'f';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\n':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = 'n';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\r':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = 'r';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\t':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = 't';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\v':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = 'v';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\\':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '"':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '"';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\'':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\'';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering default:
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* For special chars we prefer octal over
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * hexadecimal encoding, simply because glib's
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * g_strescape() does the same */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if ((c < ' ') || (c >= 127)) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = octchar((unsigned char) c >> 6);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = octchar((unsigned char) c >> 3);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = octchar((unsigned char) c);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering } else
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = c;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return buf - buf_old;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
a5ef363808b100856783784654de9b6bf2110173Lennart Poetteringchar *cescape_length(const char *s, size_t n) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering const char *f;
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering char *r, *t;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering assert(s || n == 0);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Does C style string escaping. May be reversed with
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * cunescape(). */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering r = new(char, n*4 + 1);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (!r)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return NULL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering for (f = s, t = r; f < s + n; f++)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering t += cescape_char(*f, t);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *t = 0;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return r;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
a5ef363808b100856783784654de9b6bf2110173Lennart Poetteringchar *cescape(const char *s) {
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering assert(s);
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering return cescape_length(s, strlen(s));
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering}
a5ef363808b100856783784654de9b6bf2110173Lennart Poettering
c932fb71cc90461b88ecdffe47c071d001d78fb4Shawn Landdenint cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering int r = 1;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(p);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(*p);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(ret);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek /* Unescapes C style. Returns the unescaped character in ret.
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek * Sets *eight_bit to true if the escaped sequence either fits in
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek * one byte in UTF-8 or is a non-unicode literal byte and should
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek * instead be copied directly.
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (length != (size_t) -1 && length < 1)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering switch (p[0]) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'a':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\a';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'b':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\b';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'f':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\f';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'n':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\n';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'r':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\r';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 't':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\t';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'v':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\v';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\\':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '"':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '"';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '\'':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = '\'';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 's':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* This is an extension of the XDG syntax files */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = ' ';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'x': {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* hexadecimal encoding */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering int a, b;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (length != (size_t) -1 && length < 3)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering a = unhexchar(p[1]);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (a < 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering b = unhexchar(p[2]);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (b < 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow NUL bytes */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (a == 0 && b == 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek *ret = (a << 4U) | b;
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek *eight_bit = true;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering r = 3;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'u': {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* C++11 style 16bit unicode */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering int a[4];
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering unsigned i;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering uint32_t c;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (length != (size_t) -1 && length < 5)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (i = 0; i < 4; i++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering a[i] = unhexchar(p[1 + i]);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (a[i] < 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return a[i];
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow 0 chars */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (c == 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek *ret = c;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering r = 5;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case 'U': {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* C++11 style 32bit unicode */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering int a[8];
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering unsigned i;
c932fb71cc90461b88ecdffe47c071d001d78fb4Shawn Landden char32_t c;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (length != (size_t) -1 && length < 9)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (i = 0; i < 8; i++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering a[i] = unhexchar(p[1 + i]);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (a[i] < 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return a[i];
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
dcd12626734ce81e89c74515eaca601ef9edf785Lennart Poettering c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
dcd12626734ce81e89c74515eaca601ef9edf785Lennart Poettering ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] << 8U) | ((uint32_t) a[6] << 4U) | (uint32_t) a[7];
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow 0 chars */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (c == 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow invalid code points */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (!unichar_is_valid(c))
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek *ret = c;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering r = 9;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '0':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '1':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '2':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '3':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '4':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '5':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '6':
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering case '7': {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* octal encoding */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering int a, b, c;
c932fb71cc90461b88ecdffe47c071d001d78fb4Shawn Landden char32_t m;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (length != (size_t) -1 && length < 3)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering a = unoctchar(p[0]);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (a < 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering b = unoctchar(p[1]);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (b < 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering c = unoctchar(p[2]);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (c < 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* don't allow NUL bytes */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (a == 0 && b == 0 && c == 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow bytes above 255 */
dcd12626734ce81e89c74515eaca601ef9edf785Lennart Poettering m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (m > 255)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = m;
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek *eight_bit = true;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering r = 3;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering default:
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return r;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringint cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering char *r, *t;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering const char *f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering size_t pl;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(s);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(ret);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Undoes C style string escaping, and optionally prefixes it. */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering pl = prefix ? strlen(prefix) : 0;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering r = new(char, pl+length+1);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (!r)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -ENOMEM;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (prefix)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering memcpy(r, prefix, pl);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (f = s, t = r + pl; f < s + length; f++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering size_t remaining;
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek bool eight_bit = false;
c932fb71cc90461b88ecdffe47c071d001d78fb4Shawn Landden char32_t u;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering int k;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering remaining = s + length - f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(remaining > 0);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (*f != '\\') {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* A literal literal, copy verbatim */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = *f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering continue;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (remaining == 1) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (flags & UNESCAPE_RELAX) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* A trailing backslash, copy verbatim */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = *f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering continue;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering free(r);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return -EINVAL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (k < 0) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (flags & UNESCAPE_RELAX) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Invalid escape code, let's take it literal then */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering continue;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering free(r);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return k;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek f += k;
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek if (eight_bit)
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek /* One byte? Set directly as specified */
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek *(t++) = u;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering else
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek /* Otherwise encode as multi-byte UTF-8 */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering t += utf8_encode_unichar(t, u);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *t = 0;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *ret = r;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return t - r;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringint cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return cunescape_length_with_prefix(s, length, NULL, flags, ret);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringint cunescape(const char *s, UnescapeFlags flags, char **ret) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return cunescape_length(s, strlen(s), flags, ret);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringchar *xescape(const char *s, const char *bad) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering char *r, *t;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering const char *f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Escapes all chars in bad, in addition to \ and all special
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * chars, in \xFF style escaping. May be reversed with
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * cunescape(). */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering r = new(char, strlen(s) * 4 + 1);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (!r)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return NULL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (f = s, t = r; *f; f++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if ((*f < ' ') || (*f >= 127) ||
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering (*f == '\\') || strchr(bad, *f)) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = 'x';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = hexchar(*f >> 4);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = hexchar(*f);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering } else
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = *f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *t = 0;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return r;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringstatic char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(bad);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (; *s; s++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (*s == '\\' || strchr(bad, *s))
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = *s;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering }
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return t;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringchar *shell_escape(const char *s, const char *bad) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering char *r, *t;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering r = new(char, strlen(s)*2+1);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (!r)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return NULL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering t = strcpy_backslash_escaped(r, s, bad);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *t = 0;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return r;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringchar *shell_maybe_quote(const char *s) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering const char *p;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering char *r, *t;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(s);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Encloses a string in double quotes if necessary to make it
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * OK as shell string. */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (p = s; *p; p++)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (*p <= ' ' ||
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *p >= 127 ||
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering strchr(SHELL_NEED_QUOTES, *p))
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering break;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (!*p)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return strdup(s);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering r = new(char, 1+strlen(s)*2+1+1);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (!r)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return NULL;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering t = r;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = '"';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering t = mempcpy(t, s, p - s);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++)= '"';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *t = 0;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return r;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}