|  | /* Functions to deal with the inferior being executed on GDB or | 
|  | GDBserver. | 
|  |  | 
|  | Copyright (C) 2019-2025 Free Software Foundation, Inc. | 
|  |  | 
|  | This file is part of GDB. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program 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 General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include "gdbsupport/common-inferior.h" | 
|  |  | 
|  | /* See common-inferior.h.  */ | 
|  |  | 
|  | bool startup_with_shell = true; | 
|  |  | 
|  | /* Escape characters in ARG and return an updated string.  The string | 
|  | SPECIAL contains the set of characters that must be escaped.  SPECIAL | 
|  | must not be nullptr, and it is assumed that SPECIAL contains the newline | 
|  | '\n' character.  It is assumed that ARG is not nullptr, but ARG can | 
|  | be the empty string.  */ | 
|  |  | 
|  | static std::string | 
|  | escape_characters (const char *arg, const char *special) | 
|  | { | 
|  | gdb_assert (special != nullptr); | 
|  | gdb_assert (arg != nullptr); | 
|  |  | 
|  | std::string result; | 
|  |  | 
|  | #ifdef __MINGW32__ | 
|  | static const char quote = '"'; | 
|  | #else | 
|  | static const char quote = '\''; | 
|  | #endif | 
|  |  | 
|  | /* Need to handle empty arguments specially.  */ | 
|  | if (arg[0] == '\0') | 
|  | { | 
|  | result += quote; | 
|  | result += quote; | 
|  | } | 
|  | /* The special character handling code here assumes that if SPECIAL is | 
|  | not nullptr, then SPECIAL will contain '\n'.  This is true for all our | 
|  | current usages, but if this ever changes in the future the following | 
|  | might need reworking.  */ | 
|  | else | 
|  | { | 
|  | #ifdef __MINGW32__ | 
|  | bool quoted = false; | 
|  |  | 
|  | if (strpbrk (arg, special) != nullptr) | 
|  | { | 
|  | quoted = true; | 
|  | result += quote; | 
|  | } | 
|  | #endif | 
|  | for (const char *cp = arg; *cp; ++cp) | 
|  | { | 
|  | if (*cp == '\n') | 
|  | { | 
|  | /* A newline cannot be quoted with a backslash (it just | 
|  | disappears), only by putting it inside quotes.  */ | 
|  | result += quote; | 
|  | result += '\n'; | 
|  | result += quote; | 
|  | } | 
|  | else | 
|  | { | 
|  | #ifdef __MINGW32__ | 
|  | if (*cp == quote) | 
|  | #else | 
|  | if (strchr (special, *cp) != nullptr) | 
|  | #endif | 
|  | result += '\\'; | 
|  | result += *cp; | 
|  | } | 
|  | } | 
|  | #ifdef __MINGW32__ | 
|  | if (quoted) | 
|  | result += quote; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Return a version of ARG that has special shell characters escaped.  */ | 
|  |  | 
|  | static std::string | 
|  | escape_shell_characters (const char *arg) | 
|  | { | 
|  | #ifdef __MINGW32__ | 
|  | /* This holds all the characters considered special to the | 
|  | Windows shells.  */ | 
|  | static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n"; | 
|  | #else | 
|  | /* This holds all the characters considered special to the | 
|  | typical Unix shells.  We include `^' because the SunOS | 
|  | /bin/sh treats it as a synonym for `|'.  */ | 
|  | static const char special[] = "\"!#$&*()\\|[]{}<>?'`~^; \t\n"; | 
|  | #endif | 
|  |  | 
|  | return escape_characters (arg, special); | 
|  | } | 
|  |  | 
|  | /* Return a version of ARG that has quote characters and white space | 
|  | characters escaped.  These are the characters that GDB sees as special | 
|  | when splitting a string into separate arguments.  */ | 
|  |  | 
|  | static std::string | 
|  | escape_gdb_characters (const char * arg) | 
|  | { | 
|  | #ifdef __MINGW32__ | 
|  | static const char special[] = "\" \t\n"; | 
|  | #else | 
|  | static const char special[] = "\"' \t\n"; | 
|  | #endif | 
|  |  | 
|  | return escape_characters (arg, special); | 
|  | } | 
|  |  | 
|  | /* See common-inferior.h.  */ | 
|  |  | 
|  | std::string | 
|  | construct_inferior_arguments (gdb::array_view<char * const> argv, | 
|  | bool escape_shell_char) | 
|  | { | 
|  | /* Select the desired escape function.  */ | 
|  | const auto escape_func = (escape_shell_char | 
|  | ? escape_shell_characters | 
|  | : escape_gdb_characters); | 
|  |  | 
|  | std::string result; | 
|  |  | 
|  | for (const char *a : argv) | 
|  | { | 
|  | if (!result.empty ()) | 
|  | result += " "; | 
|  |  | 
|  | result += escape_func (a); | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } |