From: Bruno Haible Date: Thu, 10 May 2012 11:52:21 +0000 (+0200) Subject: system-quote: Refactor. X-Git-Tag: v0.1~682 X-Git-Url: http://erislabs.net/gitweb/?a=commitdiff_plain;ds=sidebyside;h=150ce1bef700d6a3e56861c3a316da64be93d880;p=gnulib.git system-quote: Refactor. * lib/system-quote.h (system_quote_copy): Fix comment. * lib/system-quote.c (windows_createprocess_quote, windows_cmd_quote): New functions, extracted from system_quote_copy. (system_quote_length, system_quote_copy): Use these functions. Reported by Paul Eggert. --- diff --git a/ChangeLog b/ChangeLog index ba38632bc..29df987d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-05-10 Bruno Haible + + system-quote: Refactor. + * lib/system-quote.h (system_quote_copy): Fix comment. + * lib/system-quote.c (windows_createprocess_quote, windows_cmd_quote): + New functions, extracted from system_quote_copy. + (system_quote_length, system_quote_copy): Use these functions. + Reported by Paul Eggert. + 2012-05-08 Bruno Haible execute, spawn-pipe: Escape '*' characters in arguments on Windows. diff --git a/lib/system-quote.c b/lib/system-quote.c index facbea6db..37a9ff410 100644 --- a/lib/system-quote.c +++ b/lib/system-quote.c @@ -28,6 +28,7 @@ #include "xalloc.h" #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* The native Windows CreateProcess() function interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as @@ -46,6 +47,58 @@ */ # define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037*" # define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" + +/* Copies the quoted string to p and returns the number of bytes needed. + If p is non-NULL, there must be room for system_quote_length (string) + bytes at p. */ +static size_t +windows_createprocess_quote (char *p, const char *string) +{ + size_t len = strlen (string); + bool quote_around = + (len == 0 || strpbrk (string, SHELL_SPECIAL_CHARS) != NULL); + size_t backslashes = 0; + size_t i = 0; +# define STORE(c) \ + do \ + { \ + if (p != NULL) \ + p[i] = (c); \ + i++; \ + } \ + while (0) + + if (quote_around) + STORE ('"'); + for (; len > 0; string++, len--) + { + char c = *string; + + if (c == '"') + { + size_t j; + + for (j = backslashes + 1; j > 0; j--) + STORE ('\\'); + } + STORE (c); + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + size_t j; + + for (j = backslashes; j > 0; j--) + STORE ('\\'); + STORE ('"'); + } +# undef STORE + return i; +} + /* The native Windows cmd.exe command interpreter also interprets: - '\n', '\r' as a command terminator - no way to escape it, - '<', '>' as redirections, @@ -61,6 +114,67 @@ */ # define CMD_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037!%&'*+,;<=>[]^`{|}~" # define CMD_FORBIDDEN_CHARS "\n\r" + +/* Copies the quoted string to p and returns the number of bytes needed. + If p is non-NULL, there must be room for system_quote_length (string) + bytes at p. */ +static size_t +windows_cmd_quote (char *p, const char *string) +{ + size_t len = strlen (string); + bool quote_around = + (len == 0 || strpbrk (string, CMD_SPECIAL_CHARS) != NULL); + size_t backslashes = 0; + size_t i = 0; +# define STORE(c) \ + do \ + { \ + if (p != NULL) \ + p[i] = (c); \ + i++; \ + } \ + while (0) + + if (quote_around) + STORE ('"'); + for (; len > 0; string++, len--) + { + char c = *string; + + if (c == '"') + { + size_t j; + + for (j = backslashes + 1; j > 0; j--) + STORE ('\\'); + } + if (c == '%') + { + size_t j; + + for (j = backslashes; j > 0; j--) + STORE ('\\'); + STORE ('"'); + } + STORE (c); + if (c == '%') + STORE ('"'); + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + size_t j; + + for (j = backslashes; j > 0; j--) + STORE ('\\'); + STORE ('"'); + } + return i; +} + #endif size_t @@ -77,59 +191,11 @@ system_quote_length (enum system_command_interpreter interpreter, #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ case SCI_WINDOWS_CREATEPROCESS: - { - size_t len = strlen (string); - bool quote_around = - (len == 0 || strpbrk (string, SHELL_SPECIAL_CHARS) != NULL); - size_t backslashes = 0; - size_t length = len; - - if (quote_around) - length++; - for (; len > 0; string++, len--) - { - char c = *string; - - if (c == '"') - length += backslashes + 1; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - return length; - } + return windows_createprocess_quote (NULL, string); case SCI_SYSTEM: case SCI_WINDOWS_CMD: - { - size_t len = strlen (string); - bool quote_around = - (len == 0 || strpbrk (string, CMD_SPECIAL_CHARS) != NULL); - size_t backslashes = 0; - size_t length = len; - - if (quote_around) - length++; - for (; len > 0; string++, len--) - { - char c = *string; - - if (c == '"') - length += backslashes + 1; - if (c == '%') - length += backslashes + 2; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - return length; - } + return windows_cmd_quote (NULL, string); #endif default: @@ -153,91 +219,15 @@ system_quote_copy (char *p, #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ case SCI_WINDOWS_CREATEPROCESS: - { - size_t len = strlen (string); - bool quote_around = - (len == 0 || strpbrk (string, SHELL_SPECIAL_CHARS) != NULL); - size_t backslashes = 0; - - if (quote_around) - *p++ = '"'; - for (; len > 0; string++, len--) - { - char c = *string; - - if (c == '"') - { - size_t j; - - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - *p++ = c; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - size_t j; - - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - return p; - } + p += windows_createprocess_quote (p, string); + *p = '\0'; + return p; case SCI_SYSTEM: case SCI_WINDOWS_CMD: - { - size_t len = strlen (string); - bool quote_around = - (len == 0 || strpbrk (string, CMD_SPECIAL_CHARS) != NULL); - size_t backslashes = 0; - - if (quote_around) - *p++ = '"'; - for (; len > 0; string++, len--) - { - char c = *string; - - if (c == '"') - { - size_t j; - - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - if (c == '%') - { - size_t j; - - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p++ = c; - if (c == '%') - *p++ = '"'; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - size_t j; - - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - return p; - } + p += windows_cmd_quote (p, string); + *p = '\0'; + return p; #endif default: diff --git a/lib/system-quote.h b/lib/system-quote.h index c2c50c5a2..d5f29780b 100644 --- a/lib/system-quote.h +++ b/lib/system-quote.h @@ -58,7 +58,7 @@ extern size_t const char *string); /* Copies the quoted string to p and returns the incremented p. - There must be room for shell_quote_length (string) + 1 bytes at p. */ + There must be room for system_quote_length (string) + 1 bytes at p. */ extern char * system_quote_copy (char *p, enum system_command_interpreter interpreter,