1 1.1 christos /* Functions to deal with the inferior being executed on GDB or 2 1.1 christos GDBserver. 3 1.1 christos 4 1.1.1.4 christos Copyright (C) 2019-2025 Free Software Foundation, Inc. 5 1.1 christos 6 1.1 christos This file is part of GDB. 7 1.1 christos 8 1.1 christos This program is free software; you can redistribute it and/or modify 9 1.1 christos it under the terms of the GNU General Public License as published by 10 1.1 christos the Free Software Foundation; either version 3 of the License, or 11 1.1 christos (at your option) any later version. 12 1.1 christos 13 1.1 christos This program is distributed in the hope that it will be useful, 14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 1.1 christos GNU General Public License for more details. 17 1.1 christos 18 1.1 christos You should have received a copy of the GNU General Public License 19 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 1.1 christos 21 1.1 christos #include "gdbsupport/common-inferior.h" 22 1.1 christos 23 1.1 christos /* See common-inferior.h. */ 24 1.1 christos 25 1.1 christos bool startup_with_shell = true; 26 1.1 christos 27 1.1.1.4 christos /* Escape characters in ARG and return an updated string. The string 28 1.1.1.4 christos SPECIAL contains the set of characters that must be escaped. SPECIAL 29 1.1.1.4 christos must not be nullptr, and it is assumed that SPECIAL contains the newline 30 1.1.1.4 christos '\n' character. It is assumed that ARG is not nullptr, but ARG can 31 1.1.1.4 christos be the empty string. */ 32 1.1 christos 33 1.1.1.4 christos static std::string 34 1.1.1.4 christos escape_characters (const char *arg, const char *special) 35 1.1 christos { 36 1.1.1.4 christos gdb_assert (special != nullptr); 37 1.1.1.4 christos gdb_assert (arg != nullptr); 38 1.1.1.4 christos 39 1.1 christos std::string result; 40 1.1 christos 41 1.1 christos #ifdef __MINGW32__ 42 1.1.1.4 christos static const char quote = '"'; 43 1.1 christos #else 44 1.1.1.4 christos static const char quote = '\''; 45 1.1 christos #endif 46 1.1 christos 47 1.1.1.4 christos /* Need to handle empty arguments specially. */ 48 1.1.1.4 christos if (arg[0] == '\0') 49 1.1.1.4 christos { 50 1.1.1.4 christos result += quote; 51 1.1.1.4 christos result += quote; 52 1.1.1.4 christos } 53 1.1.1.4 christos /* The special character handling code here assumes that if SPECIAL is 54 1.1.1.4 christos not nullptr, then SPECIAL will contain '\n'. This is true for all our 55 1.1.1.4 christos current usages, but if this ever changes in the future the following 56 1.1.1.4 christos might need reworking. */ 57 1.1.1.4 christos else 58 1.1.1.4 christos { 59 1.1.1.4 christos #ifdef __MINGW32__ 60 1.1.1.4 christos bool quoted = false; 61 1.1.1.4 christos 62 1.1.1.4 christos if (strpbrk (arg, special) != nullptr) 63 1.1.1.4 christos { 64 1.1.1.4 christos quoted = true; 65 1.1.1.4 christos result += quote; 66 1.1.1.4 christos } 67 1.1.1.4 christos #endif 68 1.1.1.4 christos for (const char *cp = arg; *cp; ++cp) 69 1.1.1.4 christos { 70 1.1.1.4 christos if (*cp == '\n') 71 1.1 christos { 72 1.1.1.4 christos /* A newline cannot be quoted with a backslash (it just 73 1.1.1.4 christos disappears), only by putting it inside quotes. */ 74 1.1 christos result += quote; 75 1.1.1.4 christos result += '\n'; 76 1.1 christos result += quote; 77 1.1 christos } 78 1.1 christos else 79 1.1 christos { 80 1.1 christos #ifdef __MINGW32__ 81 1.1.1.4 christos if (*cp == quote) 82 1.1.1.4 christos #else 83 1.1.1.4 christos if (strchr (special, *cp) != nullptr) 84 1.1.1.4 christos #endif 85 1.1.1.4 christos result += '\\'; 86 1.1.1.4 christos result += *cp; 87 1.1.1.4 christos } 88 1.1.1.4 christos } 89 1.1.1.4 christos #ifdef __MINGW32__ 90 1.1.1.4 christos if (quoted) 91 1.1.1.4 christos result += quote; 92 1.1.1.4 christos #endif 93 1.1.1.4 christos } 94 1.1.1.4 christos 95 1.1.1.4 christos return result; 96 1.1.1.4 christos } 97 1.1.1.4 christos 98 1.1.1.4 christos /* Return a version of ARG that has special shell characters escaped. */ 99 1.1 christos 100 1.1.1.4 christos static std::string 101 1.1.1.4 christos escape_shell_characters (const char *arg) 102 1.1.1.4 christos { 103 1.1 christos #ifdef __MINGW32__ 104 1.1.1.4 christos /* This holds all the characters considered special to the 105 1.1.1.4 christos Windows shells. */ 106 1.1.1.4 christos static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n"; 107 1.1 christos #else 108 1.1.1.4 christos /* This holds all the characters considered special to the 109 1.1.1.4 christos typical Unix shells. We include `^' because the SunOS 110 1.1.1.4 christos /bin/sh treats it as a synonym for `|'. */ 111 1.1.1.4 christos static const char special[] = "\"!#$&*()\\|[]{}<>?'`~^; \t\n"; 112 1.1 christos #endif 113 1.1.1.4 christos 114 1.1.1.4 christos return escape_characters (arg, special); 115 1.1.1.4 christos } 116 1.1.1.4 christos 117 1.1.1.4 christos /* Return a version of ARG that has quote characters and white space 118 1.1.1.4 christos characters escaped. These are the characters that GDB sees as special 119 1.1.1.4 christos when splitting a string into separate arguments. */ 120 1.1.1.4 christos 121 1.1.1.4 christos static std::string 122 1.1.1.4 christos escape_gdb_characters (const char * arg) 123 1.1.1.4 christos { 124 1.1 christos #ifdef __MINGW32__ 125 1.1.1.4 christos static const char special[] = "\" \t\n"; 126 1.1.1.4 christos #else 127 1.1.1.4 christos static const char special[] = "\"' \t\n"; 128 1.1 christos #endif 129 1.1.1.4 christos 130 1.1.1.4 christos return escape_characters (arg, special); 131 1.1.1.4 christos } 132 1.1.1.4 christos 133 1.1.1.4 christos /* See common-inferior.h. */ 134 1.1.1.4 christos 135 1.1.1.4 christos std::string 136 1.1.1.4 christos construct_inferior_arguments (gdb::array_view<char * const> argv, 137 1.1.1.4 christos bool escape_shell_char) 138 1.1.1.4 christos { 139 1.1.1.4 christos /* Select the desired escape function. */ 140 1.1.1.4 christos const auto escape_func = (escape_shell_char 141 1.1.1.4 christos ? escape_shell_characters 142 1.1.1.4 christos : escape_gdb_characters); 143 1.1.1.4 christos 144 1.1.1.4 christos std::string result; 145 1.1.1.4 christos 146 1.1.1.4 christos for (const char *a : argv) 147 1.1 christos { 148 1.1.1.4 christos if (!result.empty ()) 149 1.1.1.4 christos result += " "; 150 1.1 christos 151 1.1.1.4 christos result += escape_func (a); 152 1.1 christos } 153 1.1 christos 154 1.1 christos return result; 155 1.1 christos } 156